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
;
112 CsrpCaptureStringParameters(
113 OUT PULONG_PTR Parameters
,
114 OUT PULONG SizeOfAllUnicodeStrings
,
115 IN PHARDERROR_MSG HardErrorMessage
,
118 ULONG nParam
, UnicodeStringParameterMask
, Size
= 0;
120 UNICODE_STRING TempStringU
;
123 UnicodeStringParameterMask
= HardErrorMessage
->UnicodeStringParameterMask
;
125 /* Read all strings from client space */
127 nParam
< HardErrorMessage
->NumberOfParameters
;
128 nParam
++, UnicodeStringParameterMask
>>= 1)
130 Parameters
[nParam
] = 0;
132 /* Check if the current parameter is a unicode string */
133 if (UnicodeStringParameterMask
& 0x01)
135 /* Read the UNICODE_STRING from the process memory */
136 Status
= NtReadVirtualMemory(hProcess
,
137 (PVOID
)HardErrorMessage
->Parameters
[nParam
],
142 if (!NT_SUCCESS(Status
)) return Status
;
144 /* Allocate a buffer for the string */
145 ParamString
= RtlAllocateHeap(RtlGetProcessHeap(),
147 TempStringU
.Length
+ sizeof(WCHAR
));
151 DPRINT1("Cannot allocate memory %d\n", TempStringU
.Length
);
152 return STATUS_NO_MEMORY
;
155 /* Read the string buffer from the process memory */
156 Status
= NtReadVirtualMemory(hProcess
,
161 if (!NT_SUCCESS(Status
))
163 DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status
);
164 RtlFreeHeap(RtlGetProcessHeap(), 0, ParamString
);
168 /* Zero terminate the string */
169 ParamString
[TempStringU
.Length
/ sizeof(WCHAR
)] = 0;
170 DPRINT("ParamString=\'%S\'\n", ParamString
);
172 Parameters
[nParam
] = (ULONG_PTR
)ParamString
;
173 Size
+= TempStringU
.Length
;
177 /* It's not a unicode string */
178 Parameters
[nParam
] = HardErrorMessage
->Parameters
[nParam
];
182 *SizeOfAllUnicodeStrings
= Size
;
183 return STATUS_SUCCESS
;
188 CsrpFreeStringParameters(
189 IN OUT PULONG_PTR Parameters
,
190 IN PHARDERROR_MSG HardErrorMessage
)
192 ULONG nParam
, UnicodeStringParameterMask
;
194 UnicodeStringParameterMask
= HardErrorMessage
->UnicodeStringParameterMask
;
196 /* Loop all parameters */
198 nParam
< HardErrorMessage
->NumberOfParameters
;
199 nParam
++, UnicodeStringParameterMask
>>= 1)
201 /* Check if the current parameter is a string */
202 if (UnicodeStringParameterMask
& 0x01)
204 /* Free the string buffer */
205 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID
)Parameters
[nParam
]);
214 OUT PUNICODE_STRING TextStringU
,
215 OUT PUNICODE_STRING CaptionStringU
,
216 IN PULONG_PTR Parameters
,
217 IN ULONG SizeOfStrings
,
218 IN PHARDERROR_MSG Message
,
222 UNICODE_STRING FileNameU
, TempStringU
, FormatU
;
224 PRTL_MESSAGE_RESOURCE_ENTRY MessageResource
;
226 ULONG Size
, ExceptionCode
;
228 /* Get the file name of the client process */
229 CsrpGetClientFileName(&FileNameU
, hProcess
);
231 /* Check if we have a file name */
232 if (!FileNameU
.Buffer
)
235 RtlInitUnicodeString(&FileNameU
, L
"System");
238 /* Get text string of the error code */
239 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
240 (ULONG_PTR
)RT_MESSAGETABLE
,
245 if (NT_SUCCESS(Status
))
247 if (MessageResource
->Flags
)
249 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
250 FormatA
.Buffer
= NULL
;
254 RtlInitAnsiString(&FormatA
, MessageResource
->Text
);
255 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
260 /* Fall back to hardcoded value */
261 RtlInitUnicodeString(&FormatU
, L
"Unknown Hard Error");
262 FormatA
.Buffer
= NULL
;
265 FormatString
= FormatU
.Buffer
;
267 /* Check whether a caption exists */
268 if (FormatString
[0] == L
'{')
270 /* Set caption start */
271 TempStringU
.Buffer
= ++FormatString
;
273 /* Get size of the caption */
274 for (Size
= 0; *FormatString
!= 0 && *FormatString
!= L
'}'; Size
++)
277 /* Skip '}', '\r', '\n' */
280 TempStringU
.Length
= Size
* sizeof(WCHAR
);
281 TempStringU
.MaximumLength
= TempStringU
.Length
;
285 /* FIXME: Set string based on severity */
286 RtlInitUnicodeString(&TempStringU
, L
"Application Error");
289 /* Calculate buffer length for the caption */
290 CaptionStringU
->MaximumLength
= FileNameU
.Length
+ TempStringU
.Length
+
293 /* Allocate a buffer for the caption */
294 CaptionStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
296 CaptionStringU
->MaximumLength
);
298 /* Append the file name, seperator and the caption text */
299 CaptionStringU
->Length
= 0;
300 RtlAppendUnicodeStringToString(CaptionStringU
, &FileNameU
);
301 RtlAppendUnicodeToString(CaptionStringU
, L
" - ");
302 RtlAppendUnicodeStringToString(CaptionStringU
, &TempStringU
);
304 /* Zero terminate the buffer */
305 CaptionStringU
->Buffer
[CaptionStringU
->Length
] = 0;
307 /* Free the file name buffer */
308 RtlFreeUnicodeString(&FileNameU
);
310 /* Check if this is an exception message */
311 if (Message
->Status
== STATUS_UNHANDLED_EXCEPTION
)
313 ExceptionCode
= Parameters
[0];
315 /* Handle special cases */
316 if (ExceptionCode
== STATUS_ACCESS_VIOLATION
)
318 Parameters
[0] = Parameters
[1];
319 Parameters
[1] = Parameters
[3];
320 if (Parameters
[2]) Parameters
[2] = (ULONG_PTR
)L
"written";
321 else Parameters
[2] = (ULONG_PTR
)L
"read";
322 MessageResource
= NULL
;
324 else if (ExceptionCode
== STATUS_IN_PAGE_ERROR
)
326 Parameters
[0] = Parameters
[1];
327 Parameters
[1] = Parameters
[3];
328 MessageResource
= NULL
;
332 /* Fall back to hardcoded value */
333 Parameters
[2] = Parameters
[1];
334 Parameters
[1] = Parameters
[0];
335 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
338 if (!MessageResource
)
340 /* Get text string of the exception code */
341 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
342 (ULONG_PTR
)RT_MESSAGETABLE
,
347 if (NT_SUCCESS(Status
))
349 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
351 if (MessageResource
->Flags
)
353 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
354 FormatA
.Buffer
= NULL
;
358 RtlInitAnsiString(&FormatA
, MessageResource
->Text
);
359 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
361 FormatString
= FormatU
.Buffer
;
365 /* Fall back to hardcoded value */
366 Parameters
[2] = Parameters
[1];
367 Parameters
[1] = Parameters
[0];
368 Parameters
[0] = (ULONG_PTR
)L
"unknown software exception";
373 /* Calculate length of text buffer */
374 TextStringU
->MaximumLength
= FormatU
.Length
+ SizeOfStrings
+ 42 * sizeof(WCHAR
);
376 /* Allocate a buffer for the text */
377 TextStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
379 TextStringU
->MaximumLength
);
381 /* Wrap in SEH to protect from invalid string parameters */
384 /* Print the string into the buffer */
385 StringCbPrintfW(TextStringU
->Buffer
,
386 TextStringU
->MaximumLength
,
393 Status
= STATUS_SUCCESS
;
395 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
397 /* Set error and free buffers */
398 Status
= _SEH2_GetExceptionCode();
399 RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU
->Buffer
);
400 RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU
->Buffer
);
404 if (NT_SUCCESS(Status
))
406 TextStringU
->Length
= wcslen(TextStringU
->Buffer
) * sizeof(WCHAR
);
409 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
419 ULONG ValidResponseOptions
,
422 ULONG Type
, MessageBoxResponse
;
424 /* Set the message box type */
425 switch (ValidResponseOptions
)
427 case OptionAbortRetryIgnore
:
428 Type
= MB_ABORTRETRYIGNORE
;
436 case OptionRetryCancel
:
437 Type
= MB_RETRYCANCEL
;
442 case OptionYesNoCancel
:
443 Type
= MB_YESNOCANCEL
;
445 case OptionShutdownSystem
:
446 Type
= MB_RETRYCANCEL
; // FIXME???
448 /* Anything else is invalid */
450 return ResponseNotHandled
;
454 if (Severity
== STATUS_SEVERITY_INFORMATIONAL
) Type
|= MB_ICONINFORMATION
;
455 else if (Severity
== STATUS_SEVERITY_WARNING
) Type
|= MB_ICONWARNING
;
456 else if (Severity
== STATUS_SEVERITY_ERROR
) Type
|= MB_ICONERROR
;
458 Type
|= MB_SYSTEMMODAL
| MB_SETFOREGROUND
;
460 DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
461 Text
, Caption
, Severity
, Type
);
463 /* Display a message box */
464 MessageBoxResponse
= MessageBoxW(0, Text
, Caption
, Type
);
466 /* Return response value */
467 switch (MessageBoxResponse
)
469 case IDOK
: return ResponseOk
;
470 case IDCANCEL
: return ResponseCancel
;
471 case IDYES
: return ResponseYes
;
472 case IDNO
: return ResponseNo
;
473 case IDABORT
: return ResponseAbort
;
474 case IDIGNORE
: return ResponseIgnore
;
475 case IDRETRY
: return ResponseRetry
;
476 case IDTRYAGAIN
: return ResponseTryAgain
;
477 case IDCONTINUE
: return ResponseContinue
;
480 return ResponseNotHandled
;
486 IN PCSRSS_PROCESS_DATA ProcessData
,
487 IN PHARDERROR_MSG Message
)
489 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
];
490 OBJECT_ATTRIBUTES ObjectAttributes
;
491 UNICODE_STRING TextU
, CaptionU
;
496 /* Default to not handled */
497 Message
->Response
= ResponseNotHandled
;
499 /* Make sure we don't have too many parameters */
500 if (Message
->NumberOfParameters
> MAXIMUM_HARDERROR_PARAMETERS
)
501 Message
->NumberOfParameters
= MAXIMUM_HARDERROR_PARAMETERS
;
503 /* Initialize object attributes */
504 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
506 /* Open client process */
507 Status
= NtOpenProcess(&hProcess
,
508 PROCESS_VM_READ
| PROCESS_QUERY_INFORMATION
,
510 &Message
->h
.ClientId
);
512 if (!NT_SUCCESS(Status
))
514 DPRINT1("NtOpenProcess failed with code: %lx\n", Status
);
518 /* Capture all string parameters from the process memory */
519 Status
= CsrpCaptureStringParameters(Parameters
, &Size
, Message
, hProcess
);
520 if (!NT_SUCCESS(Status
))
526 /* Format the caption and message box text */
527 Status
= CsrpFormatMessages(&TextU
,
535 CsrpFreeStringParameters(Parameters
, Message
);
538 if (!NT_SUCCESS(Status
))
543 /* Display the message box */
544 Message
->Response
= CsrpMessageBox(TextU
.Buffer
,
546 Message
->ValidResponseOptions
,
547 (ULONG
)Message
->Status
>> 30);
549 RtlFreeUnicodeString(&TextU
);
550 RtlFreeUnicodeString(&CaptionU
);