2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Utilities Library
4 * FILE: sdk/lib/conutils/utils.c
5 * PURPOSE: Base set of functions for loading string resources
6 * and message strings, and handle type identification.
7 * PROGRAMMERS: - Hermes Belusca-Maito (for the library);
8 * - All programmers who wrote the different console applications
9 * from which I took those functions and improved them.
12 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
19 #include <winuser.h> // MAKEINTRESOURCEW, RT_STRING
20 #include <wincon.h> // Console APIs (only if kernel32 support included)
23 /* PSEH for SEH Support */
24 #include <pseh/pseh2.h>
26 // #include "conutils.h"
30 * General-purpose utility functions (wrappers around,
31 * or reimplementations of, Win32 APIs).
34 #if 0 // The following function may be useful in the future...
36 // Performs MultiByteToWideChar then WideCharToMultiByte .
37 // See https://github.com/pcman-bbs/pcman-windows/blob/master/Lite/StrUtils.h#l33
38 // and http://www.openfoundry.org/svn/pcman/branches/OpenPCMan_2009/Lite/StrUtils.cpp
42 // IN WORD wTranslations,
45 IN LPCSTR lpSrcString
,
48 OUT LPSTR wDestString OPTIONAL
,
55 * 'LoadStringW' API ripped from user32.dll to remove
56 * any dependency of this library from user32.dll
61 IN HINSTANCE hInstance OPTIONAL
,
74 /* Use LOWORD (incremented by 1) as ResourceID */
75 /* There are always blocks of 16 strings */
76 // FindResourceExW(hInstance, RT_STRING, name, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
77 // NOTE: Instead of using LANG_NEUTRAL, one might use LANG_USER_DEFAULT...
78 hrsrc
= FindResourceW(hInstance
,
79 MAKEINTRESOURCEW((LOWORD(uID
) >> 4) + 1),
83 hmem
= LoadResource(hInstance
, hrsrc
);
86 p
= LockResource(hmem
);
87 // FreeResource(hmem);
89 /* Find the string we're looking for */
90 uID
&= 0x000F; /* Position in the block, same as % 16 */
91 for (i
= 0; i
< uID
; i
++)
95 * If nBufferMax == 0, then return a read-only pointer
96 * to the resource itself in lpBuffer it is assumed that
97 * lpBuffer is actually a (LPWSTR *).
101 *((LPWSTR
*)lpBuffer
) = p
+ 1;
105 i
= min(nBufferMax
- 1, *p
);
108 memcpy(lpBuffer
, p
+ 1, i
* sizeof(WCHAR
));
124 * "Safe" version of FormatMessageW, that does not crash if a malformed
125 * source string is retrieved and then being used for formatting.
126 * It basically wraps calls to FormatMessageW within SEH.
132 IN LPCVOID lpSource OPTIONAL
,
133 IN DWORD dwMessageId
,
134 IN DWORD dwLanguageId
,
137 IN
va_list *Arguments OPTIONAL
)
144 * Retrieve the message string. Wrap in SEH
145 * to protect from invalid string parameters.
149 dwLength
= FormatMessageW(dwFlags
,
157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
162 * An exception occurred while calling FormatMessage, this is usually
163 * the sign that a parameter was invalid, either 'lpBuffer' was NULL
164 * but we did not pass the flag FORMAT_MESSAGE_ALLOCATE_BUFFER, or the
165 * array pointer 'Arguments' was NULL or did not contain enough elements,
166 * and we did not pass the flag FORMAT_MESSAGE_IGNORE_INSERTS, and the
167 * message string expected too many inserts.
168 * In this last case only, we can call again FormatMessage but ignore
169 * explicitely the inserts. The string that we will return to the user
170 * will not be pre-formatted.
172 if (((dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) || lpBuffer
) &&
173 !(dwFlags
& FORMAT_MESSAGE_IGNORE_INSERTS
))
175 /* Remove any possible harmful flags and always ignore inserts */
176 dwFlags
&= ~FORMAT_MESSAGE_ARGUMENT_ARRAY
;
177 dwFlags
|= FORMAT_MESSAGE_IGNORE_INSERTS
;
179 /* If this call also throws an exception, we are really dead */
180 dwLength
= FormatMessageW(dwFlags
,
186 NULL
/* Arguments */);
200 IsTTYHandle(IN HANDLE hHandle
)
203 * More general test than IsConsoleHandle. Consoles, as well as
204 * serial ports, etc... verify this test, but only consoles verify
205 * the IsConsoleHandle test: indeed the latter checks whether
206 * the handle is really handled by the console subsystem.
208 return ((GetFileType(hHandle
) & ~FILE_TYPE_REMOTE
) == FILE_TYPE_CHAR
);
212 IsConsoleHandle(IN HANDLE hHandle
)
216 /* Check whether the handle may be that of a console... */
217 if ((GetFileType(hHandle
) & ~FILE_TYPE_REMOTE
) != FILE_TYPE_CHAR
)
221 * It may be. Perform another test. The idea comes from the
222 * MSDN description of the WriteConsole API:
224 * "WriteConsole fails if it is used with a standard handle
225 * that is redirected to a file. If an application processes
226 * multilingual output that can be redirected, determine whether
227 * the output handle is a console handle (one method is to call
228 * the GetConsoleMode function and check whether it succeeds).
229 * If the handle is a console handle, call WriteConsole. If the
230 * handle is not a console handle, the output is redirected and
231 * you should call WriteFile to perform the I/O."
233 return GetConsoleMode(hHandle
, &dwMode
);