]> granicus.if.org Git - postgresql/blob - src/bin/pgevent/pgevent.c
Support configurable eventlog application names on Windows
[postgresql] / src / bin / pgevent / pgevent.c
1 /*-------------------------------------------------------------------------
2  *
3  * pgevent.c
4  *              Defines the entry point for pgevent dll.
5  *              The DLL defines event source for backend
6  *
7  *
8  * IDENTIFICATION
9  *        src/bin/pgevent/pgevent.c
10  *
11  *-------------------------------------------------------------------------
12  */
13
14
15 #include <windows.h>
16 #include <olectl.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 /* Global variables */
22 HANDLE          g_module = NULL;        /* hModule of DLL */
23
24 /*
25  * The event source is stored as a registry key.
26  * The maximum length of a registry key is 255 characters.
27  * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx
28  */
29 char            event_source[256] = "PostgreSQL";
30
31 /* Prototypes */
32 HRESULT         DllInstall(BOOL bInstall, __in_opt LPCWSTR pszCmdLine);
33 STDAPI          DllRegisterServer(void);
34 STDAPI          DllUnregisterServer(void);
35 BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
36
37 /*
38  * DllInstall --- Passes the command line argument to DLL
39  */
40
41 HRESULT
42 DllInstall(BOOL bInstall,
43                    __in_opt LPCWSTR pszCmdLine)
44 {
45         size_t          ret;
46
47         if (pszCmdLine && *pszCmdLine != '\0')
48                 wcstombs_s(&ret, event_source, sizeof(event_source),
49                                    pszCmdLine, sizeof(event_source));
50
51         /*
52          * This is an ugly hack due to the strange behavior of "regsvr32 /i".
53          *
54          * When installing, regsvr32 calls DllRegisterServer before DllInstall.
55          * When uninstalling (i.e. "regsvr32 /u /i"), on the other hand, regsvr32
56          * calls DllInstall and then DllUnregisterServer as expected.
57          *
58          * This strange behavior forces us to specify -n (i.e. "regsvr32 /n /i").
59          * Without -n, DllRegisterServer called before DllInstall would mistakenly
60          * overwrite the default "PostgreSQL" event source registration.
61          */
62         if (bInstall)
63                 DllRegisterServer();
64         return S_OK;
65 }
66
67 /*
68  * DllRegisterServer --- Instructs DLL to create its registry entries
69  */
70
71 STDAPI
72 DllRegisterServer(void)
73 {
74         HKEY            key;
75         DWORD           data;
76         char            buffer[_MAX_PATH];
77         char            key_name[400];
78
79         /* Set the name of DLL full path name. */
80         if (!GetModuleFileName((HMODULE) g_module, buffer, sizeof(buffer)))
81         {
82                 MessageBox(NULL, "Could not retrieve DLL filename", "PostgreSQL error", MB_OK | MB_ICONSTOP);
83                 return SELFREG_E_TYPELIB;
84         }
85
86         /*
87          * Add PostgreSQL source name as a subkey under the Application key in the
88          * EventLog registry key.
89          */
90         _snprintf(key_name, sizeof(key_name),
91                         "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
92                           event_source);
93         if (RegCreateKey(HKEY_LOCAL_MACHINE, key_name, &key))
94         {
95                 MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
96                 return SELFREG_E_TYPELIB;
97         }
98
99         /* Add the name to the EventMessageFile subkey. */
100         if (RegSetValueEx(key,
101                                           "EventMessageFile",
102                                           0,
103                                           REG_EXPAND_SZ,
104                                           (LPBYTE) buffer,
105                                           strlen(buffer) + 1))
106         {
107                 MessageBox(NULL, "Could not set the event message file.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
108                 return SELFREG_E_TYPELIB;
109         }
110
111         /* Set the supported event types in the TypesSupported subkey. */
112         data = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
113
114         if (RegSetValueEx(key,
115                                           "TypesSupported",
116                                           0,
117                                           REG_DWORD,
118                                           (LPBYTE) & data,
119                                           sizeof(DWORD)))
120         {
121                 MessageBox(NULL, "Could not set the supported types.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
122                 return SELFREG_E_TYPELIB;
123         }
124
125         RegCloseKey(key);
126         return S_OK;
127 }
128
129 /*
130  * DllUnregisterServer --- Instructs DLL to remove only those entries created through DllRegisterServer
131  */
132
133 STDAPI
134 DllUnregisterServer(void)
135 {
136         char            key_name[400];
137
138         /*
139          * Remove PostgreSQL source name as a subkey under the Application key in
140          * the EventLog registry key.
141          */
142
143         _snprintf(key_name, sizeof(key_name),
144                         "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
145                           event_source);
146         if (RegDeleteKey(HKEY_LOCAL_MACHINE, key_name))
147         {
148                 MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
149                 return SELFREG_E_TYPELIB;
150         }
151         return S_OK;
152 }
153
154 /*
155  * DllMain --- is an optional entry point into a DLL.
156  */
157
158 BOOL            WINAPI
159 DllMain(HANDLE hModule,
160                 DWORD ul_reason_for_call,
161                 LPVOID lpReserved
162 )
163 {
164         if (ul_reason_for_call == DLL_PROCESS_ATTACH)
165                 g_module = hModule;
166         return TRUE;
167 }