1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS User API Server DLL
36718a1aaSHermès Bélusca-Maïto * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
46718a1aaSHermès Bélusca-Maïto * PURPOSE: Hard errors support.
56718a1aaSHermès Bélusca-Maïto * COPYRIGHT: Copyright 2007-2018 Dmitry Philippov (shedon@mail.ru)
66718a1aaSHermès Bélusca-Maïto * Copyright 2010-2018 Timo Kreuzer (timo.kreuzer@reactos.org)
76718a1aaSHermès Bélusca-Maïto * Copyright 2012-2018 Hermes Belusca-Maito
86718a1aaSHermès Bélusca-Maïto * Copyright 2018 Giannis Adamopoulos
9c2c66affSColin Finck */
10c2c66affSColin Finck
11c2c66affSColin Finck /* INCLUDES *******************************************************************/
12c2c66affSColin Finck
13c2c66affSColin Finck #include "usersrv.h"
14c2c66affSColin Finck
156718a1aaSHermès Bélusca-Maïto #define NTOS_MODE_USER
16c2c66affSColin Finck #include <ndk/mmfuncs.h>
176718a1aaSHermès Bélusca-Maïto
186718a1aaSHermès Bélusca-Maïto #include <undocelfapi.h>
196718a1aaSHermès Bélusca-Maïto #include <ntstrsafe.h>
20c2c66affSColin Finck
215a1a35caSHermès Bélusca-Maïto #include "resource.h"
225a1a35caSHermès Bélusca-Maïto
23c2c66affSColin Finck #define NDEBUG
24c2c66affSColin Finck #include <debug.h>
25c2c66affSColin Finck
26c2c66affSColin Finck
27c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
28c2c66affSColin Finck
295a1a35caSHermès Bélusca-Maïto /* Cache for the localized hard-error message box strings */
305a1a35caSHermès Bélusca-Maïto LANGID g_CurrentUserLangId = 0;
315a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_SuccessU = {0, 0, NULL};
325a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_InformationU = {0, 0, NULL};
335a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_WarningU = {0, 0, NULL};
345a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_ErrorU = {0, 0, NULL};
355a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_SystemProcessU = {0, 0, NULL};
365a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_OKTerminateU = {0, 0, NULL};
375a1a35caSHermès Bélusca-Maïto UNICODE_STRING g_CancelDebugU = {0, 0, NULL};
385a1a35caSHermès Bélusca-Maïto
395a1a35caSHermès Bélusca-Maïto VOID
RtlLoadUnicodeString(IN HINSTANCE hInstance OPTIONAL,IN UINT uID,OUT PUNICODE_STRING pUnicodeString,IN PCWSTR pDefaultString)405a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(
415a1a35caSHermès Bélusca-Maïto IN HINSTANCE hInstance OPTIONAL,
425a1a35caSHermès Bélusca-Maïto IN UINT uID,
435a1a35caSHermès Bélusca-Maïto OUT PUNICODE_STRING pUnicodeString,
445a1a35caSHermès Bélusca-Maïto IN PCWSTR pDefaultString)
455a1a35caSHermès Bélusca-Maïto {
465a1a35caSHermès Bélusca-Maïto UINT Length;
475a1a35caSHermès Bélusca-Maïto
485a1a35caSHermès Bélusca-Maïto /* Try to load the string from the resource */
495a1a35caSHermès Bélusca-Maïto Length = LoadStringW(hInstance, uID, (LPWSTR)&pUnicodeString->Buffer, 0);
505a1a35caSHermès Bélusca-Maïto if (Length == 0)
515a1a35caSHermès Bélusca-Maïto {
525a1a35caSHermès Bélusca-Maïto /* If the resource string was not found, use the fallback default one */
535a1a35caSHermès Bélusca-Maïto RtlInitUnicodeString(pUnicodeString, pDefaultString);
545a1a35caSHermès Bélusca-Maïto }
555a1a35caSHermès Bélusca-Maïto else
565a1a35caSHermès Bélusca-Maïto {
575a1a35caSHermès Bélusca-Maïto /* Set the string length (not NULL-terminated!) */
585a1a35caSHermès Bélusca-Maïto pUnicodeString->MaximumLength = (USHORT)(Length * sizeof(WCHAR));
595a1a35caSHermès Bélusca-Maïto pUnicodeString->Length = pUnicodeString->MaximumLength;
605a1a35caSHermès Bélusca-Maïto }
615a1a35caSHermès Bélusca-Maïto }
625a1a35caSHermès Bélusca-Maïto
635a1a35caSHermès Bélusca-Maïto
6429d56f2bSHermès Bélusca-Maïto /*
6529d56f2bSHermès Bélusca-Maïto * NOTE: _scwprintf() is NOT exported by ntdll.dll,
6629d56f2bSHermès Bélusca-Maïto * only _vscwprintf() is, so we need to implement it here.
6729d56f2bSHermès Bélusca-Maïto * Code comes from sdk/lib/crt/printf/_scwprintf.c .
6829d56f2bSHermès Bélusca-Maïto */
6929d56f2bSHermès Bélusca-Maïto int
7029d56f2bSHermès Bélusca-Maïto __cdecl
_scwprintf(const wchar_t * format,...)7129d56f2bSHermès Bélusca-Maïto _scwprintf(
7229d56f2bSHermès Bélusca-Maïto const wchar_t *format,
7329d56f2bSHermès Bélusca-Maïto ...)
7429d56f2bSHermès Bélusca-Maïto {
7529d56f2bSHermès Bélusca-Maïto int len;
7629d56f2bSHermès Bélusca-Maïto va_list args;
7729d56f2bSHermès Bélusca-Maïto
7829d56f2bSHermès Bélusca-Maïto va_start(args, format);
7929d56f2bSHermès Bélusca-Maïto len = _vscwprintf(format, args);
8029d56f2bSHermès Bélusca-Maïto va_end(args);
8129d56f2bSHermès Bélusca-Maïto
8229d56f2bSHermès Bélusca-Maïto return len;
8329d56f2bSHermès Bélusca-Maïto }
8429d56f2bSHermès Bélusca-Maïto
8529d56f2bSHermès Bélusca-Maïto
862b299f5fSHermès Bélusca-Maïto /* FIXME */
872b299f5fSHermès Bélusca-Maïto int
882b299f5fSHermès Bélusca-Maïto WINAPI
892b299f5fSHermès Bélusca-Maïto MessageBoxTimeoutW(
902b299f5fSHermès Bélusca-Maïto HWND hWnd,
912b299f5fSHermès Bélusca-Maïto LPCWSTR lpText,
922b299f5fSHermès Bélusca-Maïto LPCWSTR lpCaption,
932b299f5fSHermès Bélusca-Maïto UINT uType,
942b299f5fSHermès Bélusca-Maïto WORD wLanguageId,
952b299f5fSHermès Bélusca-Maïto DWORD dwTime);
962b299f5fSHermès Bélusca-Maïto
972b299f5fSHermès Bélusca-Maïto
98c2c66affSColin Finck static
995a1a35caSHermès Bélusca-Maïto VOID
UserpCaptureStringParameters(OUT PULONG_PTR Parameters,OUT PULONG SizeOfAllUnicodeStrings,IN PHARDERROR_MSG Message,IN HANDLE hProcess OPTIONAL)100c2c66affSColin Finck UserpCaptureStringParameters(
101c2c66affSColin Finck OUT PULONG_PTR Parameters,
102c2c66affSColin Finck OUT PULONG SizeOfAllUnicodeStrings,
1035a1a35caSHermès Bélusca-Maïto IN PHARDERROR_MSG Message,
1042b299f5fSHermès Bélusca-Maïto IN HANDLE hProcess OPTIONAL)
105c2c66affSColin Finck {
1065a1a35caSHermès Bélusca-Maïto NTSTATUS Status;
1072b299f5fSHermès Bélusca-Maïto ULONG nParam, Size = 0;
108c2c66affSColin Finck UNICODE_STRING TempStringU, ParamStringU;
109c2c66affSColin Finck ANSI_STRING TempStringA;
110c2c66affSColin Finck
111c2c66affSColin Finck if (SizeOfAllUnicodeStrings)
112c2c66affSColin Finck *SizeOfAllUnicodeStrings = 0;
113c2c66affSColin Finck
114c2c66affSColin Finck /* Read all strings from client space */
1155a1a35caSHermès Bélusca-Maïto for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam)
116c2c66affSColin Finck {
117c2c66affSColin Finck Parameters[nParam] = 0;
118c2c66affSColin Finck
119c2c66affSColin Finck /* Check if the current parameter is a unicode string */
1205a1a35caSHermès Bélusca-Maïto if (Message->UnicodeStringParameterMask & (1 << nParam))
121c2c66affSColin Finck {
1222b299f5fSHermès Bélusca-Maïto /* Skip this string if we do not have a client process */
1232b299f5fSHermès Bélusca-Maïto if (!hProcess)
1242b299f5fSHermès Bélusca-Maïto continue;
1252b299f5fSHermès Bélusca-Maïto
126c2c66affSColin Finck /* Read the UNICODE_STRING from the process memory */
127c2c66affSColin Finck Status = NtReadVirtualMemory(hProcess,
1285a1a35caSHermès Bélusca-Maïto (PVOID)Message->Parameters[nParam],
129c2c66affSColin Finck &ParamStringU,
130c2c66affSColin Finck sizeof(ParamStringU),
131c2c66affSColin Finck NULL);
132c2c66affSColin Finck if (!NT_SUCCESS(Status))
1332b299f5fSHermès Bélusca-Maïto {
1342b299f5fSHermès Bélusca-Maïto /* We failed, skip this string */
1355a1a35caSHermès Bélusca-Maïto DPRINT1("NtReadVirtualMemory(Message->Parameters) failed, Status 0x%lx, skipping.\n", Status);
1362b299f5fSHermès Bélusca-Maïto continue;
1372b299f5fSHermès Bélusca-Maïto }
138c2c66affSColin Finck
13908d70697SHermès Bélusca-Maïto /* Allocate a buffer for the string and reserve a NULL terminator */
14008d70697SHermès Bélusca-Maïto TempStringU.MaximumLength = ParamStringU.Length + sizeof(UNICODE_NULL);
141c2c66affSColin Finck TempStringU.Length = ParamStringU.Length;
142c2c66affSColin Finck TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
143c2c66affSColin Finck HEAP_ZERO_MEMORY,
144c2c66affSColin Finck TempStringU.MaximumLength);
145c2c66affSColin Finck if (!TempStringU.Buffer)
146c2c66affSColin Finck {
1472b299f5fSHermès Bélusca-Maïto /* We failed, skip this string */
1485a1a35caSHermès Bélusca-Maïto DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringU.MaximumLength);
1492b299f5fSHermès Bélusca-Maïto continue;
150c2c66affSColin Finck }
151c2c66affSColin Finck
152c2c66affSColin Finck /* Read the string buffer from the process memory */
153c2c66affSColin Finck Status = NtReadVirtualMemory(hProcess,
154c2c66affSColin Finck ParamStringU.Buffer,
155c2c66affSColin Finck TempStringU.Buffer,
156c2c66affSColin Finck ParamStringU.Length,
157c2c66affSColin Finck NULL);
158c2c66affSColin Finck if (!NT_SUCCESS(Status))
159c2c66affSColin Finck {
1602b299f5fSHermès Bélusca-Maïto /* We failed, skip this string */
1615a1a35caSHermès Bélusca-Maïto DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx, skipping.\n", Status);
162c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
1632b299f5fSHermès Bélusca-Maïto continue;
164c2c66affSColin Finck }
16508d70697SHermès Bélusca-Maïto /* NULL-terminate the string */
16608d70697SHermès Bélusca-Maïto TempStringU.Buffer[TempStringU.Length / sizeof(WCHAR)] = UNICODE_NULL;
167c2c66affSColin Finck
168c2c66affSColin Finck DPRINT("ParamString = \'%wZ\'\n", &TempStringU);
169c2c66affSColin Finck
17008d70697SHermès Bélusca-Maïto if (Message->Status == STATUS_SERVICE_NOTIFICATION)
17108d70697SHermès Bélusca-Maïto {
17208d70697SHermès Bélusca-Maïto /* Just keep the allocated NULL-terminated UNICODE string */
17308d70697SHermès Bélusca-Maïto Parameters[nParam] = (ULONG_PTR)TempStringU.Buffer;
17408d70697SHermès Bélusca-Maïto Size += TempStringU.Length;
17508d70697SHermès Bélusca-Maïto }
17608d70697SHermès Bélusca-Maïto else
17708d70697SHermès Bélusca-Maïto {
17875e80632SHermès Bélusca-Maïto /* Allocate a buffer for conversion to ANSI string */
17975e80632SHermès Bélusca-Maïto TempStringA.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&TempStringU);
180c2c66affSColin Finck TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
181c2c66affSColin Finck HEAP_ZERO_MEMORY,
182c2c66affSColin Finck TempStringA.MaximumLength);
183c2c66affSColin Finck if (!TempStringA.Buffer)
184c2c66affSColin Finck {
1852b299f5fSHermès Bélusca-Maïto /* We failed, skip this string */
1865a1a35caSHermès Bélusca-Maïto DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringA.MaximumLength);
187c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
1882b299f5fSHermès Bélusca-Maïto continue;
189c2c66affSColin Finck }
190c2c66affSColin Finck
191c2c66affSColin Finck /* Convert string to ANSI and free temporary buffer */
192c2c66affSColin Finck Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE);
193c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
194c2c66affSColin Finck if (!NT_SUCCESS(Status))
195c2c66affSColin Finck {
1962b299f5fSHermès Bélusca-Maïto /* We failed, skip this string */
1975a1a35caSHermès Bélusca-Maïto DPRINT1("RtlUnicodeStringToAnsiString() failed, Status 0x%lx, skipping.\n", Status);
198c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer);
1992b299f5fSHermès Bélusca-Maïto continue;
200c2c66affSColin Finck }
201c2c66affSColin Finck
20208d70697SHermès Bélusca-Maïto /* Note: RtlUnicodeStringToAnsiString() returns a NULL-terminated string */
203c2c66affSColin Finck Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer;
204c2c66affSColin Finck Size += TempStringU.Length;
205c2c66affSColin Finck }
20608d70697SHermès Bélusca-Maïto }
207c2c66affSColin Finck else
208c2c66affSColin Finck {
2092b299f5fSHermès Bélusca-Maïto /* It's not a unicode string, just copy the parameter */
2105a1a35caSHermès Bélusca-Maïto Parameters[nParam] = Message->Parameters[nParam];
211c2c66affSColin Finck }
212c2c66affSColin Finck }
213c2c66affSColin Finck
214c2c66affSColin Finck if (SizeOfAllUnicodeStrings)
215c2c66affSColin Finck *SizeOfAllUnicodeStrings = Size;
216c2c66affSColin Finck }
217c2c66affSColin Finck
218c2c66affSColin Finck static
2199ea2783eSHermès Bélusca-Maïto VOID
UserpFreeStringParameters(IN OUT PULONG_PTR Parameters,IN PHARDERROR_MSG Message)2209ea2783eSHermès Bélusca-Maïto UserpFreeStringParameters(
2219ea2783eSHermès Bélusca-Maïto IN OUT PULONG_PTR Parameters,
2229ea2783eSHermès Bélusca-Maïto IN PHARDERROR_MSG Message)
2239ea2783eSHermès Bélusca-Maïto {
2249ea2783eSHermès Bélusca-Maïto ULONG nParam;
2259ea2783eSHermès Bélusca-Maïto
2269ea2783eSHermès Bélusca-Maïto /* Loop all parameters */
2279ea2783eSHermès Bélusca-Maïto for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam)
2289ea2783eSHermès Bélusca-Maïto {
2299ea2783eSHermès Bélusca-Maïto /* Check if the current parameter is a string */
2309ea2783eSHermès Bélusca-Maïto if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0))
2319ea2783eSHermès Bélusca-Maïto {
2329ea2783eSHermès Bélusca-Maïto /* Free the string buffer */
2339ea2783eSHermès Bélusca-Maïto RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
2349ea2783eSHermès Bélusca-Maïto }
2359ea2783eSHermès Bélusca-Maïto }
2369ea2783eSHermès Bélusca-Maïto }
2379ea2783eSHermès Bélusca-Maïto
2389ea2783eSHermès Bélusca-Maïto static
239c2c66affSColin Finck NTSTATUS
UserpGetClientFileName(OUT PUNICODE_STRING ClientFileNameU,IN HANDLE hProcess)2409ea2783eSHermès Bélusca-Maïto UserpGetClientFileName(
2419ea2783eSHermès Bélusca-Maïto OUT PUNICODE_STRING ClientFileNameU,
2429ea2783eSHermès Bélusca-Maïto IN HANDLE hProcess)
2439ea2783eSHermès Bélusca-Maïto {
2449ea2783eSHermès Bélusca-Maïto PLIST_ENTRY ModuleListHead;
2459ea2783eSHermès Bélusca-Maïto PLIST_ENTRY Entry;
2469ea2783eSHermès Bélusca-Maïto PLDR_DATA_TABLE_ENTRY Module;
2479ea2783eSHermès Bélusca-Maïto PPEB_LDR_DATA Ldr;
2489ea2783eSHermès Bélusca-Maïto PROCESS_BASIC_INFORMATION ClientBasicInfo;
2499ea2783eSHermès Bélusca-Maïto LDR_DATA_TABLE_ENTRY ModuleData;
2509ea2783eSHermès Bélusca-Maïto PVOID ClientDllBase;
2519ea2783eSHermès Bélusca-Maïto NTSTATUS Status;
2529ea2783eSHermès Bélusca-Maïto PPEB Peb;
2539ea2783eSHermès Bélusca-Maïto
2549ea2783eSHermès Bélusca-Maïto /* Initialize string */
2559ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
2569ea2783eSHermès Bélusca-Maïto
2579ea2783eSHermès Bélusca-Maïto /* Query process information */
2589ea2783eSHermès Bélusca-Maïto Status = NtQueryInformationProcess(hProcess,
2599ea2783eSHermès Bélusca-Maïto ProcessBasicInformation,
2609ea2783eSHermès Bélusca-Maïto &ClientBasicInfo,
2619ea2783eSHermès Bélusca-Maïto sizeof(ClientBasicInfo),
2629ea2783eSHermès Bélusca-Maïto NULL);
2639ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status)) return Status;
2649ea2783eSHermès Bélusca-Maïto
2659ea2783eSHermès Bélusca-Maïto /* Locate the process loader data table and retrieve its name from it */
2669ea2783eSHermès Bélusca-Maïto
2679ea2783eSHermès Bélusca-Maïto Peb = ClientBasicInfo.PebBaseAddress;
2689ea2783eSHermès Bélusca-Maïto if (!Peb) return STATUS_UNSUCCESSFUL;
2699ea2783eSHermès Bélusca-Maïto
2709ea2783eSHermès Bélusca-Maïto Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL);
2719ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status)) return Status;
2729ea2783eSHermès Bélusca-Maïto
2739ea2783eSHermès Bélusca-Maïto ModuleListHead = &Ldr->InLoadOrderModuleList;
2749ea2783eSHermès Bélusca-Maïto Status = NtReadVirtualMemory(hProcess,
2759ea2783eSHermès Bélusca-Maïto &ModuleListHead->Flink,
2769ea2783eSHermès Bélusca-Maïto &Entry,
2779ea2783eSHermès Bélusca-Maïto sizeof(Entry),
2789ea2783eSHermès Bélusca-Maïto NULL);
2799ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status)) return Status;
2809ea2783eSHermès Bélusca-Maïto
2819ea2783eSHermès Bélusca-Maïto if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL;
2829ea2783eSHermès Bélusca-Maïto
2839ea2783eSHermès Bélusca-Maïto Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2849ea2783eSHermès Bélusca-Maïto
2859ea2783eSHermès Bélusca-Maïto Status = NtReadVirtualMemory(hProcess,
2869ea2783eSHermès Bélusca-Maïto Module,
2879ea2783eSHermès Bélusca-Maïto &ModuleData,
2889ea2783eSHermès Bélusca-Maïto sizeof(ModuleData),
2899ea2783eSHermès Bélusca-Maïto NULL);
2909ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status)) return Status;
2919ea2783eSHermès Bélusca-Maïto
2929ea2783eSHermès Bélusca-Maïto Status = NtReadVirtualMemory(hProcess,
2939ea2783eSHermès Bélusca-Maïto &Peb->ImageBaseAddress,
2949ea2783eSHermès Bélusca-Maïto &ClientDllBase,
2959ea2783eSHermès Bélusca-Maïto sizeof(ClientDllBase),
2969ea2783eSHermès Bélusca-Maïto NULL);
2979ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status)) return Status;
2989ea2783eSHermès Bélusca-Maïto
2999ea2783eSHermès Bélusca-Maïto if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL;
3009ea2783eSHermès Bélusca-Maïto
3019ea2783eSHermès Bélusca-Maïto ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength;
3029ea2783eSHermès Bélusca-Maïto ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
3039ea2783eSHermès Bélusca-Maïto HEAP_ZERO_MEMORY,
3049ea2783eSHermès Bélusca-Maïto ClientFileNameU->MaximumLength);
3059ea2783eSHermès Bélusca-Maïto if (!ClientFileNameU->Buffer)
3069ea2783eSHermès Bélusca-Maïto {
3079ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
3089ea2783eSHermès Bélusca-Maïto return STATUS_NO_MEMORY;
3099ea2783eSHermès Bélusca-Maïto }
3109ea2783eSHermès Bélusca-Maïto
3119ea2783eSHermès Bélusca-Maïto Status = NtReadVirtualMemory(hProcess,
3129ea2783eSHermès Bélusca-Maïto ModuleData.BaseDllName.Buffer,
3139ea2783eSHermès Bélusca-Maïto ClientFileNameU->Buffer,
3149ea2783eSHermès Bélusca-Maïto ClientFileNameU->MaximumLength,
3159ea2783eSHermès Bélusca-Maïto NULL);
3169ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status))
3179ea2783eSHermès Bélusca-Maïto {
3189ea2783eSHermès Bélusca-Maïto RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
3199ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
3209ea2783eSHermès Bélusca-Maïto return Status;
3219ea2783eSHermès Bélusca-Maïto }
3229ea2783eSHermès Bélusca-Maïto
3239ea2783eSHermès Bélusca-Maïto ClientFileNameU->Length = (USHORT)(wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR));
3249ea2783eSHermès Bélusca-Maïto DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU);
3259ea2783eSHermès Bélusca-Maïto
3269ea2783eSHermès Bélusca-Maïto return STATUS_SUCCESS;
3279ea2783eSHermès Bélusca-Maïto }
3289ea2783eSHermès Bélusca-Maïto
3299ea2783eSHermès Bélusca-Maïto static
3309ea2783eSHermès Bélusca-Maïto VOID
UserpDuplicateParamStringToUnicodeString(IN OUT PUNICODE_STRING UnicodeString,IN PCWSTR ParamString)33108d70697SHermès Bélusca-Maïto UserpDuplicateParamStringToUnicodeString(
33208d70697SHermès Bélusca-Maïto IN OUT PUNICODE_STRING UnicodeString,
33308d70697SHermès Bélusca-Maïto IN PCWSTR ParamString)
33408d70697SHermès Bélusca-Maïto {
33508d70697SHermès Bélusca-Maïto UNICODE_STRING FormatU, TempStringU;
33608d70697SHermès Bélusca-Maïto
33708d70697SHermès Bélusca-Maïto /* Calculate buffer length for the text message */
33808d70697SHermès Bélusca-Maïto RtlInitUnicodeString(&FormatU, (PWSTR)ParamString);
33908d70697SHermès Bélusca-Maïto if (UnicodeString->MaximumLength < FormatU.MaximumLength)
34008d70697SHermès Bélusca-Maïto {
34108d70697SHermès Bélusca-Maïto /* Duplicate the text message in a larger buffer */
34208d70697SHermès Bélusca-Maïto if (NT_SUCCESS(RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
34308d70697SHermès Bélusca-Maïto &FormatU, &TempStringU)))
34408d70697SHermès Bélusca-Maïto {
34508d70697SHermès Bélusca-Maïto *UnicodeString = TempStringU;
34608d70697SHermès Bélusca-Maïto }
34708d70697SHermès Bélusca-Maïto else
34808d70697SHermès Bélusca-Maïto {
34908d70697SHermès Bélusca-Maïto /* We could not allocate a larger buffer; continue using the smaller original buffer */
35008d70697SHermès Bélusca-Maïto DPRINT1("Cannot allocate memory for UnicodeString, use original buffer.\n");
35108d70697SHermès Bélusca-Maïto
35208d70697SHermès Bélusca-Maïto /* Copy the truncated string, NULL-terminate it */
35308d70697SHermès Bélusca-Maïto FormatU.MaximumLength = UnicodeString->MaximumLength;
35408d70697SHermès Bélusca-Maïto FormatU.Length = FormatU.MaximumLength - sizeof(UNICODE_NULL);
35508d70697SHermès Bélusca-Maïto RtlCopyUnicodeString(UnicodeString, &FormatU);
35608d70697SHermès Bélusca-Maïto }
35708d70697SHermès Bélusca-Maïto }
35808d70697SHermès Bélusca-Maïto else
35908d70697SHermès Bélusca-Maïto {
36008d70697SHermès Bélusca-Maïto /* Copy the string, NULL-terminate it */
36108d70697SHermès Bélusca-Maïto RtlCopyUnicodeString(UnicodeString, &FormatU);
36208d70697SHermès Bélusca-Maïto }
36308d70697SHermès Bélusca-Maïto }
36408d70697SHermès Bélusca-Maïto
36508d70697SHermès Bélusca-Maïto static
36608d70697SHermès Bélusca-Maïto VOID
UserpFormatMessages(IN OUT PUNICODE_STRING TextStringU,IN OUT PUNICODE_STRING CaptionStringU,OUT PUINT pdwType,OUT PULONG pdwTimeout,IN PHARDERROR_MSG Message)367c2c66affSColin Finck UserpFormatMessages(
3689ea2783eSHermès Bélusca-Maïto IN OUT PUNICODE_STRING TextStringU,
3699ea2783eSHermès Bélusca-Maïto IN OUT PUNICODE_STRING CaptionStringU,
37008d70697SHermès Bélusca-Maïto OUT PUINT pdwType,
3712363fee5SHermès Bélusca-Maïto OUT PULONG pdwTimeout,
3729ea2783eSHermès Bélusca-Maïto IN PHARDERROR_MSG Message)
373c2c66affSColin Finck {
37429d56f2bSHermès Bélusca-Maïto /* Special hardcoded messages */
37529d56f2bSHermès Bélusca-Maïto static const PCWSTR pszUnknownHardError =
37629d56f2bSHermès Bélusca-Maïto L"Unknown Hard Error 0x%08lx\n"
37729d56f2bSHermès Bélusca-Maïto L"Parameters: 0x%p 0x%p 0x%p 0x%p";
37829d56f2bSHermès Bélusca-Maïto static const PCWSTR pszExceptionHardError =
37929d56f2bSHermès Bélusca-Maïto L"Exception processing message 0x%08lx\n"
38029d56f2bSHermès Bélusca-Maïto L"Parameters: 0x%p 0x%p 0x%p 0x%p";
38129d56f2bSHermès Bélusca-Maïto
382c2c66affSColin Finck NTSTATUS Status;
3839ea2783eSHermès Bélusca-Maïto OBJECT_ATTRIBUTES ObjectAttributes;
3849ea2783eSHermès Bélusca-Maïto HANDLE hProcess;
38529d56f2bSHermès Bélusca-Maïto ULONG Severity = (ULONG)(Message->Status) >> 30;
3869ea2783eSHermès Bélusca-Maïto ULONG SizeOfStrings;
3879ea2783eSHermès Bélusca-Maïto ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0};
3889ea2783eSHermès Bélusca-Maïto ULONG_PTR CopyParameters[MAXIMUM_HARDERROR_PARAMETERS];
3899ea2783eSHermès Bélusca-Maïto UNICODE_STRING WindowTitleU, FileNameU, TempStringU, FormatU, Format2U;
3906718a1aaSHermès Bélusca-Maïto ANSI_STRING FormatA, Format2A;
3915a1a35caSHermès Bélusca-Maïto HWND hwndOwner;
392c2c66affSColin Finck PMESSAGE_RESOURCE_ENTRY MessageResource;
3935a1a35caSHermès Bélusca-Maïto PWSTR FormatString, pszBuffer;
3949ea2783eSHermès Bélusca-Maïto size_t cszBuffer;
395c2c66affSColin Finck
3969ea2783eSHermès Bélusca-Maïto /* Open client process */
3979ea2783eSHermès Bélusca-Maïto InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
3989ea2783eSHermès Bélusca-Maïto Status = NtOpenProcess(&hProcess,
3999ea2783eSHermès Bélusca-Maïto PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
4009ea2783eSHermès Bélusca-Maïto &ObjectAttributes,
4019ea2783eSHermès Bélusca-Maïto &Message->h.ClientId);
4029ea2783eSHermès Bélusca-Maïto if (!NT_SUCCESS(Status))
4039ea2783eSHermès Bélusca-Maïto {
4049ea2783eSHermès Bélusca-Maïto DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status);
4059ea2783eSHermès Bélusca-Maïto hProcess = NULL;
4069ea2783eSHermès Bélusca-Maïto }
4079ea2783eSHermès Bélusca-Maïto
4089ea2783eSHermès Bélusca-Maïto /* Capture all string parameters from the process memory */
4099ea2783eSHermès Bélusca-Maïto UserpCaptureStringParameters(Parameters, &SizeOfStrings, Message, hProcess);
4109ea2783eSHermès Bélusca-Maïto
41129d56f2bSHermès Bélusca-Maïto /* Initialize the output strings */
41229d56f2bSHermès Bélusca-Maïto TextStringU->Length = 0;
41329d56f2bSHermès Bélusca-Maïto TextStringU->Buffer[0] = UNICODE_NULL;
41429d56f2bSHermès Bélusca-Maïto
41529d56f2bSHermès Bélusca-Maïto CaptionStringU->Length = 0;
41629d56f2bSHermès Bélusca-Maïto CaptionStringU->Buffer[0] = UNICODE_NULL;
41729d56f2bSHermès Bélusca-Maïto
41808d70697SHermès Bélusca-Maïto /*
41908d70697SHermès Bélusca-Maïto * Check whether it is a service notification, in which case
42008d70697SHermès Bélusca-Maïto * we format the parameters and take the short route.
42108d70697SHermès Bélusca-Maïto */
42208d70697SHermès Bélusca-Maïto if (Message->Status == STATUS_SERVICE_NOTIFICATION)
42308d70697SHermès Bélusca-Maïto {
42408d70697SHermès Bélusca-Maïto /* Close the process handle */
42508d70697SHermès Bélusca-Maïto if (hProcess) NtClose(hProcess);
42608d70697SHermès Bélusca-Maïto
42708d70697SHermès Bélusca-Maïto /*
42808d70697SHermès Bélusca-Maïto * Retrieve the message box flags. Note that we filter out
42908d70697SHermès Bélusca-Maïto * MB_SERVICE_NOTIFICATION to not enter an infinite recursive
43008d70697SHermès Bélusca-Maïto * loop when we will call MessageBox() later on.
43108d70697SHermès Bélusca-Maïto */
43208d70697SHermès Bélusca-Maïto *pdwType = (UINT)Parameters[2] & ~MB_SERVICE_NOTIFICATION;
43308d70697SHermès Bélusca-Maïto
43429d56f2bSHermès Bélusca-Maïto /*
43529d56f2bSHermès Bélusca-Maïto * Duplicate the UNICODE text message and caption.
43629d56f2bSHermès Bélusca-Maïto * If no strings or invalid ones have been provided, keep
43729d56f2bSHermès Bélusca-Maïto * the original buffers and reset the string lengths to zero.
43829d56f2bSHermès Bélusca-Maïto */
43908d70697SHermès Bélusca-Maïto if (Message->UnicodeStringParameterMask & 0x1)
44008d70697SHermès Bélusca-Maïto UserpDuplicateParamStringToUnicodeString(TextStringU, (PCWSTR)Parameters[0]);
44108d70697SHermès Bélusca-Maïto if (Message->UnicodeStringParameterMask & 0x2)
44208d70697SHermès Bélusca-Maïto UserpDuplicateParamStringToUnicodeString(CaptionStringU, (PCWSTR)Parameters[1]);
44308d70697SHermès Bélusca-Maïto
4442363fee5SHermès Bélusca-Maïto /* Set the timeout */
4452363fee5SHermès Bélusca-Maïto if (Message->NumberOfParameters >= 4)
4462363fee5SHermès Bélusca-Maïto *pdwTimeout = (ULONG)Parameters[3];
4472363fee5SHermès Bélusca-Maïto else
4482363fee5SHermès Bélusca-Maïto *pdwTimeout = INFINITE;
4492363fee5SHermès Bélusca-Maïto
45008d70697SHermès Bélusca-Maïto goto Quit;
45108d70697SHermès Bélusca-Maïto }
45208d70697SHermès Bélusca-Maïto
45308d70697SHermès Bélusca-Maïto /* Set the message box type */
45408d70697SHermès Bélusca-Maïto *pdwType = 0;
45508d70697SHermès Bélusca-Maïto switch (Message->ValidResponseOptions)
45608d70697SHermès Bélusca-Maïto {
45708d70697SHermès Bélusca-Maïto case OptionAbortRetryIgnore:
45808d70697SHermès Bélusca-Maïto *pdwType = MB_ABORTRETRYIGNORE;
45908d70697SHermès Bélusca-Maïto break;
46008d70697SHermès Bélusca-Maïto case OptionOk:
46108d70697SHermès Bélusca-Maïto *pdwType = MB_OK;
46208d70697SHermès Bélusca-Maïto break;
46308d70697SHermès Bélusca-Maïto case OptionOkCancel:
46408d70697SHermès Bélusca-Maïto *pdwType = MB_OKCANCEL;
46508d70697SHermès Bélusca-Maïto break;
46608d70697SHermès Bélusca-Maïto case OptionRetryCancel:
46708d70697SHermès Bélusca-Maïto *pdwType = MB_RETRYCANCEL;
46808d70697SHermès Bélusca-Maïto break;
46908d70697SHermès Bélusca-Maïto case OptionYesNo:
47008d70697SHermès Bélusca-Maïto *pdwType = MB_YESNO;
47108d70697SHermès Bélusca-Maïto break;
47208d70697SHermès Bélusca-Maïto case OptionYesNoCancel:
47308d70697SHermès Bélusca-Maïto *pdwType = MB_YESNOCANCEL;
47408d70697SHermès Bélusca-Maïto break;
47508d70697SHermès Bélusca-Maïto case OptionShutdownSystem:
47608d70697SHermès Bélusca-Maïto *pdwType = MB_OK;
47708d70697SHermès Bélusca-Maïto break;
47808d70697SHermès Bélusca-Maïto case OptionOkNoWait:
47908d70697SHermès Bélusca-Maïto *pdwType = MB_OK;
48008d70697SHermès Bélusca-Maïto break;
48108d70697SHermès Bélusca-Maïto case OptionCancelTryContinue:
48208d70697SHermès Bélusca-Maïto *pdwType = MB_CANCELTRYCONTINUE;
48308d70697SHermès Bélusca-Maïto break;
48408d70697SHermès Bélusca-Maïto }
48508d70697SHermès Bélusca-Maïto
48608d70697SHermès Bélusca-Maïto /* Set the severity icon */
48708d70697SHermès Bélusca-Maïto // STATUS_SEVERITY_SUCCESS
48808d70697SHermès Bélusca-Maïto if (Severity == STATUS_SEVERITY_INFORMATIONAL) *pdwType |= MB_ICONINFORMATION;
48908d70697SHermès Bélusca-Maïto else if (Severity == STATUS_SEVERITY_WARNING) *pdwType |= MB_ICONWARNING;
49008d70697SHermès Bélusca-Maïto else if (Severity == STATUS_SEVERITY_ERROR) *pdwType |= MB_ICONERROR;
49108d70697SHermès Bélusca-Maïto
49208d70697SHermès Bélusca-Maïto *pdwType |= MB_SYSTEMMODAL | MB_SETFOREGROUND;
49308d70697SHermès Bélusca-Maïto
4942363fee5SHermès Bélusca-Maïto /* Set the timeout */
4952363fee5SHermès Bélusca-Maïto *pdwTimeout = INFINITE;
4962363fee5SHermès Bélusca-Maïto
4972b299f5fSHermès Bélusca-Maïto /* Copy the Parameters array locally */
4989ea2783eSHermès Bélusca-Maïto RtlCopyMemory(&CopyParameters, Parameters, sizeof(CopyParameters));
499c2c66affSColin Finck
5002b299f5fSHermès Bélusca-Maïto /* Get the file name of the client process */
5012b299f5fSHermès Bélusca-Maïto Status = STATUS_SUCCESS;
5022b299f5fSHermès Bélusca-Maïto if (hProcess)
5032b299f5fSHermès Bélusca-Maïto Status = UserpGetClientFileName(&FileNameU, hProcess);
5042b299f5fSHermès Bélusca-Maïto
5059ea2783eSHermès Bélusca-Maïto /* Close the process handle but keep its original value to know where stuff came from */
5069ea2783eSHermès Bélusca-Maïto if (hProcess) NtClose(hProcess);
5079ea2783eSHermès Bélusca-Maïto
5082b299f5fSHermès Bélusca-Maïto /*
5092b299f5fSHermès Bélusca-Maïto * Fall back to SYSTEM process if the client process handle
5102b299f5fSHermès Bélusca-Maïto * was NULL or we failed retrieving a file name.
5112b299f5fSHermès Bélusca-Maïto */
5122b299f5fSHermès Bélusca-Maïto if (!hProcess || !NT_SUCCESS(Status) || !FileNameU.Buffer)
513c2c66affSColin Finck {
5142b299f5fSHermès Bélusca-Maïto hProcess = NULL;
5155a1a35caSHermès Bélusca-Maïto FileNameU = g_SystemProcessU;
516c2c66affSColin Finck }
517c2c66affSColin Finck
51829d56f2bSHermès Bélusca-Maïto /* Retrieve the description of the error code */
51929d56f2bSHermès Bélusca-Maïto FormatA.Buffer = NULL;
520c2c66affSColin Finck Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
521c2c66affSColin Finck (ULONG_PTR)RT_MESSAGETABLE,
522c2c66affSColin Finck LANG_NEUTRAL,
523c2c66affSColin Finck Message->Status,
524c2c66affSColin Finck &MessageResource);
525c2c66affSColin Finck if (NT_SUCCESS(Status))
526c2c66affSColin Finck {
527c2c66affSColin Finck if (MessageResource->Flags)
528c2c66affSColin Finck {
529c2c66affSColin Finck RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text);
530c2c66affSColin Finck FormatA.Buffer = NULL;
531c2c66affSColin Finck }
532c2c66affSColin Finck else
533c2c66affSColin Finck {
53408d70697SHermès Bélusca-Maïto RtlInitAnsiString(&FormatA, (PSTR)MessageResource->Text);
5355a1a35caSHermès Bélusca-Maïto /* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
536c2c66affSColin Finck }
53729d56f2bSHermès Bélusca-Maïto ASSERT(FormatU.Buffer);
538c2c66affSColin Finck }
539c2c66affSColin Finck else
540c2c66affSColin Finck {
54108d70697SHermès Bélusca-Maïto /*
54229d56f2bSHermès Bélusca-Maïto * Fall back to unknown hard error format string.
54308d70697SHermès Bélusca-Maïto * NOTE: The value used here is ReactOS-specific: it allows specifying
54429d56f2bSHermès Bélusca-Maïto * the exact hard error status value and the parameters, contrary to
54575e80632SHermès Bélusca-Maïto * the one on Windows that only says: "Unknown Hard Error".
54608d70697SHermès Bélusca-Maïto */
54729d56f2bSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(&FormatU, NULL, 0);
548c2c66affSColin Finck FormatA.Buffer = NULL;
549c2c66affSColin Finck }
550c2c66affSColin Finck
551c2c66affSColin Finck FormatString = FormatU.Buffer;
552c2c66affSColin Finck
55329d56f2bSHermès Bélusca-Maïto /* Check whether a caption is specified in the format string */
55429d56f2bSHermès Bélusca-Maïto if (FormatString && FormatString[0] == L'{')
555c2c66affSColin Finck {
556c2c66affSColin Finck /* Set caption start */
557c2c66affSColin Finck TempStringU.Buffer = ++FormatString;
558c2c66affSColin Finck
55929d56f2bSHermès Bélusca-Maïto /* Get the caption size and find where the format string really starts */
56029d56f2bSHermès Bélusca-Maïto for (TempStringU.Length = 0;
56129d56f2bSHermès Bélusca-Maïto *FormatString != UNICODE_NULL && *FormatString != L'}';
56229d56f2bSHermès Bélusca-Maïto ++TempStringU.Length)
56329d56f2bSHermès Bélusca-Maïto {
56429d56f2bSHermès Bélusca-Maïto ++FormatString;
56529d56f2bSHermès Bélusca-Maïto }
566c2c66affSColin Finck
567c2c66affSColin Finck /* Skip '}', '\r', '\n' */
568c2c66affSColin Finck FormatString += 3;
569c2c66affSColin Finck
57029d56f2bSHermès Bélusca-Maïto TempStringU.Length *= sizeof(WCHAR);
571c2c66affSColin Finck TempStringU.MaximumLength = TempStringU.Length;
572c2c66affSColin Finck }
573c2c66affSColin Finck else
574c2c66affSColin Finck {
5756718a1aaSHermès Bélusca-Maïto if (Severity == STATUS_SEVERITY_SUCCESS)
5765a1a35caSHermès Bélusca-Maïto TempStringU = g_SuccessU;
5776718a1aaSHermès Bélusca-Maïto else if (Severity == STATUS_SEVERITY_INFORMATIONAL)
5785a1a35caSHermès Bélusca-Maïto TempStringU = g_InformationU;
5796718a1aaSHermès Bélusca-Maïto else if (Severity == STATUS_SEVERITY_WARNING)
5805a1a35caSHermès Bélusca-Maïto TempStringU = g_WarningU;
5816718a1aaSHermès Bélusca-Maïto else if (Severity == STATUS_SEVERITY_ERROR)
5825a1a35caSHermès Bélusca-Maïto TempStringU = g_ErrorU;
5836718a1aaSHermès Bélusca-Maïto else
5849ea2783eSHermès Bélusca-Maïto ASSERT(FALSE); // Unexpected, since Severity is only <= 3.
585c2c66affSColin Finck }
586c2c66affSColin Finck
5875a1a35caSHermès Bélusca-Maïto /* Retrieve the window title of the client, if it has one */
58875e80632SHermès Bélusca-Maïto RtlInitEmptyUnicodeString(&WindowTitleU, L"", 0);
5895a1a35caSHermès Bélusca-Maïto hwndOwner = NULL;
5905a1a35caSHermès Bélusca-Maïto EnumThreadWindows(HandleToUlong(Message->h.ClientId.UniqueThread),
5915a1a35caSHermès Bélusca-Maïto FindTopLevelWnd, (LPARAM)&hwndOwner);
5925a1a35caSHermès Bélusca-Maïto if (hwndOwner)
5935a1a35caSHermès Bélusca-Maïto {
5949ea2783eSHermès Bélusca-Maïto cszBuffer = GetWindowTextLengthW(hwndOwner);
5959ea2783eSHermès Bélusca-Maïto if (cszBuffer != 0)
5965a1a35caSHermès Bélusca-Maïto {
5979ea2783eSHermès Bélusca-Maïto cszBuffer += 3; // 2 characters for ": " and a NULL terminator.
59875e80632SHermès Bélusca-Maïto cszBuffer *= sizeof(WCHAR);
59975e80632SHermès Bélusca-Maïto pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
6005a1a35caSHermès Bélusca-Maïto HEAP_ZERO_MEMORY,
60175e80632SHermès Bélusca-Maïto cszBuffer);
60275e80632SHermès Bélusca-Maïto if (pszBuffer)
6035a1a35caSHermès Bélusca-Maïto {
60475e80632SHermès Bélusca-Maïto RtlInitEmptyUnicodeString(&WindowTitleU, pszBuffer, (USHORT)cszBuffer);
6059ea2783eSHermès Bélusca-Maïto cszBuffer = GetWindowTextW(hwndOwner,
6065a1a35caSHermès Bélusca-Maïto WindowTitleU.Buffer,
6075a1a35caSHermès Bélusca-Maïto WindowTitleU.MaximumLength / sizeof(WCHAR));
6089ea2783eSHermès Bélusca-Maïto WindowTitleU.Length = (USHORT)(cszBuffer * sizeof(WCHAR));
6095a1a35caSHermès Bélusca-Maïto RtlAppendUnicodeToString(&WindowTitleU, L": ");
6105a1a35caSHermès Bélusca-Maïto }
6115a1a35caSHermès Bélusca-Maïto }
6125a1a35caSHermès Bélusca-Maïto }
6135a1a35caSHermès Bélusca-Maïto
614c2c66affSColin Finck /* Calculate buffer length for the caption */
6159ea2783eSHermès Bélusca-Maïto cszBuffer = WindowTitleU.Length + FileNameU.Length + TempStringU.Length +
6165a1a35caSHermès Bélusca-Maïto 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
61708d70697SHermès Bélusca-Maïto if (CaptionStringU->MaximumLength < cszBuffer)
6182b299f5fSHermès Bélusca-Maïto {
6199ea2783eSHermès Bélusca-Maïto /* Allocate a larger buffer for the caption */
6209ea2783eSHermès Bélusca-Maïto pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
6219ea2783eSHermès Bélusca-Maïto HEAP_ZERO_MEMORY,
6229ea2783eSHermès Bélusca-Maïto cszBuffer);
6239ea2783eSHermès Bélusca-Maïto if (!pszBuffer)
6249ea2783eSHermès Bélusca-Maïto {
62508d70697SHermès Bélusca-Maïto /* We could not allocate a larger buffer; continue using the smaller original buffer */
62608d70697SHermès Bélusca-Maïto DPRINT1("Cannot allocate memory for CaptionStringU, use original buffer.\n");
6272b299f5fSHermès Bélusca-Maïto }
6289ea2783eSHermès Bélusca-Maïto else
6299ea2783eSHermès Bélusca-Maïto {
6309ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(CaptionStringU, pszBuffer, (USHORT)cszBuffer);
6319ea2783eSHermès Bélusca-Maïto }
6329ea2783eSHermès Bélusca-Maïto }
6339ea2783eSHermès Bélusca-Maïto CaptionStringU->Length = 0;
63429d56f2bSHermès Bélusca-Maïto CaptionStringU->Buffer[0] = UNICODE_NULL;
635c2c66affSColin Finck
63675e80632SHermès Bélusca-Maïto /* Build the caption */
6375a1a35caSHermès Bélusca-Maïto RtlStringCbPrintfW(CaptionStringU->Buffer,
6385a1a35caSHermès Bélusca-Maïto CaptionStringU->MaximumLength,
6395a1a35caSHermès Bélusca-Maïto L"%wZ%wZ - %wZ",
6405a1a35caSHermès Bélusca-Maïto &WindowTitleU, &FileNameU, &TempStringU);
6419ea2783eSHermès Bélusca-Maïto CaptionStringU->Length = (USHORT)(wcslen(CaptionStringU->Buffer) * sizeof(WCHAR));
642c2c66affSColin Finck
64329d56f2bSHermès Bélusca-Maïto /* Free the strings if needed */
6447cb411e8SHermès Bélusca-Maïto if (WindowTitleU.Buffer && (WindowTitleU.MaximumLength != 0))
6457cb411e8SHermès Bélusca-Maïto RtlFreeUnicodeString(&WindowTitleU);
6467cb411e8SHermès Bélusca-Maïto if (hProcess)
6477cb411e8SHermès Bélusca-Maïto RtlFreeUnicodeString(&FileNameU);
648c2c66affSColin Finck
64929d56f2bSHermès Bélusca-Maïto Format2A.Buffer = NULL;
65029d56f2bSHermès Bélusca-Maïto
65129d56f2bSHermès Bélusca-Maïto /* If we have an unknown hard error, skip the special cases handling */
65229d56f2bSHermès Bélusca-Maïto if (!FormatString)
65329d56f2bSHermès Bélusca-Maïto goto BuildMessage;
6546718a1aaSHermès Bélusca-Maïto
655c2c66affSColin Finck /* Check if this is an exception message */
656c2c66affSColin Finck if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
657c2c66affSColin Finck {
6589ea2783eSHermès Bélusca-Maïto ULONG ExceptionCode = CopyParameters[0];
659c2c66affSColin Finck
66029d56f2bSHermès Bélusca-Maïto /* Retrieve the description of the exception code */
661c2c66affSColin Finck Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
662c2c66affSColin Finck (ULONG_PTR)RT_MESSAGETABLE,
663c2c66affSColin Finck LANG_NEUTRAL,
664c2c66affSColin Finck ExceptionCode,
665c2c66affSColin Finck &MessageResource);
666c2c66affSColin Finck if (NT_SUCCESS(Status))
667c2c66affSColin Finck {
668c2c66affSColin Finck if (MessageResource->Flags)
669c2c66affSColin Finck {
6706718a1aaSHermès Bélusca-Maïto RtlInitUnicodeString(&Format2U, (PWSTR)MessageResource->Text);
6716718a1aaSHermès Bélusca-Maïto Format2A.Buffer = NULL;
672c2c66affSColin Finck }
673c2c66affSColin Finck else
674c2c66affSColin Finck {
67508d70697SHermès Bélusca-Maïto RtlInitAnsiString(&Format2A, (PSTR)MessageResource->Text);
6765a1a35caSHermès Bélusca-Maïto /* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
677c2c66affSColin Finck }
67829d56f2bSHermès Bélusca-Maïto ASSERT(Format2U.Buffer);
6796718a1aaSHermès Bélusca-Maïto
6802b299f5fSHermès Bélusca-Maïto /* Handle special cases */
6816718a1aaSHermès Bélusca-Maïto if (ExceptionCode == STATUS_ACCESS_VIOLATION)
6826718a1aaSHermès Bélusca-Maïto {
68329d56f2bSHermès Bélusca-Maïto /* Use a new FormatString */
6846718a1aaSHermès Bélusca-Maïto FormatString = Format2U.Buffer;
6859ea2783eSHermès Bélusca-Maïto CopyParameters[0] = CopyParameters[1];
6869ea2783eSHermès Bélusca-Maïto CopyParameters[1] = CopyParameters[3];
6879ea2783eSHermès Bélusca-Maïto if (CopyParameters[2])
6889ea2783eSHermès Bélusca-Maïto CopyParameters[2] = (ULONG_PTR)L"written";
6896718a1aaSHermès Bélusca-Maïto else
6909ea2783eSHermès Bélusca-Maïto CopyParameters[2] = (ULONG_PTR)L"read";
6916718a1aaSHermès Bélusca-Maïto }
6926718a1aaSHermès Bélusca-Maïto else if (ExceptionCode == STATUS_IN_PAGE_ERROR)
6936718a1aaSHermès Bélusca-Maïto {
69429d56f2bSHermès Bélusca-Maïto /* Use a new FormatString */
6956718a1aaSHermès Bélusca-Maïto FormatString = Format2U.Buffer;
6969ea2783eSHermès Bélusca-Maïto CopyParameters[0] = CopyParameters[1];
6979ea2783eSHermès Bélusca-Maïto CopyParameters[1] = CopyParameters[3];
6986718a1aaSHermès Bélusca-Maïto }
6996718a1aaSHermès Bélusca-Maïto else
7006718a1aaSHermès Bélusca-Maïto {
7016718a1aaSHermès Bélusca-Maïto /* Keep the existing FormatString */
7029ea2783eSHermès Bélusca-Maïto CopyParameters[2] = CopyParameters[1];
7039ea2783eSHermès Bélusca-Maïto CopyParameters[1] = CopyParameters[0];
7046718a1aaSHermès Bélusca-Maïto
7055a1a35caSHermès Bélusca-Maïto pszBuffer = Format2U.Buffer;
7065a1a35caSHermès Bélusca-Maïto if (!_wcsnicmp(pszBuffer, L"{EXCEPTION}", 11))
7076718a1aaSHermès Bélusca-Maïto {
7086718a1aaSHermès Bélusca-Maïto /*
7096718a1aaSHermès Bélusca-Maïto * This is a named exception. Skip the mark and
7106718a1aaSHermès Bélusca-Maïto * retrieve the exception name that follows it.
7116718a1aaSHermès Bélusca-Maïto */
7125a1a35caSHermès Bélusca-Maïto pszBuffer += 11;
7136718a1aaSHermès Bélusca-Maïto
7146718a1aaSHermès Bélusca-Maïto /* Skip '\r', '\n' */
7155a1a35caSHermès Bélusca-Maïto pszBuffer += 2;
7166718a1aaSHermès Bélusca-Maïto
7179ea2783eSHermès Bélusca-Maïto CopyParameters[0] = (ULONG_PTR)pszBuffer;
718c2c66affSColin Finck }
719c2c66affSColin Finck else
720c2c66affSColin Finck {
721c2c66affSColin Finck /* Fall back to hardcoded value */
7229ea2783eSHermès Bélusca-Maïto CopyParameters[0] = (ULONG_PTR)L"unknown software exception";
723c2c66affSColin Finck }
724c2c66affSColin Finck }
725c2c66affSColin Finck }
7266718a1aaSHermès Bélusca-Maïto else
7276718a1aaSHermès Bélusca-Maïto {
7286718a1aaSHermès Bélusca-Maïto /* Fall back to hardcoded value, and keep the existing FormatString */
7299ea2783eSHermès Bélusca-Maïto CopyParameters[2] = CopyParameters[1];
7309ea2783eSHermès Bélusca-Maïto CopyParameters[1] = CopyParameters[0];
7319ea2783eSHermès Bélusca-Maïto CopyParameters[0] = (ULONG_PTR)L"unknown software exception";
7326718a1aaSHermès Bélusca-Maïto }
73329d56f2bSHermès Bélusca-Maïto }
7346718a1aaSHermès Bélusca-Maïto
73529d56f2bSHermès Bélusca-Maïto BuildMessage:
73629d56f2bSHermès Bélusca-Maïto /*
73729d56f2bSHermès Bélusca-Maïto * Calculate buffer length for the text message. If FormatString
73829d56f2bSHermès Bélusca-Maïto * is NULL this means we have an unknown hard error whose format
73929d56f2bSHermès Bélusca-Maïto * string is in FormatU.
74029d56f2bSHermès Bélusca-Maïto */
74129d56f2bSHermès Bélusca-Maïto cszBuffer = 0;
74229d56f2bSHermès Bélusca-Maïto /* Wrap in SEH to protect from invalid string parameters */
74329d56f2bSHermès Bélusca-Maïto _SEH2_TRY
74429d56f2bSHermès Bélusca-Maïto {
74529d56f2bSHermès Bélusca-Maïto if (!FormatString)
74629d56f2bSHermès Bélusca-Maïto {
74729d56f2bSHermès Bélusca-Maïto /* Fall back to unknown hard error format string, and use the original parameters */
74829d56f2bSHermès Bélusca-Maïto cszBuffer = _scwprintf(pszUnknownHardError,
74929d56f2bSHermès Bélusca-Maïto Message->Status,
75029d56f2bSHermès Bélusca-Maïto Parameters[0], Parameters[1],
75129d56f2bSHermès Bélusca-Maïto Parameters[2], Parameters[3]);
75229d56f2bSHermès Bélusca-Maïto cszBuffer *= sizeof(WCHAR);
75329d56f2bSHermès Bélusca-Maïto }
75429d56f2bSHermès Bélusca-Maïto else
75529d56f2bSHermès Bélusca-Maïto {
75629d56f2bSHermès Bélusca-Maïto cszBuffer = _scwprintf(FormatString,
75729d56f2bSHermès Bélusca-Maïto CopyParameters[0], CopyParameters[1],
75829d56f2bSHermès Bélusca-Maïto CopyParameters[2], CopyParameters[3]);
75929d56f2bSHermès Bélusca-Maïto cszBuffer *= sizeof(WCHAR);
76029d56f2bSHermès Bélusca-Maïto
76129d56f2bSHermès Bélusca-Maïto /* Add a description for the dialog buttons */
76229d56f2bSHermès Bélusca-Maïto if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
76329d56f2bSHermès Bélusca-Maïto {
7646718a1aaSHermès Bélusca-Maïto if (Message->ValidResponseOptions == OptionOk ||
7656718a1aaSHermès Bélusca-Maïto Message->ValidResponseOptions == OptionOkCancel)
7666718a1aaSHermès Bélusca-Maïto {
7675a1a35caSHermès Bélusca-Maïto /* Reserve space for one newline and the OK-terminate-program string */
76829d56f2bSHermès Bélusca-Maïto cszBuffer += sizeof(WCHAR) + g_OKTerminateU.Length;
7696718a1aaSHermès Bélusca-Maïto }
7706718a1aaSHermès Bélusca-Maïto if (Message->ValidResponseOptions == OptionOkCancel)
7716718a1aaSHermès Bélusca-Maïto {
7725a1a35caSHermès Bélusca-Maïto /* Reserve space for one newline and the CANCEL-debug-program string */
77329d56f2bSHermès Bélusca-Maïto cszBuffer += sizeof(WCHAR) + g_CancelDebugU.Length;
7746718a1aaSHermès Bélusca-Maïto }
7756718a1aaSHermès Bélusca-Maïto }
77629d56f2bSHermès Bélusca-Maïto }
77729d56f2bSHermès Bélusca-Maïto }
77829d56f2bSHermès Bélusca-Maïto _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
77929d56f2bSHermès Bélusca-Maïto {
78029d56f2bSHermès Bélusca-Maïto /* An exception occurred, use a default string with the original parameters */
78129d56f2bSHermès Bélusca-Maïto cszBuffer = _scwprintf(pszExceptionHardError,
78229d56f2bSHermès Bélusca-Maïto Message->Status,
78329d56f2bSHermès Bélusca-Maïto Parameters[0], Parameters[1],
78429d56f2bSHermès Bélusca-Maïto Parameters[2], Parameters[3]);
78529d56f2bSHermès Bélusca-Maïto cszBuffer *= sizeof(WCHAR);
78629d56f2bSHermès Bélusca-Maïto }
78729d56f2bSHermès Bélusca-Maïto _SEH2_END;
788c2c66affSColin Finck
78929d56f2bSHermès Bélusca-Maïto cszBuffer += SizeOfStrings + sizeof(UNICODE_NULL);
79029d56f2bSHermès Bélusca-Maïto
79108d70697SHermès Bélusca-Maïto if (TextStringU->MaximumLength < cszBuffer)
7922b299f5fSHermès Bélusca-Maïto {
7939ea2783eSHermès Bélusca-Maïto /* Allocate a larger buffer for the text message */
7949ea2783eSHermès Bélusca-Maïto pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
7959ea2783eSHermès Bélusca-Maïto HEAP_ZERO_MEMORY,
7969ea2783eSHermès Bélusca-Maïto cszBuffer);
7979ea2783eSHermès Bélusca-Maïto if (!pszBuffer)
7989ea2783eSHermès Bélusca-Maïto {
79908d70697SHermès Bélusca-Maïto /* We could not allocate a larger buffer; continue using the smaller original buffer */
80008d70697SHermès Bélusca-Maïto DPRINT1("Cannot allocate memory for TextStringU, use original buffer.\n");
8012b299f5fSHermès Bélusca-Maïto }
8029ea2783eSHermès Bélusca-Maïto else
8039ea2783eSHermès Bélusca-Maïto {
8049ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(TextStringU, pszBuffer, (USHORT)cszBuffer);
8059ea2783eSHermès Bélusca-Maïto }
8069ea2783eSHermès Bélusca-Maïto }
8079ea2783eSHermès Bélusca-Maïto TextStringU->Length = 0;
80829d56f2bSHermès Bélusca-Maïto TextStringU->Buffer[0] = UNICODE_NULL;
8095a1a35caSHermès Bélusca-Maïto
810c2c66affSColin Finck /* Wrap in SEH to protect from invalid string parameters */
811c2c66affSColin Finck _SEH2_TRY
812c2c66affSColin Finck {
813c2c66affSColin Finck /* Print the string into the buffer */
8145a1a35caSHermès Bélusca-Maïto pszBuffer = TextStringU->Buffer;
8159ea2783eSHermès Bélusca-Maïto cszBuffer = TextStringU->MaximumLength;
81629d56f2bSHermès Bélusca-Maïto
81729d56f2bSHermès Bélusca-Maïto if (!FormatString)
81829d56f2bSHermès Bélusca-Maïto {
81929d56f2bSHermès Bélusca-Maïto /* Fall back to unknown hard error format string, and use the original parameters */
82029d56f2bSHermès Bélusca-Maïto RtlStringCbPrintfW(pszBuffer, cszBuffer,
82129d56f2bSHermès Bélusca-Maïto pszUnknownHardError,
82229d56f2bSHermès Bélusca-Maïto Message->Status,
82329d56f2bSHermès Bélusca-Maïto Parameters[0], Parameters[1],
82429d56f2bSHermès Bélusca-Maïto Parameters[2], Parameters[3]);
82529d56f2bSHermès Bélusca-Maïto }
82629d56f2bSHermès Bélusca-Maïto else
82729d56f2bSHermès Bélusca-Maïto {
8289ea2783eSHermès Bélusca-Maïto RtlStringCbPrintfExW(pszBuffer, cszBuffer,
8299ea2783eSHermès Bélusca-Maïto &pszBuffer, &cszBuffer,
83029d56f2bSHermès Bélusca-Maïto 0,
831c2c66affSColin Finck FormatString,
8329ea2783eSHermès Bélusca-Maïto CopyParameters[0], CopyParameters[1],
8339ea2783eSHermès Bélusca-Maïto CopyParameters[2], CopyParameters[3]);
8346718a1aaSHermès Bélusca-Maïto
83529d56f2bSHermès Bélusca-Maïto /* Add a description for the dialog buttons */
8366718a1aaSHermès Bélusca-Maïto if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
8376718a1aaSHermès Bélusca-Maïto {
8386718a1aaSHermès Bélusca-Maïto if (Message->ValidResponseOptions == OptionOk ||
8396718a1aaSHermès Bélusca-Maïto Message->ValidResponseOptions == OptionOkCancel)
8406718a1aaSHermès Bélusca-Maïto {
8419ea2783eSHermès Bélusca-Maïto RtlStringCbPrintfExW(pszBuffer, cszBuffer,
8429ea2783eSHermès Bélusca-Maïto &pszBuffer, &cszBuffer,
84329d56f2bSHermès Bélusca-Maïto 0,
8445a1a35caSHermès Bélusca-Maïto L"\n%wZ",
8455a1a35caSHermès Bélusca-Maïto &g_OKTerminateU);
8466718a1aaSHermès Bélusca-Maïto }
8476718a1aaSHermès Bélusca-Maïto if (Message->ValidResponseOptions == OptionOkCancel)
8486718a1aaSHermès Bélusca-Maïto {
8499ea2783eSHermès Bélusca-Maïto RtlStringCbPrintfExW(pszBuffer, cszBuffer,
8509ea2783eSHermès Bélusca-Maïto &pszBuffer, &cszBuffer,
85129d56f2bSHermès Bélusca-Maïto 0,
8525a1a35caSHermès Bélusca-Maïto L"\n%wZ",
8535a1a35caSHermès Bélusca-Maïto &g_CancelDebugU);
8546718a1aaSHermès Bélusca-Maïto }
8556718a1aaSHermès Bélusca-Maïto }
856c2c66affSColin Finck }
85729d56f2bSHermès Bélusca-Maïto }
858c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
859c2c66affSColin Finck {
8609ea2783eSHermès Bélusca-Maïto /* An exception occurred, use a default string with the original parameters */
8615a1a35caSHermès Bélusca-Maïto DPRINT1("Exception 0x%08lx occurred while building hard-error message, fall back to default message.\n",
8625a1a35caSHermès Bélusca-Maïto _SEH2_GetExceptionCode());
8635a1a35caSHermès Bélusca-Maïto
8646718a1aaSHermès Bélusca-Maïto RtlStringCbPrintfW(TextStringU->Buffer,
8656718a1aaSHermès Bélusca-Maïto TextStringU->MaximumLength,
86629d56f2bSHermès Bélusca-Maïto pszExceptionHardError,
8676718a1aaSHermès Bélusca-Maïto Message->Status,
8689ea2783eSHermès Bélusca-Maïto Parameters[0], Parameters[1],
8699ea2783eSHermès Bélusca-Maïto Parameters[2], Parameters[3]);
870c2c66affSColin Finck }
8716718a1aaSHermès Bélusca-Maïto _SEH2_END;
872c2c66affSColin Finck
8739ea2783eSHermès Bélusca-Maïto TextStringU->Length = (USHORT)(wcslen(TextStringU->Buffer) * sizeof(WCHAR));
874c2c66affSColin Finck
87529d56f2bSHermès Bélusca-Maïto /* Free the converted UNICODE strings */
8766718a1aaSHermès Bélusca-Maïto if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
877c2c66affSColin Finck if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
878c2c66affSColin Finck
87908d70697SHermès Bélusca-Maïto Quit:
88029d56f2bSHermès Bélusca-Maïto /* Free the captured parameters */
8819ea2783eSHermès Bélusca-Maïto UserpFreeStringParameters(Parameters, Message);
882c2c66affSColin Finck }
883c2c66affSColin Finck
8842b299f5fSHermès Bélusca-Maïto static ULONG
GetRegInt(IN PCWSTR KeyName,IN PCWSTR ValueName,IN ULONG DefaultValue)8852b299f5fSHermès Bélusca-Maïto GetRegInt(
8862b299f5fSHermès Bélusca-Maïto IN PCWSTR KeyName,
8872b299f5fSHermès Bélusca-Maïto IN PCWSTR ValueName,
8882b299f5fSHermès Bélusca-Maïto IN ULONG DefaultValue)
8892b299f5fSHermès Bélusca-Maïto {
8902b299f5fSHermès Bélusca-Maïto NTSTATUS Status;
8912b299f5fSHermès Bélusca-Maïto ULONG Value = DefaultValue;
8922b299f5fSHermès Bélusca-Maïto UNICODE_STRING String;
8932b299f5fSHermès Bélusca-Maïto OBJECT_ATTRIBUTES ObjectAttributes;
8942b299f5fSHermès Bélusca-Maïto HANDLE KeyHandle;
8952b299f5fSHermès Bélusca-Maïto ULONG ResultLength;
8962b299f5fSHermès Bélusca-Maïto UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
8972b299f5fSHermès Bélusca-Maïto PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
8982b299f5fSHermès Bélusca-Maïto
8992b299f5fSHermès Bélusca-Maïto RtlInitUnicodeString(&String, KeyName);
9002b299f5fSHermès Bélusca-Maïto InitializeObjectAttributes(&ObjectAttributes,
9012b299f5fSHermès Bélusca-Maïto &String,
9022b299f5fSHermès Bélusca-Maïto OBJ_CASE_INSENSITIVE,
9032b299f5fSHermès Bélusca-Maïto NULL,
9042b299f5fSHermès Bélusca-Maïto NULL);
9052b299f5fSHermès Bélusca-Maïto
9062b299f5fSHermès Bélusca-Maïto /* Open the registry key */
9072b299f5fSHermès Bélusca-Maïto Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
9082b299f5fSHermès Bélusca-Maïto if (NT_SUCCESS(Status))
9092b299f5fSHermès Bélusca-Maïto {
9102b299f5fSHermès Bélusca-Maïto /* Query the value */
9112b299f5fSHermès Bélusca-Maïto RtlInitUnicodeString(&String, ValueName);
9122b299f5fSHermès Bélusca-Maïto Status = NtQueryValueKey(KeyHandle,
9132b299f5fSHermès Bélusca-Maïto &String,
9142b299f5fSHermès Bélusca-Maïto KeyValuePartialInformation,
9152b299f5fSHermès Bélusca-Maïto ValueInfo,
9162b299f5fSHermès Bélusca-Maïto sizeof(ValueBuffer),
9172b299f5fSHermès Bélusca-Maïto &ResultLength);
9182b299f5fSHermès Bélusca-Maïto
9192b299f5fSHermès Bélusca-Maïto /* Close the registry key */
9202b299f5fSHermès Bélusca-Maïto NtClose(KeyHandle);
9212b299f5fSHermès Bélusca-Maïto
9222b299f5fSHermès Bélusca-Maïto if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD))
9232b299f5fSHermès Bélusca-Maïto {
9242b299f5fSHermès Bélusca-Maïto /* Directly retrieve the data */
9252b299f5fSHermès Bélusca-Maïto Value = *(PULONG)ValueInfo->Data;
9262b299f5fSHermès Bélusca-Maïto }
9272b299f5fSHermès Bélusca-Maïto }
9282b299f5fSHermès Bélusca-Maïto
9292b299f5fSHermès Bélusca-Maïto return Value;
9302b299f5fSHermès Bélusca-Maïto }
9312b299f5fSHermès Bélusca-Maïto
932ec91188fSGiannis Adamopoulos static BOOL
UserpShowInformationBalloon(IN PUNICODE_STRING TextStringU,IN PUNICODE_STRING CaptionStringU,IN UINT Type,IN PHARDERROR_MSG Message)93308d70697SHermès Bélusca-Maïto UserpShowInformationBalloon(
93429d56f2bSHermès Bélusca-Maïto IN PUNICODE_STRING TextStringU,
93529d56f2bSHermès Bélusca-Maïto IN PUNICODE_STRING CaptionStringU,
93608d70697SHermès Bélusca-Maïto IN UINT Type,
93708d70697SHermès Bélusca-Maïto IN PHARDERROR_MSG Message)
938ec91188fSGiannis Adamopoulos {
9396718a1aaSHermès Bélusca-Maïto ULONG ShellErrorMode;
94029d56f2bSHermès Bélusca-Maïto HWND hWndTaskman;
941ec91188fSGiannis Adamopoulos COPYDATASTRUCT CopyData;
942ec91188fSGiannis Adamopoulos PBALLOON_HARD_ERROR_DATA pdata;
9436718a1aaSHermès Bélusca-Maïto DWORD dwSize, cbTextLen, cbTitleLen;
944ec91188fSGiannis Adamopoulos PWCHAR pText, pCaption;
94529d56f2bSHermès Bélusca-Maïto DWORD ret;
94629d56f2bSHermès Bélusca-Maïto DWORD_PTR dwResult;
947ec91188fSGiannis Adamopoulos
9486718a1aaSHermès Bélusca-Maïto /* Query the shell error mode value */
9496718a1aaSHermès Bélusca-Maïto ShellErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
9506718a1aaSHermès Bélusca-Maïto L"ShellErrorMode", 0);
9516718a1aaSHermès Bélusca-Maïto
95229d56f2bSHermès Bélusca-Maïto /* Make the shell display the hard error message only if necessary */
9536718a1aaSHermès Bélusca-Maïto if (ShellErrorMode != 1)
9546718a1aaSHermès Bélusca-Maïto return FALSE;
9556718a1aaSHermès Bélusca-Maïto
95629d56f2bSHermès Bélusca-Maïto /* Retrieve the shell task window */
95729d56f2bSHermès Bélusca-Maïto hWndTaskman = GetTaskmanWindow();
95829d56f2bSHermès Bélusca-Maïto if (!hWndTaskman)
959ec91188fSGiannis Adamopoulos {
9606718a1aaSHermès Bélusca-Maïto DPRINT1("Failed to find shell task window (last error %lu)\n", GetLastError());
961ec91188fSGiannis Adamopoulos return FALSE;
962ec91188fSGiannis Adamopoulos }
963ec91188fSGiannis Adamopoulos
96429d56f2bSHermès Bélusca-Maïto cbTextLen = TextStringU->Length + sizeof(UNICODE_NULL);
96529d56f2bSHermès Bélusca-Maïto cbTitleLen = CaptionStringU->Length + sizeof(UNICODE_NULL);
966ec91188fSGiannis Adamopoulos
967ec91188fSGiannis Adamopoulos dwSize = sizeof(BALLOON_HARD_ERROR_DATA);
9686718a1aaSHermès Bélusca-Maïto dwSize += cbTextLen + cbTitleLen;
969ec91188fSGiannis Adamopoulos
97029d56f2bSHermès Bélusca-Maïto /* Build the data buffer */
971ec91188fSGiannis Adamopoulos pdata = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
972ec91188fSGiannis Adamopoulos if (!pdata)
973ec91188fSGiannis Adamopoulos {
9746718a1aaSHermès Bélusca-Maïto DPRINT1("Failed to allocate balloon data\n");
975ec91188fSGiannis Adamopoulos return FALSE;
976ec91188fSGiannis Adamopoulos }
977ec91188fSGiannis Adamopoulos
978ec91188fSGiannis Adamopoulos pdata->cbHeaderSize = sizeof(BALLOON_HARD_ERROR_DATA);
979ec91188fSGiannis Adamopoulos pdata->Status = Message->Status;
98008d70697SHermès Bélusca-Maïto pdata->dwType = Type;
9816718a1aaSHermès Bélusca-Maïto
982ec91188fSGiannis Adamopoulos pdata->TitleOffset = pdata->cbHeaderSize;
98329d56f2bSHermès Bélusca-Maïto pdata->MessageOffset = pdata->TitleOffset + cbTitleLen;
984ec91188fSGiannis Adamopoulos pCaption = (PWCHAR)((ULONG_PTR)pdata + pdata->TitleOffset);
985ec91188fSGiannis Adamopoulos pText = (PWCHAR)((ULONG_PTR)pdata + pdata->MessageOffset);
98629d56f2bSHermès Bélusca-Maïto RtlStringCbCopyNW(pCaption, cbTitleLen, CaptionStringU->Buffer, CaptionStringU->Length);
98729d56f2bSHermès Bélusca-Maïto RtlStringCbCopyNW(pText, cbTextLen, TextStringU->Buffer, TextStringU->Length);
988ec91188fSGiannis Adamopoulos
98929d56f2bSHermès Bélusca-Maïto /* Send the message */
99029d56f2bSHermès Bélusca-Maïto
99129d56f2bSHermès Bélusca-Maïto /* Retrieve a unique system-wide message to communicate hard error data with the shell */
992ec91188fSGiannis Adamopoulos CopyData.dwData = RegisterWindowMessageW(L"HardError");
993ec91188fSGiannis Adamopoulos CopyData.cbData = dwSize;
994ec91188fSGiannis Adamopoulos CopyData.lpData = pdata;
995ec91188fSGiannis Adamopoulos
996ec91188fSGiannis Adamopoulos dwResult = FALSE;
99729d56f2bSHermès Bélusca-Maïto ret = SendMessageTimeoutW(hWndTaskman, WM_COPYDATA, 0, (LPARAM)&CopyData,
998ec91188fSGiannis Adamopoulos SMTO_NORMAL | SMTO_ABORTIFHUNG, 3000, &dwResult);
999ec91188fSGiannis Adamopoulos
100029d56f2bSHermès Bélusca-Maïto /* Free the buffer */
1001ec91188fSGiannis Adamopoulos RtlFreeHeap(RtlGetProcessHeap(), 0, pdata);
1002ec91188fSGiannis Adamopoulos
1003ec91188fSGiannis Adamopoulos return (ret && dwResult) ? TRUE : FALSE;
1004ec91188fSGiannis Adamopoulos }
1005ec91188fSGiannis Adamopoulos
1006c2c66affSColin Finck static
100708d70697SHermès Bélusca-Maïto HARDERROR_RESPONSE
UserpMessageBox(IN PUNICODE_STRING TextStringU,IN PUNICODE_STRING CaptionStringU,IN UINT Type,IN ULONG Timeout)1008c2c66affSColin Finck UserpMessageBox(
100929d56f2bSHermès Bélusca-Maïto IN PUNICODE_STRING TextStringU,
101029d56f2bSHermès Bélusca-Maïto IN PUNICODE_STRING CaptionStringU,
101108d70697SHermès Bélusca-Maïto IN UINT Type,
10126718a1aaSHermès Bélusca-Maïto IN ULONG Timeout)
1013c2c66affSColin Finck {
101408d70697SHermès Bélusca-Maïto ULONG MessageBoxResponse;
1015c2c66affSColin Finck
101608d70697SHermès Bélusca-Maïto DPRINT("Text = '%S', Caption = '%S', Type = 0x%lx\n",
101729d56f2bSHermès Bélusca-Maïto TextStringU->Buffer, CaptionStringU->Buffer, Type);
1018c2c66affSColin Finck
1019c2c66affSColin Finck /* Display a message box */
102029d56f2bSHermès Bélusca-Maïto MessageBoxResponse = MessageBoxTimeoutW(NULL,
102129d56f2bSHermès Bélusca-Maïto TextStringU->Buffer,
102229d56f2bSHermès Bélusca-Maïto CaptionStringU->Buffer,
102329d56f2bSHermès Bélusca-Maïto Type, 0, Timeout);
1024c2c66affSColin Finck
1025c2c66affSColin Finck /* Return response value */
1026c2c66affSColin Finck switch (MessageBoxResponse)
1027c2c66affSColin Finck {
1028c2c66affSColin Finck case IDOK: return ResponseOk;
1029c2c66affSColin Finck case IDCANCEL: return ResponseCancel;
1030c2c66affSColin Finck case IDYES: return ResponseYes;
1031c2c66affSColin Finck case IDNO: return ResponseNo;
1032c2c66affSColin Finck case IDABORT: return ResponseAbort;
1033c2c66affSColin Finck case IDIGNORE: return ResponseIgnore;
1034c2c66affSColin Finck case IDRETRY: return ResponseRetry;
1035c2c66affSColin Finck case IDTRYAGAIN: return ResponseTryAgain;
1036c2c66affSColin Finck case IDCONTINUE: return ResponseContinue;
103708d70697SHermès Bélusca-Maïto default: return ResponseNotHandled;
1038c2c66affSColin Finck }
1039c2c66affSColin Finck
1040c2c66affSColin Finck return ResponseNotHandled;
1041c2c66affSColin Finck }
1042c2c66affSColin Finck
10436718a1aaSHermès Bélusca-Maïto static
10446718a1aaSHermès Bélusca-Maïto VOID
UserpLogHardError(IN PUNICODE_STRING TextStringU,IN PUNICODE_STRING CaptionStringU)10456718a1aaSHermès Bélusca-Maïto UserpLogHardError(
10466718a1aaSHermès Bélusca-Maïto IN PUNICODE_STRING TextStringU,
10476718a1aaSHermès Bélusca-Maïto IN PUNICODE_STRING CaptionStringU)
10486718a1aaSHermès Bélusca-Maïto {
10496718a1aaSHermès Bélusca-Maïto NTSTATUS Status;
10506718a1aaSHermès Bélusca-Maïto HANDLE hEventLog;
10516718a1aaSHermès Bélusca-Maïto UNICODE_STRING UNCServerNameU = {0, 0, NULL};
10526718a1aaSHermès Bélusca-Maïto UNICODE_STRING SourceNameU = RTL_CONSTANT_STRING(L"Application Popup");
10536718a1aaSHermès Bélusca-Maïto PUNICODE_STRING Strings[] = {CaptionStringU, TextStringU};
10546718a1aaSHermès Bélusca-Maïto
10556718a1aaSHermès Bélusca-Maïto Status = ElfRegisterEventSourceW(&UNCServerNameU, &SourceNameU, &hEventLog);
10566718a1aaSHermès Bélusca-Maïto if (!NT_SUCCESS(Status) || !hEventLog)
10576718a1aaSHermès Bélusca-Maïto {
10586718a1aaSHermès Bélusca-Maïto DPRINT1("ElfRegisterEventSourceW failed with Status 0x%08lx\n", Status);
10596718a1aaSHermès Bélusca-Maïto return;
10606718a1aaSHermès Bélusca-Maïto }
10616718a1aaSHermès Bélusca-Maïto
10626718a1aaSHermès Bélusca-Maïto Status = ElfReportEventW(hEventLog,
10636718a1aaSHermès Bélusca-Maïto EVENTLOG_INFORMATION_TYPE,
10646718a1aaSHermès Bélusca-Maïto 0,
10656718a1aaSHermès Bélusca-Maïto STATUS_LOG_HARD_ERROR,
10666718a1aaSHermès Bélusca-Maïto NULL, // lpUserSid
10676718a1aaSHermès Bélusca-Maïto ARRAYSIZE(Strings),
10686718a1aaSHermès Bélusca-Maïto 0, // dwDataSize
10696718a1aaSHermès Bélusca-Maïto Strings,
10706718a1aaSHermès Bélusca-Maïto NULL, // lpRawData
10716718a1aaSHermès Bélusca-Maïto 0,
10726718a1aaSHermès Bélusca-Maïto NULL,
10736718a1aaSHermès Bélusca-Maïto NULL);
10746718a1aaSHermès Bélusca-Maïto if (!NT_SUCCESS(Status))
10756718a1aaSHermès Bélusca-Maïto DPRINT1("ElfReportEventW failed with Status 0x%08lx\n", Status);
10766718a1aaSHermès Bélusca-Maïto
10776718a1aaSHermès Bélusca-Maïto ElfDeregisterEventSource(hEventLog);
10786718a1aaSHermès Bélusca-Maïto }
10796718a1aaSHermès Bélusca-Maïto
1080c2c66affSColin Finck VOID
1081c2c66affSColin Finck NTAPI
UserServerHardError(IN PCSR_THREAD ThreadData,IN PHARDERROR_MSG Message)1082c2c66affSColin Finck UserServerHardError(
1083c2c66affSColin Finck IN PCSR_THREAD ThreadData,
1084c2c66affSColin Finck IN PHARDERROR_MSG Message)
1085c2c66affSColin Finck {
10866718a1aaSHermès Bélusca-Maïto ULONG ErrorMode;
108708d70697SHermès Bélusca-Maïto UINT dwType = 0;
10882363fee5SHermès Bélusca-Maïto ULONG Timeout = INFINITE;
10899ea2783eSHermès Bélusca-Maïto UNICODE_STRING TextU, CaptionU;
10909ea2783eSHermès Bélusca-Maïto WCHAR LocalTextBuffer[256];
10919ea2783eSHermès Bélusca-Maïto WCHAR LocalCaptionBuffer[256];
1092*dad76af8SGiannis Adamopoulos NTSTATUS Status;
1093c2c66affSColin Finck
1094c2c66affSColin Finck ASSERT(ThreadData->Process != NULL);
1095c2c66affSColin Finck
1096c2c66affSColin Finck /* Default to not handled */
1097c2c66affSColin Finck Message->Response = ResponseNotHandled;
1098c2c66affSColin Finck
1099c2c66affSColin Finck /* Make sure we don't have too many parameters */
1100c2c66affSColin Finck if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
11016718a1aaSHermès Bélusca-Maïto {
110208d70697SHermès Bélusca-Maïto // NOTE: Windows just fails (STATUS_INVALID_PARAMETER) & returns ResponseNotHandled.
110308d70697SHermès Bélusca-Maïto DPRINT1("Invalid NumberOfParameters = %d\n", Message->NumberOfParameters);
1104c2c66affSColin Finck Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS;
11056718a1aaSHermès Bélusca-Maïto }
11066718a1aaSHermès Bélusca-Maïto if (Message->ValidResponseOptions > OptionCancelTryContinue)
11076718a1aaSHermès Bélusca-Maïto {
110808d70697SHermès Bélusca-Maïto DPRINT1("Unknown ValidResponseOptions = %d\n", Message->ValidResponseOptions);
110908d70697SHermès Bélusca-Maïto return; // STATUS_INVALID_PARAMETER;
11106718a1aaSHermès Bélusca-Maïto }
111108d70697SHermès Bélusca-Maïto if (Message->Status == STATUS_SERVICE_NOTIFICATION)
111208d70697SHermès Bélusca-Maïto {
111308d70697SHermès Bélusca-Maïto if (Message->NumberOfParameters < 3)
111408d70697SHermès Bélusca-Maïto {
111529d56f2bSHermès Bélusca-Maïto DPRINT1("Invalid NumberOfParameters = %d for STATUS_SERVICE_NOTIFICATION\n",
111629d56f2bSHermès Bélusca-Maïto Message->NumberOfParameters);
111708d70697SHermès Bélusca-Maïto return; // STATUS_INVALID_PARAMETER;
111808d70697SHermès Bélusca-Maïto }
111908d70697SHermès Bélusca-Maïto // (Message->UnicodeStringParameterMask & 0x3)
112008d70697SHermès Bélusca-Maïto }
1121c2c66affSColin Finck
1122*dad76af8SGiannis Adamopoulos Status = NtUserSetInformationThread(NtCurrentThread(),
1123*dad76af8SGiannis Adamopoulos UserThreadUseActiveDesktop,
1124*dad76af8SGiannis Adamopoulos NULL,
1125*dad76af8SGiannis Adamopoulos 0);
1126*dad76af8SGiannis Adamopoulos if (!NT_SUCCESS(Status))
1127*dad76af8SGiannis Adamopoulos {
1128*dad76af8SGiannis Adamopoulos DPRINT1("Failed to set thread desktop!\n");
1129*dad76af8SGiannis Adamopoulos return;
1130*dad76af8SGiannis Adamopoulos }
1131*dad76af8SGiannis Adamopoulos
11325a1a35caSHermès Bélusca-Maïto /* Re-initialize the hard errors cache */
11335a1a35caSHermès Bélusca-Maïto UserInitHardErrorsCache();
11345a1a35caSHermès Bélusca-Maïto
11352b299f5fSHermès Bélusca-Maïto /* Format the message caption and text */
11369ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(&TextU, LocalTextBuffer, sizeof(LocalTextBuffer));
11379ea2783eSHermès Bélusca-Maïto RtlInitEmptyUnicodeString(&CaptionU, LocalCaptionBuffer, sizeof(LocalCaptionBuffer));
11382363fee5SHermès Bélusca-Maïto UserpFormatMessages(&TextU, &CaptionU, &dwType, &Timeout, Message);
11396718a1aaSHermès Bélusca-Maïto
11406718a1aaSHermès Bélusca-Maïto /* Log the hard error message */
11416718a1aaSHermès Bélusca-Maïto UserpLogHardError(&TextU, &CaptionU);
11426718a1aaSHermès Bélusca-Maïto
11436718a1aaSHermès Bélusca-Maïto /* Display a hard error popup depending on the current ErrorMode */
11446718a1aaSHermès Bélusca-Maïto
11456718a1aaSHermès Bélusca-Maïto /* Query the error mode value */
11466718a1aaSHermès Bélusca-Maïto ErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
11476718a1aaSHermès Bélusca-Maïto L"ErrorMode", 0);
11486718a1aaSHermès Bélusca-Maïto
11492b299f5fSHermès Bélusca-Maïto if (Message->Status != STATUS_SERVICE_NOTIFICATION && ErrorMode != 0)
11506718a1aaSHermès Bélusca-Maïto {
11516718a1aaSHermès Bélusca-Maïto /* Returns OK for the hard error */
11526718a1aaSHermès Bélusca-Maïto Message->Response = ResponseOk;
11536718a1aaSHermès Bélusca-Maïto goto Quit;
1154c2c66affSColin Finck }
1155c2c66affSColin Finck
1156ec91188fSGiannis Adamopoulos if (Message->ValidResponseOptions == OptionOkNoWait)
1157ec91188fSGiannis Adamopoulos {
1158ec91188fSGiannis Adamopoulos /* Display the balloon */
11596718a1aaSHermès Bélusca-Maïto Message->Response = ResponseOk;
116029d56f2bSHermès Bélusca-Maïto if (UserpShowInformationBalloon(&TextU,
116129d56f2bSHermès Bélusca-Maïto &CaptionU,
116208d70697SHermès Bélusca-Maïto dwType,
1163ec91188fSGiannis Adamopoulos Message))
1164ec91188fSGiannis Adamopoulos {
1165ec91188fSGiannis Adamopoulos Message->Response = ResponseOk;
11666718a1aaSHermès Bélusca-Maïto goto Quit;
1167ec91188fSGiannis Adamopoulos }
1168ec91188fSGiannis Adamopoulos }
1169ec91188fSGiannis Adamopoulos
1170c2c66affSColin Finck /* Display the message box */
117129d56f2bSHermès Bélusca-Maïto Message->Response = UserpMessageBox(&TextU,
117229d56f2bSHermès Bélusca-Maïto &CaptionU,
117308d70697SHermès Bélusca-Maïto dwType,
11742363fee5SHermès Bélusca-Maïto Timeout);
1175c2c66affSColin Finck
11766718a1aaSHermès Bélusca-Maïto Quit:
11779ea2783eSHermès Bélusca-Maïto /* Free the strings if they have been reallocated */
11789ea2783eSHermès Bélusca-Maïto if (TextU.Buffer != LocalTextBuffer)
1179c2c66affSColin Finck RtlFreeUnicodeString(&TextU);
11809ea2783eSHermès Bélusca-Maïto if (CaptionU.Buffer != LocalCaptionBuffer)
1181c2c66affSColin Finck RtlFreeUnicodeString(&CaptionU);
11826718a1aaSHermès Bélusca-Maïto
1183*dad76af8SGiannis Adamopoulos NtUserSetInformationThread(NtCurrentThread(), UserThreadRestoreDesktop, NULL, 0);
1184*dad76af8SGiannis Adamopoulos
1185c2c66affSColin Finck return;
1186c2c66affSColin Finck }
1187c2c66affSColin Finck
11885a1a35caSHermès Bélusca-Maïto VOID
UserInitHardErrorsCache(VOID)11895a1a35caSHermès Bélusca-Maïto UserInitHardErrorsCache(VOID)
11905a1a35caSHermès Bélusca-Maïto {
11915a1a35caSHermès Bélusca-Maïto NTSTATUS Status;
11925a1a35caSHermès Bélusca-Maïto LCID CurrentUserLCID = 0;
11935a1a35caSHermès Bélusca-Maïto
11945a1a35caSHermès Bélusca-Maïto Status = NtQueryDefaultLocale(TRUE, &CurrentUserLCID);
11955a1a35caSHermès Bélusca-Maïto if (!NT_SUCCESS(Status) || CurrentUserLCID == 0)
11965a1a35caSHermès Bélusca-Maïto {
11975a1a35caSHermès Bélusca-Maïto /* Fall back to english locale */
11985a1a35caSHermès Bélusca-Maïto DPRINT1("NtQueryDefaultLocale failed with Status = 0x%08lx\n", Status);
11995a1a35caSHermès Bélusca-Maïto // LOCALE_SYSTEM_DEFAULT;
12005a1a35caSHermès Bélusca-Maïto CurrentUserLCID = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
12015a1a35caSHermès Bélusca-Maïto }
12025a1a35caSHermès Bélusca-Maïto if (g_CurrentUserLangId == LANGIDFROMLCID(CurrentUserLCID))
12035a1a35caSHermès Bélusca-Maïto {
12045a1a35caSHermès Bélusca-Maïto /* The current lang ID and the hard error strings have already been cached */
12055a1a35caSHermès Bélusca-Maïto return;
12065a1a35caSHermès Bélusca-Maïto }
12075a1a35caSHermès Bélusca-Maïto
12085a1a35caSHermès Bélusca-Maïto /* Load the strings using the current system locale */
12095a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_SUCCESS,
12105a1a35caSHermès Bélusca-Maïto &g_SuccessU, L"Success");
12115a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_INFORMATIONAL,
12125a1a35caSHermès Bélusca-Maïto &g_InformationU, L"System Information");
12135a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_WARNING,
12145a1a35caSHermès Bélusca-Maïto &g_WarningU, L"System Warning");
12155a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_ERROR,
12165a1a35caSHermès Bélusca-Maïto &g_ErrorU, L"System Error");
12175a1a35caSHermès Bélusca-Maïto // "unknown software exception"
12185a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_SYSTEM_PROCESS,
12195a1a35caSHermès Bélusca-Maïto &g_SystemProcessU, L"System Process");
12205a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_OK_TERMINATE_PROGRAM,
12215a1a35caSHermès Bélusca-Maïto &g_OKTerminateU, L"Click on OK to terminate the program.");
12225a1a35caSHermès Bélusca-Maïto RtlLoadUnicodeString(UserServerDllInstance, IDS_CANCEL_DEBUG_PROGRAM,
12235a1a35caSHermès Bélusca-Maïto &g_CancelDebugU, L"Click on CANCEL to debug the program.");
12245a1a35caSHermès Bélusca-Maïto
12255a1a35caSHermès Bélusca-Maïto /* Remember that we cached the hard error strings */
12265a1a35caSHermès Bélusca-Maïto g_CurrentUserLangId = LANGIDFROMLCID(CurrentUserLCID);
12275a1a35caSHermès Bélusca-Maïto }
12285a1a35caSHermès Bélusca-Maïto
1229c2c66affSColin Finck /* EOF */
1230