VBoxStub.cpp revision dee9e52b1688c0617890cbbd8a8488f9f315d1b7
/* $Id$ */
/** @file
* VBoxStub - VirtualBox's Windows installer stub.
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* Oracle Corporation confidential
* All rights reserved
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <windows.h>
#include <msiquery.h>
#include <objbase.h>
#include <shlobj.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strsafe.h>
#include <iprt/initterm.h>
#include "VBoxStub.h"
#include "../StubBld/VBoxStubBld.h"
#include "resource.h"
#ifndef _UNICODE
#define _UNICODE
#endif
/**
* Shows a message box with a printf() style formatted string.
*
* @returns Message box result (IDOK, IDCANCEL, ...).
*
* @param uType Type of the message box (see MSDN).
* @param pszFmt Printf-style format string to show in the message box body.
*
*/
{
char *pszMsg;
int rc;
if (pszMsg)
else
return rc;
}
/**
* Shows an error message box with a printf() style formatted string.
*
* @returns Message box result (IDOK, IDCANCEL, ...).
*
* @param pszFmt Printf-style format string to show in the message box body.
*
*/
{
char *pszMsg;
int rc;
if (pszMsg)
else
return rc;
}
/**
* Reads data from a built-in resource.
*
* @returns iprt status code.
*
* @param hInst Instance to read the data from.
* @param pszDataName Name of resource to read.
* @param ppvResource Pointer to buffer which holds the read resource data.
* @param pdwSize Pointer which holds the read data size.
*
*/
const char *pszDataName,
{
do
{
/* Find our resource. */
HRSRC hRsrc = FindResourceEx(hInst, RT_RCDATA, pszDataName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
/* Get resource size. */
/* Get pointer to resource. */
/* Lock resource. */
} while (0);
}
/**
* Constructs a full temporary file path from the given parameters.
*
* @returns iprt status code.
*
* @param pszTempPath The pure path to use for construction.
* @param pszTargetFileName The pure file name to use for construction.
* @param ppszTempFile Pointer to the constructed string. Must be freed
* using RTStrFree().
*/
static int GetTempFileAlloc(const char *pszTempPath,
const char *pszTargetFileName,
char **ppszTempFile)
{
}
/**
* Extracts a built-in resource to disk.
*
* @returns iprt status code.
*
* @param pszResourceName The resource name to extract.
* @param pszTempFile The full file path + name to extract the resource to.
*
*/
static int ExtractFile(const char *pszResourceName,
const char *pszTempFile)
{
int rc;
do
{
/* Read the data of the built-in resource. */
DWORD dwDataSize = 0;
/* Create new (and replace an old) file. */
bCreatedFile = TRUE;
/* Write contents to new file. */
} while (0);
if (RTFileIsValid(fh))
if (RT_FAILURE(rc))
{
if (bCreatedFile)
}
return rc;
}
/**
* Extracts a built-in resource to disk.
*
* @returns iprt status code.
*
* @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource.
* @param pszTempFile The full file path + name to extract the resource to.
*
*/
const char *pszTempFile)
{
}
/**
* Detects whether we're running on a 32- or 64-bit platform and returns the result.
*
* @returns TRUE if we're running on a 64-bit OS, FALSE if not.
*
*/
{
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
if (NULL != fnIsWow64Process)
{
{
/* Error in retrieving process type - assume that we're running on 32bit. */
return FALSE;
}
}
return bIsWow64;
}
/**
* Decides whether we need a specified package to handle or not.
*
* @returns TRUE if we need to handle the specified package, FALSE if not.
*
* @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource.
*
*/
{
{
return TRUE;
}
{
return TRUE;
}
{
return TRUE;
}
return FALSE;
}
/**
* Recursivly copies a directory to another location.
*
* @returns iprt status code.
*
* @param pszDestDir Location to copy the source directory to.
* @param pszSourceDir The source directory to copy.
*
*/
{
SHFILEOPSTRUCT s = {0};
{
s.fFlags = FOF_SILENT |
}
return RTErrConvertFromWin32(SHFileOperation(&s));
}
char *lpCmdLine,
int nCmdShow)
{
/* Check if we're already running and jump out if so. */
/* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */
if ( (hMutexAppRunning != NULL)
&& (GetLastError() == ERROR_ALREADY_EXISTS))
{
/* Close the mutex for this application instance. */
return 1;
}
/* Init IPRT. */
if (RT_FAILURE(vrc))
return vrc;
/* Temp variables for arguments. */
char szExtractPath[1024] = {0};
char szMSIArgs[1024] = {0};
/* Process arguments. */
for (int i = 0; i < iArgC; i++)
{
{
fExtractOnly = TRUE;
}
{
}
{
}
&& (iArgC > i))
{
i++; /* Avoid the specify path from being parsed */
}
&& (iArgC > i))
{
for (int a=i+1; a<iArgC; a++)
{
if (a > i+1) /* Insert a space. */
}
}
{
ShowInfo("Version: %d.%d.%d.%d",
}
{
ShowInfo("-- %s v%d.%d.%d.%d --\n"
"Command Line Parameters:\n\n"
"-extract | -x - Extract file contents to temporary directory\n"
"-silent | -s - Enables silent mode installation\n"
"-path | -p - Sets the path of the extraction directory\n"
"-help | /? - Print this help and exit\n"
"-msiparams <parameters> - Specifies extra parameters for the MSI installers\n"
"-logging | -l - Enables installer logging\n"
"-version | -v - Print version number and exit\n\n"
"Examples:\n"
"%s -msiparams INSTALLDIR=C:\\VBox\n"
"%s -extract -path C:\\VBox\n",
}
else
{
if (i > 0)
{
ShowInfo("Unknown option \"%s\"!\n"
"Please refer to the command line help by specifying \"/?\"\n"
"to get more information.", pArgV[i]);
}
}
}
if (bExit)
return 0;
do
{
if (pszTempPathFull == NULL)
{
}
if (!RTDirExists(pszTempPathFull))
{
}
/* Get our executable path */
/** @todo error checking */
/* Read our manifest. */
/* Extract files. */
{
char szHeaderName[_MAX_PATH] = {0};
{
char *pszTempFile = NULL;
}
}
{
/*
* Copy ".custom" directory into temp directory so that the extracted .MSI
* file(s) can use it.
*/
char *pszPathCustomDir;
{
vrc = VINF_SUCCESS;
}
/* Do actions on files. */
{
char szHeaderName[_MAX_PATH] = {0};
if (PackageIsNeeded(pPackage))
{
char *pszTempFile = NULL;
/* Handle MSI files. */
{
/* Set UI level. */
NULL);
/* Enable logging? */
if (fEnableLogging)
{
}
if ( (uStatus != ERROR_SUCCESS)
&& (uStatus != ERROR_SUCCESS_REBOOT_REQUIRED)
&& (uStatus != ERROR_INSTALL_USEREXIT))
{
if (!fSilent)
{
switch (uStatus)
{
ShowError("This installation package cannot be installed by the Windows Installer service.\n"
"You must install a Windows service pack that contains a newer version of the Windows Installer service.");
break;
ShowError("This installation package is not supported on this platform.\n");
break;
default:
/** @todo Use FormatMessage here! */
break;
}
}
}
}
} /* Package needed? */
} /* For all packages */
}
/* Clean up (only on success - prevent deleting the log). */
if ( !fExtractOnly
&& RT_SUCCESS(vrc))
{
for (int i=0; i<5; i++)
{
if (RT_SUCCESS(vrc))
break;
}
}
} while (0);
if (RT_SUCCESS(vrc))
{
if ( fExtractOnly
&& !fSilent
)
{
}
/** @todo Add more post installation stuff here if required. */
}
if (strlen(szExtractPath) <= 0)
/* Release instance mutex. */
if (hMutexAppRunning != NULL)
{
}
/* Set final exit (return) code (error level). */
if (RT_FAILURE(vrc))
{
switch(vrc)
{
case VERR_NO_CHANGE:
default:
vrc = 1;
}
}
else /* Always set to (VINF_SUCCESS), even if we got something else (like a VWRN etc). */
vrc = VINF_SUCCESS;
return vrc;
}