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.

237 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. basesys.cxx
  5. --*/
  6. #include <pch.cxx>
  7. #define _ULIB_MEMBER_
  8. #include "ulib.hxx"
  9. #include "basesys.hxx"
  10. ULIB_EXPORT
  11. BOOLEAN
  12. BASE_SYSTEM::QueryResourceString(
  13. OUT PWSTRING ResourceString,
  14. IN MSGID MsgId,
  15. IN PCSTR Format ...
  16. )
  17. /*++
  18. Routine Description:
  19. This routine computes the resource string identified by the resource
  20. identifier 'MsgId'. In addition to the 'printf' format strings
  21. supported, 'QueryResourceString' supports :
  22. 1. '%W' - Expects a pointer to a WSTRING.
  23. Arguments:
  24. ResourceString - Returns the resource string.
  25. MsgId - Supplies the message id of the resource string.
  26. Format - Supplies a 'printf' style format descriptor for the
  27. arguments to the resource string.
  28. ... - Supplies the arguments to the resource string.
  29. Return Value:
  30. FALSE - Failure.
  31. TRUE - Success.
  32. --*/
  33. {
  34. va_list ap;
  35. BOOLEAN r;
  36. va_start(ap, Format);
  37. r = QueryResourceStringV(ResourceString, MsgId, Format, ap);
  38. va_end(ap);
  39. return r;
  40. }
  41. ULIB_EXPORT
  42. BOOLEAN
  43. BASE_SYSTEM::QueryResourceStringV(
  44. OUT PWSTRING ResourceString,
  45. IN MSGID MsgId,
  46. IN PCSTR Format,
  47. IN va_list VarPointer
  48. )
  49. /*++
  50. Routine Description:
  51. This is a 'varargs' implementation of 'QueryResourceString'.
  52. Arguments:
  53. ResourceString - Returns the resource string.
  54. MsgId - Supplies the message id of the resource string.
  55. Format - Supplies a 'printf' style format descriptor for the
  56. arguments to the resource string.
  57. VarPointer - Supplies a varargs pointer to the arguments of the
  58. resource string.
  59. Return Value:
  60. FALSE - Failure.
  61. TRUE - Success.
  62. --*/
  63. {
  64. #define NUMBER_OF_ARGS 20
  65. STATIC HANDLE lib_handle = 0;
  66. PWSTR args[NUMBER_OF_ARGS];
  67. WSTR fmt[20];
  68. INT i, j;
  69. PWSTR p;
  70. PWSTRING gstring;
  71. DSTRING UnicodeFormat;
  72. WSTR display_buffer[4096];
  73. BOOL found;
  74. NTSTATUS Status;
  75. ULONG Result;
  76. for (i = 0; i < NUMBER_OF_ARGS; i++) {
  77. args[i] = NULL;
  78. }
  79. if (!UnicodeFormat.Initialize(Format)) {
  80. return FALSE;
  81. }
  82. // convert args into an array for RtlFormatMessage.
  83. i = 0;
  84. for (p = (PWSTR) UnicodeFormat.GetWSTR(); *p; p++) {
  85. // if we have a %
  86. if (*p == '%') {
  87. // perform W substitutions
  88. if (*(p + 1) == 'W') {
  89. p++;
  90. gstring = va_arg(VarPointer, PWSTRING);
  91. gstring->QueryWSTR(0, TO_END, display_buffer, 4096);
  92. } else {
  93. // convert other substutitions as appropriate by building a fmt string
  94. j = 0;
  95. // copy the %
  96. fmt[j++] = *p++;
  97. // copy the next character as long at its not a % and not NULL
  98. while (*p && *p != '%') {
  99. if ((*p == 's') && *(p - 1) != 'w') {
  100. //if its an ANSI string
  101. fmt[j++] = L'a';
  102. p++;
  103. continue;
  104. } else if ((*p == 'c') && *(p - 1) != 'w') {
  105. // if its an ANSI character
  106. fmt[j++] = L'c'; // BUGBUG hack for now
  107. p++;
  108. continue;
  109. } else if ((*p == 'w' ) && *(p + 1) == 's') {
  110. // if its a wide string (%ws->%s)
  111. fmt[j++] = L's';
  112. p++;
  113. p++; // skip the second char
  114. continue;
  115. } else if ((*p == 'w' ) && *(p + 1) == 'c') {
  116. // if its a wide char (%wc->%c)
  117. fmt[j++] = L'c';
  118. p++;
  119. p++; // skip the second char
  120. continue;
  121. } else if ((*p == 'u' )) {
  122. // BUGBUG sprint doesn't seem to work with %u, replace with %d
  123. fmt[j++] = L'd';
  124. p++;
  125. } else if (isdigit(*p)) {
  126. // BUGBUG: HACK we skip digit format stuff since Sprint doesn't seem to like em.
  127. p++;
  128. } else {
  129. // otherwise just copy the format indicator
  130. fmt[j++] = *p++;
  131. }
  132. }
  133. p--;
  134. fmt[j] = 0;
  135. if (wcsncmp(fmt, TEXT("%I64"), 4) == 0) {
  136. // if its a 64 bit integer
  137. // do some special stuff to handle LARGE_INTEGERS before telling SPrint to do its thing.
  138. ULONGLONG t = (va_arg(VarPointer,LARGE_INTEGER)).QuadPart;
  139. fmt[0]='%';
  140. fmt[1]='l';
  141. fmt[2]='d';
  142. fmt[3]=NULL;
  143. // Print(L"QueryResourceStringV: fmt: %s\n",fmt);
  144. SPrint(display_buffer, 4096, fmt, t);
  145. } else {
  146. // otherwise tell SPrint to do its thing
  147. PVOID voidptr = va_arg(VarPointer, PVOID);
  148. // Print(L"QueryResourceStringV: fmt: %s\n",fmt);
  149. SPrint(display_buffer, 4096,fmt,voidptr );
  150. }
  151. }
  152. // allocate a buffer and copy the converted string into it.
  153. args[i] = (PWSTR)MALLOC(wcslen(display_buffer) * sizeof(WCHAR) + sizeof(WCHAR));
  154. if (NULL == args[i]) {
  155. return FALSE;
  156. }
  157. wcscpy( args[i], display_buffer);
  158. // Print(L"QueryResourceStringV: args[%d]: %s\n",i,args[i]);
  159. i++;
  160. }
  161. }
  162. found = FALSE;
  163. // locate the right message in our table
  164. for(i=0;i<EFI_MESSAGE_COUNT;i++) {
  165. if(MessageTable[i].msgId == MsgId ){
  166. found = TRUE;
  167. break;
  168. }
  169. }
  170. if (found == FALSE) {
  171. return FALSE;
  172. }
  173. WCHAR *MessageFormat = MessageTable[i].string;
  174. // shove it through RtlFormatMessage.
  175. Status = RtlFormatMessage( MessageFormat,
  176. 0,
  177. FALSE,
  178. FALSE,
  179. TRUE,
  180. (va_list *)args,
  181. (PWSTR)display_buffer,
  182. sizeof( display_buffer ),
  183. &Result
  184. );
  185. for (i = 0; i < NUMBER_OF_ARGS; i++) {
  186. FREE(args[i]);
  187. }
  188. if (!NT_SUCCESS( Status )) {
  189. return FALSE;
  190. }
  191. return ResourceString->Initialize(display_buffer);
  192. }