mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
ed81c34b2c
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4534 21ef857c-d57f-4fe0-8362-d861dc6d29cd
324 lines
10 KiB
C
324 lines
10 KiB
C
/*
|
|
* Process Hacker Network Tools -
|
|
* output dialog
|
|
*
|
|
* Copyright (C) 2010-2011 wj32
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <phdk.h>
|
|
#include "nettools.h"
|
|
#include "resource.h"
|
|
|
|
#define NTM_DONE (WM_APP + 1)
|
|
#define NTM_RECEIVED (WM_APP + 2)
|
|
|
|
typedef struct _NETWORK_OUTPUT_CONTEXT
|
|
{
|
|
ULONG Action;
|
|
PH_IP_ADDRESS Address;
|
|
HWND WindowHandle;
|
|
PH_QUEUED_LOCK WindowHandleLock;
|
|
|
|
HANDLE ThreadHandle;
|
|
HANDLE PipeReadHandle;
|
|
HANDLE ProcessHandle;
|
|
|
|
PPH_FULL_STRING ReceivedString;
|
|
} NETWORK_OUTPUT_CONTEXT, *PNETWORK_OUTPUT_CONTEXT;
|
|
|
|
INT_PTR CALLBACK NetworkOutputDlgProc(
|
|
__in HWND hwndDlg,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
);
|
|
|
|
VOID PerformNetworkAction(
|
|
__in HWND hWnd,
|
|
__in ULONG Action,
|
|
__in PPH_IP_ADDRESS Address
|
|
)
|
|
{
|
|
NETWORK_OUTPUT_CONTEXT context;
|
|
|
|
memset(&context, 0, sizeof(NETWORK_OUTPUT_CONTEXT));
|
|
context.Action = Action;
|
|
context.Address = *Address;
|
|
PhInitializeQueuedLock(&context.WindowHandleLock);
|
|
context.ReceivedString = PhCreateFullString2(PAGE_SIZE);
|
|
|
|
DialogBoxParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_OUTPUT),
|
|
hWnd,
|
|
NetworkOutputDlgProc,
|
|
(LPARAM)&context
|
|
);
|
|
|
|
if (context.ThreadHandle)
|
|
{
|
|
// Wait for our thread to exit since it uses the context structure.
|
|
NtWaitForSingleObject(context.ThreadHandle, FALSE, NULL);
|
|
NtClose(context.ThreadHandle);
|
|
}
|
|
|
|
PhDereferenceObject(context.ReceivedString);
|
|
}
|
|
|
|
static NTSTATUS NetworkWorkerThreadStart(
|
|
__in PVOID Parameter
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PNETWORK_OUTPUT_CONTEXT context = Parameter;
|
|
IO_STATUS_BLOCK isb;
|
|
UCHAR buffer[4096];
|
|
|
|
while (TRUE)
|
|
{
|
|
status = NtReadFile(
|
|
context->PipeReadHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&isb,
|
|
buffer,
|
|
sizeof(buffer),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
PhAcquireQueuedLockExclusive(&context->WindowHandleLock);
|
|
|
|
if (!context->WindowHandle)
|
|
{
|
|
PhReleaseQueuedLockExclusive(&context->WindowHandleLock);
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SendMessage(context->WindowHandle, NTM_DONE, 0, 0);
|
|
PhReleaseQueuedLockExclusive(&context->WindowHandleLock);
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
SendMessage(context->WindowHandle, NTM_RECEIVED, (WPARAM)isb.Information, (LPARAM)buffer);
|
|
PhReleaseQueuedLockExclusive(&context->WindowHandleLock);
|
|
}
|
|
|
|
ExitCleanup:
|
|
NtClose(context->PipeReadHandle);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
INT_PTR CALLBACK NetworkOutputDlgProc(
|
|
__in HWND hwndDlg,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
)
|
|
{
|
|
PNETWORK_OUTPUT_CONTEXT context;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PNETWORK_OUTPUT_CONTEXT)lParam;
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_DESTROY)
|
|
RemoveProp(hwndDlg, L"Context");
|
|
}
|
|
|
|
if (!context)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
WCHAR addressString[65];
|
|
HANDLE pipeWriteHandle;
|
|
|
|
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
|
|
context->WindowHandle = hwndDlg;
|
|
|
|
if (context->Address.Type == PH_IPV4_NETWORK_TYPE)
|
|
RtlIpv4AddressToString(&context->Address.InAddr, addressString);
|
|
else
|
|
RtlIpv6AddressToString(&context->Address.In6Addr, addressString);
|
|
|
|
switch (context->Action)
|
|
{
|
|
case NETWORK_ACTION_PING:
|
|
case NETWORK_ACTION_TRACEROUTE:
|
|
if (context->Action == NETWORK_ACTION_PING)
|
|
{
|
|
SetDlgItemText(hwndDlg, IDC_MESSAGE,
|
|
PhaFormatString(L"Pinging %s...", addressString)->Buffer);
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(hwndDlg, IDC_MESSAGE,
|
|
PhaFormatString(L"Tracing route to %s...", addressString)->Buffer);
|
|
}
|
|
|
|
// Doing this properly would be too complex, so we'll just
|
|
// execute ping.exe/traceroute.exe and display its output.
|
|
|
|
if (CreatePipe(&context->PipeReadHandle, &pipeWriteHandle, NULL, 0))
|
|
{
|
|
STARTUPINFO startupInfo = { sizeof(startupInfo) };
|
|
PPH_STRING command;
|
|
OBJECT_HANDLE_FLAG_INFORMATION flagInfo;
|
|
|
|
startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
|
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
startupInfo.hStdOutput = pipeWriteHandle;
|
|
startupInfo.hStdError = pipeWriteHandle;
|
|
startupInfo.wShowWindow = SW_HIDE;
|
|
|
|
if (context->Action == NETWORK_ACTION_PING)
|
|
{
|
|
command = PhaFormatString(
|
|
L"%s\\system32\\ping.exe %s",
|
|
USER_SHARED_DATA->NtSystemRoot,
|
|
addressString
|
|
);
|
|
}
|
|
else
|
|
{
|
|
command = PhaFormatString(
|
|
L"%s\\system32\\tracert.exe %s",
|
|
USER_SHARED_DATA->NtSystemRoot,
|
|
addressString
|
|
);
|
|
}
|
|
|
|
// Allow the write handle to be inherited.
|
|
|
|
flagInfo.Inherit = TRUE;
|
|
flagInfo.ProtectFromClose = FALSE;
|
|
|
|
NtSetInformationObject(
|
|
pipeWriteHandle,
|
|
ObjectHandleFlagInformation,
|
|
&flagInfo,
|
|
sizeof(OBJECT_HANDLE_FLAG_INFORMATION)
|
|
);
|
|
|
|
PhCreateProcessWin32Ex(
|
|
NULL,
|
|
command->Buffer,
|
|
NULL,
|
|
NULL,
|
|
&startupInfo,
|
|
PH_CREATE_PROCESS_INHERIT_HANDLES,
|
|
NULL,
|
|
NULL,
|
|
&context->ProcessHandle,
|
|
NULL
|
|
);
|
|
|
|
// Essential; when the process exits, the last instance of the pipe
|
|
// will be disconnected and our thread will exit.
|
|
NtClose(pipeWriteHandle);
|
|
|
|
// Create a thread which will wait for output and display it.
|
|
context->ThreadHandle = PhCreateThread(0, NetworkWorkerThreadStart, context);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PhAcquireQueuedLockExclusive(&context->WindowHandleLock);
|
|
context->WindowHandle = NULL;
|
|
PhReleaseQueuedLockExclusive(&context->WindowHandleLock);
|
|
|
|
if (context->ProcessHandle)
|
|
{
|
|
NtTerminateProcess(context->ProcessHandle, STATUS_SUCCESS);
|
|
NtClose(context->ProcessHandle);
|
|
}
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
case IDOK:
|
|
EndDialog(hwndDlg, IDOK);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case NTM_DONE:
|
|
{
|
|
SetDlgItemText(hwndDlg, IDC_MESSAGE, L"Finished.");
|
|
}
|
|
break;
|
|
case NTM_RECEIVED:
|
|
{
|
|
OEM_STRING inputString;
|
|
UNICODE_STRING convertedString;
|
|
|
|
if (wParam != 0)
|
|
{
|
|
inputString.Buffer = (PCHAR)lParam;
|
|
inputString.Length = (USHORT)wParam;
|
|
|
|
if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE)))
|
|
{
|
|
PhAppendFullStringEx(context->ReceivedString, convertedString.Buffer, convertedString.Length);
|
|
RtlFreeUnicodeString(&convertedString);
|
|
|
|
// Remove leading newlines.
|
|
if (
|
|
context->ReceivedString->Length >= 2 * 2 &&
|
|
context->ReceivedString->Buffer[0] == '\r' && context->ReceivedString->Buffer[1] == '\n'
|
|
)
|
|
{
|
|
PhRemoveFullString(context->ReceivedString, 0, 2);
|
|
}
|
|
|
|
SetDlgItemText(hwndDlg, IDC_TEXT, context->ReceivedString->Buffer);
|
|
SendMessage(
|
|
GetDlgItem(hwndDlg, IDC_TEXT),
|
|
EM_SETSEL,
|
|
context->ReceivedString->Length / 2 - 1,
|
|
context->ReceivedString->Length / 2 - 1
|
|
);
|
|
SendMessage(GetDlgItem(hwndDlg, IDC_TEXT), WM_VSCROLL, SB_BOTTOM, 0);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|