Source code of Windows XP (NT5)
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.

2243 lines
80 KiB

  1. #include "precomp.h"
  2. #ifdef H_ONLY
  3. //================================================================================
  4. // Copyright (C) 1997 Microsoft Corporation
  5. // Author: RameshV
  6. // Description: these are the exported dhcp client api function definitions
  7. //================================================================================
  8. #ifndef APIAPPL_H_INCLUDED
  9. #define APIAPPL_H_INCLUDED
  10. #ifndef DHCPAPI_PARAMS_DEFINED
  11. #define DHCPAPI_PARAMS_DEFINED
  12. typedef struct _DHCPAPI_PARAMS { // use this structure to request params
  13. ULONG Flags; // for future use
  14. ULONG OptionId; // what option is this?
  15. BOOL IsVendor; // is this vendor specific?
  16. LPBYTE Data; // the actual data
  17. DWORD nBytesData; // how many bytes of data are there in Data?
  18. } DHCPAPI_PARAMS, *PDHCPAPI_PARAMS, *LPDHCPAPI_PARAMS;
  19. #endif DHCPAPI_PARAMS_DEFINED
  20. DWORD // win32 status
  21. DhcpAcquireParameters( // acquire/renew a lease
  22. IN LPWSTR AdapterName // adapter to acquire lease on
  23. );
  24. DWORD // win32 status
  25. DhcpAcquireParametersByBroadcast( // acquire/renew a lease
  26. IN LPWSTR AdapterName // adapter to acquire lease on
  27. );
  28. DWORD // win32 status
  29. DhcpFallbackRefreshParams( // refresh fallback params
  30. IN LPWSTR AdapterName // adapter to be refreshed
  31. );
  32. DWORD // win32 status
  33. DhcpReleaseParameters( // release an existing lease
  34. IN LPWSTR AdapterName // adpater to release lease for
  35. );
  36. DWORD // win32 status
  37. DhcpEnableDynamicConfic( // convert from static to dhcp
  38. IN LPWSTR AdapterName // convert for this adapter
  39. );
  40. DWORD // win32 status
  41. DhcpDisableDynamicConfig( // convert from dhcp to static
  42. IN LPWSTR AdapterName // convert this adapter
  43. );
  44. DWORD // win32 status
  45. DhcpReRegisterDynDns( // reregister static address with dns
  46. IN LPWSTR AdapterName
  47. );
  48. DWORD // win32 status
  49. APIENTRY
  50. DhcpRequestParams( // request parameters of client
  51. IN LPWSTR AdapterName, // adapter name to request for
  52. IN LPBYTE ClassId, // byte stream of class id to use
  53. IN DWORD ClassIdLen, // # of bytes of class id to use
  54. IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
  55. IN DWORD nSendParams, // size of above array
  56. IN DWORD Flags, // must be zero, reserved
  57. IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
  58. IN OUT LPDWORD pnRecdParamsBytes // i/p: size of above in BYTES, o/p required bytes or filled up # of elements
  59. ); // returns ERROR_MORE_DATA if o/p buffer is of insufficient size, and fills in reqd size in # of bytes
  60. DWORD // win32 status
  61. DhcpRegisterParameterChangeNotification( // notify if a parameter has changed
  62. IN LPWSTR AdapterName, // adapter of interest
  63. IN LPBYTE ClassId, // byte stream of class id to use
  64. IN DWORD ClassIdLen, // # of bytes of class id
  65. IN PDHCPAPI_PARAMS Params, // params of interest
  66. IN DWORD nParams, // # of elts in above array
  67. IN DWORD Flags, // must be zero, reserved
  68. IN OUT PHANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
  69. );
  70. DhcpDeRegisterParameterChangeNotification( // undo the registration
  71. IN HANDLE Event // handle to event returned by DhcpRegisterParameterChangeNotification, NULL ==> everything
  72. );
  73. DWORD // win32 status
  74. DhcpPersistentRequestParams( // parameters to request persistently
  75. IN LPWSTR AdapterName, // adapter name to request for
  76. IN LPBYTE ClassId, // byte stream of class id to use
  77. IN DWORD ClassIdLen, // # of bytes of class id
  78. IN PDHCPAPI_PARAMS SendParams, // persistent parameters
  79. IN DWORD nSendParams, // size of above array
  80. IN DWORD Flags, // must be zero, reserved
  81. IN LPWSTR AppName, // the name of the app that is to be used for this instance
  82. IN OUT LPDWORD UniqueId // OPTIONAL, return value is id that can be used in DhcpDelPersistentRequestParams
  83. );
  84. DWORD // win32 status
  85. DhcpDelPersistentRequestParams( // undo the effect of a persistent request -- currently undo from registry
  86. IN LPWSTR AdapterName, // the name of the adpater to delete for
  87. IN LPWSTR AppName, // the name used by the app
  88. IN DWORD UniqueId // something for this instance
  89. );
  90. #endif APIAPPL_H_INCLUDED
  91. #else H_ONLY
  92. #include <apiargs.h>
  93. #include <apistub.h>
  94. #include <apiimpl.h>
  95. #include <apiappl.h>
  96. #include <dhcploc.h>
  97. #include <dhcppro.h>
  98. #include <dhcpcsdk.h>
  99. DWORD INLINE // win32 status
  100. DhcpApiFillBuffer( // fill the buffer with some params
  101. IN OUT LPBYTE Buffer, // the buffer to fill
  102. IN DWORD MaxBufferSize, // the max size of buffer allwoed
  103. IN LPWSTR AdapterName, // fill in adapter name
  104. IN BYTE OpCode // what opcode to use?
  105. ) {
  106. DWORD Size;
  107. if( NULL == AdapterName ) Size = 0;
  108. else Size = (wcslen(AdapterName)+1)*sizeof(WCHAR);
  109. return DhcpApiArgAdd( // fill in the buffer with the reqd options
  110. Buffer,
  111. MaxBufferSize,
  112. OpCode,
  113. Size,
  114. (LPBYTE)AdapterName
  115. );
  116. }
  117. DWORD INLINE // win32 status
  118. DhcpAdapterOnlyApi( // execute apis that take only adapter name params
  119. IN LPWSTR AdapterName, // the adapter name
  120. IN BYTE OpCode
  121. )
  122. {
  123. LPBYTE Buffer;
  124. LPBYTE Buffer2;
  125. DWORD BufSize;
  126. DWORD Size;
  127. DWORD Error;
  128. BufSize = 0;
  129. Error = DhcpApiFillBuffer((LPBYTE)&BufSize, sizeof(BufSize), AdapterName, OpCode);
  130. DhcpAssert( ERROR_SUCCESS != Error );
  131. if( ERROR_MORE_DATA != Error ) return Error;
  132. DhcpAssert(BufSize);
  133. BufSize = ntohl(BufSize) + 2*sizeof(DWORD);
  134. Buffer = DhcpAllocateMemory(BufSize);
  135. if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY;
  136. *(DWORD UNALIGNED *)Buffer = htonl(0);
  137. Buffer2 = Buffer + sizeof(DWORD);
  138. *(DWORD UNALIGNED *)Buffer2 = 0;
  139. BufSize -= sizeof(DWORD);
  140. Error = DhcpApiFillBuffer(Buffer2, BufSize, AdapterName, OpCode);
  141. Size = 0;
  142. if( ERROR_SUCCESS == Error ) Error = ExecuteApiRequest(Buffer, NULL, &Size);
  143. DhcpFreeMemory(Buffer);
  144. return Error;
  145. }
  146. DWORD // win32 status
  147. DhcpAcquireParameters( // acquire/renew a lease
  148. IN LPWSTR AdapterName // adapter to acquire lease on
  149. ) {
  150. return DhcpAdapterOnlyApi(AdapterName, AcquireParametersOpCode);
  151. }
  152. DWORD // win32 status
  153. DhcpAcquireParametersByBroadcast( // acquire/renew a lease
  154. IN LPWSTR AdapterName // adapter to acquire lease on
  155. ) {
  156. return DhcpAdapterOnlyApi(AdapterName, AcquireParametersByBroadcastOpCode);
  157. }
  158. DWORD // win32 status
  159. DhcpFallbackRefreshParams( // refresh fallback params
  160. IN LPWSTR AdapterName // adapter to be refreshed
  161. )
  162. {
  163. return DhcpAdapterOnlyApi(AdapterName, FallbackParamsOpCode);
  164. }
  165. DWORD // win32 status
  166. DhcpReleaseParameters( // release an existing lease
  167. IN LPWSTR AdapterName // adpater to release lease for
  168. ) {
  169. return DhcpAdapterOnlyApi(AdapterName, ReleaseParametersOpCode);
  170. }
  171. DWORD // win32 status
  172. DhcpEnableDynamicConfig( // convert from static to dhcp
  173. IN LPWSTR AdapterName // convert for this adapter
  174. ) {
  175. return DhcpAdapterOnlyApi(AdapterName, EnableDhcpOpCode);
  176. }
  177. DWORD // win32 status
  178. DhcpDisableDynamicConfig( // convert from dhcp to static
  179. IN LPWSTR AdapterName // convert this adapter
  180. ) {
  181. return DhcpAdapterOnlyApi(AdapterName, DisableDhcpOpCode);
  182. }
  183. DWORD // win32 status
  184. DhcpStaticRefreshParamsInternal( // refresh some static parameters that have changed
  185. IN LPWSTR AdapterName,
  186. IN BOOL fDoDns
  187. )
  188. {
  189. LPBYTE Buffer, Buffer2;
  190. DWORD BufSize, Size, Error, Code;
  191. BufSize = 0;
  192. Error = DhcpApiFillBuffer(
  193. (LPBYTE)&BufSize, sizeof(BufSize), AdapterName, StaticRefreshParamsOpCode
  194. );
  195. if( ERROR_MORE_DATA != Error ) return Error;
  196. DhcpAssert( BufSize );
  197. BufSize = ntohl(BufSize) + 2 * sizeof(DWORD);
  198. BufSize += 3*sizeof(DWORD);
  199. Buffer = DhcpAllocateMemory( BufSize );
  200. if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY;
  201. *(DWORD*)Buffer = 0;
  202. Buffer2 = Buffer + sizeof(DWORD);
  203. *(DWORD*)Buffer2 = 0;
  204. BufSize -= sizeof(DWORD);
  205. Error = DhcpApiFillBuffer(
  206. Buffer2, BufSize, AdapterName, StaticRefreshParamsOpCode
  207. );
  208. DhcpAssert( ERROR_SUCCESS == Error );
  209. Code = (fDoDns ? 0x00 : 0x01);
  210. Error = DhcpApiArgAdd(
  211. Buffer2, BufSize, (BYTE)FlagsParam, sizeof(DWORD), (LPBYTE)&Code
  212. );
  213. DhcpAssert( ERROR_SUCCESS == Error );
  214. Size = 0;
  215. Error = ExecuteApiRequest(Buffer, NULL, &Size);
  216. DhcpFreeMemory( Buffer );
  217. return Error;
  218. }
  219. DWORD
  220. DhcpStaticRefreshParams(
  221. IN LPWSTR AdapterName
  222. )
  223. {
  224. return DhcpStaticRefreshParamsInternal(AdapterName, TRUE );
  225. }
  226. #if 0
  227. // pl dont use this api, use DhcpRequestParams instead.
  228. DWORD // win32 status
  229. DhcpRequestOptions( // request for specific options
  230. IN LPWSTR AdapterName, // which adapter's info is needed
  231. IN LPBYTE RequestedOpt, // list of requested options
  232. IN DWORD nRequestedOpts,// size of above BYTE array
  233. OUT LPBYTE *OptData, // the data for each available option
  234. IN OUT LPDWORD OptDataSize, // # of bytes of above byte array
  235. OUT LPBYTE *AvailOpts, // the list of available options
  236. IN OUT LPDWORD nAvailOpts // # of available options
  237. ) {
  238. PDHCP_API_ARGS DhcpApiArgs;
  239. CHAR TmpBuf[OPTION_END+1];
  240. LPBYTE OutBuf;
  241. LPBYTE InBuf;
  242. LPBYTE Buffer;
  243. LPBYTE Endp;
  244. LPBYTE RetOptList;
  245. LPBYTE RetDataList;
  246. DWORD Size;
  247. DWORD OutBufSize;
  248. DWORD InBufSize;
  249. DWORD i;
  250. DWORD nArgsReturned;
  251. DWORD Error;
  252. BOOL Tmp;
  253. // check parameter consistency
  254. if( NULL == AdapterName || NULL == RequestedOpt || 0 == nRequestedOpts )
  255. return ERROR_INVALID_PARAMETER;
  256. if( NULL == AvailOpts || 0 == nAvailOpts || NULL == OptData || 0 == OptDataSize )
  257. return ERROR_INVALID_PARAMETER;
  258. if( nRequestedOpts >= OPTION_END ) return ERROR_NO_SYSTEM_RESOURCES;
  259. // initialize out params
  260. (*nAvailOpts) = (*OptDataSize) = 0;
  261. (*AvailOpts) = (*OptData) = NULL;
  262. // calculate input buffer size for ONE option to be sent and allocate it
  263. InBufSize = 0;
  264. InBufSize += sizeof(DWORD)*2; // INBUF_SIZE, OUTBUF_SIZE
  265. InBufSize += sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR);
  266. InBufSize += sizeof(BYTE)+sizeof(DWORD)+nRequestedOpts+sizeof(BYTE);
  267. InBuf = DhcpAllocateMemory(InBufSize);
  268. if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  269. // intialize ptrs
  270. OutBufSize = 0; OutBuf = NULL;
  271. DhcpApiArgs = NULL;
  272. RetOptList = RetDataList = NULL;
  273. // now fill the input buffer
  274. ((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
  275. ((DWORD UNALIGNED*)InBuf)[1] = 0;
  276. Buffer = InBuf + sizeof(DWORD); InBufSize -= sizeof(DWORD);
  277. Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, RequestParamsOpCode);
  278. DhcpAssert(ERROR_SUCCESS == Error);
  279. TmpBuf[0] = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
  280. memcpy(&TmpBuf[1], RequestedOpt, nRequestedOpts);
  281. Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, nRequestedOpts+1, TmpBuf);
  282. DhcpAssert(ERROR_SUCCESS == Error);
  283. Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
  284. if( ERROR_SUCCESS == Error ) {
  285. DhcpAssert(0 == OutBufSize);
  286. goto Cleanup;
  287. }
  288. if( ERROR_MORE_DATA != Error ) goto Cleanup; // ERROR_MORE_DATA ==> need to allocate buffer
  289. DhcpPrint((DEBUG_OPTIONS, "RequestOptions: retrying with buffer size [%ld]\n", OutBufSize));
  290. DhcpAssert(OutBufSize);
  291. OutBuf = DhcpAllocateMemory(OutBufSize);
  292. if( NULL == OutBuf) {
  293. Error = ERROR_NOT_ENOUGH_MEMORY;
  294. goto Cleanup;
  295. }
  296. ((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
  297. Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
  298. DhcpAssert(ERROR_MORE_DATA != Error); // can happen, just hope it does not...
  299. if( ERROR_SUCCESS != Error ) goto Cleanup; // unexpected error
  300. nArgsReturned = 0;
  301. DhcpApiArgs = NULL;
  302. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned );
  303. if( ERROR_MORE_DATA != Error ) goto Cleanup;
  304. DhcpAssert(nArgsReturned);
  305. if( 0 == nArgsReturned ) goto Cleanup; // no options sent? funny.. still, quit its
  306. DhcpApiArgs = DhcpAllocateMemory(sizeof(DHCP_API_ARGS)*nArgsReturned);
  307. if( NULL == DhcpApiArgs ) {
  308. Error = ERROR_NOT_ENOUGH_MEMORY;
  309. goto Cleanup;
  310. }
  311. nArgsReturned = 0;
  312. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
  313. if( ERROR_SUCCESS != Error ) {
  314. DhcpAssert(FALSE);
  315. goto Cleanup;
  316. }
  317. DhcpAssert(nArgsReturned);
  318. RetOptList = DhcpAllocateMemory(nArgsReturned);
  319. if( NULL == RetOptList ) {
  320. Error = ERROR_NOT_ENOUGH_MEMORY;
  321. goto Cleanup;
  322. }
  323. Size = 0;
  324. for( i = 0; i < nArgsReturned; i ++ ) {
  325. DhcpAssert(DhcpApiArgs[i].ArgId == NormalOptionParam);
  326. if( DhcpApiArgs[i].ArgId != NormalOptionParam ) continue;
  327. DhcpAssert(DhcpApiArgs[i].ArgSize <= OPTION_END +1 );
  328. if( DhcpApiArgs[i].ArgSize <= 1 ) continue;
  329. Size += DhcpApiArgs[i].ArgSize;
  330. }
  331. RetDataList = DhcpAllocateMemory(Size);
  332. if( NULL == RetDataList ) {
  333. Error = ERROR_NOT_ENOUGH_MEMORY;
  334. goto Cleanup;
  335. }
  336. Size = 0;
  337. for(i = 0; i < nArgsReturned; i ++ ) {
  338. if( DhcpApiArgs[i].ArgId != NormalOptionParam ) continue;
  339. if( DhcpApiArgs[i].ArgSize <= 1 ) continue;
  340. RetOptList[i] = DhcpApiArgs[i].ArgVal[0];
  341. RetDataList[Size++] = (BYTE)(DhcpApiArgs[i].ArgSize - 1);
  342. memcpy(&RetDataList[Size], DhcpApiArgs[i].ArgVal, DhcpApiArgs[i].ArgSize - 1);
  343. Size += DhcpApiArgs[i].ArgSize - 1;
  344. }
  345. (*AvailOpts) = RetOptList;
  346. (*nAvailOpts) = nArgsReturned;
  347. (*OptData) = RetDataList;
  348. (*OptDataSize) = Size;
  349. DhcpFreeMemory(InBuf);
  350. DhcpFreeMemory(OutBuf);
  351. DhcpFreeMemory(DhcpApiArgs);
  352. return ERROR_SUCCESS;
  353. Cleanup:
  354. if( InBuf ) DhcpFreeMemory(InBuf);
  355. if( OutBuf ) DhcpFreeMemory(OutBuf);
  356. if( DhcpApiArgs ) DhcpFreeMemory(DhcpApiArgs);
  357. if( RetDataList ) DhcpFreeMemory(RetDataList);
  358. if( RetOptList) DhcpFreeMemory(RetOptList);
  359. return Error;
  360. }
  361. #endif
  362. // pl dont use this api, use DhcpRequestParams instead.
  363. DWORD // win32 status
  364. DhcpRequestOptions( // request for specific options
  365. IN LPWSTR AdapterName, // which adapter's info is needed
  366. IN LPBYTE RequestedOpt, // list of requested options
  367. IN DWORD nRequestedOpts,// size of above BYTE array
  368. OUT LPBYTE *OptData, // the data for each available option
  369. IN OUT LPDWORD OptDataSize, // # of bytes of above byte array
  370. OUT LPBYTE *AvailOpts, // the list of available options
  371. IN OUT LPDWORD nAvailOpts // # of available options
  372. ) {
  373. DHCPAPI_PARAMS SendParams;
  374. PDHCPAPI_PARAMS RecdParams;
  375. LPBYTE RetDataList;
  376. LPBYTE RetOptList;
  377. DWORD nRecdParams;
  378. DWORD Error;
  379. DWORD i;
  380. DWORD OutBufSize;
  381. // check parameter consistency
  382. if( NULL == AdapterName || NULL == RequestedOpt || 0 == nRequestedOpts )
  383. return ERROR_INVALID_PARAMETER;
  384. if( NULL == AvailOpts || 0 == nAvailOpts || NULL == OptData || 0 == OptDataSize )
  385. return ERROR_INVALID_PARAMETER;
  386. if( nRequestedOpts >= OPTION_END ) return ERROR_NO_SYSTEM_RESOURCES;
  387. // initialize out params
  388. (*nAvailOpts) = (*OptDataSize) = 0;
  389. (*AvailOpts) = (*OptData) = NULL;
  390. // try to process this request
  391. SendParams.OptionId = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
  392. SendParams.IsVendor = FALSE;
  393. SendParams.Data = RequestedOpt;
  394. SendParams.nBytesData = nRequestedOpts;
  395. nRecdParams = 0;
  396. Error = DhcpRequestParameters(
  397. AdapterName,
  398. NULL,
  399. 0,
  400. &SendParams,
  401. 1,
  402. 0,
  403. NULL,
  404. &nRecdParams
  405. );
  406. if( ERROR_MORE_DATA != Error ) return Error;
  407. while ( TRUE ) {
  408. DhcpAssert(nRecdParams);
  409. DhcpPrint((DEBUG_OPTIONS, "RequestOptions: require: 0x%lx bytes\n", nRecdParams));
  410. RecdParams = DhcpAllocateMemory(nRecdParams);
  411. if( NULL == RecdParams ) return ERROR_NOT_ENOUGH_MEMORY;
  412. Error = DhcpRequestParameters(
  413. AdapterName,
  414. NULL,
  415. 0,
  416. &SendParams,
  417. 1,
  418. 0,
  419. RecdParams,
  420. &nRecdParams
  421. );
  422. // DhcpAssert(ERROR_MORE_DATA != Error);
  423. if( ERROR_SUCCESS != Error ) {
  424. DhcpPrint((DEBUG_ERRORS, "RequestOptions:RequestParams:0x%lx\n", Error));
  425. DhcpFreeMemory(RecdParams);
  426. if( ERROR_MORE_DATA == Error ) continue;
  427. return Error;
  428. }
  429. break;
  430. }
  431. if( 0 == nRecdParams ) return ERROR_SUCCESS;
  432. DhcpPrint((DEBUG_OPTIONS, "Received 0x%lx options\n", nRecdParams));
  433. RetOptList = NULL;
  434. RetDataList = NULL;
  435. OutBufSize = 0;
  436. for( i = 0; i < nRecdParams; i ++ ) {
  437. DhcpPrint((DEBUG_TRACE, "Received option 0x%lx, 0x%lx bytes\n",
  438. RecdParams[i].OptionId, RecdParams[i].nBytesData));
  439. OutBufSize += RecdParams[i].nBytesData + sizeof(BYTE);
  440. }
  441. RetOptList = DhcpAllocateMemory(nRecdParams);
  442. RetDataList = DhcpAllocateMemory(OutBufSize);
  443. if( NULL == RetOptList || NULL == RetDataList ) {
  444. if( RetOptList ) DhcpFreeMemory(RetOptList);
  445. if( RetDataList ) DhcpFreeMemory(RetDataList);
  446. if( RecdParams ) DhcpFreeMemory(RecdParams);
  447. return ERROR_NOT_ENOUGH_MEMORY;
  448. }
  449. OutBufSize = 0;
  450. for( i = 0; i < nRecdParams ; i ++ ) {
  451. RetOptList[i] = (BYTE)RecdParams[i].OptionId;
  452. RetDataList[OutBufSize++] = (BYTE)RecdParams[i].nBytesData;
  453. memcpy(&RetDataList[OutBufSize], RecdParams[i].Data, RecdParams[i].nBytesData);
  454. OutBufSize += RecdParams[i].nBytesData;
  455. }
  456. (*AvailOpts) = RetOptList;
  457. (*nAvailOpts) = nRecdParams;
  458. (*OptData) = RetDataList;
  459. (*OptDataSize) = OutBufSize;
  460. if( RecdParams ) DhcpFreeMemory(RecdParams);
  461. return ERROR_SUCCESS;
  462. }
  463. DWORD // win32 status
  464. DhcpRequestParamsInternalEx( // request parameters of client
  465. IN BYTE OpCode, // opcode to use
  466. IN LPWSTR AdapterName, // adapter name to request for
  467. IN LPBYTE ClassId, // byte stream of class id to use
  468. IN DWORD ClassIdLen, // # of bytes of class id to use
  469. IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
  470. IN DWORD nSendParams, // size of above array
  471. IN DWORD Flags, // must be zero, reserved
  472. IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
  473. IN OUT DWORD *pnRecdParams, // input: size of above array output: filled size
  474. IN LPBYTE Bufp, // buffer for data ptrs
  475. IN OUT LPDWORD pSize // i/p: size of above array, o/p filled size
  476. )
  477. {
  478. PDHCP_API_ARGS DhcpApiArgs = NULL;
  479. LPBYTE OutBuf;
  480. LPBYTE InBuf = NULL;
  481. LPBYTE Buffer;
  482. LPBYTE Endp;
  483. DWORD OutBufSize;
  484. DWORD InBufSize;
  485. DWORD i,j;
  486. DWORD nArgsReturned;
  487. DWORD Error;
  488. DWORD nRecdParams = (*pnRecdParams);
  489. DWORD nParamsRequested;
  490. DWORD nVParamsRequested;
  491. ULONG Tmp, VTmp;
  492. CHAR TmpBuf[256], VTmpBuf[256];
  493. // check parameter consistency
  494. if( ClassIdLen && NULL == ClassId) return ERROR_INVALID_PARAMETER;
  495. if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
  496. if( nSendParams && NULL == SendParams) return ERROR_INVALID_PARAMETER;
  497. if( 0 == nSendParams && NULL != SendParams) return ERROR_INVALID_PARAMETER;
  498. if( NULL == RecdParams || 0 == nRecdParams ) return ERROR_INVALID_PARAMETER;
  499. if( NULL == AdapterName ) return ERROR_INVALID_PARAMETER;
  500. Tmp = VTmp = 0;
  501. for( i = 0; i < nRecdParams ; i ++ ) {
  502. if( FALSE == RecdParams[i].IsVendor ) {
  503. TmpBuf[ ++Tmp] = (BYTE)RecdParams[i].OptionId;
  504. } else {
  505. VTmpBuf[ ++VTmp] = (BYTE)RecdParams[i].OptionId;
  506. }
  507. }
  508. if( 0 == (VTmp + Tmp) ) return ERROR_INVALID_PARAMETER;
  509. // allocate buffers
  510. OutBufSize = (*pSize);
  511. (*pSize) = 0;
  512. if( 0 == OutBufSize ) OutBuf = NULL;
  513. else {
  514. OutBuf = Bufp;
  515. }
  516. // calculate input buffer size required
  517. InBufSize = 0;
  518. InBufSize += (DWORD)(sizeof(DWORD)*2); // INBUF_SIZE, OUTBUF_SIZE
  519. InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
  520. if( ClassIdLen )
  521. InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
  522. for( i = 0; i < nSendParams; i ++ ) {
  523. InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+SendParams[i].nBytesData;
  524. }
  525. //
  526. // Now for options request list (vendor and otherwise)
  527. //
  528. if( Tmp ) {
  529. InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+Tmp;
  530. }
  531. if( VTmp ) {
  532. InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+VTmp;
  533. }
  534. InBuf = DhcpAllocateMemory(InBufSize);
  535. if( NULL == InBuf ) {
  536. return ERROR_NOT_ENOUGH_MEMORY;
  537. }
  538. // fill up output buffer size right at start of input buffer
  539. ((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
  540. ((DWORD UNALIGNED*)InBuf)[1] = 0;
  541. Buffer = InBuf + sizeof(DWORD);
  542. InBufSize -= sizeof(DWORD);
  543. // fill in input buffer
  544. Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, OpCode);
  545. DhcpAssert(ERROR_SUCCESS == Error);
  546. if( ClassIdLen ) {
  547. Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
  548. DhcpAssert(ERROR_SUCCESS == Error);
  549. }
  550. for( i = 0; i < nSendParams; i ++ ) {
  551. BYTE Buf[OPTION_END+1];
  552. BYTE OpCode;
  553. Buf[0] = (BYTE)SendParams[i].OptionId;
  554. memcpy(&Buf[1], SendParams[i].Data, SendParams[i].nBytesData);
  555. OpCode = SendParams[i].IsVendor? VendorOptionParam: NormalOptionParam;
  556. Error = DhcpApiArgAdd(Buffer, InBufSize, OpCode, SendParams[i].nBytesData+1, Buf);
  557. DhcpAssert(ERROR_SUCCESS == Error);
  558. }
  559. //
  560. // Now fillup the request lists (vendor & otherwise)
  561. //
  562. if( Tmp ) {
  563. TmpBuf[0] = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
  564. Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, Tmp+1, TmpBuf);
  565. DhcpAssert(ERROR_SUCCESS == Error);
  566. }
  567. if( VTmp ) {
  568. VTmpBuf[0] = (BYTE)OPTION_PAD;
  569. Error = DhcpApiArgAdd(Buffer, InBufSize, VendorOptionParam, VTmp+1, VTmpBuf);
  570. }
  571. // now, execute and obtain the output filled in OutBuf
  572. Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
  573. (*pSize) = OutBufSize;
  574. if( ERROR_MORE_DATA == Error ) {
  575. // recalculate the real OutBufSize required
  576. DhcpAssert(OutBufSize != 0);
  577. goto Cleanup;
  578. }
  579. if( ERROR_SUCCESS != Error ) goto Cleanup;
  580. if( 0 == OutBufSize ) goto Cleanup;
  581. // parse output and fill in the structures..
  582. nArgsReturned = 0;
  583. DhcpApiArgs = NULL;
  584. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
  585. DhcpAssert( 0 == nArgsReturned || ERROR_MORE_DATA == Error);
  586. if( ERROR_MORE_DATA != Error ) goto Cleanup;
  587. DhcpAssert(0 != nArgsReturned);
  588. DhcpApiArgs = DhcpAllocateMemory( sizeof(DHCP_API_ARGS) * nArgsReturned);
  589. if( NULL == DhcpApiArgs ) {
  590. Error = ERROR_NOT_ENOUGH_MEMORY;
  591. goto Cleanup;
  592. }
  593. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
  594. DhcpAssert(ERROR_SUCCESS == Error);
  595. DhcpAssert(nArgsReturned);
  596. for(i = j = 0; i < nArgsReturned; i ++ ) {
  597. DhcpAssert( VendorOptionParam == DhcpApiArgs[i].ArgId || NormalOptionParam == DhcpApiArgs[i].ArgId);
  598. DhcpAssert( DhcpApiArgs[i].ArgSize > 1); // one byte for option id, and atleast one byte actual option
  599. if( VendorOptionParam != DhcpApiArgs[i].ArgId && NormalOptionParam != DhcpApiArgs[i].ArgId )
  600. continue;
  601. RecdParams[j].OptionId = DhcpApiArgs[i].ArgVal[0];
  602. RecdParams[j].IsVendor = ( VendorOptionParam == DhcpApiArgs[i].ArgId );
  603. RecdParams[j].nBytesData = DhcpApiArgs[i].ArgSize-1;
  604. RecdParams[j].Data = &DhcpApiArgs[i].ArgVal[1];
  605. j ++;
  606. }
  607. (*pnRecdParams) = j;
  608. Error = ERROR_SUCCESS;
  609. Cleanup:
  610. if( NULL != InBuf ) DhcpFreeMemory(InBuf);
  611. if( NULL != DhcpApiArgs ) DhcpFreeMemory(DhcpApiArgs);
  612. return Error;
  613. }
  614. DWORD // win32 status
  615. DhcpRequestParamsInternal( // request parameters of client
  616. IN BYTE OpCode, // opcode to use
  617. IN LPWSTR AdapterName, // adapter name to request for
  618. IN LPBYTE ClassId, // byte stream of class id to use
  619. IN DWORD ClassIdLen, // # of bytes of class id to use
  620. IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
  621. IN DWORD nSendParams, // size of above array
  622. IN DWORD Flags, // must be zero, reserved
  623. IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
  624. IN OUT LPDWORD pnRecdParams // i/p: size of above in BYTES, o/p required or filled up size
  625. ) {
  626. PDHCP_API_ARGS DhcpApiArgs = NULL;
  627. LPBYTE OutBuf;
  628. LPBYTE InBuf = NULL;
  629. LPBYTE Buffer;
  630. LPBYTE Endp;
  631. DWORD OutBufSize;
  632. DWORD InBufSize;
  633. DWORD i,j;
  634. DWORD nArgsReturned;
  635. DWORD Error;
  636. DWORD nParamsRequested;
  637. DWORD nVParamsRequested;
  638. ULONG Tmp, VTmp;
  639. ULONG OriginalOutBufSize;
  640. // check parameter consistency
  641. if( ClassIdLen && NULL == ClassId) return ERROR_INVALID_PARAMETER;
  642. if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
  643. if( nSendParams && NULL == SendParams) return ERROR_INVALID_PARAMETER;
  644. if( 0 == nSendParams && NULL != SendParams) return ERROR_INVALID_PARAMETER;
  645. if( NULL == pnRecdParams ) return ERROR_INVALID_PARAMETER;
  646. if( *pnRecdParams && NULL == RecdParams ) return ERROR_INVALID_PARAMETER;
  647. if( NULL == AdapterName ) return ERROR_INVALID_PARAMETER;
  648. Tmp = VTmp = 0;
  649. for( i = 0; i < nSendParams ; i ++ ) {
  650. if( SendParams[i].nBytesData > OPTION_END ) return ERROR_INVALID_PARAMETER;
  651. if( SendParams[i].nBytesData && NULL == SendParams[i].Data )
  652. return ERROR_INVALID_PARAMETER;
  653. if( OPTION_PARAMETER_REQUEST_LIST == SendParams[i].OptionId ) {
  654. if( SendParams[i].IsVendor ) continue;
  655. nParamsRequested = SendParams[i].nBytesData;
  656. Tmp ++;
  657. }
  658. if( OPTION_PAD == SendParams[i].OptionId ) {
  659. if( !SendParams[i].IsVendor ) continue;
  660. nVParamsRequested = SendParams[i].nBytesData;
  661. VTmp ++;
  662. }
  663. }
  664. if( 0 == (VTmp + Tmp) || 1 < VTmp || 1 < Tmp ) return ERROR_INVALID_PARAMETER;
  665. if( 0 == Tmp) nParamsRequested = 0;
  666. if( VTmp ) nParamsRequested += nVParamsRequested;
  667. // allocate buffers
  668. OriginalOutBufSize = OutBufSize = (*pnRecdParams);
  669. (*pnRecdParams) = 0;
  670. if( 0 == OutBufSize ) OutBuf = NULL;
  671. else {
  672. OutBuf = DhcpAllocateMemory(OutBufSize);
  673. if( NULL == OutBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  674. }
  675. // calculate input buffer size required
  676. InBufSize = 0;
  677. InBufSize += (DWORD)(sizeof(DWORD)*2); // INBUF_SIZE, OUTBUF_SIZE
  678. InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
  679. if( ClassIdLen )
  680. InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
  681. for( i = 0; i < nSendParams; i ++ ) {
  682. InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+SendParams[i].nBytesData;
  683. }
  684. InBuf = DhcpAllocateMemory(InBufSize);
  685. if( NULL == InBuf ) {
  686. DhcpFreeMemory(OutBuf);
  687. return ERROR_NOT_ENOUGH_MEMORY;
  688. }
  689. // fill up output buffer size right at start of input buffer
  690. ((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
  691. ((DWORD UNALIGNED*)InBuf)[1] = 0;
  692. Buffer = InBuf + sizeof(DWORD);
  693. InBufSize -= sizeof(DWORD);
  694. // fill in input buffer
  695. Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, OpCode);
  696. DhcpAssert(ERROR_SUCCESS == Error);
  697. if( ClassIdLen ) {
  698. Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
  699. DhcpAssert(ERROR_SUCCESS == Error);
  700. }
  701. for( i = 0; i < nSendParams; i ++ ) {
  702. BYTE Buf[OPTION_END+1];
  703. BYTE OpCode;
  704. Buf[0] = (BYTE)SendParams[i].OptionId;
  705. memcpy(&Buf[1], SendParams[i].Data, SendParams[i].nBytesData);
  706. OpCode = SendParams[i].IsVendor? VendorOptionParam: NormalOptionParam;
  707. Error = DhcpApiArgAdd(Buffer, InBufSize, OpCode, SendParams[i].nBytesData+1, Buf);
  708. DhcpAssert(ERROR_SUCCESS == Error);
  709. }
  710. // now, execute and obtain the output filled in OutBuf
  711. Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
  712. if( ERROR_MORE_DATA == Error ) {
  713. // recalculate the real OutBufSize required
  714. DhcpAssert(OutBufSize != 0);
  715. OutBufSize += nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)));
  716. (*pnRecdParams) = OutBufSize;
  717. goto Cleanup;
  718. }
  719. if( ERROR_SUCCESS != Error ) goto Cleanup;
  720. if( 0 == OutBufSize ) goto Cleanup;
  721. // parse output and fill in the structures..
  722. nArgsReturned = 0;
  723. DhcpApiArgs = NULL;
  724. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
  725. DhcpAssert( 0 == nArgsReturned || ERROR_MORE_DATA == Error);
  726. if( ERROR_MORE_DATA != Error ) goto Cleanup;
  727. DhcpAssert(0 != nArgsReturned);
  728. DhcpApiArgs = DhcpAllocateMemory( sizeof(DHCP_API_ARGS) * nArgsReturned);
  729. if( NULL == DhcpApiArgs ) {
  730. Error = ERROR_NOT_ENOUGH_MEMORY;
  731. goto Cleanup;
  732. }
  733. Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
  734. DhcpAssert(ERROR_SUCCESS == Error);
  735. DhcpAssert(nArgsReturned);
  736. if( OriginalOutBufSize < OutBufSize + nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)) ) ) {
  737. //
  738. // Input size is not sufficient
  739. //
  740. (*pnRecdParams ) = OutBufSize + nParamsRequested*(
  741. sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD) )
  742. );
  743. Error = ERROR_MORE_DATA;
  744. // DbgPrint("Bug 330419 repro'ed");
  745. goto Cleanup;
  746. }
  747. Endp = OutBufSize + (LPBYTE)RecdParams + nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)));
  748. for(i = j = 0; i < nArgsReturned; i ++ ) {
  749. DhcpAssert( VendorOptionParam == DhcpApiArgs[i].ArgId || NormalOptionParam == DhcpApiArgs[i].ArgId);
  750. DhcpAssert( DhcpApiArgs[i].ArgSize > 1); // one byte for option id, and atleast one byte actual option
  751. if( VendorOptionParam != DhcpApiArgs[i].ArgId && NormalOptionParam != DhcpApiArgs[i].ArgId )
  752. continue;
  753. RecdParams[j].OptionId = DhcpApiArgs[i].ArgVal[0];
  754. RecdParams[j].IsVendor = ( VendorOptionParam == DhcpApiArgs[i].ArgId );
  755. RecdParams[j].nBytesData = DhcpApiArgs[i].ArgSize-1;
  756. Endp -= RecdParams[j].nBytesData;
  757. memcpy(Endp, &DhcpApiArgs[i].ArgVal[1], RecdParams[j].nBytesData);
  758. RecdParams[j].Data = Endp;
  759. j ++;
  760. }
  761. DhcpAssert(((LPBYTE)&RecdParams[j]) <= Endp);
  762. *pnRecdParams = j;
  763. Error = ERROR_SUCCESS;
  764. Cleanup:
  765. DhcpFreeMemory(InBuf);
  766. if(OutBuf) DhcpFreeMemory(OutBuf);
  767. if(DhcpApiArgs) DhcpFreeMemory(DhcpApiArgs);
  768. return Error;
  769. }
  770. DWORD // win32 status
  771. APIENTRY
  772. DhcpRequestParameters( // request parameters of client
  773. IN LPWSTR AdapterName, // adapter name to request for
  774. IN LPBYTE ClassId, // byte stream of class id to use
  775. IN DWORD ClassIdLen, // # of bytes of class id to use
  776. IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
  777. IN DWORD nSendParams, // size of above array
  778. IN DWORD Flags, // must be zero, reserved
  779. IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
  780. IN OUT LPDWORD pnRecdParams // i/p: size of above in BYTES, o/p required or filled up size
  781. ) {
  782. return DhcpRequestParamsInternal(
  783. RequestParamsOpCode,
  784. AdapterName,
  785. ClassId,
  786. ClassIdLen,
  787. SendParams,
  788. nSendParams,
  789. Flags,
  790. RecdParams,
  791. pnRecdParams
  792. );
  793. }
  794. DWORD // win32 status
  795. DhcpRegisterParameterChangeNotificationInternal( // notify if a parameter has changed -- common between NT and VxD
  796. IN LPWSTR AdapterName, // adapter of interest
  797. IN LPBYTE ClassId, // byte stream of class id to use
  798. IN DWORD ClassIdLen, // # of bytes of class id
  799. IN PDHCPAPI_PARAMS Params, // params of interest
  800. IN DWORD nParams, // # of elts in above array
  801. IN DWORD Flags, // must be zero, reserved
  802. IN DWORD Descriptor, // thsi describes the event uniquely for this process
  803. IN HANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
  804. ) {
  805. LPBYTE InBuf;
  806. LPBYTE OptList;
  807. LPBYTE VendorOptList;
  808. LPBYTE Buffer;
  809. DWORD Error;
  810. DWORD InBufSize;
  811. DWORD nVendorOpts;
  812. DWORD nOpts;
  813. DWORD ProcId;
  814. DWORD OutBufSize;
  815. DWORD i;
  816. VendorOptList = OptList = NULL;
  817. nVendorOpts = nOpts = 0;
  818. InBufSize = 2*sizeof(DWORD); // expected outbuf size + inbuf size
  819. InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Proc Id
  820. InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Event Handle
  821. InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Descriptor
  822. InBufSize += (DWORD)(sizeof(Descriptor)+sizeof(hEvent)+sizeof(DWORD));
  823. InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
  824. if( ClassIdLen )
  825. InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
  826. for( i = 0; i < nParams; i ++ ) {
  827. if( OPTION_PARAMETER_REQUEST_LIST == Params[i].OptionId ) {
  828. if( Params[i].IsVendor ) continue;
  829. if( nOpts ) return ERROR_INVALID_PARAMETER;
  830. nOpts = Params[i].nBytesData;
  831. if( 0 == nOpts ) return ERROR_INVALID_PARAMETER;
  832. OptList = Params[i].Data;
  833. continue;
  834. }
  835. if( OPTION_PAD == Params[i].OptionId ) {
  836. if( ! Params[i].IsVendor ) continue;
  837. if( nVendorOpts ) return ERROR_INVALID_PARAMETER;
  838. nVendorOpts = Params[i].nBytesData;
  839. if( 0 == nVendorOpts ) return ERROR_INVALID_PARAMETER;
  840. VendorOptList = Params[i].Data;
  841. continue;
  842. }
  843. }
  844. if( 0 == nOpts + nVendorOpts ) return ERROR_INVALID_PARAMETER;
  845. if( nOpts ) InBufSize += sizeof(BYTE) + sizeof(DWORD) + nOpts;
  846. if( nVendorOpts ) InBufSize += sizeof(BYTE) + sizeof(DWORD) + nVendorOpts;
  847. InBuf = DhcpAllocateMemory(InBufSize);
  848. if( NULL == InBuf ) {
  849. return ERROR_NOT_ENOUGH_MEMORY;
  850. }
  851. Buffer = InBuf + sizeof(DWORD);
  852. ((DWORD UNALIGNED*)InBuf)[0] = 0; // dont expect anything in return other than status
  853. ((DWORD UNALIGNED*)Buffer)[0] = 0; // increase the input buffer size each time we add something
  854. InBufSize -= sizeof(DWORD); // ignore the first DWORD
  855. Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, RegisterParamsOpCode);
  856. DhcpAssert(ERROR_SUCCESS == Error );
  857. if( ClassIdLen ) {
  858. Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
  859. DhcpAssert(ERROR_SUCCESS == Error);
  860. }
  861. if( nOpts ) {
  862. Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, nOpts, OptList);
  863. DhcpAssert(ERROR_SUCCESS == Error);
  864. }
  865. if( nVendorOpts ) {
  866. Error = DhcpApiArgAdd(Buffer, InBufSize, VendorOptionParam, nVendorOpts, VendorOptList);
  867. DhcpAssert(ERROR_SUCCESS == Error);
  868. }
  869. ProcId = GetCurrentProcessId();
  870. Error = DhcpApiArgAdd(Buffer, InBufSize, ProcIdParam, sizeof(ProcId), (LPBYTE) &ProcId);
  871. DhcpAssert(ERROR_SUCCESS == Error);
  872. Error = DhcpApiArgAdd(Buffer, InBufSize, DescriptorParam, sizeof(Descriptor), (LPBYTE) &Descriptor);
  873. DhcpAssert(ERROR_SUCCESS == Error);
  874. Error = DhcpApiArgAdd(Buffer, InBufSize, EventHandleParam, sizeof(hEvent), (LPBYTE) &hEvent);
  875. DhcpAssert(ERROR_SUCCESS == Error);
  876. OutBufSize = 0;
  877. Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
  878. DhcpFreeMemory(InBuf);
  879. DhcpAssert(ERROR_MORE_DATA != Error );
  880. return Error;
  881. }
  882. DWORD // Ring 0 handle -- used only on win9x platform
  883. VxDGetDescriptor( // convert Event to Ring0 handle for use in vdhcp.vxd
  884. IN HANDLE Event,
  885. IN OUT LPDWORD pDescriptor
  886. ) {
  887. HANDLE Kernel32;
  888. DWORD (*HandleToRing0Handle)(HANDLE);
  889. DWORD RetVal;
  890. Kernel32 = LoadLibraryA("kernel32.dll");
  891. if( NULL == Kernel32 ) return GetLastError();
  892. HandleToRing0Handle = (DWORD (*)(HANDLE))GetProcAddress(Kernel32, "OpenVxDHandle");
  893. if( NULL == HandleToRing0Handle ) {
  894. CloseHandle(Kernel32);
  895. return GetLastError();
  896. }
  897. (*pDescriptor) = HandleToRing0Handle(Event);
  898. CloseHandle(Kernel32);
  899. if( 0 == (*pDescriptor) ) return ERROR_INVALID_PARAMETER;
  900. return ERROR_SUCCESS;
  901. }
  902. DWORD // win32 status
  903. DhcpCreateApiEventAndDescriptor( // create both the api event handle and the unique descriptor for it
  904. IN OUT LPHANDLE hEvent, // fill this with a valid event handle if succeeded
  905. IN OUT LPDWORD pDescriptor // this descriptor is unique for this process.
  906. ) {
  907. static DWORD Descriptor = 1;// use this for the descriptor
  908. OSVERSIONINFO OsVersion; // need to know if NT or Win95+
  909. BOOL BoolError;
  910. CHAR NameBuf[sizeof("DhcpPid-1-2-3-4-5-6-7-8UniqueId-1-2-3-4-5-6-7-8")];
  911. DWORD Error;
  912. // *** changing NameBuf's format requires change in apiimpl.c NotifyClients...*
  913. OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
  914. BoolError = GetVersionEx(&OsVersion);
  915. if( FALSE == BoolError ) return GetLastError();
  916. if( VER_PLATFORM_WIN32_WINDOWS == OsVersion.dwPlatformId ) {
  917. (*hEvent) = CreateEvent(
  918. NULL, // no security
  919. FALSE, // auto reset
  920. FALSE, // intially signaled? NO
  921. NULL // no name
  922. );
  923. } else {
  924. (*pDescriptor) = InterlockedIncrement(pDescriptor);
  925. sprintf(NameBuf, "DhcpPid%16xUniqueId%16x", GetCurrentProcessId(), *pDescriptor);
  926. (*hEvent) = CreateEventA( // now create the required event
  927. NULL, // no security
  928. FALSE, // automatic reset
  929. FALSE, // intially signalled? NO!
  930. NameBuf // the name to use to create
  931. );
  932. }
  933. if( NULL == (*hEvent) ) return GetLastError();
  934. if( VER_PLATFORM_WIN32_WINDOWS != OsVersion.dwPlatformId )
  935. return ERROR_SUCCESS; // done for NT.
  936. // for Memphis, need to get OpenVxdHandle procedure to get Descriptor value
  937. Error = VxDGetDescriptor(*hEvent, pDescriptor);
  938. if( ERROR_SUCCESS != Error ) {
  939. CloseHandle(*hEvent);
  940. }
  941. return Error;
  942. }
  943. DWORD // win32 status
  944. DhcpRegisterParameterChangeNotification( // notify if a parameter has changed
  945. IN LPWSTR AdapterName, // adapter of interest
  946. IN LPBYTE ClassId, // byte stream of class id to use
  947. IN DWORD ClassIdLen, // # of bytes of class id
  948. IN PDHCPAPI_PARAMS Params, // params of interest
  949. IN DWORD nParams, // # of elts in above array
  950. IN DWORD Flags, // must be zero, reserved
  951. IN OUT PHANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
  952. ) {
  953. DWORD Descriptor; // on NT this is an id unique across this process, on VxD ring0 handle
  954. DWORD Error; //
  955. DWORD i;
  956. if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
  957. if( 0 != ClassIdLen && NULL == ClassId ) return ERROR_INVALID_PARAMETER;
  958. if( 0 == nParams && NULL != Params ) return ERROR_INVALID_PARAMETER;
  959. if( 0 != nParams && NULL == Params ) return ERROR_INVALID_PARAMETER;
  960. if( Flags ) return ERROR_INVALID_PARAMETER;
  961. if( NULL == hEvent ) return ERROR_INVALID_PARAMETER;
  962. for( i = 0; i < nParams ; i ++ ) {
  963. if( Params[i].nBytesData > OPTION_END ) return ERROR_INVALID_PARAMETER;
  964. if( Params[i].nBytesData && NULL == Params[i].Data )
  965. return ERROR_INVALID_PARAMETER;
  966. }
  967. Error = DhcpCreateApiEventAndDescriptor(hEvent, &Descriptor);
  968. if( ERROR_SUCCESS != Error ) return Error;
  969. Error = DhcpRegisterParameterChangeNotificationInternal(
  970. AdapterName,
  971. ClassId,
  972. ClassIdLen,
  973. Params,
  974. nParams,
  975. Flags,
  976. Descriptor,
  977. (*hEvent)
  978. );
  979. if( ERROR_SUCCESS != Error ) {
  980. CloseHandle(*hEvent);
  981. *hEvent = NULL;
  982. return Error;
  983. }
  984. return ERROR_SUCCESS;
  985. }
  986. DhcpDeRegisterParameterChangeNotification( // undo the registration
  987. IN HANDLE Event // handle to event returned by DhcpRegisterParameterChangeNotification, NULL ==> everything
  988. ) {
  989. DWORD Error;
  990. DWORD Descriptor;
  991. DWORD ProcId;
  992. DWORD InBufSize;
  993. DWORD OutBufSize;
  994. LPBYTE InBuf;
  995. LPBYTE Buffer;
  996. InBufSize = 2*sizeof(DWORD); // input/output sizes
  997. InBufSize += sizeof(BYTE) + sizeof(DWORD); // opcode
  998. InBufSize += sizeof(BYTE) + sizeof(DWORD)*2; // proc id
  999. InBufSize += sizeof(BYTE) + sizeof(DWORD)*2; // handle
  1000. InBuf = DhcpAllocateMemory(InBufSize);
  1001. if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  1002. Buffer = InBuf + sizeof(DWORD);
  1003. ((DWORD UNALIGNED*)InBuf)[0] = 0; // nothing expected in return
  1004. ((DWORD UNALIGNED*)Buffer)[0] = 0; // initialize size to zero -- will be increased each time something is added
  1005. Error = DhcpApiFillBuffer(Buffer, InBufSize, NULL, DeRegisterParamsOpCode);
  1006. DhcpAssert(ERROR_SUCCESS == Error);
  1007. ProcId = GetCurrentProcessId();
  1008. Error = DhcpApiArgAdd(Buffer, InBufSize, ProcIdParam, sizeof(ProcId), (LPBYTE)&ProcId);
  1009. DhcpAssert(ERROR_SUCCESS == Error);
  1010. Error = DhcpApiArgAdd(Buffer, InBufSize, EventHandleParam, sizeof(Event), (LPBYTE) &Event);
  1011. DhcpAssert(ERROR_SUCCESS == Error);
  1012. OutBufSize = 0;
  1013. Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
  1014. DhcpFreeMemory(InBuf);
  1015. DhcpAssert(ERROR_MORE_DATA != Error);
  1016. if( ERROR_SUCCESS == Error ) {
  1017. CloseHandle(Event);
  1018. }
  1019. return Error;
  1020. }
  1021. DWORD // win32 status
  1022. DhcpRegistryFillParamsList( // read the registry value and add this list of values to it
  1023. IN LPWSTR AppName, // prefix for key
  1024. IN DWORD nSendParams // # of values to add
  1025. ) {
  1026. HKEY DhcpOptionKey;
  1027. LPWSTR OldValueName;
  1028. LPWSTR NewValueName;
  1029. LPWSTR ValueName;
  1030. LPWSTR Tmp, Tmp2;
  1031. BOOL fOldValueExists = FALSE;
  1032. DWORD ValueNameSize;
  1033. DWORD OldValueNameSize;
  1034. DWORD NewValueNameSize;
  1035. DWORD Error;
  1036. DWORD i;
  1037. Error = RegOpenKeyEx( // open the dhcp option key first
  1038. HKEY_LOCAL_MACHINE,
  1039. DHCP_CLIENT_OPTION_KEY,
  1040. 0 /* Reserved */,
  1041. DHCP_CLIENT_KEY_ACCESS,
  1042. &DhcpOptionKey
  1043. );
  1044. if( ERROR_SUCCESS != Error ) return Error;
  1045. OldValueName = NULL;
  1046. Error = GetRegistryString(
  1047. DhcpOptionKey,
  1048. DHCP_OPTION_LIST_VALUE,
  1049. &OldValueName,
  1050. &OldValueNameSize
  1051. );
  1052. if( ERROR_SUCCESS != Error ) {
  1053. OldValueName = DEFAULT_DHCP_KEYS_LIST_VALUE;
  1054. OldValueNameSize = sizeof(DEFAULT_DHCP_KEYS_LIST_VALUE);
  1055. } else {
  1056. fOldValueExists = TRUE;
  1057. }
  1058. NewValueNameSize = OldValueNameSize;
  1059. ValueNameSize = 0;
  1060. ValueNameSize += wcslen(AppName)*sizeof(WCHAR);
  1061. ValueNameSize += sizeof(L"\\12345");
  1062. ValueName = DhcpAllocateMemory(ValueNameSize);
  1063. if( NULL == ValueName ) {
  1064. RegCloseKey(DhcpOptionKey);
  1065. if( fOldValueExists ) DhcpFreeMemory(OldValueName);
  1066. return ERROR_NOT_ENOUGH_MEMORY;
  1067. }
  1068. NewValueNameSize = nSendParams*ValueNameSize + OldValueNameSize;
  1069. NewValueName = DhcpAllocateMemory(NewValueNameSize);
  1070. if( NULL == NewValueName ) {
  1071. RegCloseKey(DhcpOptionKey);
  1072. if( fOldValueExists ) DhcpFreeMemory(OldValueName);
  1073. DhcpFreeMemory(ValueName);
  1074. return ERROR_NOT_ENOUGH_MEMORY;
  1075. }
  1076. wcscpy(ValueName, AppName);
  1077. wcscat(ValueName, L"\\");
  1078. Tmp = NewValueName;
  1079. for( i = 0; i < nSendParams ; i ++ ) { // for each value, add its to the list
  1080. wcscpy(Tmp, ValueName);
  1081. Tmp += wcslen(Tmp);
  1082. swprintf(Tmp, L"%5x", i);
  1083. Tmp += wcslen(Tmp);
  1084. Tmp ++; // move the ptr off the last L'\0'
  1085. }
  1086. DhcpFreeMemory(ValueName);
  1087. Tmp2 = OldValueName;
  1088. while(wcslen(Tmp2)) {
  1089. wcscpy(Tmp, Tmp2);
  1090. Tmp += wcslen(Tmp2);
  1091. Tmp2 += wcslen(Tmp2);
  1092. Tmp ++;
  1093. Tmp2 ++;
  1094. }
  1095. *Tmp++ = L'\0';
  1096. if(fOldValueExists ) DhcpFreeMemory(OldValueName);
  1097. Error = RegSetValueEx( // write this string back
  1098. DhcpOptionKey,
  1099. DHCP_OPTION_LIST_VALUE,
  1100. 0 /* Reserved */,
  1101. REG_MULTI_SZ,
  1102. (LPBYTE) NewValueName,
  1103. (ULONG)(((LPBYTE)Tmp) - ((LPBYTE)NewValueName))
  1104. );
  1105. DhcpFreeMemory(NewValueName);
  1106. RegCloseKey(DhcpOptionKey);
  1107. if( ERROR_SUCCESS != Error ) {
  1108. DhcpPrint((DEBUG_ERRORS, "RegSetValueEx(OPTION_LIST):0x%lx\n", Error));
  1109. }
  1110. return Error;
  1111. }
  1112. DWORD // win32 status
  1113. DhcpRegistryFillParams( // make a subkey and fill in the details
  1114. IN LPWSTR AdapterName, // NULL ==> global change
  1115. IN LPBYTE ClassId, // this is the class of the option
  1116. IN DWORD ClassIdLen, // # of bytes of above
  1117. IN DWORD i, // key index is 3hex-digit convertion onf this
  1118. IN HKEY Key, // use this key for creating subkeys
  1119. IN PDHCPAPI_PARAMS SendParam, // ptr to structure to use for this one key write operation
  1120. IN LPWSTR AppName // name of app
  1121. ) {
  1122. HKEY SubKey;
  1123. WCHAR KeyName[7]; // key is just 5 bytes
  1124. LPWSTR SendLocation;
  1125. LPWSTR ValueName;
  1126. LPBYTE SendData;
  1127. DWORD SendDataSize;
  1128. DWORD Size;
  1129. DWORD Disposition;
  1130. DWORD Error;
  1131. DWORD OptionId;
  1132. DWORD IsVendor;
  1133. DWORD DummyKeyType;
  1134. swprintf(KeyName, L"%5x", i);
  1135. OptionId = SendParam->OptionId;
  1136. IsVendor = SendParam->IsVendor;
  1137. SendData = SendParam->Data;
  1138. SendDataSize = SendParam->nBytesData;
  1139. Size = wcslen(AppName)*sizeof(WCHAR)+sizeof(KeyName) + sizeof(L"\\");
  1140. if( AdapterName ) {
  1141. Size += (DWORD)(sizeof(DHCP_SERVICES_KEY) + sizeof(DHCP_ADAPTER_PARAMETERS_KEY) + wcslen(AdapterName)*sizeof(WCHAR));
  1142. } else {
  1143. Size += sizeof(DHCP_TCPIP_PARAMETERS_KEY);
  1144. }
  1145. SendLocation = DhcpAllocateMemory(Size);
  1146. if( NULL == SendLocation ) return ERROR_NOT_ENOUGH_MEMORY;
  1147. if( AdapterName ) {
  1148. wcscpy(SendLocation, DHCP_SERVICES_KEY DHCP_ADAPTER_PARAMETERS_KEY);
  1149. wcscat(SendLocation, L"\\?\\");
  1150. } else {
  1151. wcscpy(SendLocation, DHCP_TCPIP_PARAMETERS_KEY);
  1152. }
  1153. wcscat(SendLocation, AppName);
  1154. wcscat(SendLocation, KeyName);
  1155. Error = RegCreateKeyEx( // create the option key
  1156. Key,
  1157. KeyName,
  1158. 0 /* Reserved */,
  1159. DHCP_CLASS,
  1160. REG_OPTION_NON_VOLATILE,
  1161. KEY_ALL_ACCESS,
  1162. NULL,
  1163. &SubKey,
  1164. &Disposition
  1165. );
  1166. if( ERROR_SUCCESS != Error ) {
  1167. DhcpFreeMemory(SendLocation);
  1168. return Error;
  1169. }
  1170. DhcpAssert(REG_CREATED_NEW_KEY == Disposition);
  1171. Error = RegSetValueEx( // now create each of the values -- OPTION ID
  1172. SubKey,
  1173. DHCP_OPTION_OPTIONID_VALUE,
  1174. 0 /* Reserved */,
  1175. DHCP_OPTION_OPTIONID_TYPE,
  1176. (LPBYTE)&OptionId,
  1177. sizeof(OptionId)
  1178. );
  1179. DhcpAssert(ERROR_SUCCESS == Error);
  1180. Error = RegSetValueEx( // IS VENDOR
  1181. SubKey,
  1182. DHCP_OPTION_ISVENDOR_VALUE,
  1183. 0 /* Reserved */,
  1184. DHCP_OPTION_ISVENDOR_TYPE,
  1185. (LPBYTE) (&IsVendor),
  1186. sizeof(IsVendor)
  1187. );
  1188. DhcpAssert(ERROR_SUCCESS == Error);
  1189. if( ClassIdLen ) {
  1190. Error = RegSetValueEx( // CLASS ID
  1191. SubKey,
  1192. DHCP_OPTION_CLASSID_VALUE,
  1193. 0 /* Reserved */,
  1194. REG_BINARY,
  1195. ClassId,
  1196. ClassIdLen
  1197. );
  1198. DhcpAssert(ERROR_SUCCESS == Error);
  1199. }
  1200. Error = RegSetValueEx(
  1201. SubKey,
  1202. DHCP_OPTION_SEND_LOCATION_VALUE,
  1203. 0 /* Reserved */,
  1204. REG_SZ,
  1205. (LPBYTE)SendLocation,
  1206. (wcslen(SendLocation)+1)*sizeof(WCHAR)
  1207. );
  1208. DhcpAssert(ERROR_SUCCESS == Error);
  1209. DummyKeyType = REG_DWORD; // KeyType
  1210. Error = RegSetValueEx(
  1211. SubKey,
  1212. DHCP_OPTION_SAVE_TYPE_VALUE,
  1213. 0 /* Reserved */,
  1214. DHCP_OPTION_SAVE_TYPE_TYPE,
  1215. (LPBYTE)&DummyKeyType,
  1216. sizeof(DummyKeyType));
  1217. DhcpAssert(ERROR_SUCCESS == Error);
  1218. RegCloseKey(SubKey);
  1219. if( AdapterName ) {
  1220. wcscpy(SendLocation, DHCP_SERVICES_KEY DHCP_ADAPTER_PARAMETERS_KEY);
  1221. wcscat(SendLocation, L"\\");
  1222. wcscat(SendLocation, AdapterName);
  1223. } else {
  1224. wcscpy(SendLocation, DHCP_TCPIP_PARAMETERS_KEY);
  1225. }
  1226. ValueName = wcslen(SendLocation) + 1 + SendLocation;
  1227. wcscpy(ValueName, AppName);
  1228. wcscat(ValueName, KeyName);
  1229. Error = RegOpenKeyEx(
  1230. HKEY_LOCAL_MACHINE,
  1231. SendLocation,
  1232. 0 /* Reserved */,
  1233. KEY_ALL_ACCESS,
  1234. &SubKey
  1235. );
  1236. if( ERROR_SUCCESS != Error ) {
  1237. DhcpFreeMemory(SendLocation);
  1238. return Error;
  1239. }
  1240. Error = RegSetValueEx(
  1241. SubKey,
  1242. ValueName,
  1243. 0 /* Reserved */,
  1244. REG_BINARY,
  1245. SendData,
  1246. SendDataSize
  1247. );
  1248. DhcpAssert(ERROR_SUCCESS == Error);
  1249. RegCloseKey(SubKey);
  1250. DhcpFreeMemory(SendLocation);
  1251. return ERROR_SUCCESS;
  1252. }
  1253. DWORD // win32 status
  1254. DhcpRegistryCreateUniqueKey( // create a unique key with prefix AppName
  1255. IN LPWSTR AppName, // some App descriptor
  1256. IN OUT HKEY* Key // return the opened key here
  1257. ) {
  1258. DWORD FullKeyNameSize, Disposition;
  1259. DWORD Error;
  1260. LPWSTR FullKeyName;
  1261. FullKeyNameSize = sizeof(DHCP_CLIENT_OPTION_KEY);
  1262. FullKeyNameSize += wcslen(AppName)*sizeof(WCHAR) + sizeof(WCHAR);
  1263. FullKeyName = DhcpAllocateMemory(FullKeyNameSize);
  1264. if( NULL == FullKeyName ) return ERROR_NOT_ENOUGH_MEMORY;
  1265. wcscpy(FullKeyName, DHCP_CLIENT_OPTION_KEY);
  1266. wcscat(FullKeyName, L"\\");
  1267. wcscat(FullKeyName, AppName);
  1268. Error = RegCreateKeyEx(
  1269. HKEY_LOCAL_MACHINE,
  1270. FullKeyName,
  1271. 0 /* Reserved */,
  1272. DHCP_CLASS,
  1273. REG_OPTION_NON_VOLATILE,
  1274. KEY_ALL_ACCESS,
  1275. NULL,
  1276. Key,
  1277. &Disposition
  1278. );
  1279. DhcpFreeMemory(FullKeyName);
  1280. if( ERROR_SUCCESS != Error ) return Error;
  1281. if( REG_OPENED_EXISTING_KEY == Disposition ) {
  1282. RegCloseKey(*Key);
  1283. return ERROR_ALREADY_EXISTS;
  1284. }
  1285. return ERROR_SUCCESS;
  1286. }
  1287. DWORD // win32 status
  1288. DhcpRegistryPersistentRequestParams( // edit registry to consider this additional persistent request
  1289. IN LPWSTR AdapterName, // which adapter is this request for?
  1290. IN LPBYTE ClassId, // class
  1291. IN DWORD ClassIdLen, // # of bytes in class id
  1292. IN PDHCPAPI_PARAMS SendParams, // the actual parameters to fill up
  1293. IN DWORD nSendParams, // the size of the above array
  1294. IN PDHCPAPI_PARAMS RecdParams, // would like to receive these
  1295. IN DWORD nRecdParams, // count..
  1296. IN LPWSTR AppName // some thing unique about the app that wants to do registrations
  1297. ) {
  1298. HKEY Key;
  1299. DWORD i;
  1300. DWORD Error;
  1301. DWORD LastError;
  1302. DHCPAPI_PARAMS NonVendorParams;
  1303. ULONG nVendorOpt, nNonVendorOpt;
  1304. CHAR Buf[256];
  1305. if( NULL == AppName ) return ERROR_INVALID_PARAMETER;
  1306. if( 0 == nSendParams && NULL != SendParams ) return ERROR_INVALID_PARAMETER;
  1307. if( 0 != nSendParams && NULL == SendParams ) return ERROR_INVALID_PARAMETER;
  1308. if( 0 != nRecdParams && NULL == RecdParams ) return ERROR_INVALID_PARAMETER;
  1309. if( 0 == nRecdParams && NULL != RecdParams ) return ERROR_INVALID_PARAMETER;
  1310. if( ClassIdLen && NULL == ClassId || 0 == ClassIdLen && NULL != ClassId)
  1311. return ERROR_INVALID_PARAMETER;
  1312. for( i = 0; i < nSendParams; i ++ ) {
  1313. if( SendParams[i].nBytesData == 0 ) return ERROR_INVALID_PARAMETER;
  1314. }
  1315. nVendorOpt = nNonVendorOpt = 0;
  1316. // --ft: 07/25/00 fixes the way the non-vendor options
  1317. // are collected from RecdParams.
  1318. for (i = 0; i < nRecdParams; i++)
  1319. {
  1320. if (RecdParams[i].IsVendor)
  1321. {
  1322. nVendorOpt = 1;
  1323. }
  1324. else
  1325. {
  1326. Buf[nNonVendorOpt++] = (BYTE)RecdParams[i].OptionId;
  1327. }
  1328. }
  1329. // if nVendorOpt is 1 this means we have at least one vendor option in
  1330. // the requested parameters list. Make sure then OPTION_VENDOR_SPEC_INFO
  1331. // is mentioned in the array to be sent as OPTION_PARAMETER_REQUEST_LIST
  1332. if( nVendorOpt ) {
  1333. for( i = 0; i < nNonVendorOpt ; i ++ )
  1334. if( Buf[i] == OPTION_VENDOR_SPEC_INFO )
  1335. break;
  1336. if( i == nNonVendorOpt ) Buf[nNonVendorOpt ++] = (BYTE)OPTION_VENDOR_SPEC_INFO;
  1337. }
  1338. NonVendorParams.Flags = 0;
  1339. NonVendorParams.OptionId = OPTION_PARAMETER_REQUEST_LIST;
  1340. NonVendorParams.IsVendor = FALSE;
  1341. NonVendorParams.Data = Buf;
  1342. NonVendorParams.nBytesData = nNonVendorOpt;
  1343. Error = DhcpRegistryCreateUniqueKey( // first try creating the key
  1344. AppName,
  1345. &Key
  1346. );
  1347. if( ERROR_SUCCESS != Error ) return Error;
  1348. Error = DhcpRegistryFillParamsList(
  1349. AppName,
  1350. nSendParams + (nNonVendorOpt?1:0)
  1351. );
  1352. if( ERROR_SUCCESS != Error ) {
  1353. DhcpAssert(FALSE);
  1354. DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParamsList:0x%lx\n", Error));
  1355. RegCloseKey(Key);
  1356. return Error;
  1357. }
  1358. LastError = ERROR_SUCCESS;
  1359. for( i = 0; i < nSendParams; i ++ ) { // now enter the particular option in the registry
  1360. Error = DhcpRegistryFillParams(
  1361. AdapterName,
  1362. ClassId,
  1363. ClassIdLen,
  1364. i,
  1365. Key,
  1366. &SendParams[i],
  1367. AppName
  1368. );
  1369. if( ERROR_SUCCESS != Error ) {
  1370. DhcpAssert(FALSE);
  1371. DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParams:0x%lx\n", Error));
  1372. LastError = Error;
  1373. }
  1374. }
  1375. if( nNonVendorOpt ) {
  1376. Error = DhcpRegistryFillParams(
  1377. AdapterName,
  1378. ClassId,
  1379. ClassIdLen,
  1380. i ++,
  1381. Key,
  1382. &NonVendorParams,
  1383. AppName
  1384. );
  1385. if( ERROR_SUCCESS != Error ) {
  1386. DhcpAssert(FALSE);
  1387. DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParams:0x%lx\n", Error));
  1388. LastError = Error;
  1389. }
  1390. }
  1391. RegCloseKey(Key);
  1392. return LastError;
  1393. }
  1394. // Please note that AppName must be unique for each request (and if it is not, things are
  1395. // likely to behave weirdly.. This is the same name that should be used for the deletion..
  1396. DWORD // win32 status
  1397. DhcpPersistentRequestParams( // parameters to request persistently
  1398. IN LPWSTR AdapterName, // adapter name to request for
  1399. IN LPBYTE ClassId, // byte stream of class id to use
  1400. IN DWORD ClassIdLen, // # of bytes of class id
  1401. IN PDHCPAPI_PARAMS SendParams, // persistent parameters
  1402. IN DWORD nSendParams, // size of above array
  1403. IN DWORD Flags, // must be zero, reserved
  1404. IN LPWSTR AppName // name of app doing the persistent request
  1405. ) {
  1406. DWORD Error;
  1407. DWORD nRecdParams;
  1408. nRecdParams = 0;
  1409. Error = DhcpRequestParamsInternal(
  1410. PersistentRequestParamsOpCode,
  1411. AdapterName,
  1412. ClassId,
  1413. ClassIdLen,
  1414. SendParams,
  1415. nSendParams,
  1416. Flags,
  1417. NULL,
  1418. &nRecdParams
  1419. );
  1420. DhcpAssert(ERROR_MORE_DATA != Error );
  1421. if( ERROR_INVALID_PARAMETER == Error ) Error = ERROR_SUCCESS; // see below comment
  1422. if( ERROR_SUCCESS != Error ) { // if AdapterName is NULL or if ClassId is not the one currently in use
  1423. return Error; // only then do we get ERROR_INVALID_PARAMETER -- so filter those out
  1424. }
  1425. return DhcpRegistryPersistentRequestParams( // now munge the registry
  1426. AdapterName,
  1427. ClassId,
  1428. ClassIdLen,
  1429. SendParams,
  1430. nSendParams,
  1431. NULL,
  1432. 0,
  1433. AppName
  1434. );
  1435. }
  1436. DWORD // win32 status
  1437. DhcpDelPersistentRequestParams( // undo the effect of a persistent request -- currently undo from registry
  1438. IN LPWSTR AdapterName, // the name of the adpater to delete for
  1439. IN LPWSTR AppName // the name used by the app
  1440. ) {
  1441. HKEY Key;
  1442. DWORD Error;
  1443. DWORD LocationSize;
  1444. DWORD FullKeyNameSize, Disposition;
  1445. LPWSTR FullKeyName;
  1446. LPWSTR LocationValue;
  1447. LPWSTR Tmp, Tmp2;
  1448. FullKeyNameSize = sizeof(DHCP_CLIENT_OPTION_KEY);
  1449. FullKeyNameSize += wcslen(AppName)*sizeof(WCHAR) + sizeof(WCHAR);
  1450. FullKeyName = DhcpAllocateMemory(FullKeyNameSize);
  1451. if( NULL == FullKeyName ) return ERROR_NOT_ENOUGH_MEMORY;
  1452. wcscpy(FullKeyName, DHCP_CLIENT_OPTION_KEY);
  1453. wcscat(FullKeyName, L"\\");
  1454. wcscat(FullKeyName, AppName);
  1455. Error = DhcpRegRecurseDelete(HKEY_LOCAL_MACHINE, FullKeyName);
  1456. DhcpAssert(ERROR_SUCCESS == Error);
  1457. DhcpFreeMemory(FullKeyName);
  1458. Error = RegOpenKeyEx(
  1459. HKEY_LOCAL_MACHINE,
  1460. DHCP_CLIENT_OPTION_KEY,
  1461. 0 /* Reserved */,
  1462. DHCP_CLIENT_KEY_ACCESS,
  1463. &Key
  1464. );
  1465. if( ERROR_SUCCESS != Error ) {
  1466. DhcpAssert(FALSE);
  1467. return Error;
  1468. } else {
  1469. DhcpRegRecurseDelete(Key, AppName);
  1470. }
  1471. LocationValue = NULL;
  1472. Error = GetRegistryString( // read the value
  1473. Key,
  1474. DHCP_OPTION_LIST_VALUE,
  1475. &LocationValue,
  1476. &LocationSize
  1477. );
  1478. if( LocationValue == NULL ) Error = ERROR_FILE_NOT_FOUND;
  1479. if( ERROR_SUCCESS != Error ) {
  1480. RegCloseKey(Key);
  1481. return Error;
  1482. }
  1483. Tmp = Tmp2 = LocationValue;
  1484. while(wcslen(Tmp) ) {
  1485. if( 0 != wcsncmp(AppName, Tmp, wcslen(AppName))) {
  1486. wcscpy(Tmp2, Tmp);
  1487. Tmp2 += wcslen(Tmp) +1;
  1488. Tmp += wcslen(Tmp) +1;
  1489. continue;
  1490. }
  1491. if( Tmp[wcslen(AppName)] != L'\\' ) {
  1492. wcscpy(Tmp2, Tmp);
  1493. Tmp2 += wcslen(Tmp) +1;
  1494. Tmp += wcslen(Tmp) +1;
  1495. continue;
  1496. }
  1497. //
  1498. // found required entry.. just skip over it..
  1499. //
  1500. Tmp += wcslen(Tmp) +1;
  1501. }
  1502. *Tmp2 ++ = L'\0';
  1503. Error = RegSetValueEx(
  1504. Key,
  1505. DHCP_OPTION_LIST_VALUE,
  1506. 0 /* Reserved */,
  1507. REG_MULTI_SZ,
  1508. (LPBYTE)LocationValue,
  1509. (ULONG)(((LPBYTE)Tmp2 - (LPBYTE)LocationValue))
  1510. );
  1511. RegCloseKey(Key);
  1512. DhcpFreeMemory(LocationValue);
  1513. return Error;
  1514. }
  1515. BOOL _inline
  1516. CharInMem(
  1517. IN BYTE Byte,
  1518. IN LPBYTE Mem,
  1519. IN ULONG MemSz
  1520. )
  1521. {
  1522. while(MemSz) {
  1523. if( Byte == *Mem ) return TRUE;
  1524. Mem ++; MemSz --;
  1525. }
  1526. return FALSE;
  1527. }
  1528. DWORD
  1529. APIENTRY
  1530. DhcpRegisterOptions(
  1531. IN LPWSTR AdapterName,
  1532. IN LPBYTE OptionList,
  1533. IN DWORD OptionListSz,
  1534. IN HANDLE *pdwHandle
  1535. ) {
  1536. DHCPAPI_PARAMS DhcpParams;
  1537. DWORD Error;
  1538. DHCP_OPTION DummyOption;
  1539. LPBYTE Value;
  1540. DWORD ValueSize, ValueType;
  1541. BYTE Buf[256];
  1542. ULONG nElementsInBuf;
  1543. DhcpParams.OptionId = OPTION_PARAMETER_REQUEST_LIST;
  1544. DhcpParams.IsVendor = FALSE;
  1545. DhcpParams.Data = OptionList;
  1546. DhcpParams.nBytesData = OptionListSz;
  1547. Error = DhcpRegisterParameterChangeNotification(
  1548. AdapterName,
  1549. NULL,
  1550. 0,
  1551. &DhcpParams,
  1552. 1,
  1553. 0,
  1554. pdwHandle
  1555. );
  1556. if( ERROR_SUCCESS != Error ) return Error;
  1557. memset(&DummyOption, 0, sizeof(DummyOption));
  1558. Value = NULL; ValueSize = 0;
  1559. Error = DhcpRegReadFromAnyLocation(
  1560. DHCP_REGISTER_OPTIONS_LOC,
  1561. AdapterName,
  1562. &Value,
  1563. &ValueType,
  1564. &ValueSize
  1565. );
  1566. if( ERROR_SUCCESS == Error && REG_BINARY == ValueType && 0 != ValueSize ) {
  1567. //
  1568. // Got some pre-existing values... add the remaining to it..
  1569. //
  1570. memcpy(Buf, Value, ValueSize);
  1571. while(OptionListSz) {
  1572. if( !CharInMem(*OptionList, Value, ValueSize) )
  1573. Buf[ValueSize++] = *OptionList;
  1574. OptionList ++; OptionListSz --;
  1575. }
  1576. OptionList = Buf;
  1577. OptionListSz = ValueSize;
  1578. }
  1579. if( NULL != Value ) DhcpFreeMemory(Value);
  1580. DummyOption.Data = OptionList;
  1581. DummyOption.DataLen = OptionListSz;
  1582. Error = DhcpRegSaveOptionAtLocationEx(
  1583. &DummyOption,
  1584. AdapterName,
  1585. DHCP_REGISTER_OPTIONS_LOC,
  1586. REG_BINARY
  1587. );
  1588. return Error;
  1589. }
  1590. DWORD
  1591. APIENTRY
  1592. DhcpDeRegisterOptions (
  1593. IN HANDLE OpenHandle
  1594. ) {
  1595. DWORD Error;
  1596. Error = DhcpDeRegisterParameterChangeNotification(OpenHandle);
  1597. if( ERROR_SUCCESS != Error ) return Error;
  1598. //
  1599. // can't undo registry as we don't have enough information to do that.
  1600. //
  1601. return Error;
  1602. }
  1603. //================================================================================
  1604. // C L I E N T A P I E N T R Y P O I N T S
  1605. //================================================================================
  1606. DWORD
  1607. APIENTRY
  1608. DhcpCApiInitialize(
  1609. OUT LPDWORD Version
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. This routine intializes all the DHCP Client side APIs
  1614. Arguemnts:
  1615. Version - a pointer to a DWORD that gets filled with DHCP APIs version #.
  1616. Return Value:
  1617. Returns STatus.
  1618. --*/
  1619. {
  1620. if( NULL != Version ) *Version = 2;
  1621. return ERROR_SUCCESS;
  1622. }
  1623. VOID
  1624. APIENTRY
  1625. DhcpCApiCleanup(
  1626. VOID
  1627. )
  1628. /*++
  1629. Routine Description:
  1630. This routine cleansup afterall the DHCP Client side APIs have been called.
  1631. --*/
  1632. {
  1633. return ;
  1634. }
  1635. DWORD // win32 status
  1636. APIENTRY
  1637. DhcpRequestParams( // request parameters of client
  1638. IN DWORD Flags, // must be DHCPCAPI_REQUEST_SYNCHRONOUS
  1639. IN LPVOID Reserved, // this parameter is reserved
  1640. IN LPWSTR AdapterName, // adapter name to request for
  1641. IN LPDHCPCAPI_CLASSID ClassId, // reserved must be NULL
  1642. IN DHCPCAPI_PARAMS_ARRAY SendParams, // parameters to send.
  1643. IN OUT DHCPCAPI_PARAMS_ARRAY RecdParams, // parameters that are to be requested..
  1644. IN LPBYTE Buffer, // a buffer to hold data for RecdParams
  1645. IN OUT LPDWORD pSize, // i/p: size of above in BYTES, o/p required bytes..
  1646. IN LPWSTR RequestIdStr // name of the application, unique per request
  1647. ) // returns ERROR_MORE_DATA if o/p buffer is of insufficient size, and fills in reqd size in # of bytes
  1648. /*++
  1649. Routine Description:
  1650. This routine can be used to do Request options from the DHCP Server and based on
  1651. whether then whether the request is permanent or not, this request would be stored
  1652. in the registry for persistence across boots. The requests can have a particular class
  1653. for which they'd be defined... (the class is sent on wire for the server to decide
  1654. which options to send). The request could be ASYNCHRONOUS in the sense that the call
  1655. returns even before the server returns the data.. But this is not yet implemented.
  1656. Arugments:
  1657. Flags - currently DHCPCAPI_REQUEST_SYNCHRONOUS must be defined.
  1658. if a persisten request is desired, DHCPCAPI_REQUEST_PERSISTENT can
  1659. also be passed (bit-wise OR'ed)
  1660. Reserved - MUST be NULL. Reserved for future USE.
  1661. AdapterName - The Name of the adapter for which this request is designed. This
  1662. cannot be NULL currently though it is a nice thing to implement for
  1663. future.
  1664. ClassId - The binary ClassId information to use to send on wire.
  1665. SendParams - The Parameters to actual send on wire.
  1666. RecdParams - The parameters to be received back from the DHCP server
  1667. Buffer - A buffer to hold some information. This cannot be NULL and some
  1668. pointers within the RecdParams structure use this buffer, so it cannot
  1669. be deallocated so long as the RecdParams array is in USE.
  1670. pSize - This is (on input) the size in bytes of the Buffer variable. When
  1671. the function returns ERROR_MORE_DATA, this variable would be the size
  1672. in bytes required. If the function returns SUCCESSFULLY, this would
  1673. be the number of bytes space used up in reality.
  1674. RequestIdStr - a string identifying the request being made. This has to be unique
  1675. to each request (and a Guid is suggested). This string is needed to
  1676. undo the effects of a RequestParam via UndoRequestParams..
  1677. Return Value:
  1678. This function returns ERROR_MORE_DATA if the buffer space provided by "Buffer" variable
  1679. is not sufficient. (In this case, the pSize variable is filled in with the actual
  1680. size required). On success it returns ERROR_SUCCESS. Otherwise, it returns Win32
  1681. status.
  1682. --*/
  1683. {
  1684. ULONG Error;
  1685. ULONG i;
  1686. //
  1687. // Parameter validation
  1688. //
  1689. if( Flags != DHCPCAPI_REQUEST_SYNCHRONOUS &&
  1690. Flags != DHCPCAPI_REQUEST_PERSISTENT &&
  1691. Flags != (DHCPCAPI_REQUEST_SYNCHRONOUS | DHCPCAPI_REQUEST_PERSISTENT)) {
  1692. return ERROR_INVALID_PARAMETER;
  1693. }
  1694. if( NULL != Reserved || NULL == AdapterName ||
  1695. 0 == RecdParams.nParams || NULL == pSize ) {
  1696. return ERROR_INVALID_PARAMETER;
  1697. }
  1698. if( NULL == Buffer && *pSize ) {
  1699. return ERROR_INVALID_PARAMETER;
  1700. }
  1701. if( NULL != ClassId ) {
  1702. if( 0 != ClassId->Flags ) return ERROR_INVALID_PARAMETER;
  1703. if( NULL == ClassId->Data || 0 == ClassId->nBytesData ) {
  1704. return ERROR_INVALID_PARAMETER;
  1705. }
  1706. }
  1707. if( NULL == RecdParams.Params || (0 != SendParams.nParams && NULL == SendParams.Params) ) {
  1708. return ERROR_INVALID_PARAMETER;
  1709. }
  1710. for( i = 0; i < RecdParams.nParams ; i ++ ) {
  1711. if( 0 != RecdParams.Params[i].nBytesData ||
  1712. NULL != RecdParams.Params[i].Data ) {
  1713. return ERROR_INVALID_PARAMETER;
  1714. }
  1715. }
  1716. //
  1717. // Now call the DhcpRequestParameters API and do datatype conversions for that..
  1718. //
  1719. Error = ERROR_SUCCESS;
  1720. if( Flags & DHCPCAPI_REQUEST_SYNCHRONOUS ) {
  1721. Error = DhcpRequestParamsInternalEx(
  1722. RequestParamsOpCode,
  1723. AdapterName,
  1724. ClassId? ClassId->Data : NULL,
  1725. ClassId? ClassId->nBytesData : 0,
  1726. SendParams.Params,
  1727. SendParams.nParams,
  1728. 0,
  1729. RecdParams.Params,
  1730. &RecdParams.nParams,
  1731. Buffer,
  1732. pSize
  1733. );
  1734. }
  1735. if( ERROR_SUCCESS != Error ) return Error;
  1736. if( Flags & DHCPCAPI_REQUEST_PERSISTENT ) {
  1737. Error = DhcpRegistryPersistentRequestParams(
  1738. AdapterName,
  1739. ClassId? ClassId->Data : NULL,
  1740. ClassId? ClassId->nBytesData : 0,
  1741. SendParams.Params,
  1742. SendParams.nParams,
  1743. RecdParams.Params,
  1744. RecdParams.nParams,
  1745. RequestIdStr
  1746. );
  1747. }
  1748. return Error;
  1749. }
  1750. DWORD // win32 status
  1751. APIENTRY
  1752. DhcpUndoRequestParams( // undo the effect of a persistent request -- currently undo from registry
  1753. IN DWORD Flags, // must be zero, reserved
  1754. IN LPVOID Reserved, // this parameter is reserved
  1755. IN LPWSTR AdapterName, // the original adapter this was registerdd for,..
  1756. IN LPWSTR RequestIdStr // the requestId str passed to RequestParams..
  1757. )
  1758. /*++
  1759. Routine Description:
  1760. This function is used to undo the effects of a persistent request done
  1761. via DhcpRequestParams with DHCPCAPI_REQUEST_PERSISTENT option.
  1762. Arguments:
  1763. Flags - MUST be zero. Reserved for future use.
  1764. Reserved - MUST be NULL
  1765. AdapterName - The original adapter name this request was made for
  1766. RequestIdStr - The original request Id string passed to RequestParams
  1767. Return Value:
  1768. returns Win32 status
  1769. --*/
  1770. {
  1771. if( 0 != Flags || NULL != Reserved || NULL == RequestIdStr )
  1772. return ERROR_INVALID_PARAMETER;
  1773. return DhcpDelPersistentRequestParams(
  1774. AdapterName,
  1775. RequestIdStr
  1776. );
  1777. }
  1778. DWORD // win32 status
  1779. APIENTRY
  1780. DhcpRegisterParamChange( // notify if a parameter has changed
  1781. IN DWORD Flags, // must be DHCPCAPI_REGISTER_HANDLE_EVENT
  1782. IN LPVOID Reserved, // this parameter is reserved
  1783. IN LPWSTR AdapterName, // adapter of interest
  1784. IN LPDHCPCAPI_CLASSID ClassId, // reserved must be NULL
  1785. IN DHCPCAPI_PARAMS_ARRAY Params, // parameters of interest
  1786. IN OUT LPVOID Handle // handle to event that will be SetEvent'ed in case of param change
  1787. )
  1788. /*++
  1789. Routine Description;
  1790. This function registers with DHCP for any notifications on changes to the
  1791. specified options.. (notifications are via an EVENT handle)
  1792. Arguments:
  1793. Flags - this decides how the notification works -- via EVENTS or otherwise.
  1794. Currently, only event based mechanism is provided. So, this must be
  1795. DHCPCAPI_REGISTER_HANDLE_EVENT. In this case, Handle must also
  1796. be the address of a handle variable. (This is not the event handle
  1797. itself, the event handle is returned in this address).
  1798. Reserved - MUST be NULL.
  1799. AdapterName - MUST NOT BE NULL. This is the name of the adapter for which the
  1800. notification is being registered..
  1801. ClassId - This specifies the classId if any for which the registration is.
  1802. Params - This is the set of parameter to listen on and notify of when any
  1803. change happens..
  1804. Handle - See "Flags" for what this variable is.
  1805. Return values:
  1806. returns Win32 status codes
  1807. --*/
  1808. {
  1809. DWORD Error;
  1810. CHAR Buf[256]; // cannot request more options than this!
  1811. CHAR VBuf[256];
  1812. DHCPAPI_PARAMS Param[2], *pReqParams;
  1813. ULONG i;
  1814. DWORD nOpt, nVOpt;
  1815. if( Flags != DHCPCAPI_REGISTER_HANDLE_EVENT ) {
  1816. return ERROR_INVALID_PARAMETER;
  1817. }
  1818. if( NULL != Reserved || NULL == AdapterName || 0 == Params.nParams || NULL == Handle ) {
  1819. return ERROR_INVALID_PARAMETER;
  1820. }
  1821. nOpt = nVOpt = 0;
  1822. for( i = 0; i < Params.nParams ; i ++ ) {
  1823. if( Params.Params[i].IsVendor ) {
  1824. VBuf[nVOpt++] = (BYTE)Params.Params[i].OptionId;
  1825. } else {
  1826. Buf[nOpt++] = (BYTE)Params.Params[i].OptionId;
  1827. }
  1828. }
  1829. Param[0].OptionId = OPTION_PARAMETER_REQUEST_LIST;
  1830. Param[0].IsVendor = FALSE;
  1831. Param[0].Data = Buf;
  1832. Param[0].nBytesData = nOpt;
  1833. Param[1].OptionId = OPTION_PAD;
  1834. Param[1].IsVendor = TRUE;
  1835. Param[1].Data = VBuf;
  1836. Param[1].nBytesData = nVOpt;
  1837. if( 0 == nOpt ) pReqParams = &Param[1]; else pReqParams = &Param[0];
  1838. return DhcpRegisterParameterChangeNotification(
  1839. AdapterName,
  1840. ClassId? ClassId->Data : NULL,
  1841. ClassId? ClassId->nBytesData : 0,
  1842. pReqParams,
  1843. (nOpt != 0) + (nVOpt != 0),
  1844. 0,
  1845. Handle
  1846. );
  1847. }
  1848. DWORD
  1849. APIENTRY
  1850. DhcpDeRegisterParamChange( // undo the registration
  1851. IN DWORD Flags, // MUST BE ZERO --> No flags yet.
  1852. IN LPVOID Reserved, // MUST BE NULL --> Reserved
  1853. IN LPVOID Event // handle to event returned by DhcpRegisterParamChange.
  1854. )
  1855. /*++
  1856. Routine description:
  1857. This routine undoes whateve was done by previous routine, and closes the
  1858. handle also. The handle cannot be used after this.
  1859. Arguments:
  1860. Flags - MUST BE DHCPCAPI_REGISTER_HANDLE_EVENT currently.
  1861. Reserved - MuST BE NULL
  1862. Event - this is the event handle returned in the "Handle" parameter to
  1863. DhcpRegisterParamChange function.
  1864. Return Value:
  1865. Win32 status
  1866. --*/
  1867. {
  1868. return DhcpDeRegisterParameterChangeNotification(Event);
  1869. }
  1870. DWORD
  1871. APIENTRY
  1872. DhcpRemoveDNSRegistrations(
  1873. VOID
  1874. )
  1875. {
  1876. return DhcpAdapterOnlyApi(NULL, RemoveDNSRegistrationsOpCode);
  1877. }
  1878. //================================================================================
  1879. // end of file
  1880. //================================================================================
  1881. #endif H_ONLY