Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

668 lines
24 KiB

  1. /*++
  2. Copyright (C) 1998 Microsoft Corporation
  3. Module Name:
  4. change.c
  5. Abstract:
  6. handles some change notifications for dhcp.
  7. --*/
  8. #include "precomp.h"
  9. #include <dhcpcapi.h>
  10. #include <apiappl.h>
  11. #include <dhcploc.h>
  12. #include <dhcppro.h>
  13. DWORD
  14. ConvertNetworkString(
  15. IN OUT LPBYTE Buf,
  16. IN ULONG Size
  17. )
  18. /*++
  19. Routine Description:
  20. This routine converts a wide character string where each
  21. character is in network-order, to host-order so that the
  22. string can be used (for ex, for displaying).
  23. Arguments:
  24. Buf -- wide character string buffer, replace in-place.
  25. Size -- size of above buffer in BYTES.
  26. Return Value:
  27. ERROR_INTERNAL_ERROR or ERROR_SUCCESS
  28. --*/
  29. {
  30. if( 0 == Size ) return ERROR_INTERNAL_ERROR;
  31. if( Size % sizeof(WCHAR)) return ERROR_INTERNAL_ERROR;
  32. while( Size ) {
  33. *(LPWSTR) Buf = ntohs(*(LPWSTR)Buf);
  34. Buf += sizeof(WCHAR);
  35. Size -= sizeof(WCHAR);
  36. }
  37. return ERROR_SUCCESS;
  38. }
  39. DWORD
  40. ConvertFromBufferToClassInfo(
  41. IN LPBYTE Data,
  42. IN ULONG nData,
  43. IN OUT LPDHCP_CLASS_INFO ClassesArray,
  44. IN OUT LPDWORD Size
  45. )
  46. /*++
  47. Routine Description:
  48. This routine converts a buffer which has wire-data to the
  49. DHCP_CLASS_INFO array structure. The wire-data format is as
  50. follows: it is a set of triples, where each triple contains the
  51. actual user-class-id used on wire (binary), its name (LPWSTR), and
  52. its description (LPWSTR). Each of these three items have their
  53. length specified first using two bytes -- the hi-byte followed by
  54. the lo-byte.
  55. N.B. If the first of the triple (user-class-id) has length X,
  56. then the actual number of bytes of data on-wire would be X rounded
  57. off to 4 to preserve alignment. This is taken care of in this
  58. routine.
  59. N.B #2. The pointers within the ClassesArray all point to the
  60. buffer (Data) provided.
  61. Arguments:
  62. Data -- the wire-data buffer
  63. nData -- number of bytes of above
  64. ClassesArray -- input buffer that will be formatted with info.
  65. Size -- on input, this must be size of above buffer in bytes.
  66. on output, if the routine failed with ERROR_MORE_DATA, then
  67. this will contain the required number of bytes. If the
  68. routine succeeded, then this will contain the number of
  69. elements in above array that got filled.
  70. Return Values:
  71. ERROR_SUCCESS -- success
  72. ERROR_MORE_DATA -- data buffer provided in ClassesArray must be at
  73. least as many bytes as "Size."
  74. Win32 errors
  75. --*/
  76. {
  77. ULONG ReqdSize, ThisSize, nBytes, nClasses;
  78. LPBYTE Buf;
  79. Buf = Data; nBytes = 0;
  80. ReqdSize = 0; nClasses = 0;
  81. do {
  82. //
  83. // Require length (hi-byte, lo-byte)
  84. //
  85. if( nBytes + 2 > nData ) return ERROR_INTERNAL_ERROR;
  86. //
  87. // user-classid binary blob of specified size.
  88. // N.B. length must be rounded off to nearest
  89. // multiple of 4.
  90. //
  91. ThisSize = ((Buf[0])<<8)+Buf[1];
  92. if( 0 == ThisSize ) return ERROR_INTERNAL_ERROR;
  93. ThisSize = (ThisSize + 3) & ~3;
  94. //
  95. // Go over class id.
  96. //
  97. Buf += 2 + ThisSize;
  98. nBytes += 2 + ThisSize;
  99. ReqdSize += ThisSize;
  100. if( nBytes + 2 > nData ) return ERROR_INTERNAL_ERROR;
  101. //
  102. // user class name.. size must be multiple of sizeof(WCHAR)
  103. //
  104. ThisSize = ((Buf[0])<<8)+Buf[1];
  105. Buf += 2 + ThisSize;
  106. nBytes += 2 + ThisSize;
  107. if( (ThisSize % 2 ) ) return ERROR_INTERNAL_ERROR;
  108. ReqdSize += ThisSize + sizeof(L'\0');
  109. if( nBytes + 2 > nData ) return ERROR_INTERNAL_ERROR;
  110. //
  111. // user class description..
  112. //
  113. ThisSize = ((Buf[0])<<8)+Buf[1];
  114. Buf += 2 + ThisSize;
  115. nBytes += 2 + ThisSize;
  116. if( (ThisSize % 2 ) ) return ERROR_INTERNAL_ERROR;
  117. ReqdSize += ThisSize + sizeof(L'\0');
  118. nClasses ++;
  119. } while( nBytes < nData );
  120. //
  121. // Check if we have the required size.
  122. //
  123. ReqdSize += sizeof(DHCP_CLASS_INFO)*nClasses;
  124. if( (*Size) < ReqdSize ) {
  125. *Size = ReqdSize;
  126. return ERROR_MORE_DATA;
  127. } else {
  128. *Size = nClasses;
  129. }
  130. //
  131. // Assemble the array.
  132. //
  133. Buf = nClasses*sizeof(DHCP_CLASS_INFO) + ((LPBYTE)ClassesArray);
  134. nClasses = 0;
  135. do {
  136. ClassesArray[nClasses].Version = DHCP_CLASS_INFO_VERSION_0;
  137. //
  138. // user class id binary info
  139. //
  140. ThisSize = ((Data[0])<<8)+Data[1];
  141. Data += 2;
  142. ClassesArray[nClasses].ClassData = Buf;
  143. ClassesArray[nClasses].ClassDataLen = ThisSize;
  144. memcpy(Buf, Data, ThisSize);
  145. ThisSize = (ThisSize + 3)&~3;
  146. Buf += ThisSize; Data += ThisSize;
  147. //
  148. // class name
  149. //
  150. ThisSize = ((Data[0])<<8)+Data[1];
  151. Data += 2;
  152. ClassesArray[nClasses].ClassName = (LPWSTR)Buf;
  153. memcpy(Buf, Data, ThisSize);
  154. if( ERROR_SUCCESS != ConvertNetworkString(Buf, ThisSize) ){
  155. return ERROR_INTERNAL_ERROR;
  156. }
  157. Buf += ThisSize; Data += ThisSize;
  158. *(LPWSTR)Buf = L'\0'; Buf += sizeof(WCHAR);
  159. //
  160. // Class description
  161. //
  162. ThisSize = ((Data[0])<<8)+Data[1];
  163. Data += 2;
  164. if( 0 == ThisSize ) {
  165. ClassesArray[nClasses].ClassDescr = NULL;
  166. } else {
  167. ClassesArray[nClasses].ClassDescr = (LPWSTR)Buf;
  168. memcpy(Buf, Data, ThisSize);
  169. if( ERROR_SUCCESS != ConvertNetworkString(Buf, ThisSize) ) {
  170. return ERROR_INTERNAL_ERROR;
  171. }
  172. }
  173. Buf += ThisSize; Data += ThisSize;
  174. *(LPWSTR)Buf = L'\0'; Buf += sizeof(WCHAR);
  175. nClasses ++;
  176. } while( nClasses < *Size );
  177. return ERROR_SUCCESS;
  178. }
  179. //DOC DhcpEnumClasses enumerates the list of classes available on the system for configuration.
  180. //DOC This is predominantly going to be used by the NetUI. (in which case the ClassData part of the
  181. //DOC DHCP_CLASS_INFO structure is essentially useless).
  182. //DOC Note that Flags is used for future use.
  183. //DOC The AdapterName can currently be only GUIDs but may soon be EXTENDED to be IpAddress strings or
  184. //DOC h-w addresses or any other user friendly means of denoting the Adapter. Note that if the Adapter
  185. //DOC Name is NULL (not the empty string L""), then it refers to either ALL adapters.
  186. //DOC The Size parameter is an input/output parameter. The input value is the # of bytes of allocated
  187. //DOC space in the ClassesArray buffer. On return, the meaning of this value depends on the return value.
  188. //DOC If the function returns ERROR_SUCCESS, then, this parameter would return the # of elements in the
  189. //DOC array ClassesArray. If the function returns ERROR_MORE_DATA, then, this parameter refers to the
  190. //DOC # of bytes space that is actually REQUIRED to hold the information.
  191. //DOC In all other cases, the values in Size and ClassesArray dont mean anything.
  192. //DOC
  193. //DOC Return Values:
  194. //DOC ERROR_DEVICE_DOES_NOT_EXIST The AdapterName is illegal in the given context
  195. //DOC ERROR_INVALID_PARAMETER
  196. //DOC ERROR_MORE_DATA ClassesArray is not a large enough buff..
  197. //DOC ERROR_FILE_NOT_FOUND The DHCP Client is not running and could not be started up.
  198. //DOC ERROR_NOT_ENOUGH_MEMORY This is NOT the same as ERROR_MORE_DATA
  199. //DOC Win32 errors
  200. //DOC
  201. //DOC Remarks:
  202. //DOC To notify DHCP that some class has changed, please use the DhcpHandlePnPEvent API.
  203. DWORD
  204. DhcpEnumClasses( // enumerate the list of classes available
  205. IN DWORD Flags, // currently must be zero
  206. IN LPWSTR AdapterName, // currently must be AdapterGUID (cannot be NULL yet)
  207. IN OUT DWORD *Size, // input # of bytes available in BUFFER, output # of elements in array
  208. IN OUT DHCP_CLASS_INFO *ClassesArray // pre-allocated buffer
  209. )
  210. {
  211. DHCPAPI_PARAMS SendParams; // we need to get something from teh dhcp server..
  212. PDHCPAPI_PARAMS RecdParams;
  213. DWORD Result;
  214. DWORD nBytesToAllocate;
  215. DWORD nRecdParams;
  216. BYTE Opt;
  217. if( 0 != Flags || NULL == AdapterName || NULL == Size ) {
  218. return ERROR_INVALID_PARAMETER; // sanity check
  219. }
  220. if( NULL == ClassesArray && 0 != *Size ) {
  221. return ERROR_INVALID_DATA; // if *Size is non-Zero, then the ClassesArray buffer should exist
  222. }
  223. Opt = OPTION_USER_CLASS; // intiialize request packet for this option..
  224. SendParams.OptionId = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
  225. SendParams.IsVendor = FALSE;
  226. SendParams.Data = &Opt;
  227. SendParams.nBytesData = sizeof(Opt);
  228. nBytesToAllocate = 0;
  229. Result = DhcpRequestParameters // try to get this either directly from client or via INFORM
  230. (
  231. /* LPWSTR AdapterName */ AdapterName,
  232. /* LPBYTE ClassId */ NULL,
  233. /* DWORD ClassIdLen */ 0,
  234. /* PDHCPAPI_PARAMS SendParams */ &SendParams,
  235. /* DWORD nSendParams */ 1,
  236. /* DWORD Flags */ 0,
  237. /* PDHCPAPI_PARAMS RecdParams */ NULL,
  238. /* LPDWORD pnRecdParamsBytes*/ &nBytesToAllocate
  239. );
  240. if( ERROR_MORE_DATA != Result ) { // either an error or dont have anything to return?
  241. return Result;
  242. }
  243. DhcpAssert(nBytesToAllocate); // if it were 0, Result would have been ERROR_SUCCESS
  244. RecdParams = DhcpAllocateMemory(nBytesToAllocate);
  245. if( NULL == RecdParams ) { // um? dont have memory? cant really happen?
  246. return ERROR_NOT_ENOUGH_MEMORY;
  247. }
  248. nRecdParams = nBytesToAllocate;
  249. Result = DhcpRequestParameters // try to get this either directly from client or via INFORM
  250. (
  251. /* LPWSTR AdapterName */ AdapterName,
  252. /* LPBYTE ClassId */ NULL,
  253. /* DWORD ClassIdLen */ 0,
  254. /* PDHCPAPI_PARAMS SendParams */ &SendParams,
  255. /* DWORD nSendParams */ 1,
  256. /* DWORD Flags */ 0,
  257. /* PDHCPAPI_PARAMS RecdParams */ RecdParams,
  258. /* LPDWORD pnRecdParamsBytes*/ &nRecdParams
  259. );
  260. if( ERROR_SUCCESS == Result && 1 != nRecdParams ) {
  261. DhcpAssert(FALSE);
  262. Result = ERROR_INTERNAL_ERROR; // dont expect this to happen..
  263. }
  264. if( ERROR_SUCCESS != Result ) { // aw, comeone, cant happen now...
  265. // it is possible for instance to have a PnP event in the middle that would cause
  266. // the adapter to go away. In this case ERROR_FILE_NOT_FOUND (2) is returned.
  267. // no point for the assert - otherwise returning the error up to the caller is
  268. // just fine.
  269. //DhcpAssert(FALSE);
  270. DhcpPrint((DEBUG_ERRORS, "DhcpRequestParams: 0x%lx (%ld)\n", Result, Result));
  271. DhcpFreeMemory(RecdParams);
  272. return Result;
  273. }
  274. DhcpAssert(NULL != RecdParams);
  275. Result = ConvertFromBufferToClassInfo( // convert from straight bytes to classinfo struct
  276. RecdParams->Data,
  277. RecdParams->nBytesData,
  278. ClassesArray,
  279. Size
  280. );
  281. DhcpFreeMemory(RecdParams);
  282. return Result;
  283. }
  284. ULONG _inline // status
  285. GetRegistryClassIdName( // get registr string class id name written by ui
  286. IN LPWSTR AdapterName, // for this adapter
  287. OUT LPWSTR *ClassIdName
  288. )
  289. {
  290. ULONG Error;
  291. LPBYTE Value;
  292. ULONG ValueType, ValueSize;
  293. *ClassIdName = NULL;
  294. ValueSize = 0; Value = NULL;
  295. Error = DhcpRegReadFromLocation(
  296. DEFAULT_USER_CLASS_UI_LOC_FULL,
  297. AdapterName,
  298. &Value,
  299. &ValueType,
  300. &ValueSize
  301. );
  302. if( ERROR_SUCCESS != Error ) return Error; // failed?
  303. if( REG_SZ != ValueType ) {
  304. if( Value ) DhcpFreeMemory(Value);
  305. DhcpPrint((DEBUG_ERRORS, "DhcpClassId Type is incorrect: %ld\n", ValueType));
  306. DhcpAssert(FALSE);
  307. return ERROR_INVALID_DATA; // uh ? should not have happened!
  308. }
  309. *ClassIdName = (LPWSTR)Value;
  310. return ERROR_SUCCESS;
  311. }
  312. ULONG _inline // status
  313. ConvertClassIdNameToBin( // get corresponding value, return itself in ASCII o/w
  314. IN LPWSTR AdapterName, // for this adapter
  315. IN LPWSTR ClassIdName, // ClassIdName for which we are searching
  316. IN BOOL SkipClassEnum, // to skip dhcp class enumeration during initialization
  317. OUT LPBYTE *ClassIdBin, // fill this ptr up
  318. OUT ULONG *ClassIdBinSize // fill this with size of memory allocated
  319. )
  320. {
  321. ULONG Error, Size, i;
  322. PDHCP_CLASS_INFO pDhcpClassInfo;// array
  323. LPBYTE BinData;
  324. ULONG BinDataLen;
  325. pDhcpClassInfo = NULL;
  326. BinData = NULL; BinDataLen = 0;
  327. *ClassIdBin = NULL; *ClassIdBinSize = 0;
  328. // do not perform class enumeration before Dhcp is initialized.
  329. if (!SkipClassEnum) {
  330. do { // not a loop, just to avoid GOTOs
  331. Size = 0; // buffer yet be allocated..
  332. Error = DhcpEnumClasses(
  333. /* Flags */ 0,
  334. /* AdapterName */ AdapterName,
  335. /* Size */ &Size,
  336. /* ClassesArray */ NULL
  337. );
  338. if( ERROR_MORE_DATA != Error ) { // failed?
  339. break;
  340. }
  341. DhcpAssert(0 != Size);
  342. pDhcpClassInfo = DhcpAllocateMemory(Size);
  343. if( NULL == pDhcpClassInfo ) return ERROR_NOT_ENOUGH_MEMORY;
  344. Error = DhcpEnumClasses(
  345. /* Flags */ 0,
  346. /* AdapterName */ AdapterName,
  347. /* Size */ &Size,
  348. /* ClassesArray */ pDhcpClassInfo
  349. );
  350. if( ERROR_SUCCESS != Error ) { // This call should not fail!
  351. DhcpPrint((DEBUG_ERRORS, "DhcpEnumClasses failed %ld\n", Error));
  352. DhcpAssert(FALSE);
  353. DhcpFreeMemory(pDhcpClassInfo);
  354. return Error;
  355. }
  356. DhcpAssert(0 != Size);
  357. for( i = 0; i != Size ; i ++ ) {
  358. if( 0 == wcscmp(pDhcpClassInfo[i].ClassName, ClassIdName) )
  359. break;
  360. }
  361. if( i != Size ) { // found a match
  362. BinData = pDhcpClassInfo[i].ClassData;
  363. BinDataLen = pDhcpClassInfo[i].ClassDataLen;
  364. } else {
  365. DhcpFreeMemory(pDhcpClassInfo);
  366. }
  367. } while(0); // not a loop just to avoid GOTOs
  368. }
  369. // BinData and BinDataLen holds the info we know..
  370. if( NULL == BinData ) { // couldn't find the class..
  371. DhcpPrint((DEBUG_ERRORS, "Could not find the class <%ws>\n", ClassIdName));
  372. BinDataLen = wcslen(ClassIdName);
  373. BinData = DhcpAllocateMemory(BinDataLen);
  374. if( NULL == BinData ) { // could not allocate this mem?
  375. return ERROR_NOT_ENOUGH_MEMORY;
  376. }
  377. Error = wcstombs(BinData, ClassIdName, BinDataLen);
  378. if( -1 == Error ) { // failed conversion?
  379. Error = GetLastError();
  380. DhcpPrint((DEBUG_ERRORS, "Failed ot convert %ws\n", ClassIdName));
  381. DhcpAssert(FALSE);
  382. DhcpFreeMemory(BinData);
  383. return Error;
  384. }
  385. *ClassIdBin = BinData; *ClassIdBinSize = BinDataLen;
  386. return ERROR_SUCCESS;
  387. }
  388. // successfully got the bindata etc..
  389. DhcpAssert(pDhcpClassInfo); // this is where the string is..
  390. *ClassIdBin = DhcpAllocateMemory(BinDataLen); // try allocating memory
  391. if( NULL == *ClassIdBin ) { // failed
  392. return ERROR_NOT_ENOUGH_MEMORY;
  393. }
  394. memcpy(*ClassIdBin, BinData, BinDataLen);
  395. *ClassIdBinSize = BinDataLen;
  396. if (pDhcpClassInfo != NULL)
  397. DhcpFreeMemory(pDhcpClassInfo); // free allocated ptr
  398. return ERROR_SUCCESS;
  399. }
  400. LPWSTR _inline // String (allocated)
  401. GetRegClassIdBinLocation( // find where to store bin
  402. IN LPWSTR AdapterName // for this adapter
  403. )
  404. {
  405. ULONG Error;
  406. LPWSTR Value, RetVal;
  407. ULONG ValueSize, ValueType;
  408. ValueSize = 0; Value = NULL;
  409. Error = DhcpRegReadFromLocation(
  410. DHCP_CLIENT_PARAMETER_KEY REGISTRY_CONNECT_STRING DHCP_CLASS_LOCATION_VALUE,
  411. AdapterName,
  412. &(LPBYTE)Value,
  413. &ValueType,
  414. &ValueSize
  415. );
  416. if( ERROR_SUCCESS != Error ) { // couldn't find it? choose default!
  417. ValueSize = 0; // didn't allocate nothing..
  418. } else if( ValueType != DHCP_CLASS_LOCATION_TYPE ) {
  419. DhcpPrint((DEBUG_ERRORS, "DhcpLocationType is %ld\n", ValueType));
  420. DhcpAssert(FALSE);
  421. ValueSize = 0;
  422. }
  423. if( 0 == ValueSize ) { // choose default..
  424. Value = DEFAULT_USER_CLASS_LOC_FULL;
  425. }
  426. Error = DhcpRegExpandString( // replace '?' with AdapterName
  427. Value,
  428. AdapterName,
  429. &RetVal,
  430. NULL
  431. );
  432. if( 0 != ValueSize ) DhcpFreeMemory(Value); // free only if we didn't allocate
  433. if( ERROR_SUCCESS != Error ) return NULL; // can't return error codes?
  434. return RetVal;
  435. }
  436. ULONG _inline // status
  437. SetRegistryClassIdBin( // write the binary classid value
  438. IN LPWSTR AdapterName, // for this adapter
  439. IN LPBYTE ClassIdBin, // Binary value to write
  440. IN ULONG ClassIdBinSize // size of entry..
  441. )
  442. {
  443. ULONG Error;
  444. LPWSTR RegLocation; // registry location..
  445. LPWSTR RegValue;
  446. HKEY RegKey;
  447. RegLocation = GetRegClassIdBinLocation(AdapterName);
  448. if( NULL == RegLocation ) return ERROR_NOT_ENOUGH_MEMORY;
  449. RegValue = wcsrchr(RegLocation, REGISTRY_CONNECT);
  450. if( NULL == RegValue ) { // invalid string?
  451. return ERROR_INVALID_DATA;
  452. }
  453. *RegValue ++ = L'\0'; // separate key and value..
  454. Error = RegOpenKeyEx( // open the key..
  455. HKEY_LOCAL_MACHINE,
  456. RegLocation,
  457. 0 /* Reserved */,
  458. DHCP_CLIENT_KEY_ACCESS,
  459. &RegKey
  460. );
  461. if( ERROR_SUCCESS != Error ) {
  462. DhcpPrint((DEBUG_ERRORS, "Could not open key: %ws : %ld\n", RegLocation, Error));
  463. DhcpFreeMemory(RegLocation);
  464. return Error;
  465. }
  466. Error = RegSetValueEx(
  467. RegKey,
  468. RegValue,
  469. 0 /* Reserved */,
  470. REG_BINARY,
  471. ClassIdBin,
  472. ClassIdBinSize
  473. );
  474. RegCloseKey(RegKey);
  475. if( ERROR_SUCCESS != Error ) {
  476. DhcpPrint((DEBUG_ERRORS, "Could not save value:"
  477. "%ws / %ws: %ld\n", RegLocation, RegValue, Error));
  478. }
  479. DhcpFreeMemory(RegLocation);
  480. return Error;
  481. }
  482. ULONG // status
  483. FixupDhcpClassId( // fix ClassIdBin value in registry based on ClassId
  484. IN LPWSTR AdapterName,
  485. IN BOOL SkipClassEnum
  486. )
  487. {
  488. LPWSTR ClassIdName; // as written by UI
  489. LPBYTE ClassIdBin; // as needs to be written in registry
  490. ULONG ClassIdBinSize;// the # of bytes of above..
  491. ULONG Error; // status
  492. ClassIdName = NULL;
  493. Error = GetRegistryClassIdName(AdapterName, &ClassIdName);
  494. if( ERROR_SUCCESS != Error || NULL == ClassIdName
  495. || L'\0' == *ClassIdName ) {
  496. DhcpPrint((DEBUG_ERRORS, "Could not read ClassId: %ld\n", Error));
  497. ClassIdName = NULL;
  498. }
  499. ClassIdBinSize = 0; ClassIdBin = NULL;
  500. if( ClassIdName ) {
  501. Error = ConvertClassIdNameToBin(
  502. AdapterName, ClassIdName, SkipClassEnum, &ClassIdBin, &ClassIdBinSize
  503. );
  504. DhcpFreeMemory(ClassIdName);// Dont need this memory anymore
  505. } else {
  506. Error = ERROR_SUCCESS;
  507. }
  508. if( ERROR_SUCCESS != Error || NULL == ClassIdBin ) {
  509. DhcpPrint((DEBUG_ERRORS, "Could not convert classid.. making it NULL\n"));
  510. ClassIdBin = NULL;
  511. ClassIdBinSize = 0;
  512. }
  513. Error = SetRegistryClassIdBin(AdapterName, ClassIdBin, ClassIdBinSize);
  514. if( ClassIdBin ) DhcpFreeMemory(ClassIdBin);
  515. return Error;
  516. }
  517. //DOC DhcpHandlePnpEvent can be called as an API by any process (excepting that executing within the
  518. //DOC DHCP process itself) when any of the registry based configuration has changed and DHCP client has to
  519. //DOC re-read the registry. The Flags parameter is for future expansion.
  520. //DOC The AdapterName can currently be only GUIDs but may soon be EXTENDED to be IpAddress strings or
  521. //DOC h-w addresses or any other user friendly means of denoting the Adapter. Note that if the Adapter
  522. //DOC Name is NULL (not the empty string L""), then it refers to either GLOBAL parameters or ALL adapters
  523. //DOC depending on which BOOL has been set. (this may not get done for BETA2).
  524. //DOC The Changes structure gives the information on what changed.
  525. //DOC Currently, only a few of the defined BOOLs would be supported (for BETA2 NT5).
  526. //DOC
  527. //DOC Return Values:
  528. //DOC ERROR_DEVICE_DOES_NOT_EXIST The AdapterName is illegal in the given context
  529. //DOC ERROR_INVALID_PARAMETER
  530. //DOC ERROR_CALL_NOT_SUPPORTED The particular parameter that has changed is not completely pnp yet.
  531. //DOC Win32 errors
  532. DWORD
  533. WINAPI
  534. DhcpHandlePnPEvent(
  535. IN DWORD Flags, // MUST BE ZERO
  536. IN DWORD Caller, // currently must be DHCP_CALLER_TCPUI
  537. IN LPWSTR AdapterName, // currently must be the adapter GUID or NULL if global
  538. IN LPDHCP_PNP_CHANGE Changes, // specify what changed
  539. IN LPVOID Reserved // reserved for future use..
  540. )
  541. {
  542. ULONG Error;
  543. if( 0 != Flags || DHCP_CALLER_TCPUI != Caller ||
  544. NULL != Reserved || NULL == Changes ) {
  545. return ERROR_INVALID_PARAMETER; // sanity check
  546. }
  547. if( Changes->Version > DHCP_PNP_CHANGE_VERSION_0 ) {
  548. return ERROR_NOT_SUPPORTED; // this version is not supported
  549. }
  550. if( Changes->ClassIdChanged ) { // the classid got changed..
  551. // The UI writes any changes to the "DhcpClassId" registry value... but
  552. // this is just the name of the class and not the actual ClassId binary value
  553. // So we read this compare and write the correct value..
  554. (void) FixupDhcpClassId(AdapterName, FALSE); // figure the binary classid value
  555. }
  556. Error = DhcpStaticRefreshParams(AdapterName); // refresh all static params..
  557. if( ERROR_SUCCESS != Error ) return Error;
  558. if( Changes->ClassIdChanged ) {
  559. //
  560. // If ClassID changes, we have to refresh lease..
  561. //
  562. (void) DhcpAcquireParameters(AdapterName);
  563. }
  564. return ERROR_SUCCESS;
  565. }
  566. //================================================================================
  567. // end of file
  568. //================================================================================