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