ReactOS 0.4.16-dev-2491-g3dc6630
utils.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Console Utilities Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Base set of functions for loading string resources
5 * and message strings, and handle type identification.
6 * COPYRIGHT: Copyright 2017-2021 ReactOS Team
7 * Copyright 2017-2021 Hermes Belusca-Maito
8 */
9
18/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
19#define UNICODE
20#define _UNICODE
21
22#include <windef.h>
23#include <winbase.h>
24#include <wincon.h> // Console APIs (only if kernel32 support included)
25//#include <winnls.h>
26#include <strsafe.h>
27
28/* PSEH for SEH Support */
29#include <pseh/pseh2.h>
30
31// #include "conutils.h"
32#include "utils.h"
33
34/* Predefined Resource Types */
35#ifndef MAKEINTRESOURCE
36#define MAKEINTRESOURCE(i) ((ULONG_PTR)((WORD)(i)))
37#endif
38#ifndef RT_STRING
39#define RT_STRING MAKEINTRESOURCE(6)
40#endif
41#ifndef RT_MESSAGETABLE
42#define RT_MESSAGETABLE MAKEINTRESOURCE(11)
43#endif
44
45
46#if 0 // The following function may be useful in the future...
47
48// Performs MultiByteToWideChar then WideCharToMultiByte .
49// See https://github.com/pcman-bbs/pcman-windows/blob/master/Lite/StrUtils.h#l33
50// and http://www.openfoundry.org/svn/pcman/branches/OpenPCMan_2009/Lite/StrUtils.cpp
51// for the idea.
52int
53MultiByteToMultiByte(
54 // IN WORD wTranslations,
56 IN UINT SrcCodePage,
57 IN LPCSTR lpSrcString,
58 IN int cbSrcChar,
59 IN UINT DestCodePage,
60 OUT LPSTR wDestString OPTIONAL,
61 IN int cbDestChar
62);
63
64#endif
65
108INT
109WINAPI
112 IN UINT uID,
113 IN LANGID LanguageId,
116{
117 HRSRC hrsrc;
118 HGLOBAL hmem;
119 WCHAR *p;
120 UINT i;
121
122 if (!lpBuffer)
123 return 0;
124
125 /* Use LOWORD (incremented by 1) as ResourceID */
126 /* There are always blocks of 16 strings */
129 MAKEINTRESOURCEW((LOWORD(uID) >> 4) + 1),
130 LanguageId);
131 if (!hrsrc) return 0;
132
133 hmem = LoadResource(hInstance, hrsrc);
134 if (!hmem) return 0;
135
136 p = LockResource(hmem);
137 // FreeResource(hmem);
138
139 /* Find the string we're looking for */
140 uID &= 0x000F; /* Position in the block, same as % 16 */
141 for (i = 0; i < uID; i++)
142 p += *p + 1;
143
144 /*
145 * If nBufferMax == 0, then return a read-only pointer to the resource
146 * itself in lpBuffer. It is assumed that lpBuffer is actually a (LPWSTR*).
147 */
148 if (nBufferMax == 0)
149 {
150 *((LPWSTR*)lpBuffer) = p + 1;
151 return *p;
152 }
153
154 i = min(nBufferMax - 1, *p);
155 if (i > 0)
156 {
157 memcpy(lpBuffer, p + 1, i * sizeof(WCHAR));
158 lpBuffer[i] = L'\0';
159 }
160 else
161 {
162 if (nBufferMax > 1)
163 {
164 lpBuffer[0] = L'\0';
165 return 0;
166 }
167 }
168
169 return i;
170}
171
181INT
182WINAPI
185 IN UINT uID,
188{
189 // NOTE: Instead of using LANG_NEUTRAL, one might use LANG_USER_DEFAULT...
193}
194
262DWORD
263WINAPI
266 IN LPCVOID lpSource OPTIONAL,
267 IN DWORD dwMessageId,
268 IN DWORD dwLanguageId,
270 IN DWORD nSize,
271 IN va_list *Arguments OPTIONAL)
272{
273 DWORD dwLength = 0;
274
276 {
277 /*
278 * Retrieve the message string. Wrap in SEH
279 * to protect from invalid string parameters.
280 */
282 {
284 lpSource,
285 dwMessageId,
286 dwLanguageId,
287 lpBuffer,
288 nSize,
289 Arguments);
290 }
292 {
293 dwLength = 0;
294
295 /*
296 * An exception occurred while calling FormatMessage, this is usually
297 * the sign that a parameter was invalid, either 'lpBuffer' was NULL
298 * but we did not pass the flag FORMAT_MESSAGE_ALLOCATE_BUFFER, or the
299 * array pointer 'Arguments' was NULL or did not contain enough elements,
300 * and we did not pass the flag FORMAT_MESSAGE_IGNORE_INSERTS, and the
301 * message string expected too many inserts.
302 * In this last case only, we can call again FormatMessage but ignore
303 * explicitly the inserts. The string that we will return to the user
304 * will not be pre-formatted.
305 */
308 {
309 /* Remove any possible harmful flags and always ignore inserts */
310 dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
312
313 /* If this call also throws an exception, we are really dead */
315 lpSource,
316 dwMessageId,
317 dwLanguageId,
318 lpBuffer,
319 nSize,
320 NULL /* Arguments */);
321 }
322 }
323 _SEH2_END;
324 }
326 {
327 }
328 _SEH2_END;
329
330 return dwLength;
331}
332
361LANGID
363 IN LANGID LangId OPTIONAL)
364{
365 /* The function pointer is shared amongst all threads */
366 static volatile LANGID (WINAPI *pfnSetThreadUILanguage)(LANGID) = NULL;
367
368 if (!pfnSetThreadUILanguage)
369 {
370 /* Load the API from kernel32 */
371 PVOID pFunc = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetThreadUILanguage");
372 if (!pFunc)
373 {
374 /* Fail since the API is not available */
375 return 0;
376 }
377 /* Set the function pointer in case it hasn't been already set by another thread */
378 InterlockedCompareExchangePointer((PVOID*)&pfnSetThreadUILanguage, pFunc, NULL);
379 // ASSERT(pfnSetThreadUILanguage);
380 }
381 return pfnSetThreadUILanguage(LangId);
382}
383
402BOOL
404{
405 /*
406 * More general test than IsConsoleHandle(). Consoles, as well as serial
407 * (communications) ports, etc... verify this test, but only consoles
408 * verify the IsConsoleHandle() test: indeed the latter checks whether
409 * the handle is really handled by the console subsystem.
410 */
411 return ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR);
412}
413
428BOOL
430{
431 DWORD dwMode;
432
433 /* Check whether the handle may be that of a console... */
434 if ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR)
435 return FALSE;
436
437 /*
438 * It may be. Perform another test. The idea comes from the
439 * MSDN description of the WriteConsole API:
440 *
441 * "WriteConsole fails if it is used with a standard handle
442 * that is redirected to a file. If an application processes
443 * multilingual output that can be redirected, determine whether
444 * the output handle is a console handle (one method is to call
445 * the GetConsoleMode function and check whether it succeeds).
446 * If the handle is a console handle, call WriteConsole. If the
447 * handle is not a console handle, the output is redirected and
448 * you should call WriteFile to perform the I/O."
449 */
450 return GetConsoleMode(hHandle, &dwMode);
451}
452
453/* EOF */
HINSTANCE hInstance
Definition: charmap.c:19
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define GetProcAddress(x, y)
Definition: compat.h:753
static DWORD DWORD * dwLength
Definition: fusion.c:86
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:269
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang)
Definition: res.c:164
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
char * va_list
Definition: vadefs.h:50
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
USHORT LANGID
Definition: mui.h:9
CONST void * LPCVOID
Definition: minwindef.h:164
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
_Out_ LPWSTR lpBuffer
Definition: netsh.h:68
_Out_ LPWSTR _In_ DWORD nBufferMax
Definition: netsh.h:69
#define LOWORD(l)
Definition: pedump.c:82
#define RT_STRING
Definition: pedump.c:368
_In_ UINT uID
Definition: shlwapi.h:156
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_FINALLY
Definition: pseh2_64.h:153
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define LANG_NEUTRAL
Definition: nls.h:22
#define MAKELANGID(p, s)
Definition: nls.h:15
#define SUBLANG_NEUTRAL
Definition: nls.h:167
#define IsConsoleHandle(h)
Definition: console.h:14
LANGID ConSetThreadUILanguage(IN LANGID LangId OPTIONAL)
Definition: utils.c:362
INT WINAPI K32LoadStringW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:183
INT WINAPI K32LoadStringExW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, IN LANGID LanguageId, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:110
BOOL IsTTYHandle(IN HANDLE hHandle)
Definition: utils.c:403
DWORD WINAPI FormatMessageSafeW(IN DWORD dwFlags, IN LPCVOID lpSource OPTIONAL, IN DWORD dwMessageId, IN DWORD dwLanguageId, OUT LPWSTR lpBuffer, IN DWORD nSize, IN va_list *Arguments OPTIONAL)
Definition: utils.c:264
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
void * PVOID
Definition: typedefs.h:50
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:397
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:396
#define FILE_TYPE_CHAR
Definition: winbase.h:284
#define FILE_TYPE_REMOTE
Definition: winbase.h:286
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:1834
#define WINAPI
Definition: msvc.h:6
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182