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