2025-11-28 00:35:46 +09:00

253 lines
6.8 KiB
C++

/*
* 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;
}