dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/* $Id$ */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/** @file
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * VBoxStub - VirtualBox's Windows installer stub.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/*
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync * Copyright (C) 2010-2014 Oracle Corporation
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
78f327ee942771169c65c91baf789fd10e72b01avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
78f327ee942771169c65c91baf789fd10e72b01avboxsync * available from http://www.virtualbox.org. This file is free software;
78f327ee942771169c65c91baf789fd10e72b01avboxsync * you can redistribute it and/or modify it under the terms of the GNU
78f327ee942771169c65c91baf789fd10e72b01avboxsync * General Public License (GPL) as published by the Free Software
78f327ee942771169c65c91baf789fd10e72b01avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
78f327ee942771169c65c91baf789fd10e72b01avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
78f327ee942771169c65c91baf789fd10e72b01avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/*******************************************************************************
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync* Header Files *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync*******************************************************************************/
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0501
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# undef _WIN32_WINNT
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# define _WIN32_WINNT 0x0501 /* AttachConsole() / FreeConsole(). */
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync#endif
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#include <Windows.h>
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync#include <commctrl.h>
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync#include <fcntl.h>
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync#include <io.h>
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync#include <lmerr.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <msiquery.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <objbase.h>
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <shlobj.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <stdlib.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <stdio.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <string.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <strsafe.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <VBox/version.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/assert.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/dir.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/file.h>
0912cf29d2641459d225c40114c567a63273746cvboxsync#include <iprt/getopt.h>
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#include <iprt/initterm.h>
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#include <iprt/list.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/mem.h>
0912cf29d2641459d225c40114c567a63273746cvboxsync#include <iprt/message.h>
701a45600245e42829e1187817299e812eebdec5vboxsync#include <iprt/param.h>
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#include <iprt/path.h>
0912cf29d2641459d225c40114c567a63273746cvboxsync#include <iprt/stream.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/string.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/thread.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include "VBoxStub.h"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include "../StubBld/VBoxStubBld.h"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include "resource.h"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync# include "VBoxStubCertUtil.h"
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync# include "VBoxStubPublicCert.h"
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync#endif
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync#ifndef TARGET_NT4
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync/* Use an own console window if run in verbose mode. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync# define VBOX_STUB_WITH_OWN_CONSOLE
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync#endif
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/*******************************************************************************
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync* Defined Constants And Macros *
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync*******************************************************************************/
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#define MY_UNICODE_SUB(str) L ##str
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync#define MY_UNICODE(str) MY_UNICODE_SUB(str)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/*******************************************************************************
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync* Structures and Typedefs *
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync*******************************************************************************/
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/**
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * Cleanup record.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsynctypedef struct STUBCLEANUPREC
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync{
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /** List entry. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTLISTNODE ListEntry;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /** True if file, false if directory. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync bool fFile;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /** The path to the file or directory to clean up. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync char szPath[1];
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync} STUBCLEANUPREC;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/** Pointer to a cleanup record. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsynctypedef STUBCLEANUPREC *PSTUBCLEANUPREC;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync/*******************************************************************************
0912cf29d2641459d225c40114c567a63273746cvboxsync* Global Variables *
0912cf29d2641459d225c40114c567a63273746cvboxsync*******************************************************************************/
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/** Whether it's a silent or interactive GUI driven install. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic bool g_fSilent = false;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/** List of temporary files. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic RTLISTANCHOR g_TmpFiles;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync/** Verbosity flag. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsyncstatic int g_iVerbosity = 0;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Shows an error message box with a printf() style formatted string.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns RTEXITCODE_FAILURE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszFmt Printf-style format string to show in the message box body.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsyncstatic RTEXITCODE ShowError(const char *pszFmt, ...)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszMsg;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_list va;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_start(va, pszFmt);
0912cf29d2641459d225c40114c567a63273746cvboxsync if (RTStrAPrintfV(&pszMsg, pszFmt, va))
0912cf29d2641459d225c40114c567a63273746cvboxsync {
0912cf29d2641459d225c40114c567a63273746cvboxsync if (g_fSilent)
0912cf29d2641459d225c40114c567a63273746cvboxsync RTMsgError("%s", pszMsg);
0912cf29d2641459d225c40114c567a63273746cvboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PRTUTF16 pwszMsg;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc = RTStrToUtf16(pszMsg, &pwszMsg);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_SUCCESS(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MessageBoxW(GetDesktopWindow(), pwszMsg, MY_UNICODE(VBOX_STUB_TITLE), MB_ICONERROR);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTUtf16Free(pwszMsg);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MessageBoxA(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync RTStrFree(pszMsg);
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync else /* Should never happen! */
0912cf29d2641459d225c40114c567a63273746cvboxsync AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_end(va);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_FAILURE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Shows a message box with a printf() style formatted string.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param uType Type of the message box (see MSDN).
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszFmt Printf-style format string to show in the message box body.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsyncstatic void ShowInfo(const char *pszFmt, ...)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszMsg;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_list va;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_start(va, pszFmt);
0912cf29d2641459d225c40114c567a63273746cvboxsync int rc = RTStrAPrintfV(&pszMsg, pszFmt, va);
0912cf29d2641459d225c40114c567a63273746cvboxsync va_end(va);
0912cf29d2641459d225c40114c567a63273746cvboxsync if (rc >= 0)
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync {
0912cf29d2641459d225c40114c567a63273746cvboxsync if (g_fSilent)
0912cf29d2641459d225c40114c567a63273746cvboxsync RTPrintf("%s\n", pszMsg);
0912cf29d2641459d225c40114c567a63273746cvboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PRTUTF16 pwszMsg;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc = RTStrToUtf16(pszMsg, &pwszMsg);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_SUCCESS(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MessageBoxW(GetDesktopWindow(), pwszMsg, MY_UNICODE(VBOX_STUB_TITLE), MB_ICONINFORMATION);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTUtf16Free(pwszMsg);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MessageBoxA(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync else /* Should never happen! */
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt));
0912cf29d2641459d225c40114c567a63273746cvboxsync RTStrFree(pszMsg);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Finds the specified in the resource section of the executable.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns IPRT status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszDataName Name of resource to read.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param ppvResource Where to return the pointer to the data.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pdwSize Where to return the size of the data (if found).
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Optional.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic int FindData(const char *pszDataName, PVOID *ppvResource, DWORD *pdwSize)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync AssertReturn(pszDataName, VERR_INVALID_PARAMETER);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync HINSTANCE hInst = NULL; /* indicates the executable image */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync /* Find our resource. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PRTUTF16 pwszDataName;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc = RTStrToUtf16(pszDataName, &pwszDataName);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync AssertRCReturn(rc, rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync HRSRC hRsrc = FindResourceExW(hInst,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync (LPWSTR)RT_RCDATA,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync pwszDataName,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTUtf16Free(pwszDataName);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync AssertReturn(hRsrc, VERR_IO_GEN_FAILURE);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync /* Get resource size. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync DWORD cb = SizeofResource(hInst, hRsrc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync AssertReturn(cb > 0, VERR_NO_DATA);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (pdwSize)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync *pdwSize = cb;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync /* Get pointer to resource. */
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync HGLOBAL hData = LoadResource(hInst, hRsrc);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync AssertReturn(hData, VERR_IO_GEN_FAILURE);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync /* Lock resource. */
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync *ppvResource = LockResource(hData);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync AssertReturn(*ppvResource, VERR_IO_GEN_FAILURE);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync return VINF_SUCCESS;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Finds the header for the given package.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns Pointer to the package header on success. On failure NULL is
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * returned after ShowError has been invoked.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param iPackage The package number.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsyncstatic PVBOXSTUBPKG FindPackageHeader(unsigned iPackage)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync char szHeaderName[32];
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTStrPrintf(szHeaderName, sizeof(szHeaderName), "HDR_%02d", iPackage);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PVBOXSTUBPKG pPackage;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync int rc = FindData(szHeaderName, (PVOID *)&pPackage, NULL);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ShowError("Internal error: Could not find package header #%u: %Rrc", iPackage, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return NULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /** @todo validate it. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return pPackage;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync}
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Constructs a full temporary file path from the given parameters.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns iprt status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszTempPath The pure path to use for construction.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszTargetFileName The pure file name to use for construction.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param ppszTempFile Pointer to the constructed string. Must be freed
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * using RTStrFree().
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int GetTempFileAlloc(const char *pszTempPath,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync const char *pszTargetFileName,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char **ppszTempFile)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (RTStrAPrintf(ppszTempFile, "%s\\%s", pszTempPath, pszTargetFileName) >= 0)
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return VINF_SUCCESS;
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return VERR_NO_STR_MEMORY;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Extracts a built-in resource to disk.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns iprt status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszResourceName The resource name to extract.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszTempFile The full file path + name to extract the resource to.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int ExtractFile(const char *pszResourceName,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync const char *pszTempFile)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync int rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTFILE fh;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL bCreatedFile = FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync do
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(pszResourceName, ("Resource pointer invalid!\n"));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(pszTempFile, ("Temp file pointer invalid!"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Read the data of the built-in resource. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync PVOID pvData = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DWORD dwDataSize = 0;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = FindData(pszResourceName, &pvData, &dwDataSize);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(rc, ("Could not read resource data!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Create new (and replace an old) file. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = RTFileOpen(&fh, pszTempFile,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTFILE_O_CREATE_REPLACE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync | RTFILE_O_WRITE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync | RTFILE_O_DENY_NOT_DELETE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync | RTFILE_O_DENY_WRITE);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(rc, ("Could not open file for writing!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync bCreatedFile = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Write contents to new file. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync size_t cbWritten = 0;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = RTFileWrite(fh, pvData, dwDataSize, &cbWritten);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(rc, ("Could not open file for writing!\n"));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(dwDataSize == cbWritten, ("File was not extracted completely! Disk full?\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } while (0);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RTFileIsValid(fh))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTFileClose(fh);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_FAILURE(rc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (bCreatedFile)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTFileDelete(pszTempFile);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Extracts a built-in resource to disk.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns iprt status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszTempFile The full file path + name to extract the resource to.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int Extract(const PVBOXSTUBPKG pPackage,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync const char *pszTempFile)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return ExtractFile(pPackage->szResourceName,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync pszTempFile);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Detects whether we're running on a 32- or 64-bit platform and returns the result.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns TRUE if we're running on a 64-bit OS, FALSE if not.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic BOOL IsWow64(void)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL bIsWow64 = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (NULL != fnIsWow64Process)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Error in retrieving process type - assume that we're running on 32bit. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return bIsWow64;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Decides whether we need a specified package to handle or not.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @returns @c true if we need to handle the specified package, @c false if not.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic bool PackageIsNeeded(PVBOXSTUBPKG pPackage)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (pPackage->byArch == VBOXSTUBPKGARCH_ALL)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return true;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync VBOXSTUBPKGARCH enmArch = IsWow64() ? VBOXSTUBPKGARCH_AMD64 : VBOXSTUBPKGARCH_X86;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return pPackage->byArch == enmArch;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync}
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/**
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * Adds a cleanup record.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync *
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @returns Fully complained boolean success indicator.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @param pszPath The path to the file or directory to clean up.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @param fFile @c true if file, @c false if directory.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic bool AddCleanupRec(const char *pszPath, bool fFile)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync{
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync size_t cchPath = strlen(pszPath); Assert(cchPath > 0);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PSTUBCLEANUPREC pRec = (PSTUBCLEANUPREC)RTMemAlloc(RT_OFFSETOF(STUBCLEANUPREC, szPath[cchPath + 1]));
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (!pRec)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync ShowError("Out of memory!");
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return false;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync pRec->fFile = fFile;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync memcpy(pRec->szPath, pszPath, cchPath + 1);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTListPrepend(&g_TmpFiles, &pRec->ListEntry);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return true;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync}
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync/**
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * Cleans up all the extracted files and optionally removes the package
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * directory.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync *
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @param cPackages The number of packages.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * @param pszPkgDir The package directory, NULL if it shouldn't be
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * removed.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic void CleanUp(unsigned cPackages, const char *pszPkgDir)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync{
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync for (int i = 0; i < 5; i++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync bool fFinalTry = i == 4;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PSTUBCLEANUPREC pCur, pNext;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (pCur->fFile)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = RTFileDelete(pCur->szPath);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = RTDirRemoveRecursive(pCur->szPath, RTDIRRMREC_F_CONTENT_AND_DIR);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (rc == VERR_DIR_NOT_EMPTY && fFinalTry)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = VINF_SUCCESS;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = VINF_SUCCESS;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_SUCCESS(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTListNodeRemove(&pCur->ListEntry);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTMemFree(pCur);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync else if (fFinalTry)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (pCur->fFile)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync ShowError("Failed to delete temporary file '%s': %Rrc", pCur->szPath, rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync else
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync ShowError("Failed to delete temporary directory '%s': %Rrc", pCur->szPath, rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RTListIsEmpty(&g_TmpFiles) || fFinalTry)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (!pszPkgDir)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = RTDirRemove(pszPkgDir);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_SUCCESS(rc) || rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND || fFinalTry)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /* Delay a little and try again. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTThreadSleep(i == 0 ? 100 : 3000);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Processes an MSI package.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns Fully complained exit code.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pszMsi The path to the MSI to process.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pszMsiArgs Any additional installer (MSI) argument
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param fLogging Whether to enable installer logging.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic RTEXITCODE ProcessMsiPackage(const char *pszMsi, const char *pszMsiArgs, bool fLogging)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync int rc;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Set UI level.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync INSTALLUILEVEL enmDesiredUiLevel = g_fSilent ? INSTALLUILEVEL_NONE : INSTALLUILEVEL_FULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync INSTALLUILEVEL enmRet = MsiSetInternalUI(enmDesiredUiLevel, NULL);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (enmRet == INSTALLUILEVEL_NOCHANGE /* means error */)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Internal error: MsiSetInternalUI failed.");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Enable logging?
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (fLogging)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync char szLogFile[RTPATH_MAX];
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrCopy(szLogFile, sizeof(szLogFile), pszMsi);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_SUCCESS(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTPathStripFilename(szLogFile);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTPathAppend(szLogFile, sizeof(szLogFile), "VBoxInstallLog.txt");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Internal error: Filename path too long.");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PRTUTF16 pwszLogFile;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrToUtf16(szLogFile, &pwszLogFile);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("RTStrToUtf16 failed on '%s': %Rrc", szLogFile, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync UINT uLogLevel = MsiEnableLogW(INSTALLLOGMODE_VERBOSE,
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync pwszLogFile,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync INSTALLLOGATTRIBUTES_FLUSHEACHLINE);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTUtf16Free(pwszLogFile);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (uLogLevel != ERROR_SUCCESS)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("MsiEnableLogW failed");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Initialize the common controls (extended version). This is necessary to
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * run the actual .MSI installers with the new fancy visual control
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * styles (XP+). Also, an integrated manifest is required.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync INITCOMMONCONTROLSEX ccEx;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ccEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ccEx.dwICC = ICC_LINK_CLASS | ICC_LISTVIEW_CLASSES | ICC_PAGESCROLLER_CLASS |
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES |
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync InitCommonControlsEx(&ccEx); /* Ignore failure. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Convert both strings to UTF-16 and start the installation.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PRTUTF16 pwszMsi;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrToUtf16(pszMsi, &pwszMsi);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("RTStrToUtf16 failed on '%s': %Rrc", pszMsi, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PRTUTF16 pwszMsiArgs;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrToUtf16(pszMsiArgs, &pwszMsiArgs);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTUtf16Free(pwszMsi);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("RTStrToUtf16 failed on '%s': %Rrc", pszMsi, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync UINT uStatus = MsiInstallProductW(pwszMsi, pwszMsiArgs);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTUtf16Free(pwszMsi);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTUtf16Free(pwszMsiArgs);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (uStatus == ERROR_SUCCESS)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (uStatus == ERROR_SUCCESS_REBOOT_REQUIRED)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS; /* we currently don't indicate this */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Installation failed. Figure out what to say.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync switch (uStatus)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync case ERROR_INSTALL_USEREXIT:
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /* Don't say anything? */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync break;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync case ERROR_INSTALL_PACKAGE_VERSION:
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ShowError("This installation package cannot be installed by the Windows Installer service.\n"
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync "You must install a Windows service pack that contains a newer version of the Windows Installer service.");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync break;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync case ERROR_INSTALL_PLATFORM_UNSUPPORTED:
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ShowError("This installation package is not supported on this platform.");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync break;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync default:
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Try get windows to format the message.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync | FORMAT_MESSAGE_IGNORE_INSERTS
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync | FORMAT_MESSAGE_FROM_SYSTEM;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync HMODULE hModule = NULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (uStatus >= NERR_BASE && uStatus <= MAX_NERR)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync hModule = LoadLibraryExW(L"netmsg.dll",
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync NULL,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync LOAD_LIBRARY_AS_DATAFILE);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (hModule != NULL)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync PWSTR pwszMsg;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (FormatMessageW(dwFormatFlags,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync hModule, /* If NULL, load system stuff. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync uStatus,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync (PWSTR)&pwszMsg,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync 0,
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync NULL) > 0)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync ShowError("Installation failed! Error: %ls", pwszMsg);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync LocalFree(pwszMsg);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync else /* If text lookup failed, show at least the error number. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync ShowError("Installation failed! Error: %u", uStatus);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (hModule)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FreeLibrary(hModule);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync break;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_FAILURE;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync}
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Processes a package.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns Fully complained exit code.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param iPackage The package number.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pszPkgDir The package directory (aka extraction dir).
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pszMsiArgs Any additional installer (MSI) argument
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param fLogging Whether to enable installer logging.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsyncstatic RTEXITCODE ProcessPackage(unsigned iPackage, const char *pszPkgDir, const char *pszMsiArgs, bool fLogging)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Get the package header and check if it's needed.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PVBOXSTUBPKG pPackage = FindPackageHeader(iPackage);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (pPackage == NULL)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_FAILURE;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (!PackageIsNeeded(pPackage))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Deal with the file based on it's extension.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync char szPkgFile[RTPATH_MAX];
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc = RTPathJoin(szPkgFile, sizeof(szPkgFile), pszPkgDir, pPackage->szFileName);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_FAILURE(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return ShowError("Internal error: RTPathJoin failed: %Rrc", rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTPathChangeToDosSlashes(szPkgFile, true /* Force conversion. */); /* paranoia */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RTEXITCODE rcExit;
d1bb48754376874c3cc6b1091a6abec549663c0cvboxsync const char *pszSuff = RTPathSuffix(szPkgFile);
d1bb48754376874c3cc6b1091a6abec549663c0cvboxsync if (RTStrICmp(pszSuff, ".msi") == 0)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rcExit = ProcessMsiPackage(szPkgFile, pszMsiArgs, fLogging);
d1bb48754376874c3cc6b1091a6abec549663c0cvboxsync else if (RTStrICmp(pszSuff, ".cab") == 0)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rcExit = RTEXITCODE_SUCCESS; /* Ignore .cab files, they're generally referenced by other files. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync else
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rcExit = ShowError("Internal error: Do not know how to handle file '%s'.", pPackage->szFileName);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return rcExit;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync}
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Install the public certificate into TrustedPublishers so the installer won't
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * prompt the user during silent installs.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns Fully complained exit code.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsyncstatic RTEXITCODE InstallCertificate(void)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE,
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync "TrustedPublisher",
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync g_ab_VBoxStubPublicCert,
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync sizeof(g_ab_VBoxStubPublicCert)))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Failed to construct install certificate.");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync}
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#endif /* VBOX_WITH_CODE_SIGNING */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync/**
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Copies the "<exepath>.custom" directory to the extraction path if it exists.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * This is used by the MSI packages from the resource section.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @returns Fully complained exit code.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * @param pszDstDir The destination directory.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsyncstatic RTEXITCODE CopyCustomDir(const char *pszDstDir)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync char szSrcDir[RTPATH_MAX];
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync int rc = RTPathExecDir(szSrcDir, sizeof(szSrcDir));
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_SUCCESS(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = RTPathAppend(szSrcDir, sizeof(szSrcDir), ".custom");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Failed to construct '.custom' dir path: %Rrc", rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RTDirExists(szSrcDir))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Use SHFileOperation w/ FO_COPY to do the job. This API requires an
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * extra zero at the end of both source and destination paths.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync size_t cwc;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTUTF16 wszSrcDir[RTPATH_MAX + 1];
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PRTUTF16 pwszSrcDir = wszSrcDir;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrToUtf16Ex(szSrcDir, RTSTR_MAX, &pwszSrcDir, RTPATH_MAX, &cwc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("RTStrToUtf16Ex failed on '%s': %Rrc", szSrcDir, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync wszSrcDir[cwc] = '\0';
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTUTF16 wszDstDir[RTPATH_MAX + 1];
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PRTUTF16 pwszDstDir = wszSrcDir;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTStrToUtf16Ex(pszDstDir, RTSTR_MAX, &pwszDstDir, RTPATH_MAX, &cwc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("RTStrToUtf16Ex failed on '%s': %Rrc", pszDstDir, rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync wszDstDir[cwc] = '\0';
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync SHFILEOPSTRUCTW FileOp;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync RT_ZERO(FileOp); /* paranoia */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.hwnd = NULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.wFunc = FO_COPY;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.pFrom = wszSrcDir;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.pTo = wszDstDir;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.fFlags = FOF_SILENT
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync | FOF_NOCONFIRMATION
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync | FOF_NOCONFIRMMKDIR
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync | FOF_NOERRORUI;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.fAnyOperationsAborted = FALSE;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.hNameMappings = NULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync FileOp.lpszProgressTitle = NULL;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = SHFileOperationW(&FileOp);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (rc != 0) /* Not a Win32 status code! */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Copying the '.custom' dir failed: %#x", rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /*
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * Add a cleanup record for recursively deleting the destination
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * .custom directory. We should actually add this prior to calling
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * SHFileOperationW since it may partially succeed...
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync char *pszDstSubDir = RTPathJoinA(pszDstDir, ".custom");
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (!pszDstSubDir)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return ShowError("Out of memory!");
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync bool fRc = AddCleanupRec(pszDstSubDir, false /*fFile*/);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTStrFree(pszDstSubDir);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (!fRc)
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return RTEXITCODE_FAILURE;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsyncstatic RTEXITCODE ExtractFiles(unsigned cPackages, const char *pszDstDir, bool fExtractOnly, bool *pfCreatedExtractDir)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync{
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync int rc;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Make sure the directory exists.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync *pfCreatedExtractDir = false;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (!RTDirExists(pszDstDir))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync rc = RTDirCreate(pszDstDir, 0700, 0);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Failed to create extraction path '%s': %Rrc", pszDstDir, rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync *pfCreatedExtractDir = true;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /*
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync * Extract files.
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync for (unsigned k = 0; k < cPackages; k++)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PVBOXSTUBPKG pPackage = FindPackageHeader(k);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (!pPackage)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_FAILURE; /* Done complaining already. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (fExtractOnly || PackageIsNeeded(pPackage))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync char szDstFile[RTPATH_MAX];
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = RTPathJoin(szDstFile, sizeof(szDstFile), pszDstDir, pPackage->szFileName);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (RT_FAILURE(rc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return ShowError("Internal error: RTPathJoin failed: %Rrc", rc);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync rc = Extract(pPackage, szDstFile);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync if (RT_FAILURE(rc))
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return ShowError("Error extracting package #%u: %Rrc", k, rc);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync if (!fExtractOnly && !AddCleanupRec(szDstFile, true /*fFile*/))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync RTFileDelete(szDstFile);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync return RTEXITCODE_FAILURE;
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync return RTEXITCODE_SUCCESS;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncint WINAPI WinMain(HINSTANCE hInstance,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync HINSTANCE hPrevInstance,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *lpCmdLine,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync int nCmdShow)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync char **argv = __argv;
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync int argc = __argc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Check if we're already running and jump out if so. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */
0912cf29d2641459d225c40114c567a63273746cvboxsync HANDLE hMutexAppRunning = CreateMutex(NULL, FALSE, "VBoxStubInstaller");
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync if ( hMutexAppRunning != NULL
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync && GetLastError() == ERROR_ALREADY_EXISTS)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Close the mutex for this application instance. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync CloseHandle(hMutexAppRunning);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync hMutexAppRunning = NULL;
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync return RTEXITCODE_FAILURE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Init IPRT. */
230bd8589bba39933ac5ec21482d6186d675e604vboxsync int vrc = RTR3InitExe(argc, &argv, 0);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /* Close the mutex for this application instance. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync CloseHandle(hMutexAppRunning);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync hMutexAppRunning = NULL;
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync return RTMsgInitFailure(vrc);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /*
0912cf29d2641459d225c40114c567a63273746cvboxsync * Parse arguments.
0912cf29d2641459d225c40114c567a63273746cvboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /* Parameter variables. */
0912cf29d2641459d225c40114c567a63273746cvboxsync bool fExtractOnly = false;
0912cf29d2641459d225c40114c567a63273746cvboxsync bool fEnableLogging = false;
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync bool fEnableSilentCert = true;
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync#endif
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync char szExtractPath[RTPATH_MAX] = {0};
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync char szMSIArgs[_4K] = {0};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /* Parameter definitions. */
0912cf29d2641459d225c40114c567a63273746cvboxsync static const RTGETOPTDEF s_aOptions[] =
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync /** @todo Replace short parameters with enums since they're not
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync * used (and not documented to the public). */
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--extract", 'x', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-extract", 'x', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/extract", 'x', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--silent", 's', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-silent", 's', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/silent", 's', RTGETOPT_REQ_NOTHING },
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync { "--no-silent-cert", 'c', RTGETOPT_REQ_NOTHING },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync { "-no-silent-cert", 'c', RTGETOPT_REQ_NOTHING },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync { "/no-silent-cert", 'c', RTGETOPT_REQ_NOTHING },
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync#endif
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--logging", 'l', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-logging", 'l', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/logging", 'l', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--path", 'p', RTGETOPT_REQ_STRING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-path", 'p', RTGETOPT_REQ_STRING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/path", 'p', RTGETOPT_REQ_STRING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--msiparams", 'm', RTGETOPT_REQ_STRING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-msiparams", 'm', RTGETOPT_REQ_STRING },
c1e6c5ee6a408d7812315f2024903e1e2ca8064bvboxsync { "--reinstall", 'f', RTGETOPT_REQ_NOTHING },
c1e6c5ee6a408d7812315f2024903e1e2ca8064bvboxsync { "-reinstall", 'f', RTGETOPT_REQ_NOTHING },
c1e6c5ee6a408d7812315f2024903e1e2ca8064bvboxsync { "/reinstall", 'f', RTGETOPT_REQ_NOTHING },
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync { "-verbose", 'v', RTGETOPT_REQ_NOTHING },
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync { "/verbose", 'v', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--version", 'V', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-version", 'V', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/version", 'V', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-v", 'V', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "--help", 'h', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "-help", 'h', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/help", 'h', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync { "/?", 'h', RTGETOPT_REQ_NOTHING },
0912cf29d2641459d225c40114c567a63273746cvboxsync };
0912cf29d2641459d225c40114c567a63273746cvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /* Parse the parameters. */
0912cf29d2641459d225c40114c567a63273746cvboxsync int ch;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync bool fParsingDone = false;
0912cf29d2641459d225c40114c567a63273746cvboxsync RTGETOPTUNION ValueUnion;
0912cf29d2641459d225c40114c567a63273746cvboxsync RTGETOPTSTATE GetState;
0912cf29d2641459d225c40114c567a63273746cvboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync while ( (ch = RTGetOpt(&GetState, &ValueUnion))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync && rcExit == RTEXITCODE_SUCCESS
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync && !fParsingDone)
0912cf29d2641459d225c40114c567a63273746cvboxsync {
0912cf29d2641459d225c40114c567a63273746cvboxsync switch (ch)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync case 'f': /* Force re-installation. */
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync if (szMSIArgs[0])
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " ");
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync if (RT_SUCCESS(vrc))
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs),
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync "REINSTALLMODE=vomus REINSTALL=ALL");
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("MSI parameters are too long.");
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync break;
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'x':
0912cf29d2641459d225c40114c567a63273746cvboxsync fExtractOnly = true;
0912cf29d2641459d225c40114c567a63273746cvboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 's':
0912cf29d2641459d225c40114c567a63273746cvboxsync g_fSilent = true;
0912cf29d2641459d225c40114c567a63273746cvboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync case 'c':
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync fEnableSilentCert = false;
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync break;
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync#endif
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'l':
0912cf29d2641459d225c40114c567a63273746cvboxsync fEnableLogging = true;
0912cf29d2641459d225c40114c567a63273746cvboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'p':
0912cf29d2641459d225c40114c567a63273746cvboxsync vrc = RTStrCopy(szExtractPath, sizeof(szExtractPath), ValueUnion.psz);
0912cf29d2641459d225c40114c567a63273746cvboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("Extraction path is too long.");
0912cf29d2641459d225c40114c567a63273746cvboxsync break;
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'm':
0912cf29d2641459d225c40114c567a63273746cvboxsync if (szMSIArgs[0])
0912cf29d2641459d225c40114c567a63273746cvboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " ");
0912cf29d2641459d225c40114c567a63273746cvboxsync if (RT_SUCCESS(vrc))
0912cf29d2641459d225c40114c567a63273746cvboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz);
0912cf29d2641459d225c40114c567a63273746cvboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("MSI parameters are too long.");
0912cf29d2641459d225c40114c567a63273746cvboxsync break;
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'V':
0912cf29d2641459d225c40114c567a63273746cvboxsync ShowInfo("Version: %d.%d.%d.%d",
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD,
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync VBOX_SVN_REV);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync fParsingDone = true;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync break;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync case 'v':
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync g_iVerbosity++;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync break;
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync case 'h':
0912cf29d2641459d225c40114c567a63273746cvboxsync ShowInfo("-- %s v%d.%d.%d.%d --\n"
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync "\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "Command Line Parameters:\n\n"
0912cf29d2641459d225c40114c567a63273746cvboxsync "--extract - Extract file contents to temporary directory\n"
aa929735951456d7d4f09261e80d9e461724077bvboxsync "--help - Print this help and exit\n"
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync "--logging - Enables installer logging\n"
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync "--msiparams <parameters> - Specifies extra parameters for the MSI installers\n"
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync "--no-silent-cert - Do not install VirtualBox Certificate automatically when --silent option is specified\n"
0912cf29d2641459d225c40114c567a63273746cvboxsync "--path - Sets the path of the extraction directory\n"
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync "--reinstall - Forces VirtualBox to get re-installed\n"
935b743482f6f5b2a731d62322a75f9d111a3cb9vboxsync "--silent - Enables silent mode installation\n"
0912cf29d2641459d225c40114c567a63273746cvboxsync "--version - Print version number and exit\n\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "Examples:\n"
0912cf29d2641459d225c40114c567a63273746cvboxsync "%s --msiparams INSTALLDIR=C:\\VBox\n"
0912cf29d2641459d225c40114c567a63273746cvboxsync "%s --extract -path C:\\VBox",
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync VBOX_STUB_TITLE, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV,
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync argv[0], argv[0]);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync fParsingDone = true;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync break;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync case VINF_GETOPT_NOT_OPTION:
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /* Are (optional) MSI parameters specified and this is the last
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * parameter? Append everything to the MSI parameter list then. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (szMSIArgs[0])
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " ");
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_SUCCESS(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("MSI parameters are too long.");
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync continue;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /* Fall through is intentional. */
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync default:
0912cf29d2641459d225c40114c567a63273746cvboxsync if (g_fSilent)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = RTGetOptPrintError(ch, &ValueUnion);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (ch == VERR_GETOPT_UNKNOWN_OPTION)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("Unknown option \"%s\"\n"
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync "Please refer to the command line help by specifying \"/?\"\n"
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync "to get more information.", ValueUnion.psz);
0912cf29d2641459d225c40114c567a63273746cvboxsync else
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("Parameter parsing error: %Rrc\n"
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync "Please refer to the command line help by specifying \"/?\"\n"
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync "to get more information.", ch);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (rcExit != RTEXITCODE_SUCCESS)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = VERR_PARSE_ERROR;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# ifdef VBOX_STUB_WITH_OWN_CONSOLE /* Use an own console window if run in debug mode. */
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync if ( RT_SUCCESS(vrc)
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync && g_iVerbosity)
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync {
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync if (!AllocConsole())
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync {
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync DWORD dwErr = GetLastError();
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync ShowError("Unable to allocate console, error = %ld\n",
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync dwErr);
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync /* Close the mutex for this application instance. */
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync CloseHandle(hMutexAppRunning);
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync hMutexAppRunning = NULL;
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync return RTEXITCODE_FAILURE;
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync }
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync freopen("CONOUT$", "w", stdout);
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync setvbuf(stdout, NULL, _IONBF, 0);
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync freopen("CONOUT$", "w", stderr);
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync }
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# endif /* VBOX_STUB_WITH_OWN_CONSOLE */
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync#endif
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if ( RT_SUCCESS(vrc)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync && g_iVerbosity)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTPrintf("Silent installation : %RTbool\n", g_fSilent);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTPrintf("Logging enabled : %RTbool\n", fEnableLogging);
290a0363e80cdea1609d56d5b16faba63e4fda57vboxsync#ifdef VBOX_WITH_CODE_SIGNING
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTPrintf("Certificate installation : %RTbool\n", fEnableSilentCert);
290a0363e80cdea1609d56d5b16faba63e4fda57vboxsync#endif
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTPrintf("Additional MSI parameters: %s\n",
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync szMSIArgs[0] ? szMSIArgs : "<None>");
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_SUCCESS(vrc))
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /*
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * Determine the extration path if not given by the user, and gather some
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * other bits we'll be needing later.
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (szExtractPath[0] == '\0')
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath));
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_SUCCESS(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = RTPathAppend(szExtractPath, sizeof(szExtractPath), "VirtualBox");
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync ShowError("Failed to determine extraction path (%Rrc)", vrc);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync else
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /** @todo should check if there is a .custom subdirectory there or not. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTPathChangeToDosSlashes(szExtractPath,
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync true /* Force conversion. */); /* MSI requirement. */
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync /* Read our manifest. */
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync PVBOXSTUBPKGHEADER pHeader;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_SUCCESS(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync vrc = FindData("MANIFEST", (PVOID *)&pHeader, NULL);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_FAILURE(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ShowError("Internal package error: Manifest not found (%Rrc)", vrc);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (RT_SUCCESS(vrc))
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /** @todo If we could, we should validate the header. Only the magic isn't
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * commonly defined, nor the version number... */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTListInit(&g_TmpFiles);
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /*
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * Up to this point, we haven't done anything that requires any cleanup.
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync * From here on, we do everything in function so we can counter clean up.
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync bool fCreatedExtractDir;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ExtractFiles(pHeader->byCntPkgs, szExtractPath,
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync fExtractOnly, &fCreatedExtractDir);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (rcExit == RTEXITCODE_SUCCESS)
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (fExtractOnly)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync ShowInfo("Files were extracted to: %s", szExtractPath);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync else
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = CopyCustomDir(szExtractPath);
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#ifdef VBOX_WITH_CODE_SIGNING
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync if (rcExit == RTEXITCODE_SUCCESS && fEnableSilentCert && g_fSilent)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = InstallCertificate();
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync#endif
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync unsigned iPackage = 0;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync while ( iPackage < pHeader->byCntPkgs
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync && rcExit == RTEXITCODE_SUCCESS)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync rcExit = ProcessPackage(iPackage, szExtractPath,
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync szMSIArgs, fEnableLogging);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync iPackage++;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /* Don't fail if cleanup fail. At least for now. */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync CleanUp(pHeader->byCntPkgs,
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync !fEnableLogging
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync && fCreatedExtractDir ? szExtractPath : NULL);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync }
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync /* Free any left behind cleanup records (not strictly needed). */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync PSTUBCLEANUPREC pCur, pNext;
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry)
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync {
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTListNodeRemove(&pCur->ListEntry);
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync RTMemFree(pCur);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
15fb3f6d968fd393475b33b09311294a23959b0fvboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# ifdef VBOX_STUB_WITH_OWN_CONSOLE
75d2ded9de5cfe8db87f8e0d40bff05da8e91c27vboxsync if (g_iVerbosity)
75d2ded9de5cfe8db87f8e0d40bff05da8e91c27vboxsync FreeConsole();
f9bf78a22f6a21de513febdca5af9ced238d1867vboxsync# endif /* VBOX_STUB_WITH_OWN_CONSOLE */
0b13ce7f75e6d378e896f340cb4197a0fbc07cbfvboxsync#endif
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync /*
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync * Release instance mutex.
98242607fbc6f6f99815fbec709e38e73e7f9583vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (hMutexAppRunning != NULL)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync CloseHandle(hMutexAppRunning);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync hMutexAppRunning = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync return rcExit;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync