Skip to content

Commit 39417f1

Browse files
committed
NetworkTools: Fix crash winsiderss#379
1 parent 9e927e6 commit 39417f1

File tree

3 files changed

+115
-27
lines changed

3 files changed

+115
-27
lines changed

plugins/NetworkTools/nettools.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,17 @@ typedef enum _PH_NETWORK_ACTION
9393
MENU_ACTION_COPY,
9494
} PH_NETWORK_ACTION;
9595

96+
#define UPDATE_MENUITEM 1005
9697
#define NTM_RECEIVEDTRACE (WM_APP + 1)
9798
#define NTM_RECEIVEDWHOIS (WM_APP + 2)
9899
#define NTM_RECEIVEDFINISH (WM_APP + 3)
99100
#define WM_TRACERT_UPDATE (WM_APP + 4)
100101
#define WM_TRACERT_HOSTNAME (WM_APP + 5)
101102
#define WM_TRACERT_COUNTRY (WM_APP + 6)
102103

103-
#define UPDATE_MENUITEM 1005
104+
#define PH_SHOWDIALOG (WM_APP + 10)
105+
#define PH_SHOWINSTALL (WM_APP + 11)
106+
#define PH_SHOWERROR (WM_APP + 12)
104107

105108
typedef struct _NETWORK_PING_CONTEXT
106109
{
@@ -155,6 +158,12 @@ typedef struct _NETWORK_WHOIS_CONTEXT
155158
WCHAR IpAddressString[INET6_ADDRSTRLEN + 1];
156159
} NETWORK_WHOIS_CONTEXT, *PNETWORK_WHOIS_CONTEXT;
157160

