BOOLEAN LastUpdateCheckExpired( VOID ) { ULONG64 lastUpdateTimeTicks = 0; LARGE_INTEGER currentUpdateTimeTicks; PPH_STRING lastUpdateTimeString; PhQuerySystemTime(¤tUpdateTimeTicks); lastUpdateTimeString = PhGetStringSetting(SETTING_NAME_LAST_CHECK); PhStringToInteger64(&lastUpdateTimeString->sr, 0, &lastUpdateTimeTicks); if (currentUpdateTimeTicks.QuadPart - lastUpdateTimeTicks >= 7 * PH_TICKS_PER_DAY) { PPH_STRING currentUpdateTimeString; currentUpdateTimeString = PhFormatUInt64(currentUpdateTimeTicks.QuadPart, FALSE); PhSetStringSetting2(SETTING_NAME_LAST_CHECK, ¤tUpdateTimeString->sr); PhDereferenceObject(currentUpdateTimeString); PhDereferenceObject(lastUpdateTimeString); return TRUE; } PhDereferenceObject(lastUpdateTimeString); return FALSE; }
static BOOLEAN LastUpdateCheckExpired( VOID ) { ULONG64 lastUpdateTimeTicks = 0; LARGE_INTEGER currentUpdateTimeTicks; PPH_STRING lastUpdateTimeString; // Get the last update check time lastUpdateTimeString = PhGetStringSetting(SETTING_NAME_LAST_CHECK); PhStringToInteger64(&lastUpdateTimeString->sr, 0, &lastUpdateTimeTicks); // Query the current time PhQuerySystemTime(¤tUpdateTimeTicks); // Check if the last update check was more than 7 days ago if (currentUpdateTimeTicks.QuadPart - lastUpdateTimeTicks >= 7 * PH_TICKS_PER_DAY) { PPH_STRING currentUpdateTimeString = PhFormatUInt64(currentUpdateTimeTicks.QuadPart, FALSE); // Save the current time PhSetStringSetting2(SETTING_NAME_LAST_CHECK, ¤tUpdateTimeString->sr); // Cleanup PhDereferenceObject(currentUpdateTimeString); PhDereferenceObject(lastUpdateTimeString); return TRUE; } // Cleanup PhDereferenceObject(lastUpdateTimeString); return FALSE; }
PPH_LOG_ENTRY PhpCreateLogEntry( _In_ UCHAR Type ) { PPH_LOG_ENTRY entry; entry = PhAllocate(sizeof(PH_LOG_ENTRY)); memset(entry, 0, sizeof(PH_LOG_ENTRY)); entry->Type = Type; PhQuerySystemTime(&entry->Time); return entry; }
PPH_STRING PhapGetRelativeTimeString( __in PLARGE_INTEGER Time ) { LARGE_INTEGER time; LARGE_INTEGER currentTime; SYSTEMTIME timeFields; PPH_STRING timeRelativeString; PPH_STRING timeString; time = *Time; PhQuerySystemTime(¤tTime); timeRelativeString = PHA_DEREFERENCE(PhFormatTimeSpanRelative(currentTime.QuadPart - time.QuadPart)); PhLargeIntegerToLocalSystemTime(&timeFields, &time); timeString = PhaFormatDateTime(&timeFields); return PhaFormatString(L"%s (%s)", timeRelativeString->Buffer, timeString->Buffer); }
VOID PhWritePhTextHeader( __inout PPH_FILE_STREAM FileStream ) { PPH_STRING version; LARGE_INTEGER time; SYSTEMTIME systemTime; PPH_STRING dateString; PPH_STRING timeString; PhWriteStringAsAnsiFileStream2(FileStream, L"Process Hacker "); if (version = PhGetPhVersion()) { PhWriteStringAsAnsiFileStream(FileStream, &version->sr); PhDereferenceObject(version); } PhWriteStringFormatFileStream(FileStream, L"\r\nWindows NT %u.%u", PhOsVersion.dwMajorVersion, PhOsVersion.dwMinorVersion); if (PhOsVersion.szCSDVersion[0] != 0) PhWriteStringFormatFileStream(FileStream, L" %s", PhOsVersion.szCSDVersion); #ifdef _M_IX86 PhWriteStringAsAnsiFileStream2(FileStream, L" (32-bit)"); #else PhWriteStringAsAnsiFileStream2(FileStream, L" (64-bit)"); #endif PhQuerySystemTime(&time); PhLargeIntegerToLocalSystemTime(&systemTime, &time); dateString = PhFormatDate(&systemTime, NULL); timeString = PhFormatTime(&systemTime, NULL); PhWriteStringFormatFileStream(FileStream, L"\r\n%s %s\r\n\r\n", dateString->Buffer, timeString->Buffer); PhDereferenceObject(dateString); PhDereferenceObject(timeString); }
VOID StatusBarUpdate( _In_ BOOLEAN ResetMaxWidths ) { static ULONG64 lastTickCount = 0; ULONG count; ULONG i; HDC hdc; BOOLEAN resetMaxWidths = FALSE; PPH_STRING text[MAX_STATUSBAR_ITEMS]; ULONG widths[MAX_STATUSBAR_ITEMS]; if (ProcessesUpdatedCount < 2) return; if (ResetMaxWidths) resetMaxWidths = TRUE; if (!StatusBarItemList || StatusBarItemList->Count == 0) { // The status bar doesn't cope well with 0 parts. widths[0] = -1; SendMessage(StatusBarHandle, SB_SETPARTS, 1, (LPARAM)widths); SendMessage(StatusBarHandle, SB_SETTEXT, 0, (LPARAM)L""); return; } hdc = GetDC(StatusBarHandle); SelectObject(hdc, (HFONT)SendMessage(StatusBarHandle, WM_GETFONT, 0, 0)); // Reset max. widths for Max. CPU Process and Max. I/O Process parts once in a while. { LARGE_INTEGER tickCount; PhQuerySystemTime(&tickCount); if (tickCount.QuadPart - lastTickCount >= 10 * PH_TICKS_PER_SEC) { resetMaxWidths = TRUE; lastTickCount = tickCount.QuadPart; } } count = 0; for (i = 0; i < StatusBarItemList->Count; i++) { SIZE size; ULONG width; PSTATUSBAR_ITEM statusItem; statusItem = StatusBarItemList->Items[i]; switch (statusItem->Id) { case ID_STATUS_CPUUSAGE: { text[count] = PhFormatString( L"CPU Usage: %.2f%%", (SystemStatistics.CpuKernelUsage + SystemStatistics.CpuUserUsage) * 100 ); } break; case ID_STATUS_COMMITCHARGE: { ULONG commitUsage = SystemStatistics.Performance->CommittedPages; FLOAT commitFraction = (FLOAT)commitUsage / SystemStatistics.Performance->CommitLimit * 100; text[count] = PhFormatString( L"Commit Charge: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(commitUsage, PAGE_SIZE), -1)->Buffer, commitFraction ); } break; case ID_STATUS_PHYSICALMEMORY: { ULONG physicalUsage = PhSystemBasicInformation.NumberOfPhysicalPages - SystemStatistics.Performance->AvailablePages; FLOAT physicalFraction = (FLOAT)physicalUsage / PhSystemBasicInformation.NumberOfPhysicalPages * 100; text[count] = PhFormatString( L"Physical Memory: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(physicalUsage, PAGE_SIZE), -1)->Buffer, physicalFraction ); } break; case ID_STATUS_FREEMEMORY: { ULONG physicalFree = SystemStatistics.Performance->AvailablePages; FLOAT physicalFreeFraction = (FLOAT)physicalFree / PhSystemBasicInformation.NumberOfPhysicalPages * 100; text[count] = PhFormatString( L"Free Memory: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(physicalFree, PAGE_SIZE), -1)->Buffer, physicalFreeFraction ); } break; case ID_STATUS_NUMBEROFPROCESSES: { text[count] = PhConcatStrings2( L"Processes: ", PhaFormatUInt64(SystemStatistics.NumberOfProcesses, TRUE)->Buffer ); } break; case ID_STATUS_NUMBEROFTHREADS: { text[count] = PhConcatStrings2( L"Threads: ", PhaFormatUInt64(SystemStatistics.NumberOfThreads, TRUE)->Buffer ); } break; case ID_STATUS_NUMBEROFHANDLES: { text[count] = PhConcatStrings2( L"Handles: ", PhaFormatUInt64(SystemStatistics.NumberOfHandles, TRUE)->Buffer ); } break; case ID_STATUS_IO_RO: { text[count] = PhConcatStrings2( L"I/O R+O: ", PhaFormatSize(SystemStatistics.IoReadDelta.Delta + SystemStatistics.IoOtherDelta.Delta, -1)->Buffer ); } break; case ID_STATUS_IO_W: { text[count] = PhConcatStrings2( L"I/O W: ", PhaFormatSize(SystemStatistics.IoWriteDelta.Delta, -1)->Buffer ); } break; case ID_STATUS_MAX_CPU_PROCESS: { PPH_PROCESS_ITEM processItem; if (SystemStatistics.MaxCpuProcessId && (processItem = PhReferenceProcessItem(SystemStatistics.MaxCpuProcessId))) { if (!PH_IS_FAKE_PROCESS_ID(processItem->ProcessId)) { text[count] = PhFormatString( L"%s (%lu): %.2f%%", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId), processItem->CpuUsage * 100 ); } else { text[count] = PhFormatString( L"%s: %.2f%%", processItem->ProcessName->Buffer, processItem->CpuUsage * 100 ); } PhDereferenceObject(processItem); } else { text[count] = PhCreateString(L"-"); } } break; case ID_STATUS_MAX_IO_PROCESS: { PPH_PROCESS_ITEM processItem; if (SystemStatistics.MaxIoProcessId && (processItem = PhReferenceProcessItem(SystemStatistics.MaxIoProcessId))) { if (!PH_IS_FAKE_PROCESS_ID(processItem->ProcessId)) { text[count] = PhFormatString( L"%s (%lu): %s", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId), PhaFormatSize(processItem->IoReadDelta.Delta + processItem->IoWriteDelta.Delta + processItem->IoOtherDelta.Delta, -1)->Buffer ); } else { text[count] = PhFormatString( L"%s: %s", processItem->ProcessName->Buffer, PhaFormatSize(processItem->IoReadDelta.Delta + processItem->IoWriteDelta.Delta + processItem->IoOtherDelta.Delta, -1)->Buffer ); } PhDereferenceObject(processItem); } else { text[count] = PhCreateString(L"-"); } } break; case ID_STATUS_NUMBEROFVISIBLEITEMS: { HWND tnHandle = NULL; tnHandle = GetCurrentTreeNewHandle(); if (tnHandle) { ULONG visibleCount = 0; visibleCount = TreeNew_GetFlatNodeCount(tnHandle); text[count] = PhFormatString( L"Visible: %lu", visibleCount ); } else { text[count] = PhCreateString( L"Visible: N/A" ); } } break; case ID_STATUS_NUMBEROFSELECTEDITEMS: { HWND tnHandle = NULL; tnHandle = GetCurrentTreeNewHandle(); if (tnHandle) { ULONG visibleCount = 0; ULONG selectedCount = 0; visibleCount = TreeNew_GetFlatNodeCount(tnHandle); for (ULONG i = 0; i < visibleCount; i++) { if (TreeNew_GetFlatNode(tnHandle, i)->Selected) selectedCount++; } text[count] = PhFormatString( L"Selected: %lu", selectedCount ); } else { text[count] = PhCreateString( L"Selected: N/A" ); } } break; case ID_STATUS_INTERVALSTATUS: { ULONG interval; interval = PhGetIntegerSetting(L"UpdateInterval"); if (UpdateAutomatically) { switch (interval) { case 500: text[count] = PhCreateString(L"Interval: Fast"); break; case 1000: text[count] = PhCreateString(L"Interval: Normal"); break; case 2000: text[count] = PhCreateString(L"Interval: Below Normal"); break; case 5000: text[count] = PhCreateString(L"Interval: Slow"); break; case 10000: text[count] = PhCreateString(L"Interval: Very Slow"); break; } } else { text[count] = PhCreateString(L"Interval: Paused"); } } break; } if (resetMaxWidths) StatusBarMaxWidths[count] = 0; if (!GetTextExtentPoint32(hdc, text[count]->Buffer, (ULONG)text[count]->Length / sizeof(WCHAR), &size)) size.cx = 200; if (count != 0) widths[count] = widths[count - 1]; else widths[count] = 0; width = size.cx + 10; if (width <= StatusBarMaxWidths[count]) { width = StatusBarMaxWidths[count]; } else { StatusBarMaxWidths[count] = width; } widths[count] += width; count++; } ReleaseDC(StatusBarHandle, hdc); SendMessage(StatusBarHandle, SB_SETPARTS, count, (LPARAM)widths); for (i = 0; i < count; i++) { SendMessage(StatusBarHandle, SB_SETTEXT, i, (LPARAM)text[i]->Buffer); PhDereferenceObject(text[i]); } }
NTSTATUS UpdateDownloadThread( _In_ PVOID Parameter ) { BOOLEAN downloadSuccess = FALSE; BOOLEAN hashSuccess = FALSE; BOOLEAN signatureSuccess = FALSE; HANDLE tempFileHandle = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING downloadHostPath = NULL; PPH_STRING downloadUrlPath = NULL; PUPDATER_HASH_CONTEXT hashContext = NULL; USHORT httpPort = 0; LARGE_INTEGER timeNow; LARGE_INTEGER timeStart; ULONG64 timeTicks = 0; ULONG64 timeBitsPerSecond = 0; PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)Parameter; SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Initializing download request..."); if (!PhHttpSocketParseUrl( context->SetupFileDownloadUrl, &downloadHostPath, &downloadUrlPath, &httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Create the local path string. context->SetupFilePath = UpdaterParseDownloadFileName(downloadUrlPath); if (PhIsNullOrEmptyString(context->SetupFilePath)) goto CleanupExit; // Create temporary output file. if (!NT_SUCCESS(PhCreateFileWin32( &tempFileHandle, PhGetString(context->SetupFilePath), FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Connecting..."); if (!PhHttpSocketCreate(&httpContext, NULL)) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, PhGetString(downloadHostPath), httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, PhGetString(downloadUrlPath), PH_HTTP_FLAG_REFRESH | (httpPort == PH_HTTP_DEFAULT_HTTPS_PORT ? PH_HTTP_FLAG_SECURE : 0) )) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Sending download request..."); if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Waiting for response..."); if (!PhHttpSocketEndRequest(httpContext)) { context->ErrorCode = GetLastError(); goto CleanupExit; } else { ULONG bytesDownloaded = 0; ULONG downloadedBytes = 0; ULONG contentLength = 0; PPH_STRING status; IO_STATUS_BLOCK isb; BYTE buffer[PAGE_SIZE]; status = PhFormatString(L"Downloading update %s...", PhGetStringOrEmpty(context->Version)); SendMessage(context->DialogHandle, TDM_SET_MARQUEE_PROGRESS_BAR, FALSE, 0); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)status->Buffer); PhDereferenceObject(status); if (!PhHttpSocketQueryHeaderUlong( httpContext, PH_HTTP_QUERY_CONTENT_LENGTH, &contentLength )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Initialize hash algorithm. if (!(hashContext = UpdaterInitializeHash())) goto CleanupExit; // Zero the buffer. memset(buffer, 0, PAGE_SIZE); // Start the clock. PhQuerySystemTime(&timeStart); // Download the data. while (PhHttpSocketReadData(httpContext, buffer, PAGE_SIZE, &bytesDownloaded)) { // If we get zero bytes, the file was uploaded or there was an error if (bytesDownloaded == 0) break; // If the dialog was closed, just cleanup and exit if (!UpdateDialogThreadHandle) goto CleanupExit; // Update the hash of bytes we downloaded. UpdaterUpdateHash(hashContext, buffer, bytesDownloaded); // Write the downloaded bytes to disk. if (!NT_SUCCESS(NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesDownloaded, NULL, NULL ))) { goto CleanupExit; } downloadedBytes += (DWORD)isb.Information; // Check the number of bytes written are the same we downloaded. if (bytesDownloaded != isb.Information) goto CleanupExit; // Query the current time PhQuerySystemTime(&timeNow); // Calculate the number of ticks timeTicks = (timeNow.QuadPart - timeStart.QuadPart) / PH_TICKS_PER_SEC; timeBitsPerSecond = downloadedBytes / __max(timeTicks, 1); // TODO: Update on timer callback. { FLOAT percent = ((FLOAT)downloadedBytes / contentLength * 100); PPH_STRING totalLength = PhFormatSize(contentLength, -1); PPH_STRING totalDownloaded = PhFormatSize(downloadedBytes, -1); PPH_STRING totalSpeed = PhFormatSize(timeBitsPerSecond, -1); PPH_STRING statusMessage = PhFormatString( L"Downloaded: %s of %s (%.0f%%)\r\nSpeed: %s/s", PhGetStringOrEmpty(totalDownloaded), PhGetStringOrEmpty(totalLength), percent, PhGetStringOrEmpty(totalSpeed) ); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_CONTENT, (LPARAM)statusMessage->Buffer); SendMessage(context->DialogHandle, TDM_SET_PROGRESS_BAR_POS, (WPARAM)percent, 0); PhDereferenceObject(statusMessage); PhDereferenceObject(totalSpeed); PhDereferenceObject(totalLength); PhDereferenceObject(totalDownloaded); } } if (UpdaterVerifyHash(hashContext, context->SetupFileHash)) { hashSuccess = TRUE; } if (UpdaterVerifySignature(hashContext, context->SetupFileSignature)) { signatureSuccess = TRUE; } if (hashSuccess && signatureSuccess) { downloadSuccess = TRUE; } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (hashContext) UpdaterDestroyHash(hashContext); if (tempFileHandle) NtClose(tempFileHandle); if (downloadHostPath) PhDereferenceObject(downloadHostPath); if (downloadUrlPath) PhDereferenceObject(downloadUrlPath); if (UpdateDialogThreadHandle) { if (downloadSuccess && hashSuccess && signatureSuccess) { ShowUpdateInstallDialog(context); } else if (downloadSuccess) { if (signatureSuccess) ShowUpdateFailedDialog(context, TRUE, FALSE); else if (hashSuccess) ShowUpdateFailedDialog(context, FALSE, TRUE); else ShowUpdateFailedDialog(context, FALSE, FALSE); } else { ShowUpdateFailedDialog(context, FALSE, FALSE); } } PhDereferenceObject(context); return STATUS_SUCCESS; }
static VOID DbgProcessLogMessageEntry( _Inout_ PPH_DBGEVENTS_CONTEXT Context, _In_ BOOLEAN GlobalEvents ) { NTSTATUS status; PDBWIN_PAGE_BUFFER debugMessageBuffer; PDEBUG_LOG_ENTRY entry = NULL; HANDLE processHandle = NULL; PPH_STRING fileName = NULL; HICON icon = NULL; debugMessageBuffer = GlobalEvents ? Context->GlobalDebugBuffer : Context->LocalDebugBuffer; entry = PhAllocate(sizeof(DEBUG_LOG_ENTRY)); memset(entry, 0, sizeof(DEBUG_LOG_ENTRY)); PhQuerySystemTime(&entry->Time); entry->ProcessId = UlongToHandle(debugMessageBuffer->ProcessId); entry->Message = PhConvertMultiByteToUtf16(debugMessageBuffer->Buffer); if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID) { status = PhGetProcessImageFileNameByProcessId(entry->ProcessId, &fileName); } else { if (NT_SUCCESS(status = PhOpenProcess(&processHandle, ProcessQueryAccess, entry->ProcessId))) { status = PhGetProcessImageFileName(processHandle, &fileName); NtClose(processHandle); } } if (!NT_SUCCESS(status)) fileName = PhGetKernelFileName(); PhSwapReference2(&fileName, PhGetFileName(fileName)); icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", TRUE); if (icon) { entry->ImageIndex = ImageList_AddIcon(Context->ListViewImageList, icon); DestroyIcon(icon); } entry->FilePath = fileName; entry->ProcessName = PhGetBaseName(fileName); // Drop event if it matches a filter for (ULONG i = 0; i < Context->ExcludeList->Count; i++) { PDBG_FILTER_TYPE filterEntry = Context->ExcludeList->Items[i]; if (filterEntry->Type == FilterByName) { if (PhEqualString(filterEntry->ProcessName, entry->ProcessName, TRUE)) { DbgFreeLogEntry(entry); return; } } else if (filterEntry->Type == FilterByPid) { if (filterEntry->ProcessId == entry->ProcessId) { DbgFreeLogEntry(entry); return; } } } DbgAddLogEntry(Context, entry); }