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.

3921 lines
98 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This module contains the miscellaneous UL routines.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "miscp.h"
  13. //
  14. // Binary <--> Base64 Conversion Tables.
  15. //
  16. DECLSPEC_ALIGN(UL_CACHE_LINE) UCHAR BinaryToBase64Table[64] =
  17. {
  18. // 0 1 2 3 4 5 6 7
  19. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  20. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  21. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  22. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  23. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  24. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  25. 'w', 'x', 'y', 'z', '0', '1', '2', '3',
  26. '4', '5', '6', '7', '8', '9', '+', '/'
  27. };
  28. DECLSPEC_ALIGN(UL_CACHE_LINE) UCHAR Base64ToBinaryTable[256];
  29. const static char hexArray[] = "0123456789ABCDEF";
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text( PAGE, UlOpenRegistry )
  32. #pragma alloc_text( PAGE, UlReadLongParameter )
  33. #pragma alloc_text( PAGE, UlReadLongLongParameter )
  34. #pragma alloc_text( PAGE, UlReadGenericParameter )
  35. #pragma alloc_text( PAGE, UlIssueDeviceControl )
  36. #endif // ALLOC_PRAGMA
  37. #if 0
  38. NOT PAGEABLE -- UlBuildDeviceControlIrp
  39. NOT PAGEABLE -- UlULongLongToAscii
  40. NOT PAGEABLE -- UlpRestartDeviceControl
  41. NOT PAGEABLE -- UlAllocateReceiveBuffer
  42. NOT PAGEABLE -- UlAllocateReceiveBufferPool
  43. NOT PAGEABLE -- UlFreeReceiveBufferPool
  44. NOT PAGEABLE -- UlAllocateIrpContextPool
  45. NOT PAGEABLE -- UlFreeIrpContextPool
  46. NOT PAGEABLE -- UlAllocateRequestBufferPool
  47. NOT PAGEABLE -- UlFreeRequestBufferPool
  48. NOT PAGEABLE -- UlAllocateInternalRequestPool
  49. NOT PAGEABLE -- UlFreeInternalRequestPool
  50. NOT PAGEABLE -- UlAllocateChunkTrackerPool
  51. NOT PAGEABLE -- UlFreeChunkTrackerPool
  52. NOT PAGEABLE -- UlAllocateFullTrackerPool
  53. NOT PAGEABLE -- UlFreeFullTrackerPool
  54. NOT PAGEABLE -- UlAllocateResponseBufferPool
  55. NOT PAGEABLE -- UlFreeResponseBufferPool
  56. NOT PAGEABLE -- UlAllocateLogFileBufferPool
  57. NOT PAGEABLE -- UlFreeLogFileBufferPool
  58. NOT PAGEABLE -- UlAllocateLogDataBufferPool
  59. NOT PAGEABLE -- UlFreeLogDataBufferPool
  60. NOT PAGEABLE -- UlAllocateErrorLogBufferPool
  61. NOT PAGEABLE -- UlFreeErrorLogBufferPool
  62. NOT PAGEABLE -- UlUlInterlockedIncrement64
  63. NOT PAGEABLE -- UlUlInterlockedDecrement64
  64. NOT PAGEABLE -- UlUlInterlockedAdd64
  65. NOT PAGEABLE -- UlUlInterlockedExchange64
  66. NOT PAGEABLE -- TwoDigitsToUnicode
  67. NOT PAGEABLE -- TimeFieldsToHttpDate
  68. NOT PAGEABLE -- AsciiToShort
  69. NOT PAGEABLE -- TwoAsciisToShort
  70. NOT PAGEABLE -- NumericToAsciiMonth
  71. NOT PAGEABLE -- StringTimeToSystemTime
  72. #endif
  73. //
  74. // Public functions.
  75. //
  76. /***************************************************************************++
  77. Routine Description:
  78. Opens a handle to the UL's Parameters registry key.
  79. Arguments:
  80. BaseName - Supplies the name of the parent registry key containing
  81. the Parameters key.
  82. ParametersHandle - Returns a handle to the Parameters key.
  83. Return Value:
  84. NTSTATUS - Completion status.
  85. --***************************************************************************/
  86. NTSTATUS
  87. UlOpenRegistry(
  88. IN PUNICODE_STRING BaseName,
  89. OUT PHANDLE ParametersHandle,
  90. IN PWSTR OptionalParameterString
  91. )
  92. {
  93. HANDLE configHandle;
  94. NTSTATUS status;
  95. PWSTR parametersString = REGISTRY_PARAMETERS;
  96. UNICODE_STRING parametersKeyName;
  97. OBJECT_ATTRIBUTES objectAttributes;
  98. //
  99. // Sanity check.
  100. //
  101. PAGED_CODE();
  102. if (OptionalParameterString)
  103. {
  104. parametersString = OptionalParameterString;
  105. }
  106. //
  107. // Open the registry for the initial string.
  108. //
  109. InitializeObjectAttributes(
  110. &objectAttributes, // ObjectAttributes
  111. BaseName, // ObjectName
  112. OBJ_CASE_INSENSITIVE | // Attributes
  113. OBJ_KERNEL_HANDLE,
  114. NULL, // RootDirectory
  115. NULL // SecurityDescriptor
  116. );
  117. status = ZwOpenKey( &configHandle, KEY_READ, &objectAttributes );
  118. if (!NT_SUCCESS(status))
  119. {
  120. return STATUS_UNSUCCESSFUL;
  121. }
  122. //
  123. // Now open the parameters key.
  124. //
  125. status = UlInitUnicodeStringEx( &parametersKeyName, parametersString );
  126. if ( NT_SUCCESS(status) )
  127. {
  128. InitializeObjectAttributes(
  129. &objectAttributes, // ObjectAttributes
  130. &parametersKeyName, // ObjectName
  131. OBJ_CASE_INSENSITIVE, // Attributes
  132. configHandle, // RootDirectory
  133. NULL // SecurityDescriptor
  134. );
  135. status = ZwOpenKey( ParametersHandle, KEY_READ, &objectAttributes );
  136. }
  137. ZwClose( configHandle );
  138. return status;
  139. } // UlOpenRegistry
  140. /***************************************************************************++
  141. Routine Description:
  142. Reads a single (LONG/ULONG) value from the registry.
  143. Arguments:
  144. ParametersHandle - Supplies an open registry handle.
  145. ValueName - Supplies the name of the value to read.
  146. DefaultValue - Supplies the default value.
  147. Return Value:
  148. LONG - The value read from the registry or the default if the
  149. registry data was unavailable or incorrect.
  150. --***************************************************************************/
  151. LONG
  152. UlReadLongParameter(
  153. IN HANDLE ParametersHandle,
  154. IN PWCHAR ValueName,
  155. IN LONG DefaultValue
  156. )
  157. {
  158. PKEY_VALUE_PARTIAL_INFORMATION information = { 0 };
  159. UNICODE_STRING valueKeyName;
  160. ULONG informationLength;
  161. LONG returnValue;
  162. NTSTATUS status;
  163. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(LONG)];
  164. //
  165. // Sanity check.
  166. //
  167. PAGED_CODE();
  168. //
  169. // Build the value name, read it from the registry.
  170. //
  171. status = UlInitUnicodeStringEx(
  172. &valueKeyName,
  173. ValueName
  174. );
  175. if ( NT_SUCCESS(status) )
  176. {
  177. information = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  178. status = ZwQueryValueKey(
  179. ParametersHandle,
  180. &valueKeyName,
  181. KeyValuePartialInformation,
  182. (PVOID)information,
  183. sizeof(buffer),
  184. &informationLength
  185. );
  186. }
  187. //
  188. // If the read succeeded, the type is DWORD and the length is
  189. // sane, use it. Otherwise, use the default.
  190. //
  191. if (status == STATUS_SUCCESS &&
  192. information->Type == REG_DWORD &&
  193. information->DataLength == sizeof(returnValue))
  194. {
  195. RtlMoveMemory( &returnValue, information->Data, sizeof(returnValue) );
  196. }
  197. else
  198. {
  199. returnValue = DefaultValue;
  200. }
  201. return returnValue;
  202. } // UlReadLongParameter
  203. /***************************************************************************++
  204. Routine Description:
  205. Reads a single (LONGLONG/ULONGLONG) value from the registry.
  206. Arguments:
  207. ParametersHandle - Supplies an open registry handle.
  208. ValueName - Supplies the name of the value to read.
  209. DefaultValue - Supplies the default value.
  210. Return Value:
  211. LONGLONG - The value read from the registry or the default if the
  212. registry data was unavailable or incorrect.
  213. --***************************************************************************/
  214. LONGLONG
  215. UlReadLongLongParameter(
  216. IN HANDLE ParametersHandle,
  217. IN PWCHAR ValueName,
  218. IN LONGLONG DefaultValue
  219. )
  220. {
  221. PKEY_VALUE_PARTIAL_INFORMATION information = { 0 };
  222. UNICODE_STRING valueKeyName;
  223. ULONG informationLength;
  224. LONGLONG returnValue;
  225. NTSTATUS status;
  226. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(LONGLONG)];
  227. //
  228. // Sanity check.
  229. //
  230. PAGED_CODE();
  231. //
  232. // Build the value name, read it from the registry.
  233. //
  234. status = UlInitUnicodeStringEx(
  235. &valueKeyName,
  236. ValueName
  237. );
  238. if ( NT_SUCCESS(status) )
  239. {
  240. information = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  241. status = ZwQueryValueKey(
  242. ParametersHandle,
  243. &valueKeyName,
  244. KeyValuePartialInformation,
  245. (PVOID)information,
  246. sizeof(buffer),
  247. &informationLength
  248. );
  249. }
  250. //
  251. // If the read succeeded, the type is DWORD and the length is
  252. // sane, use it. Otherwise, use the default.
  253. //
  254. if (status == STATUS_SUCCESS &&
  255. information->Type == REG_QWORD &&
  256. information->DataLength == sizeof(returnValue))
  257. {
  258. RtlMoveMemory( &returnValue, information->Data, sizeof(returnValue) );
  259. }
  260. else
  261. {
  262. returnValue = DefaultValue;
  263. }
  264. return returnValue;
  265. } // UlReadLongLongParameter
  266. /***************************************************************************++
  267. Routine Description:
  268. Reads a single free-form value from the registry.
  269. Arguments:
  270. ParametersHandle - Supplies an open registry handle.
  271. ValueName - Supplies the name of the value to read.
  272. Value - Receives the value read from the registry.
  273. Return Value:
  274. NTSTATUS - Completion status.
  275. --***************************************************************************/
  276. NTSTATUS
  277. UlReadGenericParameter(
  278. IN HANDLE ParametersHandle,
  279. IN PWCHAR ValueName,
  280. OUT PKEY_VALUE_PARTIAL_INFORMATION * Value
  281. )
  282. {
  283. KEY_VALUE_PARTIAL_INFORMATION partialInfo;
  284. UNICODE_STRING valueKeyName;
  285. ULONG informationLength;
  286. NTSTATUS status;
  287. PKEY_VALUE_PARTIAL_INFORMATION newValue;
  288. ULONG dataLength;
  289. //
  290. // Sanity check.
  291. //
  292. PAGED_CODE();
  293. //
  294. // Build the value name, then perform an initial read. The read
  295. // should fail with buffer overflow, but that's OK. We just want
  296. // to get the length of the data.
  297. //
  298. status = UlInitUnicodeStringEx( &valueKeyName, ValueName );
  299. if ( NT_ERROR(status) )
  300. {
  301. return status;
  302. }
  303. status = ZwQueryValueKey(
  304. ParametersHandle,
  305. &valueKeyName,
  306. KeyValuePartialInformation,
  307. (PVOID)&partialInfo,
  308. sizeof(partialInfo),
  309. &informationLength
  310. );
  311. if (NT_ERROR(status))
  312. {
  313. return status;
  314. }
  315. //
  316. // Determine the data length. Ensure that strings and multi-sz get
  317. // properly terminated.
  318. //
  319. dataLength = partialInfo.DataLength - 1;
  320. if (partialInfo.Type == REG_SZ || partialInfo.Type == REG_EXPAND_SZ)
  321. {
  322. dataLength += 1;
  323. }
  324. if (partialInfo.Type == REG_MULTI_SZ)
  325. {
  326. dataLength += 2;
  327. }
  328. //
  329. // Allocate the buffer.
  330. //
  331. newValue = UL_ALLOCATE_STRUCT_WITH_SPACE(
  332. PagedPool,
  333. KEY_VALUE_PARTIAL_INFORMATION,
  334. dataLength,
  335. UL_REGISTRY_DATA_POOL_TAG
  336. );
  337. if (newValue == NULL)
  338. {
  339. return STATUS_INSUFFICIENT_RESOURCES;
  340. }
  341. //
  342. // update the actually allocated length for later use
  343. //
  344. dataLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
  345. RtlZeroMemory( newValue, dataLength );
  346. //
  347. // Perform the actual read.
  348. //
  349. status = ZwQueryValueKey(
  350. ParametersHandle,
  351. &valueKeyName,
  352. KeyValuePartialInformation,
  353. (PVOID)(newValue),
  354. dataLength,
  355. &informationLength
  356. );
  357. if (NT_SUCCESS(status))
  358. {
  359. *Value = newValue;
  360. }
  361. else
  362. {
  363. UL_FREE_POOL( newValue, UL_REGISTRY_DATA_POOL_TAG );
  364. }
  365. return status;
  366. } // UlReadGenericParameter
  367. /***************************************************************************++
  368. Routine Description:
  369. Builds a properly formatted device control IRP.
  370. Arguments:
  371. Irp - Supplies the IRP to format.
  372. IoControlCode - Supplies the device IO control code.
  373. InputBuffer - Supplies the input buffer.
  374. InputBufferLength - Supplies the length of InputBuffer.
  375. OutputBuffer - Supplies the output buffer.
  376. OutputBufferLength - Supplies the length of OutputBuffer.
  377. MdlAddress - Supplies a MDL to attach to the IRP. This is assumed to
  378. be a non-paged MDL.
  379. FileObject - Supplies the file object for the target driver.
  380. DeviceObject - Supplies the correct device object for the target
  381. driver.
  382. IoStatusBlock - Receives the final completion status of the request.
  383. CompletionRoutine - Supplies a pointer to a completion routine to
  384. call after the request completes. This will only be called if
  385. this routine returns STATUS_PENDING.
  386. CompletionContext - Supplies an uninterpreted context value passed
  387. to the completion routine.
  388. TargetThread - Optionally supplies a target thread for the IRP. If
  389. this value is NULL, then the current thread is used.
  390. --***************************************************************************/
  391. VOID
  392. UlBuildDeviceControlIrp(
  393. IN OUT PIRP Irp,
  394. IN ULONG IoControlCode,
  395. IN PVOID InputBuffer OPTIONAL,
  396. IN ULONG InputBufferLength,
  397. IN PVOID OutputBuffer OPTIONAL,
  398. IN ULONG OutputBufferLength,
  399. IN PMDL MdlAddress,
  400. IN PFILE_OBJECT FileObject,
  401. IN PDEVICE_OBJECT DeviceObject,
  402. IN PIO_STATUS_BLOCK IoStatusBlock,
  403. IN PIO_COMPLETION_ROUTINE CompletionRoutine,
  404. IN PVOID CompletionContext,
  405. IN PETHREAD TargetThread OPTIONAL
  406. )
  407. {
  408. PIO_STACK_LOCATION irpSp;
  409. //
  410. // Sanity check.
  411. //
  412. ASSERT( Irp != NULL );
  413. ASSERT( FileObject != NULL );
  414. ASSERT( DeviceObject != NULL );
  415. //
  416. // Fill in the service independent parameters in the IRP.
  417. //
  418. Irp->Flags = 0;
  419. Irp->RequestorMode = KernelMode;
  420. Irp->PendingReturned = FALSE;
  421. Irp->UserIosb = IoStatusBlock;
  422. Irp->UserEvent = NULL;
  423. Irp->AssociatedIrp.SystemBuffer = InputBuffer ? InputBuffer : OutputBuffer;
  424. Irp->UserBuffer = OutputBuffer;
  425. Irp->MdlAddress = MdlAddress;
  426. Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  427. Irp->Tail.Overlay.Thread = TargetThread ? TargetThread : PsGetCurrentThread();
  428. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  429. Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  430. //
  431. // Put the file object pointer in the stack location.
  432. //
  433. irpSp = IoGetNextIrpStackLocation( Irp );
  434. irpSp->FileObject = FileObject;
  435. irpSp->DeviceObject = DeviceObject;
  436. //
  437. // Fill in the service dependent parameters in the IRP stack.
  438. //
  439. irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
  440. irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
  441. irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
  442. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
  443. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  444. irpSp->MinorFunction = 0;
  445. //
  446. // Set the completion routine appropriately.
  447. //
  448. if (CompletionRoutine == NULL)
  449. {
  450. IoSetCompletionRoutine(
  451. Irp,
  452. NULL,
  453. NULL,
  454. FALSE,
  455. FALSE,
  456. FALSE
  457. );
  458. }
  459. else
  460. {
  461. IoSetCompletionRoutine(
  462. Irp,
  463. CompletionRoutine,
  464. CompletionContext,
  465. TRUE,
  466. TRUE,
  467. TRUE
  468. );
  469. }
  470. } // UlBuildDeviceControlIrp
  471. /***************************************************************************++
  472. Routine Description:
  473. Converts the given ULONGLLONG to an ASCII representation and stores it
  474. in the given string.
  475. Arguments:
  476. String - Receives the ASCII representation of the ULONGLONG.
  477. Value - Supplies the ULONGLONG to convert.
  478. Return Value:
  479. PSTR - Pointer to the next character in String *after* the converted
  480. ULONGLONG.
  481. --***************************************************************************/
  482. PSTR
  483. UlULongLongToAscii(
  484. IN PSTR String,
  485. IN ULONGLONG Value
  486. )
  487. {
  488. PSTR p1;
  489. PSTR p2;
  490. CHAR ch;
  491. ULONG digit;
  492. //
  493. // Special case 0 to make the rest of the routine simpler.
  494. //
  495. if (Value == 0)
  496. {
  497. *String++ = '0';
  498. }
  499. else
  500. {
  501. //
  502. // Convert the ULONG. Note that this will result in the string
  503. // being backwards in memory.
  504. //
  505. p1 = String;
  506. p2 = String;
  507. while (Value != 0)
  508. {
  509. digit = (ULONG)( Value % 10 );
  510. Value = Value / 10;
  511. *p1++ = '0' + (CHAR)digit;
  512. }
  513. //
  514. // Reverse the string.
  515. //
  516. String = p1;
  517. p1--;
  518. while (p1 > p2)
  519. {
  520. ch = *p1;
  521. *p1 = *p2;
  522. *p2 = ch;
  523. p2++;
  524. p1--;
  525. }
  526. }
  527. *String = '\0';
  528. return String;
  529. } // UlULongLongToAscii
  530. NTSTATUS
  531. _RtlIntegerToUnicode(
  532. IN ULONG Value,
  533. IN ULONG Base OPTIONAL,
  534. IN LONG BufferLength,
  535. OUT PWSTR String
  536. )
  537. {
  538. PWSTR p1;
  539. PWSTR p2;
  540. WCHAR ch;
  541. ULONG digit;
  542. UNREFERENCED_PARAMETER(Base);
  543. UNREFERENCED_PARAMETER(BufferLength);
  544. //
  545. // Special case 0 to make the rest of the routine simpler.
  546. //
  547. if (Value == 0)
  548. {
  549. *String++ = L'0';
  550. }
  551. else
  552. {
  553. //
  554. // Convert the ULONG. Note that this will result in the string
  555. // being backwards in memory.
  556. //
  557. p1 = String;
  558. p2 = String;
  559. while (Value != 0)
  560. {
  561. digit = (ULONG)( Value % 10 );
  562. Value = Value / 10;
  563. *p1++ = L'0' + (WCHAR)digit;
  564. }
  565. //
  566. // Reverse the string.
  567. //
  568. String = p1;
  569. p1--;
  570. while (p1 > p2)
  571. {
  572. ch = *p1;
  573. *p1 = *p2;
  574. *p2 = ch;
  575. p2++;
  576. p1--;
  577. }
  578. }
  579. *String = L'\0';
  580. return STATUS_SUCCESS;
  581. } // _RtlIntegerToUnicode
  582. /***************************************************************************++
  583. Routine Description:
  584. Synchronously issues a device control request to the TDI provider.
  585. Arguments:
  586. pTdiObject - Supplies a pointer to the TDI object.
  587. pIrpParameters - Supplies a pointer to the IRP parameters.
  588. IrpParametersLength - Supplies the length of pIrpParameters.
  589. pMdlBuffer - Optionally supplies a pointer to a buffer to be mapped
  590. into a MDL and placed in the MdlAddress field of the IRP.
  591. MdlBufferLength - Optionally supplies the length of pMdlBuffer.
  592. MinorFunction - Supplies the minor function code of the request.
  593. Return Value:
  594. NTSTATUS - Completion status.
  595. --***************************************************************************/
  596. NTSTATUS
  597. UlIssueDeviceControl(
  598. IN PUX_TDI_OBJECT pTdiObject,
  599. IN PVOID pIrpParameters,
  600. IN ULONG IrpParametersLength,
  601. IN PVOID pMdlBuffer OPTIONAL,
  602. IN ULONG MdlBufferLength OPTIONAL,
  603. IN UCHAR MinorFunction
  604. )
  605. {
  606. NTSTATUS status;
  607. PIRP pIrp;
  608. PIO_STACK_LOCATION pIrpSp;
  609. UL_STATUS_BLOCK ulStatus;
  610. IO_STATUS_BLOCK UserIosb;
  611. PMDL pMdl;
  612. //
  613. // Sanity check.
  614. //
  615. PAGED_CODE();
  616. //
  617. // Initialize the event that will signal I/O completion.
  618. //
  619. UlInitializeStatusBlock( &ulStatus );
  620. //
  621. // Set the file object event to the non-signaled state.
  622. //
  623. KeResetEvent( &pTdiObject->pFileObject->Event );
  624. //
  625. // Allocate an IRP for the request.
  626. //
  627. pIrp = UlAllocateIrp(
  628. pTdiObject->pDeviceObject->StackSize, // StackSize
  629. FALSE // ChargeQuota
  630. );
  631. if (pIrp == NULL)
  632. {
  633. return STATUS_INSUFFICIENT_RESOURCES;
  634. }
  635. //
  636. // Initialize the User IO_STATUS_BLOCK
  637. //
  638. UserIosb.Information = 0;
  639. UserIosb.Status = STATUS_SUCCESS;
  640. //
  641. // Establish the service independent parameters.
  642. //
  643. pIrp->Flags = IRP_SYNCHRONOUS_API;
  644. pIrp->RequestorMode = KernelMode;
  645. pIrp->PendingReturned = FALSE;
  646. pIrp->UserIosb = &UserIosb;
  647. pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
  648. pIrp->Tail.Overlay.OriginalFileObject = pTdiObject->pFileObject;
  649. //
  650. // If we have a MDL buffer, allocate a new MDL and map the
  651. // buffer into it.
  652. //
  653. if (pMdlBuffer != NULL)
  654. {
  655. pMdl = UlAllocateMdl(
  656. pMdlBuffer, // VirtualAddress
  657. MdlBufferLength, // Length
  658. FALSE, // SecondaryBuffer
  659. FALSE, // ChargeQuota
  660. pIrp // Irp
  661. );
  662. if (pMdl == NULL)
  663. {
  664. UlFreeIrp( pIrp );
  665. return STATUS_INSUFFICIENT_RESOURCES;
  666. }
  667. MmBuildMdlForNonPagedPool( pMdl );
  668. }
  669. else
  670. {
  671. pIrp->MdlAddress = NULL;
  672. }
  673. //
  674. // Initialize the IRP stack location.
  675. //
  676. pIrpSp = IoGetNextIrpStackLocation( pIrp );
  677. pIrpSp->FileObject = pTdiObject->pFileObject;
  678. pIrpSp->DeviceObject = pTdiObject->pDeviceObject;
  679. ASSERT( IrpParametersLength <= sizeof(pIrpSp->Parameters) );
  680. RtlCopyMemory(
  681. &pIrpSp->Parameters,
  682. pIrpParameters,
  683. IrpParametersLength
  684. );
  685. pIrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  686. pIrpSp->MinorFunction = MinorFunction;
  687. //
  688. // Reference the file object.
  689. //
  690. ObReferenceObject( pTdiObject->pFileObject );
  691. //
  692. // Establish a completion routine to free the MDL and dereference
  693. // the FILE_OBJECT.
  694. //
  695. IoSetCompletionRoutine(
  696. pIrp, // Irp
  697. &UlpRestartDeviceControl, // CompletionRoutine
  698. &ulStatus, // Context
  699. TRUE, // InvokeOnSuccess
  700. TRUE, // InvokeOnError
  701. TRUE // InvokeOnCancel
  702. );
  703. //
  704. // Issue the request.
  705. //
  706. status = UlCallDriver( pTdiObject->pDeviceObject, pIrp );
  707. //
  708. // If necessary, wait for the request to complete and snag the
  709. // final completion status.
  710. //
  711. if (status == STATUS_PENDING)
  712. {
  713. UlWaitForStatusBlockEvent( &ulStatus );
  714. status = ulStatus.IoStatus.Status;
  715. }
  716. return status;
  717. } // UlIssueDeviceControl
  718. /***************************************************************************++
  719. Routine Description:
  720. Allocates the pool necessary for a new UL_RECEIVE_BUFFER structure and
  721. initializes the structure.
  722. Arguments:
  723. IrpStackSize - Supplies the IrpStackSize.
  724. Return Value:
  725. PVOID - Pointer to the newly allocated block if successful, FALSE
  726. otherwise.
  727. --***************************************************************************/
  728. PVOID
  729. UlAllocateReceiveBuffer(
  730. IN CCHAR IrpStackSize
  731. )
  732. {
  733. PUL_RECEIVE_BUFFER pBuffer;
  734. SIZE_T irpLength;
  735. SIZE_T mdlLength;
  736. SIZE_T ExtraLength;
  737. //
  738. // Calculate the required length of the buffer & allocate it.
  739. //
  740. irpLength = IoSizeOfIrp( IrpStackSize );
  741. irpLength = ALIGN_UP( irpLength, PVOID );
  742. mdlLength = MmSizeOfMdl( (PVOID)(PAGE_SIZE - 1), g_UlReceiveBufferSize );
  743. mdlLength = ALIGN_UP( mdlLength, PVOID );
  744. ExtraLength = irpLength + (mdlLength*2) + g_UlReceiveBufferSize;
  745. ASSERT( ( ExtraLength & (sizeof(PVOID) - 1) ) == 0 );
  746. pBuffer = UL_ALLOCATE_STRUCT_WITH_SPACE(
  747. NonPagedPool,
  748. UL_RECEIVE_BUFFER,
  749. ExtraLength,
  750. UL_RCV_BUFFER_POOL_TAG
  751. );
  752. if (pBuffer != NULL)
  753. {
  754. PUCHAR pRawBuffer = (PUCHAR)(pBuffer);
  755. //
  756. // Initialize the IRP, MDL, and data pointers within the buffer.
  757. //
  758. pBuffer->Signature = UL_RECEIVE_BUFFER_SIGNATURE_X;
  759. pRawBuffer += ALIGN_UP( sizeof(UL_RECEIVE_BUFFER), PVOID );
  760. pBuffer->pIrp = (PIRP)pRawBuffer;
  761. pRawBuffer += irpLength;
  762. pBuffer->pMdl = (PMDL)pRawBuffer;
  763. pRawBuffer += mdlLength;
  764. pBuffer->pPartialMdl = (PMDL)pRawBuffer;
  765. pRawBuffer += mdlLength;
  766. pBuffer->pDataArea = (PVOID)pRawBuffer;
  767. pBuffer->UnreadDataLength = 0;
  768. //
  769. // Initialize the IRP.
  770. //
  771. IoInitializeIrp(
  772. pBuffer->pIrp, // Irp
  773. (USHORT)irpLength, // PacketSize
  774. IrpStackSize // StackSize
  775. );
  776. //
  777. // Initialize the primary MDL.
  778. //
  779. MmInitializeMdl(
  780. pBuffer->pMdl, // MemoryDescriptorList
  781. pBuffer->pDataArea, // BaseVa
  782. g_UlReceiveBufferSize // Length
  783. );
  784. MmBuildMdlForNonPagedPool( pBuffer->pMdl );
  785. }
  786. return (PVOID)pBuffer;
  787. } // UlAllocateReceiveBuffer
  788. /***************************************************************************++
  789. Routine Description:
  790. Allocates the pool necessary for a new UL_RECEIVE_BUFFER structure and
  791. initializes the structure.
  792. Arguments:
  793. PoolType - Supplies the type of pool to allocate. This must always
  794. be NonPagedPool.
  795. ByteLength - Supplies the byte length for the allocation request.
  796. This should be sizeof(UL_RECEIVE_BUFFER), but is basically ignored.
  797. Tag - Supplies the tag to use for the pool. This should be
  798. UL_RCV_BUFFER_POOL_TAG, but is basically ignored.
  799. Note: These parameters are required so that this function has a
  800. signature identical to ExAllocatePoolWithTag.
  801. Return Value:
  802. PVOID - Pointer to the newly allocated block if successful, FALSE
  803. otherwise.
  804. --***************************************************************************/
  805. PVOID
  806. UlAllocateReceiveBufferPool(
  807. IN POOL_TYPE PoolType,
  808. IN SIZE_T ByteLength,
  809. IN ULONG Tag
  810. )
  811. {
  812. UNREFERENCED_PARAMETER(PoolType);
  813. UNREFERENCED_PARAMETER(ByteLength);
  814. UNREFERENCED_PARAMETER(Tag);
  815. //
  816. // Sanity check.
  817. //
  818. ASSERT( PoolType == NonPagedPool );
  819. ASSERT( ByteLength == sizeof(UL_RECEIVE_BUFFER) );
  820. ASSERT( Tag == UL_RCV_BUFFER_POOL_TAG );
  821. return UlAllocateReceiveBuffer( DEFAULT_IRP_STACK_SIZE );
  822. } // UlAllocateReceiveBufferPool
  823. /***************************************************************************++
  824. Routine Description:
  825. Frees the pool allocated for a UL_RECEIVE_BUFFER structure.
  826. Arguments:
  827. pBuffer - Supplies the buffer to free.
  828. --***************************************************************************/
  829. VOID
  830. UlFreeReceiveBufferPool(
  831. IN PVOID pBuffer
  832. )
  833. {
  834. PUL_RECEIVE_BUFFER pReceiveBuffer;
  835. pReceiveBuffer = (PUL_RECEIVE_BUFFER)pBuffer;
  836. ASSERT(pReceiveBuffer->Signature == UL_RECEIVE_BUFFER_SIGNATURE_X);
  837. UL_FREE_POOL( pReceiveBuffer, UL_RCV_BUFFER_POOL_TAG );
  838. } // UlFreeReceiveBufferPool
  839. /***************************************************************************++
  840. Routine Description:
  841. Allocates the pool necessary for a new UL_IRP_CONTEXT structure and
  842. initializes the structure.
  843. Arguments:
  844. PoolType - Supplies the type of pool to allocate. This must always
  845. be NonPagedPool.
  846. ByteLength - Supplies the byte length for the allocation request.
  847. This should be sizeof(UL_IRP_CONTEXT), but is basically ignored.
  848. Tag - Supplies the tag to use for the pool. This should be
  849. UL_IRP_CONTEXT_POOL_TAG, but is basically ignored.
  850. Note: These parameters are required so that this function has a
  851. signature identical to ExAllocatePoolWithTag.
  852. Return Value:
  853. PVOID - Pointer to the newly allocated block if successful, FALSE
  854. otherwise.
  855. --***************************************************************************/
  856. PVOID
  857. UlAllocateIrpContextPool(
  858. IN POOL_TYPE PoolType,
  859. IN SIZE_T ByteLength,
  860. IN ULONG Tag
  861. )
  862. {
  863. PUL_IRP_CONTEXT pIrpContext;
  864. UNREFERENCED_PARAMETER(PoolType);
  865. UNREFERENCED_PARAMETER(ByteLength);
  866. UNREFERENCED_PARAMETER(Tag);
  867. //
  868. // Sanity check.
  869. //
  870. ASSERT( PoolType == NonPagedPool );
  871. ASSERT( ByteLength == sizeof(UL_IRP_CONTEXT) );
  872. ASSERT( Tag == UL_IRP_CONTEXT_POOL_TAG );
  873. //
  874. // Allocate the IRP context.
  875. //
  876. pIrpContext = UL_ALLOCATE_STRUCT(
  877. NonPagedPool,
  878. UL_IRP_CONTEXT,
  879. UL_IRP_CONTEXT_POOL_TAG
  880. );
  881. if (pIrpContext != NULL)
  882. {
  883. //
  884. // Initialize it.
  885. //
  886. pIrpContext->Signature = UL_IRP_CONTEXT_SIGNATURE_X;
  887. #if DBG
  888. pIrpContext->pCompletionRoutine = &UlDbgInvalidCompletionRoutine;
  889. #endif
  890. }
  891. return (PVOID)pIrpContext;
  892. } // UlAllocateIrpContextPool
  893. /***************************************************************************++
  894. Routine Description:
  895. Frees the pool allocated for a UL_IRP_CONTEXT structure.
  896. Arguments:
  897. pBuffer - Supplies the buffer to free.
  898. --***************************************************************************/
  899. VOID
  900. UlFreeIrpContextPool(
  901. IN PVOID pBuffer
  902. )
  903. {
  904. PUL_IRP_CONTEXT pIrpContext;
  905. pIrpContext = (PUL_IRP_CONTEXT)pBuffer;
  906. ASSERT(pIrpContext->Signature == UL_IRP_CONTEXT_SIGNATURE_X);
  907. UL_FREE_POOL( pIrpContext, UL_IRP_CONTEXT_POOL_TAG );
  908. } // UlFreeIrpContextPool
  909. /***************************************************************************++
  910. Routine Description:
  911. Allocates the pool necessary for a new UL_REQUEST_BUFFER structure and
  912. initializes the structure.
  913. Arguments:
  914. PoolType - Supplies the type of pool to allocate. This must always
  915. be NonPagedPool.
  916. ByteLength - Supplies the byte length for the allocation request.
  917. This should be DEFAULT_MAX_REQUEST_BUFFER_SIZE but is basically
  918. ignored.
  919. Tag - Supplies the tag to use for the pool. This should be
  920. UL_REQUEST_BUFFER_POOL_TAG, but is basically ignored.
  921. Note: These parameters are required so that this function has a
  922. signature identical to ExAllocatePoolWithTag.
  923. Return Value:
  924. PVOID - Pointer to the newly allocated block if successful, FALSE
  925. otherwise.
  926. --***************************************************************************/
  927. PVOID
  928. UlAllocateRequestBufferPool(
  929. IN POOL_TYPE PoolType,
  930. IN SIZE_T ByteLength,
  931. IN ULONG Tag
  932. )
  933. {
  934. PUL_REQUEST_BUFFER pRequestBuffer;
  935. UNREFERENCED_PARAMETER(PoolType);
  936. UNREFERENCED_PARAMETER(ByteLength);
  937. UNREFERENCED_PARAMETER(Tag);
  938. //
  939. // Sanity check.
  940. //
  941. ASSERT( PoolType == NonPagedPool );
  942. ASSERT( ByteLength == DEFAULT_MAX_REQUEST_BUFFER_SIZE );
  943. ASSERT( Tag == UL_REQUEST_BUFFER_POOL_TAG );
  944. //
  945. // Allocate the request buffer.
  946. //
  947. pRequestBuffer = UL_ALLOCATE_STRUCT_WITH_SPACE(
  948. NonPagedPool,
  949. UL_REQUEST_BUFFER,
  950. DEFAULT_MAX_REQUEST_BUFFER_SIZE,
  951. UL_REQUEST_BUFFER_POOL_TAG
  952. );
  953. if (pRequestBuffer != NULL)
  954. {
  955. //
  956. // Initialize it.
  957. //
  958. pRequestBuffer->Signature = MAKE_FREE_TAG(UL_REQUEST_BUFFER_POOL_TAG);
  959. }
  960. return (PVOID)pRequestBuffer;
  961. } // UlAllocateRequestBufferPool
  962. /***************************************************************************++
  963. Routine Description:
  964. Frees the pool allocated for a UL_REQUEST_BUFFER structure.
  965. Arguments:
  966. pBuffer - Supplies the buffer to free.
  967. --***************************************************************************/
  968. VOID
  969. UlFreeRequestBufferPool(
  970. IN PVOID pBuffer
  971. )
  972. {
  973. PUL_REQUEST_BUFFER pRequestBuffer;
  974. pRequestBuffer = (PUL_REQUEST_BUFFER)pBuffer;
  975. ASSERT(pRequestBuffer->Signature == MAKE_FREE_TAG(UL_REQUEST_BUFFER_POOL_TAG));
  976. UL_FREE_POOL_WITH_SIG(pRequestBuffer, UL_REQUEST_BUFFER_POOL_TAG);
  977. } // UlFreeRequestBufferPool
  978. /***************************************************************************++
  979. Routine Description:
  980. Allocates the pool necessary for a new UL_INTERNAL_REQUEST structure and
  981. initializes the structure.
  982. Arguments:
  983. PoolType - Supplies the type of pool to allocate. This must always
  984. be NonPagedPool.
  985. ByteLength - Supplies the byte length for the allocation request.
  986. This should be sizeof(UL_INTERNAL_REQUEST) but is basically ignored.
  987. Tag - Supplies the tag to use for the pool. This should be
  988. UL_INTERNAL_REQUEST_POOL_TAG, but is basically ignored.
  989. Note: These parameters are required so that this function has a
  990. signature identical to ExAllocatePoolWithTag.
  991. Return Value:
  992. PVOID - Pointer to the newly allocated block if successful, FALSE
  993. otherwise.
  994. --***************************************************************************/
  995. PVOID
  996. UlAllocateInternalRequestPool(
  997. IN POOL_TYPE PoolType,
  998. IN SIZE_T ByteLength,
  999. IN ULONG Tag
  1000. )
  1001. {
  1002. PUL_INTERNAL_REQUEST pRequest;
  1003. PUL_FULL_TRACKER pTracker;
  1004. ULONG SpaceLength;
  1005. ULONG UrlBufferSize;
  1006. UNREFERENCED_PARAMETER(PoolType);
  1007. UNREFERENCED_PARAMETER(ByteLength);
  1008. UNREFERENCED_PARAMETER(Tag);
  1009. //
  1010. // Sanity check.
  1011. //
  1012. ASSERT( PoolType == NonPagedPool );
  1013. ASSERT( ByteLength == sizeof(UL_INTERNAL_REQUEST) );
  1014. ASSERT( Tag == UL_INTERNAL_REQUEST_POOL_TAG );
  1015. //
  1016. // Allocate the request buffer plus the default cooked URL buffer and
  1017. // the full tracker plus the auxiliary buffer.
  1018. //
  1019. ASSERT( (g_UlMaxInternalUrlLength & (sizeof(WCHAR) - 1)) == 0);
  1020. UrlBufferSize = g_UlMaxInternalUrlLength + sizeof(WCHAR);
  1021. SpaceLength = g_UlFullTrackerSize + UrlBufferSize +
  1022. DEFAULT_MAX_ROUTING_TOKEN_LENGTH;
  1023. pRequest = UL_ALLOCATE_STRUCT_WITH_SPACE(
  1024. NonPagedPool,
  1025. UL_INTERNAL_REQUEST,
  1026. SpaceLength,
  1027. UL_INTERNAL_REQUEST_POOL_TAG
  1028. );
  1029. if (pRequest != NULL)
  1030. {
  1031. pRequest->pTracker =
  1032. (PUL_FULL_TRACKER)((PCHAR)pRequest +
  1033. ALIGN_UP(sizeof(UL_INTERNAL_REQUEST), PVOID));
  1034. pRequest->pUrlBuffer =
  1035. (PWSTR)((PCHAR)pRequest->pTracker + g_UlFullTrackerSize);
  1036. pRequest->pDefaultRoutingTokenBuffer =
  1037. (PWSTR)((PCHAR)pRequest->pUrlBuffer + UrlBufferSize);
  1038. //
  1039. // Initialize the Request structure
  1040. //
  1041. INIT_HTTP_REQUEST( pRequest );
  1042. pRequest->Signature = MAKE_FREE_TAG(UL_INTERNAL_REQUEST_POOL_TAG);
  1043. //
  1044. // Initialize the fast/cache tracker.
  1045. //
  1046. pTracker = pRequest->pTracker;
  1047. pTracker->Signature = UL_FULL_TRACKER_POOL_TAG;
  1048. pTracker->IrpContext.Signature = UL_IRP_CONTEXT_SIGNATURE;
  1049. pTracker->FromLookaside = FALSE;
  1050. pTracker->FromRequest = TRUE;
  1051. pTracker->ResponseStatusCode = 0;
  1052. pTracker->AuxilaryBufferLength =
  1053. g_UlMaxFixedHeaderSize +
  1054. g_UlMaxVariableHeaderSize +
  1055. g_UlMaxCopyThreshold;
  1056. UlInitializeFullTrackerPool( pTracker, DEFAULT_MAX_IRP_STACK_SIZE );
  1057. }
  1058. return (PVOID)pRequest;
  1059. } // UlAllocateInternalRequestPool
  1060. /***************************************************************************++
  1061. Routine Description:
  1062. Frees the pool allocated for a UL_INTERNAL_REQUEST structure.
  1063. Arguments:
  1064. pBuffer - Supplies the buffer to free.
  1065. --***************************************************************************/
  1066. VOID
  1067. UlFreeInternalRequestPool(
  1068. IN PVOID pBuffer
  1069. )
  1070. {
  1071. PUL_INTERNAL_REQUEST pRequest;
  1072. pRequest = (PUL_INTERNAL_REQUEST)pBuffer;
  1073. ASSERT(pRequest->Signature == MAKE_FREE_TAG(UL_INTERNAL_REQUEST_POOL_TAG));
  1074. UL_FREE_POOL_WITH_SIG( pRequest, UL_INTERNAL_REQUEST_POOL_TAG );
  1075. } // UlFreeInternalRequestPool
  1076. /***************************************************************************++
  1077. Routine Description:
  1078. Allocates the pool necessary for a new UL_CHUNK_TRACKER structure and
  1079. initializes the structure.
  1080. Arguments:
  1081. PoolType - Supplies the type of pool to allocate. This must always
  1082. be NonPagedPool.
  1083. ByteLength - Supplies the byte length for the allocation request.
  1084. This should be g_UlChunkTrackerSize but is basically ignored.
  1085. Tag - Supplies the tag to use for the pool. This should be
  1086. UL_CHUNK_TRACKER_POOL_TAG, but is basically ignored.
  1087. Note: These parameters are required so that this function has a
  1088. signature identical to ExAllocatePoolWithTag.
  1089. Return Value:
  1090. PVOID - Pointer to the newly allocated block if successful, FALSE
  1091. otherwise.
  1092. --***************************************************************************/
  1093. PVOID
  1094. UlAllocateChunkTrackerPool(
  1095. IN POOL_TYPE PoolType,
  1096. IN SIZE_T ByteLength,
  1097. IN ULONG Tag
  1098. )
  1099. {
  1100. PUL_CHUNK_TRACKER pTracker;
  1101. UNREFERENCED_PARAMETER(PoolType);
  1102. UNREFERENCED_PARAMETER(ByteLength);
  1103. UNREFERENCED_PARAMETER(Tag);
  1104. //
  1105. // Sanity check.
  1106. //
  1107. ASSERT( PoolType == NonPagedPool );
  1108. ASSERT( ByteLength == g_UlChunkTrackerSize );
  1109. ASSERT( Tag == UL_CHUNK_TRACKER_POOL_TAG );
  1110. //
  1111. // Allocate the tracker buffer.
  1112. //
  1113. pTracker = (PUL_CHUNK_TRACKER)UL_ALLOCATE_POOL(
  1114. NonPagedPool,
  1115. g_UlChunkTrackerSize,
  1116. UL_CHUNK_TRACKER_POOL_TAG
  1117. );
  1118. if (pTracker != NULL)
  1119. {
  1120. pTracker->Signature = MAKE_FREE_TAG(UL_CHUNK_TRACKER_POOL_TAG);
  1121. pTracker->IrpContext.Signature = UL_IRP_CONTEXT_SIGNATURE;
  1122. pTracker->FromLookaside = TRUE;
  1123. //
  1124. // Set up the IRP.
  1125. //
  1126. pTracker->pIrp =
  1127. (PIRP)((PCHAR)pTracker +
  1128. ALIGN_UP(sizeof(UL_CHUNK_TRACKER), PVOID));
  1129. IoInitializeIrp(
  1130. pTracker->pIrp,
  1131. IoSizeOfIrp(DEFAULT_MAX_IRP_STACK_SIZE),
  1132. DEFAULT_MAX_IRP_STACK_SIZE
  1133. );
  1134. }
  1135. return pTracker;
  1136. } // UlAllocateChunkTrackerPool
  1137. /***************************************************************************++
  1138. Routine Description:
  1139. Frees the pool allocated for a UL_CHUNK_TRACKER structure.
  1140. Arguments:
  1141. pBuffer - Supplies the buffer to free.
  1142. --***************************************************************************/
  1143. VOID
  1144. UlFreeChunkTrackerPool(
  1145. IN PVOID pBuffer
  1146. )
  1147. {
  1148. PUL_CHUNK_TRACKER pTracker = (PUL_CHUNK_TRACKER)pBuffer;
  1149. ASSERT(pTracker->Signature == MAKE_FREE_TAG(UL_CHUNK_TRACKER_POOL_TAG));
  1150. UL_FREE_POOL_WITH_SIG( pTracker, UL_CHUNK_TRACKER_POOL_TAG );
  1151. } // UlFreeChunkTrackerPool
  1152. /***************************************************************************++
  1153. Routine Description:
  1154. Allocates the pool necessary for a new UL_FULL_TRACKER structure and
  1155. initializes the structure.
  1156. Arguments:
  1157. PoolType - Supplies the type of pool to allocate. This must always
  1158. be NonPagedPool.
  1159. ByteLength - Supplies the byte length for the allocation request.
  1160. This should be g_UlFullTrackerSize but is basically ignored.
  1161. Tag - Supplies the tag to use for the pool. This should be
  1162. UL_FULL_TRACKER_POOL_TAG, but is basically ignored.
  1163. Note: These parameters are required so that this function has a
  1164. signature identical to ExAllocatePoolWithTag.
  1165. Return Value:
  1166. PVOID - Pointer to the newly allocated block if successful, FALSE
  1167. otherwise.
  1168. --***************************************************************************/
  1169. PVOID
  1170. UlAllocateFullTrackerPool(
  1171. IN POOL_TYPE PoolType,
  1172. IN SIZE_T ByteLength,
  1173. IN ULONG Tag
  1174. )
  1175. {
  1176. PUL_FULL_TRACKER pTracker;
  1177. UNREFERENCED_PARAMETER(PoolType);
  1178. UNREFERENCED_PARAMETER(ByteLength);
  1179. UNREFERENCED_PARAMETER(Tag);
  1180. //
  1181. // Sanity check.
  1182. //
  1183. ASSERT( PoolType == NonPagedPool );
  1184. ASSERT( ByteLength == g_UlFullTrackerSize );
  1185. ASSERT( Tag == UL_FULL_TRACKER_POOL_TAG );
  1186. //
  1187. // Allocate the tracker buffer.
  1188. //
  1189. pTracker = (PUL_FULL_TRACKER)UL_ALLOCATE_POOL(
  1190. NonPagedPool,
  1191. g_UlFullTrackerSize,
  1192. UL_FULL_TRACKER_POOL_TAG
  1193. );
  1194. if (pTracker != NULL)
  1195. {
  1196. pTracker->Signature = MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG);
  1197. pTracker->IrpContext.Signature = UL_IRP_CONTEXT_SIGNATURE;
  1198. pTracker->FromLookaside = TRUE;
  1199. pTracker->FromRequest = FALSE;
  1200. pTracker->AuxilaryBufferLength =
  1201. g_UlMaxFixedHeaderSize +
  1202. g_UlMaxVariableHeaderSize +
  1203. g_UlMaxCopyThreshold;
  1204. UlInitializeFullTrackerPool( pTracker, DEFAULT_MAX_IRP_STACK_SIZE );
  1205. }
  1206. return pTracker;
  1207. } // UlAllocateFullTrackerPool
  1208. /***************************************************************************++
  1209. Routine Description:
  1210. Frees the pool allocated for a UL_FULL_TRACKER structure.
  1211. Arguments:
  1212. pBuffer - Supplies the buffer to free.
  1213. --***************************************************************************/
  1214. VOID
  1215. UlFreeFullTrackerPool(
  1216. IN PVOID pBuffer
  1217. )
  1218. {
  1219. PUL_FULL_TRACKER pTracker = (PUL_FULL_TRACKER)pBuffer;
  1220. ASSERT(pTracker->Signature == MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG));
  1221. UL_FREE_POOL_WITH_SIG( pTracker, UL_FULL_TRACKER_POOL_TAG );
  1222. } // UlFreeFullTrackerPool
  1223. /***************************************************************************++
  1224. Routine Description:
  1225. Allocates the pool necessary for a new UL_INTERNAL_RESPONSE structure and
  1226. initializes the structure.
  1227. Arguments:
  1228. PoolType - Supplies the type of pool to allocate. This must always
  1229. be NonPagedPool.
  1230. ByteLength - Supplies the byte length for the allocation request.
  1231. This should be g_UlResponseBufferSize but is basically ignored.
  1232. Tag - Supplies the tag to use for the pool. This should be
  1233. UL_INTERNAL_RESPONSE_POOL_TAG, but is basically ignored.
  1234. Note: These parameters are required so that this function has a
  1235. signature identical to ExAllocatePoolWithTag.
  1236. Return Value:
  1237. PVOID - Pointer to the newly allocated block if successful, FALSE
  1238. otherwise.
  1239. --***************************************************************************/
  1240. PVOID
  1241. UlAllocateResponseBufferPool(
  1242. IN POOL_TYPE PoolType,
  1243. IN SIZE_T ByteLength,
  1244. IN ULONG Tag
  1245. )
  1246. {
  1247. PUL_INTERNAL_RESPONSE pResponseBuffer;
  1248. UNREFERENCED_PARAMETER(PoolType);
  1249. UNREFERENCED_PARAMETER(ByteLength);
  1250. UNREFERENCED_PARAMETER(Tag);
  1251. //
  1252. // Sanity check.
  1253. //
  1254. ASSERT( PoolType == NonPagedPool );
  1255. ASSERT( ByteLength == g_UlResponseBufferSize );
  1256. ASSERT( Tag == UL_INTERNAL_RESPONSE_POOL_TAG );
  1257. //
  1258. // Allocate the default internal response buffer.
  1259. //
  1260. pResponseBuffer = (PUL_INTERNAL_RESPONSE)UL_ALLOCATE_POOL(
  1261. NonPagedPool,
  1262. g_UlResponseBufferSize,
  1263. UL_INTERNAL_RESPONSE_POOL_TAG
  1264. );
  1265. if (pResponseBuffer != NULL)
  1266. {
  1267. //
  1268. // Initialize it.
  1269. //
  1270. pResponseBuffer->Signature = MAKE_FREE_TAG(UL_INTERNAL_RESPONSE_POOL_TAG);
  1271. }
  1272. return (PVOID)pResponseBuffer;
  1273. } // UlAllocateResponseBufferPool
  1274. /***************************************************************************++
  1275. Routine Description:
  1276. Frees the pool allocated for a UL_INTERNAL_RESPONSE structure.
  1277. Arguments:
  1278. pBuffer - Supplies the buffer to free.
  1279. --***************************************************************************/
  1280. VOID
  1281. UlFreeResponseBufferPool(
  1282. IN PVOID pBuffer
  1283. )
  1284. {
  1285. PUL_INTERNAL_RESPONSE pResponseBuffer;
  1286. pResponseBuffer = (PUL_INTERNAL_RESPONSE)pBuffer;
  1287. UL_FREE_POOL_WITH_SIG( pResponseBuffer, UL_INTERNAL_RESPONSE_POOL_TAG );
  1288. } // UlFreeResponseBufferPool
  1289. /***************************************************************************++
  1290. Routine Description:
  1291. Allocates the pool necessary for a new UL_FILE_LOG_BUFFER structure and
  1292. initializes the structure.
  1293. Arguments:
  1294. PoolType - Supplies the type of pool to allocate. This must always
  1295. be PagedPool.
  1296. ByteLength - Supplies the byte length for the allocation request.
  1297. This should be sizeof(UL_LOG_FILE_BUFFER) but is basically ignored.
  1298. Tag - Supplies the tag to use for the pool. This should be
  1299. UL_LOG_FILE_BUFFER_POOL_TAG, but is basically ignored.
  1300. Note: These parameters are required so that this function has a
  1301. signature identical to ExAllocatePoolWithTag.
  1302. Return Value:
  1303. PVOID - Pointer to the newly allocated block if successful, FALSE
  1304. otherwise.
  1305. --***************************************************************************/
  1306. PVOID
  1307. UlAllocateLogFileBufferPool(
  1308. IN POOL_TYPE PoolType,
  1309. IN SIZE_T ByteLength,
  1310. IN ULONG Tag
  1311. )
  1312. {
  1313. PUL_LOG_FILE_BUFFER pLogBuffer;
  1314. UNREFERENCED_PARAMETER(PoolType);
  1315. UNREFERENCED_PARAMETER(ByteLength);
  1316. UNREFERENCED_PARAMETER(Tag);
  1317. //
  1318. // Sanity check.
  1319. //
  1320. ASSERT( PoolType == NonPagedPool );
  1321. ASSERT( ByteLength == sizeof(UL_LOG_FILE_BUFFER) );
  1322. ASSERT( Tag == UL_LOG_FILE_BUFFER_POOL_TAG );
  1323. //
  1324. // Allocate the default log buffer.
  1325. //
  1326. pLogBuffer = UL_ALLOCATE_STRUCT_WITH_SPACE(
  1327. PagedPool,
  1328. UL_LOG_FILE_BUFFER,
  1329. g_UlLogBufferSize,
  1330. UL_LOG_FILE_BUFFER_POOL_TAG
  1331. );
  1332. if ( pLogBuffer != NULL )
  1333. {
  1334. pLogBuffer->Signature = MAKE_FREE_TAG(UL_LOG_FILE_BUFFER_POOL_TAG);
  1335. pLogBuffer->BufferUsed = 0;
  1336. pLogBuffer->Buffer = (PUCHAR) (pLogBuffer + 1);
  1337. }
  1338. return pLogBuffer;
  1339. } // UlAllocateLogFileBufferPool
  1340. /***************************************************************************++
  1341. Routine Description:
  1342. Frees the pool allocated for a UL_LOG_FILE_BUFFER structure.
  1343. Arguments:
  1344. pBuffer - Supplies the buffer to free.
  1345. --***************************************************************************/
  1346. VOID
  1347. UlFreeLogFileBufferPool(
  1348. IN PVOID pBuffer
  1349. )
  1350. {
  1351. PUL_LOG_FILE_BUFFER pLogBuffer;
  1352. pLogBuffer = (PUL_LOG_FILE_BUFFER) pBuffer;
  1353. ASSERT(pLogBuffer->Signature == MAKE_FREE_TAG(UL_LOG_FILE_BUFFER_POOL_TAG));
  1354. UL_FREE_POOL_WITH_SIG( pLogBuffer, UL_LOG_FILE_BUFFER_POOL_TAG );
  1355. } // UlFreeLogFileBufferPool
  1356. /***************************************************************************++
  1357. Routine Description:
  1358. Allocates the pool necessary for a new UL_FILE_LOG_BUFFER structure and
  1359. initializes the structure.
  1360. Return Value:
  1361. PVOID - Pointer to the newly allocated block if successful, FALSE
  1362. otherwise.
  1363. --***************************************************************************/
  1364. PVOID
  1365. UlAllocateLogDataBufferPool(
  1366. IN POOL_TYPE PoolType,
  1367. IN SIZE_T ByteLength,
  1368. IN ULONG Tag
  1369. )
  1370. {
  1371. PUL_LOG_DATA_BUFFER pLogDataBuffer = NULL;
  1372. USHORT Size = UL_ANSI_LOG_LINE_BUFFER_SIZE;
  1373. BOOLEAN Binary = FALSE;
  1374. UNREFERENCED_PARAMETER(PoolType);
  1375. UNREFERENCED_PARAMETER(ByteLength);
  1376. //
  1377. // We understand what type of buffer is asked, by looking at the tag.
  1378. //
  1379. ASSERT(ByteLength ==
  1380. (sizeof(UL_LOG_DATA_BUFFER) + UL_ANSI_LOG_LINE_BUFFER_SIZE) ||
  1381. ByteLength ==
  1382. (sizeof(UL_LOG_DATA_BUFFER) + UL_BINARY_LOG_LINE_BUFFER_SIZE)
  1383. );
  1384. ASSERT(PoolType == NonPagedPool );
  1385. ASSERT(Tag == UL_BINARY_LOG_DATA_BUFFER_POOL_TAG ||
  1386. Tag == UL_ANSI_LOG_DATA_BUFFER_POOL_TAG );
  1387. if (Tag == UL_BINARY_LOG_DATA_BUFFER_POOL_TAG)
  1388. {
  1389. Binary = TRUE;
  1390. Size = UL_BINARY_LOG_LINE_BUFFER_SIZE;
  1391. }
  1392. pLogDataBuffer =
  1393. UL_ALLOCATE_STRUCT_WITH_SPACE(
  1394. NonPagedPool,
  1395. UL_LOG_DATA_BUFFER,
  1396. Size,
  1397. Tag
  1398. );
  1399. if ( pLogDataBuffer != NULL )
  1400. {
  1401. pLogDataBuffer->Signature = MAKE_FREE_TAG(Tag);
  1402. pLogDataBuffer->Used = 0;
  1403. pLogDataBuffer->Size = Size;
  1404. pLogDataBuffer->Line = (PUCHAR) (pLogDataBuffer + 1);
  1405. pLogDataBuffer->Flags.Value = 0;
  1406. pLogDataBuffer->Flags.IsFromLookaside = 1;
  1407. if (Binary)
  1408. {
  1409. pLogDataBuffer->Flags.Binary = 1;
  1410. }
  1411. }
  1412. return pLogDataBuffer;
  1413. } // UlAllocateBinaryLogDataBufferPool
  1414. /***************************************************************************++
  1415. Routine Description:
  1416. Frees the pool allocated for a UL_LOG_DATA_BUFFER structure.
  1417. Arguments:
  1418. pBuffer - Supplies the buffer to free.
  1419. --***************************************************************************/
  1420. VOID
  1421. UlFreeLogDataBufferPool(
  1422. IN PVOID pBuffer
  1423. )
  1424. {
  1425. ULONG Tag;
  1426. PUL_LOG_DATA_BUFFER pLogDataBuffer;
  1427. pLogDataBuffer = (PUL_LOG_DATA_BUFFER) pBuffer;
  1428. if (pLogDataBuffer->Flags.Binary)
  1429. {
  1430. Tag = UL_BINARY_LOG_DATA_BUFFER_POOL_TAG;
  1431. }
  1432. else
  1433. {
  1434. Tag = UL_ANSI_LOG_DATA_BUFFER_POOL_TAG;
  1435. }
  1436. ASSERT(pLogDataBuffer->Signature == MAKE_FREE_TAG(Tag));
  1437. UL_FREE_POOL_WITH_SIG(
  1438. pLogDataBuffer,
  1439. Tag
  1440. );
  1441. } // UlFreeLogDataBufferPool
  1442. /***************************************************************************++
  1443. Routine Description:
  1444. Allocates the pool necessary for a new UL_ERROR_LOG_BUFFER structure and
  1445. initializes the structure.
  1446. Return Value:
  1447. PVOID - Pointer to the newly allocated block if successful, FALSE
  1448. otherwise.
  1449. --***************************************************************************/
  1450. PVOID
  1451. UlAllocateErrorLogBufferPool(
  1452. IN POOL_TYPE PoolType,
  1453. IN SIZE_T ByteLength,
  1454. IN ULONG Tag
  1455. )
  1456. {
  1457. PUL_ERROR_LOG_BUFFER pErrorLogBuffer = NULL;
  1458. UNREFERENCED_PARAMETER(PoolType);
  1459. UNREFERENCED_PARAMETER(ByteLength);
  1460. //
  1461. // We understand what type of buffer is asked, by looking at the tag.
  1462. //
  1463. ASSERT(ByteLength == UL_ERROR_LOG_BUFFER_SIZE);
  1464. ASSERT(PoolType == NonPagedPool );
  1465. ASSERT(Tag == UL_ERROR_LOG_BUFFER_POOL_TAG);
  1466. pErrorLogBuffer =
  1467. UL_ALLOCATE_STRUCT_WITH_SPACE(
  1468. NonPagedPool,
  1469. UL_ERROR_LOG_BUFFER,
  1470. UL_ERROR_LOG_BUFFER_SIZE,
  1471. Tag
  1472. );
  1473. if ( pErrorLogBuffer != NULL )
  1474. {
  1475. pErrorLogBuffer->Signature = MAKE_FREE_TAG(Tag);
  1476. pErrorLogBuffer->Used = 0;
  1477. pErrorLogBuffer->pBuffer = (PUCHAR) (pErrorLogBuffer + 1);
  1478. pErrorLogBuffer->IsFromLookaside = TRUE;
  1479. }
  1480. return pErrorLogBuffer;
  1481. } // UlAllocateErrorLogBufferPool
  1482. /***************************************************************************++
  1483. Routine Description:
  1484. Frees the pool allocated for a UL_ERROR_LOG_BUFFER structure.
  1485. Arguments:
  1486. pBuffer - Supplies the buffer to free.
  1487. --***************************************************************************/
  1488. VOID
  1489. UlFreeErrorLogBufferPool(
  1490. IN PVOID pBuffer
  1491. )
  1492. {
  1493. PUL_ERROR_LOG_BUFFER pErrorLogBuffer = (PUL_ERROR_LOG_BUFFER) pBuffer;
  1494. ASSERT(pErrorLogBuffer->Signature ==
  1495. MAKE_FREE_TAG(UL_ERROR_LOG_BUFFER_POOL_TAG));
  1496. UL_FREE_POOL_WITH_SIG(
  1497. pErrorLogBuffer,
  1498. UL_ERROR_LOG_BUFFER_POOL_TAG
  1499. );
  1500. } // UlFreeErrorLogBufferPool
  1501. //
  1502. // Private routines.
  1503. //
  1504. /***************************************************************************++
  1505. Routine Description:
  1506. Completion handler for device control IRPs.
  1507. Arguments:
  1508. pDeviceObject - Supplies the device object for the IRP being
  1509. completed.
  1510. pIrp - Supplies the IRP being completed.
  1511. pContext - Supplies the context associated with this request. In
  1512. this case, it's a pointer to a UL_STATUS_BLOCK structure.
  1513. Return Value:
  1514. NTSTATUS - STATUS_SUCCESS if IO should continue processing this
  1515. IRP, STATUS_MORE_PROCESSING_REQUIRED if IO should stop processing
  1516. this IRP.
  1517. --***************************************************************************/
  1518. NTSTATUS
  1519. UlpRestartDeviceControl(
  1520. IN PDEVICE_OBJECT pDeviceObject,
  1521. IN PIRP pIrp,
  1522. IN PVOID pContext
  1523. )
  1524. {
  1525. PUL_STATUS_BLOCK pStatus;
  1526. UNREFERENCED_PARAMETER(pDeviceObject);
  1527. //
  1528. // If we attached an MDL to the IRP, then free it here and reset
  1529. // the MDL pointer to NULL. IO can't handle a nonpaged MDL in an
  1530. // IRP, so we do it here.
  1531. //
  1532. if (pIrp->MdlAddress != NULL)
  1533. {
  1534. UlFreeMdl( pIrp->MdlAddress );
  1535. pIrp->MdlAddress = NULL;
  1536. }
  1537. //
  1538. // Complete the request.
  1539. //
  1540. pStatus = (PUL_STATUS_BLOCK)pContext;
  1541. UlSignalStatusBlock(
  1542. pStatus,
  1543. pIrp->IoStatus.Status,
  1544. pIrp->IoStatus.Information
  1545. );
  1546. //
  1547. // Tell IO to continue processing this IRP.
  1548. //
  1549. return STATUS_SUCCESS;
  1550. } // UlpRestartDeviceControl
  1551. /*++
  1552. Routine Description:
  1553. Routine to initialize the utilitu code.
  1554. Arguments:
  1555. Return Value:
  1556. --*/
  1557. NTSTATUS
  1558. InitializeHttpUtil(
  1559. VOID
  1560. )
  1561. {
  1562. ULONG i;
  1563. HttpCmnInitializeHttpCharsTable(g_UrlC14nConfig.EnableDbcs);
  1564. //
  1565. // Initialize base64 <--> binary conversion tables.
  1566. // N.B. - This initialization must be done at run-time and not
  1567. // compile-time.
  1568. //
  1569. for (i = 0; i < 256; i++)
  1570. {
  1571. Base64ToBinaryTable[i] = INVALID_BASE64_TO_BINARY_TABLE_ENTRY;
  1572. }
  1573. for (i = 0; i < 64; i++)
  1574. {
  1575. ASSERT(BinaryToBase64Table[i] < 256);
  1576. Base64ToBinaryTable[BinaryToBase64Table[i]] = (UCHAR)i;
  1577. }
  1578. return STATUS_SUCCESS;
  1579. } // InitializeHttpUtil
  1580. //
  1581. // constants used by the date formatter
  1582. //
  1583. const PCWSTR pDays[] =
  1584. {
  1585. L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
  1586. };
  1587. const PCWSTR pMonths[] =
  1588. {
  1589. L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul",
  1590. L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
  1591. };
  1592. __inline
  1593. VOID
  1594. TwoDigitsToUnicode(
  1595. PWSTR pBuffer,
  1596. ULONG Number
  1597. )
  1598. {
  1599. ASSERT(Number < 100);
  1600. pBuffer[0] = L'0' + (WCHAR)(Number / 10);
  1601. pBuffer[1] = L'0' + (WCHAR)(Number % 10);
  1602. }
  1603. /***************************************************************************++
  1604. Routine Description:
  1605. Converts the given system time to string representation containing
  1606. GMT Formatted String.
  1607. Arguments:
  1608. pTime - System time that needs to be converted.
  1609. pBuffer - pointer to string which will contain the GMT time on
  1610. successful return.
  1611. BufferLength - size of pszBuff in bytes
  1612. Return Value:
  1613. NTSTATUS
  1614. History:
  1615. MuraliK 3-Jan-1995
  1616. paulmcd 4-Mar-1999 copied to ul
  1617. --***************************************************************************/
  1618. NTSTATUS
  1619. TimeFieldsToHttpDate(
  1620. IN PTIME_FIELDS pTime,
  1621. OUT PWSTR pBuffer,
  1622. IN ULONG BufferLength
  1623. )
  1624. {
  1625. NTSTATUS Status;
  1626. ASSERT(pBuffer != NULL);
  1627. if (BufferLength < (DATE_HDR_LENGTH + 1) * sizeof(WCHAR))
  1628. {
  1629. return STATUS_BUFFER_TOO_SMALL;
  1630. }
  1631. // 0 1 2
  1632. // 01234567890123456789012345678
  1633. // Formats a string like: "Thu, 14 Jul 1994 15:26:05 GMT"
  1634. //
  1635. //
  1636. // write the constants
  1637. //
  1638. pBuffer[3] = L',';
  1639. pBuffer[4] = pBuffer[7] = pBuffer[11] = L' ';
  1640. pBuffer[19] = pBuffer[22] = L':';
  1641. //
  1642. // now the variants
  1643. //
  1644. //
  1645. // 0-based Weekday
  1646. //
  1647. RtlCopyMemory(&(pBuffer[0]), pDays[pTime->Weekday], 3*sizeof(WCHAR));
  1648. TwoDigitsToUnicode(&(pBuffer[5]), pTime->Day);
  1649. //
  1650. // 1-based Month
  1651. //
  1652. RtlCopyMemory(&(pBuffer[8]), pMonths[pTime->Month - 1], 3*sizeof(WCHAR)); // 1-based
  1653. Status = _RtlIntegerToUnicode(pTime->Year, 10, 5, &(pBuffer[12]));
  1654. ASSERT(NT_SUCCESS(Status));
  1655. pBuffer[16] = L' ';
  1656. TwoDigitsToUnicode(&(pBuffer[17]), pTime->Hour);
  1657. TwoDigitsToUnicode(&(pBuffer[20]), pTime->Minute);
  1658. TwoDigitsToUnicode(&(pBuffer[23]), pTime->Second);
  1659. RtlCopyMemory(&(pBuffer[25]), L" GMT", sizeof(L" GMT"));
  1660. return STATUS_SUCCESS;
  1661. } // TimeFieldsToHttpDate
  1662. __inline
  1663. SHORT
  1664. AsciiToShort(
  1665. PCHAR pString
  1666. )
  1667. {
  1668. return (SHORT)atoi(pString);
  1669. }
  1670. __inline
  1671. SHORT
  1672. TwoAsciisToShort(
  1673. PCHAR pString
  1674. )
  1675. {
  1676. SHORT Value;
  1677. SHORT Number;
  1678. Number = pString[1] - '0';
  1679. if (Number <= 9)
  1680. {
  1681. Value = Number;
  1682. Number = pString[0] - '0';
  1683. if (Number <= 9)
  1684. {
  1685. Value += Number * 10;
  1686. return Value;
  1687. }
  1688. }
  1689. return 0;
  1690. }
  1691. /***************************************************************************++
  1692. DateTime function ported from user mode W3SVC
  1693. --***************************************************************************/
  1694. /************************************************************
  1695. * Data
  1696. ************************************************************/
  1697. static const PSTR s_rgchMonths[] = {
  1698. "Jan", "Feb", "Mar", "Apr",
  1699. "May", "Jun", "Jul", "Aug",
  1700. "Sep", "Oct", "Nov", "Dec"
  1701. };
  1702. // Custom hash table for NumericToAsciiMonth() for mapping "Apr" to 4
  1703. static const CHAR MonthIndexTable[64] = {
  1704. -1,'A', 2, 12, -1, -1, -1, 8, // A to G
  1705. -1, -1, -1, -1, 7, -1,'N', -1, // F to O
  1706. 9, -1,'R', -1, 10, -1, 11, -1, // P to W
  1707. -1, 5, -1, -1, -1, -1, -1, -1, // X to Z
  1708. -1,'A', 2, 12, -1, -1, -1, 8, // a to g
  1709. -1, -1, -1, -1, 7, -1,'N', -1, // f to o
  1710. 9, -1,'R', -1, 10, -1, 11, -1, // p to w
  1711. -1, 5, -1, -1, -1, -1, -1, -1 // x to z
  1712. };
  1713. /************************************************************
  1714. * Functions
  1715. ************************************************************/
  1716. /***************************************************************************++
  1717. Converts three letters of a month to numeric month
  1718. Arguments:
  1719. s String to convert
  1720. Returns:
  1721. numeric equivalent, 0 on failure.
  1722. --***************************************************************************/
  1723. __inline
  1724. SHORT
  1725. NumericToAsciiMonth(
  1726. PCHAR s
  1727. )
  1728. {
  1729. UCHAR monthIndex;
  1730. UCHAR c;
  1731. PSTR monthString;
  1732. //
  1733. // use the third character as the index
  1734. //
  1735. c = (s[2] - 0x40) & 0x3F;
  1736. monthIndex = MonthIndexTable[c];
  1737. if ( monthIndex < 13 ) {
  1738. goto verify;
  1739. }
  1740. //
  1741. // ok, we need to look at the second character
  1742. //
  1743. if ( monthIndex == 'N' ) {
  1744. //
  1745. // we got an N which we need to resolve further
  1746. //
  1747. //
  1748. // if s[1] is 'u' then Jun, if 'a' then Jan
  1749. //
  1750. if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
  1751. monthIndex = 1;
  1752. } else {
  1753. monthIndex = 6;
  1754. }
  1755. } else if ( monthIndex == 'R' ) {
  1756. //
  1757. // if s[1] is 'a' then March, if 'p' then April
  1758. //
  1759. if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
  1760. monthIndex = 3;
  1761. } else {
  1762. monthIndex = 4;
  1763. }
  1764. } else {
  1765. goto error_exit;
  1766. }
  1767. verify:
  1768. monthString = (PSTR) s_rgchMonths[monthIndex-1];
  1769. if ( (s[0] == monthString[0]) &&
  1770. (s[1] == monthString[1]) &&
  1771. (s[2] == monthString[2]) ) {
  1772. return(monthIndex);
  1773. } else if ( (toupper(s[0]) == monthString[0]) &&
  1774. (tolower(s[1]) == monthString[1]) &&
  1775. (tolower(s[2]) == monthString[2]) ) {
  1776. return monthIndex;
  1777. }
  1778. error_exit:
  1779. return(0);
  1780. } // NumericToAsciiMonth
  1781. /***************************************************************************++
  1782. Converts a string representation of a GMT time (three different
  1783. varieties) to an NT representation of a file time.
  1784. We handle the following variations:
  1785. Sun, 06 Nov 1994 08:49:37 GMT (RFC 822 updated by RFC 1123)
  1786. Sunday, 06-Nov-94 08:49:37 GMT (RFC 850)
  1787. Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format)
  1788. Arguments:
  1789. pTimeString String representation of time field
  1790. TimeStringLength Length of the string representation of time field
  1791. pTime Large integer containing the time in NT format
  1792. Returns:
  1793. TRUE on success and FALSE on failure.
  1794. History:
  1795. Johnl 24-Jan-1995 Modified from WWW library
  1796. ericsten 30-Nov-2000 Ported from user-mode W3SVC
  1797. --***************************************************************************/
  1798. BOOLEAN
  1799. StringTimeToSystemTime(
  1800. IN PCSTR pTimeString,
  1801. IN USHORT TimeStringLength,
  1802. OUT LARGE_INTEGER *pTime
  1803. )
  1804. {
  1805. PSTR pString;
  1806. TIME_FIELDS Fields;
  1807. USHORT Length;
  1808. if (NULL == pTimeString)
  1809. {
  1810. return FALSE;
  1811. }
  1812. Fields.Milliseconds = 0;
  1813. Length = 0;
  1814. while (Length < TimeStringLength && ',' != pTimeString[Length])
  1815. {
  1816. Length++;
  1817. }
  1818. if (Length < TimeStringLength)
  1819. {
  1820. //
  1821. // Thursday, 10-Jun-93 01:29:59 GMT
  1822. // or: Thu, 10 Jan 1993 01:29:59 GMT
  1823. //
  1824. Length++;
  1825. pString = (PSTR) &pTimeString[Length];
  1826. while (Length < TimeStringLength && ' ' == *pString)
  1827. {
  1828. Length++;
  1829. pString++;
  1830. }
  1831. if ((TimeStringLength - Length) < 18)
  1832. {
  1833. return FALSE;
  1834. }
  1835. if ('-' == *(pString + 2))
  1836. {
  1837. //
  1838. // First format: Thursday, 10-Jun-93 01:29:59 GMT
  1839. //
  1840. if ('-' == *(pString + 6) &&
  1841. ' ' == *(pString + 9) &&
  1842. ':' == *(pString + 12) &&
  1843. ':' == *(pString + 15))
  1844. {
  1845. Fields.Day = AsciiToShort(pString);
  1846. Fields.Month = NumericToAsciiMonth(pString + 3);
  1847. Fields.Year = AsciiToShort(pString + 7);
  1848. Fields.Hour = AsciiToShort(pString + 10);
  1849. Fields.Minute = AsciiToShort(pString + 13);
  1850. Fields.Second = AsciiToShort(pString + 16);
  1851. }
  1852. else
  1853. {
  1854. return FALSE;
  1855. }
  1856. }
  1857. else
  1858. {
  1859. //
  1860. // Second format: Thu, 10 Jan 1993 01:29:59 GMT
  1861. //
  1862. if ((TimeStringLength - Length) < 20)
  1863. {
  1864. return FALSE;
  1865. }
  1866. if (' ' == *(pString + 2) &&
  1867. ' ' == *(pString + 6) &&
  1868. ' ' == *(pString + 11) &&
  1869. ':' == *(pString + 14) &&
  1870. ':' == *(pString + 17))
  1871. {
  1872. Fields.Day = TwoAsciisToShort(pString);
  1873. Fields.Month = NumericToAsciiMonth(pString + 3);
  1874. Fields.Year = TwoAsciisToShort(pString + 7) * 100 +
  1875. TwoAsciisToShort(pString + 9);
  1876. Fields.Hour = TwoAsciisToShort(pString + 12);
  1877. Fields.Minute = TwoAsciisToShort(pString + 15);
  1878. Fields.Second = TwoAsciisToShort(pString + 18);
  1879. }
  1880. else
  1881. {
  1882. return FALSE;
  1883. }
  1884. }
  1885. }
  1886. else
  1887. {
  1888. //
  1889. // Thu Jun 9 01:29:59 1993 GMT
  1890. //
  1891. Length = 0;
  1892. pString = (PSTR) pTimeString;
  1893. while (Length < TimeStringLength && ' ' == *pString)
  1894. {
  1895. Length++;
  1896. pString++;
  1897. }
  1898. if ((TimeStringLength - Length) < 24)
  1899. {
  1900. return FALSE;
  1901. }
  1902. if (' ' != *(pString + 3) ||
  1903. ' ' != *(pString + 7) ||
  1904. ' ' != *(pString + 10) ||
  1905. ':' != *(pString + 13) ||
  1906. ':' != *(pString + 16))
  1907. {
  1908. return FALSE;
  1909. }
  1910. if (isdigit(*(pString + 8)))
  1911. {
  1912. Fields.Day = AsciiToShort(pString + 8);
  1913. }
  1914. else
  1915. {
  1916. if (' ' != *(pString + 8))
  1917. {
  1918. return FALSE;
  1919. }
  1920. Fields.Day = AsciiToShort(pString + 9);
  1921. }
  1922. Fields.Month = NumericToAsciiMonth(pString + 4);
  1923. Fields.Year = AsciiToShort(pString + 20);
  1924. Fields.Hour = AsciiToShort(pString + 11);
  1925. Fields.Minute = AsciiToShort(pString + 14);
  1926. Fields.Second = AsciiToShort(pString + 17);
  1927. }
  1928. //
  1929. // Adjust for dates with only two digits
  1930. //
  1931. if (Fields.Year < 1000)
  1932. {
  1933. if (Fields.Year < 50)
  1934. {
  1935. Fields.Year += 2000;
  1936. }
  1937. else
  1938. {
  1939. Fields.Year += 1900;
  1940. }
  1941. }
  1942. return RtlTimeFieldsToTime(&Fields, pTime);
  1943. }
  1944. /***************************************************************************++
  1945. End of DateTime function ported from user mode W3SVC
  1946. --***************************************************************************/
  1947. /*++
  1948. Routine Description:
  1949. Search input list of ETags for one that matches our local ETag.
  1950. All strings must be NULL terminated (ANSI C strings).
  1951. Arguments:
  1952. pLocalETag - The local ETag we're using.
  1953. pETagList - The ETag list we've received from the client.
  1954. bWeakCompare - Whether using Weak Comparison is ok
  1955. Returns:
  1956. FIND_ETAG_STATUS value:
  1957. ETAG_FOUND - pLocalETag was found on the list
  1958. ETAG_NOT_FOUND - pLocalETag was NOT found on the list
  1959. ETAG_PARSE_ERROR - one (or more) elements on the list were invalid
  1960. Author:
  1961. Anil Ruia (AnilR) 3-Apr-2000
  1962. History:
  1963. Eric Stenson (EricSten) 6-Dec-2000 ported from user-mode
  1964. --*/
  1965. FIND_ETAG_STATUS
  1966. FindInETagList(
  1967. IN PUCHAR pLocalETag,
  1968. IN PUCHAR pETagList,
  1969. IN BOOLEAN fWeakCompare
  1970. )
  1971. {
  1972. ULONG QuoteCount;
  1973. PUCHAR pFileETag;
  1974. BOOLEAN Matched;
  1975. // We'll loop through the ETag string, looking for ETag to
  1976. // compare, as long as we have an ETag to look at.
  1977. do
  1978. {
  1979. while (IS_HTTP_LWS(*pETagList))
  1980. {
  1981. pETagList++;
  1982. }
  1983. if (!*pETagList)
  1984. {
  1985. // Ran out of ETag.
  1986. return ETAG_NOT_FOUND;
  1987. }
  1988. // If this ETag is *, it's a match.
  1989. if (*pETagList == '*')
  1990. {
  1991. return ETAG_FOUND;
  1992. }
  1993. // See if this ETag is weak.
  1994. if (pETagList[0] == 'W' && pETagList[1] == '/')
  1995. {
  1996. // This is a weak validator. If we're not doing the weak
  1997. // comparison, fail.
  1998. if (!fWeakCompare)
  1999. {
  2000. return ETAG_NOT_FOUND;
  2001. }
  2002. // Skip over the 'W/', and any intervening whitespace.
  2003. pETagList += 2;
  2004. while (IS_HTTP_LWS(*pETagList))
  2005. {
  2006. pETagList++;
  2007. }
  2008. if (!*pETagList)
  2009. {
  2010. // Ran out of ETag.
  2011. return ETAG_PARSE_ERROR;
  2012. }
  2013. }
  2014. if (*pETagList != '"')
  2015. {
  2016. // This isn't a quoted string, so fail.
  2017. return ETAG_PARSE_ERROR;
  2018. }
  2019. // OK, right now we should be at the start of a quoted string that
  2020. // we can compare against our current ETag.
  2021. QuoteCount = 0;
  2022. Matched = TRUE;
  2023. pFileETag = pLocalETag;
  2024. // Do the actual compare. We do this by scanning the current ETag,
  2025. // which is a quoted string. We look for two quotation marks, the
  2026. // the delimiters of the quoted string. If after we find two quotes
  2027. // in the ETag everything has matched, then we've matched this ETag.
  2028. // Otherwise we'll try the next one.
  2029. do
  2030. {
  2031. UCHAR Temp;
  2032. Temp = *pETagList;
  2033. if (IS_HTTP_CTL(Temp))
  2034. {
  2035. return ETAG_PARSE_ERROR;
  2036. }
  2037. if (Temp == '"')
  2038. {
  2039. QuoteCount++;
  2040. }
  2041. if (*pFileETag != Temp)
  2042. {
  2043. Matched = FALSE;
  2044. // at this point, we can skip the current
  2045. // ETag on the list.
  2046. break;
  2047. }
  2048. pETagList++;
  2049. if (*pFileETag == '\0')
  2050. {
  2051. break;
  2052. }
  2053. pFileETag++;
  2054. }
  2055. while (QuoteCount != 2);
  2056. if (Matched)
  2057. {
  2058. return ETAG_FOUND;
  2059. }
  2060. // Otherwise, at this point we need to look at the next ETag.
  2061. while (QuoteCount != 2)
  2062. {
  2063. if (*pETagList == '"')
  2064. {
  2065. QuoteCount++;
  2066. }
  2067. else
  2068. {
  2069. if (IS_HTTP_CTL(*pETagList))
  2070. {
  2071. return ETAG_PARSE_ERROR;
  2072. }
  2073. }
  2074. pETagList++;
  2075. }
  2076. while (IS_HTTP_LWS(*pETagList))
  2077. {
  2078. pETagList++;
  2079. }
  2080. if (*pETagList == ',')
  2081. {
  2082. pETagList++;
  2083. }
  2084. else
  2085. {
  2086. return ETAG_NOT_FOUND;
  2087. }
  2088. } while ( *pETagList );
  2089. return ETAG_NOT_FOUND;
  2090. } // FindInETagList
  2091. /*++
  2092. Routine Description:
  2093. Build a NULL-terminated ANSI string from the IP address
  2094. Arguments:
  2095. IpAddressString - String buffer to place the ANSI string
  2096. (caller allocated)
  2097. TdiAddress - TDI address to be converted
  2098. TdiAddressType - type of address at TdiAddress
  2099. Returns:
  2100. Count of bytes written into IpAddressString.
  2101. Not including the terminating null.
  2102. --*/
  2103. USHORT
  2104. HostAddressAndPortToString(
  2105. OUT PUCHAR IpAddressString,
  2106. IN PVOID TdiAddress,
  2107. IN USHORT TdiAddressType
  2108. )
  2109. {
  2110. PCHAR psz = (PCHAR) IpAddressString;
  2111. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  2112. {
  2113. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) TdiAddress);
  2114. struct in_addr IPv4Addr
  2115. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  2116. USHORT IpPortNum = SWAP_SHORT(pIPv4Address->sin_port);
  2117. psz = RtlIpv4AddressToStringA(&IPv4Addr, psz);
  2118. *psz++ = ':';
  2119. psz = UlStrPrintUlong(psz, IpPortNum, '\0');
  2120. }
  2121. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  2122. {
  2123. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) TdiAddress);
  2124. struct in6_addr IPv6Addr
  2125. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  2126. USHORT IpPortNum = SWAP_SHORT(pIPv6Address->sin6_port);
  2127. *psz++ = '[';
  2128. psz = RtlIpv6AddressToStringA(&IPv6Addr, psz);
  2129. *psz++ = ']';
  2130. *psz++ = ':';
  2131. psz = UlStrPrintUlong(psz, IpPortNum, '\0');
  2132. }
  2133. else
  2134. {
  2135. ASSERT(! "Unexpected TdiAddressType");
  2136. *psz = '\0';
  2137. }
  2138. return DIFF_USHORT(psz - (PCHAR) IpAddressString);
  2139. } // HostAddressAndPortToString
  2140. /****************************************************************************++
  2141. Routine Description:
  2142. Build a NULL terminated UNICODE string from the IP address & port.
  2143. Arguments:
  2144. IpAddressStringW - String buffer to place the UNICODE string
  2145. (caller allocated)
  2146. TdiAddress - TDI address to be converted
  2147. TdiAddressType - type of address at TdiAddress
  2148. Returns:
  2149. Count of bytes written into IpAddressStringW.
  2150. Not including the terminating null.
  2151. --****************************************************************************/
  2152. USHORT
  2153. HostAddressAndPortToStringW(
  2154. PWCHAR IpAddressStringW,
  2155. PVOID TdiAddress,
  2156. USHORT TdiAddressType
  2157. )
  2158. {
  2159. PWCHAR pszW = IpAddressStringW;
  2160. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  2161. {
  2162. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) TdiAddress);
  2163. struct in_addr IPv4Addr
  2164. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  2165. USHORT IpPortNum = SWAP_SHORT(pIPv4Address->sin_port);
  2166. pszW = RtlIpv4AddressToStringW(&IPv4Addr, pszW);
  2167. *pszW++ = L':';
  2168. pszW = UlStrPrintUlongW(pszW, IpPortNum, 0, L'\0');
  2169. }
  2170. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  2171. {
  2172. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) TdiAddress);
  2173. struct in6_addr IPv6Addr
  2174. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  2175. USHORT IpPortNum = SWAP_SHORT(pIPv6Address->sin6_port);
  2176. *pszW++ = L'[';
  2177. pszW = RtlIpv6AddressToStringW(&IPv6Addr, pszW);
  2178. *pszW++ = L']';
  2179. *pszW++ = L':';
  2180. pszW = UlStrPrintUlongW(pszW, IpPortNum, 0, L'\0');
  2181. }
  2182. else
  2183. {
  2184. ASSERT(! "Unexpected TdiAddressType");
  2185. *pszW = L'\0';
  2186. }
  2187. return (DIFF_USHORT(pszW - IpAddressStringW) * sizeof(WCHAR));
  2188. } // HostAddressAndPortToString
  2189. /*++
  2190. Routine Description:
  2191. Build a NULL terminated UNICODE string from the IP address
  2192. Arguments:
  2193. IpAddressStringW - String buffer to place the UNICODE string
  2194. (caller allocated)
  2195. TdiAddress - TDI address to be converted
  2196. TdiAddressType - type of address at TdiAddress
  2197. Returns:
  2198. Count of bytes written into IpAddressStringW.
  2199. Not including the terminating null.
  2200. --*/
  2201. USHORT
  2202. HostAddressToStringW(
  2203. OUT PWCHAR IpAddressStringW,
  2204. IN PVOID TdiAddress,
  2205. IN USHORT TdiAddressType
  2206. )
  2207. {
  2208. PWCHAR pszW = IpAddressStringW;
  2209. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  2210. {
  2211. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) TdiAddress);
  2212. struct in_addr IPv4Addr
  2213. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  2214. pszW = RtlIpv4AddressToStringW(&IPv4Addr, pszW);
  2215. *pszW = L'\0';
  2216. }
  2217. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  2218. {
  2219. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) TdiAddress);
  2220. struct in6_addr IPv6Addr
  2221. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  2222. *pszW++ = L'[';
  2223. pszW = RtlIpv6AddressToStringW(&IPv6Addr, pszW);
  2224. *pszW++ = L']';
  2225. *pszW = L'\0';
  2226. }
  2227. else
  2228. {
  2229. ASSERT(! "Unexpected TdiAddressType");
  2230. *pszW = L'\0';
  2231. }
  2232. return (DIFF_USHORT(pszW - IpAddressStringW) * sizeof(WCHAR));
  2233. } // HostAddressToStringW
  2234. /*++
  2235. Routine Description:
  2236. Build a NULL terminated routing token UNICODE string from
  2237. the IP address and port.
  2238. e.g
  2239. 1.1.1.1:80:1.1.1.1
  2240. Arguments:
  2241. IpAddressStringW - String buffer to place the UNICODE string
  2242. (caller allocated)
  2243. TdiAddress - TDI address to be converted
  2244. TdiAddressType - type of address at TdiAddress
  2245. Returns:
  2246. Count of bytes written into IpAddressStringW.
  2247. Not including the terminating null.
  2248. --*/
  2249. USHORT
  2250. HostAddressAndPortToRoutingTokenW(
  2251. OUT PWCHAR IpAddressStringW,
  2252. IN PVOID TdiAddress,
  2253. IN USHORT TdiAddressType
  2254. )
  2255. {
  2256. PWCHAR pszW = IpAddressStringW;
  2257. //
  2258. // WARNING:
  2259. // Provided buffer should be at least as big as
  2260. // MAX_IP_BASED_ROUTING_TOKEN_LENGTH.
  2261. //
  2262. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  2263. {
  2264. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) TdiAddress);
  2265. struct in_addr IPv4Addr
  2266. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  2267. USHORT IpPortNum = SWAP_SHORT(pIPv4Address->sin_port);
  2268. pszW = RtlIpv4AddressToStringW(&IPv4Addr, pszW);
  2269. *pszW++ = L':';
  2270. pszW = UlStrPrintUlongW(pszW, IpPortNum, 0, L':');
  2271. pszW = RtlIpv4AddressToStringW(&IPv4Addr, pszW);
  2272. *pszW = L'\0';
  2273. }
  2274. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  2275. {
  2276. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) TdiAddress);
  2277. struct in6_addr IPv6Addr
  2278. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  2279. USHORT IpPortNum = SWAP_SHORT(pIPv6Address->sin6_port);
  2280. *pszW++ = L'[';
  2281. pszW = RtlIpv6AddressToStringW(&IPv6Addr, pszW);
  2282. *pszW++ = L']';
  2283. *pszW++ = L':';
  2284. pszW = UlStrPrintUlongW(pszW, IpPortNum, 0, L':');
  2285. *pszW++ = L'[';
  2286. pszW = RtlIpv6AddressToStringW(&IPv6Addr, pszW);
  2287. *pszW++ = L']';
  2288. *pszW = L'\0';
  2289. }
  2290. else
  2291. {
  2292. ASSERT(! "Unexpected TdiAddressType");
  2293. *pszW = L'\0';
  2294. }
  2295. return DIFF_USHORT(pszW - IpAddressStringW) * sizeof(WCHAR);
  2296. } // HostAddressAndPortToRoutingTokenW
  2297. /*++
  2298. Routine Description:
  2299. Calculates current bias (daylight time aware) and time zone ID.
  2300. Captured from base\client\datetime.c
  2301. Until this two functions are exposed in the kernel we have to
  2302. keep them here.
  2303. Arguments:
  2304. IN CONST TIME_ZONE_INFORMATION *ptzi - time zone for which to calculate bias
  2305. OUT KSYSTEM_TIME *pBias - current bias
  2306. Return Value:
  2307. TIME_ZONE_ID_UNKNOWN - daylight saving time is not used in the
  2308. current time zone.
  2309. TIME_ZONE_ID_STANDARD - The system is operating in the range covered
  2310. by StandardDate.
  2311. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered
  2312. by DaylightDate.
  2313. TIME_ZONE_ID_INVALID - The operation failed.
  2314. --*/
  2315. ULONG
  2316. UlCalcTimeZoneIdAndBias(
  2317. IN RTL_TIME_ZONE_INFORMATION *ptzi,
  2318. OUT PLONG pBias
  2319. )
  2320. {
  2321. LARGE_INTEGER TimeZoneBias;
  2322. LARGE_INTEGER NewTimeZoneBias;
  2323. LARGE_INTEGER LocalCustomBias;
  2324. LARGE_INTEGER UtcStandardTime;
  2325. LARGE_INTEGER UtcDaylightTime;
  2326. LARGE_INTEGER StandardTime;
  2327. LARGE_INTEGER DaylightTime;
  2328. LARGE_INTEGER CurrentUniversalTime;
  2329. ULONG CurrentTimeZoneId = UL_TIME_ZONE_ID_INVALID;
  2330. NewTimeZoneBias.QuadPart = Int32x32To64(ptzi->Bias * 60, C_NS_TICKS_PER_SEC);
  2331. //
  2332. // Now see if we have stored cutover times
  2333. //
  2334. if (ptzi->StandardStart.Month && ptzi->DaylightStart.Month)
  2335. {
  2336. KeQuerySystemTime(&CurrentUniversalTime);
  2337. //
  2338. // We have timezone cutover information. Compute the
  2339. // cutover dates and compute what our current bias
  2340. // is
  2341. //
  2342. if((!UlpCutoverTimeToSystemTime(
  2343. &ptzi->StandardStart,
  2344. &StandardTime,
  2345. &CurrentUniversalTime)
  2346. ) ||
  2347. (!UlpCutoverTimeToSystemTime(
  2348. &ptzi->DaylightStart,
  2349. &DaylightTime,
  2350. &CurrentUniversalTime)
  2351. )
  2352. )
  2353. {
  2354. return UL_TIME_ZONE_ID_INVALID;
  2355. }
  2356. //
  2357. // Convert standard time and daylight time to utc
  2358. //
  2359. LocalCustomBias.QuadPart = Int32x32To64(ptzi->StandardBias*60, C_NS_TICKS_PER_SEC);
  2360. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  2361. UtcDaylightTime.QuadPart = DaylightTime.QuadPart + TimeZoneBias.QuadPart;
  2362. LocalCustomBias.QuadPart = Int32x32To64(ptzi->DaylightBias*60, C_NS_TICKS_PER_SEC);
  2363. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  2364. UtcStandardTime.QuadPart = StandardTime.QuadPart + TimeZoneBias.QuadPart;
  2365. //
  2366. // If daylight < standard, then time >= daylight and
  2367. // less than standard is daylight
  2368. //
  2369. if (UtcDaylightTime.QuadPart < UtcStandardTime.QuadPart)
  2370. {
  2371. //
  2372. // If today is >= DaylightTime and < StandardTime, then
  2373. // We are in daylight savings time
  2374. //
  2375. if ((CurrentUniversalTime.QuadPart >= UtcDaylightTime.QuadPart) &&
  2376. (CurrentUniversalTime.QuadPart < UtcStandardTime.QuadPart))
  2377. {
  2378. CurrentTimeZoneId = UL_TIME_ZONE_ID_DAYLIGHT;
  2379. }
  2380. else
  2381. {
  2382. CurrentTimeZoneId = UL_TIME_ZONE_ID_STANDARD;
  2383. }
  2384. }
  2385. else
  2386. {
  2387. //
  2388. // If today is >= StandardTime and < DaylightTime, then
  2389. // We are in standard time
  2390. //
  2391. if ((CurrentUniversalTime.QuadPart >= UtcStandardTime.QuadPart) &&
  2392. (CurrentUniversalTime.QuadPart < UtcDaylightTime.QuadPart))
  2393. {
  2394. CurrentTimeZoneId = UL_TIME_ZONE_ID_STANDARD;
  2395. }
  2396. else
  2397. {
  2398. CurrentTimeZoneId = UL_TIME_ZONE_ID_DAYLIGHT;
  2399. }
  2400. }
  2401. // Bias in minutes
  2402. *pBias = ptzi->Bias + (CurrentTimeZoneId == UL_TIME_ZONE_ID_DAYLIGHT ?
  2403. ptzi->DaylightBias : ptzi->StandardBias
  2404. );
  2405. }
  2406. else
  2407. {
  2408. *pBias = ptzi->Bias;
  2409. CurrentTimeZoneId = UL_TIME_ZONE_ID_UNKNOWN;
  2410. }
  2411. return CurrentTimeZoneId;
  2412. } // UlCalcTimeZoneIdAndBias
  2413. BOOLEAN
  2414. UlpCutoverTimeToSystemTime(
  2415. PTIME_FIELDS CutoverTime,
  2416. PLARGE_INTEGER SystemTime,
  2417. PLARGE_INTEGER CurrentSystemTime
  2418. )
  2419. {
  2420. TIME_FIELDS CurrentTimeFields;
  2421. //
  2422. // Get the current system time
  2423. //
  2424. RtlTimeToTimeFields(CurrentSystemTime,&CurrentTimeFields);
  2425. //
  2426. // check for absolute time field. If the year is specified,
  2427. // the the time is an abosulte time
  2428. //
  2429. if ( CutoverTime->Year )
  2430. {
  2431. return FALSE;
  2432. }
  2433. else
  2434. {
  2435. TIME_FIELDS WorkingTimeField;
  2436. TIME_FIELDS ScratchTimeField;
  2437. LARGE_INTEGER ScratchTime;
  2438. CSHORT BestWeekdayDate;
  2439. CSHORT WorkingWeekdayNumber;
  2440. CSHORT TargetWeekdayNumber;
  2441. CSHORT TargetYear;
  2442. CSHORT TargetMonth;
  2443. CSHORT TargetWeekday; // range [0..6] == [Sunday..Saturday]
  2444. BOOLEAN MonthMatches;
  2445. //
  2446. // The time is an day in the month style time
  2447. //
  2448. // the convention is the Day is 1-5 specifying 1st, 2nd... Last
  2449. // day within the month. The day is WeekDay.
  2450. //
  2451. //
  2452. // Compute the target month and year
  2453. //
  2454. TargetWeekdayNumber = CutoverTime->Day;
  2455. if ( TargetWeekdayNumber > 5 || TargetWeekdayNumber == 0 ) {
  2456. return FALSE;
  2457. }
  2458. TargetWeekday = CutoverTime->Weekday;
  2459. TargetMonth = CutoverTime->Month;
  2460. MonthMatches = FALSE;
  2461. TargetYear = CurrentTimeFields.Year;
  2462. try_next_year:
  2463. BestWeekdayDate = 0;
  2464. WorkingTimeField.Year = TargetYear;
  2465. WorkingTimeField.Month = TargetMonth;
  2466. WorkingTimeField.Day = 1;
  2467. WorkingTimeField.Hour = CutoverTime->Hour;
  2468. WorkingTimeField.Minute = CutoverTime->Minute;
  2469. WorkingTimeField.Second = CutoverTime->Second;
  2470. WorkingTimeField.Milliseconds = CutoverTime->Milliseconds;
  2471. WorkingTimeField.Weekday = 0;
  2472. //
  2473. // Convert to time and then back to time fields so we can determine
  2474. // the weekday of day 1 on the month
  2475. //
  2476. if ( !RtlTimeFieldsToTime(&WorkingTimeField,&ScratchTime) ) {
  2477. return FALSE;
  2478. }
  2479. RtlTimeToTimeFields(&ScratchTime,&ScratchTimeField);
  2480. //
  2481. // Compute bias to target weekday
  2482. //
  2483. if ( ScratchTimeField.Weekday > TargetWeekday ) {
  2484. WorkingTimeField.Day += (7-(ScratchTimeField.Weekday - TargetWeekday));
  2485. }
  2486. else if ( ScratchTimeField.Weekday < TargetWeekday ) {
  2487. WorkingTimeField.Day += (TargetWeekday - ScratchTimeField.Weekday);
  2488. }
  2489. //
  2490. // We are now at the first weekday that matches our target weekday
  2491. //
  2492. BestWeekdayDate = WorkingTimeField.Day;
  2493. WorkingWeekdayNumber = 1;
  2494. //
  2495. // Keep going one week at a time until we either pass the
  2496. // target weekday, or we match exactly
  2497. //
  2498. while ( WorkingWeekdayNumber < TargetWeekdayNumber ) {
  2499. WorkingTimeField.Day += 7;
  2500. if ( !RtlTimeFieldsToTime(&WorkingTimeField,&ScratchTime) ) {
  2501. break;
  2502. }
  2503. RtlTimeToTimeFields(&ScratchTime,&ScratchTimeField);
  2504. WorkingWeekdayNumber++;
  2505. BestWeekdayDate = ScratchTimeField.Day;
  2506. }
  2507. WorkingTimeField.Day = BestWeekdayDate;
  2508. //
  2509. // If the months match, and the date is less than the current
  2510. // date, then be have to go to next year.
  2511. //
  2512. if ( !RtlTimeFieldsToTime(&WorkingTimeField,&ScratchTime) ) {
  2513. return FALSE;
  2514. }
  2515. if ( MonthMatches ) {
  2516. if ( WorkingTimeField.Day < CurrentTimeFields.Day ) {
  2517. MonthMatches = FALSE;
  2518. TargetYear++;
  2519. goto try_next_year;
  2520. }
  2521. if ( WorkingTimeField.Day == CurrentTimeFields.Day ) {
  2522. if (ScratchTime.QuadPart < CurrentSystemTime->QuadPart) {
  2523. MonthMatches = FALSE;
  2524. TargetYear++;
  2525. goto try_next_year;
  2526. }
  2527. }
  2528. }
  2529. *SystemTime = ScratchTime;
  2530. return TRUE;
  2531. }
  2532. } // UlpCutoverTimeToSystemTime
  2533. /*++
  2534. Routine Description:
  2535. Predicate for testing if system is close to being out of Non-Paged
  2536. Pool memory
  2537. Notes:
  2538. The Right Thing(tm) would be to query the value of
  2539. MmMaximumNonPagedPoolInBytes (%SDXROOT%\base\ntos\mm\miglobal.c).
  2540. However, this value is not exposed outside of the memory manager.
  2541. (from LandyW) "A crude workaround for now would be for your driver
  2542. to periodically allocate a big chunk of pool and if it fails, you
  2543. know you are low. If it works, then just return it." (27-Jul-2001)
  2544. We check to see if there is 3MB of NPP available. To avoid frag-
  2545. mentation issue, we do this in small chunks, tallying up to 3MB.
  2546. Returns:
  2547. TRUE - System is low on non-paged pool
  2548. FALSE - System is NOT low on non-paged pool
  2549. --*/
  2550. //
  2551. // NOTE: (NPP_CHUNK_COUNT * NPP_CHUNK_SIZE) == 3MB
  2552. //
  2553. #define NPP_CHUNK_SIZE (128 * 1024)
  2554. #define NPP_CHUNK_COUNT ((3 * 1024 * 1024) / NPP_CHUNK_SIZE)
  2555. BOOLEAN
  2556. UlIsLowNPPCondition( VOID )
  2557. {
  2558. BOOLEAN bRet;
  2559. PVOID aPtrs[NPP_CHUNK_COUNT];
  2560. int i;
  2561. //
  2562. // Optimisim is a good thing.
  2563. //
  2564. bRet = FALSE;
  2565. RtlZeroMemory( aPtrs, sizeof(aPtrs) );
  2566. //
  2567. // To avoid failing an allocation on a fragmentation issue, we
  2568. // allocate multiple smaller chunks, which brings us to 3MB of
  2569. // NonPagedPool. If we fail on any of the allocs, we know we're
  2570. // nearly out of NPP, and are in a Low NPP Condition.
  2571. //
  2572. for (i = 0 ; i < NPP_CHUNK_COUNT ; i++ )
  2573. {
  2574. aPtrs[i] = UL_ALLOCATE_POOL(
  2575. NonPagedPool,
  2576. NPP_CHUNK_SIZE, // 128K
  2577. UL_AUXILIARY_BUFFER_POOL_TAG
  2578. );
  2579. if ( !aPtrs[i] )
  2580. {
  2581. // Alloc failed! We're in a low-NPP condition!
  2582. bRet = TRUE;
  2583. goto End;
  2584. }
  2585. }
  2586. End:
  2587. //
  2588. // Clean up memory
  2589. //
  2590. for ( i = 0; i < NPP_CHUNK_COUNT; i++ )
  2591. {
  2592. if ( aPtrs[i] )
  2593. {
  2594. UL_FREE_POOL(
  2595. aPtrs[i],
  2596. UL_AUXILIARY_BUFFER_POOL_TAG
  2597. );
  2598. }
  2599. }
  2600. return bRet;
  2601. } // UlIsLowNPPCondition
  2602. /***************************************************************************++
  2603. Routine Description:
  2604. Generates a hex string from a ULONG. The incoming buffer must be big enough
  2605. to hold "12345678" plus the nul terminator.
  2606. Arguments:
  2607. n - input ULONG
  2608. Return Value:
  2609. a pointer to the end of the string
  2610. --***************************************************************************/
  2611. PSTR
  2612. UlUlongToHexString(
  2613. ULONG n,
  2614. PSTR wszHexDword
  2615. )
  2616. {
  2617. const int ULONGHEXDIGITS = sizeof(ULONG) * 2;
  2618. PSTR p = wszHexDword;
  2619. unsigned shift = (sizeof(ULONG) * 8) - 4;
  2620. ULONG mask = 0xFu << shift;
  2621. int i;
  2622. for (i = 0; i < ULONGHEXDIGITS; ++i, mask >>= 4, shift -= 4)
  2623. {
  2624. unsigned digit = (unsigned) ((n & mask) >> shift);
  2625. p[i] = hexArray[digit];
  2626. }
  2627. return p+i;
  2628. } // UlUlongToHexString
  2629. /***************************************************************************++
  2630. Routine Description:
  2631. This function does what strstr does, but assumes that str1 is not NULL
  2632. terminated. str2 is NULL terminated.
  2633. Arguments:
  2634. str1 - the input string
  2635. str2 - the substring
  2636. length - length of input string
  2637. Return Value:
  2638. offset of the substring, NULL if none found.
  2639. --***************************************************************************/
  2640. char *
  2641. UxStrStr(
  2642. const char *str1,
  2643. const char *str2,
  2644. ULONG length
  2645. )
  2646. {
  2647. char *cp = (char *) str1;
  2648. char *s1, *s2;
  2649. ULONG l1;
  2650. if ( !*str2 )
  2651. return((char *)str1);
  2652. while (length)
  2653. {
  2654. l1 = length;
  2655. s1 = cp;
  2656. s2 = (char *) str2;
  2657. while ( l1 && *s2 && !(*s1-*s2) )
  2658. l1--, s1++, s2++;
  2659. if (!*s2)
  2660. return(cp);
  2661. cp++;
  2662. length --;
  2663. }
  2664. return(NULL);
  2665. }
  2666. /***************************************************************************++
  2667. Routine Description:
  2668. This function does what strstr does, but assumes that str1 is not NULL
  2669. terminated. str2 is NULL terminated.
  2670. Arguments:
  2671. str1 - the input string
  2672. str2 - the substring
  2673. length - length of input string
  2674. Return Value:
  2675. offset of the substring, NULL if none found.
  2676. --***************************************************************************/
  2677. char *
  2678. UxStriStr(
  2679. const char *str1,
  2680. const char *str2,
  2681. ULONG length1
  2682. )
  2683. {
  2684. ULONG length2;
  2685. length2 = (ULONG) strlen(str2);
  2686. while (length1 >= length2 )
  2687. {
  2688. if(_strnicmp(str1, str2, length2) == 0)
  2689. return ((char *)str1);
  2690. str1 ++;
  2691. length1 --;
  2692. }
  2693. return(NULL);
  2694. }
  2695. /**************************************************************************++
  2696. Routine Description:
  2697. This routine encodes binary data in base64 format. It does not spilt
  2698. encoded base64 data across lines.
  2699. Arguments:
  2700. pBinaryData - Supplied pointer to binary data to encode.
  2701. BinaryDataLen - Supplies length of binary data in bytes.
  2702. pBase64Data - Supplies output buffer where base64 data will be written.
  2703. Base64DataLen - Supplies length of output buffer in bytes.
  2704. BytesWritten - Returns the number of bytes written in the output buffer.
  2705. Return Value:
  2706. NTSTATUS.
  2707. --**************************************************************************/
  2708. NTSTATUS
  2709. BinaryToBase64(
  2710. IN PUCHAR pBinaryData,
  2711. IN ULONG BinaryDataLen,
  2712. IN PUCHAR pBase64Data,
  2713. IN ULONG Base64DataLen,
  2714. OUT PULONG BytesWritten
  2715. )
  2716. {
  2717. NTSTATUS Status;
  2718. ULONG RequiredBase64Len;
  2719. ULONG i;
  2720. UCHAR o0, o1, o2, o3;
  2721. UCHAR end24bits[3];
  2722. PUCHAR p, pOrig;
  2723. //
  2724. // N.B. The following macros only work with UCHAR's (because of >> operator.)
  2725. //
  2726. #define UPPER_6_BITS(c) (((c) & 0xfc) >> 2)
  2727. #define UPPER_4_BITS(c) (((c) & 0xf0) >> 4)
  2728. #define UPPER_2_BITS(c) (((c) & 0xc0) >> 6)
  2729. #define LOWER_2_BITS(c) ((c) & 0x03)
  2730. #define LOWER_4_BITS(c) ((c) & 0x0f)
  2731. #define LOWER_6_BITS(c) ((c) & 0x3f)
  2732. // Sanity Check.
  2733. ASSERT(pBinaryData && BinaryDataLen);
  2734. ASSERT(pBase64Data && Base64DataLen);
  2735. ASSERT(BytesWritten);
  2736. // Initialize output argument.
  2737. *BytesWritten = 0;
  2738. //
  2739. // Check if the output buffer can contain base64 encoded data.
  2740. //
  2741. Status = BinaryToBase64Length(BinaryDataLen, &RequiredBase64Len);
  2742. if (!NT_SUCCESS(Status))
  2743. {
  2744. return Status;
  2745. }
  2746. if (RequiredBase64Len > Base64DataLen)
  2747. {
  2748. return STATUS_BUFFER_TOO_SMALL;
  2749. }
  2750. // Return the number of bytes written.
  2751. *BytesWritten = RequiredBase64Len;
  2752. p = pBinaryData;
  2753. pOrig = pBase64Data;
  2754. for (i = 0; i + 3 <= BinaryDataLen; i += 3)
  2755. {
  2756. //
  2757. // Encode 3 bytes at indices i, i+1, i+2.
  2758. //
  2759. o0 = UPPER_6_BITS(p[i]);
  2760. o1 = (LOWER_2_BITS(p[i]) << 4) | UPPER_4_BITS(p[i+1]);
  2761. o2 = (LOWER_4_BITS(p[i+1]) << 2) | UPPER_2_BITS(p[i+2]);
  2762. o3 = LOWER_6_BITS(p[i+2]);
  2763. ASSERT(o0 < 64 && o1 < 64 && o2 < 64 && o3 < 64);
  2764. //
  2765. // Encode binary bytes and write out the base64 bytes.
  2766. //
  2767. *pBase64Data++ = BinaryToBase64Table[o0];
  2768. *pBase64Data++ = BinaryToBase64Table[o1];
  2769. *pBase64Data++ = BinaryToBase64Table[o2];
  2770. *pBase64Data++ = BinaryToBase64Table[o3];
  2771. }
  2772. if (i < BinaryDataLen)
  2773. {
  2774. //
  2775. // Zero pad the remaining bits to get 24 bits.
  2776. //
  2777. end24bits[0] = p[i];
  2778. end24bits[1] = (BinaryDataLen > i+1) ? p[i+1] : '\0';
  2779. end24bits[2] = '\0';
  2780. o0 = UPPER_6_BITS(end24bits[0]);
  2781. o1 = (LOWER_2_BITS(end24bits[0]) << 4) | UPPER_4_BITS(end24bits[1]);
  2782. o2 = (LOWER_4_BITS(end24bits[1]) << 2) | UPPER_2_BITS(end24bits[2]);
  2783. pBase64Data[0] = BinaryToBase64Table[o0];
  2784. pBase64Data[1] = BinaryToBase64Table[o1];
  2785. pBase64Data[2] = BinaryToBase64Table[o2];
  2786. pBase64Data[3] = '=';
  2787. pBase64Data[2] = (BinaryDataLen > i+1) ? pBase64Data[2] : '=';
  2788. ASSERT(pBase64Data + 4 == pOrig + RequiredBase64Len);
  2789. }
  2790. else
  2791. {
  2792. ASSERT(pBase64Data == pOrig + RequiredBase64Len);
  2793. }
  2794. return STATUS_SUCCESS;
  2795. }
  2796. /**************************************************************************++
  2797. Routine Description:
  2798. This routine decodes Base64 encoded data to binary format.
  2799. Arguments:
  2800. pBase64Data - Supplies pointer to base64 encoded data.
  2801. Base64DataLen - Length of base64 data in bytes.
  2802. pBinaryData - Supplies pointer to a buffer where decoded data will
  2803. be written.
  2804. BinaryDataLen - Supplied the length of output buffer in bytes.
  2805. BytesWritten - Returns the number of bytes written in the output buffer.
  2806. Return Value:
  2807. NTSTATUS.
  2808. --**************************************************************************/
  2809. NTSTATUS
  2810. Base64ToBinary(
  2811. IN PUCHAR pBase64Data,
  2812. IN ULONG Base64DataLen,
  2813. IN PUCHAR pBinaryData,
  2814. IN ULONG BinaryDataLen,
  2815. OUT PULONG BytesWritten
  2816. )
  2817. {
  2818. ULONG i;
  2819. UCHAR b;
  2820. NTSTATUS Status;
  2821. ULONG RequiredBinaryLen;
  2822. ULONG BitsAvail, NumBitsAvail;
  2823. PUCHAR pCurr = pBinaryData;
  2824. // Sanity check.
  2825. ASSERT(pBase64Data && Base64DataLen);
  2826. ASSERT(pBinaryData && BinaryDataLen);
  2827. ASSERT(BytesWritten);
  2828. // Initialize output argument.
  2829. *BytesWritten = 0;
  2830. //
  2831. // Check if output buffer is big enough to hold the data.
  2832. //
  2833. Status = Base64ToBinaryLength(Base64DataLen, &RequiredBinaryLen);
  2834. if (!NT_SUCCESS(Status))
  2835. {
  2836. return Status;
  2837. }
  2838. if (RequiredBinaryLen > BinaryDataLen)
  2839. {
  2840. return STATUS_BUFFER_TOO_SMALL;
  2841. }
  2842. ASSERT(Base64DataLen % 4 == 0);
  2843. BitsAvail = 0;
  2844. NumBitsAvail = 0;
  2845. for (i = 0; i < Base64DataLen; i ++)
  2846. {
  2847. //
  2848. // See if base64 char is valid. All valid base64 chars are mapped
  2849. // to n where 0 <= n <= 63. In adition, '=' is also a valid
  2850. // base64 char.
  2851. //
  2852. b = Base64ToBinaryTable[pBase64Data[i]];
  2853. if (b == INVALID_BASE64_TO_BINARY_TABLE_ENTRY)
  2854. {
  2855. if (pBase64Data[i] != '=')
  2856. {
  2857. return STATUS_INVALID_PARAMETER;
  2858. }
  2859. // Handle '=' outside the for loop.
  2860. break;
  2861. }
  2862. ASSERT(NumBitsAvail < 8);
  2863. ASSERT(0 <= b && b <= 63);
  2864. BitsAvail = (BitsAvail << 6) | b;
  2865. NumBitsAvail += 6;
  2866. if (NumBitsAvail >= 8)
  2867. {
  2868. NumBitsAvail -= 8;
  2869. *pCurr++ = (UCHAR)(BitsAvail >> NumBitsAvail);
  2870. }
  2871. ASSERT(NumBitsAvail < 8);
  2872. }
  2873. if (i < Base64DataLen)
  2874. {
  2875. ASSERT(pBase64Data[i] == '=');
  2876. //
  2877. // There can be at most two '=' chars and they must appear at the end
  2878. // of the encoded data. A char, if any, that follows '=' char, must
  2879. // be a '='.
  2880. //
  2881. if (i + 2 < Base64DataLen ||
  2882. (i + 1 < Base64DataLen && pBase64Data[i+1] != '='))
  2883. {
  2884. return STATUS_INVALID_PARAMETER;
  2885. }
  2886. //
  2887. // All the remaining bits at this point must be zeros.
  2888. //
  2889. ASSERT(NumBitsAvail > 0 && NumBitsAvail < 8);
  2890. if (BitsAvail & ((1<<NumBitsAvail)-1))
  2891. {
  2892. return STATUS_INVALID_PARAMETER;
  2893. }
  2894. }
  2895. *BytesWritten = (ULONG)(pCurr - pBinaryData);
  2896. ASSERT(*BytesWritten <= BinaryDataLen);
  2897. return STATUS_SUCCESS;
  2898. }