Beispiel #1
0
DWORD WINAPI InstallerThread(LPVOID data)
{
    gGlobalData.success = false;

    if (!CreateInstallationDirectory())
        goto Error;
    ProgressStep();

    if (!InstallCopyFiles())
        goto Error;

    if (gGlobalData.registerAsDefault) {
        // need to sublaunch SumatraPDF.exe instead of replicating the code
        // because registration uses translated strings
        ScopedMem<WCHAR> installedExePath(GetInstalledExePath());
        CreateProcessHelper(installedExePath, L"-register-for-pdf");
    }

    if (gGlobalData.installBrowserPlugin)
        InstallBrowserPlugin();
    else if (IsBrowserPluginInstalled())
        UninstallBrowserPlugin();

    if (gGlobalData.installPdfFilter)
        InstallPdfFilter();
    else if (IsPdfFilterInstalled())
        UninstallPdfFilter();

    if (gGlobalData.installPdfPreviewer)
        InstallPdfPreviewer();
    else if (IsPdfPreviewerInstalled())
        UninstallPdfPreviewer();

    if (!CreateAppShortcut(true) && !CreateAppShortcut(false)) {
        NotifyFailed(_TR("Failed to create a shortcut"));
        goto Error;
    }

    // consider installation a success from here on
    // (still warn, if we've failed to create the uninstaller, though)
    gGlobalData.success = true;

    if (!WriteUninstallerRegistryInfo(HKEY_LOCAL_MACHINE) &&
        !WriteUninstallerRegistryInfo(HKEY_CURRENT_USER)) {
        NotifyFailed(_TR("Failed to write the uninstallation information to the registry"));
    }
    if (!WriteExtendedFileExtensionInfo(HKEY_LOCAL_MACHINE) &&
        !WriteExtendedFileExtensionInfo(HKEY_CURRENT_USER)) {
        NotifyFailed(_TR("Failed to write the extended file extension information to the registry"));
    }
    ProgressStep();

Error:
    // TODO: roll back installation on failure (restore previous installation!)
    if (gHwndFrame && !gGlobalData.silent) {
        Sleep(500); // allow a glimpse of the completed progress bar before hiding it
        PostMessage(gHwndFrame, WM_APP_INSTALLATION_FINISHED, 0, 0);
    }
    return 0;
}
Beispiel #2
0
DWORD WINAPI UninstallerThread(LPVOID data)
{
    // also kill the original uninstaller, if it's just spawned
    // a DELETE_ON_CLOSE copy from the temp directory
    WCHAR *exePath = GetUninstallerPath();
    if (!path::IsSame(exePath, GetOwnPath()))
        KillProcess(exePath, TRUE);
    free(exePath);

    if (!RemoveUninstallerRegistryInfo(HKEY_LOCAL_MACHINE) &&
        !RemoveUninstallerRegistryInfo(HKEY_CURRENT_USER)) {
        NotifyFailed(L"Failed to delete uninstaller registry keys");
    }

    if (!RemoveShortcut(true) && !RemoveShortcut(false))
        NotifyFailed(L"Couldn't remove the shortcut");

    UninstallBrowserPlugin();
    UninstallPdfFilter();
    UninstallPdfPreviewer();
    RemoveOwnRegistryKeys();

    if (!RemoveInstalledFiles())
        NotifyFailed(L"Couldn't remove installation directory");

    // always succeed, even for partial uninstallations
    gGlobalData.success = true;

    if (!gGlobalData.silent)
        PostMessage(gHwndFrame, WM_APP_INSTALLATION_FINISHED, 0, 0);
    return 0;
}
Beispiel #3
0
// Try harder getting temporary directory
// Caller needs to free() the result.
// Returns NULL if fails for any reason.
static WCHAR *GetValidTempDir()
{
    ScopedMem<WCHAR> d(path::GetTempPath());
    if (!d) {
        NotifyFailed(_TR("Couldn't obtain temporary directory"));
        return NULL;
    }
    bool ok = dir::Create(d);
    if (!ok) {
        LogLastError();
        NotifyFailed(_TR("Couldn't create temporary directory"));
        return NULL;
    }
    return d.StealData();
}
Beispiel #4
0
static bool InstallCopyFiles()
{
    bool ok;
    HGLOBAL res = 0;
    HRSRC resSrc = FindResource(GetModuleHandle(nullptr), MAKEINTRESOURCE(1), RT_RCDATA);
    if (!resSrc)
        goto Corrupted;
    res = LoadResource(nullptr, resSrc);
    if (!res)
        goto Corrupted;

    const char *data = (const char*)LockResource(res);
    DWORD dataSize = SizeofResource(nullptr, resSrc);

    lzma::SimpleArchive archive;
    ok = lzma::ParseSimpleArchive(data, dataSize, &archive);
    if (!ok)
        goto Corrupted;

    // on error, ExtractFiles() shows error message itself
    ok = ExtractFiles(&archive);
Exit:
    UnlockResource(res);
    return ok;
Corrupted:
    NotifyFailed(_TR("The installer has been corrupted. Please download it again.\nSorry for the inconvenience!"));
    ok = false;
    goto Exit;
}
Beispiel #5
0
// If this is uninstaller and we're running from installation directory,
// copy uninstaller to temp directory and execute from there, exiting
// ourselves. This is needed so that uninstaller can delete itself
// from installation directory and remove installation directory
// If returns TRUE, this is an installer and we sublaunched ourselves,
// so the caller needs to exit
bool ExecuteUninstallerFromTempDir()
{
    // only need to sublaunch if running from installation dir
    ScopedMem<WCHAR> ownDir(path::GetDir(GetOwnPath()));
    ScopedMem<WCHAR> tempPath(GetTempUninstallerPath());

    // no temp directory available?
    if (!tempPath)
        return false;

    // not running from the installation directory?
    // (likely a test uninstaller that shouldn't be removed anyway)
    if (!path::IsSame(ownDir, gGlobalData.installDir))
        return false;

    // already running from temp directory?
    if (path::IsSame(GetOwnPath(), tempPath))
        return false;

    if (!CopyFile(GetOwnPath(), tempPath, FALSE)) {
        NotifyFailed(L"Failed to copy uninstaller to temp directory");
        return false;
    }

    ScopedMem<WCHAR> args(str::Format(L"/d \"%s\" %s", gGlobalData.installDir, gGlobalData.silent ? L"/s" : L""));
    bool ok = CreateProcessHelper(tempPath, args);

    // mark the uninstaller for removal at shutdown (note: works only for administrators)
    MoveFileEx(tempPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);

    return ok;
}
Beispiel #6
0
// Try harder getting temporary directory
// Caller needs to free() the result.
// Returns NULL if fails for any reason.
static WCHAR *GetValidTempDir()
{
    WCHAR d[MAX_PATH];
    DWORD res = GetTempPath(dimof(d), d);
    if ((0 == res) || (res >= MAX_PATH)) {
        NotifyFailed(L"Couldn't obtain temporary directory");
        return NULL;
    }
    BOOL success = CreateDirectory(d, NULL);
    if (!success && (ERROR_ALREADY_EXISTS != GetLastError())) {
        LogLastError();
        NotifyFailed(L"Couldn't create temporary directory");
        return NULL;
    }
    return str::Dup(d);
}
Beispiel #7
0
static bool CreateInstallationDirectory()
{
    bool ok = dir::CreateAll(gGlobalData.installDir);
    if (!ok) {
        LogLastError();
        NotifyFailed(_TR("Couldn't create the installation directory"));
    }
    return ok;
}
Beispiel #8
0
void
Downloader::StoppedHandler (HttpRequest *sender, HttpRequestStoppedEventArgs *args)
{
	SetFilename (sender->GetFilename ());
	if (args->IsSuccess ()) {
		NotifyFinished ();
	} else {
		NotifyFailed (args->GetErrorMessage ());
	}
}
Beispiel #9
0
static bool ExtractFiles(lzma::SimpleArchive *archive)
{
    lzma::FileInfo *fi;
    char *uncompressed;

    FileTransaction trans;
    for (int i = 0; gPayloadData[i].fileName; i++) {
        if (!gPayloadData[i].install)
            continue;
        int idx = lzma::GetIdxFromName(archive, gPayloadData[i].fileName);
        if (-1 == idx) {
            NotifyFailed(_TR("Some files to be installed are damaged or missing"));
            return false;
        }

        fi = &archive->files[idx];
        uncompressed = lzma::GetFileDataByIdx(archive, idx, nullptr);
        if (!uncompressed) {
            NotifyFailed(_TR("The installer has been corrupted. Please download it again.\nSorry for the inconvenience!"));
            return false;
        }
        ScopedMem<WCHAR> filePath(str::conv::FromUtf8(fi->name));
        ScopedMem<WCHAR> extPath(path::Join(gGlobalData.installDir, filePath));
        bool ok = trans.WriteAll(extPath, uncompressed, fi->uncompressedSize);
        free(uncompressed);
        if (!ok) {
            ScopedMem<WCHAR> msg(str::Format(_TR("Couldn't write %s to disk"), filePath));
            NotifyFailed(msg);
            return false;
        }
        trans.SetModificationTime(extPath, fi->ftModified);

        ProgressStep();
    }

    return trans.Commit();
}
Beispiel #10
0
static bool InstallCopyFiles()
{
    // extract all payload files one by one (transacted, if possible)
    ZipFile archive(GetOwnPath());
    FileTransaction trans;

    for (int i = 0; gPayloadData[i].filepath; i++) {
        // skip files that are only uninstalled
        if (!gPayloadData[i].install)
            continue;
        ScopedMem<WCHAR> filepathT(str::conv::FromUtf8(gPayloadData[i].filepath));

        size_t size;
        ScopedMem<char> data(archive.GetFileData(filepathT, &size));
        if (!data) {
            NotifyFailed(L"Some files to be installed are damaged or missing");
            return false;
        }

        ScopedMem<WCHAR> extpath(path::Join(gGlobalData.installDir, path::GetBaseName(filepathT)));
        bool ok = trans.WriteAll(extpath, data, size);
        if (!ok) {
            ScopedMem<WCHAR> msg(str::Format(L"Couldn't write %s to disk", filepathT));
            NotifyFailed(msg);
            return false;
        }

        // set modification time to original value
        FILETIME ftModified = archive.GetFileTime(filepathT);
        trans.SetModificationTime(extpath, ftModified);

        ProgressStep();
    }

    return trans.Commit();
}
Beispiel #11
0
static bool InstallCopyFiles()
{
    FileInfo fileInfos[32];

    HRSRC resSrc = FindResource(ghinst, MAKEINTRESOURCE(1), RT_RCDATA);
    CrashIf(!resSrc);
    HGLOBAL res = LoadResource(NULL, resSrc);
    CrashIf(!res);
    const uint8_t *data = (const uint8_t*)LockResource(res);
    DWORD dataSize = SizeofResource(NULL, resSrc);

    // extract all payload files one by one (transacted, if possible)
    FileTransaction trans;

    const int32_t *idata = (const int32_t*)data;
    int32_t fileCount = *idata++;
    CrashIf(fileCount >= dimof(fileInfos));
    int32_t off = 0;
    for (int32_t i = 0; i < fileCount; i++) {
        fileInfos[i].off = off;
        fileInfos[i].sizeUncompressed = *idata++;
        fileInfos[i].sizeCompressed = *idata++;
        off += fileInfos[i].sizeCompressed;
        data = (const uint8_t*)idata;
        fileInfos[i].name = (const char*)data;
        while (*data) {
            ++data;
        }
        ++data;
        idata = (const int32_t*)data;
    }

    uint8_t *dst;
    for (int32_t i = 0; i < fileCount; i++) {
        ScopedMem<WCHAR> filepathT(str::conv::FromUtf8(fileInfos[i].name));
        int32_t srcLen = fileInfos[i].sizeCompressed;
        off = fileInfos[i].off;
        const uint8_t *src = data + off;
        unsigned dstLen;
        dst = decodeLZMA((uint8_t*)src, (unsigned)srcLen, &dstLen);
        CrashIf(dstLen != (unsigned)fileInfos[i].sizeUncompressed);
        ScopedMem<WCHAR> extpath(path::Join(gGlobalData.installDir, path::GetBaseName(filepathT)));
        bool ok = trans.WriteAll(extpath, dst, dstLen);
        if (!ok) {
            ScopedMem<WCHAR> msg(str::Format(_TR("Couldn't write %s to disk"), filepathT));
            NotifyFailed(msg);
            goto Error;
        }
        free(dst);

        // set modification time to original value
        //FILETIME ftModified = archive.GetFileTime(filepathT);
        //trans.SetModificationTime(extpath, ftModified);

        ProgressStep();
    }

    UnlockResource(res);
    return trans.Commit();
Error:
    UnlockResource(res);
    return false;
}