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.

468 lines
15 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. message.c
  5. Abstract:
  6. Message table resource accessing functions
  7. Author:
  8. Steve Wood (stevewo) 10-Sep-1991
  9. Revision History:
  10. --*/
  11. #include "ntrtlp.h"
  12. #include "string.h"
  13. #include "stdio.h"
  14. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  15. #pragma alloc_text(PAGE,RtlFindMessage)
  16. #endif
  17. NTSTATUS
  18. RtlFindMessage(
  19. IN PVOID DllHandle,
  20. IN ULONG MessageTableId,
  21. IN ULONG MessageLanguageId,
  22. IN ULONG MessageId,
  23. OUT PMESSAGE_RESOURCE_ENTRY *MessageEntry
  24. )
  25. {
  26. NTSTATUS Status;
  27. ULONG NumberOfBlocks;
  28. ULONG EntryIndex;
  29. PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
  30. PMESSAGE_RESOURCE_DATA MessageData;
  31. PMESSAGE_RESOURCE_BLOCK MessageBlock;
  32. PCHAR s;
  33. ULONG_PTR ResourceIdPath[ 3 ];
  34. RTL_PAGED_CODE();
  35. ResourceIdPath[ 0 ] = MessageTableId;
  36. ResourceIdPath[ 1 ] = 1;
  37. ResourceIdPath[ 2 ] = MessageLanguageId;
  38. Status = LdrpSearchResourceSection_U( DllHandle,
  39. ResourceIdPath,
  40. 3,
  41. 0,
  42. (PVOID *)&ResourceDataEntry
  43. );
  44. if (!NT_SUCCESS( Status )) {
  45. return( Status );
  46. }
  47. Status = LdrpAccessResourceData( DllHandle,
  48. ResourceDataEntry,
  49. (PVOID *)&MessageData,
  50. NULL
  51. );
  52. if (!NT_SUCCESS( Status )) {
  53. return( Status );
  54. }
  55. NumberOfBlocks = MessageData->NumberOfBlocks;
  56. MessageBlock = &MessageData->Blocks[ 0 ];
  57. while (NumberOfBlocks--) {
  58. if (MessageId >= MessageBlock->LowId &&
  59. MessageId <= MessageBlock->HighId
  60. ) {
  61. s = (PCHAR)MessageData + MessageBlock->OffsetToEntries;
  62. EntryIndex = MessageId - MessageBlock->LowId;
  63. while (EntryIndex--) {
  64. s += ((PMESSAGE_RESOURCE_ENTRY)s)->Length;
  65. }
  66. *MessageEntry = (PMESSAGE_RESOURCE_ENTRY)s;
  67. return( STATUS_SUCCESS );
  68. }
  69. MessageBlock++;
  70. }
  71. return( STATUS_MESSAGE_NOT_FOUND );
  72. }
  73. #ifndef NTOS_KERNEL_RUNTIME
  74. #define MAX_INSERTS 200
  75. NTSTATUS
  76. RtlFormatMessage(
  77. IN PWSTR MessageFormat,
  78. IN ULONG MaximumWidth OPTIONAL,
  79. IN BOOLEAN IgnoreInserts,
  80. IN BOOLEAN ArgumentsAreAnsi,
  81. IN BOOLEAN ArgumentsAreAnArray,
  82. IN va_list *Arguments,
  83. OUT PWSTR Buffer,
  84. IN ULONG Length,
  85. OUT PULONG ReturnLength OPTIONAL
  86. )
  87. {
  88. ULONG Column;
  89. int cchRemaining, cchWritten;
  90. PULONG_PTR ArgumentsArray = (PULONG_PTR)Arguments;
  91. ULONG_PTR rgInserts[ MAX_INSERTS ];
  92. ULONG cSpaces;
  93. ULONG MaxInsert, CurInsert;
  94. ULONG PrintParameterCount;
  95. ULONG_PTR PrintParameter1;
  96. ULONG_PTR PrintParameter2;
  97. WCHAR PrintFormatString[ 32 ];
  98. BOOLEAN DefaultedFormatString;
  99. WCHAR c;
  100. PWSTR s, s1, s2, s3;
  101. PWSTR lpDst, lpDstBeg, lpDstLastSpace;
  102. BOOLEAN WideArg = FALSE;
  103. cchRemaining = Length / sizeof( WCHAR );
  104. lpDst = Buffer;
  105. MaxInsert = 0;
  106. lpDstLastSpace = NULL;
  107. Column = 0;
  108. s = MessageFormat;
  109. while (*s != UNICODE_NULL) {
  110. if (*s == L'%') {
  111. s++;
  112. lpDstBeg = lpDst;
  113. if (*s >= L'1' && *s <= L'9') {
  114. CurInsert = *s++ - L'0';
  115. if (*s >= L'0' && *s <= L'9') {
  116. CurInsert = (CurInsert * 10) + (*s++ - L'0');
  117. if (*s >= L'0' && *s <= L'9') {
  118. CurInsert = (CurInsert * 10) + (*s++ - L'0');
  119. if (*s >= L'0' && *s <= L'9') {
  120. return( STATUS_INVALID_PARAMETER );
  121. }
  122. }
  123. }
  124. CurInsert -= 1;
  125. PrintParameterCount = 0;
  126. if (*s == L'!') {
  127. DefaultedFormatString = FALSE;
  128. s1 = PrintFormatString;
  129. *s1++ = L'%';
  130. s2 = s1;
  131. s++;
  132. while (*s != L'!') {
  133. if (*s != UNICODE_NULL) {
  134. if (s1 >= &PrintFormatString[ 31 ]) {
  135. return( STATUS_INVALID_PARAMETER );
  136. }
  137. if (*s == L'*') {
  138. if (PrintParameterCount++ > 1) {
  139. return( STATUS_INVALID_PARAMETER );
  140. }
  141. }
  142. *s1++ = *s++;
  143. } else {
  144. return( STATUS_INVALID_PARAMETER );
  145. }
  146. }
  147. s++;
  148. *s1 = UNICODE_NULL;
  149. WideArg = FALSE;
  150. #if !defined(_IA64_)
  151. // look for I64 format string
  152. s3 = s2;
  153. while (*s3 && !WideArg) {
  154. if (s3[0] == L'I' && s3[1] == L'6' && s3[2] == L'4') {
  155. WideArg = TRUE;
  156. }
  157. s3 += 1;
  158. }
  159. #endif
  160. } else {
  161. DefaultedFormatString = TRUE;
  162. wcscpy( PrintFormatString, L"%s" );
  163. s1 = PrintFormatString + wcslen( PrintFormatString );
  164. WideArg = FALSE;
  165. }
  166. if (IgnoreInserts) {
  167. if (!wcscmp( PrintFormatString, L"%s" )) {
  168. cchWritten = _snwprintf( lpDst,
  169. cchRemaining,
  170. L"%%%u",
  171. CurInsert+1
  172. );
  173. } else {
  174. cchWritten = _snwprintf( lpDst,
  175. cchRemaining,
  176. L"%%%u!%s!",
  177. CurInsert+1,
  178. &PrintFormatString[ 1 ]
  179. );
  180. }
  181. if (cchWritten == -1) {
  182. return(STATUS_BUFFER_OVERFLOW);
  183. }
  184. } else if (ARGUMENT_PRESENT( Arguments )) {
  185. if ((CurInsert+PrintParameterCount) >= MAX_INSERTS) {
  186. return( STATUS_INVALID_PARAMETER );
  187. }
  188. if (ArgumentsAreAnsi) {
  189. if (s1[ -1 ] == L'c' && s1[ -2 ] != L'h'
  190. && s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
  191. wcscpy( &s1[ -1 ], L"hc" );
  192. } else if (s1[ -1 ] == L's' && s1[ -2 ] != L'h'
  193. && s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
  194. wcscpy( &s1[ -1 ], L"hs" );
  195. } else if (s1[ -1 ] == L'S') {
  196. s1[ -1 ] = L's';
  197. } else if (s1[ -1 ] == L'C') {
  198. s1[ -1 ] = L'c';
  199. }
  200. }
  201. while (CurInsert >= MaxInsert) {
  202. if (ArgumentsAreAnArray) {
  203. rgInserts[ MaxInsert++ ] = *((PULONG_PTR)Arguments)++;
  204. } else {
  205. if (WideArg) {
  206. rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
  207. rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
  208. } else {
  209. rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
  210. }
  211. }
  212. }
  213. s1 = (PWSTR)rgInserts[ CurInsert ];
  214. PrintParameter1 = 0;
  215. PrintParameter2 = 0;
  216. if (PrintParameterCount > 0) {
  217. if (ArgumentsAreAnArray) {
  218. PrintParameter1 = rgInserts[ MaxInsert++ ] = *((PULONG_PTR)Arguments)++;
  219. } else {
  220. PrintParameter1 = va_arg( *Arguments, ULONG_PTR );
  221. }
  222. if (PrintParameterCount > 1) {
  223. if (ArgumentsAreAnArray) {
  224. PrintParameter2 = rgInserts[ MaxInsert++ ] = *((PULONG_PTR)Arguments)++;
  225. } else {
  226. PrintParameter2 = rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
  227. }
  228. }
  229. }
  230. if (WideArg) {
  231. cchWritten = _snwprintf(
  232. lpDst,
  233. cchRemaining,
  234. PrintFormatString,
  235. *(PULONGLONG)&rgInserts[CurInsert],
  236. PrintParameter1,
  237. PrintParameter2
  238. );
  239. } else {
  240. cchWritten = _snwprintf(
  241. lpDst,
  242. cchRemaining,
  243. PrintFormatString,
  244. s1,
  245. PrintParameter1,
  246. PrintParameter2
  247. );
  248. }
  249. if (cchWritten == -1) {
  250. return(STATUS_BUFFER_OVERFLOW);
  251. }
  252. } else {
  253. return( STATUS_INVALID_PARAMETER );
  254. }
  255. if ((cchRemaining -= cchWritten) <= 0) {
  256. return STATUS_BUFFER_OVERFLOW;
  257. }
  258. lpDst += cchWritten;
  259. } else if (*s == L'0') {
  260. break;
  261. } else if (!*s) {
  262. return( STATUS_INVALID_PARAMETER );
  263. } else if (*s == L'r') {
  264. if ((cchRemaining -= 1) <= 0) {
  265. return STATUS_BUFFER_OVERFLOW;
  266. }
  267. *lpDst++ = L'\r';
  268. s++;
  269. lpDstBeg = NULL;
  270. } else if (*s == L'n') {
  271. if ((cchRemaining -= 2) <= 0) {
  272. return STATUS_BUFFER_OVERFLOW;
  273. }
  274. *lpDst++ = L'\r';
  275. *lpDst++ = L'\n';
  276. s++;
  277. lpDstBeg = NULL;
  278. } else if (*s == L't') {
  279. if ((cchRemaining -= 1) <= 0) {
  280. return STATUS_BUFFER_OVERFLOW;
  281. }
  282. if (Column % 8) {
  283. Column = (Column + 7) & ~7;
  284. } else {
  285. Column += 8;
  286. }
  287. lpDstLastSpace = lpDst;
  288. *lpDst++ = L'\t';
  289. s++;
  290. } else if (*s == L'b') {
  291. if ((cchRemaining -= 1) <= 0) {
  292. return STATUS_BUFFER_OVERFLOW;
  293. }
  294. lpDstLastSpace = lpDst;
  295. *lpDst++ = L' ';
  296. s++;
  297. } else if (IgnoreInserts) {
  298. if ((cchRemaining -= 2) <= 0) {
  299. return STATUS_BUFFER_OVERFLOW;
  300. }
  301. *lpDst++ = L'%';
  302. *lpDst++ = *s++;
  303. } else {
  304. if ((cchRemaining -= 1) <= 0) {
  305. return STATUS_BUFFER_OVERFLOW;
  306. }
  307. *lpDst++ = *s++;
  308. }
  309. if (lpDstBeg == NULL) {
  310. lpDstLastSpace = NULL;
  311. Column = 0;
  312. } else {
  313. Column += (ULONG)(lpDst - lpDstBeg);
  314. }
  315. } else {
  316. c = *s++;
  317. if (c == L'\r' || c == L'\n') {
  318. if ((c == L'\n' && *s == L'\r') ||
  319. (c == L'\r' && *s == L'\n')
  320. )
  321. {
  322. s++;
  323. }
  324. if (MaximumWidth != 0) {
  325. lpDstLastSpace = lpDst;
  326. c = L' ';
  327. } else {
  328. c = L'\n';
  329. }
  330. }
  331. if (c == L'\n') {
  332. if ((cchRemaining -= 2) <= 0) {
  333. return STATUS_BUFFER_OVERFLOW;
  334. }
  335. *lpDst++ = L'\r';
  336. *lpDst++ = L'\n';
  337. lpDstLastSpace = NULL;
  338. Column = 0;
  339. } else {
  340. if ((cchRemaining -= 1) <= 0) {
  341. return STATUS_BUFFER_OVERFLOW;
  342. }
  343. if (c == L' ') {
  344. lpDstLastSpace = lpDst;
  345. }
  346. *lpDst++ = c;
  347. Column += 1;
  348. }
  349. }
  350. if (MaximumWidth != 0 &&
  351. MaximumWidth != 0xFFFFFFFF &&
  352. Column >= MaximumWidth
  353. ) {
  354. if (lpDstLastSpace != NULL) {
  355. lpDstBeg = lpDstLastSpace;
  356. while (*lpDstBeg == L' ' || *lpDstBeg == L'\t') {
  357. lpDstBeg += 1;
  358. if (lpDstBeg == lpDst) {
  359. break;
  360. }
  361. }
  362. while (lpDstLastSpace > Buffer) {
  363. if (lpDstLastSpace[ -1 ] == L' ' || lpDstLastSpace[ -1 ] == L'\t') {
  364. lpDstLastSpace -= 1;
  365. }
  366. else {
  367. break;
  368. }
  369. }
  370. cSpaces = (ULONG)(lpDstBeg - lpDstLastSpace);
  371. if (cSpaces == 1) {
  372. if ((cchRemaining -= 1) <= 0) {
  373. return STATUS_BUFFER_OVERFLOW;
  374. }
  375. }
  376. else
  377. if (cSpaces > 2) {
  378. cchRemaining += (cSpaces - 2);
  379. }
  380. memmove( lpDstLastSpace + 2,
  381. lpDstBeg,
  382. (ULONG) ((lpDst - lpDstBeg) * sizeof( WCHAR ))
  383. );
  384. *lpDstLastSpace++ = L'\r';
  385. *lpDstLastSpace++ = L'\n';
  386. Column = (ULONG)(lpDst - lpDstBeg);
  387. lpDst = lpDstLastSpace + Column;
  388. lpDstLastSpace = NULL;
  389. }
  390. else {
  391. if ((cchRemaining -= 2) <= 0) {
  392. return STATUS_BUFFER_OVERFLOW;
  393. }
  394. *lpDst++ = L'\r';
  395. *lpDst++ = L'\n';
  396. lpDstLastSpace = NULL;
  397. Column = 0;
  398. }
  399. }
  400. }
  401. if ((cchRemaining -= 1) <= 0) {
  402. return STATUS_BUFFER_OVERFLOW;
  403. }
  404. *lpDst++ = '\0';
  405. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  406. *ReturnLength = (ULONG)(lpDst - Buffer) * sizeof( WCHAR );
  407. }
  408. return( STATUS_SUCCESS );
  409. }
  410. #endif