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.

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