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.

1802 lines
48 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. misc.h
  5. Abstract:
  6. This module contains miscellaneous constants & declarations.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Henry Sanders (henrysa) 17-Jun-1998 Merge with old httputil.h
  10. Paul McDaniel (paulmcd) 30-Mar-1999 added refcounted eresource
  11. Revision History:
  12. --*/
  13. #ifndef _MISC_H_
  14. #define _MISC_H_
  15. #define UL_MAX_HTTP_STATUS_CODE 999
  16. #define UL_MAX_HTTP_STATUS_CODE_LENGTH 3
  17. #define HTTP_PREFIX_ANSI "http://"
  18. #define HTTP_PREFIX_ANSI_LENGTH (sizeof(HTTP_PREFIX_ANSI)-sizeof(CHAR))
  19. #define HTTPS_PREFIX_ANSI "https://"
  20. #define HTTPS_PREFIX_ANSI_LENGTH (sizeof(HTTPS_PREFIX_ANSI)-sizeof(CHAR))
  21. #define HTTP_PREFIX_COLON_INDEX 4 // the colon location for http: (+4)
  22. #define HTTPS_PREFIX_COLON_INDEX 5 // the colon location for https: (+5)
  23. //
  24. // Note that the length of the strong wildcard prefix is the same as
  25. // that of the (weak) wildcard prefix.
  26. //
  27. #define HTTPS_WILD_PREFIX L"https://*:"
  28. #define HTTPS_WILD_PREFIX_LENGTH (sizeof(HTTPS_WILD_PREFIX)-sizeof(WCHAR))
  29. #define HTTP_WILD_PREFIX L"http://*:"
  30. #define HTTP_WILD_PREFIX_LENGTH (sizeof(HTTP_WILD_PREFIX)-sizeof(WCHAR))
  31. #define HTTPS_STRONG_WILD_PREFIX L"https://+:"
  32. #define HTTP_STRONG_WILD_PREFIX L"http://+:"
  33. #define HTTP_IP_PREFIX L"http://"
  34. #define HTTP_IP_PREFIX_LENGTH (sizeof(HTTP_IP_PREFIX)-sizeof(WCHAR))
  35. #define HTTPS_IP_PREFIX L"https://"
  36. #define HTTPS_IP_PREFIX_LENGTH (sizeof(HTTPS_IP_PREFIX)-sizeof(WCHAR))
  37. NTSTATUS
  38. InitializeHttpUtil(
  39. VOID
  40. );
  41. //
  42. // Our presumed cache-line size.
  43. //
  44. #define CACHE_LINE_SIZE UL_CACHE_LINE
  45. //
  46. // # of 100ns ticks per second ( 1ns = (1 / (10^9))s )
  47. //
  48. #define C_NS_TICKS_PER_SEC ((LONGLONG) (10 * 1000 * 1000))
  49. //
  50. // # of 100ns ticks per minute ( 1ns = (1 / ((10^9) * 60)) min )
  51. //
  52. #define C_NS_TICKS_PER_MIN ((LONGLONG) (C_NS_TICKS_PER_SEC * 60))
  53. //
  54. // # of millisecs per hour ( 1 ms = (1 / ((10^3) * 60 * 60)) hour )
  55. //
  56. #define C_MS_TICKS_PER_HOUR ((LONGLONG) (1000 * 60 * 60))
  57. //
  58. // # of 100ns ticks per milli second ( 1ns = (1 / (10^4)) milli sec )
  59. //
  60. #define C_NS_TICKS_PER_MSEC ((LONGLONG) (10 * 1000))
  61. //
  62. // # of seconds per year (aprox)
  63. // 1 year = (60 sec/min * 60 min/hr * 24 hr/day * 365 day/year)
  64. //
  65. #define C_SECS_PER_YEAR ((ULONG) (60 * 60 * 24 * 365))
  66. //
  67. // Alignment macros.
  68. //
  69. #define ROUND_UP( val, pow2 ) \
  70. ( ( (ULONG_PTR)(val) + (pow2) - 1 ) & ~( (pow2) - 1 ) )
  71. //
  72. // Macros for swapping the bytes in a long and a short.
  73. //
  74. #define SWAP_LONG RtlUlongByteSwap
  75. #define SWAP_SHORT RtlUshortByteSwap
  76. #define VALID_BOOLEAN_VALUE(x) ((x) == TRUE || (x) == FALSE)
  77. //
  78. // Context values stored in PFILE_OBJECT->FsContext2 to identify a handle
  79. // as a control channel, filter channel or an app pool.
  80. //
  81. // BUGBUG: Can these be spoofed?
  82. //
  83. #define UL_CONTROL_CHANNEL_CONTEXT ((PVOID) MAKE_SIGNATURE('CTRL'))
  84. #define UL_CONTROL_CHANNEL_CONTEXT_X ((PVOID) MAKE_SIGNATURE('Xctr'))
  85. #define UL_FILTER_CHANNEL_CONTEXT ((PVOID) MAKE_SIGNATURE('FLTR'))
  86. #define UL_FILTER_CHANNEL_CONTEXT_X ((PVOID) MAKE_SIGNATURE('Xflt'))
  87. #define UL_APP_POOL_CONTEXT ((PVOID) MAKE_SIGNATURE('APPP'))
  88. #define UL_APP_POOL_CONTEXT_X ((PVOID) MAKE_SIGNATURE('Xapp'))
  89. #define UC_SERVER_CONTEXT ((PVOID) MAKE_SIGNATURE('SERV'))
  90. #define UC_SERVER_CONTEXT_X ((PVOID) MAKE_SIGNATURE('Xerv'))
  91. #define IS_SERVER( pFileObject ) \
  92. ( (pFileObject)->FsContext2 == UC_SERVER_CONTEXT )
  93. #define IS_EX_SERVER( pFileObject ) \
  94. ( (pFileObject)->FsContext2 == UC_SERVER_CONTEXT_X )
  95. #define MARK_VALID_SERVER( pFileObject ) \
  96. ( (pFileObject)->FsContext2 = UC_SERVER_CONTEXT )
  97. #define MARK_INVALID_SERVER( pFileObject ) \
  98. ( (pFileObject)->FsContext2 = UC_SERVER_CONTEXT_X )
  99. #define IS_CONTROL_CHANNEL( pFileObject ) \
  100. ( (pFileObject)->FsContext2 == UL_CONTROL_CHANNEL_CONTEXT )
  101. #define IS_EX_CONTROL_CHANNEL( pFileObject ) \
  102. ( (pFileObject)->FsContext2 == UL_CONTROL_CHANNEL_CONTEXT_X )
  103. #define MARK_VALID_CONTROL_CHANNEL( pFileObject ) \
  104. ( (pFileObject)->FsContext2 = UL_CONTROL_CHANNEL_CONTEXT )
  105. #define MARK_INVALID_CONTROL_CHANNEL( pFileObject ) \
  106. ( (pFileObject)->FsContext2 = UL_CONTROL_CHANNEL_CONTEXT_X )
  107. #define GET_CONTROL_CHANNEL( pFileObject ) \
  108. ((PUL_CONTROL_CHANNEL)((pFileObject)->FsContext))
  109. #define GET_PP_CONTROL_CHANNEL( pFileObject ) \
  110. ((PUL_CONTROL_CHANNEL *)&((pFileObject)->FsContext))
  111. #define IS_FILTER_PROCESS( pFileObject ) \
  112. ( (pFileObject)->FsContext2 == UL_FILTER_CHANNEL_CONTEXT )
  113. #define IS_EX_FILTER_PROCESS( pFileObject ) \
  114. ( (pFileObject)->FsContext2 == UL_FILTER_CHANNEL_CONTEXT_X )
  115. #define MARK_VALID_FILTER_CHANNEL( pFileObject ) \
  116. ( (pFileObject)->FsContext2 = UL_FILTER_CHANNEL_CONTEXT )
  117. #define MARK_INVALID_FILTER_CHANNEL( pFileObject ) \
  118. ( (pFileObject)->FsContext2 = UL_FILTER_CHANNEL_CONTEXT_X )
  119. #define GET_FILTER_PROCESS( pFileObject ) \
  120. ((PUL_FILTER_PROCESS)((pFileObject)->FsContext))
  121. #define GET_PP_FILTER_PROCESS( pFileObject ) \
  122. ((PUL_FILTER_PROCESS *)&((pFileObject)->FsContext))
  123. #define IS_APP_POOL( pFileObject ) \
  124. ( (pFileObject)->FsContext2 == UL_APP_POOL_CONTEXT )
  125. #define IS_EX_APP_POOL( pFileObject ) \
  126. ( (pFileObject)->FsContext2 == UL_APP_POOL_CONTEXT_X )
  127. #define MARK_VALID_APP_POOL( pFileObject ) \
  128. ( (pFileObject)->FsContext2 = UL_APP_POOL_CONTEXT )
  129. #define MARK_INVALID_APP_POOL( pFileObject ) \
  130. ( (pFileObject)->FsContext2 = UL_APP_POOL_CONTEXT_X )
  131. #define GET_APP_POOL_PROCESS( pFileObject ) \
  132. ((PUL_APP_POOL_PROCESS)((pFileObject)->FsContext))
  133. #define GET_PP_APP_POOL_PROCESS( pFileObject ) \
  134. ((PUL_APP_POOL_PROCESS *)&((pFileObject)->FsContext))
  135. #define IS_APP_POOL_FO( pFileObject ) \
  136. ((pFileObject->DeviceObject->DriverObject == g_UlDriverObject) && \
  137. (IS_APP_POOL(pFileObject)))
  138. #define IS_FILTER_PROCESS_FO(pFileObject) \
  139. ((pFileObject->DeviceObject->DriverObject == g_UlDriverObject) && \
  140. (IS_FILTER_PROCESS(pFileObject)))
  141. //
  142. // A locked doubly-linked list
  143. //
  144. typedef struct DECLSPEC_ALIGN(UL_CACHE_LINE) _LOCKED_LIST_HEAD
  145. {
  146. UL_SPIN_LOCK SpinLock;
  147. ULONG Count;
  148. LIST_ENTRY ListHead;
  149. } LOCKED_LIST_HEAD, *PLOCKED_LIST_HEAD;
  150. //
  151. // Manipulators for LOCKED_LIST_HEADs
  152. //
  153. __inline
  154. VOID
  155. UlInitalizeLockedList(
  156. IN PLOCKED_LIST_HEAD pListHead,
  157. IN PSTR pListName
  158. )
  159. {
  160. UNREFERENCED_PARAMETER(pListName);
  161. InitializeListHead(&pListHead->ListHead);
  162. pListHead->Count = 0;
  163. UlInitializeSpinLock(&pListHead->SpinLock, pListName);
  164. } // UlInitalizeLockedList
  165. __inline
  166. VOID
  167. UlDestroyLockedList(
  168. IN PLOCKED_LIST_HEAD pListHead
  169. )
  170. {
  171. UNREFERENCED_PARAMETER(pListHead);
  172. ASSERT(IsListEmpty(&pListHead->ListHead));
  173. ASSERT(pListHead->Count == 0);
  174. ASSERT(UlDbgSpinLockUnowned(&pListHead->SpinLock));
  175. } // UlDestroyLockedList
  176. __inline
  177. BOOLEAN
  178. UlLockedListInsertHead(
  179. IN PLOCKED_LIST_HEAD pListHead,
  180. IN PLIST_ENTRY pListEntry,
  181. IN ULONG ListLimit
  182. )
  183. {
  184. KIRQL OldIrql;
  185. UlAcquireSpinLock(&pListHead->SpinLock, &OldIrql);
  186. ASSERT(NULL == pListEntry->Flink);
  187. if (HTTP_LIMIT_INFINITE != ListLimit && (pListHead->Count + 1) >= ListLimit)
  188. {
  189. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  190. return FALSE;
  191. }
  192. pListHead->Count += 1;
  193. InsertHeadList(
  194. &pListHead->ListHead,
  195. pListEntry
  196. );
  197. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  198. return TRUE;
  199. } // UlLockedListInsertHead
  200. __inline
  201. BOOLEAN
  202. UlLockedListInsertTail(
  203. IN PLOCKED_LIST_HEAD pListHead,
  204. IN PLIST_ENTRY pListEntry,
  205. IN ULONG ListLimit
  206. )
  207. {
  208. KIRQL OldIrql;
  209. UlAcquireSpinLock(&pListHead->SpinLock, &OldIrql);
  210. ASSERT(NULL == pListEntry->Flink);
  211. if (HTTP_LIMIT_INFINITE != ListLimit && (pListHead->Count + 1) >= ListLimit)
  212. {
  213. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  214. return FALSE;
  215. }
  216. pListHead->Count += 1;
  217. InsertTailList(
  218. &pListHead->ListHead,
  219. pListEntry
  220. );
  221. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  222. return TRUE;
  223. } // UlLockedListInsertTail
  224. __inline
  225. PLIST_ENTRY
  226. UlLockedListRemoveHead(
  227. IN PLOCKED_LIST_HEAD pListHead
  228. )
  229. {
  230. KIRQL OldIrql;
  231. PLIST_ENTRY pEntry = NULL;
  232. UlAcquireSpinLock(&pListHead->SpinLock, &OldIrql);
  233. if (!IsListEmpty(&pListHead->ListHead))
  234. {
  235. pEntry = RemoveHeadList(&pListHead->ListHead);
  236. ASSERT(NULL != pEntry);
  237. pEntry->Flink = NULL;
  238. pListHead->Count -= 1;
  239. ASSERT(HTTP_LIMIT_INFINITE != pListHead->Count);
  240. }
  241. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  242. return pEntry;
  243. } // UlLockedListRemoveHead
  244. __inline
  245. BOOLEAN
  246. UlLockedListRemoveEntry(
  247. IN PLOCKED_LIST_HEAD pListHead,
  248. IN PLIST_ENTRY pListEntry
  249. )
  250. {
  251. KIRQL OldIrql;
  252. UlAcquireSpinLock(&pListHead->SpinLock, &OldIrql);
  253. if (NULL == pListEntry->Flink)
  254. {
  255. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  256. return FALSE;
  257. }
  258. RemoveEntryList(pListEntry);
  259. pListEntry->Flink = NULL;
  260. pListHead->Count -= 1;
  261. ASSERT(HTTP_LIMIT_INFINITE != pListHead->Count);
  262. UlReleaseSpinLock(&pListHead->SpinLock, OldIrql);
  263. return TRUE;
  264. } // UlLockedListRemoveEntry
  265. //
  266. // Miscellaneous validators, etc.
  267. //
  268. #define IS_VALID_DEVICE_OBJECT( pDeviceObject ) \
  269. ( ((pDeviceObject) != NULL) && \
  270. ((pDeviceObject)->Type == IO_TYPE_DEVICE) && \
  271. ((pDeviceObject)->Size == sizeof(DEVICE_OBJECT)) )
  272. #define IS_VALID_FILE_OBJECT( pFileObject ) \
  273. ( ((pFileObject) != NULL) && \
  274. ((pFileObject)->Type == IO_TYPE_FILE) && \
  275. ((pFileObject)->Size == sizeof(FILE_OBJECT)) )
  276. #define IS_VALID_IRP( pIrp ) \
  277. ( ((pIrp) != NULL) && \
  278. ((pIrp)->Type == IO_TYPE_IRP) && \
  279. ((pIrp)->Size >= IoSizeOfIrp((pIrp)->StackCount)) )
  280. //
  281. // IP Based routing token looks like L"https://1.1.1.1:80:1.1.1.1".
  282. // Space is calculated including the terminated null and the second
  283. // column. It is in bytes.
  284. //
  285. #define MAX_IP_BASED_ROUTING_TOKEN_LENGTH \
  286. (HTTPS_IP_PREFIX_LENGTH \
  287. + MAX_IP_ADDR_AND_PORT_STRING_LEN * sizeof(WCHAR) \
  288. + sizeof(WCHAR) + MAX_IP_ADDR_PLUS_BRACKETS_STRING_LEN * sizeof(WCHAR) \
  289. + sizeof(WCHAR))
  290. //
  291. // Make sure that the maximum possible IP Based Routing token can fit to the
  292. // default provided routing token space in the request structure. This is
  293. // necessary to avoid the memory allocation per hit, when there is an IP bound
  294. // site in the cgroup tree.
  295. //
  296. C_ASSERT(DEFAULT_MAX_ROUTING_TOKEN_LENGTH >= MAX_IP_BASED_ROUTING_TOKEN_LENGTH);
  297. NTSTATUS
  298. TimeFieldsToHttpDate(
  299. IN PTIME_FIELDS pTime,
  300. OUT PWSTR pBuffer,
  301. IN ULONG BufferLength
  302. );
  303. BOOLEAN
  304. StringTimeToSystemTime(
  305. IN PCSTR pTimeString,
  306. IN USHORT TimeStringLength,
  307. OUT LARGE_INTEGER *pTime
  308. );
  309. ULONG
  310. HttpUnicodeToUTF8(
  311. IN PCWSTR lpSrcStr,
  312. IN LONG cchSrc,
  313. OUT LPSTR lpDestStr,
  314. IN LONG cchDest
  315. );
  316. NTSTATUS
  317. HttpUTF8ToUnicode(
  318. IN LPCSTR lpSrcStr,
  319. IN LONG cchSrc,
  320. OUT LPWSTR lpDestStr,
  321. IN OUT PLONG pcchDest,
  322. IN ULONG dwFlags
  323. );
  324. typedef enum _FIND_ETAG_STATUS
  325. {
  326. ETAG_FOUND,
  327. ETAG_NOT_FOUND,
  328. ETAG_PARSE_ERROR,
  329. } FIND_ETAG_STATUS;
  330. FIND_ETAG_STATUS
  331. FindInETagList(
  332. IN PUCHAR pLocalETag,
  333. IN PUCHAR pETagList,
  334. IN BOOLEAN fWeakCompare
  335. );
  336. USHORT
  337. HostAddressAndPortToString(
  338. OUT PUCHAR IpAddressString,
  339. IN PVOID TdiAddress,
  340. IN USHORT TdiAddressType
  341. );
  342. USHORT
  343. HostAddressAndPortToStringW(
  344. PWCHAR IpAddressString,
  345. PVOID TdiAddress,
  346. USHORT TdiAddressType
  347. );
  348. USHORT
  349. HostAddressToStringW(
  350. OUT PWCHAR IpAddressStringW,
  351. IN PVOID TdiAddress,
  352. IN USHORT TdiAddressType
  353. );
  354. USHORT
  355. HostAddressAndPortToRoutingTokenW(
  356. OUT PWCHAR IpAddressStringW,
  357. IN PVOID TdiAddress,
  358. IN USHORT TdiAddressType
  359. );
  360. /***************************************************************************++
  361. Routine Description:
  362. Stores the decimal representation of an unsigned 32-bit
  363. number in a character buffer, followed by a terminator
  364. character. Returns a pointer to the next position in the
  365. output buffer, to make appending strings easy; i.e., you
  366. can use the result of UlStrPrintUlong as the argument to the
  367. next call to UlStrPrintUlong. Note: the string is >not<
  368. zero-terminated unless you passed in '\0' as chTerminator
  369. Arguments:
  370. psz - output buffer; assumed to be large enough to hold the number.
  371. n - the number to print into psz, a 32-bit unsigned integer
  372. chTerminator - character to append after the decimal representation of n
  373. Return Value:
  374. pointer to end of string
  375. History:
  376. GeorgeRe 19-Sep-2000
  377. --***************************************************************************/
  378. __inline
  379. PCHAR
  380. UlStrPrintUlong(
  381. OUT PCHAR psz,
  382. IN ULONG n,
  383. IN CHAR chTerminator)
  384. {
  385. CHAR digits[MAX_ULONG_STR];
  386. int i = 0;
  387. ASSERT(psz != NULL);
  388. digits[i++] = chTerminator;
  389. // Build the string in reverse
  390. do
  391. {
  392. digits[i++] = (CHAR) (n % 10) + '0';
  393. n /= 10;
  394. } while (n != 0);
  395. while (--i >= 0)
  396. *psz++ = digits[i];
  397. // Back up to the nul terminator, if present
  398. if (chTerminator == '\0')
  399. {
  400. --psz;
  401. ASSERT(*psz == '\0');
  402. }
  403. return psz;
  404. } // UlStrPrintUlong
  405. /***************************************************************************++
  406. Routine Description:
  407. Identical to the above function except it writes to a WCHAR buffer and
  408. it pads zeros to the beginning of the number.
  409. --***************************************************************************/
  410. __inline
  411. PWCHAR
  412. UlStrPrintUlongW(
  413. OUT PWCHAR pwsz,
  414. IN ULONG n,
  415. IN LONG padding,
  416. IN WCHAR wchTerminator)
  417. {
  418. WCHAR digits[MAX_ULONG_STR];
  419. int i = 0;
  420. ASSERT(pwsz != NULL);
  421. digits[i++] = wchTerminator;
  422. // Build the string in reverse
  423. do
  424. {
  425. digits[i++] = (WCHAR) (n % 10) + L'0';
  426. n /= 10;
  427. } while (n != 0);
  428. // Padd Zeros to the beginning
  429. while( padding && --padding >= (i-1))
  430. *pwsz++ = L'0';
  431. // Reverse back
  432. while (--i >= 0)
  433. *pwsz++ = digits[i];
  434. // Back up to the nul terminator, if present
  435. if (wchTerminator == L'\0')
  436. {
  437. --pwsz;
  438. ASSERT(*pwsz == L'\0');
  439. }
  440. return pwsz;
  441. } // UlStrPrintUlongW
  442. __inline
  443. PCHAR
  444. UlStrPrintUlongPad(
  445. OUT PCHAR psz,
  446. IN ULONG n,
  447. IN LONG padding,
  448. IN CHAR chTerminator)
  449. {
  450. CHAR digits[MAX_ULONG_STR];
  451. int i = 0;
  452. ASSERT(psz != NULL);
  453. digits[i++] = chTerminator;
  454. // Build the string in reverse
  455. do
  456. {
  457. digits[i++] = (CHAR) (n % 10) + '0';
  458. n /= 10;
  459. } while (n != 0);
  460. // Padd Zeros to the beginning
  461. while( padding && --padding >= (i-1))
  462. *psz++ = '0';
  463. // Reverse back
  464. while (--i >= 0)
  465. *psz++ = digits[i];
  466. // Back up to the nul terminator, if present
  467. if (chTerminator == '\0')
  468. {
  469. --psz;
  470. ASSERT(*psz == '\0');
  471. }
  472. return psz;
  473. } // UlStrPrintUlongPad
  474. /***************************************************************************++
  475. Routine Description:
  476. Stores the decimal representation of an unsigned 64-bit
  477. number in a character buffer, followed by a terminator
  478. character. Returns a pointer to the next position in the
  479. output buffer, to make appending strings easy; i.e., you
  480. can use the result of UlStrPrintUlonglong as the argument to the
  481. next call to UlStrPrintUlonglong. Note: the string is >not<
  482. zero-terminated unless you passed in '\0' as chTerminator
  483. Arguments:
  484. psz - output buffer; assumed to be large enough to hold the number.
  485. n - the number to print into psz, a 64-bit unsigned integer
  486. chTerminator - character to append after the decimal representation of n
  487. Return Value:
  488. pointer to end of string
  489. History:
  490. GeorgeRe 19-Sep-2000
  491. --***************************************************************************/
  492. __inline
  493. PCHAR
  494. UlStrPrintUlonglong(
  495. OUT PCHAR psz,
  496. IN ULONGLONG n,
  497. IN CHAR chTerminator)
  498. {
  499. CHAR digits[MAX_ULONGLONG_STR];
  500. int i;
  501. if (n <= ULONG_MAX)
  502. {
  503. // If this is a 32-bit integer, it's faster to use the
  504. // 32-bit routine.
  505. return UlStrPrintUlong(psz, (ULONG)n, chTerminator);
  506. }
  507. ASSERT(psz != NULL);
  508. i = 0;
  509. digits[i++] = chTerminator;
  510. // Build the string in reverse
  511. do
  512. {
  513. digits[i++] = (CHAR) (n % 10) + '0';
  514. n /= 10;
  515. } while (n != 0);
  516. while (--i >= 0)
  517. *psz++ = digits[i];
  518. // Back up to the nul terminator, if present
  519. if (chTerminator == '\0')
  520. {
  521. --psz;
  522. ASSERT(*psz == '\0');
  523. }
  524. return psz;
  525. } // UlStrPrintUlonglong
  526. /***************************************************************************++
  527. Routine Description:
  528. Stores a string in a character buffer, followed by a
  529. terminator character. Returns a pointer to the next position
  530. in the output buffer, to make appending strings easy; i.e.,
  531. you can use the result of UlStrPrintStr as the argument to the
  532. next call to UlStrPrintStr. Note: the string is >not<
  533. zero-terminated unless you passed in '\0' as chTerminator
  534. Arguments:
  535. pszOutput - output buffer; assumed to be large enough to hold the number.
  536. pszInput - input string
  537. chTerminator - character to append after the input string
  538. Return Value:
  539. pointer to end of string
  540. History:
  541. GeorgeRe 19-Sep-2000
  542. --***************************************************************************/
  543. __inline
  544. PCHAR
  545. UlStrPrintStr(
  546. OUT PCHAR pszOutput,
  547. IN const CHAR* pszInput,
  548. IN CHAR chTerminator)
  549. {
  550. ASSERT(pszOutput != NULL);
  551. ASSERT(pszInput != NULL);
  552. // copy the input string
  553. while (*pszInput != '\0')
  554. *pszOutput++ = *pszInput++;
  555. *pszOutput = chTerminator;
  556. // Move past the terminator character unless it's a nul
  557. if (chTerminator != '\0')
  558. ++pszOutput;
  559. return pszOutput;
  560. } // UlStrPrintStr
  561. /***************************************************************************++
  562. Routine Description:
  563. Converts an V4 Ip address to string in the provided buffer.
  564. Arguments:
  565. psz - Pointer to the buffer
  566. RawAddress - IP address structure from TDI / UL_CONNECTION
  567. chTerminator - The terminator char will be appended to the end
  568. Return:
  569. The number of bytes copied to destination buffer.
  570. --***************************************************************************/
  571. __inline
  572. PCHAR
  573. UlStrPrintIP(
  574. OUT PCHAR psz,
  575. IN const VOID* pTdiAddress,
  576. IN USHORT TdiAddressType,
  577. IN CHAR chTerminator
  578. )
  579. {
  580. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  581. {
  582. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) pTdiAddress);
  583. struct in_addr IPv4Addr
  584. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  585. psz = RtlIpv4AddressToStringA(&IPv4Addr, psz);
  586. }
  587. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  588. {
  589. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) pTdiAddress);
  590. struct in6_addr IPv6Addr
  591. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  592. psz = RtlIpv6AddressToStringA(&IPv6Addr, psz);
  593. // Write Scope ID
  594. *psz++ = '%';
  595. psz = UlStrPrintUlong(psz, pIPv6Address->sin6_scope_id, '\0');
  596. }
  597. else
  598. {
  599. ASSERT(! "Unexpected TdiAddressType");
  600. *psz++ = '?';
  601. }
  602. *psz = chTerminator;
  603. // Move past the terminator character unless it's a nul
  604. if (chTerminator != '\0')
  605. ++psz;
  606. return psz;
  607. } // UlStrPrintIP
  608. /***************************************************************************++
  609. Routine Description:
  610. Converts an V4 or V6 Ip address to string in the provided buffer.
  611. Provided seperator is inserted between Ip and Port and also
  612. appended after the port.
  613. String is * NOT * going to be null terminated.
  614. Arguments:
  615. psz - Pointer to the buffer
  616. RawAddress - IP address structure from TDI / UL_CONNECTION
  617. chSeperator - the seperator character
  618. Return:
  619. The char pointer pointing after the last written seperator.
  620. --***************************************************************************/
  621. __inline
  622. PCHAR
  623. UlStrPrintIPAndPort(
  624. OUT PCHAR psz,
  625. IN const VOID* pTdiAddress,
  626. IN USHORT TdiAddressType,
  627. IN CHAR chSeperator
  628. )
  629. {
  630. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  631. {
  632. PTDI_ADDRESS_IP pIPv4Address = ((PTDI_ADDRESS_IP) pTdiAddress);
  633. struct in_addr IPv4Addr
  634. = * (struct in_addr UNALIGNED*) &pIPv4Address->in_addr;
  635. USHORT IpPortNum = SWAP_SHORT(pIPv4Address->sin_port);
  636. psz = RtlIpv4AddressToStringA(&IPv4Addr, psz);
  637. *psz++ = chSeperator;
  638. psz = UlStrPrintUlong(psz, IpPortNum, '\0');
  639. }
  640. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  641. {
  642. PTDI_ADDRESS_IP6 pIPv6Address = ((PTDI_ADDRESS_IP6) pTdiAddress);
  643. struct in6_addr IPv6Addr
  644. = * (struct in6_addr UNALIGNED*) &pIPv6Address->sin6_addr[0];
  645. USHORT IpPortNum = SWAP_SHORT(pIPv6Address->sin6_port);
  646. psz = RtlIpv6AddressToStringA(&IPv6Addr, psz);
  647. // Write Scope ID
  648. *psz++ = '%';
  649. psz = UlStrPrintUlong(psz, pIPv6Address->sin6_scope_id, '\0');
  650. *psz++ = chSeperator;
  651. psz = UlStrPrintUlong(psz, IpPortNum, '\0');
  652. }
  653. else
  654. {
  655. ASSERT(! "Unexpected TdiAddressType");
  656. *psz++ = '?';
  657. }
  658. *psz++ = chSeperator;
  659. return psz;
  660. } // UlStrPrintIPAndPort
  661. __inline
  662. VOID
  663. CopyTdiAddrToSockAddr(
  664. IN USHORT TdiAddressType,
  665. IN const VOID* pTdiAddress,
  666. OUT struct sockaddr* pSockAddress
  667. )
  668. {
  669. if (TdiAddressType == TDI_ADDRESS_TYPE_IP)
  670. {
  671. const PTDI_ADDRESS_IP pIPv4Address
  672. = (const PTDI_ADDRESS_IP) pTdiAddress;
  673. struct sockaddr_in *pSockAddrIPv4
  674. = (struct sockaddr_in*) pSockAddress;
  675. pSockAddrIPv4->sin_family = TdiAddressType;
  676. pSockAddrIPv4->sin_port = pIPv4Address->sin_port;
  677. pSockAddrIPv4->sin_addr.s_addr
  678. = (UNALIGNED ULONG) pIPv4Address->in_addr;
  679. RtlCopyMemory(
  680. &pSockAddrIPv4->sin_zero[0],
  681. &pIPv4Address->sin_zero[0],
  682. 8 * sizeof(UCHAR)
  683. );
  684. }
  685. else if (TdiAddressType == TDI_ADDRESS_TYPE_IP6)
  686. {
  687. const PTDI_ADDRESS_IP6 pIPv6Address
  688. = (const PTDI_ADDRESS_IP6) pTdiAddress;
  689. struct sockaddr_in6 *pSockAddrIPv6
  690. = (struct sockaddr_in6*) pSockAddress;
  691. pSockAddrIPv6->sin6_family = TdiAddressType;
  692. pSockAddrIPv6->sin6_port = pIPv6Address->sin6_port;
  693. pSockAddrIPv6->sin6_flowinfo
  694. = (UNALIGNED ULONG) pIPv6Address->sin6_flowinfo;
  695. RtlCopyMemory(
  696. &pSockAddrIPv6->sin6_addr,
  697. &pIPv6Address->sin6_addr[0],
  698. 8 * sizeof(USHORT)
  699. );
  700. pSockAddrIPv6->sin6_scope_id
  701. = (UNALIGNED ULONG) pIPv6Address->sin6_scope_id;
  702. }
  703. else
  704. {
  705. ASSERT(! "Unexpected TdiAddressType");
  706. }
  707. } // CopyTdiAddrToSockAddr
  708. __inline
  709. PCHAR
  710. UlStrPrintProtocolStatus(
  711. OUT PCHAR psz,
  712. IN USHORT HttpStatusCode,
  713. IN CHAR chTerminator
  714. )
  715. {
  716. ASSERT(HttpStatusCode <= UL_MAX_HTTP_STATUS_CODE);
  717. //
  718. // Build ASCII representation of 3-digit status code
  719. // in reverse order: units, tens, hundreds
  720. //
  721. psz[2] = '0' + (CHAR)(HttpStatusCode % 10);
  722. HttpStatusCode /= 10;
  723. psz[1] = '0' + (CHAR)(HttpStatusCode % 10);
  724. HttpStatusCode /= 10;
  725. psz[0] = '0' + (CHAR)(HttpStatusCode % 10);
  726. psz[3] = chTerminator;
  727. return psz + 4;
  728. } // UlStrPrintProtocolStatus
  729. __inline
  730. VOID
  731. UlProbeForRead(
  732. IN const VOID* Address,
  733. IN SIZE_T Length,
  734. IN ULONG Alignment,
  735. IN KPROCESSOR_MODE RequestorMode
  736. )
  737. {
  738. ASSERT((Alignment == 1) || (Alignment == 2) ||
  739. (Alignment == 4) || (Alignment == 8) ||
  740. (Alignment == 16));
  741. UlTraceVerbose(IOCTL,
  742. ("http!UlProbeForRead: "
  743. "%Id bytes @ %p, Align = %lu, Mode = '%c'.\n",
  744. Length, Address, Alignment,
  745. (RequestorMode != KernelMode) ? 'U' : 'K'
  746. ));
  747. if (RequestorMode != KernelMode)
  748. {
  749. // ASSERT(Length == 0 || (LONG_PTR) Address > 0);
  750. // ProbeForRead will throw an exception if we probe kernel-mode data
  751. ProbeForRead(Address, Length, Alignment);
  752. }
  753. else if (Length != 0)
  754. {
  755. // Check alignment
  756. if ( ( ((ULONG_PTR) Address) & (Alignment - 1)) != 0 )
  757. ExRaiseDatatypeMisalignment();
  758. }
  759. } // UlProbeForRead
  760. __inline
  761. VOID
  762. UlProbeForWrite(
  763. IN PVOID Address,
  764. IN SIZE_T Length,
  765. IN ULONG Alignment,
  766. IN KPROCESSOR_MODE RequestorMode
  767. )
  768. {
  769. ASSERT((Alignment == 1) || (Alignment == 2) ||
  770. (Alignment == 4) || (Alignment == 8) ||
  771. (Alignment == 16));
  772. UlTraceVerbose(IOCTL,
  773. ("http!UlProbeForWrite: "
  774. "%Id bytes @ %p, Align = %lu, Mode = '%c'.\n",
  775. Length, Address, Alignment,
  776. (RequestorMode != KernelMode) ? 'U' : 'K'
  777. ));
  778. if (RequestorMode != KernelMode)
  779. {
  780. // ASSERT(Length == 0 || (LONG_PTR) Address > 0);
  781. // ProbeForWrite will throw an exception if we probe kernel-mode data
  782. ProbeForWrite(Address, Length, Alignment);
  783. }
  784. else if (Length != 0)
  785. {
  786. // Check alignment
  787. if ( ( ((ULONG_PTR) Address) & (Alignment - 1)) != 0 )
  788. ExRaiseDatatypeMisalignment();
  789. }
  790. } // UlProbeForWrite
  791. /***************************************************************************++
  792. Routine Description:
  793. Probes an ANSI string and validates its length and accessibility.
  794. This MUST be called from within an exception handler, as it
  795. will throw exceptions if the data is invalid.
  796. Arguments:
  797. pStr - Pointer to the ANSI string to be validated.
  798. ByteLength - Length in bytes of pStr, excluding the trailing '\0'.
  799. RequestorMode - UserMode or KernelMode
  800. --***************************************************************************/
  801. __inline
  802. VOID
  803. UlProbeAnsiString(
  804. IN PCSTR pStr,
  805. IN USHORT ByteLength,
  806. IN KPROCESSOR_MODE RequestorMode
  807. )
  808. {
  809. UlTraceVerbose(IOCTL,
  810. ("http!UlProbeAnsiString: "
  811. "%hu bytes @ %p, "
  812. "Mode='%c'.\n",
  813. ByteLength, pStr,
  814. ((RequestorMode != KernelMode) ? 'U' : 'K')
  815. ));
  816. // String cannot be empty or NULL.
  817. if (0 == ByteLength || NULL == pStr)
  818. {
  819. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  820. }
  821. UlProbeForRead(
  822. pStr,
  823. (SIZE_T) ByteLength,
  824. sizeof(CHAR),
  825. RequestorMode
  826. );
  827. } // UlProbeAnsiString
  828. /***************************************************************************++
  829. Routine Description:
  830. Probes a WCHAR string and validates its length and accessibility.
  831. This MUST be called from within an exception handler, as it
  832. will throw exceptions if the data is invalid.
  833. Arguments:
  834. pStr - Pointer to the WCHAR string to be validated.
  835. ByteLength - Length in bytes of pStr, excluding the trailing L'\0'.
  836. RequestorMode - UserMode or KernelMode
  837. --***************************************************************************/
  838. __inline
  839. VOID
  840. UlProbeWideString(
  841. IN PCWSTR pStr,
  842. IN USHORT ByteLength,
  843. IN KPROCESSOR_MODE RequestorMode
  844. )
  845. {
  846. UlTraceVerbose(IOCTL,
  847. ("http!UlProbeWideString: "
  848. "%hu bytes (%hu) WCHARs @ %p,"
  849. "Mode = '%c'.\n",
  850. ByteLength,
  851. ByteLength / sizeof(WCHAR),
  852. pStr,
  853. ((RequestorMode != KernelMode) ? 'U' : 'K')
  854. ));
  855. // String cannot be empty or NULL.
  856. // ByteLength must be even.
  857. // Data must be WCHAR-aligned.
  858. if (0 == ByteLength || NULL == pStr
  859. || (ByteLength & (sizeof(WCHAR) - 1)) != 0
  860. || (((ULONG_PTR) pStr) & (sizeof(WCHAR) - 1)) != 0)
  861. {
  862. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  863. }
  864. UlProbeForRead(
  865. pStr,
  866. (SIZE_T) ByteLength,
  867. sizeof(WCHAR),
  868. RequestorMode
  869. );
  870. } // UlProbeWideString
  871. /***************************************************************************++
  872. Routine Description:
  873. Probes a UNICODE_STRING and validates its members. And captures down
  874. to a kernel buffer.
  875. If this function returns success, caller should clean up the allocated
  876. Unicode buffer by calling UlFreeCapturedUnicodeString(), once it's done
  877. with it.
  878. Arguments:
  879. pSrc - Pointer to the UNICODE_STRING to be validated.
  880. The UNICODE_STRING struct should live in kernel mode
  881. (local stack copy), but the Buffer should be in user
  882. mode address space, unless RequestorMode == KernelMode.
  883. pDst - Pointer to the UNICODE_STRING to hold the captured user
  884. buffer. Caller must have initialized this before passing
  885. in.
  886. AllocationLimit - User string will be refused if it is exceeding this limit.
  887. Expressed in WCHARs. If zero, no size check is done.
  888. RequestorMode - UserMode or KernelMode.
  889. --***************************************************************************/
  890. __inline
  891. NTSTATUS
  892. UlProbeAndCaptureUnicodeString(
  893. IN PCUNICODE_STRING pSrc,
  894. IN KPROCESSOR_MODE RequestorMode,
  895. OUT PUNICODE_STRING pDst,
  896. IN const USHORT AllocationLimit // In WCHARS, optional
  897. )
  898. {
  899. NTSTATUS Status = STATUS_SUCCESS;
  900. PWSTR pKernelBuffer = NULL;
  901. ASSERT(NULL != pSrc);
  902. ASSERT(NULL != pDst);
  903. ASSERT(pSrc != pDst);
  904. ASSERT(AllocationLimit <= UNICODE_STRING_MAX_WCHAR_LEN);
  905. // Ensure that pDst is properly initialized
  906. RtlInitEmptyUnicodeString(pDst, NULL, 0);
  907. UlTraceVerbose(IOCTL,
  908. ("http!UlProbeAndCaptureUnicodeString: struct @ %p, "
  909. "Length = %hu bytes (%hu) WCHARs, "
  910. "MaxLen = %hu bytes,"
  911. "Mode = '%c'.\n",
  912. pSrc,
  913. pSrc->Length,
  914. pSrc->Length / sizeof(WCHAR),
  915. pSrc->MaximumLength,
  916. (RequestorMode != KernelMode) ? 'U' : 'K'
  917. ));
  918. // Do not allocate/copy more than the limit being enforced.
  919. // if limit is non-zero, otherwise it is not being enforced
  920. if (0 != AllocationLimit &&
  921. (AllocationLimit * sizeof(WCHAR)) < pSrc->Length)
  922. {
  923. return STATUS_INVALID_PARAMETER;
  924. }
  925. if ((pSrc->MaximumLength < pSrc->Length) || (pSrc->Length == 0))
  926. {
  927. return STATUS_INVALID_PARAMETER;
  928. }
  929. __try
  930. {
  931. // Probe the user's buffer first.
  932. UlProbeWideString(
  933. pSrc->Buffer,
  934. pSrc->Length,
  935. RequestorMode
  936. );
  937. // Allocate a kernel buffer and capture the user's buffer.
  938. // The ULONG cast prevents USHORT arithmetic overflow.
  939. pKernelBuffer = (PWSTR) UL_ALLOCATE_ARRAY(
  940. PagedPool,
  941. WCHAR,
  942. ((ULONG) pSrc->Length + sizeof(WCHAR))
  943. / sizeof(WCHAR),
  944. UL_UNICODE_STRING_POOL_TAG
  945. );
  946. if (pKernelBuffer == NULL)
  947. {
  948. Status = STATUS_NO_MEMORY;
  949. __leave;
  950. }
  951. // Copy and null-terminate the unicode string.
  952. RtlCopyMemory(pKernelBuffer, pSrc->Buffer, pSrc->Length);
  953. pKernelBuffer[pSrc->Length/sizeof(WCHAR)] = UNICODE_NULL;
  954. pDst->Buffer = pKernelBuffer;
  955. pDst->Length = pSrc->Length;
  956. pDst->MaximumLength = pDst->Length + sizeof(WCHAR);
  957. }
  958. __except( UL_EXCEPTION_FILTER() )
  959. {
  960. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  961. }
  962. if (!NT_SUCCESS(Status))
  963. {
  964. if (pKernelBuffer != NULL)
  965. {
  966. UL_FREE_POOL(pKernelBuffer, UL_UNICODE_STRING_POOL_TAG );
  967. }
  968. }
  969. return Status;
  970. } // UlProbeAndCaptureUnicodeString
  971. // Cleans up a UNICODE_STRING initialized by UlProbeAndCaptureUnicodeString()
  972. __inline
  973. VOID
  974. UlFreeCapturedUnicodeString(
  975. IN PUNICODE_STRING pCapturedUnicodeString
  976. )
  977. {
  978. ASSERT(pCapturedUnicodeString);
  979. if (pCapturedUnicodeString->Buffer != NULL)
  980. {
  981. UL_FREE_POOL(
  982. pCapturedUnicodeString->Buffer,
  983. UL_UNICODE_STRING_POOL_TAG
  984. );
  985. }
  986. RtlInitEmptyUnicodeString(pCapturedUnicodeString, NULL, 0);
  987. }
  988. //
  989. // Small macro to test the sanity of an unicode string
  990. // also tests whether it is null terminated or not.
  991. //
  992. #define IS_WELL_FORMED_UNICODE_STRING(pUStr) \
  993. ((pUStr) && \
  994. (pUStr)->Buffer && \
  995. (pUStr)->Length && \
  996. (!((pUStr)->Length & 1)) && \
  997. (pUStr)->Length < (pUStr)->MaximumLength && \
  998. (!((pUStr)->MaximumLength & 1)) && \
  999. (pUStr)->Buffer[ \
  1000. (pUStr)->Length/sizeof(WCHAR)] \
  1001. == UNICODE_NULL \
  1002. )
  1003. //
  1004. // 64-bit interlocked routines
  1005. //
  1006. #ifdef _WIN64
  1007. #define UlInterlockedIncrement64 InterlockedIncrement64
  1008. #define UlInterlockedDecrement64 InterlockedDecrement64
  1009. #define UlInterlockedAdd64 InterlockedAdd64
  1010. #define UlInterlockedExchange64 InterlockedExchange64
  1011. #else // !_WIN64
  1012. __inline
  1013. LONGLONG
  1014. UlInterlockedIncrement64 (
  1015. IN OUT PLONGLONG Addend
  1016. )
  1017. {
  1018. LONGLONG localAddend;
  1019. LONGLONG addendPlusOne;
  1020. LONGLONG originalAddend;
  1021. do {
  1022. localAddend = *((volatile LONGLONG *) Addend);
  1023. addendPlusOne = localAddend + 1;
  1024. originalAddend = InterlockedCompareExchange64( Addend,
  1025. addendPlusOne,
  1026. localAddend );
  1027. PAUSE_PROCESSOR;
  1028. } while (originalAddend != localAddend);
  1029. return addendPlusOne;
  1030. } // UlInterlockedIncrement64
  1031. __inline
  1032. LONGLONG
  1033. UlInterlockedDecrement64 (
  1034. IN OUT PLONGLONG Addend
  1035. )
  1036. {
  1037. LONGLONG localAddend;
  1038. LONGLONG addendMinusOne;
  1039. LONGLONG originalAddend;
  1040. do {
  1041. localAddend = *((volatile LONGLONG *) Addend);
  1042. addendMinusOne = localAddend - 1;
  1043. originalAddend = InterlockedCompareExchange64( Addend,
  1044. addendMinusOne,
  1045. localAddend );
  1046. PAUSE_PROCESSOR;
  1047. } while (originalAddend != localAddend);
  1048. return addendMinusOne;
  1049. } // UlInterlockedDecrement64
  1050. __inline
  1051. LONGLONG
  1052. UlInterlockedAdd64 (
  1053. IN OUT PLONGLONG Addend,
  1054. IN LONGLONG Value
  1055. )
  1056. {
  1057. LONGLONG localAddend;
  1058. LONGLONG addendPlusValue;
  1059. LONGLONG originalAddend;
  1060. do {
  1061. localAddend = *((volatile LONGLONG *) Addend);
  1062. addendPlusValue = localAddend + Value;
  1063. originalAddend = InterlockedCompareExchange64( Addend,
  1064. addendPlusValue,
  1065. localAddend );
  1066. PAUSE_PROCESSOR;
  1067. } while (originalAddend != localAddend);
  1068. return originalAddend;
  1069. } // UlInterlockedAdd64
  1070. __inline
  1071. LONGLONG
  1072. UlInterlockedExchange64 (
  1073. IN OUT PLONGLONG Addend,
  1074. IN LONGLONG newValue
  1075. )
  1076. {
  1077. LONGLONG localAddend;
  1078. LONGLONG originalAddend;
  1079. do {
  1080. localAddend = *((volatile LONGLONG *) Addend);
  1081. originalAddend = InterlockedCompareExchange64( Addend,
  1082. newValue,
  1083. localAddend );
  1084. PAUSE_PROCESSOR;
  1085. } while (originalAddend != localAddend);
  1086. return originalAddend;
  1087. } // UlInterlockedExchange64
  1088. #endif // !_WIN64
  1089. //
  1090. // Barrier support for read-mostly operations
  1091. // Note that the AMD64 and IA32 barrier relies on program ordering
  1092. // and does not generate a hardware barrier
  1093. //
  1094. #if defined(_M_IA64)
  1095. #define UL_READMOSTLY_READ_BARRIER() __mf()
  1096. #define UL_READMOSTLY_WRITE_BARRIER() __mf()
  1097. #define UL_READMOSTLY_MEMORY_BARRIER() __mf()
  1098. #elif defined(_AMD64_) || defined(_X86_)
  1099. extern VOID _ReadWriteBarrier();
  1100. extern VOID _WriteBarrier();
  1101. #pragma intrinsic(_ReadWriteBarrier)
  1102. #pragma intrinsic(_WriteBarrier)
  1103. #define UL_READMOSTLY_READ_BARRIER() _ReadWriteBarrier()
  1104. #define UL_READMOSTLY_WRITE_BARRIER() _WriteBarrier()
  1105. #define UL_READMOSTLY_MEMORY_BARRIER() _ReadWriteBarrier()
  1106. #else
  1107. #error Cannot generate memory barriers for this architecture
  1108. #endif
  1109. __inline
  1110. PVOID
  1111. UlpFixup(
  1112. IN PUCHAR pUserPtr,
  1113. IN PUCHAR pKernelPtr,
  1114. IN PUCHAR pOffsetPtr,
  1115. IN ULONG BufferLength
  1116. )
  1117. {
  1118. ASSERT( pOffsetPtr >= pKernelPtr );
  1119. ASSERT( DIFF(pOffsetPtr - pKernelPtr) <= BufferLength );
  1120. UNREFERENCED_PARAMETER(BufferLength);
  1121. return pUserPtr + DIFF(pOffsetPtr - pKernelPtr);
  1122. } // UlpFixup
  1123. #define FIXUP_PTR( Type, pUserPtr, pKernelPtr, pOffsetPtr, BufferLength ) \
  1124. (Type)UlpFixup( \
  1125. (PUCHAR)(pUserPtr), \
  1126. (PUCHAR)(pKernelPtr), \
  1127. (PUCHAR)(pOffsetPtr), \
  1128. (BufferLength) \
  1129. )
  1130. //
  1131. // Time utility to calculate the TimeZone Bias Daylight/standart
  1132. // and returns one of the following values.
  1133. // It's taken from base\client\timedate.c.
  1134. // Once this two functions are exposed in the kernel we can get rid of
  1135. // this two functions.
  1136. //
  1137. #define UL_TIME_ZONE_ID_INVALID 0xFFFFFFFF
  1138. #define UL_TIME_ZONE_ID_UNKNOWN 0
  1139. #define UL_TIME_ZONE_ID_STANDARD 1
  1140. #define UL_TIME_ZONE_ID_DAYLIGHT 2
  1141. BOOLEAN
  1142. UlpCutoverTimeToSystemTime(
  1143. PTIME_FIELDS CutoverTime,
  1144. PLARGE_INTEGER SystemTime,
  1145. PLARGE_INTEGER CurrentSystemTime
  1146. );
  1147. ULONG
  1148. UlCalcTimeZoneIdAndBias(
  1149. IN RTL_TIME_ZONE_INFORMATION *ptzi,
  1150. OUT PLONG pBias
  1151. );
  1152. BOOLEAN
  1153. UlIsLowNPPCondition( VOID );
  1154. //
  1155. // Converts from NtStatus to Win32Status
  1156. //
  1157. #define HttpNtStatusToWin32Status( Status ) \
  1158. ( ( (Status) == STATUS_SUCCESS ) \
  1159. ? NO_ERROR \
  1160. : RtlNtStatusToDosErrorNoTeb( Status ) )
  1161. ULONG
  1162. HttpUnicodeToUTF8Count(
  1163. IN LPCWSTR pwszIn,
  1164. IN ULONG dwInLen,
  1165. IN BOOLEAN bEncode
  1166. );
  1167. NTSTATUS
  1168. HttpUnicodeToUTF8Encode(
  1169. IN LPCWSTR pwszIn,
  1170. IN ULONG dwInLen,
  1171. OUT PUCHAR pszOut,
  1172. IN ULONG dwOutLen,
  1173. OUT ULONG *pdwOutLen,
  1174. IN BOOLEAN bEncode
  1175. );
  1176. PSTR
  1177. UlUlongToHexString(
  1178. ULONG n,
  1179. PSTR pBuffer
  1180. );
  1181. PCHAR
  1182. UxStriStr(
  1183. const char *str1,
  1184. const char *str2,
  1185. ULONG length
  1186. );
  1187. PCHAR
  1188. UxStrStr(
  1189. const char *str1,
  1190. const char *str2,
  1191. ULONG length
  1192. );
  1193. /**************************************************************************++
  1194. Routine Description:
  1195. This routine tries to convert a SECURITY_STATUS to an NTSTATUS. It calls
  1196. MapSecurityError to perform the conversion. If the conversion fails,
  1197. it returns STATUS_UNSUCCESSFUL.
  1198. This routine always returns a valid NTSTATUS.
  1199. Arguments:
  1200. SecStatus - SECURITY_STATUS to be converted into NTSTATUS.
  1201. Return Value:
  1202. NTSTATUS.
  1203. --**************************************************************************/
  1204. __forceinline
  1205. NTSTATUS
  1206. SecStatusToNtStatus(
  1207. SECURITY_STATUS SecStatus
  1208. )
  1209. {
  1210. NTSTATUS Status;
  1211. //
  1212. // Try to convert SECURITY_STATUS to NTSTATUS. If a corresponding
  1213. // NTSTATUS is not found, then return STATUS_UNSUCCESSFUL.
  1214. //
  1215. Status = MapSecurityError(SecStatus);
  1216. //
  1217. // The following is temporarily disabled because, the tests will fail.
  1218. // Enable this when MapSecurityError is fixed.
  1219. //
  1220. #if 0
  1221. if (!NT_SUCCESS(Status) && Status == (NTSTATUS)SecStatus)
  1222. {
  1223. Status = STATUS_UNSUCCESSFUL;
  1224. }
  1225. #endif
  1226. return Status;
  1227. }
  1228. /**************************************************************************++
  1229. Routine Description:
  1230. This routine returns the number of bytes required to encode n byte
  1231. binary data in base64.
  1232. Arguments:
  1233. BinaryLength - Length of binary data (in bytes)
  1234. pBase64Length - Pointer to length of Base64 data (in bytes)
  1235. Return Value:
  1236. NTSTATUS.
  1237. --**************************************************************************/
  1238. __forceinline
  1239. NTSTATUS
  1240. BinaryToBase64Length(
  1241. IN ULONG BinaryLength,
  1242. OUT PULONG pBase64Length
  1243. )
  1244. {
  1245. NTSTATUS Status;
  1246. //
  1247. // Every 6 bits in binary will be encoded by 8 bits in base64.
  1248. // Hence the output is roughly 33.33% larger than input.
  1249. // First round up (BinaryLength / 3). Now. each 3 bytes
  1250. // in binary data will yield 4 bytes of base64 encoded data.
  1251. //
  1252. // N.B. The order of arithmetic operation is important.
  1253. // Actual formula of conversion is:
  1254. // Base64Length = ceil(BinaryLength/3) * 4.
  1255. //
  1256. *pBase64Length = ((BinaryLength + 2) / 3) * 4;
  1257. Status = STATUS_SUCCESS;
  1258. // Was there an arithmetic overflow in the above computation?
  1259. if (*pBase64Length < BinaryLength)
  1260. {
  1261. Status = STATUS_INTEGER_OVERFLOW;
  1262. }
  1263. return Status;
  1264. }
  1265. /**************************************************************************++
  1266. Routine Description:
  1267. This routine returns the number of bytes required to decode base64
  1268. encoded data of length n back to binary format.
  1269. Arguments:
  1270. Base64Length - Length of base64 data (in bytes).
  1271. pBinaryLength - Length of binary data (in bytes).
  1272. Return Value:
  1273. NTSTATUS.
  1274. --**************************************************************************/
  1275. __forceinline
  1276. NTSTATUS
  1277. Base64ToBinaryLength(
  1278. IN ULONG Base64Length,
  1279. OUT PULONG pBinaryLength
  1280. )
  1281. {
  1282. NTSTATUS Status;
  1283. *pBinaryLength = (Base64Length / 4) * 3;
  1284. Status = STATUS_SUCCESS;
  1285. // Base64Length must be a multiple of 4.
  1286. if (Base64Length % 4 != 0)
  1287. {
  1288. Status = STATUS_INVALID_PARAMETER;
  1289. }
  1290. return Status;
  1291. }
  1292. /**************************************************************************++
  1293. Safer version of UlInitUnicodeString, using the private function until
  1294. the Rtl one is exposed.
  1295. --**************************************************************************/
  1296. __inline
  1297. NTSTATUS
  1298. UlInitUnicodeStringEx(
  1299. OUT PUNICODE_STRING DestinationString,
  1300. IN PCWSTR SourceString OPTIONAL
  1301. )
  1302. {
  1303. if (SourceString != NULL)
  1304. {
  1305. SIZE_T Length = wcslen(SourceString);
  1306. //
  1307. // We are actually limited to 32765 characters since we want
  1308. // to store a meaningful MaximumLength also.
  1309. //
  1310. if (Length > (UNICODE_STRING_MAX_CHARS - 1))
  1311. {
  1312. return STATUS_NAME_TOO_LONG;
  1313. }
  1314. Length *= sizeof(WCHAR);
  1315. DestinationString->Length = (USHORT) Length;
  1316. DestinationString->MaximumLength = (USHORT) (Length + sizeof(WCHAR));
  1317. DestinationString->Buffer = (PWSTR) SourceString;
  1318. }
  1319. else
  1320. {
  1321. DestinationString->Length = 0;
  1322. DestinationString->MaximumLength = 0;
  1323. DestinationString->Buffer = NULL;
  1324. }
  1325. return STATUS_SUCCESS;
  1326. }
  1327. NTSTATUS
  1328. BinaryToBase64(
  1329. IN PUCHAR pBinaryData,
  1330. IN ULONG BinaryDataLen,
  1331. IN PUCHAR pBase64Data,
  1332. IN ULONG Base64DataLen,
  1333. OUT PULONG BytesWritten
  1334. );
  1335. NTSTATUS
  1336. Base64ToBinary(
  1337. IN PUCHAR pBase64Data,
  1338. IN ULONG Base64DataLen,
  1339. IN PUCHAR pBinaryData,
  1340. IN ULONG BinaryDataLen,
  1341. OUT PULONG BytesWritten
  1342. );
  1343. //
  1344. // A simple exclusive spinlock at passive level that doesn't raise IRQLs.
  1345. //
  1346. #define UL_EX_LOCK_FREE 0
  1347. #define UL_EX_LOCK_LOCKED 1
  1348. typedef LONG UL_EXCLUSIVE_LOCK, *PUL_EXCLUSIVE_LOCK;
  1349. __inline
  1350. VOID
  1351. UlInitializeExclusiveLock(
  1352. PUL_EXCLUSIVE_LOCK pExLock
  1353. )
  1354. {
  1355. *pExLock = UL_EX_LOCK_FREE;
  1356. }
  1357. __inline
  1358. VOID
  1359. UlAcquireExclusiveLock(
  1360. PUL_EXCLUSIVE_LOCK pExLock
  1361. )
  1362. {
  1363. while (TRUE)
  1364. {
  1365. if (UL_EX_LOCK_FREE == *((volatile LONG *) pExLock))
  1366. {
  1367. if (UL_EX_LOCK_FREE == InterlockedCompareExchange(
  1368. pExLock,
  1369. UL_EX_LOCK_LOCKED,
  1370. UL_EX_LOCK_FREE
  1371. ))
  1372. {
  1373. break;
  1374. }
  1375. }
  1376. PAUSE_PROCESSOR;
  1377. }
  1378. }
  1379. __inline
  1380. VOID
  1381. UlReleaseExclusiveLock(
  1382. PUL_EXCLUSIVE_LOCK pExLock
  1383. )
  1384. {
  1385. ASSERT( UL_EX_LOCK_LOCKED == *pExLock );
  1386. InterlockedExchange( pExLock, UL_EX_LOCK_FREE );
  1387. }
  1388. #endif // _MISC_H_