summaryrefslogtreecommitdiffstats
path: root/src/bin/pgevent/pgevent.c
blob: 807a2c93120d61f9c479ad4fda9f9a557b3c31e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*-------------------------------------------------------------------------
 *
 * pgevent.c
 *		Defines the entry point for pgevent dll.
 *		The DLL defines event source for backend
 *
 *
 * IDENTIFICATION
 *	  src/bin/pgevent/pgevent.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres_fe.h"

#include <olectl.h>

/* Global variables */
HANDLE		g_module = NULL;	/* hModule of DLL */

/*
 * The event source is stored as a registry key.
 * The maximum length of a registry key is 255 characters.
 * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx
 */
char		event_source[256] = DEFAULT_EVENT_SOURCE;

/* Prototypes */
HRESULT		DllInstall(BOOL bInstall, LPCWSTR pszCmdLine);
STDAPI		DllRegisterServer(void);
STDAPI		DllUnregisterServer(void);
BOOL		WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);

/*
 * DllInstall --- Passes the command line argument to DLL
 */

HRESULT
DllInstall(BOOL bInstall,
		   LPCWSTR pszCmdLine)
{
	if (pszCmdLine && *pszCmdLine != '\0')
		wcstombs(event_source, pszCmdLine, sizeof(event_source));

	/*
	 * This is an ugly hack due to the strange behavior of "regsvr32 /i".
	 *
	 * When installing, regsvr32 calls DllRegisterServer before DllInstall.
	 * When uninstalling (i.e. "regsvr32 /u /i"), on the other hand, regsvr32
	 * calls DllInstall and then DllUnregisterServer as expected.
	 *
	 * This strange behavior forces us to specify -n (i.e. "regsvr32 /n /i").
	 * Without -n, DllRegisterServer called before DllInstall would mistakenly
	 * overwrite the default "PostgreSQL" event source registration.
	 */
	if (bInstall)
		DllRegisterServer();
	return S_OK;
}

/*
 * DllRegisterServer --- Instructs DLL to create its registry entries
 */

STDAPI
DllRegisterServer(void)
{
	HKEY		key;
	DWORD		data;
	char		buffer[_MAX_PATH];
	char		key_name[400];

	/* Set the name of DLL full path name. */
	if (!GetModuleFileName((HMODULE) g_module, buffer, sizeof(buffer)))
	{
		MessageBox(NULL, "Could not retrieve DLL filename", "PostgreSQL error", MB_OK | MB_ICONSTOP);
		return SELFREG_E_TYPELIB;
	}

	/*
	 * Add PostgreSQL source name as a subkey under the Application key in the
	 * EventLog registry key.
	 */
	_snprintf(key_name, sizeof(key_name),
			  "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
			  event_source);
	if (RegCreateKey(HKEY_LOCAL_MACHINE, key_name, &key))
	{
		MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
		return SELFREG_E_TYPELIB;
	}

	/* Add the name to the EventMessageFile subkey. */
	if (RegSetValueEx(key,
					  "EventMessageFile",
					  0,
					  REG_EXPAND_SZ,
					  (LPBYTE) buffer,
					  strlen(buffer) + 1))
	{
		MessageBox(NULL, "Could not set the event message file.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
		return SELFREG_E_TYPELIB;
	}

	/* Set the supported event types in the TypesSupported subkey. */
	data = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;

	if (RegSetValueEx(key,
					  "TypesSupported",
					  0,
					  REG_DWORD,
					  (LPBYTE) &data,
					  sizeof(DWORD)))
	{
		MessageBox(NULL, "Could not set the supported types.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
		return SELFREG_E_TYPELIB;
	}

	RegCloseKey(key);
	return S_OK;
}

/*
 * DllUnregisterServer --- Instructs DLL to remove only those entries created through DllRegisterServer
 */

STDAPI
DllUnregisterServer(void)
{
	char		key_name[400];

	/*
	 * Remove PostgreSQL source name as a subkey under the Application key in
	 * the EventLog registry key.
	 */

	_snprintf(key_name, sizeof(key_name),
			  "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
			  event_source);
	if (RegDeleteKey(HKEY_LOCAL_MACHINE, key_name))
	{
		MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
		return SELFREG_E_TYPELIB;
	}
	return S_OK;
}

/*
 * DllMain --- is an optional entry point into a DLL.
 */

BOOL		WINAPI
DllMain(HANDLE hModule,
		DWORD ul_reason_for_call,
		LPVOID lpReserved
)
{
	if (ul_reason_for_call == DLL_PROCESS_ATTACH)
		g_module = hModule;
	return TRUE;
}