-
Notifications
You must be signed in to change notification settings - Fork 21
Add flag for getting command line arguments of processes #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,11 +21,13 @@ struct ProcessInfo { | |
DWORD pid; | ||
DWORD ppid; | ||
DWORD memory; // Reported in bytes | ||
TCHAR arguments[512]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice below you trim if the command line goes over, is there a actual maximum value we could use here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The actual maximum is 8191 (at least for processes run from cmd line), but increasing it beyond ~720 causes the JS tests to error out without any message. I tried switching to allocating the ProcessInfo array on the heap, but that causes a heap out of memory exception when running the tests with the current size. Earlier I thought I was seeing nondeterministic failures when it was set to 720, so I'm wary of increasing it close to that. My guess is that it failed because it wasn't able to find a piece of contiguous memory large enough, even though its not a particularly large array, ~54k. |
||
}; | ||
|
||
enum ProcessDataFlags { | ||
NONE = 0, | ||
MEMORY = 1 | ||
MEMORY = 1, | ||
ARGUMENTS = 2 | ||
}; | ||
|
||
void GetRawProcessList(ProcessInfo process_info[1024], uint32_t* process_count, DWORD* flags); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
#include "process.h" | ||
#include "process_arguments.h" | ||
#include <windows.h> | ||
#include <winternl.h> | ||
#include <psapi.h> | ||
|
||
bool GetProcessCommandLineArguments(ProcessInfo process_info[1024], uint32_t *process_count) { | ||
pfnNtQueryInformationProcess gNtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress( | ||
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); | ||
|
||
PPROCESS_BASIC_INFORMATION pbi = NULL; | ||
PEB peb = {NULL}; | ||
RTL_USER_PROCESS_PARAMETERS process_parameters = {NULL}; | ||
|
||
// Get process handle | ||
DWORD pid = process_info[*process_count].pid; | ||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); | ||
if (hProcess == INVALID_HANDLE_VALUE) { | ||
return FALSE; | ||
} | ||
|
||
// Get process basic information | ||
HANDLE heap = GetProcessHeap(); | ||
DWORD pbi_size = sizeof(PROCESS_BASIC_INFORMATION); | ||
pbi = (PROCESS_BASIC_INFORMATION *)HeapAlloc(heap, HEAP_ZERO_MEMORY, pbi_size); | ||
if (!pbi) { | ||
CloseHandle(hProcess); | ||
return FALSE; | ||
} | ||
|
||
// Get Process Environment Block (PEB) | ||
DWORD size_needed; | ||
NTSTATUS status = gNtQueryInformationProcess(hProcess, ProcessBasicInformation, pbi, pbi_size, &size_needed); | ||
if (status >= 0 && pbi->PebBaseAddress) { | ||
|
||
// Read PEB | ||
SIZE_T bytes_read; | ||
if (ReadProcessMemory(hProcess, pbi->PebBaseAddress, &peb, sizeof(peb), &bytes_read)) { | ||
|
||
// Read the processs parameters | ||
bytes_read = 0; | ||
if (ReadProcessMemory(hProcess, peb.ProcessParameters, &process_parameters, sizeof(RTL_USER_PROCESS_PARAMETERS), &bytes_read)) { | ||
if (process_parameters.CommandLine.Length > 0) { | ||
|
||
// Allocate space to read the command line parameter | ||
WCHAR *buffer = NULL; | ||
buffer = (WCHAR *)HeapAlloc(heap, HEAP_ZERO_MEMORY, process_parameters.CommandLine.Length); | ||
if (buffer) { | ||
if (ReadProcessMemory(hProcess, process_parameters.CommandLine.Buffer, buffer, process_parameters.CommandLine.Length, &bytes_read)) { | ||
|
||
// Copy only as much as will fit in the arguments property | ||
DWORD buffer_size = process_parameters.CommandLine.Length >= sizeof(process_info[*process_count].arguments) | ||
? sizeof(process_info[*process_count].arguments) - sizeof(TCHAR) | ||
: process_parameters.CommandLine.Length; | ||
|
||
WideCharToMultiByte(CP_ACP, 0, buffer, | ||
(int)(buffer_size / sizeof(WCHAR)), | ||
process_info[*process_count].arguments, sizeof(process_info[*process_count].arguments), | ||
NULL, NULL); | ||
|
||
CloseHandle(hProcess); | ||
HeapFree(heap, 0, pbi); | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
CloseHandle(hProcess); | ||
HeapFree(heap, 0, pbi); | ||
return false; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
#ifndef SRC_PROCESS_ARGUMENTS_H_ | ||
#define SRC_PROCESS_ARGUMENTS_H_ | ||
|
||
#include "process.h" | ||
#include <winternl.h> | ||
|
||
typedef NTSTATUS(NTAPI *pfnNtQueryInformationProcess)( | ||
IN HANDLE ProcessHandle, | ||
IN PROCESSINFOCLASS ProcessInformationClass, | ||
OUT PVOID ProcessInformation, | ||
IN ULONG ProcessInformationLength, | ||
OUT PULONG ReturnLength OPTIONAL); | ||
|
||
bool GetProcessCommandLineArguments(ProcessInfo process_info[1024], uint32_t *process_count); | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,16 @@ | |
declare module 'windows-process-tree' { | ||
export enum ProcessDataFlag { | ||
None = 0, | ||
Memory = 1 | ||
Memory = 1, | ||
Arguments = 2 | ||
} | ||
|
||
export interface IProcessInfo { | ||
pid: number; | ||
ppid: number; | ||
name: string; | ||
memory?: number; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. jsdoc explaining the unit would be good |
||
arguments?: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
export interface IProcessCpuInfo extends IProcessInfo { | ||
|
@@ -24,11 +26,10 @@ declare module 'windows-process-tree' { | |
pid: number; | ||
name: string; | ||
memory?: number; | ||
arguments?: string; | ||
children: IProcessTreeNode[]; | ||
} | ||
|
||
|
||
|
||
/** | ||
* Returns a tree of processes with the rootPid process as the root. | ||
* @param {number} rootPid - The pid of the process that will be the root of the tree. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should omit the types here as they are redundant and could succumb to bit rot |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this again we should probably name this "CommandLine" instead of Arguments as that's the Windows terminology for the exe+args.