@@ -315,6 +315,136 @@ static NTSTATUS NTAPI PhpOpenThreadTokenObject(
315
315
);
316
316
}
317
317
318
+ static BOOLEAN PhpWordMatchThreadStringRef (
319
+ _In_ PPH_STRING SearchText ,
320
+ _In_ PPH_STRINGREF Text
321
+ )
322
+ {
323
+ PH_STRINGREF part ;
324
+ PH_STRINGREF remainingPart ;
325
+
326
+ remainingPart = SearchText -> sr ;
327
+
328
+ while (remainingPart .Length )
329
+ {
330
+ PhSplitStringRefAtChar (& remainingPart , '|' , & part , & remainingPart );
331
+
332
+ if (part .Length )
333
+ {
334
+ if (PhFindStringInStringRef (Text , & part , TRUE) != -1 )
335
+ return TRUE;
336
+ }
337
+ }
338
+
339
+ return FALSE;
340
+ }
341
+
342
+ static BOOLEAN PhpWordMatchThreadStringZ (
343
+ _In_ PPH_STRING SearchText ,
344
+ _In_ PWSTR Text
345
+ )
346
+ {
347
+ PH_STRINGREF text ;
348
+
349
+ PhInitializeStringRef (& text , Text );
350
+
351
+ return PhpWordMatchThreadStringRef (SearchText , & text );
352
+ }
353
+
354
+ BOOLEAN PhpThreadTreeFilterCallback (
355
+ _In_ PPH_TREENEW_NODE Node ,
356
+ _In_opt_ PPH_THREADS_CONTEXT Context
357
+ )
358
+ {
359
+ PPH_THREAD_NODE threadNode = (PPH_THREAD_NODE )Node ;
360
+ PPH_THREAD_ITEM threadItem = threadNode -> ThreadItem ;
361
+
362
+ if (PhIsNullOrEmptyString (Context -> SearchboxText ))
363
+ return TRUE;
364
+
365
+ // thread properties
366
+
367
+ if (threadNode -> ThreadIdText [0 ])
368
+ {
369
+ if (PhpWordMatchThreadStringZ (Context -> SearchboxText , threadNode -> ThreadIdText ))
370
+ return TRUE;
371
+ }
372
+
373
+ if (threadNode -> PriorityText [0 ])
374
+ {
375
+ if (PhpWordMatchThreadStringZ (Context -> SearchboxText , threadNode -> PriorityText ))
376
+ return TRUE;
377
+ }
378
+
379
+ if (threadNode -> BasePriorityText [0 ])
380
+ {
381
+ if (PhpWordMatchThreadStringZ (Context -> SearchboxText , threadNode -> BasePriorityText ))
382
+ return TRUE;
383
+ }
384
+
385
+ if (threadNode -> IdealProcessorText [0 ])
386
+ {
387
+ if (PhpWordMatchThreadStringZ (Context -> SearchboxText , threadNode -> IdealProcessorText ))
388
+ return TRUE;
389
+ }
390
+
391
+ if (threadNode -> ThreadIdHexText [0 ])
392
+ {
393
+ if (PhpWordMatchThreadStringZ (Context -> SearchboxText , threadNode -> ThreadIdHexText ))
394
+ return TRUE;
395
+ }
396
+
397
+ if (!PhIsNullOrEmptyString (threadNode -> StartAddressText ))
398
+ {
399
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> StartAddressText -> sr ))
400
+ return TRUE;
401
+ }
402
+
403
+ if (!PhIsNullOrEmptyString (threadNode -> PrioritySymbolicText ))
404
+ {
405
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> PrioritySymbolicText -> sr ))
406
+ return TRUE;
407
+ }
408
+
409
+ if (!PhIsNullOrEmptyString (threadNode -> CreatedText ))
410
+ {
411
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> CreatedText -> sr ))
412
+ return TRUE;
413
+ }
414
+
415
+ if (!PhIsNullOrEmptyString (threadNode -> NameText ))
416
+ {
417
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> NameText -> sr ))
418
+ return TRUE;
419
+ }
420
+
421
+ if (!PhIsNullOrEmptyString (threadNode -> StateText ))
422
+ {
423
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> StateText -> sr ))
424
+ return TRUE;
425
+ }
426
+
427
+ if (!PhIsNullOrEmptyString (threadNode -> ThreadItem -> ServiceName ))
428
+ {
429
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> ThreadItem -> ServiceName -> sr ))
430
+ return TRUE;
431
+ }
432
+
433
+ if (!PhIsNullOrEmptyString (threadNode -> ThreadItem -> StartAddressString ))
434
+ {
435
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> ThreadItem -> StartAddressString -> sr ))
436
+ return TRUE;
437
+ }
438
+
439
+ if (!PhIsNullOrEmptyString (threadNode -> ThreadItem -> StartAddressFileName ))
440
+ {
441
+ if (PhpWordMatchThreadStringRef (Context -> SearchboxText , & threadNode -> ThreadItem -> StartAddressFileName -> sr ))
442
+ return TRUE;
443
+ }
444
+
445
+ return FALSE;
446
+ }
447
+
318
448
VOID PhShowThreadContextMenu (
319
449
_In_ HWND hwndDlg ,
320
450
_In_ PPH_PROCESS_ITEM ProcessItem ,
@@ -445,21 +575,27 @@ INT_PTR CALLBACK PhpProcessThreadsDlgProc(
445
575
& threadsContext -> LoadingStateChangedEventRegistration
446
576
);
447
577
threadsContext -> WindowHandle = hwndDlg ;
578
+ threadsContext -> SearchboxHandle = GetDlgItem (hwndDlg , IDC_SEARCH );
579
+
580
+ PhCreateSearchControl (hwndDlg , threadsContext -> SearchboxHandle , L"Search Threads (Ctrl+K)" );
448
581
449
582
// Initialize the list.
450
583
tnHandle = GetDlgItem (hwndDlg , IDC_LIST );
451
584
PhInitializeThreadList (hwndDlg , tnHandle , & threadsContext -> ListContext );
452
585
TreeNew_SetEmptyText (tnHandle , & EmptyThreadsText , 0 );
453
586
PhInitializeProviderEventQueue (& threadsContext -> EventQueue , 100 );
587
+ threadsContext -> SearchboxText = PhReferenceEmptyString ();
588
+ threadsContext -> FilterEntry = PhAddTreeNewFilter (& threadsContext -> ListContext .TreeFilterSupport , PhpThreadTreeFilterCallback , threadsContext );
589
+
454
590
// Use Cycles instead of Context Switches on Vista and above, but only when we can
455
591
// open the process, since cycle time information requires sufficient access to the
456
- // threads.
592
+ // threads. (wj32)
457
593
{
458
594
HANDLE processHandle ;
459
595
460
596
// We make a distinction between PROCESS_QUERY_INFORMATION and PROCESS_QUERY_LIMITED_INFORMATION since
461
597
// the latter can be used when opening audiodg.exe even though we can't access its threads using
462
- // THREAD_QUERY_LIMITED_INFORMATION.
598
+ // THREAD_QUERY_LIMITED_INFORMATION. (wj32)
463
599
464
600
if (processItem -> ProcessId == SYSTEM_IDLE_PROCESS_ID )
465
601
{
@@ -474,7 +610,7 @@ INT_PTR CALLBACK PhpProcessThreadsDlgProc(
474
610
{
475
611
threadsContext -> ListContext .UseCycleTime = TRUE;
476
612
477
- // We can't use cycle time for protected processes (without KProcessHacker).
613
+ // We can't use cycle time for protected processes (without KProcessHacker). (wj32)
478
614
if (processItem -> IsProtectedProcess )
479
615
{
480
616
threadsContext -> ListContext .UseCycleTime = FALSE;
@@ -509,6 +645,9 @@ INT_PTR CALLBACK PhpProcessThreadsDlgProc(
509
645
break ;
510
646
case WM_DESTROY :
511
647
{
648
+ PhRemoveTreeNewFilter (& threadsContext -> ListContext .TreeFilterSupport , threadsContext -> FilterEntry );
649
+ if (threadsContext -> SearchboxText ) PhDereferenceObject (threadsContext -> SearchboxText );
650
+
512
651
PhEmCallObjectOperation (EmThreadsContextType , threadsContext , EmObjectDelete );
513
652
514
653
PhUnregisterCallback (
@@ -557,13 +696,36 @@ INT_PTR CALLBACK PhpProcessThreadsDlgProc(
557
696
558
697
if (dialogItem = PhBeginPropPageLayout (hwndDlg , propPageContext ))
559
698
{
560
- PhAddPropPageLayoutItem (hwndDlg , GetDlgItem (hwndDlg , IDC_LIST ), dialogItem , PH_ANCHOR_ALL );
699
+ PhAddPropPageLayoutItem (hwndDlg , threadsContext -> SearchboxHandle , dialogItem , PH_ANCHOR_TOP | PH_ANCHOR_RIGHT );
700
+ PhAddPropPageLayoutItem (hwndDlg , tnHandle , dialogItem , PH_ANCHOR_ALL );
561
701
PhEndPropPageLayout (hwndDlg , propPageContext );
562
702
}
563
703
}
564
704
break ;
565
705
case WM_COMMAND :
566
706
{
707
+ switch (GET_WM_COMMAND_CMD (wParam , lParam ))
708
+ {
709
+ case EN_CHANGE :
710
+ {
711
+ PPH_STRING newSearchboxText ;
712
+
713
+ if (GET_WM_COMMAND_HWND (wParam , lParam ) != threadsContext -> SearchboxHandle )
714
+ break ;
715
+
716
+ newSearchboxText = PH_AUTO (PhGetWindowText (threadsContext -> SearchboxHandle ));
717
+
718
+ if (!PhEqualString (threadsContext -> SearchboxText , newSearchboxText , FALSE))
719
+ {
720
+ // Cache the current search text for our callback.
721
+ PhSwapReference (& threadsContext -> SearchboxText , newSearchboxText );
722
+
723
+ PhApplyTreeNewFilters (& threadsContext -> ListContext .TreeFilterSupport );
724
+ }
725
+ }
726
+ break ;
727
+ }
728
+
567
729
switch (GET_WM_COMMAND_ID (wParam , lParam ))
568
730
{
569
731
case ID_SHOWCONTEXTMENU :
@@ -915,7 +1077,7 @@ INT_PTR CALLBACK PhpProcessThreadsDlgProc(
915
1077
// Can't disable, it screws up the deltas.
916
1078
break ;
917
1079
case PSN_QUERYINITIALFOCUS :
918
- SetWindowLongPtr (hwndDlg , DWLP_MSGRESULT , (LPARAM )GetDlgItem ( hwndDlg , IDC_LIST ) );
1080
+ SetWindowLongPtr (hwndDlg , DWLP_MSGRESULT , (LPARAM )tnHandle );
919
1081
return TRUE;
920
1082
}
921
1083
}
0 commit comments