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.

753 lines
25 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. ntrtlstringandbuffer.h
  5. Abstract:
  6. Broken out from nturtl and rtl so I can move it between them in seperate
  7. trees without merge madness. To be integrated into ntrtl.h
  8. Author:
  9. Jay Krell (a-JayK) December 2000
  10. Environment:
  11. Revision History:
  12. --*/
  13. #ifndef _NTRTL_STRING_AND_BUFFER_
  14. #define _NTRTL_STRING_AND_BUFFER_
  15. #if _MSC_VER >= 1100
  16. #pragma once
  17. #endif
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. #if defined (_MSC_VER)
  22. #if ( _MSC_VER >= 800 )
  23. #pragma warning(disable:4514)
  24. #if _MSC_VER >= 1200
  25. #pragma warning(push)
  26. #endif
  27. #pragma warning(disable:4001)
  28. #pragma warning(disable:4201)
  29. #pragma warning(disable:4214)
  30. #endif
  31. #endif
  32. //
  33. // not NTSYSAPI so easily statically linked to
  34. //
  35. //
  36. // These work for both UNICODE_STRING and STRING.
  37. // That's why "plain" 0 and sizeof(Buffer[0]) is used.
  38. //
  39. // odd but correct use of RTL_STRING_IS_PUT_AT_SAFE instead of RTL_STRING_IS_GET_AT_SAFE,
  40. // we are reaching past the Length
  41. #define RTL_STRING_IS_NUL_TERMINATED(s) (RTL_STRING_IS_PUT_AT_SAFE(s, RTL_STRING_GET_LENGTH_CHARS(s), 0) \
  42. && RTL_STRING_GET_AT_UNSAFE(s, RTL_STRING_GET_LENGTH_CHARS(s)) == 0)
  43. #define RTL_STRING_NUL_TERMINATE(s) ((VOID)(ASSERT(RTL_STRING_IS_PUT_AT_SAFE(s, RTL_STRING_GET_LENGTH_CHARS(s), 0)), \
  44. ((s)->Buffer[RTL_STRING_GET_LENGTH_CHARS(s)] = 0)))
  45. #define RTL_NUL_TERMINATE_STRING(s) (RTL_STRING_NUL_TERMINATE(s)) /* compatibility */
  46. #define RTL_STRING_MAKE_LENGTH_INCLUDE_TERMINAL_NUL(s) ((VOID)(ASSERT(RTL_STRING_IS_NUL_TERMINATED(s)), \
  47. ((s)->Length += sizeof((s)->Buffer[0]))))
  48. #define RTL_STRING_IS_EMPTY(s) ((s)->Length == 0)
  49. #define RTL_STRING_GET_LAST_CHAR(s) (RTL_STRING_GET_AT((s), RTL_STRING_GET_LENGTH_CHARS(s) - 1))
  50. #define RTL_STRING_GET_LENGTH_CHARS(s) ((s)->Length / sizeof((s)->Buffer[0]))
  51. #define RTL_STRING_GET_MAX_LENGTH_CHARS(s) ((s)->MaximumLength / sizeof((s)->Buffer[0]))
  52. #define RTL_STRING_GET_LENGTH_BYTES(s) ((s)->Length)
  53. #define RTL_STRING_SET_LENGTH_CHARS_UNSAFE(s,n) ((s)->Length = (RTL_STRING_LENGTH_TYPE)(((n) * sizeof(s)->Buffer[0])))
  54. //
  55. // We don't provide an explicit/retail RTL_STRING_GET_AT_SAFE because it'd
  56. // need a return value distinct from all values of c. -1? NTSTATUS? Seems too heavy.
  57. //
  58. // For consistency then, we also don't provide RTL_STRING_PUT_AT_SAFE.
  59. //
  60. #define RTL_STRING_IS_GET_AT_SAFE(s,n) ((n) < RTL_STRING_GET_LENGTH_CHARS(s))
  61. #define RTL_STRING_GET_AT_UNSAFE(s,n) ((s)->Buffer[n])
  62. #define RTLP_STRING_GET_AT_SAFE(s,n) (RTL_STRING_IS_GET_AT_SAFE(s,n) ? RTL_STRING_GET_AT_UNSAFE(s,n) : 0)
  63. #define RTL_STRING_IS_PUT_AT_SAFE(s,n,c) ((n) < RTL_STRING_GET_MAX_LENGTH_CHARS(s))
  64. #define RTL_STRING_PUT_AT_UNSAFE(s,n,c) ((s)->Buffer[n] = (c))
  65. #define RTLP_STRING_PUT_AT_SAFE(s,n,c) ((void)(RTL_STRING_IS_PUT_AT_SAFE(s,n,c) ? RTL_STRING_PUT_AT_UNSAFE(s,n,c) : 0))
  66. #if defined(RTL_STRING_RANGE_CHECKED)
  67. #define RTL_STRING_GET_AT(s,n) (ASSERT(RTL_STRING_IS_GET_AT_SAFE(s,n)), \
  68. RTL_STRING_GET_AT_UNSAFE(s,n))
  69. #else
  70. #define RTL_STRING_GET_AT(s,n) (RTL_STRING_GET_AT_UNSAFE(s,n))
  71. #endif
  72. #if defined(RTL_STRING_RANGE_CHECKED)
  73. #define RTL_STRING_PUT_AT(s,n,c) (ASSERT(RTL_STRING_IS_PUT_AT_SAFE(s,n,c)), \
  74. RTL_STRING_PUT_AT_UNSAFE(s,n,c))
  75. #else
  76. #define RTL_STRING_PUT_AT(s,n,c) (RTL_STRING_PUT_AT_UNSAFE(s,n,c))
  77. #endif
  78. //
  79. // preallocated heap-growable buffers
  80. //
  81. struct _RTL_BUFFER;
  82. #if !defined(RTL_BUFFER)
  83. // This is duplicated in ntldr.h.
  84. #define RTL_BUFFER RTL_BUFFER
  85. typedef struct _RTL_BUFFER {
  86. PUCHAR Buffer;
  87. PUCHAR StaticBuffer;
  88. SIZE_T Size;
  89. SIZE_T StaticSize;
  90. SIZE_T ReservedForAllocatedSize; // for future doubling
  91. PVOID ReservedForIMalloc; // for future pluggable growth
  92. } RTL_BUFFER, *PRTL_BUFFER;
  93. #endif
  94. #define RTLP_BUFFER_IS_HEAP_ALLOCATED(b) ((b)->Buffer != (b)->StaticBuffer)
  95. //++
  96. //
  97. // NTSTATUS
  98. // RtlInitBuffer(
  99. // OUT PRTL_BUFFER Buffer,
  100. // IN PUCHAR StaticBuffer,
  101. // IN SIZE_T StaticSize
  102. // );
  103. //
  104. // Routine Description:
  105. //
  106. // Initialize a preallocated heap-growable buffer.
  107. //
  108. // Arguments:
  109. //
  110. // Buffer - "this"
  111. // StaticBuffer - preallocated storage for Buffer to use until/unless more than StaticSize is needed
  112. // StaticSize - the size of StaticBuffer in bytes
  113. //
  114. // Return Value:
  115. //
  116. // STATUS_SUCCESS
  117. //
  118. //--
  119. #define RtlInitBuffer(Buff, StatBuff, StatSize) \
  120. do { \
  121. (Buff)->Buffer = (StatBuff); \
  122. (Buff)->Size = (StatSize); \
  123. (Buff)->StaticBuffer = (StatBuff); \
  124. (Buff)->StaticSize = (StatSize); \
  125. } while (0)
  126. #define RTL_ENSURE_BUFFER_SIZE_NO_COPY (0x00000001)
  127. NTSTATUS
  128. NTAPI
  129. RtlpEnsureBufferSize(
  130. IN ULONG Flags,
  131. IN OUT PRTL_BUFFER Buffer,
  132. IN SIZE_T NewSizeBytes
  133. );
  134. //++
  135. //
  136. // NTSTATUS
  137. // RtlEnsureBufferSize(
  138. // IN OUT PRTL_BUFFER Buffer,
  139. // IN SIZE_T NewSizeBytes
  140. // );
  141. //
  142. // Routine Description:
  143. //
  144. // If Buffer is smaller than NewSize, grow it to NewSize, using the static buffer if it
  145. // is large enough, else heap allocating
  146. //
  147. // Arguments:
  148. //
  149. // Flags -
  150. // RTL_ENSURE_BUFFER_SIZE_NO_COPY
  151. // Buffer -
  152. // NewSizeBytes -
  153. //
  154. // Return Value:
  155. //
  156. // STATUS_SUCCESS
  157. // STATUS_NO_MEMORY
  158. //
  159. //--
  160. #define RtlEnsureBufferSize(Flags, Buff, NewSizeBytes) \
  161. ( ((Buff) != NULL && (NewSizeBytes) <= (Buff)->Size) \
  162. ? STATUS_SUCCESS \
  163. : RtlpEnsureBufferSize((Flags), (Buff), (NewSizeBytes)) \
  164. )
  165. //++
  166. //
  167. // VOID
  168. // RtlFreeBuffer(
  169. // IN OUT PRTL_BUFFER Buffer,
  170. // );
  171. //
  172. //
  173. // Routine Description:
  174. //
  175. // Free any heap allocated storage associated with Buffer.
  176. // Notes:
  177. // - RtlFreeBuffer returns a buffer to the state it was in after
  178. // calling RtlInitBuffer, so you may reuse it.
  179. // - If you want to shrink the buffer without freeing it, just poke Buffer->Size down.
  180. // This is safe regardless of if the buffer has gone heap allocated or not.
  181. // - You may RtlFreeBuffer an RTL_BUFFER that is all zeros. You do not need to track if you
  182. // called RtlInitBuffer if you know you filled it with zeros.
  183. // - You may RtlFreeBuffer an RTL_BUFFER repeatedly.
  184. //
  185. // Arguments:
  186. //
  187. // Buffer -
  188. //
  189. // Return Value:
  190. //
  191. // none, unconditional success
  192. //
  193. //--
  194. #define RtlFreeBuffer(Buff) \
  195. do { \
  196. if ((Buff) != NULL && (Buff)->Buffer != NULL) { \
  197. if (RTLP_BUFFER_IS_HEAP_ALLOCATED(Buff)) { \
  198. UNICODE_STRING UnicodeString; \
  199. UnicodeString.Buffer = (PWSTR)(PVOID)(Buff)->Buffer; \
  200. RtlFreeUnicodeString(&UnicodeString); \
  201. } \
  202. (Buff)->Buffer = (Buff)->StaticBuffer; \
  203. (Buff)->Size = (Buff)->StaticSize; \
  204. } \
  205. } while (0)
  206. //
  207. // a preallocated buffer that is "tied" to a UNICODE_STRING
  208. //
  209. struct _RTL_UNICODE_STRING_BUFFER;
  210. typedef struct _RTL_UNICODE_STRING_BUFFER {
  211. UNICODE_STRING String;
  212. RTL_BUFFER ByteBuffer;
  213. UCHAR MinimumStaticBufferForTerminalNul[sizeof(WCHAR)];
  214. } RTL_UNICODE_STRING_BUFFER, *PRTL_UNICODE_STRING_BUFFER;
  215. //
  216. // MAX_UNICODE_STRING_MAXLENGTH is the maximum allowed value for UNICODE_STRING::MaximumLength.
  217. // MAX_UNICODE_STRING_LENGTH is the maximum allowed value for UNICODE_STRING::Length, allowing
  218. // room for a terminal nul.
  219. //
  220. // Explanation of MAX_UNICODE_STRING_MAXLENGTH implementation
  221. // ~0 is all bits set, maximum value in two's complement arithmetic, which C guarantees for unsigned types
  222. // << shifts out the number of bits that fit in UNICODE_STRING::Length
  223. // ~ and now we have all bits set that fit in UNICODE_STRING::Length,
  224. // like if UNICODE_STRING::Length is 16 bits, we have 0xFFFF
  225. // then mask so it is even multiple of whatever UNICODE_STRING::Buffer points to.
  226. // If Length is changed to ULONG or SIZE_T, this macro is still correct.
  227. // If Buffer pointed to CHAR or "WIDER_CHAR" or something else, this macro is still correct.
  228. //
  229. #define MAX_UNICODE_STRING_MAXLENGTH ((~((~(SIZE_T)0) << (RTL_FIELD_SIZE(UNICODE_STRING, Length) * CHAR_BIT))) & ~(sizeof(((PCUNICODE_STRING)0)->Buffer[0]) - 1))
  230. #define MAX_UNICODE_STRING_LENGTH (MAX_UNICODE_STRING_MAXLENGTH - sizeof(((PCUNICODE_STRING)0)->Buffer[0]))
  231. //++
  232. //
  233. // NTSTATUS
  234. // RtlInitUnicodeStringBuffer(
  235. // OUT PRTL_UNICODE_STRING_BUFFER Buffer,
  236. // IN PUCHAR StaticBuffer,
  237. // IN SIZE_T StaticSize
  238. // );
  239. //
  240. // Routine Description:
  241. //
  242. //
  243. // Arguments:
  244. //
  245. // Buffer -
  246. // StaticBuffer - can be NULL, but generally is not
  247. // StaticSize - should be at least sizeof(WCHAR), but can be zero
  248. // ought to be an even multiple of sizeof(WCHAR)
  249. // gets rounded to down to an even multiple of sizeof(WCHAR)
  250. // gets clamped to MAX_UNICODE_STRING_MAXLENGTH (64k - 2)
  251. //
  252. // RTL_UNICODE_STRING_BUFFER contains room for the terminal nul for the
  253. // case of StaticBuffer == NULL or StaticSize < sizeof(WCHAR), or, more likely,
  254. // for RtlTakeRemainingStaticBuffer leaving it with no static buffer.
  255. //
  256. // Return Value:
  257. //
  258. // STATUS_SUCCESS
  259. //
  260. //--
  261. #define RtlInitUnicodeStringBuffer(Buff, StatBuff, StatSize) \
  262. do { \
  263. SIZE_T TempStaticSize = (StatSize); \
  264. PUCHAR TempStaticBuff = (StatBuff); \
  265. TempStaticSize &= ~(sizeof((Buff)->String.Buffer[0]) - 1); \
  266. if (TempStaticSize > UNICODE_STRING_MAX_BYTES) { \
  267. TempStaticSize = UNICODE_STRING_MAX_BYTES; \
  268. } \
  269. if (TempStaticSize < sizeof(WCHAR)) { \
  270. TempStaticBuff = (Buff)->MinimumStaticBufferForTerminalNul; \
  271. TempStaticSize = sizeof(WCHAR); \
  272. } \
  273. RtlInitBuffer(&(Buff)->ByteBuffer, TempStaticBuff, TempStaticSize); \
  274. (Buff)->String.Buffer = (WCHAR*)TempStaticBuff; \
  275. if ((Buff)->String.Buffer != NULL) \
  276. (Buff)->String.Buffer[0] = 0; \
  277. (Buff)->String.Length = 0; \
  278. (Buff)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)TempStaticSize; \
  279. } while (0)
  280. //++
  281. //
  282. // NTSTATUS
  283. // RtlSyncStringToBuffer(
  284. // IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer
  285. // );
  286. //
  287. // Routine Description:
  288. //
  289. // After carefully modifying the underlying RTL_BUFFER, this updates
  290. // dependent fields in the underlying UNICODE_STRING.
  291. //
  292. // For example, use this after you grow the buffer with RtlEnsureBufferSize,
  293. // but that example you don't need, use RtlEnsureUnicodeStringBufferSizeChars
  294. // or RtlEnsureStringBufferSizeBytes.
  295. //
  296. // Arguments:
  297. //
  298. // UnicodeStringBuffer -
  299. //
  300. // Return Value:
  301. //
  302. // STATUS_SUCCESS - hooray
  303. //
  304. //--
  305. #define RtlSyncStringToBuffer(x) \
  306. ( \
  307. ( ASSERT((x)->String.Length < (x)->ByteBuffer.Size) ), \
  308. ( ASSERT((x)->String.MaximumLength >= (x)->String.Length) ), \
  309. ( ASSERT((x)->String.MaximumLength <= (x)->ByteBuffer.Size) ), \
  310. ( (x)->String.Buffer = (PWSTR)(x)->ByteBuffer.Buffer ), \
  311. ( (x)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)((x)->ByteBuffer.Size) ), \
  312. ( ASSERT(RTL_STRING_IS_NUL_TERMINATED(&(x)->String)) ), \
  313. ( STATUS_SUCCESS ) \
  314. )
  315. //++
  316. //
  317. // NTSTATUS
  318. // RtlSyncBufferToString(
  319. // IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer
  320. // );
  321. //
  322. // Routine Description:
  323. //
  324. // After carefully modifying the underlying UNICODE_STRING, this updates
  325. // dependent fields in the underlying RTL_BUFFER.
  326. //
  327. // For example, use this after you the alloc the buffer with RtlAnsiStringToUnicodeString.
  328. // This is possible because RTL_BUFFER deliberately uses the same memory allocator
  329. // as RtlAnsiStringToUnicodeString.
  330. //
  331. // Arguments:
  332. //
  333. // UnicodeStringBuffer -
  334. //
  335. // Return Value:
  336. //
  337. // STATUS_SUCCESS - hooray
  338. //
  339. //--
  340. #define RtlSyncBufferToString(Buff_) \
  341. ( \
  342. ( (Buff_)->ByteBuffer.Buffer = (Buff_)->String.Buffer ), \
  343. ( (Buff_)->ByteBuffer.Buffer.Size = (Buff_)->String.MaximumLength ), \
  344. ( STATUS_SUCCESS ) \
  345. )
  346. //++
  347. //
  348. // NTSTATUS
  349. // RtlEnsureUnicodeStringBufferSizeChars(
  350. // IN OUT PRTL_BUFFER Buffer,
  351. // IN USHORT NewSizeChars
  352. // );
  353. //
  354. // NTSTATUS
  355. // RtlEnsureUnicodeStringBufferSizeBytes(
  356. // IN OUT PRTL_BUFFER Buffer,
  357. // IN USHORT NewSizeBytes
  358. // );
  359. //
  360. // Routine Description:
  361. //
  362. // Optionally multiply cch to go from count of character to count of bytes.
  363. // +1 or +2 for you to account for the terminal nul.
  364. // Delegate to underlying RtlEnsureBufferSize.
  365. // Keep String.Buffer, .MaximumLength, and terminal nul in sync.
  366. //
  367. // Arguments:
  368. //
  369. // Buffer -
  370. // NewSizeChars -
  371. // NewSizeBytes - must be a multiple of sizeof(WCHAR), and we don't presently
  372. // verify that.
  373. //
  374. // Return Value:
  375. //
  376. // STATUS_SUCCESS - hooray
  377. // STATUS_NO_MEMORY - out of memory
  378. // STATUS_NAME_TOO_LONG - (NewSizeChars + 1) * sizeof(WCHAR) > UNICODE_STRING_MAX_BYTES (USHORT)
  379. //
  380. //--
  381. #define RtlEnsureUnicodeStringBufferSizeBytes(Buff_, NewSizeBytes_) \
  382. ( ( ((NewSizeBytes_) + sizeof((Buff_)->String.Buffer[0])) > UNICODE_STRING_MAX_BYTES ) \
  383. ? STATUS_NAME_TOO_LONG \
  384. : !NT_SUCCESS(RtlEnsureBufferSize(0, &(Buff_)->ByteBuffer, ((NewSizeBytes_) + sizeof((Buff_)->String.Buffer[0])))) \
  385. ? STATUS_NO_MEMORY \
  386. : (RtlSyncStringToBuffer(Buff_)) \
  387. )
  388. #define RtlEnsureUnicodeStringBufferSizeChars(Buff_, NewSizeChars_) \
  389. (RtlEnsureUnicodeStringBufferSizeBytes((Buff_), (NewSizeChars_) * sizeof((Buff_)->String.Buffer[0])))
  390. //++
  391. //
  392. // NTSTATUS
  393. // RtlAppendUnicodeStringBuffer(
  394. // OUT PRTL_UNICODE_STRING_BUFFER Destination,
  395. // IN PCUNICODE_STRING Source
  396. // );
  397. //
  398. // Routine Description:
  399. //
  400. //
  401. // Arguments:
  402. //
  403. // Destination -
  404. // Source -
  405. //
  406. // Return Value:
  407. //
  408. // STATUS_SUCCESS
  409. // STATUS_NO_MEMORY
  410. // STATUS_NAME_TOO_LONG (64K UNICODE_STRING length would be exceeded)
  411. //
  412. //--
  413. #define RtlAppendUnicodeStringBuffer(Dest, Source) \
  414. ( ( ( (Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]) ) > UNICODE_STRING_MAX_BYTES ) \
  415. ? STATUS_NAME_TOO_LONG \
  416. : (!NT_SUCCESS( \
  417. RtlEnsureBufferSize( \
  418. 0, \
  419. &(Dest)->ByteBuffer, \
  420. (Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]) ) ) \
  421. ? STATUS_NO_MEMORY \
  422. : ( ( (Dest)->String.Buffer = (PWSTR)(Dest)->ByteBuffer.Buffer ), \
  423. ( RtlMoveMemory( \
  424. (Dest)->String.Buffer + (Dest)->String.Length / sizeof((Dest)->String.Buffer[0]), \
  425. (Source)->Buffer, \
  426. (Source)->Length) ), \
  427. ( (Dest)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)((Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]))), \
  428. ( (Dest)->String.Length = (USHORT) ((Dest)->String.Length + (Source)->Length )), \
  429. ( (Dest)->String.Buffer[(Dest)->String.Length / sizeof((Dest)->String.Buffer[0])] = 0 ), \
  430. ( STATUS_SUCCESS ) ) ) )
  431. NTSTATUS
  432. NTAPI
  433. RtlMultiAppendUnicodeStringBuffer(
  434. OUT PRTL_UNICODE_STRING_BUFFER Destination,
  435. IN ULONG NumberOfSources,
  436. IN const UNICODE_STRING* SourceArray
  437. );
  438. //++
  439. //
  440. // VOID
  441. // RtlFreeUnicodeStringBuffer(
  442. // OUT PRTL_UNICODE_STRING_BUFFER Buffer
  443. // );
  444. //
  445. // Routine Description:
  446. //
  447. // Arguments:
  448. //
  449. // Buffer -
  450. //
  451. // Return Value:
  452. //
  453. // none, unconditional success
  454. //
  455. // If Buffer is a local, the stores are generally "dead" (their result
  456. // is never read) and the optimizer should "kill" them (not bother performing them).
  457. //
  458. // A buffer can be freed multiple times.
  459. // A buffer that has been freed is in the same state as one that just been inited.
  460. // A buffer that is all zeros (RtlZeroMemory) can be freed. You do not need to
  461. // track if you inited it.
  462. //--
  463. #define RtlFreeUnicodeStringBuffer(Buff) \
  464. do { \
  465. if ((Buff) != NULL) { \
  466. RtlFreeBuffer(&(Buff)->ByteBuffer); \
  467. (Buff)->String.Buffer = (PWSTR)(Buff)->ByteBuffer.StaticBuffer; \
  468. if ((Buff)->String.Buffer != NULL) \
  469. (Buff)->String.Buffer[0] = 0; \
  470. (Buff)->String.Length = 0; \
  471. (Buff)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)(Buff)->ByteBuffer.StaticSize; \
  472. } \
  473. } while (0)
  474. //++
  475. //
  476. // NTSTATUS
  477. // RtlAssignUnicodeStringBuffer(
  478. // IN OUT PRTL_UNICODE_STRING_BUFFER Buffer,
  479. // PCUNICODE_STRING String
  480. // );
  481. // Routine Description:
  482. //
  483. // Arguments:
  484. //
  485. // Buffer -
  486. // String -
  487. //
  488. // Return Value:
  489. //
  490. // STATUS_SUCCESS
  491. // STATUS_NO_MEMORY
  492. //--
  493. #define RtlAssignUnicodeStringBuffer(Buff, Str) \
  494. (((Buff)->String.Length = 0), (RtlAppendUnicodeStringBuffer((Buff), (Str))))
  495. //++
  496. //
  497. // NTSTATUS
  498. // RtlTakeRemainingStaticBuffer(
  499. // IN OUT PRTL_BUFFER Buffer,
  500. // OUT PUCHAR* RemainingStaticBuffer,
  501. // OUT SIZE_T* RemainingStaticSize
  502. // );
  503. //
  504. // Routine Description:
  505. //
  506. // This function makes it easy to share a static buffer among
  507. // multiple buffers, as long as the buffers are actually initialized
  508. // and "sealed" linearly/independently/one after another with
  509. // no "overlap" (overlap in control and dataflow, not in actual addresses).
  510. //
  511. // Note that if a buffer is using exactly all of its static buffer, you
  512. // will get back 0 and STATUS_SUCCESS. This is not an error condition.
  513. // This is why RtlInitUnicodeStringBuffer can now accept zero sized static buffers.
  514. //
  515. // Note that even if you violate the conditions that make this function most
  516. // useful, your code will still work, just less quickly.
  517. //
  518. // A pattern that should work is allocating one static buffer and moving it "through"
  519. // multiple buffers. Even if you run out of static space, it should work to
  520. // move the remaining zero size static buffer forward. Of course, you'll heap allocate.
  521. //
  522. // Arguments:
  523. //
  524. // Buffer -
  525. // RemainingStaticBuffer -
  526. // RemainingStaticSize -
  527. //
  528. // Return Value:
  529. //
  530. // STATUS_SUCCESS
  531. //
  532. //--
  533. #define RtlTakeRemainingStaticBuffer(Buff, OutBuff, OutSize) \
  534. (((Buff)->Buffer != (Buff)->StaticBuffer) \
  535. ? ( /* take the whole thing */ \
  536. ( *(OutBuff) = (Buff)->StaticBuffer ), \
  537. ( *(OutSize) = (Buff)->StaticSize ), \
  538. /* leave the buffer with nothing */ \
  539. ( (Buff)->StaticBuffer = NULL ), \
  540. ( (Buff)->StaticSize = 0 ), \
  541. ( STATUS_SUCCESS ) \
  542. ) \
  543. : ( /* only take what isn't being used */ \
  544. ( *(OutBuff) = &(Buff)->StaticBuffer[(Buff)->Size] ), \
  545. ( *(OutSize) = ((Buff)->StaticSize - (Buff)->Size) ), \
  546. /* leave the buffer with just what it is using */ \
  547. ( (Buff)->StaticSize = (Buff)->Size ), \
  548. ( STATUS_SUCCESS ) \
  549. ))
  550. NTSTATUS
  551. NTAPI
  552. RtlPrependStringToUnicodeStringBuffer(
  553. IN ULONG Flags,
  554. IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer,
  555. IN PCUNICODE_STRING UnicodeString
  556. );
  557. NTSTATUS
  558. NTAPI
  559. RtlUnicodeStringBufferRight(
  560. IN ULONG Flags,
  561. IN OUT PRTL_UNICODE_STRING_BUFFER Buffer,
  562. IN ULONG Length
  563. );
  564. NTSTATUS
  565. NTAPI
  566. RtlUnicodeStringBufferLeft(
  567. IN ULONG Flags,
  568. IN OUT PRTL_UNICODE_STRING_BUFFER Buffer,
  569. IN ULONG Length
  570. );
  571. NTSTATUS
  572. NTAPI
  573. RtlUnicodeStringBufferMid(
  574. IN ULONG Flags,
  575. IN OUT PRTL_UNICODE_STRING_BUFFER Buffer,
  576. IN ULONG Offset,
  577. IN ULONG Length
  578. );
  579. NTSTATUS
  580. NTAPI
  581. RtlInsertStringIntoUnicodeStringBuffer(
  582. IN ULONG Flags,
  583. IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer,
  584. IN ULONG Offset,
  585. IN PCUNICODE_STRING InsertString
  586. );
  587. NTSTATUS
  588. NTAPI
  589. RtlBufferTakeValue(
  590. IN ULONG Flags,
  591. IN OUT PRTL_BUFFER DestinationBuffer,
  592. IN OUT PRTL_BUFFER SourceBuffer
  593. );
  594. //++
  595. //
  596. // NTSTATUS
  597. // RtlUnicodeStringBufferTakeValue(
  598. // OUT NTSTATUS* Status,
  599. // IN ULONG Flags,
  600. // IN OUT RTL_UNICODE_STRING_BUFFER DestinationBuffer,
  601. // IN OUT RTL_UNICODE_STRING_BUFFER SourceBuffer
  602. // );
  603. //
  604. //--
  605. #define RtlUnicodeStringBufferTakeValue(Status, Flags, DestinationBuffer, SourceBuffer) \
  606. ( \
  607. ((Flags) != 0) \
  608. ? (*(Status) = STATUS_INVALID_PARAMETER) \
  609. : (!NT_SUCCESS(*(Status) = RtlBufferTakeValue(0, &(DestinationBuffer)->ByteBuffer, &(SourceBuffer)->ByteBuffer))) \
  610. ? (*(Status)) \
  611. : (*(Status) = RtlSyncStringToBuffer(DestinationBuffer), RtlSyncStringToBuffer(SourceBuffer)) \
  612. )
  613. NTSTATUS
  614. NTAPI
  615. RtlValidateBuffer(
  616. IN ULONG Flags,
  617. IN CONST RTL_BUFFER* Buffer
  618. );
  619. NTSTATUS
  620. NTAPI
  621. RtlValidateUnicodeStringBuffer(
  622. IN ULONG Flags,
  623. IN CONST RTL_UNICODE_STRING_BUFFER* UnicodeStringBuffer
  624. );
  625. #define RTL_FIND_AND_REPLACE_CHARACTER_IN_STRING_CASE_SENSITIVE (0x00000001)
  626. NTSTATUS
  627. NTAPI
  628. RtlFindAndReplaceCharacterInString(
  629. ULONG Flags,
  630. PVOID Reserved,
  631. PUNICODE_STRING String,
  632. WCHAR Find,
  633. WCHAR Replace
  634. );
  635. typedef struct _RTL_ANSI_STRING_BUFFER {
  636. ANSI_STRING String;
  637. RTL_BUFFER ByteBuffer;
  638. UCHAR MinimumStaticBufferForTerminalNul[1];
  639. } RTL_ANSI_STRING_BUFFER, *PRTL_ANSI_STRING_BUFFER;
  640. NTSTATUS
  641. NTAPI
  642. RtlInitAnsiStringBuffer(
  643. PRTL_ANSI_STRING_BUFFER StringBuffer,
  644. PUCHAR StaticBuffer,
  645. SIZE_T StaticSize
  646. );
  647. VOID
  648. NTAPI
  649. RtlFreeAnsiStringBuffer(
  650. PRTL_ANSI_STRING_BUFFER AnsiStringBuffer
  651. );
  652. NTSTATUS
  653. NTAPI
  654. RtlAssignAnsiStringBufferFromUnicodeString(
  655. PRTL_ANSI_STRING_BUFFER AnsiStringBuffer,
  656. PCUNICODE_STRING UnicodeString
  657. );
  658. NTSTATUS
  659. NTAPI
  660. RtlAssignAnsiStringBufferFromUnicode(
  661. PRTL_ANSI_STRING_BUFFER AnsiStringBuffer,
  662. PCWSTR Unicode
  663. );
  664. NTSTATUS
  665. NTAPI
  666. RtlUnicodeStringBufferEnsureTrailingNtPathSeperator(
  667. PRTL_UNICODE_STRING_BUFFER StringBuffer
  668. );
  669. #ifdef __cplusplus
  670. } // extern "C"
  671. #endif
  672. #if defined (_MSC_VER) && ( _MSC_VER >= 800 )
  673. #if _MSC_VER >= 1200
  674. #pragma warning(pop)
  675. #else
  676. #pragma warning(default:4001)
  677. #pragma warning(default:4201)
  678. #pragma warning(default:4214)
  679. #endif
  680. #endif
  681. #endif