161+
// TDM_NAVIGATE_PAGE can not be called from other threads without comctl32.dll throwing access violations
162+
// after navigating to the page and you press keys such as ctrl, alt, home and insert. (dmex)
163+
#define TaskDialogNavigatePage(WindowHandle, Config) \
164+
assert(HandleToUlong(NtCurrentThreadId()) == GetWindowThreadProcessId(WindowHandle, NULL)); \
165+
SendMessage(WindowHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)Config);
166+
158167
VOID ShowWhoisWindow(
159168
_In_ PPH_NETWORK_ITEM NetworkItem
160169
);
@@ -294,14 +303,12 @@ VOID DrawCountryIcon(
294303

295304
typedef struct _PH_UPDATER_CONTEXT
296305
{
297-
BOOLEAN FixedWindowStyles;
298306
HWND DialogHandle;
299307
HICON IconSmallHandle;
300308
HICON IconLargeHandle;
309+
WNDPROC DefaultWindowProc;
301310

302311
PPH_STRING FileDownloadUrl;
303-
PPH_STRING RevVersion;
304-
PPH_STRING Size;
305312
} PH_UPDATER_CONTEXT, *PPH_UPDATER_CONTEXT;
306313

307314
VOID TaskDialogLinkClicked(

plugins/NetworkTools/pages.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ VOID ShowDbCheckForUpdatesDialog(
182182
config.pszMainInstruction = L"Download the latest GeoIP database?";
183183
config.pszContent = L"This product includes GeoLite2 data created by MaxMind, available from <a href=\"http://www.maxmind.com\">http://www.maxmind.com</a>\r\n\r\nSelect download to continue.";
184184

185-
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
185+
TaskDialogNavigatePage(Context->DialogHandle, &config);
186186
}
187187

188188
VOID ShowDbCheckingForUpdatesDialog(
@@ -204,7 +204,7 @@ VOID ShowDbCheckingForUpdatesDialog(
204204
config.pszMainInstruction = L"Downloading";
205205
config.pszContent = L"Downloaded: ~ of ~ (~%%)\r\nSpeed: ~/s";
206206

207-
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
207+
TaskDialogNavigatePage(Context->DialogHandle, &config);
208208
}
209209

210210
VOID ShowDbInstallRestartDialog(
@@ -228,7 +228,7 @@ VOID ShowDbInstallRestartDialog(
228228
config.pszMainInstruction = L"The GeoIP database has been installed";
229229
config.pszContent = L"You need to restart Process Hacker for the changes to take effect...";
230230

231-
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
231+
TaskDialogNavigatePage(Context->DialogHandle, &config);
232232
}
233233

234234
VOID ShowDbUpdateFailedDialog(
@@ -251,5 +251,5 @@ VOID ShowDbUpdateFailedDialog(
251251
config.pszMainInstruction = L"Error downloading GeoIP database.";
252252
config.pszContent = L"Click Retry to download the database again.";
253253

254-
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
255-
}
254+
TaskDialogNavigatePage(Context->DialogHandle, &config);
255+
}

plugins/NetworkTools/update.c

Lines changed: 99 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Process Hacker Network Tools -
33
* GeoIP database updater
44
*
5-
* Copyright (C) 2016 dmex
5+
* Copyright (C) 2016-2019 dmex
66
*
77
* This file is part of Process Hacker.
88
*
@@ -29,21 +29,36 @@
2929
HWND UpdateDialogHandle = NULL;
3030
HANDLE UpdateDialogThreadHandle = NULL;
3131
PH_EVENT InitializedEvent = PH_EVENT_INIT;
32+
PPH_OBJECT_TYPE UpdateContextType = NULL;
33+
PH_INITONCE UpdateContextTypeInitOnce = PH_INITONCE_INIT;
3234

33-
VOID FreeUpdateContext(
34-
_In_ _Post_invalid_ PPH_UPDATER_CONTEXT Context
35+
VOID UpdateContextDeleteProcedure(
36+
_In_ PVOID Object,
37+
_In_ ULONG Flags
3538
)
3639
{
37-
if (Context->FileDownloadUrl)
38-
PhDereferenceObject(Context->FileDownloadUrl);
40+
PPH_UPDATER_CONTEXT context = Object;
3941

40-
if (Context->RevVersion)
41-
PhDereferenceObject(Context->RevVersion);
42+
if (context->FileDownloadUrl)
43+
PhDereferenceObject(context->FileDownloadUrl);
44+
}
45+
46+
PPH_UPDATER_CONTEXT CreateUpdateContext(
47+
VOID
48+
)
49+
{
50+
PPH_UPDATER_CONTEXT context;
51+
52+
if (PhBeginInitOnce(&UpdateContextTypeInitOnce))
53+
{
54+
UpdateContextType = PhCreateObjectType(L"GeoIpContextObjectType", 0, UpdateContextDeleteProcedure);
55+
PhEndInitOnce(&UpdateContextTypeInitOnce);
56+
}
4257

43-
if (Context->Size)
44-
PhDereferenceObject(Context->Size);
58+
context = PhCreateObject(sizeof(PH_UPDATER_CONTEXT), UpdateContextType);
59+
memset(context, 0, sizeof(PH_UPDATER_CONTEXT));
4560

46-
PhDereferenceObject(Context);
61+
return context;
4762
}
4863

4964
VOID TaskDialogCreateIcons(
@@ -484,18 +499,68 @@ NTSTATUS GeoIPUpdateThread(
484499
{
485500
if (success)
486501
{
487-
ShowDbInstallRestartDialog(context);
502+
PostMessage(context->DialogHandle, PH_SHOWINSTALL, 0, 0);
488503
}
489504
else
490505
{
491-
ShowDbUpdateFailedDialog(context);
506+
PostMessage(context->DialogHandle, PH_SHOWERROR, 0, 0);
492507
}
493508
}
494509

495510
PhDereferenceObject(context);
496511
return STATUS_SUCCESS;
497512
}
498513

514+
LRESULT CALLBACK TaskDialogSubclassProc(
515+
_In_ HWND hwndDlg,
516+
_In_ UINT uMsg,
517+
_In_ WPARAM wParam,
518+
_In_ LPARAM lParam
519+
)
520+
{
521+
PPH_UPDATER_CONTEXT context;
522+
WNDPROC oldWndProc;
523+
524+
if (!(context = PhGetWindowContext(hwndDlg, UCHAR_MAX)))
525+
return 0;
526+
527+
oldWndProc = context->DefaultWindowProc;
528+
529+
switch (uMsg)
530+
{
531+
case WM_DESTROY:
532+
{
533+
SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
534+
PhRemoveWindowContext(hwndDlg, UCHAR_MAX);
535+
536+
PhUnregisterWindowCallback(hwndDlg);
537+
}
538+
break;
539+
case PH_SHOWDIALOG:
540+
{
541+
if (IsMinimized(hwndDlg))
542+
ShowWindow(hwndDlg, SW_RESTORE);
543+
else
544+
ShowWindow(hwndDlg, SW_SHOW);
545+
546+
SetForegroundWindow(hwndDlg);
547+
}
548+
break;
549+
case PH_SHOWINSTALL:
550+
{
551+
ShowDbInstallRestartDialog(context);
552+
}
553+
break;
554+
case PH_SHOWERROR:
555+
{
556+
ShowDbUpdateFailedDialog(context);
557+
}
558+
break;
559+
}
560+
561+
return CallWindowProc(oldWndProc, hwndDlg, uMsg, wParam, lParam);
562+
}
563+
499564
HRESULT CALLBACK TaskDialogBootstrapCallback(
500565
_In_ HWND hwndDlg,
501566
_In_ UINT uMsg,
@@ -518,6 +583,13 @@ HRESULT CALLBACK TaskDialogBootstrapCallback(
518583
// Create the Taskdialog icons
519584
TaskDialogCreateIcons(context);
520585

586+
PhRegisterWindowCallback(hwndDlg, PH_PLUGIN_WINDOW_EVENT_TYPE_TOPMOST, NULL);
587+
588+
// Subclass the Taskdialog.
589+
context->DefaultWindowProc = (WNDPROC)GetWindowLongPtr(hwndDlg, GWLP_WNDPROC);
590+
PhSetWindowContext(hwndDlg, UCHAR_MAX, context);
591+
SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (LONG_PTR)TaskDialogSubclassProc);
592+
521593
ShowDbCheckForUpdatesDialog(context);
522594
}
523595
break;
@@ -532,23 +604,21 @@ NTSTATUS GeoIPUpdateDialogThread(
532604
{
533605
PH_AUTO_POOL autoPool;
534606
PPH_UPDATER_CONTEXT context;
535-
INT result = 0;
536607
TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) };
537608

538609
PhInitializeAutoPool(&autoPool);
539610

540-
context = (PPH_UPDATER_CONTEXT)PhCreateAlloc(sizeof(PH_UPDATER_CONTEXT));
541-
memset(context, 0, sizeof(PH_UPDATER_CONTEXT));
611+
context = CreateUpdateContext();
542612

543613
config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED;
544614
config.pszContent = L"Initializing...";
545615
config.lpCallbackData = (LONG_PTR)context;
546616
config.pfCallback = TaskDialogBootstrapCallback;
547617
config.hwndParent = Parameter;
548618

549-
TaskDialogIndirect(&config, &result, NULL, NULL);
619+
TaskDialogIndirect(&config, NULL, NULL, NULL);
550620

551-
FreeUpdateContext(context);
621+
PhDereferenceObject(context);
552622
PhDeleteAutoPool(&autoPool);
553623

554624
return STATUS_SUCCESS;
@@ -601,5 +671,16 @@ VOID ShowGeoIPUpdateDialog(
601671
_In_opt_ HWND Parent
602672
)
603673
{
604-
PhCreateThread2(GeoIPUpdateDialogThread, Parent);
674+
if (!UpdateDialogThreadHandle)
675+
{
676+
if (!(UpdateDialogThreadHandle = PhCreateThread(0, GeoIPUpdateDialogThread, NULL)))
677+
{
678+
PhShowStatus(PhMainWndHandle, L"Unable to create the updater window.", 0, GetLastError());
679+
return;
680+
}
681+
682+
PhWaitForEvent(&InitializedEvent, NULL);
683+
}
684+
685+
PostMessage(UpdateDialogHandle, PH_SHOWDIALOG, 0, 0);
605686
}

0 commit comments

Comments
 (0)