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 ******************************************************************/
22 /* FUNCTIONS *****************************************************************/
26 CsrpGetClientFileName(
27 OUT PUNICODE_STRING ClientFileNameU
,
30 PLIST_ENTRY ModuleListHead
;
32 PLDR_DATA_TABLE_ENTRY Module
;
34 PROCESS_BASIC_INFORMATION ClientBasicInfo
;
35 LDR_DATA_TABLE_ENTRY ModuleData
;
40 /* Initialize string */
41 ClientFileNameU
->MaximumLength
= 0;
42 ClientFileNameU
->Length
= 0;
43 ClientFileNameU
->Buffer
= NULL
;
45 /* Query process information */
46 Status
= NtQueryInformationProcess(hProcess
,
47 ProcessBasicInformation
,
49 sizeof(ClientBasicInfo
),
51 if (!NT_SUCCESS(Status
)) return Status
;
53 Peb
= ClientBasicInfo
.PebBaseAddress
;
54 if (!Peb
) return STATUS_UNSUCCESSFUL
;
56 Status
= NtReadVirtualMemory(hProcess
, &Peb
->Ldr
, &Ldr
, sizeof(Ldr
), NULL
);
57 if (!NT_SUCCESS(Status
)) return Status
;
59 ModuleListHead
= &Ldr
->InLoadOrderModuleList
;
60 Status
= NtReadVirtualMemory(hProcess
,
61 &ModuleListHead
->Flink
,
65 if (!NT_SUCCESS(Status
)) return Status
;
67 if (Entry
== ModuleListHead
) return STATUS_UNSUCCESSFUL
;
69 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
71 Status
= NtReadVirtualMemory(hProcess
,
76 if (!NT_SUCCESS(Status
)) return Status
;
78 Status
= NtReadVirtualMemory(hProcess
,
79 &Peb
->ImageBaseAddress
,
81 sizeof(ClientDllBase
),
83 if (!NT_SUCCESS(Status
)) return Status
;
85 if (ClientDllBase
!= ModuleData
.DllBase
) return STATUS_UNSUCCESSFUL
;
87 ClientFileNameU
->MaximumLength
= ModuleData
.BaseDllName
.MaximumLength
;
88 ClientFileNameU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
90 ClientFileNameU
->MaximumLength
);
92 Status
= NtReadVirtualMemory(hProcess
,
93 ModuleData
.BaseDllName
.Buffer
,
94 ClientFileNameU
->Buffer
,
95 ClientFileNameU
->MaximumLength
,
97 if (!NT_SUCCESS(Status
))
99 RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU
->Buffer
);
100 ClientFileNameU
->Buffer
= NULL
;
101 ClientFileNameU
->MaximumLength
= 0;
105 ClientFileNameU
->Length
= wcslen(ClientFileNameU
->Buffer
)*sizeof(wchar_t);
106 DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU
);
108 return STATUS_SUCCESS
;
113 CsrpFreeStringParameters(
114 IN OUT PULONG_PTR Parameters
,
115 IN PHARDERROR_MSG HardErrorMessage
)
119 /* Loop all parameters */
120 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
122 /* Check if the current parameter is a string */
123 if (HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
) && Parameters
[nParam
])
125 /* Free the string buffer */
126 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID
)Parameters
[nParam
]);
133 CsrpCaptureStringParameters(
134 OUT PULONG_PTR Parameters
,
135 OUT PULONG SizeOfAllUnicodeStrings
,
136 IN PHARDERROR_MSG HardErrorMessage
,
139 ULONG nParam
, Size
= 0;
140 NTSTATUS Status
= STATUS_SUCCESS
;
141 UNICODE_STRING TempStringU
, ParamStringU
;
142 ANSI_STRING TempStringA
;
144 /* Read all strings from client space */
145 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
147 Parameters
[nParam
] = 0;
149 /* Check if the current parameter is a unicode string */
150 if (HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
))
152 /* Read the UNICODE_STRING from the process memory */
153 Status
= NtReadVirtualMemory(hProcess
,
154 (PVOID
)HardErrorMessage
->Parameters
[nParam
],
156 sizeof(ParamStringU
),
159 if (!NT_SUCCESS(Status
))
162 /* Allocate a buffer for the string */
163 TempStringU
.MaximumLength
= ParamStringU
.Length
;
164 TempStringU
.Length
= ParamStringU
.Length
;
165 TempStringU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
167 TempStringU
.MaximumLength
);
169 if (!TempStringU
.Buffer
)
171 DPRINT1("Cannot allocate memory %u\n", TempStringU
.MaximumLength
);
172 Status
= STATUS_NO_MEMORY
;
175 /* Read the string buffer from the process memory */
176 Status
= NtReadVirtualMemory(hProcess
,
181 if (!NT_SUCCESS(Status
))
183 DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status
);
184 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
188 DPRINT("ParamString=\'%wZ\'\n", &TempStringU
);
190 /* Allocate a buffer for converted to ANSI string */
191 TempStringA
.MaximumLength
= RtlUnicodeStringToAnsiSize(&TempStringU
);
192 TempStringA
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
194 TempStringA
.MaximumLength
);
196 if (!TempStringA
.Buffer
)
198 DPRINT1("Cannot allocate memory %u\n", TempStringA
.MaximumLength
);
199 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
200 Status
= STATUS_NO_MEMORY
;
204 /* Convert string to ANSI and free temporary buffer */
205 Status
= RtlUnicodeStringToAnsiString(&TempStringA
, &TempStringU
, FALSE
);
206 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
207 if (!NT_SUCCESS(Status
))
209 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA
.Buffer
);
213 /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
214 Parameters
[nParam
] = (ULONG_PTR
)TempStringA
.Buffer
;
215 Size
+= TempStringU
.Length
;
219 /* It's not a unicode string */
220 Parameters
[nParam
] = HardErrorMessage
->Parameters
[nParam
];
224 if (!NT_SUCCESS(Status
))
226 CsrpFreeStringParameters(Parameters
, HardErrorMessage
);
230 *SizeOfAllUnicodeStrings
= Size
;
237 OUT PUNICODE_STRING TextStringU
,
238 OUT PUNICODE_STRING CaptionStringU
,
239 IN PULONG_PTR Parameters
,
240 IN ULONG SizeOfStrings
,
241 IN PHARDERROR_MSG Message
,
245 UNICODE_STRING FileNameU
, TempStringU
, FormatU
;
247 PMESSAGE_RESOURCE_ENTRY MessageResource
;
249 ULONG Size
, ExceptionCode
;
251 /* Get the file name of the client process */
252 CsrpGetClientFileName(&FileNameU
, hProcess
);
254 /* Check if we have a file name */
255 if (!FileNameU
.Buffer
)
258 RtlInitUnicodeString(&FileNameU
, L
"System");
261 /* Get text string of the error code */
262 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
263 (ULONG_PTR
)RT_MESSAGETABLE
,
268 if (NT_SUCCESS(Status
))
270 if (MessageResource
->Flags
)
272 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
273 FormatA
.Buffer
= NULL
;
277 RtlInitAnsiString(&FormatA
, (PCHAR
)MessageResource
->Text
);
278 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
283 /* Fall back to hardcoded value */
284 RtlInitUnicodeString(&FormatU
, L
"Unknown Hard Error");
285 FormatA
.Buffer
= NULL
;
288 FormatString
= FormatU
.Buffer
;
290 /* Check whether a caption exists */
291 if (FormatString
[0] == L
'{')
293 /* Set caption start */
294 TempStringU
.Buffer
= ++FormatString
;
296 /* Get size of the caption */
297 for (Size
= 0; *FormatString
!= 0 && *FormatString
!= L
'}'; Size
++)
300 /* Skip '}', '\r', '\n' */
303 TempStringU
.Length
= Size
* sizeof(WCHAR
);
304 TempStringU
.MaximumLength
= TempStringU
.Length
;
308 /* FIXME: Set string based on severity */
309 RtlInitUnicodeString(&TempStringU
, L
"Application Error");
312 /* Calculate buffer length for the caption */
313 CaptionStringU
->MaximumLength
= FileNameU
.Length
+ TempStringU
.Length
+
316 /* Allocate a buffer for the caption */
317 CaptionStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
319 CaptionStringU
->MaximumLength
);
321 /* Append the file name, seperator and the caption text */
322 CaptionStringU
->Length
= 0;
323 RtlAppendUnicodeStringToString(CaptionStringU
, &FileNameU
);
324 RtlAppendUnicodeToString(CaptionStringU
, L
" - ");
325 RtlAppendUnicodeStringToString(CaptionStringU
, &TempStringU
);
327 /* Zero terminate the buffer */
328 CaptionStringU
->Buffer
[CaptionStringU
->Length
/ sizeof(WCHAR
)] = 0;
330 /* Free the file name buffer */
331 RtlFreeUnicodeString(&FileNameU
);
333 /* Check if this is an exception message */
334 if (Message
->Status
== STATUS_UNHANDLED_EXCEPTION
)
336 ExceptionCode
= Parameters
[0];
338 /* Handle special cases */
339 if (ExceptionCode
== STATUS_ACCESS_VIOLATION
)
341 Parameters
[0] = Parameters
[1];
342 Parameters
[1] = Parameters
[3];
343 if (Parameters
[2]) Parameters
[2] = (ULONG_PTR
)L
"written";
344 else Parameters
[2] = (ULONG_PTR
)L
"read";
345 MessageResource
= NULL
;
347 else if (ExceptionCode
== STATUS_IN_PAGE_ERROR
)
349 Parameters
[0] = Parameters
[1];
350 Parameters
[1] = Parameters
[3];
351 MessageResource
= NULL
;
355 /* Fall back to hardcoded value */
356 Parameters
[2] = Parameters
[1];
357 Parameters
[1] = Parameters
[0];
358 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
361 if (!MessageResource
)
363 /* Get text string of the exception code */
364 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
365 (ULONG_PTR
)RT_MESSAGETABLE
,
370 if (NT_SUCCESS(Status
))
372 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
374 if (MessageResource
->Flags
)
376 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
377 FormatA
.Buffer
= NULL
;
381 RtlInitAnsiString(&FormatA
, (PCHAR
)MessageResource
->Text
);
382 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
384 FormatString
= FormatU
.Buffer
;
388 /* Fall back to hardcoded value */
389 Parameters
[2] = Parameters
[1];
390 Parameters
[1] = Parameters
[0];
391 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
396 /* Calculate length of text buffer */
397 TextStringU
->MaximumLength
= FormatU
.Length
+ SizeOfStrings
+ 42 * sizeof(WCHAR
);
399 /* Allocate a buffer for the text */
400 TextStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
402 TextStringU
->MaximumLength
);
404 /* Wrap in SEH to protect from invalid string parameters */
407 /* Print the string into the buffer */
408 StringCbPrintfW(TextStringU
->Buffer
,
409 TextStringU
->MaximumLength
,
415 Status
= STATUS_SUCCESS
;
417 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
419 /* Set error and free buffers */
420 Status
= _SEH2_GetExceptionCode();
421 RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU
->Buffer
);
422 RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU
->Buffer
);
426 if (NT_SUCCESS(Status
))
428 TextStringU
->Length
= wcslen(TextStringU
->Buffer
) * sizeof(WCHAR
);
431 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
441 ULONG ValidResponseOptions
,
444 ULONG Type
, MessageBoxResponse
;
446 /* Set the message box type */
447 switch (ValidResponseOptions
)
449 case OptionAbortRetryIgnore
:
450 Type
= MB_ABORTRETRYIGNORE
;
458 case OptionRetryCancel
:
459 Type
= MB_RETRYCANCEL
;
464 case OptionYesNoCancel
:
465 Type
= MB_YESNOCANCEL
;
467 case OptionShutdownSystem
:
468 Type
= MB_RETRYCANCEL
; // FIXME???
470 /* Anything else is invalid */
472 return ResponseNotHandled
;
476 if (Severity
== STATUS_SEVERITY_INFORMATIONAL
) Type
|= MB_ICONINFORMATION
;
477 else if (Severity
== STATUS_SEVERITY_WARNING
) Type
|= MB_ICONWARNING
;
478 else if (Severity
== STATUS_SEVERITY_ERROR
) Type
|= MB_ICONERROR
;
480 Type
|= MB_SYSTEMMODAL
| MB_SETFOREGROUND
;
482 DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
483 Text
, Caption
, Severity
, Type
);
485 /* Display a message box */
486 MessageBoxResponse
= MessageBoxW(0, Text
, Caption
, Type
);
488 /* Return response value */
489 switch (MessageBoxResponse
)
491 case IDOK
: return ResponseOk
;
492 case IDCANCEL
: return ResponseCancel
;
493 case IDYES
: return ResponseYes
;
494 case IDNO
: return ResponseNo
;
495 case IDABORT
: return ResponseAbort
;
496 case IDIGNORE
: return ResponseIgnore
;
497 case IDRETRY
: return ResponseRetry
;
498 case IDTRYAGAIN
: return ResponseTryAgain
;
499 case IDCONTINUE
: return ResponseContinue
;
502 return ResponseNotHandled
;
508 IN PCSR_THREAD ThreadData
,
509 IN PHARDERROR_MSG Message
)
512 PCSR_PROCESS ProcessData
= ThreadData
->Process
;
514 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
];
515 OBJECT_ATTRIBUTES ObjectAttributes
;
516 UNICODE_STRING TextU
, CaptionU
;
521 /* Default to not handled */
522 ASSERT(ProcessData
!= NULL
);
523 Message
->Response
= ResponseNotHandled
;
525 /* Make sure we don't have too many parameters */
526 if (Message
->NumberOfParameters
> MAXIMUM_HARDERROR_PARAMETERS
)
527 Message
->NumberOfParameters
= MAXIMUM_HARDERROR_PARAMETERS
;
529 /* Initialize object attributes */
530 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
532 /* Open client process */
533 Status
= NtOpenProcess(&hProcess
,
534 PROCESS_VM_READ
| PROCESS_QUERY_INFORMATION
,
536 &Message
->h
.ClientId
);
538 if (!NT_SUCCESS(Status
))
540 DPRINT1("NtOpenProcess failed with code: %lx\n", Status
);
544 /* Capture all string parameters from the process memory */
545 Status
= CsrpCaptureStringParameters(Parameters
, &Size
, Message
, hProcess
);
546 if (!NT_SUCCESS(Status
))
552 /* Format the caption and message box text */
553 Status
= CsrpFormatMessages(&TextU
,
561 CsrpFreeStringParameters(Parameters
, Message
);
564 if (!NT_SUCCESS(Status
))
569 /* Display the message box */
570 Message
->Response
= CsrpMessageBox(TextU
.Buffer
,
572 Message
->ValidResponseOptions
,
573 (ULONG
)Message
->Status
>> 30);
575 RtlFreeUnicodeString(&TextU
);
576 RtlFreeUnicodeString(&CaptionU
);