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