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.

412 lines
11 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. message.c
  5. Abstract:
  6. This module provides support routines to map DosxxxMessage APIs to
  7. the FormatMessage syntax and semantics.
  8. Author:
  9. Dan Hinsley (DanHi) 24-Sept-1991
  10. Environment:
  11. Contains NT specific code.
  12. Revision History:
  13. --*/
  14. #define ERROR_MR_MSG_TOO_LONG 316
  15. #define ERROR_MR_UN_ACC_MSGF 318
  16. #define ERROR_MR_INV_IVCOUNT 320
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #define NOMINMAX // Avoid windows vs. stdlib.h conflicts.
  21. #include <windef.h>
  22. #include <winbase.h>
  23. #include <winnls.h>
  24. #include <lmcons.h>
  25. #include <lmerr.h>
  26. #include <netdebug.h> // NetpKdPrint
  27. #include <netlib.h> // NetpMemory*
  28. #include <netlibnt.h> // NetpNtStatusToApiStatus
  29. #include <string.h>
  30. #include <stdio.h>
  31. #include <stdlib.h> // itoa
  32. #include <tstring.h>
  33. //
  34. // forward declare
  35. //
  36. DWORD MyAllocUnicode( LPSTR pszAscii, LPWSTR * ppwszUnicode ) ;
  37. DWORD MyAllocUnicodeVector( LPSTR * ppszAscii,
  38. LPWSTR* ppwszUnicode,
  39. UINT cpwszUnicode ) ;
  40. VOID MyFreeUnicode( LPWSTR pwszUnicode ) ;
  41. VOID MyFreeUnicodeVector( LPWSTR * ppwsz, UINT cpwsz ) ;
  42. //
  43. // 100 is plenty since FormatMessage only take 99 & old DosGetMessage 9.
  44. //
  45. #define MAX_INSERT_STRINGS (100)
  46. WORD
  47. DosGetMessage(
  48. IN LPSTR * InsertionStrings,
  49. IN WORD NumberofStrings,
  50. OUT LPBYTE Buffer,
  51. IN WORD BufferLength,
  52. IN WORD MessageId,
  53. IN LPTSTR FileName,
  54. OUT PWORD pMessageLength
  55. )
  56. /*++
  57. Routine Description:
  58. This maps the OS/2 DosGetMessage API to the NT FormatMessage API.
  59. Arguments:
  60. InsertionStrings - Pointer to an array of strings that will be used
  61. to replace the %n's in the message.
  62. NumberofStrings - The number of insertion strings.
  63. Buffer - The buffer to put the message into.
  64. BufferLength - The length of the supplied buffer.
  65. MessageId - The message number to retrieve.
  66. FileName - The name of the message file to get the message from.
  67. pMessageLength - A pointer to return the length of the returned message.
  68. Return Value:
  69. NERR_Success
  70. ERROR_MR_MSG_TOO_LONG
  71. ERROR_MR_INV_IVCOUNT
  72. ERROR_MR_UN_ACC_MSGF
  73. ERROR_MR_MID_NOT_FOUND
  74. ERROR_INVALID_PARAMETER
  75. --*/
  76. {
  77. DWORD dwFlags = FORMAT_MESSAGE_ARGUMENT_ARRAY;
  78. DWORD Status, i;
  79. LPWSTR UnicodeIStrings[MAX_INSERT_STRINGS] ;
  80. LPWSTR UnicodeBuffer = NULL;
  81. LPWSTR UnicodeNumberString = NULL ;
  82. CHAR NumberString [18];
  83. static HANDLE lpSource = NULL ;
  84. static TCHAR CurrentMsgFile[MAX_PATH] = {0,} ;
  85. //
  86. // init clear the output string
  87. //
  88. Status = NERR_Success;
  89. if (BufferLength)
  90. Buffer[0] = '\0' ;
  91. if (pMessageLength)
  92. *pMessageLength = 0;
  93. //
  94. // make sure we are not over loaded & allocate
  95. // memory for the Unicode buffer
  96. //
  97. if (NumberofStrings > MAX_INSERT_STRINGS)
  98. return ERROR_INVALID_PARAMETER ;
  99. if (!(UnicodeBuffer = NetpMemoryAllocate(BufferLength * sizeof(WCHAR))))
  100. return ERROR_NOT_ENOUGH_MEMORY ;
  101. //
  102. // init the string table & map the strings to unicode
  103. //
  104. for (i = 0; i < MAX_INSERT_STRINGS; i++)
  105. UnicodeIStrings[i] = NULL ;
  106. Status = MyAllocUnicodeVector(InsertionStrings,
  107. UnicodeIStrings,
  108. NumberofStrings) ;
  109. if (Status)
  110. goto ExitPoint ;
  111. //
  112. // See if they want to get the message from the system message file.
  113. //
  114. if (! STRCMP(FileName, OS2MSG_FILENAME)) {
  115. dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
  116. }
  117. else
  118. {
  119. //
  120. // They want it from a separate message file. Get a handle to DLL
  121. // If its for the same file as before, dont reload.
  122. //
  123. if (!(lpSource && !STRCMP(CurrentMsgFile,FileName)))
  124. {
  125. if (lpSource)
  126. {
  127. FreeLibrary(lpSource) ;
  128. }
  129. STRCPY(CurrentMsgFile, FileName) ;
  130. lpSource = LoadLibraryEx(FileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  131. if (!lpSource)
  132. {
  133. Status = ERROR_MR_UN_ACC_MSGF;
  134. goto ExitPoint ;
  135. }
  136. }
  137. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  138. }
  139. //
  140. // If they just want to get the message back for later formatting,
  141. // ignore the insert strings.
  142. //
  143. if (NumberofStrings == 0)
  144. {
  145. dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;
  146. }
  147. //
  148. // call the Unicode version
  149. //
  150. *pMessageLength = (WORD) FormatMessageW(dwFlags,
  151. (LPVOID) lpSource,
  152. (DWORD) MessageId,
  153. 0, // LanguageId defaulted
  154. UnicodeBuffer,
  155. (DWORD)BufferLength,
  156. (va_list *)UnicodeIStrings);
  157. //
  158. // If it failed get the return code and map it to an OS/2 equivalent
  159. //
  160. if (*pMessageLength == 0)
  161. {
  162. UnicodeBuffer[0] = 0 ;
  163. Status = GetLastError();
  164. if (Status == ERROR_MR_MID_NOT_FOUND)
  165. {
  166. //
  167. // get the message number in Unicode
  168. //
  169. _itoa(MessageId, NumberString, 16);
  170. Status = MyAllocUnicode(NumberString, &UnicodeNumberString) ;
  171. if (Status)
  172. goto ExitPoint ;
  173. //
  174. // re-setup to get it from the system. use the not found message
  175. //
  176. dwFlags = FORMAT_MESSAGE_ARGUMENT_ARRAY |
  177. FORMAT_MESSAGE_FROM_SYSTEM;
  178. MessageId = ERROR_MR_MID_NOT_FOUND ;
  179. //
  180. // setup insert strings
  181. //
  182. MyFreeUnicodeVector(UnicodeIStrings, NumberofStrings) ;
  183. UnicodeIStrings[0] = UnicodeNumberString ;
  184. UnicodeIStrings[1] = FileName ;
  185. //
  186. // recall the API
  187. //
  188. *pMessageLength = (WORD) FormatMessageW(dwFlags,
  189. (LPVOID) lpSource,
  190. (DWORD) MessageId,
  191. 0, // LanguageId defaulted
  192. UnicodeBuffer,
  193. (DWORD)BufferLength,
  194. (va_list *)UnicodeIStrings);
  195. UnicodeIStrings[1] = NULL ;
  196. //
  197. // revert to original error
  198. //
  199. Status = ERROR_MR_MID_NOT_FOUND ;
  200. }
  201. }
  202. if (UnicodeBuffer[0])
  203. {
  204. BOOL fUsedDefault;
  205. *pMessageLength = (WORD)WideCharToMultiByte(CP_OEMCP,
  206. 0,
  207. UnicodeBuffer,
  208. -1,
  209. Buffer,
  210. BufferLength,
  211. NULL, // use system default char
  212. &fUsedDefault );
  213. if (*pMessageLength == 0)
  214. {
  215. Status = GetLastError() ;
  216. goto ExitPoint ;
  217. }
  218. }
  219. ExitPoint:
  220. //
  221. // note: UnicodeNumberString dont need to be freed
  222. // since if used, they would be in the UnicodeIStrings which is whacked
  223. //
  224. if (UnicodeBuffer) NetpMemoryFree(UnicodeBuffer) ;
  225. MyFreeUnicodeVector(UnicodeIStrings, NumberofStrings) ;
  226. return (WORD)(Status);
  227. }
  228. /************** misc unicode helper routines *************************/
  229. /*
  230. * MyAllocUnicode
  231. * Given a MBCS string, allocate a new Unicode translation of that string
  232. *
  233. * IN
  234. * pszAscii - pointer to original MBCS string
  235. * ppwszUnicode - pointer to cell to hold new Unicode string addr
  236. * OUT
  237. * ppwszUnicode - contains new Unicode string
  238. *
  239. * RETURNS
  240. * Error code, 0 if successful.
  241. *
  242. * The client must free the allocated string with MyFreeUnicode.
  243. */
  244. DWORD
  245. MyAllocUnicode(
  246. LPSTR pszAscii,
  247. LPWSTR * ppwszUnicode )
  248. {
  249. UINT count;
  250. BYTE * pbAlloc;
  251. INT cbAscii;
  252. if (pszAscii == NULL)
  253. {
  254. *ppwszUnicode = NULL;
  255. return NERR_Success;
  256. }
  257. // Calculate size of Unicode string.
  258. cbAscii = strlen(pszAscii)+1;
  259. pbAlloc = (BYTE *) NetpMemoryAllocate(sizeof(WCHAR) * cbAscii) ;
  260. if (!pbAlloc)
  261. return ERROR_NOT_ENOUGH_MEMORY ;
  262. *ppwszUnicode = (LPWSTR)pbAlloc;
  263. count = MultiByteToWideChar(CP_OEMCP,
  264. MB_PRECOMPOSED,
  265. pszAscii,
  266. cbAscii,
  267. *ppwszUnicode,
  268. cbAscii);
  269. if (count == 0)
  270. {
  271. *ppwszUnicode = NULL;
  272. NetpMemoryFree(pbAlloc);
  273. return ( GetLastError() );
  274. }
  275. return NERR_Success;
  276. }
  277. /*
  278. * MyAllocUnicode
  279. * Given an array of MBCS strings, allocate a new array of Unicode strings
  280. *
  281. * IN
  282. * ppszAscii - array of MBCS strings
  283. * cpwszUnicode - number of elements to translate
  284. * OUT
  285. * ppwszUnicode - output array of UnicodeStrings
  286. *
  287. * RETURNS
  288. * Error code, 0 if successful.
  289. *
  290. */
  291. DWORD
  292. MyAllocUnicodeVector(
  293. LPSTR * ppszAscii,
  294. LPWSTR* ppwszUnicode,
  295. UINT cpwszUnicode )
  296. {
  297. DWORD err;
  298. UINT i;
  299. for (i = 0; i < cpwszUnicode; ++i)
  300. {
  301. err = MyAllocUnicode(ppszAscii[i], ppwszUnicode+i);
  302. if (err)
  303. {
  304. MyFreeUnicodeVector(ppwszUnicode,i);
  305. return err;
  306. }
  307. }
  308. return NERR_Success;
  309. }
  310. /*
  311. * MyFreeUnicode
  312. * Deallocates a Unicode string alloc'd by MyAllocUnicode (q.v.).
  313. *
  314. * IN
  315. * pwszUnicode - pointer to the alloc'd string
  316. */
  317. VOID
  318. MyFreeUnicode( LPWSTR pwszUnicode )
  319. {
  320. if (pwszUnicode != NULL)
  321. NetpMemoryFree((LPBYTE)pwszUnicode);
  322. }
  323. /*
  324. * MyFreeUnicodeVector
  325. * Deallocates an array of Unicodes string alloc'd by MyAllocUnicodeVector.
  326. *
  327. * IN
  328. * pp - pointer to the array of strings
  329. */
  330. VOID
  331. MyFreeUnicodeVector(
  332. LPWSTR * ppwsz,
  333. UINT cpwsz )
  334. {
  335. while (cpwsz-- > 0)
  336. {
  337. MyFreeUnicode(*ppwsz);
  338. *ppwsz = NULL ;
  339. ppwsz++ ;
  340. }
  341. }