/
dhcpnotify.cpp
252 lines (218 loc) · 6.83 KB
/
dhcpnotify.cpp
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
* Copyright © 1999 - 2000 Microsoft Corporation. All Rights Reserved.
*
* Author: Stephen R. Husak - Microsoft Developer Support
*
* Abstract:
* This code demonstrates the use of the DHCP Client Options API -
* DhcpRegisterParamChange/DhcpDeRegisterParamChange
*/
/*
* Includes
*/
#define UNICODE
#include <windows.h> // windows
#include <stdio.h> // standard i/o
#include <iphlpapi.h> // ip helper
#include <dhcpcsdk.h> // dhcp client options api
// Exit Event Handler
HANDLE g_hExitEvent;
/*
* OutputError
*
* retrieves the system message for an error
*/
void OutputError(DWORD dwError)
{
LPVOID lpMsgBuf; // buffer to copy string into (allocated by call)
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL) == 0)
printf("Error Reported: %d GetLastError: %d\n", dwError, GetLastError());
else
{
printf("Error %d: %s\n", dwError, (LPCSTR) lpMsgBuf);
// free the buffer.
LocalFree(lpMsgBuf);
}
}
/*
* DetermineAdapter
*
* NOTE:
*
* This code retrieves the Adapter Name to use for the DHCP Client API
* using the IPHelper API.
*
* NT has a name for the adapter that through this API has device
* information in front of it followed by a {GUID}, 98 does not and
* the Index is used instead. So if the string is set to ?? (what it is
* in 98) we revert to using the string representation of the index.
*
*/
LPSTR DetermineAdapter()
{
DWORD dwResult; // result of API calls
IP_INTERFACE_INFO * pInfo = NULL; // adapter information structure
DWORD dwSize = 0; // size of required buffer
CHAR szAdapter[MAX_ADAPTER_NAME] = {0}; // the adapter to use
char * ptr; // pointer to adapter name
// get buffer size
dwResult = GetInterfaceInfo(NULL, &dwSize);
if (dwResult == ERROR_INSUFFICIENT_BUFFER)
{
// allocate buffer
pInfo = (IP_INTERFACE_INFO *) LocalAlloc(LPTR, dwSize);
if (!pInfo)
{
OutputError(GetLastError());
exit(1);
}
// make the actual call
dwResult = GetInterfaceInfo(pInfo, &dwSize);
if (dwResult != ERROR_SUCCESS)
{
OutputError(GetLastError());
exit(2);
}
}
else
{
OutputError(GetLastError());
exit(3);
}
// convert, parse, and convert back
ptr = NULL;
WideCharToMultiByte(0, 0, pInfo->Adapter[0].Name,
lstrlenW(pInfo->Adapter[0].Name),
szAdapter, MAX_ADAPTER_NAME, NULL, NULL);
if (szAdapter[0] != '?')
{
// find the GUID
ptr = strchr(szAdapter, '{');
}
// use index if the pointer is not set
if (!ptr)
{
sprintf_s(szAdapter, MAX_ADAPTER_NAME, "%ld\0", pInfo->Adapter[0].Index);
ptr = szAdapter;
}
// free what was allocated
if (pInfo)
LocalFree(pInfo);
return ptr;
}
/*
* CtrlHandler
*
* handle control events to provide graceful cleanup
*/
BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
{
printf("\n\nStop Event Received... Aborting... \n\n");
switch (dwCtrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_SHUTDOWN_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_CLOSE_EVENT:
SetEvent(g_hExitEvent);
break;
default:
return FALSE;
}
return TRUE;
}
/*
* main
*
* this is where it all happens
*/
int main(int argc, char * argv[])
{
DWORD dwResult; // result from API call
DWORD dwVersion; // API version reported
WCHAR wszAdapter[MAX_ADAPTER_NAME] = {0}; // the adapter name in wide chars
char * ptr; // pointer to adapter name
g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, L"DHCP_EXIT_EVENT");
if (g_hExitEvent == NULL)
OutputError(GetLastError());
SetConsoleCtrlHandler(CtrlHandler, true);
if (argc > 1)
// use what's on the command line for the adapter ID
ptr = argv[1];
else
// use IP Helper API to get the adapter ID to use
ptr = DetermineAdapter();
// convert it for the API call
MultiByteToWideChar(0, 0, ptr, (int) strlen(ptr), wszAdapter, MAX_ADAPTER_NAME);
// initialize the DHCP Client Options API
dwResult = DhcpCApiInitialize(&dwVersion);
if (dwResult != 0)
{
OutputError(dwResult);
exit(4);
}
else
printf("DHCP Client Options API version %d\n", dwVersion);
//
// Here the watch is set up - since this is an easy example, the request
// is set up statically, however in a real-world scenario this may require
// building the watch array in a more 'dynamic' way
//
// Also for this sample we are using one item that is almost always in a
// DHCP configuration.
//
// the DHCP Client Options API array for watching the options
//
DHCPCAPI_PARAMS watch[1] =
{{0, OPTION_ROUTER_ADDRESS, FALSE, NULL, 0}}; // gateway address
// set-up the actual array
DHCPCAPI_PARAMS_ARRAY watcharray = {1, watch}; // we are watching 1 item
printf("Watching DHCP Options Change on Adapter [%S]\n", wszAdapter);
HANDLE hEvent; // handle that will be set when parameter(s) change
// make the request on the adapter
dwResult = DhcpRegisterParamChange(DHCPCAPI_REGISTER_HANDLE_EVENT,
NULL,
wszAdapter,
NULL,
watcharray,
&hEvent);
// wait for the events to become signaled
if (dwResult == ERROR_SUCCESS)
{
HANDLE lpHandles[2] = {g_hExitEvent, hEvent};
DWORD rc = 0;
while (rc = WaitForMultipleObjects(2, lpHandles, FALSE, INFINITE))
{
if (rc == WAIT_OBJECT_0)
break;
ResetEvent(hEvent);
printf("Parameter has changed.\n");
// the change could then be read and applied as needed
// see the sample DHCPREQUEST or the DhcpRequestParams() API
// for more information
}
}
else
{
OutputError(dwResult);
}
dwResult = DhcpDeRegisterParamChange(DHCPCAPI_REGISTER_HANDLE_EVENT,
NULL, &hEvent);
if (dwResult != ERROR_SUCCESS)
OutputError(dwResult);
// de-init the api
DhcpCApiCleanup();
// close out the exit event handle
CloseHandle(g_hExitEvent);
return 0;
}