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.

834 lines
17 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcp.c
  5. Abstract:
  6. This module contains DHCP specific utility routines used by the
  7. DHCP components.
  8. Author:
  9. Manny Weiser (mannyw) 12-Aug-1992
  10. Revision History:
  11. Madan Appiah (madana) 21-Oct-1992
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <dhcpl.h>
  17. DWORD
  18. NTTimeToNTPTime(PULONG pTime,
  19. PFILETIME pft OPTIONAL);
  20. DWORD
  21. NTPTimeToNTFileTime(PLONG pTime, PFILETIME pft, BOOL bHostOrder);
  22. #undef DhcpAllocateMemory
  23. #undef DhcpFreeMemory
  24. PVOID
  25. DhcpAllocateMemory(
  26. DWORD Size
  27. )
  28. /*++
  29. Routine Description:
  30. This function allocates the required size of memory by calling
  31. LocalAlloc.
  32. Arguments:
  33. Size - size of the memory block required.
  34. Return Value:
  35. Pointer to the allocated block.
  36. --*/
  37. {
  38. ASSERT( Size != 0 );
  39. return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) );
  40. }
  41. #undef DhcpFreeMemory
  42. VOID
  43. DhcpFreeMemory(
  44. PVOID Memory
  45. )
  46. /*++
  47. Routine Description:
  48. This function frees up the memory that was allocated by
  49. DhcpAllocateMemory.
  50. Arguments:
  51. Memory - pointer to the memory block that needs to be freed up.
  52. Return Value:
  53. none.
  54. --*/
  55. {
  56. LPVOID Ptr;
  57. ASSERT( Memory != NULL );
  58. Ptr = LocalFree( Memory );
  59. ASSERT( Ptr == NULL );
  60. }
  61. DATE_TIME
  62. DhcpCalculateTime(
  63. DWORD RelativeTime
  64. )
  65. /*++
  66. Routine Description:
  67. The function calculates the absolute time of a time RelativeTime
  68. seconds from now.
  69. Arguments:
  70. RelativeTime - Relative time, in seconds.
  71. Return Value:
  72. The time in RelativeTime seconds from the current system time.
  73. --*/
  74. {
  75. SYSTEMTIME systemTime;
  76. ULONGLONG absoluteTime;
  77. if( RelativeTime == INFINIT_LEASE ) {
  78. ((DATE_TIME *)&absoluteTime)->dwLowDateTime =
  79. DHCP_DATE_TIME_INFINIT_LOW;
  80. ((DATE_TIME *)&absoluteTime)->dwHighDateTime =
  81. DHCP_DATE_TIME_INFINIT_HIGH;
  82. }
  83. else {
  84. GetSystemTime( &systemTime );
  85. SystemTimeToFileTime(
  86. &systemTime,
  87. (FILETIME *)&absoluteTime );
  88. absoluteTime = absoluteTime + RelativeTime * (ULONGLONG)10000000; }
  89. return( *(DATE_TIME *)&absoluteTime );
  90. }
  91. DATE_TIME
  92. DhcpGetDateTime(
  93. VOID
  94. )
  95. /*++
  96. Routine Description:
  97. This function returns FILETIME.
  98. Arguments:
  99. none.
  100. Return Value:
  101. FILETIME.
  102. --*/
  103. {
  104. SYSTEMTIME systemTime;
  105. DATE_TIME Time;
  106. GetSystemTime( &systemTime );
  107. SystemTimeToFileTime( &systemTime, (FILETIME *)&Time );
  108. return( Time );
  109. }
  110. VOID
  111. DhcpNTToNTPTime(
  112. LPDATE_TIME AbsNTTime,
  113. DWORD Offset,
  114. PULONG NTPTimeStamp
  115. )
  116. /*++
  117. Routine Description:
  118. The function calculates the absolute NTP timestamp from AbsTime on
  119. NT added by given offset.
  120. Arguments:
  121. AbsNTTime - AbsTime on NT. If 0, it will use current time.
  122. RelativeOffset - offset to be added to AnsNTTime (in seconds.)
  123. Return Value:
  124. The time in RelativeTime seconds from the current system time.
  125. --*/
  126. {
  127. ULONGLONG LocalAbsNTTime;
  128. DWORD Error;
  129. if ( AbsNTTime == 0 ) {
  130. GetSystemTimeAsFileTime((FILETIME *)&LocalAbsNTTime );
  131. } else {
  132. LocalAbsNTTime = *(ULONGLONG *)AbsNTTime;
  133. }
  134. // add offset
  135. LocalAbsNTTime += Offset * (ULONGLONG)10000000;
  136. // now convert to NT timestamp
  137. Error = NTTimeToNTPTime( NTPTimeStamp, (PFILETIME)&LocalAbsNTTime );
  138. DhcpAssert( ERROR_SUCCESS == Error );
  139. return;
  140. }
  141. VOID
  142. DhcpNTPToNTTime(
  143. PULONG NTPTimeStamp,
  144. DWORD Offset,
  145. DATE_TIME *NTTime
  146. )
  147. /*++
  148. Routine Description:
  149. The function calculates the absolute NTP timestamp from AbsTime on
  150. NT added by given offset.
  151. Arguments:
  152. AbsNTTime - AbsTime on NT. If 0, it will use current time.
  153. RelativeOffset - offset to be added to AnsNTTime (in seconds.)
  154. Return Value:
  155. The time in RelativeTime seconds from the current system time.
  156. --*/
  157. {
  158. ULONGLONG LocalAbsNTTime;
  159. DWORD Error;
  160. Error = NTPTimeToNTFileTime(
  161. NTPTimeStamp,
  162. (FILETIME *)&LocalAbsNTTime,
  163. FALSE // not in host order.
  164. );
  165. DhcpAssert( ERROR_SUCCESS == Error );
  166. // add offset
  167. LocalAbsNTTime += Offset * (ULONGLONG)10000000;
  168. // now convert to NT timestamp
  169. // MBUG
  170. *(ULONGLONG *)NTTime = LocalAbsNTTime;
  171. return;
  172. }
  173. DWORD
  174. DhcpReportEventW(
  175. LPWSTR Source,
  176. DWORD EventID,
  177. DWORD EventType,
  178. DWORD NumStrings,
  179. DWORD DataLength,
  180. LPWSTR *Strings,
  181. LPVOID Data
  182. )
  183. /*++
  184. Routine Description:
  185. This function writes the specified (EventID) log at the end of the
  186. eventlog.
  187. Arguments:
  188. Source - Points to a null-terminated string that specifies the name
  189. of the module referenced. The node must exist in the
  190. registration database, and the module name has the
  191. following format:
  192. \EventLog\System\Lanmanworkstation
  193. EventID - The specific event identifier. This identifies the
  194. message that goes with this event.
  195. EventType - Specifies the type of event being logged. This
  196. parameter can have one of the following
  197. values:
  198. Value Meaning
  199. EVENTLOG_ERROR_TYPE Error event
  200. EVENTLOG_WARNING_TYPE Warning event
  201. EVENTLOG_INFORMATION_TYPE Information event
  202. NumStrings - Specifies the number of strings that are in the array
  203. at 'Strings'. A value of zero indicates no strings
  204. are present.
  205. DataLength - Specifies the number of bytes of event-specific raw
  206. (binary) data to write to the log. If cbData is
  207. zero, no event-specific data is present.
  208. Strings - Points to a buffer containing an array of null-terminated
  209. strings that are merged into the message before
  210. displaying to the user. This parameter must be a valid
  211. pointer (or NULL), even if cStrings is zero.
  212. Data - Buffer containing the raw data. This parameter must be a
  213. valid pointer (or NULL), even if cbData is zero.
  214. Return Value:
  215. Returns the WIN32 extended error obtained by GetLastError().
  216. NOTE : This function works slow since it calls the open and close
  217. eventlog source everytime.
  218. --*/
  219. {
  220. HANDLE EventlogHandle;
  221. DWORD ReturnCode;
  222. //
  223. // open eventlog section.
  224. //
  225. EventlogHandle = RegisterEventSourceW(
  226. NULL,
  227. Source
  228. );
  229. if (EventlogHandle == NULL) {
  230. ReturnCode = GetLastError();
  231. goto Cleanup;
  232. }
  233. //
  234. // Log the error code specified
  235. //
  236. if( !ReportEventW(
  237. EventlogHandle,
  238. (WORD)EventType,
  239. 0, // event category
  240. EventID,
  241. NULL,
  242. (WORD)NumStrings,
  243. DataLength,
  244. Strings,
  245. Data
  246. ) ) {
  247. ReturnCode = GetLastError();
  248. goto Cleanup;
  249. }
  250. ReturnCode = NO_ERROR;
  251. Cleanup:
  252. if( EventlogHandle != NULL ) {
  253. DeregisterEventSource(EventlogHandle);
  254. }
  255. return ReturnCode;
  256. }
  257. DWORD
  258. DhcpReportEventA(
  259. LPWSTR Source,
  260. DWORD EventID,
  261. DWORD EventType,
  262. DWORD NumStrings,
  263. DWORD DataLength,
  264. LPSTR *Strings,
  265. LPVOID Data
  266. )
  267. /*++
  268. Routine Description:
  269. This function writes the specified (EventID) log at the end of the
  270. eventlog.
  271. Arguments:
  272. Source - Points to a null-terminated string that specifies the name
  273. of the module referenced. The node must exist in the
  274. registration database, and the module name has the
  275. following format:
  276. \EventLog\System\Lanmanworkstation
  277. EventID - The specific event identifier. This identifies the
  278. message that goes with this event.
  279. EventType - Specifies the type of event being logged. This
  280. parameter can have one of the following
  281. values:
  282. Value Meaning
  283. EVENTLOG_ERROR_TYPE Error event
  284. EVENTLOG_WARNING_TYPE Warning event
  285. EVENTLOG_INFORMATION_TYPE Information event
  286. NumStrings - Specifies the number of strings that are in the array
  287. at 'Strings'. A value of zero indicates no strings
  288. are present.
  289. DataLength - Specifies the number of bytes of event-specific raw
  290. (binary) data to write to the log. If cbData is
  291. zero, no event-specific data is present.
  292. Strings - Points to a buffer containing an array of null-terminated
  293. strings that are merged into the message before
  294. displaying to the user. This parameter must be a valid
  295. pointer (or NULL), even if cStrings is zero.
  296. Data - Buffer containing the raw data. This parameter must be a
  297. valid pointer (or NULL), even if cbData is zero.
  298. Return Value:
  299. Returns the WIN32 extended error obtained by GetLastError().
  300. NOTE : This function works slow since it calls the open and close
  301. eventlog source everytime.
  302. --*/
  303. {
  304. HANDLE EventlogHandle;
  305. DWORD ReturnCode;
  306. //
  307. // open eventlog section.
  308. //
  309. EventlogHandle = RegisterEventSourceW(
  310. NULL,
  311. Source
  312. );
  313. if (EventlogHandle == NULL) {
  314. ReturnCode = GetLastError();
  315. goto Cleanup;
  316. }
  317. //
  318. // Log the error code specified
  319. //
  320. if( !ReportEventA(
  321. EventlogHandle,
  322. (WORD)EventType,
  323. 0, // event category
  324. EventID,
  325. NULL,
  326. (WORD)NumStrings,
  327. DataLength,
  328. Strings,
  329. Data
  330. ) ) {
  331. ReturnCode = GetLastError();
  332. goto Cleanup;
  333. }
  334. ReturnCode = NO_ERROR;
  335. Cleanup:
  336. if( EventlogHandle != NULL ) {
  337. DeregisterEventSource(EventlogHandle);
  338. }
  339. return ReturnCode;
  340. }
  341. DWORD
  342. DhcpLogUnknownOption(
  343. LPWSTR Source,
  344. DWORD EventID,
  345. LPOPTION Option
  346. )
  347. /*++
  348. Routine Description:
  349. This routine logs an unknown DHCP option to event log.
  350. Arguments:
  351. Source - name of the app that logs this error. it should be either
  352. "DhcpClient" or "DhcpServer".
  353. EventID - Event identifier number.
  354. Option - pointer to the unknown option structure.
  355. Return Value:
  356. Windows Error code.
  357. --*/
  358. {
  359. LPWSTR Strings[2];
  360. WCHAR StringsBuffer[ 2 * (3 + 1) ];
  361. // for two string each is 1byte decimal number (0 - 255).
  362. LPWSTR StringsPtr = StringsBuffer;
  363. //
  364. // convert option number.
  365. //
  366. Strings[0] = StringsPtr;
  367. DhcpDecimalToString( StringsPtr, Option->OptionType );
  368. StringsPtr += 3;
  369. *StringsPtr++ = L'\0';
  370. //
  371. // convert option length.
  372. //
  373. Strings[1] = StringsPtr;
  374. DhcpDecimalToString( StringsPtr, Option->OptionLength );
  375. StringsPtr += 3;
  376. *StringsPtr++ = L'\0';
  377. //
  378. // log error.
  379. //
  380. return(
  381. DhcpReportEventW(
  382. Source,
  383. EventID,
  384. EVENTLOG_WARNING_TYPE,
  385. 2,
  386. (DWORD)Option->OptionLength,
  387. Strings,
  388. (PVOID)Option->OptionValue )
  389. );
  390. }
  391. #if DBG
  392. VOID
  393. DhcpAssertFailed(
  394. LPSTR FailedAssertion,
  395. LPSTR FileName,
  396. DWORD LineNumber,
  397. LPSTR Message
  398. )
  399. /*++
  400. Routine Description:
  401. Assertion failed.
  402. Arguments:
  403. FailedAssertion :
  404. FileName :
  405. LineNumber :
  406. Message :
  407. Return Value:
  408. none.
  409. --*/
  410. {
  411. #ifndef DHCP_NOASSERT
  412. RtlAssert(
  413. FailedAssertion,
  414. FileName,
  415. (ULONG) LineNumber,
  416. (PCHAR) Message);
  417. #endif
  418. DhcpPrint(( 0, "Assert @ %s \n", FailedAssertion ));
  419. DhcpPrint(( 0, "Assert Filename, %s \n", FileName ));
  420. DhcpPrint(( 0, "Line Num. = %ld.\n", LineNumber ));
  421. DhcpPrint(( 0, "Message is %s\n", Message ));
  422. }
  423. #endif
  424. LPWSTR
  425. DhcpRegIpAddressToKey(
  426. DHCP_IP_ADDRESS IpAddress,
  427. LPWSTR KeyBuffer
  428. )
  429. /*++
  430. Routine Description:
  431. This function converts an IpAddress to registry key. The registry
  432. key is unicode string of IpAddress in dotted form.
  433. Arguments:
  434. IpAddress : IpAddress that needs conversion. The IpAddress is in
  435. host order.
  436. KeyBuffer : pointer a buffer that will hold the converted
  437. registry key. The buffer should be big enough to
  438. converted key.
  439. Return Value:
  440. Pointer to the key the buffer.
  441. --*/
  442. {
  443. LPSTR OemKey;
  444. LPWSTR UnicodeKey;
  445. DWORD NetworkOrderIpAddress;
  446. NetworkOrderIpAddress = htonl(IpAddress);
  447. OemKey = inet_ntoa( *(struct in_addr *)&NetworkOrderIpAddress );
  448. UnicodeKey = DhcpOemToUnicode( OemKey, KeyBuffer );
  449. DhcpAssert( UnicodeKey == KeyBuffer );
  450. return( UnicodeKey );
  451. }
  452. DHCP_IP_ADDRESS
  453. DhcpRegKeyToIpAddress(
  454. LPWSTR Key
  455. )
  456. /*++
  457. Routine Description:
  458. This function converts registry key to Ip Address.
  459. Arguments:
  460. Key : Pointer to registry key.
  461. Return Value:
  462. Converted IpAddress.
  463. --*/
  464. {
  465. CHAR OemKeyBuffer[DHCP_IP_KEY_LEN];
  466. LPSTR OemKey;
  467. OemKey = DhcpUnicodeToOem( Key, OemKeyBuffer );
  468. DhcpAssert( OemKey == OemKeyBuffer );
  469. return( ntohl(inet_addr( OemKey )) );
  470. }
  471. LPWSTR
  472. DhcpRegOptionIdToKey(
  473. DHCP_OPTION_ID OptionId,
  474. LPWSTR KeyBuffer
  475. )
  476. /*++
  477. Routine Description:
  478. This function converts an OptionId to registry key. The registry
  479. key is unicode string of OptionId, 3 unicode char. long and of the
  480. form L"000".
  481. Arguments:
  482. IpAddress : IpAddress that needs conversion.
  483. KeyBuffer : pointer a buffer that will hold the converted
  484. registry key. The buffer should be at least 8 char.
  485. long.
  486. Return Value:
  487. Pointer to the key the buffer.
  488. --*/
  489. {
  490. int i;
  491. for (i = 2; i >= 0; i--) {
  492. KeyBuffer[i] = L'0' + (BYTE)(OptionId % 10 );
  493. OptionId /= 10;
  494. }
  495. KeyBuffer[3] = L'\0';
  496. return( KeyBuffer );
  497. }
  498. DHCP_OPTION_ID
  499. DhcpRegKeyToOptionId(
  500. LPWSTR Key
  501. )
  502. /*++
  503. Routine Description:
  504. This function converts registry key to OptionId.
  505. Arguments:
  506. Key : Pointer to registry key.
  507. Return Value:
  508. Converted OptionId.
  509. --*/
  510. {
  511. DHCP_OPTION_ID OptionId = 0;
  512. int i;
  513. for (i = 0; i < 3 && Key[i] != L'\0'; i++) {
  514. OptionId = (OptionId * 10) + (Key[i] - L'0');
  515. }
  516. return( OptionId );
  517. }
  518. DWORD
  519. DhcpStartWaitableTimer(
  520. HANDLE TimerHandle,
  521. DWORD SleepTime)
  522. /*++
  523. Routine Description:
  524. This routine starts the waitable timer. This timer fires off even
  525. when the system is in hibernate state.
  526. Arguments
  527. TimerHandle - Waitable Timer Handle
  528. SleepTime - Sleep Time in seconds.
  529. Return Value:
  530. Status of the operation.
  531. --*/
  532. {
  533. DATE_TIME SleepTimeInNSec; // sleep time in nano seconds since Jan 1 1901
  534. DWORD Error;
  535. BOOL Result;
  536. Error = STATUS_SUCCESS;
  537. SleepTimeInNSec = DhcpCalculateTime( SleepTime );
  538. Result = SetWaitableTimer(
  539. TimerHandle, // handle to timer object
  540. (LARGE_INTEGER *)&SleepTimeInNSec, // due time.
  541. 0, // not periodic
  542. NULL, // completion routine
  543. NULL, // completion routine arg
  544. TRUE // resume power state when due
  545. );
  546. if ( !Result ) {
  547. DhcpPrint((0, "SetWaitableTimer reported Error = %d\n",Error=GetLastError()));
  548. }
  549. return Error;
  550. }
  551. VOID
  552. DhcpCancelWaitableTimer(
  553. HANDLE TimerHandle
  554. )
  555. /*++
  556. Routine Description:
  557. This routine cancels the waitable timer.
  558. Arguments
  559. TimerHandle - Waitable Timer Handle
  560. Return Value:
  561. --*/
  562. {
  563. BOOL Result;
  564. Result = CancelWaitableTimer( TimerHandle );
  565. if ( !Result ) {
  566. DhcpPrint((0,"SetWaitableTimer reported Error = %lx\n",GetLastError()));
  567. }
  568. }