26 static HANDLE UpdateDialogThreadHandle = NULL;
27 static HWND UpdateDialogHandle = NULL;
37 static BOOLEAN ParseVersionString(
42 ULONG64 majorInteger = 0, minorInteger = 0, revisionInteger = 0;
53 Context->MajorVersion = (ULONG)majorInteger;
54 Context->MinorVersion = (ULONG)minorInteger;
55 Context->RevisionVersion = (ULONG)revisionInteger;
63 static BOOLEAN ReadRequestString(
64 _In_ HINTERNET Handle,
65 _Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
66 _Out_ ULONG *DataLength
70 ULONG allocatedLength;
75 allocatedLength =
sizeof(buffer);
76 data = (PSTR)PhAllocate(allocatedLength);
82 while (WinHttpReadData(Handle, buffer,
PAGE_SIZE, &returnLength))
84 if (returnLength == 0)
87 if (allocatedLength < dataLength + returnLength)
90 data = (PSTR)PhReAllocate(data, allocatedLength);
94 memcpy(data + dataLength, buffer, returnLength);
98 dataLength += returnLength;
101 if (allocatedLength < dataLength + 1)
104 data = (PSTR)PhReAllocate(data, allocatedLength);
108 data[dataLength] = 0;
110 *DataLength = dataLength;
128 static VOID FreeUpdateContext(
135 Context->HaveData =
FALSE;
138 Context->MinorVersion = 0;
139 Context->MajorVersion = 0;
140 Context->RevisionVersion = 0;
141 Context->CurrentMinorVersion = 0;
142 Context->CurrentMajorVersion = 0;
143 Context->CurrentRevisionVersion = 0;
155 if (Context->FontHandle)
157 DeleteObject(Context->FontHandle);
158 Context->FontHandle = NULL;
161 if (Context->IconBitmap)
163 DeleteObject(Context->IconBitmap);
164 Context->IconBitmap = NULL;
167 if (Context->IconHandle)
169 DestroyIcon(Context->IconHandle);
170 Context->IconHandle = NULL;
176 static BOOLEAN QueryUpdateData(
180 BOOLEAN isSuccess =
FALSE;
181 HINTERNET httpSessionHandle = NULL;
182 HINTERNET httpConnectionHandle = NULL;
183 HINTERNET httpRequestHandle = NULL;
184 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
186 ULONG xmlStringBufferLength = 0;
187 PSTR xmlStringBuffer = NULL;
191 &Context->CurrentMajorVersion,
192 &Context->CurrentMinorVersion,
194 &Context->CurrentRevisionVersion
202 Context->CurrentMajorVersion,
203 Context->CurrentMinorVersion,
204 Context->CurrentRevisionVersion
210 WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
213 if (!(httpSessionHandle = WinHttpOpen(
214 Context->UserAgent->Buffer,
215 proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
216 proxyConfig.lpszProxy,
217 proxyConfig.lpszProxyBypass,
224 if (!(httpConnectionHandle = WinHttpConnect(
226 L
"processhacker.sourceforge.net",
227 INTERNET_DEFAULT_HTTP_PORT,
234 if (!(httpRequestHandle = WinHttpOpenRequest(
235 httpConnectionHandle,
240 WINHTTP_DEFAULT_ACCEPT_TYPES,
247 if (!WinHttpSendRequest(
249 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
250 WINHTTP_NO_REQUEST_DATA, 0,
251 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0
257 if (!WinHttpReceiveResponse(httpRequestHandle, NULL))
261 if (!ReadRequestString(httpRequestHandle, &xmlStringBuffer, &xmlStringBufferLength))
265 if (xmlStringBuffer == NULL || xmlStringBuffer[0] ==
'\0')
269 xmlNode =
mxmlLoadString(NULL, xmlStringBuffer, QueryXmlDataCallback);
322 if (!ParseVersionString(Context))
329 if (httpRequestHandle)
330 WinHttpCloseHandle(httpRequestHandle);
332 if (httpConnectionHandle)
333 WinHttpCloseHandle(httpConnectionHandle);
335 if (httpSessionHandle)
336 WinHttpCloseHandle(httpSessionHandle);
348 static NTSTATUS UpdateCheckSilentThread(
353 ULONGLONG currentVersion = 0;
354 ULONGLONG latestVersion = 0;
356 context = CreateUpdateContext();
360 if (!QueryUpdateData(context))
387 if (currentVersion < latestVersion)
392 if (!UpdateDialogHandle)
406 FreeUpdateContext(context);
409 return STATUS_SUCCESS;
412 static NTSTATUS UpdateCheckThread(
417 ULONGLONG currentVersion = 0;
418 ULONGLONG latestVersion = 0;
424 context->
HaveData = QueryUpdateData(context);
430 return STATUS_SUCCESS;
456 if (currentVersion == latestVersion)
461 else if (currentVersion > latestVersion)
472 return STATUS_SUCCESS;
475 static NTSTATUS UpdateDownloadThread(
479 BOOLEAN downloadSuccess =
FALSE;
480 BOOLEAN hashSuccess =
FALSE;
481 BOOLEAN verifySuccess =
FALSE;
482 HANDLE tempFileHandle = NULL;
483 HINTERNET httpSessionHandle = NULL;
484 HINTERNET httpConnectionHandle = NULL;
485 HINTERNET httpRequestHandle = NULL;
489 URL_COMPONENTS httpUrlComponents = {
sizeof(URL_COMPONENTS) };
490 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
497 setupTempPath =
PhCreateStringEx(NULL, GetTempPath(0, NULL) *
sizeof(WCHAR));
502 if (GetTempPath((ULONG)setupTempPath->
Length /
sizeof(WCHAR), setupTempPath->
Buffer) == 0)
510 L
"%sprocesshacker-%lu.%lu-setup.exe",
522 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
523 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY,
524 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
533 httpUrlComponents.dwSchemeLength = (ULONG)-1;
534 httpUrlComponents.dwHostNameLength = (ULONG)-1;
535 httpUrlComponents.dwUrlPathLength = (ULONG)-1;
537 if (!WinHttpCrackUrl(
549 httpUrlComponents.lpszHostName,
550 httpUrlComponents.dwHostNameLength *
sizeof(WCHAR)
557 httpUrlComponents.lpszUrlPath,
558 httpUrlComponents.dwUrlPathLength *
sizeof(WCHAR)
566 WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
569 if (!(httpSessionHandle = WinHttpOpen(
571 proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
572 proxyConfig.lpszProxy,
573 proxyConfig.lpszProxyBypass,
580 if (!(httpConnectionHandle = WinHttpConnect(
583 INTERNET_DEFAULT_HTTP_PORT,
590 if (!(httpRequestHandle = WinHttpOpenRequest(
591 httpConnectionHandle,
596 WINHTTP_DEFAULT_ACCEPT_TYPES,
605 if (!WinHttpSendRequest(
607 WINHTTP_NO_ADDITIONAL_HEADERS,
609 WINHTTP_NO_REQUEST_DATA,
611 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
620 if (WinHttpReceiveResponse(httpRequestHandle, NULL))
622 ULONG bytesDownloaded = 0;
623 ULONG downloadedBytes = 0;
624 ULONG contentLengthSize =
sizeof(ULONG);
625 ULONG contentLength = 0;
632 if (!WinHttpQueryHeaders(
634 WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
635 WINHTTP_HEADER_NAME_BY_INDEX,
651 while (WinHttpReadData(httpRequestHandle, buffer,
PAGE_SIZE, &bytesDownloaded))
654 if (bytesDownloaded == 0)
659 if (!UpdateDialogThreadHandle)
691 FLOAT percent = ((FLOAT)downloadedBytes / contentLength * 100);
696 L
"%s of %s (%.0f%%)",
703 SendMessage(context->
ProgressHandle, PBM_SETPOS, (ULONG)percent, 0);
713 if (
PhFinalHash(&hashContext, &hashBuffer, 20, NULL))
727 downloadSuccess =
TRUE;
732 NtClose(tempFileHandle);
734 if (httpRequestHandle)
735 WinHttpCloseHandle(httpRequestHandle);
737 if (httpConnectionHandle)
738 WinHttpCloseHandle(httpConnectionHandle);
740 if (httpSessionHandle)
741 WinHttpCloseHandle(httpSessionHandle);
750 verifySuccess =
TRUE;
753 if (downloadSuccess && hashSuccess && verifySuccess)
757 else if (downloadSuccess)
766 return STATUS_SUCCESS;
778 if (uMsg == WM_INITDIALOG)
781 SetProp(hwndDlg, L
"Context", (HANDLE)context);
787 if (uMsg == WM_NCDESTROY)
789 RemoveProp(hwndDlg, L
"Context");
790 FreeUpdateContext(context);
803 HWND parentWindow = GetParent(hwndDlg);
805 memset(&headerFont, 0,
sizeof(LOGFONT));
806 headerFont.lfHeight = -15;
807 headerFont.lfWeight = FW_MEDIUM;
808 headerFont.lfQuality = CLEARTYPE_QUALITY | ANTIALIASED_QUALITY;
815 context->
FontHandle = CreateFontIndirect(&headerFont);
819 GetModuleHandle(NULL),
820 MAKEINTRESOURCE(PHAPP_IDI_PROCESSHACKER),
831 SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)context->
IconHandle);
840 PhCenterWindow(hwndDlg, (IsWindowVisible(parentWindow) && !IsIconic(parentWindow)) ? parentWindow : NULL);
845 HANDLE updateCheckThread = NULL;
848 if (updateCheckThread =
PhCreateThread(0, UpdateCheckThread, context))
849 NtClose(updateCheckThread);
855 if (IsIconic(hwndDlg))
856 ShowWindow(hwndDlg, SW_RESTORE);
858 ShowWindow(hwndDlg, SW_SHOW);
860 SetForegroundWindow(hwndDlg);
865 case WM_CTLCOLORSTATIC:
867 HDC hDC = (HDC)wParam;
868 HWND hwndChild = (HWND)lParam;
873 SetTextColor(hDC, RGB(19, 112, 171));
877 SetBkMode(hDC, TRANSPARENT);
880 return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
885 switch (GET_WM_COMMAND_ID(wParam, lParam))
899 HANDLE updateCheckThread = NULL;
901 SetDlgItemText(hwndDlg,
IDC_MESSAGE, L
"Checking for new releases...");
905 if (updateCheckThread =
PhCreateThread(0, UpdateCheckThread, context))
906 NtClose(updateCheckThread);
913 HANDLE downloadThreadHandle = NULL;
919 SendDlgItemMessage(hwndDlg,
IDC_PROGRESS, PBM_SETPOS, 0, 0);
922 SendDlgItemMessage(hwndDlg,
IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0);
926 NtClose(downloadThreadHandle);
931 PhShellExecute(hwndDlg, L
"http://processhacker.sourceforge.net/downloads.php", NULL);
938 SHELLEXECUTEINFO info = {
sizeof(SHELLEXECUTEINFO) };
945 info.nShow = SW_SHOW;
950 if (!ShellExecuteEx(&info))
956 Button_SetText(GetDlgItem(hwndDlg,
IDC_DOWNLOAD), L
"Retry");
978 L
"Process Hacker %lu.%lu (r%lu)",
991 Button_SetText(GetDlgItem(hwndDlg,
IDC_DOWNLOAD), L
"Download");
1005 SetDlgItemText(hwndDlg,
IDC_MESSAGE, L
"You're running the latest version.");
1007 L
"Stable release build: v%lu.%lu (r%lu)",
1024 SetDlgItemText(hwndDlg,
IDC_MESSAGE, L
"You're running a newer version!");
1026 L
"SVN release build: v%lu.%lu (r%lu)",
1047 SetDlgItemText(hwndDlg,
IDC_STATUS, L
"Click Install to continue update...");
1050 Button_SetText(GetDlgItem(hwndDlg,
IDC_DOWNLOAD), L
"Install");
1060 SendDlgItemMessage(hwndDlg,
IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0);
1062 SetDlgItemText(hwndDlg,
IDC_MESSAGE, L
"Please check for updates again...");
1063 SetDlgItemText(hwndDlg,
IDC_RELDATE, L
"An error was encountered while checking for updates.");
1065 if ((BOOLEAN)wParam)
1066 SetDlgItemText(hwndDlg,
IDC_STATUS, L
"Hash check failed.");
1067 else if ((BOOLEAN)lParam)
1068 SetDlgItemText(hwndDlg,
IDC_STATUS, L
"Signature check failed.");
1071 Button_SetText(GetDlgItem(hwndDlg,
IDC_DOWNLOAD), L
"Retry");
1081 SetDlgItemText(hwndDlg,
IDC_MESSAGE, L
"Please check for updates again...");
1082 SetDlgItemText(hwndDlg,
IDC_RELDATE, L
"An error was encountered while checking for updates.");
1084 Button_SetText(GetDlgItem(hwndDlg,
IDC_DOWNLOAD), L
"Retry");
1090 switch (((LPNMHDR)lParam)->code)
1108 static NTSTATUS ShowUpdateDialogThread(
1109 _In_ PVOID Parameter
1120 context = CreateUpdateContext();
1124 UpdateDialogHandle = CreateDialogParam(
1134 while (result = GetMessage(&message, NULL, 0, 0))
1139 if (!IsDialogMessage(UpdateDialogHandle, &message))
1141 TranslateMessage(&message);
1142 DispatchMessage(&message);
1151 if (UpdateDialogHandle)
1153 DestroyWindow(UpdateDialogHandle);
1154 UpdateDialogHandle = NULL;
1157 if (UpdateDialogThreadHandle)
1159 NtClose(UpdateDialogThreadHandle);
1160 UpdateDialogThreadHandle = NULL;
1163 return STATUS_SUCCESS;
1170 if (!UpdateDialogThreadHandle)
1172 if (!(UpdateDialogThreadHandle =
PhCreateThread(0, ShowUpdateDialogThread, Context)))
1188 HANDLE silentCheckThread = NULL;
1190 if (silentCheckThread =
PhCreateThread(0, UpdateCheckSilentThread, NULL))
1191 NtClose(silentCheckThread);