240 lines
6.6 KiB
C++
240 lines
6.6 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 -
|
|
* DhcpRequestParams
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include <windows.h> // windows
|
|
#include <stdio.h> // standard i/o
|
|
#include <iphlpapi.h> // ip helper
|
|
#include <dhcpcsdk.h> // dhcp client options api
|
|
|
|
// initial buffer size for options buffer
|
|
#define INITIAL_BUFFER_SIZE 256
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
/*
|
|
* 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 = NULL; // pointer to adapter name
|
|
|
|
if (argc > 1)
|
|
ptr = argv[1];
|
|
else
|
|
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 request 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 request array in a more 'dynamic' way
|
|
//
|
|
// Also for this sample we are using two items that are almost always in a
|
|
// DHCP configuration. Hence this information is retrieved from the local
|
|
// DHCP cache.
|
|
//
|
|
// the DHCP Client Options API arrays for getting the options
|
|
DHCPCAPI_PARAMS requests[2] =
|
|
{{0, OPTION_SUBNET_MASK, FALSE, NULL, 0}, // subnet mask
|
|
{0, OPTION_ROUTER_ADDRESS, FALSE, NULL, 0}}; // gateway address
|
|
|
|
// set-up the actual arrays
|
|
DHCPCAPI_PARAMS_ARRAY sendarray = {0, NULL}; // we aren't sending anything
|
|
DHCPCAPI_PARAMS_ARRAY requestarray = {2, requests}; // we are requesting 2
|
|
|
|
// buffer variables
|
|
DWORD dwSize = INITIAL_BUFFER_SIZE; // size of buffer for options
|
|
LPBYTE buffer = NULL; // buffer for options
|
|
IN_ADDR addr; // address in return code
|
|
|
|
printf("Getting DHCP Options on Adapter [%S]\n", wszAdapter);
|
|
|
|
// loop until buffer is big enough to get the data and then make request
|
|
do
|
|
{
|
|
if (buffer)
|
|
LocalFree(buffer);
|
|
|
|
buffer = (LPBYTE) LocalAlloc(LPTR, dwSize); // allocate the buffer
|
|
if (!buffer)
|
|
{
|
|
OutputError(GetLastError());
|
|
exit(5);
|
|
}
|
|
|
|
// make the request on the adapter
|
|
dwResult = DhcpRequestParams(DHCPCAPI_REQUEST_SYNCHRONOUS,
|
|
NULL,
|
|
wszAdapter,
|
|
NULL, sendarray,
|
|
requestarray,
|
|
buffer, &dwSize,
|
|
NULL);
|
|
}
|
|
while (dwResult == ERROR_MORE_DATA);
|
|
|
|
// parse out results
|
|
if (dwResult == ERROR_SUCCESS)
|
|
{
|
|
|
|
// first check subnet
|
|
if (requests[0].nBytesData > 0)
|
|
{
|
|
memcpy(&addr, (LPVOID) requests[0].Data, 4);
|
|
printf("Subnet Mask: %s\n", inet_ntoa(addr));
|
|
}
|
|
else
|
|
printf("Subnet Mask NOT present!\n");
|
|
|
|
// check for router address
|
|
if (requests[1].nBytesData > 0)
|
|
{
|
|
memcpy(&addr, (LPVOID) requests[1].Data, 4);
|
|
printf("Gateway Address: %s\n", inet_ntoa(addr));
|
|
}
|
|
else
|
|
printf("Gateway Address NOT present!\n");
|
|
}
|
|
else
|
|
{
|
|
OutputError(dwResult);
|
|
}
|
|
|
|
// free the buffer
|
|
if (buffer)
|
|
LocalFree(buffer);
|
|
|
|
// de-init the api
|
|
DhcpCApiCleanup();
|
|
|
|
return 0;
|
|
}
|