VBoxStub.cpp revision 2c872d5e527386b5202fb36f281a391aecd82c5f
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/* $Id$ */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/** @file
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * VBoxStub - VirtualBox's Windows installer stub.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/*
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Copyright (C) 2010 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*******************************************************************************/
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <windows.h>
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync#include <lmerr.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <msiquery.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <objbase.h>
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>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/initterm.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/mem.h>
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#include <iprt/path.h>
701a45600245e42829e1187817299e812eebdec5vboxsync#include <iprt/param.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
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#ifndef _UNICODE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#define _UNICODE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync#endif
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Shows a message box with a printf() style formatted string.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns Message box result (IDOK, IDCANCEL, ...).
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @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 */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int ShowInfo(const char *pszFmt, ...)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszMsg;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_list va;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_start(va, pszFmt);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrAPrintfV(&pszMsg, pszFmt, va);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_end(va);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync int rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (pszMsg)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync else
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = MessageBox(GetDesktopWindow(), pszFmt, VBOX_STUB_TITLE, MB_ICONINFORMATION);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrFree(pszMsg);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Shows an error message box with a printf() style formatted string.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns Message box result (IDOK, IDCANCEL, ...).
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszFmt Printf-style format string to show in the message box body.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int ShowError(const char *pszFmt, ...)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszMsg;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_list va;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync int rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync va_start(va, pszFmt);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync if (RTStrAPrintfV(&pszMsg, pszFmt, va))
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync RTStrFree(pszMsg);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync else /* Should never happen! */
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt));
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync va_end(va);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return rc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Reads data from a built-in resource.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns iprt status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param hInst Instance to read the data from.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszDataName Name of resource to read.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param ppvResource Pointer to buffer which holds the read resource data.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pdwSize Pointer which holds the read data size.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic int ReadData(HINSTANCE hInst,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync const char *pszDataName,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync PVOID *ppvResource,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DWORD *pdwSize)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync do
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(pszDataName, ("Resource name is empty!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Find our resource. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync HRSRC hRsrc = FindResourceEx(hInst, RT_RCDATA, pszDataName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(hRsrc, ("Could not find resource!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Get resource size. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *pdwSize = SizeofResource(hInst, hRsrc);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync AssertMsgBreak(*pdwSize > 0, ("Size of resource is invalid!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Get pointer to resource. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync HGLOBAL hData = LoadResource(hInst, hRsrc);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(hData, ("Could not load resource!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Lock resource. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *ppvResource = LockResource(hData);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(*ppvResource, ("Could not lock resource!\n"));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return VINF_SUCCESS;
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } while (0);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return VERR_IO_GEN_FAILURE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
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;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync rc = ReadData(NULL, 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 *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns TRUE if we need to handle the specified package, FALSE if not.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncstatic BOOL PackageIsNeeded(PVBOXSTUBPKG pPackage)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL bIsWow64 = IsWow64();
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if ((bIsWow64 && pPackage->byArch == VBOXSTUBPKGARCH_AMD64)) /* 64bit Windows. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync else if ((!bIsWow64 && pPackage->byArch == VBOXSTUBPKGARCH_X86)) /* 32bit. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync else if (pPackage->byArch == VBOXSTUBPKGARCH_ALL)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Recursively copies a directory to another location.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @returns iprt status code.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszDestDir Location to copy the source directory to.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param pszSourceDir The source directory to copy.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncint CopyDir(const char *pszDestDir, const char *pszSourceDir)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync{
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync char szDest[RTPATH_MAX + 1];
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync char szSource[RTPATH_MAX + 1];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync AssertStmt(pszDestDir, "Destination directory invalid!");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync AssertStmt(pszSourceDir, "Source directory invalid!");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync SHFILEOPSTRUCT s = {0};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if ( RTStrPrintf(szDest, _MAX_PATH, "%s%c", pszDestDir, '\0') > 0
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync && RTStrPrintf(szSource, _MAX_PATH, "%s%c", pszSourceDir, '\0') > 0)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync s.hwnd = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync s.wFunc = FO_COPY;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync s.pTo = szDest;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync s.pFrom = szSource;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync s.fFlags = FOF_SILENT |
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync FOF_NOCONFIRMATION |
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync FOF_NOCONFIRMMKDIR |
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync FOF_NOERRORUI;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return RTErrConvertFromWin32(SHFileOperation(&s));
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! */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync HANDLE hMutexAppRunning = CreateMutex (NULL, FALSE, "VBoxStubInstaller");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if ( (hMutexAppRunning != NULL)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync && (GetLastError() == ERROR_ALREADY_EXISTS))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Close the mutex for this application instance. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync CloseHandle(hMutexAppRunning);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync hMutexAppRunning = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return 1;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Init IPRT. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync int vrc = RTR3Init();
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_FAILURE(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return vrc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL fExtractOnly = FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL fSilent = FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync BOOL fEnableLogging = FALSE;
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync BOOL fExit = FALSE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Temp variables for arguments. */
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync char szExtractPath[RTPATH_MAX] = {0};
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync char szMSIArgs[RTPATH_MAX] = {0};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Process arguments. */
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync for (int i = 0; i < argc; i++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync if ( (0 == RTStrICmp(argv[i], "-x"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "-extract"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/extract")))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync fExtractOnly = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if ( (0 == RTStrICmp(argv[i], "-s"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "-silent"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/silent")))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync fSilent = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if ( (0 == RTStrICmp(argv[i], "-l"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "-logging"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/logging")))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync fEnableLogging = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if (( (0 == RTStrICmp(argv[i], "-p"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "-path"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/path")))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync )
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync if (argc > i)
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync vrc = ::StringCbCat(szExtractPath, sizeof(szExtractPath), argv[i+1]);
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync i++; /* Avoid the specified path from being parsed. */
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync }
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync ShowError("No path for extraction specified!");
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync fExit = TRUE;
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if (( (0 == RTStrICmp(argv[i], "-msiparams"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/msiparams")))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync && (argc > i))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync for (int a = i + 1; a < argc; a++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (a > i+1) /* Insert a space. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), " ");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), argv[a]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if ( (0 == RTStrICmp(argv[i], "-v"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "-version"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/version")))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ShowInfo("Version: %d.%d.%d.%d",
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync fExit = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync else if ( (0 == RTStrICmp(argv[i], "-help"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/help"))
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync || (0 == RTStrICmp(argv[i], "/?")))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ShowInfo("-- %s v%d.%d.%d.%d --\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "Command Line Parameters:\n\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-extract | -x - Extract file contents to temporary directory\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-silent | -s - Enables silent mode installation\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-path | -p - Sets the path of the extraction directory\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-help | /? - Print this help and exit\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-msiparams <parameters> - Specifies extra parameters for the MSI installers\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-logging | -l - Enables installer logging\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "-version | -v - Print version number and exit\n\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "Examples:\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "%s -msiparams INSTALLDIR=C:\\VBox\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "%s -extract -path C:\\VBox\n",
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync VBOX_STUB_TITLE, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV,
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync argv[0], argv[0]);
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync fExit = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync else
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (i > 0)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync ShowError("Unknown option \"%s\"!\n"
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync "Please refer to the command line help by specifying \"/?\"\n"
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync "to get more information.", argv[i]);
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync fExit = TRUE;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync if (fExit)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return 0;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync HRESULT hr = S_OK;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync do /* break loop */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Get/create our temp path (only if not already set). */
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (szExtractPath[0] == '\0')
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not retrieve temp directory!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = RTPathAppend(szExtractPath, sizeof(szExtractPath), "VirtualBox");
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not construct temp directory!\n"));
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync /* Convert slahes; this is necessary for MSI routines later! */
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync RTPathChangeToDosSlashes(szExtractPath, true /* Force conversion. */);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync }
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (!RTDirExists(szExtractPath))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = RTDirCreate(szExtractPath, 0700);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not create temp directory!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Get our executable path */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char szPathExe[_MAX_PATH];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = RTPathExecDir(szPathExe, sizeof(szPathExe));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /** @todo error checking */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Read our manifest. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync PVBOXSTUBPKGHEADER pHeader = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DWORD cbHeader = 0;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = ReadData(NULL, "MANIFEST", (LPVOID*)&pHeader, &cbHeader);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Manifest not found!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Extract files. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync for (BYTE k = 0; k < pHeader->byCntPkgs; k++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync PVBOXSTUBPKG pPackage = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DWORD cbPackage = 0;
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync char szHeaderName[RTPATH_MAX + 1] = {0};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync hr = ::StringCchPrintf(szHeaderName, RTPATH_MAX, "HDR_%02d", k);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = ReadData(NULL, szHeaderName, (LPVOID*)&pPackage, &cbPackage);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Header not found!\n")); /** @todo include header name, how? */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (PackageIsNeeded(pPackage) || fExtractOnly)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszTempFile = NULL;
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = GetTempFileAlloc(szExtractPath, pPackage->szFileName, &pszTempFile);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not create name for temporary extracted file!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = Extract(pPackage, pszTempFile);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not extract file!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrFree(pszTempFile);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (FALSE == fExtractOnly && !RT_FAILURE(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /*
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Copy ".custom" directory into temp directory so that the extracted .MSI
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * file(s) can use it.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync char *pszPathCustomDir = RTPathJoinA(szPathExe, ".custom");
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync pszPathCustomDir = RTPathChangeToDosSlashes(pszPathCustomDir, true /* Force conversion. */);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (pszPathCustomDir && RTDirExists(pszPathCustomDir))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = CopyDir(szExtractPath, pszPathCustomDir);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_FAILURE(vrc)) /* Don't fail if it's missing! */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = VINF_SUCCESS;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrFree(pszPathCustomDir);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Do actions on files. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync for (BYTE k = 0; k < pHeader->byCntPkgs; k++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync PVBOXSTUBPKG pPackage = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DWORD cbPackage = 0;
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync char szHeaderName[RTPATH_MAX] = {0};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync hr = StringCchPrintf(szHeaderName, RTPATH_MAX, "HDR_%02d", k);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = ReadData(NULL, szHeaderName, (LPVOID*)&pPackage, &cbPackage);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Package not found!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (PackageIsNeeded(pPackage))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync char *pszTempFile = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = GetTempFileAlloc(szExtractPath, pPackage->szFileName, &pszTempFile);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgRCBreak(vrc, ("Could not create name for temporary action file!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Handle MSI files. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RTStrICmp(RTPathExt(pszTempFile), ".msi") == 0)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Set UI level. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync INSTALLUILEVEL UILevel = MsiSetInternalUI( fSilent
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ? INSTALLUILEVEL_NONE
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync : INSTALLUILEVEL_FULL,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync NULL);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(UILevel != INSTALLUILEVEL_NOCHANGE, ("Could not set installer UI level!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Enable logging? */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (fEnableLogging)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync char *pszLog = RTPathJoinA(szExtractPath, "VBoxInstallLog.txt");
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync /* Convert slahes; this is necessary for MSI routines! */
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync pszLog = RTPathChangeToDosSlashes(pszLog, true /* Force conversion. */);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync AssertMsgBreak(pszLog, ("Could not construct path for log file!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync UINT uLogLevel = MsiEnableLog(INSTALLLOGMODE_VERBOSE,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync pszLog, INSTALLLOGATTRIBUTES_FLUSHEACHLINE);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrFree(pszLog);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync AssertMsgBreak(uLogLevel == ERROR_SUCCESS, ("Could not set installer logging level!\n"));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync UINT uStatus = ::MsiInstallProductA(pszTempFile, szMSIArgs);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if ( (uStatus != ERROR_SUCCESS)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync && (uStatus != ERROR_SUCCESS_REBOOT_REQUIRED)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync && (uStatus != ERROR_INSTALL_USEREXIT))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (!fSilent)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync switch (uStatus)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync case ERROR_INSTALL_PACKAGE_VERSION:
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ShowError("This installation package cannot be installed by the Windows Installer service.\n"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync "You must install a Windows service pack that contains a newer version of the Windows Installer service.");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync case ERROR_INSTALL_PLATFORM_UNSUPPORTED:
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync ShowError("This installation package is not supported on this platform.");
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync default:
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync {
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync | FORMAT_MESSAGE_IGNORE_INSERTS
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync | FORMAT_MESSAGE_FROM_SYSTEM;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync HMODULE hModule = NULL;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync if (uStatus >= NERR_BASE && uStatus <= MAX_NERR)
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync {
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync hModule = LoadLibraryEx(TEXT("netmsg.dll"),
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync NULL,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync LOAD_LIBRARY_AS_DATAFILE);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync if (hModule != NULL)
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync DWORD dwBufferLength;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync LPSTR szMessageBuffer;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync if (dwBufferLength = FormatMessageA(dwFormatFlags,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync hModule, /* If NULL, load system stuff. */
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync uStatus,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync (LPSTR)&szMessageBuffer,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync 0,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync NULL))
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync {
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync ShowError("Installation failed! Error: %s", szMessageBuffer);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync LocalFree(szMessageBuffer);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync else /* If text lookup failed, show at least the error number. */
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync ShowError("Installation failed! Error: %u", uStatus);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync if (hModule)
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync FreeLibrary(hModule);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync break;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = VERR_NO_CHANGE; /* No change done to the system. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTStrFree(pszTempFile);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } /* Package needed? */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } /* For all packages */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Clean up (only on success - prevent deleting the log). */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if ( !fExtractOnly
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync && RT_SUCCESS(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync for (int i=0; i<5; i++)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync vrc = RTDirRemoveRecursive(szExtractPath, 0 /*fFlags*/);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_SUCCESS(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync break;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync RTThreadSleep(3000 /* Wait 3 seconds.*/);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } while (0);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_SUCCESS(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if ( fExtractOnly
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync && !fSilent)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync ShowInfo("Files were extracted to: %s", szExtractPath);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /** @todo Add more post installation stuff here if required. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Release instance mutex. */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (hMutexAppRunning != NULL)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync CloseHandle(hMutexAppRunning);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync hMutexAppRunning = NULL;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /* Set final exit (return) code (error level). */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (RT_FAILURE(vrc))
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync switch(vrc)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync case VERR_NO_CHANGE:
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync default:
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = 1;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync else /* Always set to (VINF_SUCCESS), even if we got something else (like a VWRN etc). */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync vrc = VINF_SUCCESS;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return vrc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync