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.

467 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. ULONGLONG 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(_WIN64)
  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, ULONGLONG );
  207. } else {
  208. rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
  209. }
  210. }
  211. }
  212. s1 = (PWSTR)rgInserts[ CurInsert ];
  213. PrintParameter1 = 0;
  214. PrintParameter2 = 0;
  215. if (PrintParameterCount > 0) {
  216. if (ArgumentsAreAnArray) {
  217. rgInserts[ MaxInsert++ ] = PrintParameter1 = *((PULONG_PTR)Arguments)++;
  218. } else {
  219. PrintParameter1 = va_arg( *Arguments, ULONG_PTR );
  220. }
  221. if (PrintParameterCount > 1) {
  222. if (ArgumentsAreAnArray) {
  223. rgInserts[ MaxInsert++ ] = PrintParameter2 = *((PULONG_PTR)Arguments)++;
  224. } else {
  225. rgInserts[ MaxInsert++ ] = PrintParameter2 = va_arg( *Arguments, ULONG_PTR );
  226. }
  227. }
  228. }
  229. if (WideArg) {
  230. cchWritten = _snwprintf(
  231. lpDst,
  232. cchRemaining,
  233. PrintFormatString,
  234. rgInserts[CurInsert],
  235. PrintParameter1,
  236. PrintParameter2
  237. );
  238. } else {
  239. cchWritten = _snwprintf(
  240. lpDst,
  241. cchRemaining,
  242. PrintFormatString,
  243. s1,
  244. PrintParameter1,
  245. PrintParameter2
  246. );
  247. }
  248. if (cchWritten == -1) {
  249. return(STATUS_BUFFER_OVERFLOW);
  250. }
  251. } else {
  252. return( STATUS_INVALID_PARAMETER );
  253. }
  254. if ((cchRemaining -= cchWritten) <= 0) {
  255. return STATUS_BUFFER_OVERFLOW;
  256. }
  257. lpDst += cchWritten;
  258. } else if (*s == L'0') {
  259. break;
  260. } else if (!*s) {
  261. return( STATUS_INVALID_PARAMETER );
  262. } else if (*s == L'r') {
  263. if ((cchRemaining -= 1) <= 0) {
  264. return STATUS_BUFFER_OVERFLOW;
  265. }
  266. *lpDst++ = L'\r';
  267. s++;
  268. lpDstBeg = NULL;
  269. } else if (*s == L'n') {
  270. if ((cchRemaining -= 2) <= 0) {
  271. return STATUS_BUFFER_OVERFLOW;
  272. }
  273. *lpDst++ = L'\r';
  274. *lpDst++ = L'\n';
  275. s++;
  276. lpDstBeg = NULL;
  277. } else if (*s == L't') {
  278. if ((cchRemaining -= 1) <= 0) {
  279. return STATUS_BUFFER_OVERFLOW;
  280. }
  281. if (Column % 8) {
  282. Column = (Column + 7) & ~7;
  283. } else {
  284. Column += 8;
  285. }
  286. lpDstLastSpace = lpDst;
  287. *lpDst++ = L'\t';
  288. s++;
  289. } else if (*s == L'b') {
  290. if ((cchRemaining -= 1) <= 0) {
  291. return STATUS_BUFFER_OVERFLOW;
  292. }
  293. lpDstLastSpace = lpDst;
  294. *lpDst++ = L' ';
  295. s++;
  296. } else if (IgnoreInserts) {
  297. if ((cchRemaining -= 2) <= 0) {
  298. return STATUS_BUFFER_OVERFLOW;
  299. }
  300. *lpDst++ = L'%';
  301. *lpDst++ = *s++;
  302. } else {
  303. if ((cchRemaining -= 1) <= 0) {
  304. return STATUS_BUFFER_OVERFLOW;
  305. }
  306. *lpDst++ = *s++;
  307. }
  308. if (lpDstBeg == NULL) {
  309. lpDstLastSpace = NULL;
  310. Column = 0;
  311. } else {
  312. Column += (ULONG)(lpDst - lpDstBeg);
  313. }
  314. } else {
  315. c = *s++;
  316. if (c == L'\r' || c == L'\n') {
  317. if ((c == L'\n' && *s == L'\r') ||
  318. (c == L'\r' && *s == L'\n')
  319. )
  320. {
  321. s++;
  322. }
  323. if (MaximumWidth != 0) {
  324. lpDstLastSpace = lpDst;
  325. c = L' ';
  326. } else {
  327. c = L'\n';
  328. }
  329. }
  330. if (c == L'\n') {
  331. if ((cchRemaining -= 2) <= 0) {
  332. return STATUS_BUFFER_OVERFLOW;
  333. }
  334. *lpDst++ = L'\r';
  335. *lpDst++ = L'\n';
  336. lpDstLastSpace = NULL;
  337. Column = 0;
  338. } else {
  339. if ((cchRemaining -= 1) <= 0) {
  340. return STATUS_BUFFER_OVERFLOW;
  341. }
  342. if (c == L' ') {
  343. lpDstLastSpace = lpDst;
  344. }
  345. *lpDst++ = c;
  346. Column += 1;
  347. }
  348. }
  349. if (MaximumWidth != 0 &&
  350. MaximumWidth != 0xFFFFFFFF &&
  351. Column >= MaximumWidth
  352. ) {
  353. if (lpDstLastSpace != NULL) {
  354. lpDstBeg = lpDstLastSpace;
  355. while (*lpDstBeg == L' ' || *lpDstBeg == L'\t') {
  356. lpDstBeg += 1;
  357. if (lpDstBeg == lpDst) {
  358. break;
  359. }
  360. }
  361. while (lpDstLastSpace > Buffer) {
  362. if (lpDstLastSpace[ -1 ] == L' ' || lpDstLastSpace[ -1 ] == L'\t') {
  363. lpDstLastSpace -= 1;
  364. }
  365. else {
  366. break;
  367. }
  368. }
  369. cSpaces = (ULONG)(lpDstBeg - lpDstLastSpace);
  370. if (cSpaces == 1) {
  371. if ((cchRemaining -= 1) <= 0) {
  372. return STATUS_BUFFER_OVERFLOW;
  373. }
  374. }
  375. else
  376. if (cSpaces > 2) {
  377. cchRemaining += (cSpaces - 2);
  378. }
  379. memmove( lpDstLastSpace + 2,
  380. lpDstBeg,
  381. (ULONG) ((lpDst - lpDstBeg) * sizeof( WCHAR ))
  382. );
  383. *lpDstLastSpace++ = L'\r';
  384. *lpDstLastSpace++ = L'\n';
  385. Column = (ULONG)(lpDst - lpDstBeg);
  386. lpDst = lpDstLastSpace + Column;
  387. lpDstLastSpace = NULL;
  388. }
  389. else {
  390. if ((cchRemaining -= 2) <= 0) {
  391. return STATUS_BUFFER_OVERFLOW;
  392. }
  393. *lpDst++ = L'\r';
  394. *lpDst++ = L'\n';
  395. lpDstLastSpace = NULL;
  396. Column = 0;
  397. }
  398. }
  399. }
  400. if ((cchRemaining -= 1) <= 0) {
  401. return STATUS_BUFFER_OVERFLOW;
  402. }
  403. *lpDst++ = '\0';
  404. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  405. *ReturnLength = (ULONG)(lpDst - Buffer) * sizeof( WCHAR );
  406. }
  407. return( STATUS_SUCCESS );
  408. }
  409. #endif