Beispiel #1
0
	//------------------------------------------------------------------------------------
	// TaskManager call this function on a different thread
	//------------------------------------------------------------------------------------
	core::Task* System::Do()
	{
		if (m_bAsyncUpdate == false)
			return NULL;

		AsyncUpdate();

		return this;

	} // Do
Beispiel #2
0
static NTSTATUS DownloadUpdateThreadStart(
    __in PVOID Parameter
    )
{
    PPH_STRING downloadUrlPath = NULL;
    HANDLE tempFileHandle = NULL;
    HINTERNET hInitialize = NULL, hConnection = NULL, hRequest = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HWND hwndDlg = (HWND)Parameter;

    Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), FALSE);
    SetDlgItemText(hwndDlg, IDC_STATUS, L"Initializing");

    // Reset the progress state on Vista and above.
    if (WindowsVersion > WINDOWS_XP)
        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0L);

    if (!ConnectionAvailable())
        return status;

    __try
    {
        // Get temp dir.
        WCHAR tempPathString[MAX_PATH];
        DWORD tempPathLength = GetTempPath(MAX_PATH, tempPathString);

        if (tempPathLength == 0 || tempPathLength > MAX_PATH)
        {
            LogEvent(hwndDlg, PhFormatString(L"CreateFile failed (%d)", GetLastError()));
            __leave;
        }

        // create the download path string.
        downloadUrlPath = PhFormatString(
            L"/projects/processhacker/files/processhacker2/processhacker-%u.%u-setup.exe/download?use_mirror=autoselect", /* ?use_mirror=waix" */
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Append the tempath to our string: %TEMP%processhacker-%u.%u-setup.exe
        // Example: C:\\Users\\dmex\\AppData\\Temp\\processhacker-2.10-setup.exe
        SetupFilePath = PhFormatString(
            L"%sprocesshacker-%u.%u-setup.exe",
            tempPathString,
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Create output file
        status = PhCreateFileWin32(
            &tempFileHandle,
            SetupFilePath->Buffer,
            FILE_GENERIC_READ | FILE_GENERIC_WRITE,
            FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OVERWRITE_IF,
            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
            );

        if (!NT_SUCCESS(status))
        {
            LogEvent(hwndDlg, PhFormatString(L"PhCreateFileWin32 failed (%s)", ((PPH_STRING)PHA_DEREFERENCE(PhGetNtMessage(status)))->Buffer));
            __leave;
        }

        {
            // Create a user agent string.
            PPH_STRING phVersion = PhGetPhVersion();
            PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer);

            // Initialize the wininet library.
            if (!(hInitialize = InternetOpen(
                userAgent->Buffer,
                INTERNET_OPEN_TYPE_PRECONFIG,
                NULL,
                NULL,
                0
                )))
            {
                LogEvent(hwndDlg, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError()));

                PhDereferenceObject(userAgent);
                PhDereferenceObject(phVersion);

                __leave;
            }

            PhDereferenceObject(userAgent);
            PhDereferenceObject(phVersion);
        }

        // Connect to the server.
        if (!(hConnection = InternetConnect(
            hInitialize,
            L"sourceforge.net",
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0)))
        {
            LogEvent(hwndDlg, PhFormatString(L"InternetConnect failed (%d)", GetLastError()));
            __leave;
        }

        // Open the HTTP request.
        if (!(hRequest = HttpOpenRequest(
            hConnection,
            NULL,
            downloadUrlPath->Buffer,
            NULL,
            NULL,
            NULL,
            INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RESYNCHRONIZE,
            0
            )))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpOpenRequest failed (%d)", GetLastError()));
            __leave;
        }

        SetDlgItemText(hwndDlg, IDC_STATUS, L"Connecting");

        // Send the HTTP request.
        if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError()));

            // Enable the 'Retry' button.
            Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
            SetDlgItemText(hwndDlg, IDC_DOWNLOAD, L"Retry");

            // Reset the state and let user retry the download.
            PhUpdaterState = Download;
        }
        else
        {
            BYTE hashBuffer[20]; 
            DWORD contentLengthSize = sizeof(DWORD);
            PH_HASH_CONTEXT hashContext;

            // Initialize hash algorithm.
            PhInitializeHash(&hashContext, Sha1HashAlgorithm);

            if (!HttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &contentLengthSize, 0))
            {
                // No content length...impossible to calculate % complete...
                // we can read the data, BUT in this instance Sourceforge always returns the content length
                // so instead we'll exit here instead of downloading the file.
                LogEvent(hwndDlg, PhFormatString(L"HttpQueryInfo failed (%d)", GetLastError()));
                __leave;
            }
            else
            {
                BYTE buffer[PAGE_SIZE];
                DWORD bytesRead = 0, startTick = 0;
                IO_STATUS_BLOCK isb;

                // Zero the buffer.
                ZeroMemory(buffer, PAGE_SIZE);

                // Reset the counters.
                bytesDownloaded = 0, timeTransferred = 0, LastUpdateTime = 0;
                IsUpdating = FALSE;

                // Start the clock.
                startTick = GetTickCount();
                timeTransferred = startTick;

                // Download the data.
                while (InternetReadFile(hRequest, buffer, PAGE_SIZE, &bytesRead))
                {
                    // If we get zero bytes, the file was uploaded or there was an error.
                    if (bytesRead == 0)
                        break;

                    // If window closed and thread handle was closed, just dispose and exit.
                    // (This also skips error checking/prompts and updating the disposed UI)
                    if (!DownloadThreadHandle)
                        __leave;

                    // Update the hash of bytes we downloaded.
                    PhUpdateHash(&hashContext, buffer, bytesRead);

                    // Write the downloaded bytes to disk.
                    status = NtWriteFile(
                        tempFileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &isb,
                        buffer,
                        bytesRead,
                        NULL,
                        NULL
                        );

                    if (!NT_SUCCESS(status))
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }

                    // Check dwBytesRead are the same dwBytesWritten length returned by WriteFile.
                    if (bytesRead != isb.Information)
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }
                                        
                    // Update our total bytes downloaded
                    PhAcquireQueuedLockExclusive(&Lock);
                    bytesDownloaded += (DWORD)isb.Information;
                    PhReleaseQueuedLockExclusive(&Lock);

                    AsyncUpdate();
                }

                // Check if we downloaded the entire file.
                assert(bytesDownloaded == contentLength);

                // Compute our hash result.
                if (PhFinalHash(&hashContext, &hashBuffer, 20, NULL))
                {
                    // Allocate our hash string, hex the final hash result in our hashBuffer.
                    PPH_STRING hexString = PhBufferToHexString(hashBuffer, 20);

                    if (PhEqualString(hexString, UpdateData.Hash, TRUE))
                    {
                        // If PH is not elevated, set the UAC shield for the install button as the setup requires elevation.
                        if (!PhElevated)
                            SendMessage(GetDlgItem(hwndDlg, IDC_DOWNLOAD), BCM_SETSHIELD, 0, TRUE);

                        // Set the download result, don't include hash status since it succeeded.
                        //SetDlgItemText(hwndDlg, IDC_STATUS, L"Download Complete");
                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Install");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash succeeded, set state as ready to install.
                        PhUpdaterState = Install;
                    }
                    else
                    {
                        if (WindowsVersion > WINDOWS_XP)
                            SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);

                        SetDlgItemText(hwndDlg, IDC_STATUS, L"Download complete, SHA1 Hash failed.");

                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash failed, reset state to downloading so user can redownload the file.
                        PhUpdaterState = Download;
                    }

                    PhDereferenceObject(hexString);
                }
                else
                {
                    //SetDlgItemText(hwndDlg, IDC_STATUS, L"PhFinalHash failed");

                    // Show fancy Red progressbar if hash failed on Vista and above.
                    if (WindowsVersion > WINDOWS_XP)
                        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);
                }
            }
        }

        status = STATUS_SUCCESS;
    }
    __finally
    {
        if (hInitialize)
        {
            InternetCloseHandle(hInitialize);
            hInitialize = NULL;
        }

        if (hConnection)
        {
            InternetCloseHandle(hConnection);
            hConnection = NULL;
        }

        if (hRequest)
        {
            InternetCloseHandle(hRequest);
            hRequest = NULL;
        }

        if (tempFileHandle)
        {
            NtClose(tempFileHandle);
            tempFileHandle = NULL;
        }

        if (downloadUrlPath)
        {
            PhDereferenceObject(downloadUrlPath);
            downloadUrlPath = NULL;
        }
    }

    return status;
}