From 58a686c945de9b80daa3ecab5db321cd975b7812 Mon Sep 17 00:00:00 2001 From: wj32 Date: Tue, 5 Jan 2010 23:37:19 +0000 Subject: [PATCH] added error message formatting git-svn-id: svn://svn.code.sf.net/p/processhacker/code@2567 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- 2.x/trunk/ProcessHacker/include/ntimport.h | 2 + 2.x/trunk/ProcessHacker/include/ntrtl.h | 16 +++ 2.x/trunk/ProcessHacker/include/ph.h | 32 +++++ 2.x/trunk/ProcessHacker/include/symprvp.h | 2 +- 2.x/trunk/ProcessHacker/ntimport.c | 2 + 2.x/trunk/ProcessHacker/process.c | 44 ++++++ 2.x/trunk/ProcessHacker/procprp.c | 26 +++- 2.x/trunk/ProcessHacker/support.c | 154 +++++++++++++++++++++ 8 files changed, 276 insertions(+), 2 deletions(-) diff --git a/2.x/trunk/ProcessHacker/include/ntimport.h b/2.x/trunk/ProcessHacker/include/ntimport.h index 9e1d44635..af5710080 100644 --- a/2.x/trunk/ProcessHacker/include/ntimport.h +++ b/2.x/trunk/ProcessHacker/include/ntimport.h @@ -61,8 +61,10 @@ EXT _NtWriteFile NtWriteFile EQNULL; EXT _NtWriteVirtualMemory NtWriteVirtualMemory EQNULL; EXT _RtlCreateQueryDebugBuffer RtlCreateQueryDebugBuffer EQNULL; EXT _RtlDestroyQueryDebugBuffer RtlDestroyQueryDebugBuffer EQNULL; +EXT _RtlFindMessage RtlFindMessage EQNULL; EXT _RtlMultiByteToUnicodeN RtlMultiByteToUnicodeN EQNULL; EXT _RtlMultiByteToUnicodeSize RtlMultiByteToUnicodeSize EQNULL; +EXT _RtlNtStatusToDosError RtlNtStatusToDosError EQNULL; EXT _RtlQueryProcessDebugInformation RtlQueryProcessDebugInformation EQNULL; EXT _RtlUnicodeToMultiByteN RtlUnicodeToMultiByteN EQNULL; EXT _RtlUnicodeToMultiByteSize RtlUnicodeToMultiByteSize EQNULL; diff --git a/2.x/trunk/ProcessHacker/include/ntrtl.h b/2.x/trunk/ProcessHacker/include/ntrtl.h index a13d7fb04..2973c37c1 100644 --- a/2.x/trunk/ProcessHacker/include/ntrtl.h +++ b/2.x/trunk/ProcessHacker/include/ntrtl.h @@ -329,4 +329,20 @@ typedef NTSTATUS (NTAPI *_RtlQueryProcessDebugInformation)( #define RTL_QUERY_PROCESS_MODULES32 0x00000040 #define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 +// Messages + +typedef NTSTATUS (NTAPI *_RtlFindMessage)( + __in PVOID DllHandle, + __in ULONG MessageTableId, + __in ULONG MessageLanguageId, + __in ULONG MessageId, + __out PMESSAGE_RESOURCE_ENTRY *MessageEntry + ); + +// Errors + +typedef ULONG (NTAPI *_RtlNtStatusToDosError)( + __in NTSTATUS Status + ); + #endif diff --git a/2.x/trunk/ProcessHacker/include/ph.h b/2.x/trunk/ProcessHacker/include/ph.h index 65ff76f19..222a678f0 100644 --- a/2.x/trunk/ProcessHacker/include/ph.h +++ b/2.x/trunk/ProcessHacker/include/ph.h @@ -49,6 +49,16 @@ NTSTATUS PhOpenProcessToken( __in HANDLE ProcessHandle ); +NTSTATUS PhTerminateProcess( + __in HANDLE ProcessHandle, + __in NTSTATUS ExitStatus + ); + +NTSTATUS PhTerminateThread( + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ); + NTSTATUS PhReadVirtualMemory( __in HANDLE ProcessHandle, __in PVOID BaseAddress, @@ -683,6 +693,21 @@ VOID PhThreadProviderUpdate( // support +PPH_STRING PhGetMessage( + __in HANDLE DllHandle, + __in ULONG MessageTableId, + __in ULONG MessageLanguageId, + __in ULONG MessageId + ); + +PPH_STRING PhGetNtMessage( + __in NTSTATUS Status + ); + +PPH_STRING PhGetWin32Message( + __in ULONG Result + ); + #define PH_MAX_MESSAGE_SIZE 400 INT PhShowMessage( @@ -701,6 +726,13 @@ INT PhShowMessage_V( #define PhShowError(hWnd, Format, ...) PhShowMessage(hWnd, MB_OK | MB_ICONERROR, Format, __VA_ARGS__) +VOID PhShowStatus( + __in HWND hWnd, + __in_opt PWSTR Message, + __in NTSTATUS Status, + __in_opt ULONG Win32Result + ); + PVOID PhGetFileVersionInfo( __in PWSTR FileName ); diff --git a/2.x/trunk/ProcessHacker/include/symprvp.h b/2.x/trunk/ProcessHacker/include/symprvp.h index 28130c156..c87f07274 100644 --- a/2.x/trunk/ProcessHacker/include/symprvp.h +++ b/2.x/trunk/ProcessHacker/include/symprvp.h @@ -25,7 +25,7 @@ typedef BOOL (WINAPI *_SymFromAddr)( __in HANDLE hProcess, __in DWORD64 Address, __out_opt PDWORD64 Displacement, - __inout PSYMBOL_INFO Symbol + __inout PSYMBOL_INFOW Symbol ); typedef DWORD64 (WINAPI *_SymLoadModule64)( diff --git a/2.x/trunk/ProcessHacker/ntimport.c b/2.x/trunk/ProcessHacker/ntimport.c index 0b2465abf..5c5d8f8c3 100644 --- a/2.x/trunk/ProcessHacker/ntimport.c +++ b/2.x/trunk/ProcessHacker/ntimport.c @@ -83,8 +83,10 @@ BOOLEAN PhInitializeImports() InitProcReq("ntdll.dll", NtWriteVirtualMemory); InitProcReq("ntdll.dll", RtlCreateQueryDebugBuffer); InitProcReq("ntdll.dll", RtlDestroyQueryDebugBuffer); + InitProcReq("ntdll.dll", RtlFindMessage); InitProcReq("ntdll.dll", RtlMultiByteToUnicodeN); InitProcReq("ntdll.dll", RtlMultiByteToUnicodeSize); + InitProcReq("ntdll.dll", RtlNtStatusToDosError); InitProcReq("ntdll.dll", RtlQueryProcessDebugInformation); InitProcReq("ntdll.dll", RtlUnicodeToMultiByteN); InitProcReq("ntdll.dll", RtlUnicodeToMultiByteSize); diff --git a/2.x/trunk/ProcessHacker/process.c b/2.x/trunk/ProcessHacker/process.c index 5e51a5459..4cb595be2 100644 --- a/2.x/trunk/ProcessHacker/process.c +++ b/2.x/trunk/ProcessHacker/process.c @@ -114,6 +114,50 @@ NTSTATUS PhOpenProcessToken( } } +NTSTATUS PhTerminateProcess( + __in HANDLE ProcessHandle, + __in NTSTATUS ExitStatus + ) +{ + if (PhKphHandle) + { + return KphTerminateProcess( + PhKphHandle, + ProcessHandle, + ExitStatus + ); + } + else + { + return NtTerminateProcess( + ProcessHandle, + ExitStatus + ); + } +} + +NTSTATUS PhTerminateThread( + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ) +{ + if (PhKphHandle) + { + return KphTerminateThread( + PhKphHandle, + ThreadHandle, + ExitStatus + ); + } + else + { + return NtTerminateThread( + ThreadHandle, + ExitStatus + ); + } +} + NTSTATUS PhReadVirtualMemory( __in HANDLE ProcessHandle, __in PVOID BaseAddress, diff --git a/2.x/trunk/ProcessHacker/procprp.c b/2.x/trunk/ProcessHacker/procprp.c index 979921370..c678cc5eb 100644 --- a/2.x/trunk/ProcessHacker/procprp.c +++ b/2.x/trunk/ProcessHacker/procprp.c @@ -334,7 +334,31 @@ INT_PTR CALLBACK PhpProcessGeneralDlgProc( processItem->ProcessName->Buffer ) == IDYES) { - + NTSTATUS status; + HANDLE processHandle; + + if (NT_SUCCESS(status = PhOpenProcess( + &processHandle, + PROCESS_TERMINATE, + processItem->ProcessId + ))) + { + status = PhTerminateProcess( + processHandle, + STATUS_SUCCESS + ); + CloseHandle(processHandle); + } + + if (!NT_SUCCESS(status)) + { + PhShowStatus( + hwndDlg, + L"Unable to terminate the process", + status, + 0 + ); + } } } break; diff --git a/2.x/trunk/ProcessHacker/support.c b/2.x/trunk/ProcessHacker/support.c index 7883fd2d0..dd0f9a09b 100644 --- a/2.x/trunk/ProcessHacker/support.c +++ b/2.x/trunk/ProcessHacker/support.c @@ -23,6 +23,105 @@ #include #include +PPH_STRING PhGetMessage( + __in HANDLE DllHandle, + __in ULONG MessageTableId, + __in ULONG MessageLanguageId, + __in ULONG MessageId + ) +{ + NTSTATUS status; + PMESSAGE_RESOURCE_ENTRY messageEntry; + + status = RtlFindMessage( + DllHandle, + MessageTableId, + MessageLanguageId, + MessageId, + &messageEntry + ); + + // Try using the system LANGID. + if (!NT_SUCCESS(status)) + { + status = RtlFindMessage( + DllHandle, + MessageTableId, + GetSystemDefaultLangID(), + MessageId, + &messageEntry + ); + } + + // Try using U.S. English. + if (!NT_SUCCESS(status)) + { + status = RtlFindMessage( + DllHandle, + MessageTableId, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + MessageId, + &messageEntry + ); + } + + if (!NT_SUCCESS(status)) + return NULL; + + if (messageEntry->Flags & MESSAGE_RESOURCE_UNICODE) + { + return PhCreateStringEx((PWSTR)messageEntry->Text, messageEntry->Length); + } + else + { + return PhCreateStringFromAnsiEx((PSTR)messageEntry->Text, messageEntry->Length); + } +} + +PPH_STRING PhGetNtMessage( + __in NTSTATUS Status + ) +{ + PPH_STRING message; + + message = PhGetMessage(GetModuleHandle(L"ntdll.dll"), 0xb, GetUserDefaultLangID(), (ULONG)Status); + + if (!message) + return NULL; + if (message->Length == 0) + return message; + + // Fix those messages which are formatted like: + // {Asdf}\r\nAsdf asdf asdf... + if (message->Buffer[0] == '{') + { + ULONG indexOfNewLine = PhStringIndexOfChar(message, 0, '\n'); + + if (indexOfNewLine != -1) + { + PPH_STRING newMessage; + + newMessage = PhSubstring( + message, + indexOfNewLine + 1, + message->Length / 2 - indexOfNewLine - 1 + ); + PhDereferenceObject(message); + + message = newMessage; + } + } + + return message; +} + +PPH_STRING PhGetWin32Message( + __in ULONG Result + ) +{ + return PhGetMessage(GetModuleHandle(L"kernel32.dll"), 0xb, GetUserDefaultLangID(), Result); +} + INT PhShowMessage( __in HWND hWnd, __in ULONG Type, @@ -55,6 +154,61 @@ INT PhShowMessage_V( return MessageBox(hWnd, message, PH_APP_NAME, Type); } +VOID PhShowStatus( + __in HWND hWnd, + __in_opt PWSTR Message, + __in NTSTATUS Status, + __in_opt ULONG Win32Result + ) +{ + PPH_STRING statusMessage; + + if (!Win32Result) + { + // In some cases we want the simple Win32 messages. + if ( + Status != STATUS_ACCESS_DENIED && + Status != STATUS_ACCESS_VIOLATION + ) + { + statusMessage = PhGetNtMessage(Status); + } + else + { + statusMessage = PhGetWin32Message(RtlNtStatusToDosError(Status)); + } + } + else + { + statusMessage = PhGetWin32Message(Win32Result); + } + + if (!statusMessage) + { + if (Message) + { + PhShowError(hWnd, L"%s.", Message); + } + else + { + PhShowError(hWnd, L"Unable to perform the operation."); + } + + return; + } + + if (Message) + { + PhShowError(hWnd, L"%s: %s", Message, statusMessage->Buffer); + } + else + { + PhShowError(hWnd, L"%s", statusMessage->Buffer); + } + + PhDereferenceObject(statusMessage); +} + PVOID PhGetFileVersionInfo( __in PWSTR FileName )