27 typedef struct _WS_WATCH_CONTEXT
42 HANDLE LoadingSymbolsForProcessId;
43 SINGLE_LIST_ENTRY ResultListHead;
47 typedef struct _SYMBOL_LOOKUP_RESULT
49 SINGLE_LIST_ENTRY ListEntry;
71 _In_ HWND ParentWindowHandle,
79 context->RefCount = 1;
80 context->ProcessItem = ProcessItem;
96 _InterlockedIncrement(&Context->RefCount);
103 if (_InterlockedDecrement(&Context->RefCount) == 0)
105 PSINGLE_LIST_ENTRY listEntry;
107 if (Context->SymbolProvider)
114 listEntry = Context->ResultListHead.Next;
121 listEntry = listEntry->Next;
132 static NTSTATUS EtpSymbolLookupFunction(
141 if (result->Context->Destroying)
145 return STATUS_SUCCESS;
149 result->Context->SymbolProvider,
150 (ULONG64)result->Address,
162 return STATUS_SUCCESS;
166 PushEntryList(&result->Context->ResultListHead, &result->ListEntry);
170 return STATUS_SUCCESS;
173 static VOID EtpQueueSymbolLookup(
181 result->Context = Context;
182 result->Address = Address;
227 static VOID EtpProcessSymbolLookupResults(
232 PSINGLE_LIST_ENTRY listEntry;
236 listEntry = Context->ResultListHead.Next;
237 Context->ResultListHead.Next = NULL;
246 listEntry = listEntry->Next;
249 Context->ListViewHandle,
252 result->Symbol->Buffer
260 static BOOLEAN EtpUpdateWsWatch(
272 if (!Context->Buffer)
275 status = NtQueryInformationProcess(
276 Context->ProcessHandle,
277 ProcessWorkingSetWatchEx,
283 if (status == STATUS_UNSUCCESSFUL)
289 if (status == STATUS_NO_MORE_ENTRIES)
296 if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH)
299 Context->Buffer = PhAllocate(returnLength);
300 Context->BufferSize = returnLength;
302 status = NtQueryInformationProcess(
303 Context->ProcessHandle,
304 ProcessWorkingSetWatchEx,
322 wsWatchInfo = Context->Buffer;
324 while (wsWatchInfo->
BasicInfo.FaultingPc)
337 newCount = PtrToUlong(*entry) + 1;
338 *entry = UlongToPtr(newCount);
349 basicSymbol = EtpGetBasicSymbol(Context->SymbolProvider, (ULONG64)wsWatchInfo->
BasicInfo.FaultingPc);
355 EtpQueueSymbolLookup(Context, wsWatchInfo->
BasicInfo.FaultingPc);
361 Context->ListViewHandle,
374 EtpProcessSymbolLookupResults(hwndDlg, Context);
380 static BOOLEAN NTAPI EnumGenericModulesCallback(
382 _In_opt_ PVOID Context
397 (ULONG64)Module->BaseAddress, Module->Size);
411 if (uMsg == WM_INITDIALOG)
414 SetProp(hwndDlg, L
"Context", (HANDLE)context);
420 if (uMsg == WM_DESTROY)
421 RemoveProp(hwndDlg, L
"Context");
435 context->WindowHandle = hwndDlg;
436 context->ListViewHandle = lvHandle = GetDlgItem(hwndDlg,
IDC_LIST);
446 context->BufferSize = 0x2000;
447 context->Buffer = PhAllocate(context->BufferSize);
453 if (!context->SymbolProvider || !context->SymbolProvider->IsRealHandle)
455 PhShowError(hwndDlg, L
"Unable to open the process.");
456 EndDialog(hwndDlg, IDCANCEL);
460 context->ProcessHandle = context->SymbolProvider->ProcessHandle;
463 context->LoadingSymbolsForProcessId = context->ProcessItem->ProcessId;
466 context->ProcessHandle,
468 EnumGenericModulesCallback,
476 EnumGenericModulesCallback,
480 context->Enabled = EtpUpdateWsWatch(hwndDlg, context);
482 if (context->Enabled)
487 SetTimer(hwndDlg, 1, 1000, NULL);
497 context->Destroying =
TRUE;
504 context->Buffer = NULL;
510 switch (LOWORD(wParam))
514 EndDialog(hwndDlg, IDOK);
519 HANDLE processHandle;
524 context->ProcessItem->ProcessId
527 status = NtSetInformationProcess(
529 ProcessWorkingSetWatchEx,
533 NtClose(processHandle);
540 SetTimer(hwndDlg, 1, 1000, NULL);
544 PhShowStatus(hwndDlg, L
"Unable to enable WS watch", status, 0);
562 EtpUpdateWsWatch(hwndDlg, context);