Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1137 lines
28 KiB

  1. /*++
  2. Copyright (c) 1998-2001 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. #ifdef __cplusplus
  16. extern "C" {
  17. #endif
  18. extern ULONG HttpChars[256];
  19. extern USHORT FastPopChars[256];
  20. extern USHORT DummyPopChars[256];
  21. #define HTTP_CHAR 0x001
  22. #define HTTP_UPCASE 0x002
  23. #define HTTP_LOCASE 0x004
  24. #define HTTP_ALPHA (HTTP_UPCASE | HTTP_LOCASE)
  25. #define HTTP_DIGIT 0x008
  26. #define HTTP_CTL 0x010
  27. #define HTTP_LWS 0x020
  28. #define HTTP_HEX 0x040
  29. #define HTTP_SEPERATOR 0x080
  30. #define HTTP_TOKEN 0x100
  31. #define URL_LEGAL 0x200
  32. #define URL_TOKEN (HTTP_ALPHA | HTTP_DIGIT | URL_LEGAL)
  33. #define IS_HTTP_UPCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE)
  34. #define IS_HTTP_LOCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE)
  35. #define IS_HTTP_ALPHA(c) (HttpChars[(UCHAR)(c)] & HTTP_ALPHA)
  36. #define IS_HTTP_DIGIT(c) (HttpChars[(UCHAR)(c)] & HTTP_DIGIT)
  37. #define IS_HTTP_HEX(c) (HttpChars[(UCHAR)(c)] & HTTP_HEX)
  38. #define IS_HTTP_CTL(c) (HttpChars[(UCHAR)(c)] & HTTP_CTL)
  39. #define IS_HTTP_LWS(c) (HttpChars[(UCHAR)(c)] & HTTP_LWS)
  40. #define IS_HTTP_SEPERATOR(c) (HttpChars[(UCHAR)(c)] & HTTP_SEPERATOR)
  41. #define IS_HTTP_TOKEN(c) (HttpChars[(UCHAR)(c)] & HTTP_TOKEN)
  42. #define IS_URL_TOKEN(c) (HttpChars[(UCHAR)(c)] & URL_TOKEN)
  43. //
  44. // Constant Declarations for UTF8 Encoding
  45. //
  46. #define ASCII 0x007f
  47. #define UTF8_2_MAX 0x07ff // max UTF8 2-byte sequence (32 * 64 =2048)
  48. #define UTF8_1ST_OF_2 0xc0 // 110x xxxx
  49. #define UTF8_1ST_OF_3 0xe0 // 1110 xxxx
  50. #define UTF8_1ST_OF_4 0xf0 // 1111 xxxx
  51. #define UTF8_TRAIL 0x80 // 10xx xxxx
  52. #define HIGHER_6_BIT(u) ((u) >> 12)
  53. #define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6)
  54. #define LOWER_6_BIT(u) ((u) & 0x003f)
  55. #define BIT7(a) ((a) & 0x80)
  56. #define BIT6(a) ((a) & 0x40)
  57. #define HIGH_SURROGATE_START 0xd800
  58. #define HIGH_SURROGATE_END 0xdbff
  59. #define LOW_SURROGATE_START 0xdc00
  60. #define LOW_SURROGATE_END 0xdfff
  61. NTSTATUS
  62. InitializeHttpUtil(
  63. VOID
  64. );
  65. //
  66. // Our presumed cache-line size.
  67. //
  68. #define CACHE_LINE_SIZE UL_CACHE_LINE
  69. //
  70. // # of 100ns ticks per second ( 1ns = (1 / (10^9))s )
  71. //
  72. #define C_NS_TICKS_PER_SEC ((LONGLONG) (10 * 1000 * 1000))
  73. //
  74. // Alignment macros.
  75. //
  76. #define ROUND_UP( val, pow2 ) \
  77. ( ( (ULONG_PTR)(val) + (pow2) - 1 ) & ~( (pow2) - 1 ) )
  78. //
  79. // Calculate the dimension of an array.
  80. //
  81. #define DIMENSION(x) ( sizeof(x) / sizeof(x[0]) )
  82. //
  83. // nice MIN/MAX macros
  84. //
  85. #define MIN(a,b) ( ((a) > (b)) ? (b) : (a) )
  86. #define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
  87. //
  88. // Macros for swapping the bytes in a long and a short.
  89. //
  90. #define SWAP_LONG RtlUlongByteSwap
  91. #define SWAP_SHORT RtlUshortByteSwap
  92. //
  93. // Context values stored in PFILE_OBJECT->FsContext2 to identify a handle
  94. // as a control channel, filter channel or an app pool.
  95. //
  96. #define UL_CONTROL_CHANNEL_CONTEXT ((PVOID)'LRTC')
  97. #define UL_CONTROL_CHANNEL_CONTEXT_X ((PVOID)'rtcX')
  98. #define UL_FILTER_CHANNEL_CONTEXT ((PVOID)'RTLF')
  99. #define UL_FILTER_CHANNEL_CONTEXT_X ((PVOID)'tlfX')
  100. #define UL_APP_POOL_CONTEXT ((PVOID)'PPPA')
  101. #define UL_APP_POOL_CONTEXT_X ((PVOID)'ppaX')
  102. #define IS_CONTROL_CHANNEL( pFileObject ) \
  103. ( (pFileObject)->FsContext2 == UL_CONTROL_CHANNEL_CONTEXT )
  104. #define MARK_VALID_CONTROL_CHANNEL( pFileObject ) \
  105. ( (pFileObject)->FsContext2 = UL_CONTROL_CHANNEL_CONTEXT )
  106. #define MARK_INVALID_CONTROL_CHANNEL( pFileObject ) \
  107. ( (pFileObject)->FsContext2 = UL_CONTROL_CHANNEL_CONTEXT_X )
  108. #define GET_CONTROL_CHANNEL( pFileObject ) \
  109. ((PUL_CONTROL_CHANNEL)((pFileObject)->FsContext))
  110. #define GET_PP_CONTROL_CHANNEL( pFileObject ) \
  111. ((PUL_CONTROL_CHANNEL *)&((pFileObject)->FsContext))
  112. #define IS_FILTER_PROCESS( pFileObject ) \
  113. ( (pFileObject)->FsContext2 == UL_FILTER_CHANNEL_CONTEXT )
  114. #define IS_EX_FILTER_PROCESS( pFileObject ) \
  115. ( (pFileObject)->FsContext2 == UL_FILTER_CHANNEL_CONTEXT_X )
  116. #define MARK_VALID_FILTER_CHANNEL( pFileObject ) \
  117. ( (pFileObject)->FsContext2 = UL_FILTER_CHANNEL_CONTEXT )
  118. #define MARK_INVALID_FILTER_CHANNEL( pFileObject ) \
  119. ( (pFileObject)->FsContext2 = UL_FILTER_CHANNEL_CONTEXT_X )
  120. #define GET_FILTER_PROCESS( pFileObject ) \
  121. ((PUL_FILTER_PROCESS)((pFileObject)->FsContext))
  122. #define GET_PP_FILTER_PROCESS( pFileObject ) \
  123. ((PUL_FILTER_PROCESS *)&((pFileObject)->FsContext))
  124. #define IS_APP_POOL( pFileObject ) \
  125. ( (pFileObject)->FsContext2 == UL_APP_POOL_CONTEXT )
  126. #define IS_EX_APP_POOL( pFileObject ) \
  127. ( (pFileObject)->FsContext2 == UL_APP_POOL_CONTEXT_X )
  128. #define MARK_VALID_APP_POOL( pFileObject ) \
  129. ( (pFileObject)->FsContext2 = UL_APP_POOL_CONTEXT )
  130. #define MARK_INVALID_APP_POOL( pFileObject ) \
  131. ( (pFileObject)->FsContext2 = UL_APP_POOL_CONTEXT_X )
  132. #define GET_APP_POOL_PROCESS( pFileObject ) \
  133. ((PUL_APP_POOL_PROCESS)((pFileObject)->FsContext))
  134. #define GET_PP_APP_POOL_PROCESS( pFileObject ) \
  135. ((PUL_APP_POOL_PROCESS *)&((pFileObject)->FsContext))
  136. #define IS_VALID_UL_NONPAGED_RESOURCE(pResource) \
  137. (((pResource) != NULL) && \
  138. ((pResource)->Signature == UL_NONPAGED_RESOURCE_SIGNATURE) && \
  139. ((pResource)->RefCount > 0))
  140. typedef struct _UL_NONPAGED_RESOURCE
  141. {
  142. //
  143. // NonPagedPool
  144. //
  145. SINGLE_LIST_ENTRY LookasideEntry; // must be first, links
  146. // into the lookaside list
  147. ULONG Signature; // UL_NONPAGED_RESOURCE_SIGNATURE
  148. LONG RefCount; // the reference count
  149. UL_ERESOURCE Resource; // the actual resource
  150. } UL_NONPAGED_RESOURCE, * PUL_NONPAGED_RESOURCE;
  151. #define UL_NONPAGED_RESOURCE_SIGNATURE ((ULONG)'RNLU')
  152. #define UL_NONPAGED_RESOURCE_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_NONPAGED_RESOURCE_SIGNATURE)
  153. PUL_NONPAGED_RESOURCE
  154. UlResourceNew(
  155. ULONG OwnerTag
  156. );
  157. VOID
  158. UlReferenceResource(
  159. PUL_NONPAGED_RESOURCE pResource
  160. REFERENCE_DEBUG_FORMAL_PARAMS
  161. );
  162. VOID
  163. UlDereferenceResource(
  164. PUL_NONPAGED_RESOURCE pResource
  165. REFERENCE_DEBUG_FORMAL_PARAMS
  166. );
  167. #define REFERENCE_RESOURCE( pres ) \
  168. UlReferenceResource( \
  169. (pres) \
  170. REFERENCE_DEBUG_ACTUAL_PARAMS \
  171. )
  172. #define DEREFERENCE_RESOURCE( pres ) \
  173. UlDereferenceResource( \
  174. (pres) \
  175. REFERENCE_DEBUG_ACTUAL_PARAMS \
  176. )
  177. PVOID
  178. UlResourceAllocatePool(
  179. IN POOL_TYPE PoolType,
  180. IN SIZE_T ByteLength,
  181. IN ULONG Tag
  182. );
  183. VOID
  184. UlResourceFreePool(
  185. IN PVOID pBuffer
  186. );
  187. //
  188. // Miscellaneous validators, etc.
  189. //
  190. #define IS_VALID_DEVICE_OBJECT( pDeviceObject ) \
  191. ( ((pDeviceObject) != NULL) && \
  192. ((pDeviceObject)->Type == IO_TYPE_DEVICE) && \
  193. ((pDeviceObject)->Size == sizeof(DEVICE_OBJECT)) )
  194. #define IS_VALID_FILE_OBJECT( pFileObject ) \
  195. ( ((pFileObject) != NULL) && \
  196. ((pFileObject)->Type == IO_TYPE_FILE) && \
  197. ((pFileObject)->Size == sizeof(FILE_OBJECT)) )
  198. #define IS_VALID_IRP( pIrp ) \
  199. ( ((pIrp) != NULL) && \
  200. ((pIrp)->Type == IO_TYPE_IRP) && \
  201. ((pIrp)->Size >= IoSizeOfIrp((pIrp)->StackCount)) )
  202. // 2^32-1 + '\0'
  203. #define MAX_ULONG_STR sizeof("4294967295")
  204. // 2^64-1 + '\0'
  205. #define MAX_ULONGLONG_STR sizeof("18446744073709551615")
  206. #define MAX_IPV4_STRING_LENGTH sizeof("255.255.255.255")
  207. NTSTATUS
  208. TimeFieldsToHttpDate(
  209. IN PTIME_FIELDS pTime,
  210. OUT PWSTR pBuffer,
  211. IN ULONG BufferLength
  212. );
  213. BOOLEAN
  214. StringTimeToSystemTime(
  215. IN const PSTR pszTime,
  216. OUT LARGE_INTEGER * pliTime
  217. );
  218. ULONG
  219. HttpUnicodeToUTF8(
  220. IN PCWSTR lpSrcStr,
  221. IN LONG cchSrc,
  222. OUT LPSTR lpDestStr,
  223. IN LONG cchDest
  224. );
  225. BOOLEAN
  226. FindInETagList(
  227. IN PUCHAR pLocalETag,
  228. IN PUCHAR pETagList,
  229. IN BOOLEAN fWeakCompare
  230. );
  231. ULONG
  232. HostAddressAndPortToStringW(
  233. IN OUT PWCHAR IpAddressStringW,
  234. IN ULONG IpAddress,
  235. IN USHORT IpPortNum
  236. );
  237. /***************************************************************************++
  238. Routine Description:
  239. Stores the decimal representation of an unsigned 32-bit
  240. number in a character buffer, followed by a terminator
  241. character. Returns a pointer to the next position in the
  242. output buffer, to make appending strings easy; i.e., you
  243. can use the result of UlStrPrintUlong as the argument to the
  244. next call to UlStrPrintUlong. Note: the string is >not<
  245. zero-terminated unless you passed in '\0' as chTerminator
  246. Arguments:
  247. psz - output buffer; assumed to be large enough to hold the number.
  248. n - the number to print into psz, a 32-bit unsigned integer
  249. chTerminator - character to append after the decimal representation of n
  250. Return Value:
  251. pointer to end of string
  252. History:
  253. GeorgeRe 19-Sep-2000
  254. --***************************************************************************/
  255. __inline
  256. PCHAR
  257. FASTCALL
  258. UlStrPrintUlong(
  259. OUT PCHAR psz,
  260. IN ULONG n,
  261. IN CHAR chTerminator)
  262. {
  263. CHAR digits[MAX_ULONG_STR];
  264. int i = 0;
  265. ASSERT(psz != NULL);
  266. digits[i++] = chTerminator;
  267. // Build the string in reverse
  268. do
  269. {
  270. digits[i++] = (CHAR) (n % 10) + '0';
  271. n /= 10;
  272. } while (n != 0);
  273. while (--i >= 0)
  274. *psz++ = digits[i];
  275. // Back up to the nul terminator, if present
  276. if (chTerminator == '\0')
  277. {
  278. --psz;
  279. ASSERT(*psz == '\0');
  280. }
  281. return psz;
  282. }
  283. /***************************************************************************++
  284. Routine Description:
  285. Identical to the above function except it writes to a WCHAR buffer and
  286. it pads zeros to the beginning of the number.
  287. --***************************************************************************/
  288. __inline
  289. PWCHAR
  290. FASTCALL
  291. UlStrPrintUlongW(
  292. OUT PWCHAR pwsz,
  293. IN ULONG n,
  294. IN LONG padding,
  295. IN WCHAR wchTerminator)
  296. {
  297. WCHAR digits[MAX_ULONG_STR];
  298. int i = 0;
  299. ASSERT(pwsz != NULL);
  300. digits[i++] = wchTerminator;
  301. // Build the string in reverse
  302. do
  303. {
  304. digits[i++] = (WCHAR) (n % 10) + L'0';
  305. n /= 10;
  306. } while (n != 0);
  307. // Padd Zeros to the beginning
  308. while( padding && --padding >= (i-1))
  309. *pwsz++ = L'0';
  310. // Reverse back
  311. while (--i >= 0)
  312. *pwsz++ = digits[i];
  313. // Back up to the nul terminator, if present
  314. if (wchTerminator == L'\0')
  315. {
  316. --pwsz;
  317. ASSERT(*pwsz == L'\0');
  318. }
  319. return pwsz;
  320. }
  321. __inline
  322. PCHAR
  323. FASTCALL
  324. UlStrPrintUlongPad(
  325. OUT PCHAR psz,
  326. IN ULONG n,
  327. IN LONG padding,
  328. IN CHAR chTerminator)
  329. {
  330. CHAR digits[MAX_ULONG_STR];
  331. int i = 0;
  332. ASSERT(psz != NULL);
  333. digits[i++] = chTerminator;
  334. // Build the string in reverse
  335. do
  336. {
  337. digits[i++] = (CHAR) (n % 10) + '0';
  338. n /= 10;
  339. } while (n != 0);
  340. // Padd Zeros to the beginning
  341. while( padding && --padding >= (i-1))
  342. *psz++ = '0';
  343. // Reverse back
  344. while (--i >= 0)
  345. *psz++ = digits[i];
  346. // Back up to the nul terminator, if present
  347. if (chTerminator == '\0')
  348. {
  349. --psz;
  350. ASSERT(*psz == '\0');
  351. }
  352. return psz;
  353. }
  354. /***************************************************************************++
  355. Routine Description:
  356. Stores the decimal representation of an unsigned 64-bit
  357. number in a character buffer, followed by a terminator
  358. character. Returns a pointer to the next position in the
  359. output buffer, to make appending strings easy; i.e., you
  360. can use the result of UlStrPrintUlonglong as the argument to the
  361. next call to UlStrPrintUlonglong. Note: the string is >not<
  362. zero-terminated unless you passed in '\0' as chTerminator
  363. Arguments:
  364. psz - output buffer; assumed to be large enough to hold the number.
  365. n - the number to print into psz, a 64-bit unsigned integer
  366. chTerminator - character to append after the decimal representation of n
  367. Return Value:
  368. pointer to end of string
  369. History:
  370. GeorgeRe 19-Sep-2000
  371. --***************************************************************************/
  372. __inline
  373. PCHAR
  374. FASTCALL
  375. UlStrPrintUlonglong(
  376. OUT PCHAR psz,
  377. IN ULONGLONG n,
  378. IN CHAR chTerminator)
  379. {
  380. CHAR digits[MAX_ULONGLONG_STR];
  381. int i;
  382. if (n <= ULONG_MAX)
  383. {
  384. return UlStrPrintUlong(psz, (ULONG)n, chTerminator);
  385. }
  386. ASSERT(psz != NULL);
  387. i = 0;
  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. }
  405. /* Wide Char version */
  406. __inline
  407. PWCHAR
  408. FASTCALL
  409. UlStrPrintUlonglongW(
  410. OUT PWCHAR pwsz,
  411. IN ULONGLONG n,
  412. IN WCHAR wchTerminator)
  413. {
  414. WCHAR digits[MAX_ULONGLONG_STR];
  415. int i;
  416. if (n <= ULONG_MAX)
  417. {
  418. return UlStrPrintUlongW(pwsz, (ULONG)n, 0, wchTerminator);
  419. }
  420. ASSERT(pwsz != NULL);
  421. i = 0;
  422. digits[i++] = wchTerminator;
  423. // Build the string in reverse
  424. do
  425. {
  426. digits[i++] = (WCHAR) (n % 10) + L'0';
  427. n /= 10;
  428. } while (n != 0);
  429. while (--i >= 0)
  430. *pwsz++ = digits[i];
  431. // Back up to the nul terminator, if present
  432. if (wchTerminator == L'\0')
  433. {
  434. --pwsz;
  435. ASSERT(*pwsz == L'\0');
  436. }
  437. return pwsz;
  438. }
  439. /***************************************************************************++
  440. Routine Description:
  441. Stores a string in a character buffer, followed by a
  442. terminator character. Returns a pointer to the next position
  443. in the output buffer, to make appending strings easy; i.e.,
  444. you can use the result of UlStrPrintStr as the argument to the
  445. next call to UlStrPrintStr. Note: the string is >not<
  446. zero-terminated unless you passed in '\0' as chTerminator
  447. Arguments:
  448. pszOutput - output buffer; assumed to be large enough to hold the number.
  449. pszInput - input string
  450. chTerminator - character to append after the input string
  451. Return Value:
  452. pointer to end of string
  453. History:
  454. GeorgeRe 19-Sep-2000
  455. --***************************************************************************/
  456. __inline
  457. PCHAR
  458. FASTCALL
  459. UlStrPrintStr(
  460. OUT PCHAR pszOutput,
  461. IN const CHAR* pszInput,
  462. IN CHAR chTerminator)
  463. {
  464. ASSERT(pszOutput != NULL);
  465. ASSERT(pszInput != NULL);
  466. // copy the input string
  467. while (*pszInput != '\0')
  468. *pszOutput++ = *pszInput++;
  469. *pszOutput = chTerminator;
  470. // Move past the terminator character unless it's a nul
  471. if (chTerminator != '\0')
  472. ++pszOutput;
  473. return pszOutput;
  474. }
  475. /* Wide Char version */
  476. __inline
  477. PWCHAR
  478. FASTCALL
  479. UlStrPrintStrW(
  480. OUT PWCHAR pwszOutput,
  481. IN const WCHAR* pwszInput,
  482. IN WCHAR wchTerminator)
  483. {
  484. ASSERT(pwszOutput != NULL);
  485. ASSERT(pwszInput != NULL);
  486. // copy the input string
  487. while (*pwszInput != L'\0')
  488. *pwszOutput++ = *pwszInput++;
  489. *pwszOutput = wchTerminator;
  490. // Move past the terminator character unless it's a nul
  491. if (wchTerminator != L'\0')
  492. ++pwszOutput;
  493. return pwszOutput;
  494. }
  495. /* This version also does SpaceToPlus Conversion */
  496. __inline
  497. PCHAR
  498. FASTCALL
  499. UlStrPrintStrC(
  500. OUT PCHAR pszOutput,
  501. IN const CHAR* pszInput,
  502. IN CHAR chTerminator)
  503. {
  504. ASSERT(pszOutput != NULL);
  505. ASSERT(pszInput != NULL);
  506. // copy the input string
  507. while (*pszInput != '\0')
  508. {
  509. if (*pszInput == ' ')
  510. {
  511. *pszOutput++ = '+'; pszInput++;
  512. }
  513. else
  514. {
  515. *pszOutput++ = *pszInput++;
  516. }
  517. }
  518. *pszOutput = chTerminator;
  519. // Move past the terminator character unless it's a nul
  520. if (chTerminator != '\0')
  521. ++pszOutput;
  522. return pszOutput;
  523. }
  524. /***************************************************************************++
  525. Routine Description:
  526. Assumes that no information has been saved in the high byte of the WCHAR
  527. this function simply unpads the ansi string from wchar buffer back to
  528. a char buffer.
  529. If bReplaceSpaces is TRUE, it replaces the spaces in the source string
  530. with '+' sign, not including the terminator.
  531. --***************************************************************************/
  532. __inline
  533. LONG
  534. FASTCALL
  535. UlStrPrintStrUnPad(
  536. OUT PCHAR pszOutput,
  537. IN ULONG OutputSize,
  538. IN const WCHAR* pwszInput,
  539. IN CHAR chTerminator,
  540. IN BOOLEAN bReplaceSpaces)
  541. {
  542. ULONG Copied = 0;
  543. ASSERT(pszOutput != NULL);
  544. ASSERT(pwszInput != NULL);
  545. //
  546. // copy the input string discard the wchar's high byte
  547. // by explicitly casting it to char
  548. //
  549. if (bReplaceSpaces)
  550. {
  551. while (*pwszInput != L'\0' && Copied < OutputSize)
  552. {
  553. if (*pwszInput == L' ')
  554. {
  555. *pszOutput++ = (CHAR) '+'; pwszInput++, Copied++;
  556. }
  557. else
  558. {
  559. *pszOutput++ = (CHAR) *pwszInput++, Copied++;
  560. }
  561. }
  562. }
  563. else
  564. {
  565. while (*pwszInput != L'\0' && Copied < OutputSize)
  566. *pszOutput++ = (CHAR) *pwszInput++, Copied++;
  567. }
  568. //
  569. // return -1 if we couldn't copy
  570. // the whole Input string
  571. //
  572. if (*pwszInput != L'\0')
  573. return -1;
  574. //
  575. // Copy the seperator if there's
  576. // a space for that too
  577. //
  578. if (Copied < OutputSize)
  579. *pszOutput = chTerminator;
  580. // Count the terminator character unless it's a nul
  581. if (chTerminator != '\0')
  582. ++Copied;
  583. //
  584. // return how many chars we have copied
  585. //
  586. return (LONG) Copied;
  587. }
  588. /***************************************************************************++
  589. Routine Description:
  590. W/o storing any information to the high bytes of the WCHAR this function
  591. simply converts the ansi string to wchar buffer by padding zeros.
  592. --***************************************************************************/
  593. __inline
  594. PWCHAR
  595. FASTCALL
  596. UlStrPrintStrPad(
  597. OUT PWCHAR pwszOutput,
  598. IN const CHAR* pszInput,
  599. IN WCHAR wchTerminator)
  600. {
  601. ULONG Copied = 0;
  602. ASSERT(pwszOutput != NULL);
  603. ASSERT(pszInput != NULL);
  604. // copy the input string
  605. while (*pszInput != '\0')
  606. *pwszOutput++ = (WCHAR) *pszInput++;
  607. // copy the separator
  608. *pwszOutput = wchTerminator;
  609. // Move past the terminator character unless it's a nul
  610. if (wchTerminator != L'\0')
  611. ++pwszOutput;
  612. return pwszOutput;
  613. }
  614. /***************************************************************************++
  615. Routine Description:
  616. Converts an V4 Ip address to string in the provided buffer.
  617. Arguments:
  618. psz - Pointer to the buffer
  619. RawAddress - IP address structure from TDI / UL_CONNECTION
  620. chTerminator - The terminator char will be appended to the end
  621. Return:
  622. The number of bytes copied to destination buffer.
  623. --***************************************************************************/
  624. __inline
  625. PCHAR
  626. FASTCALL
  627. UlStrPrintIP(
  628. OUT PCHAR psz,
  629. IN IPAddr IpAddress,
  630. IN CHAR chTerminator
  631. )
  632. {
  633. psz = UlStrPrintUlong(psz, (IpAddress >> 24) & 0xFF, '.' );
  634. psz = UlStrPrintUlong(psz, (IpAddress >> 16) & 0xFF, '.' );
  635. psz = UlStrPrintUlong(psz, (IpAddress >> 8) & 0xFF, '.' );
  636. psz = UlStrPrintUlong(psz, (IpAddress >> 0) & 0xFF, chTerminator);
  637. return psz;
  638. }
  639. __inline
  640. PCHAR
  641. FASTCALL
  642. UlStrPrintProtocolStatus(
  643. OUT PCHAR psz,
  644. IN USHORT StatusCode,
  645. IN CHAR chTerminator
  646. )
  647. {
  648. ASSERT(StatusCode <= 999);
  649. *psz++ = '0' + ((StatusCode / 100) % 10);
  650. *psz++ = '0' + ((StatusCode / 10) % 10);
  651. *psz++ = '0' + ((StatusCode / 1) % 10);
  652. *psz++ = chTerminator;
  653. return psz;
  654. }
  655. __inline
  656. VOID
  657. ProbeTestForRead (
  658. IN const void* Address,
  659. IN SIZE_T Length,
  660. IN ULONG Alignment
  661. )
  662. /*++
  663. Routine Description:
  664. This function probes a structure for read accessibility and ensures
  665. correct alignment of the structure. If the structure is not accessible
  666. or has incorrect alignment, then an exception is raised.
  667. Adapted from \nt\base\ntos\ex\probe.c's version of ProbeForWrite.
  668. The regular ProbeForRead does not dereference any of the memory
  669. in the buffer.
  670. Arguments:
  671. Address - Supplies a pointer to the structure to be probed.
  672. Length - Supplies the length of the structure.
  673. Alignment - Supplies the required alignment of the structure expressed
  674. as the number of bytes in the primitive datatype (e.g., 1 for char,
  675. 2 for short, 4 for long, and 8 for quad).
  676. Return Value:
  677. None.
  678. --*/
  679. {
  680. ULONG_PTR StartAddress = (ULONG_PTR)Address;
  681. ULONG_PTR EndAddress = StartAddress + Length - 1;
  682. // Do the regular ProbeForRead checks for misalignment or
  683. // out-of-bounds addresses. This will raise exceptions, if needed.
  684. ProbeForRead(Address, Length, Alignment);
  685. //
  686. // If the structure has zero length, then do not probe the structure for
  687. // read accessibility or alignment.
  688. //
  689. if (Length == 0)
  690. return;
  691. //
  692. // The preceding checks should guarantee us a valid address range
  693. //
  694. ASSERT(StartAddress <= EndAddress);
  695. //
  696. // N.B. Only the contents of the buffer may be probed.
  697. // Therefore the starting byte is probed for the
  698. // first page, and then the first byte in the page
  699. // for each succeeding page.
  700. //
  701. // First byte of last page in range
  702. EndAddress = (EndAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
  703. do {
  704. *(volatile CHAR *)StartAddress;
  705. StartAddress = (StartAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
  706. } while (StartAddress != EndAddress);
  707. } // ProbeTestForRead
  708. //
  709. // 64-bit interlocked routines
  710. //
  711. #ifdef _WIN64
  712. #define UlInterlockedIncrement64 InterlockedIncrement64
  713. #define UlInterlockedDecrement64 InterlockedDecrement64
  714. #define UlInterlockedAdd64 InterlockedAdd64
  715. #define UlInterlockedExchange64 InterlockedExchange64
  716. #else
  717. __inline
  718. LONGLONG
  719. FASTCALL
  720. UlInterlockedIncrement64 (
  721. IN OUT PLONGLONG Addend
  722. )
  723. {
  724. LONGLONG localAddend;
  725. LONGLONG addendPlusOne;
  726. LONGLONG originalAddend;
  727. do {
  728. localAddend = *((volatile LONGLONG *) Addend);
  729. addendPlusOne = localAddend + 1;
  730. originalAddend = InterlockedCompareExchange64( Addend,
  731. addendPlusOne,
  732. localAddend );
  733. } while (originalAddend != localAddend);
  734. return addendPlusOne;
  735. }
  736. __inline
  737. LONGLONG
  738. FASTCALL
  739. UlInterlockedDecrement64 (
  740. IN OUT PLONGLONG Addend
  741. )
  742. {
  743. LONGLONG localAddend;
  744. LONGLONG addendMinusOne;
  745. LONGLONG originalAddend;
  746. do {
  747. localAddend = *((volatile LONGLONG *) Addend);
  748. addendMinusOne = localAddend - 1;
  749. originalAddend = InterlockedCompareExchange64( Addend,
  750. addendMinusOne,
  751. localAddend );
  752. } while (originalAddend != localAddend);
  753. return addendMinusOne;
  754. }
  755. __inline
  756. LONGLONG
  757. FASTCALL
  758. UlInterlockedAdd64 (
  759. IN OUT PLONGLONG Addend,
  760. IN LONGLONG Value
  761. )
  762. {
  763. LONGLONG localAddend;
  764. LONGLONG addendPlusValue;
  765. LONGLONG originalAddend;
  766. do {
  767. localAddend = *((volatile LONGLONG *) Addend);
  768. addendPlusValue = localAddend + Value;
  769. originalAddend = InterlockedCompareExchange64( Addend,
  770. addendPlusValue,
  771. localAddend );
  772. } while (originalAddend != localAddend);
  773. return addendPlusValue;
  774. }
  775. __inline
  776. LONGLONG
  777. FASTCALL
  778. UlInterlockedExchange64 (
  779. IN OUT PLONGLONG Addend,
  780. IN LONGLONG newValue
  781. )
  782. {
  783. LONGLONG localAddend;
  784. LONGLONG originalAddend;
  785. do {
  786. localAddend = *((volatile LONGLONG *) Addend);
  787. originalAddend = InterlockedCompareExchange64( Addend,
  788. newValue,
  789. localAddend );
  790. } while (originalAddend != localAddend);
  791. return originalAddend;
  792. }
  793. #endif
  794. //
  795. // Barrier support for read-mostly operations
  796. // Note that the AMD64 and IA32 barrier relies on program ordering
  797. // and does not generate a hardware barrier
  798. //
  799. #if defined(_M_IA64)
  800. #define UL_READMOSTLY_READ_BARRIER() __mf()
  801. #define UL_READMOSTLY_WRITE_BARRIER() __mf()
  802. #define UL_READMOSTLY_MEMORY_BARRIER() __mf()
  803. #elif defined(_AMD64_) || defined(_X86_)
  804. extern "C" void _ReadWriteBarrier();
  805. extern "C" void _WriteBarrier();
  806. #pragma intrinsic(_ReadWriteBarrier)
  807. #pragma intrinsic(_WriteBarrier)
  808. #define UL_READMOSTLY_READ_BARRIER() _ReadWriteBarrier()
  809. #define UL_READMOSTLY_WRITE_BARRIER() _WriteBarrier()
  810. #define UL_READMOSTLY_MEMORY_BARRIER() _ReadWriteBarrier()
  811. #else
  812. #error Cannot generate memory barriers for this architecture
  813. #endif
  814. __inline
  815. PVOID
  816. UlpFixup(
  817. IN PUCHAR pUserPtr,
  818. IN PUCHAR pKernelPtr,
  819. IN PUCHAR pOffsetPtr,
  820. IN ULONG BufferLength
  821. )
  822. {
  823. ASSERT( pOffsetPtr >= pKernelPtr );
  824. ASSERT( DIFF(pOffsetPtr - pKernelPtr) <= BufferLength );
  825. return pUserPtr + DIFF(pOffsetPtr - pKernelPtr);
  826. } // UlpFixup
  827. #define FIXUP_PTR( Type, pUserPtr, pKernelPtr, pOffsetPtr, BufferLength ) \
  828. (Type)UlpFixup( \
  829. (PUCHAR)(pUserPtr), \
  830. (PUCHAR)(pKernelPtr), \
  831. (PUCHAR)(pOffsetPtr), \
  832. (BufferLength) \
  833. )
  834. //
  835. // Time utility to calculate the TimeZone Bias Daylight/standart
  836. // and returns one of the following values.
  837. // It's taken from base\client\timedate.c.
  838. // Once this two functions are exposed in the kernel we can get rid of
  839. // this two functions.
  840. //
  841. #define UL_TIME_ZONE_ID_INVALID 0xFFFFFFFF
  842. #define UL_TIME_ZONE_ID_UNKNOWN 0
  843. #define UL_TIME_ZONE_ID_STANDARD 1
  844. #define UL_TIME_ZONE_ID_DAYLIGHT 2
  845. BOOLEAN
  846. UlCutoverTimeToSystemTime(
  847. PTIME_FIELDS CutoverTime,
  848. PLARGE_INTEGER SystemTime,
  849. PLARGE_INTEGER CurrentSystemTime
  850. );
  851. ULONG
  852. UlCalcTimeZoneIdAndBias(
  853. IN RTL_TIME_ZONE_INFORMATION *ptzi,
  854. OUT PLONG pBias
  855. );
  856. #ifdef __cplusplus
  857. }; // extern "C"
  858. #endif
  859. #endif // _MISC_H_