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.

544 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. stralign.h
  5. Abstract:
  6. This module contains macros and prototypes to expose the unaligned wide
  7. character interfaces.
  8. Public interfaces created or declared here include:
  9. ua_CharUpper()
  10. ua_CharUpperW()
  11. ua_lstrcmp()
  12. ua_lstrcmpW()
  13. ua_lstrcmpi()
  14. ua_lstrcmpiW()
  15. ua_lstrlen()
  16. ua_lstrlenW()
  17. ua_tcscpy()
  18. ua_wcschr()
  19. ua_wcscpy()
  20. ua_wcslen()
  21. ua_wcsrchr()
  22. STRUC_ALIGNED_STACK_COPY()
  23. TSTR_ALIGNED()
  24. TSTR_ALIGNED_STACK_COPY()
  25. WSTR_ALIGNED()
  26. WSTR_ALIGNED_STACK_COPY()
  27. Author:
  28. Revision History:
  29. --*/
  30. #if !defined(__STRALIGN_H_) && !defined(MIDL_PASS)
  31. #define __STRALIGN_H_
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. #if defined(_X86_)
  36. //
  37. // Alignment of unicode strings is not necessary on X86.
  38. //
  39. #define WSTR_ALIGNED(s) TRUE
  40. #define ua_CharUpperW CharUpperW
  41. #define ua_lstrcmpiW lstrcmpiW
  42. #define ua_lstrcmpW lstrcmpW
  43. #define ua_lstrlenW lstrlenW
  44. #define ua_wcschr wcschr
  45. #define ua_wcscpy wcscpy
  46. #define ua_wcslen wcslen
  47. #define ua_wcsrchr wcsrchr
  48. #else
  49. //
  50. // The C runtime libraries expect aligned string pointers. Following are the
  51. // prototypes for our own, slower worker functions that accept unaligned
  52. // UNICODE strings.
  53. //
  54. //
  55. // Macro to determine whether a pointer to a unicode character is naturally
  56. // aligned.
  57. //
  58. #define WSTR_ALIGNED(s) (((DWORD_PTR)(s) & (sizeof(WCHAR)-1)) == 0)
  59. //
  60. // Platform-specific prototypes for worker functions exported from kernel32.
  61. // Do not call these directly, they do not exist on all platforms. Instead
  62. // use the equivalent ua_xxx() routines.
  63. //
  64. LPUWSTR
  65. WINAPI
  66. uaw_CharUpperW(
  67. IN OUT LPUWSTR String
  68. );
  69. int
  70. APIENTRY
  71. uaw_lstrcmpW(
  72. IN PCUWSTR String1,
  73. IN PCUWSTR String2
  74. );
  75. int
  76. APIENTRY
  77. uaw_lstrcmpiW(
  78. IN PCUWSTR String1,
  79. IN PCUWSTR String2
  80. );
  81. int
  82. WINAPI
  83. uaw_lstrlenW(
  84. IN LPCUWSTR String
  85. );
  86. PUWSTR
  87. __cdecl
  88. uaw_wcschr(
  89. IN PCUWSTR String,
  90. IN WCHAR Character
  91. );
  92. PUWSTR
  93. _cdecl
  94. uaw_wcscpy(
  95. IN PUWSTR Destination,
  96. IN PCUWSTR Source
  97. );
  98. size_t
  99. __cdecl
  100. uaw_wcslen(
  101. IN PCUWSTR String
  102. );
  103. PUWSTR
  104. __cdecl
  105. uaw_wcsrchr(
  106. IN PCUWSTR String,
  107. IN WCHAR Character
  108. );
  109. //
  110. // Following are the inline wrappers that determine the optimal worker function
  111. // to call based on the alignment of the UNICODE string arguments. Their
  112. // behavior is otherwise identical to the corresponding standard run-time
  113. // routiunes.
  114. //
  115. #if defined(CharUpper)
  116. __inline
  117. LPUWSTR
  118. static
  119. ua_CharUpperW(
  120. LPUWSTR String
  121. )
  122. {
  123. if (WSTR_ALIGNED(String)) {
  124. return CharUpperW( (PWSTR)String );
  125. } else {
  126. return uaw_CharUpperW( String );
  127. }
  128. }
  129. #endif
  130. #if defined(lstrcmp)
  131. __inline
  132. int
  133. static
  134. ua_lstrcmpW(
  135. IN LPCUWSTR String1,
  136. IN LPCUWSTR String2
  137. )
  138. {
  139. if (WSTR_ALIGNED(String1) && WSTR_ALIGNED(String2)) {
  140. return lstrcmpW( (LPCWSTR)String1, (LPCWSTR)String2);
  141. } else {
  142. return uaw_lstrcmpW( String1, String2 );
  143. }
  144. }
  145. #endif
  146. #if defined(lstrcmpi)
  147. __inline
  148. int
  149. static
  150. ua_lstrcmpiW(
  151. IN LPCUWSTR String1,
  152. IN LPCUWSTR String2
  153. )
  154. {
  155. if (WSTR_ALIGNED(String1) && WSTR_ALIGNED(String2)) {
  156. return lstrcmpiW( (LPCWSTR)String1, (LPCWSTR)String2 );
  157. } else {
  158. return uaw_lstrcmpiW( String1, String2 );
  159. }
  160. }
  161. #endif
  162. #if defined(lstrlen)
  163. __inline
  164. int
  165. static
  166. ua_lstrlenW(
  167. IN LPCUWSTR String
  168. )
  169. {
  170. if (WSTR_ALIGNED(String)) {
  171. return lstrlenW( (PCWSTR)String );
  172. } else {
  173. return uaw_lstrlenW( String );
  174. }
  175. }
  176. #endif
  177. #if defined(_WSTRING_DEFINED)
  178. //
  179. // Certain run-time string functions are overloaded in C++, to avoid
  180. // inadvertent stripping of the const attribute.
  181. //
  182. // The functions of interest here include: wcschr and wcsrchr.
  183. //
  184. // There are three flavors of these functions:
  185. //
  186. // Flavor Returns Parameter
  187. //
  188. // 1 PWSTR PCWSTR
  189. // 2 PCWSTR PCWSTR
  190. // 3 PWSTR PWSTR
  191. //
  192. // string.h declares flavor 1 whether for C or C++. This is the non-ANSI,
  193. // backward compatible mode.
  194. //
  195. // wchar.h declares flavor 1 if C, or flavors 2 and 3 if C++. This is the
  196. // ANSI method.
  197. //
  198. // Our corresponding functions need to match what was declared. The way
  199. // we can tell is by looking at _WConst_return... if it is defined then
  200. // we want to match the prototypes in wchar.h, otherwise we'll match
  201. // the prototypes in string.h.
  202. //
  203. #if defined(_WConst_return)
  204. typedef _WConst_return WCHAR UNALIGNED *PUWSTR_C;
  205. #else
  206. typedef WCHAR UNALIGNED *PUWSTR_C;
  207. #endif
  208. //
  209. // Here is flavor 1 or 2
  210. //
  211. __inline
  212. PUWSTR_C
  213. static
  214. ua_wcschr(
  215. IN PCUWSTR String,
  216. IN WCHAR Character
  217. )
  218. {
  219. if (WSTR_ALIGNED(String)) {
  220. return wcschr((PCWSTR)String, Character);
  221. } else {
  222. return (PUWSTR_C)uaw_wcschr(String, Character);
  223. }
  224. }
  225. __inline
  226. PUWSTR_C
  227. static
  228. ua_wcsrchr(
  229. IN PCUWSTR String,
  230. IN WCHAR Character
  231. )
  232. {
  233. if (WSTR_ALIGNED(String)) {
  234. return wcsrchr((PCWSTR)String, Character);
  235. } else {
  236. return (PUWSTR_C)uaw_wcsrchr(String, Character);
  237. }
  238. }
  239. #if defined(__cplusplus) && defined(_WConst_Return)
  240. //
  241. // Here is flavor 3
  242. //
  243. __inline
  244. PUWSTR
  245. static
  246. ua_wcschr(
  247. IN PUWSTR String,
  248. IN WCHAR Character
  249. )
  250. {
  251. if (WSTR_ALIGNED(String)) {
  252. return wcschr(String, Character);
  253. } else {
  254. return uaw_wcschr((PCUWSTR)String, Character);
  255. }
  256. }
  257. __inline
  258. PUWSTR
  259. static
  260. ua_wcsrchr(
  261. IN PUWSTR String,
  262. IN WCHAR Character
  263. )
  264. {
  265. if (WSTR_ALIGNED(String)) {
  266. return wcsrchr(String, Character);
  267. } else {
  268. return uaw_wcsrchr((PCUWSTR)String, Character);
  269. }
  270. }
  271. #endif // __cplusplus && _WConst_Return
  272. __inline
  273. PUWSTR
  274. static
  275. ua_wcscpy(
  276. IN PUWSTR Destination,
  277. IN PCUWSTR Source
  278. )
  279. {
  280. if (WSTR_ALIGNED(Source) && WSTR_ALIGNED(Destination)) {
  281. return wcscpy( (PWSTR)Destination, (PCWSTR)Source );
  282. } else {
  283. return uaw_wcscpy( Destination, Source );
  284. }
  285. }
  286. __inline
  287. size_t
  288. static
  289. ua_wcslen(
  290. IN PCUWSTR String
  291. )
  292. {
  293. if (WSTR_ALIGNED(String)) {
  294. return wcslen( (PCWSTR)String );
  295. } else {
  296. return uaw_wcslen( String );
  297. }
  298. }
  299. #endif // _WSTRING_DEFINED
  300. #endif // _X86_
  301. //++
  302. //
  303. // VOID
  304. // WSTR_ALIGNED_STACK_COPY (
  305. // OUT PCWSTR *TargetString,
  306. // IN PCUWSTR SourceString OPTIONAL
  307. // )
  308. //
  309. // VOID
  310. // TSTR_ALIGNED_STACK_COPY (
  311. // OUT PCTSTR *TargetString,
  312. // IN PCUTSTR SourceString OPTIONAL
  313. // )
  314. //
  315. // Routine Description:
  316. //
  317. // These macros set TargetString to an aligned pointer to the string
  318. // represented by SourceString. If necessary, an aligned copy of
  319. // SourceString is copied onto the stack.
  320. //
  321. // Arguments:
  322. //
  323. // TargetString - Supplies a pointer to a pointer to the resultant
  324. // string. This may be the same as SourceString if
  325. // that argument is aligned.
  326. //
  327. // SourceString - Supplies a pointer to the possibly unaligned UNICODE
  328. // string.
  329. //
  330. // Return Value:
  331. //
  332. // None.
  333. //
  334. // Note:
  335. //
  336. // These macros may allocate memory on the stack via the CRT function
  337. // _alloca(). This memory is "freed" when the calling function exits.
  338. // As a result, do not use these macros inside of a loop that may execute
  339. // a large number of times - instead, use a wrapper function, or use
  340. // an explicit buffer like this:
  341. //
  342. // TCHAR AlignedStringBuffer[ MAX_FOOSTR_CHARS ];
  343. // PTSTR AlignedString;
  344. //
  345. // while (a < b) {
  346. // ...
  347. // if (TSTR_ALIGNED(s) {
  348. // AlignedString = s;
  349. // } else {
  350. // AlignedString = (PTSTR)ua_tcscpy(AlignedStringBuffer,s);
  351. // }
  352. // SomeSystemFunction(AlignedString);
  353. // ...
  354. // }
  355. //
  356. //
  357. //--
  358. //
  359. // __UA_WSTRSIZE returns the number of bytes required to store the
  360. // supplied null-terminated UNICODE string.
  361. //
  362. // __UA_LOCALCOPY accepts a pointer to unaligned data and a size. It
  363. // allocates an aligned buffer on the stack and copies the data into
  364. // it, returning a pointer to the buffer.
  365. //
  366. #if !defined(__UA_WCSLEN)
  367. #define __UA_WCSLEN ua_wcslen
  368. #endif
  369. #define __UA_WSTRSIZE(s) ((__UA_WCSLEN(s)+1)*sizeof(WCHAR))
  370. #define __UA_STACKCOPY(p,s) memcpy(_alloca(s),p,s)
  371. //
  372. // Note that NULL is aligned.
  373. //
  374. #if defined(_X86_)
  375. #define WSTR_ALIGNED_STACK_COPY(d,s) (*(d) = (PCWSTR)(s))
  376. #else
  377. //
  378. // Use of an inline function here is not possible, as the results of
  379. // the _alloca() will not be preserved upon return from the function.
  380. //
  381. #define WSTR_ALIGNED_STACK_COPY(d,s) \
  382. { \
  383. PCUWSTR __ua_src; \
  384. ULONG __ua_size; \
  385. PWSTR __ua_dst; \
  386. \
  387. __ua_src = (s); \
  388. if (WSTR_ALIGNED(__ua_src)) { \
  389. __ua_dst = (PWSTR)__ua_src; \
  390. } else { \
  391. __ua_size = __UA_WSTRSIZE(__ua_src); \
  392. __ua_dst = (PWSTR)_alloca(__ua_size); \
  393. memcpy(__ua_dst,__ua_src,__ua_size); \
  394. } \
  395. *(d) = (PCWSTR)__ua_dst; \
  396. }
  397. #endif
  398. #define ASTR_ALIGNED_STACK_COPY(d,s) (*(d) = (PCSTR)(s))
  399. //++
  400. //
  401. // <type> CONST *
  402. // STRUC_ALIGNED_STACK_COPY (
  403. // IN <type name>,
  404. // IN PVOID Struc OPTIONAL
  405. // )
  406. //
  407. // Routine Description:
  408. //
  409. // This macro returns an aligned pointer to Struc, creating a local
  410. // copy on the stack if necessary.
  411. //
  412. // This should be used only for relatively small structures, and efforts
  413. // should be made to align the structure properly in the first place. Use
  414. // this macro only as a last resort.
  415. //
  416. // Arguments:
  417. //
  418. // <type> - The type specifier of Struc
  419. //
  420. // Struc - Supplies a pointer to the structure in question.
  421. //
  422. // Return Value:
  423. //
  424. // Returns a const pointer to Struc if it is properly aligned, or a pointer
  425. // to a stack-allocated copy of Struc if it is not.
  426. //
  427. //--
  428. #if !defined(_X86_)
  429. #define __UA_STRUC_ALIGNED(t,s) \
  430. (((DWORD_PTR)(s) & (TYPE_ALIGNMENT(t)-1)) == 0)
  431. #define STRUC_ALIGNED_STACK_COPY(t,s) \
  432. __UA_STRUC_ALIGNED(t,s) ? \
  433. ((t const *)(s)) : \
  434. ((t const *)__UA_STACKCOPY((s),sizeof(t)))
  435. #else
  436. #define STRUC_ALIGNED_STACK_COPY(t,s) ((CONST t *)(s))
  437. #endif
  438. #if defined(UNICODE)
  439. #define TSTR_ALIGNED_STACK_COPY(d,s) WSTR_ALIGNED_STACK_COPY(d,s)
  440. #define TSTR_ALIGNED(x) WSTR_ALIGNED(x)
  441. #define ua_CharUpper ua_CharUpperW
  442. #define ua_lstrcmp ua_lstrcmpW
  443. #define ua_lstrcmpi ua_lstrcmpiW
  444. #define ua_lstrlen ua_lstrlenW
  445. #define ua_tcscpy ua_wcscpy
  446. #else
  447. #define TSTR_ALIGNED_STACK_COPY(d,s) ASTR_ALIGNED_STACK_COPY(d,s)
  448. #define TSTR_ALIGNED(x) TRUE
  449. #define ua_CharUpper CharUpperA
  450. #define ua_lstrcmp lstrcmpA
  451. #define ua_lstrcmpi lstrcmpiA
  452. #define ua_lstrlen lstrlenA
  453. #define ua_tcscpy strcpy
  454. #endif // UNICODE
  455. #ifdef __cplusplus
  456. }
  457. #endif
  458. #endif // __STRALIGN_H_