2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: subsys/csrss/win32csr/dllmain.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Dmitry Philippov (shedon@mail.ru)
7 * Timo Kreuzer (timo.kreuzer@reactos.org)
10 /* INCLUDES ******************************************************************/
20 /* FUNCTIONS *****************************************************************/
24 CsrpGetClientFileName(
25 OUT PUNICODE_STRING ClientFileNameU
,
28 PLIST_ENTRY ModuleListHead
;
30 PLDR_DATA_TABLE_ENTRY Module
;
32 PROCESS_BASIC_INFORMATION ClientBasicInfo
;
33 LDR_DATA_TABLE_ENTRY ModuleData
;
38 /* Initialize string */
39 ClientFileNameU
->MaximumLength
= 0;
40 ClientFileNameU
->Length
= 0;
41 ClientFileNameU
->Buffer
= NULL
;
43 /* Query process information */
44 Status
= NtQueryInformationProcess(hProcess
,
45 ProcessBasicInformation
,
47 sizeof(ClientBasicInfo
),
49 if (!NT_SUCCESS(Status
)) return Status
;
51 Peb
= ClientBasicInfo
.PebBaseAddress
;
52 if (!Peb
) return STATUS_UNSUCCESSFUL
;
54 Status
= NtReadVirtualMemory(hProcess
, &Peb
->Ldr
, &Ldr
, sizeof(Ldr
), NULL
);
55 if (!NT_SUCCESS(Status
)) return Status
;
57 ModuleListHead
= &Ldr
->InLoadOrderModuleList
;
58 Status
= NtReadVirtualMemory(hProcess
,
59 &ModuleListHead
->Flink
,
63 if (!NT_SUCCESS(Status
)) return Status
;
65 if (Entry
== ModuleListHead
) return STATUS_UNSUCCESSFUL
;
67 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
69 Status
= NtReadVirtualMemory(hProcess
,
74 if (!NT_SUCCESS(Status
)) return Status
;
76 Status
= NtReadVirtualMemory(hProcess
,
77 &Peb
->ImageBaseAddress
,
79 sizeof(ClientDllBase
),
81 if (!NT_SUCCESS(Status
)) return Status
;
83 if (ClientDllBase
!= ModuleData
.DllBase
) return STATUS_UNSUCCESSFUL
;
85 ClientFileNameU
->MaximumLength
= ModuleData
.BaseDllName
.MaximumLength
;
86 ClientFileNameU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
88 ClientFileNameU
->MaximumLength
);
90 Status
= NtReadVirtualMemory(hProcess
,
91 ModuleData
.BaseDllName
.Buffer
,
92 ClientFileNameU
->Buffer
,
93 ClientFileNameU
->MaximumLength
,
95 if (!NT_SUCCESS(Status
))
97 RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU
->Buffer
);
98 ClientFileNameU
->Buffer
= NULL
;
99 ClientFileNameU
->MaximumLength
= 0;
103 ClientFileNameU
->Length
= wcslen(ClientFileNameU
->Buffer
)*sizeof(wchar_t);
104 DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU
);
106 return STATUS_SUCCESS
;
111 CsrpFreeStringParameters(
112 IN OUT PULONG_PTR Parameters
,
113 IN PHARDERROR_MSG HardErrorMessage
)
117 /* Loop all parameters */
118 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
120 /* Check if the current parameter is a string */
121 if (HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
) && Parameters
[nParam
])
123 /* Free the string buffer */
124 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID
)Parameters
[nParam
]);
131 CsrpCaptureStringParameters(
132 OUT PULONG_PTR Parameters
,
133 OUT PULONG SizeOfAllUnicodeStrings
,
134 IN PHARDERROR_MSG HardErrorMessage
,
137 ULONG nParam
, Size
= 0;
138 NTSTATUS Status
= STATUS_SUCCESS
;
139 UNICODE_STRING TempStringU
, ParamStringU
;
140 ANSI_STRING TempStringA
;
142 /* Read all strings from client space */
143 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
145 Parameters
[nParam
] = 0;
147 /* Check if the current parameter is a unicode string */
148 if (HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
))
150 /* Read the UNICODE_STRING from the process memory */
151 Status
= NtReadVirtualMemory(hProcess
,
152 (PVOID
)HardErrorMessage
->Parameters
[nParam
],
154 sizeof(ParamStringU
),
157 if (!NT_SUCCESS(Status
))
160 /* Allocate a buffer for the string */
161 TempStringU
.MaximumLength
= ParamStringU
.Length
;
162 TempStringU
.Length
= ParamStringU
.Length
;
163 TempStringU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
165 TempStringU
.MaximumLength
);
167 if (!TempStringU
.Buffer
)
169 DPRINT1("Cannot allocate memory %u\n", TempStringU
.MaximumLength
);
170 Status
= STATUS_NO_MEMORY
;
173 /* Read the string buffer from the process memory */
174 Status
= NtReadVirtualMemory(hProcess
,
179 if (!NT_SUCCESS(Status
))
181 DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status
);
182 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
186 DPRINT("ParamString=\'%wZ\'\n", &TempStringU
);
188 /* Allocate a buffer for converted to ANSI string */
189 TempStringA
.MaximumLength
= RtlUnicodeStringToAnsiSize(&TempStringU
);
190 TempStringA
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
192 TempStringA
.MaximumLength
);
194 if (!TempStringA
.Buffer
)
196 DPRINT1("Cannot allocate memory %u\n", TempStringA
.MaximumLength
);
197 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
198 Status
= STATUS_NO_MEMORY
;
202 /* Convert string to ANSI and free temporary buffer */
203 Status
= RtlUnicodeStringToAnsiString(&TempStringA
, &TempStringU
, FALSE
);
204 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
205 if (!NT_SUCCESS(Status
))
207 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA
.Buffer
);
211 /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
212 Parameters
[nParam
] = (ULONG_PTR
)TempStringA
.Buffer
;
213 Size
+= TempStringU
.Length
;
217 /* It's not a unicode string */
218 Parameters
[nParam
] = HardErrorMessage
->Parameters
[nParam
];
222 if (!NT_SUCCESS(Status
))
224 CsrpFreeStringParameters(Parameters
, HardErrorMessage
);
228 *SizeOfAllUnicodeStrings
= Size
;
235 OUT PUNICODE_STRING TextStringU
,
236 OUT PUNICODE_STRING CaptionStringU
,
237 IN PULONG_PTR Parameters
,
238 IN ULONG SizeOfStrings
,
239 IN PHARDERROR_MSG Message
,
243 UNICODE_STRING FileNameU
, TempStringU
, FormatU
;
245 PMESSAGE_RESOURCE_ENTRY MessageResource
;
247 ULONG Size
, ExceptionCode
;
249 /* Get the file name of the client process */
250 CsrpGetClientFileName(&FileNameU
, hProcess
);
252 /* Check if we have a file name */
253 if (!FileNameU
.Buffer
)
256 RtlInitUnicodeString(&FileNameU
, L
"System");
259 /* Get text string of the error code */
260 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
261 (ULONG_PTR
)RT_MESSAGETABLE
,
266 if (NT_SUCCESS(Status
))
268 if (MessageResource
->Flags
)
270 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
271 FormatA
.Buffer
= NULL
;
275 RtlInitAnsiString(&FormatA
, (PCHAR
)MessageResource
->Text
);
276 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
281 /* Fall back to hardcoded value */
282 RtlInitUnicodeString(&FormatU
, L
"Unknown Hard Error");
283 FormatA
.Buffer
= NULL
;
286 FormatString
= FormatU
.Buffer
;
288 /* Check whether a caption exists */
289 if (FormatString
[0] == L
'{')
291 /* Set caption start */
292 TempStringU
.Buffer
= ++FormatString
;
294 /* Get size of the caption */
295 for (Size
= 0; *FormatString
!= 0 && *FormatString
!= L
'}'; Size
++)
298 /* Skip '}', '\r', '\n' */
301 TempStringU
.Length
= Size
* sizeof(WCHAR
);
302 TempStringU
.MaximumLength
= TempStringU
.Length
;
306 /* FIXME: Set string based on severity */
307 RtlInitUnicodeString(&TempStringU
, L
"Application Error");
310 /* Calculate buffer length for the caption */
311 CaptionStringU
->MaximumLength
= FileNameU
.Length
+ TempStringU
.Length
+
314 /* Allocate a buffer for the caption */
315 CaptionStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
317 CaptionStringU
->MaximumLength
);
319 /* Append the file name, seperator and the caption text */
320 CaptionStringU
->Length
= 0;
321 RtlAppendUnicodeStringToString(CaptionStringU
, &FileNameU
);
322 RtlAppendUnicodeToString(CaptionStringU
, L
" - ");
323 RtlAppendUnicodeStringToString(CaptionStringU
, &TempStringU
);
325 /* Zero terminate the buffer */
326 CaptionStringU
->Buffer
[CaptionStringU
->Length
] = 0;
328 /* Free the file name buffer */
329 RtlFreeUnicodeString(&FileNameU
);
331 /* Check if this is an exception message */
332 if (Message
->Status
== STATUS_UNHANDLED_EXCEPTION
)
334 ExceptionCode
= Parameters
[0];
336 /* Handle special cases */
337 if (ExceptionCode
== STATUS_ACCESS_VIOLATION
)
339 Parameters
[0] = Parameters
[1];
340 Parameters
[1] = Parameters
[3];
341 if (Parameters
[2]) Parameters
[2] = (ULONG_PTR
)L
"written";
342 else Parameters
[2] = (ULONG_PTR
)L
"read";
343 MessageResource
= NULL
;
345 else if (ExceptionCode
== STATUS_IN_PAGE_ERROR
)
347 Parameters
[0] = Parameters
[1];
348 Parameters
[1] = Parameters
[3];
349 MessageResource
= NULL
;
353 /* Fall back to hardcoded value */
354 Parameters
[2] = Parameters
[1];
355 Parameters
[1] = Parameters
[0];
356 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
359 if (!MessageResource
)
361 /* Get text string of the exception code */
362 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
363 (ULONG_PTR
)RT_MESSAGETABLE
,
368 if (NT_SUCCESS(Status
))
370 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
372 if (MessageResource
->Flags
)
374 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
375 FormatA
.Buffer
= NULL
;
379 RtlInitAnsiString(&FormatA
, (PCHAR
)MessageResource
->Text
);
380 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
382 FormatString
= FormatU
.Buffer
;
386 /* Fall back to hardcoded value */
387 Parameters
[2] = Parameters
[1];
388 Parameters
[1] = Parameters
[0];
389 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
394 /* Calculate length of text buffer */
395 TextStringU
->MaximumLength
= FormatU
.Length
+ SizeOfStrings
+ 42 * sizeof(WCHAR
);
397 /* Allocate a buffer for the text */
398 TextStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
400 TextStringU
->MaximumLength
);
402 /* Wrap in SEH to protect from invalid string parameters */
405 /* Print the string into the buffer */
406 StringCbPrintfW(TextStringU
->Buffer
,
407 TextStringU
->MaximumLength
,
413 Status
= STATUS_SUCCESS
;
415 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
417 /* Set error and free buffers */
418 Status
= _SEH2_GetExceptionCode();
419 RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU
->Buffer
);
420 RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU
->Buffer
);
424 if (NT_SUCCESS(Status
))
426 TextStringU
->Length
= wcslen(TextStringU
->Buffer
) * sizeof(WCHAR
);
429 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
439 ULONG ValidResponseOptions
,
442 ULONG Type
, MessageBoxResponse
;
444 /* Set the message box type */
445 switch (ValidResponseOptions
)
447 case OptionAbortRetryIgnore
:
448 Type
= MB_ABORTRETRYIGNORE
;
456 case OptionRetryCancel
:
457 Type
= MB_RETRYCANCEL
;
462 case OptionYesNoCancel
:
463 Type
= MB_YESNOCANCEL
;
465 case OptionShutdownSystem
:
466 Type
= MB_RETRYCANCEL
; // FIXME???
468 /* Anything else is invalid */
470 return ResponseNotHandled
;
474 if (Severity
== STATUS_SEVERITY_INFORMATIONAL
) Type
|= MB_ICONINFORMATION
;
475 else if (Severity
== STATUS_SEVERITY_WARNING
) Type
|= MB_ICONWARNING
;
476 else if (Severity
== STATUS_SEVERITY_ERROR
) Type
|= MB_ICONERROR
;
478 Type
|= MB_SYSTEMMODAL
| MB_SETFOREGROUND
;
480 DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
481 Text
, Caption
, Severity
, Type
);
483 /* Display a message box */
484 MessageBoxResponse
= MessageBoxW(0, Text
, Caption
, Type
);
486 /* Return response value */
487 switch (MessageBoxResponse
)
489 case IDOK
: return ResponseOk
;
490 case IDCANCEL
: return ResponseCancel
;
491 case IDYES
: return ResponseYes
;
492 case IDNO
: return ResponseNo
;
493 case IDABORT
: return ResponseAbort
;
494 case IDIGNORE
: return ResponseIgnore
;
495 case IDRETRY
: return ResponseRetry
;
496 case IDTRYAGAIN
: return ResponseTryAgain
;
497 case IDCONTINUE
: return ResponseContinue
;
500 return ResponseNotHandled
;
506 IN PCSRSS_PROCESS_DATA ProcessData
,
507 IN PHARDERROR_MSG Message
)
509 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
];
510 OBJECT_ATTRIBUTES ObjectAttributes
;
511 UNICODE_STRING TextU
, CaptionU
;
516 /* Default to not handled */
517 Message
->Response
= ResponseNotHandled
;
519 /* Make sure we don't have too many parameters */
520 if (Message
->NumberOfParameters
> MAXIMUM_HARDERROR_PARAMETERS
)
521 Message
->NumberOfParameters
= MAXIMUM_HARDERROR_PARAMETERS
;
523 /* Initialize object attributes */
524 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
526 /* Open client process */
527 Status
= NtOpenProcess(&hProcess
,
528 PROCESS_VM_READ
| PROCESS_QUERY_INFORMATION
,
530 &Message
->h
.ClientId
);
532 if (!NT_SUCCESS(Status
))
534 DPRINT1("NtOpenProcess failed with code: %lx\n", Status
);
538 /* Capture all string parameters from the process memory */
539 Status
= CsrpCaptureStringParameters(Parameters
, &Size
, Message
, hProcess
);
540 if (!NT_SUCCESS(Status
))
546 /* Format the caption and message box text */
547 Status
= CsrpFormatMessages(&TextU
,
555 CsrpFreeStringParameters(Parameters
, Message
);
558 if (!NT_SUCCESS(Status
))
563 /* Display the message box */
564 Message
->Response
= CsrpMessageBox(TextU
.Buffer
,
566 Message
->ValidResponseOptions
,
567 (ULONG
)Message
->Status
>> 30);
569 RtlFreeUnicodeString(&TextU
);
570 RtlFreeUnicodeString(&CaptionU
);