summaryrefslogtreecommitdiffstats
path: root/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/Installer/win/StubBld/VBoxStubBld.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp b/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp
new file mode 100644
index 00000000..e8f5b5cc
--- /dev/null
+++ b/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp
@@ -0,0 +1,308 @@
+/* $Id: VBoxStubBld.cpp $ */
+/** @file
+ * VBoxStubBld - VirtualBox's Windows installer stub builder.
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/win/windows.h>
+#include <shellapi.h>
+#include <strsafe.h>
+
+#include <VBox/version.h>
+
+#include "VBoxStubBld.h"
+
+HRESULT GetFile (const char* pszFilePath,
+ HANDLE* phFile,
+ DWORD* pdwFileSize)
+{
+ HRESULT hr = S_OK;
+ *phFile = ::CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (INVALID_HANDLE_VALUE == *phFile)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ *pdwFileSize = ::GetFileSize(*phFile, NULL);
+ if (!*pdwFileSize)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+ return hr;
+}
+
+HRESULT UpdateResource(HANDLE hFile,
+ DWORD dwFileSize,
+ HANDLE hResourceUpdate,
+ const char *szResourceType,
+ const char *szResourceId)
+{
+ HRESULT hr = S_OK;
+ PVOID pvFile = NULL;
+ HANDLE hMap = NULL;
+
+ hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ pvFile = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, dwFileSize);
+ if (!::UpdateResourceA(hResourceUpdate, szResourceType, szResourceId,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pvFile, dwFileSize))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if (pvFile)
+ {
+ ::UnmapViewOfFile(pvFile);
+ pvFile = NULL;
+ }
+
+ if (hMap)
+ {
+ ::CloseHandle(hMap);
+ hMap = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT IntegrateFile (HANDLE hResourceUpdate,
+ const char* szResourceType,
+ const char* szResourceId,
+ const char* pszFilePath)
+{
+ HRESULT hr = S_OK;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD dwFileSize = 0;
+
+ do
+ {
+ hr = GetFile(pszFilePath, &hFile, &dwFileSize);
+ if (FAILED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ break;
+ }
+ else
+ {
+ hr = UpdateResource(hFile, dwFileSize, hResourceUpdate, szResourceType, szResourceId);
+ if (FAILED(hr))
+ {
+ printf("ERROR: Error updating resource for file %s!", pszFilePath);
+ break;
+ }
+ }
+
+ } while (0);
+
+
+ if (INVALID_HANDLE_VALUE != hFile)
+ {
+ ::CloseHandle(hFile);
+ hFile = INVALID_HANDLE_VALUE;
+ }
+
+ return hr;
+}
+
+static char * MyPathFilename(const char *pszPath)
+{
+ const char *psz = pszPath;
+ const char *pszName = pszPath;
+
+ for (;; psz++)
+ {
+ switch (*psz)
+ {
+ /* handle separators. */
+ case ':':
+ pszName = psz + 1;
+ break;
+
+ case '\\':
+ case '/':
+ pszName = psz + 1;
+ break;
+
+ /* the end */
+ case '\0':
+ if (*pszName)
+ return (char *)(void *)pszName;
+ return NULL;
+ }
+ }
+
+ /* will never get here */
+}
+
+
+int main (int argc, char* argv[])
+{
+ HRESULT hr = S_OK;
+ int rc = 0;
+
+ char szSetupStub[_MAX_PATH] = {"VBoxStub.exe"};
+ char szOutput[_MAX_PATH] = {"VirtualBox-MultiArch.exe"};
+ HANDLE hUpdate = NULL;
+
+ do
+ {
+ printf(VBOX_PRODUCT " Stub Builder v%d.%d.%d.%d\n",
+ VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
+
+ if (argc < 2)
+ printf("WARNING: No parameters given! Using default values!\n");
+
+ VBOXSTUBBUILDPKG stbBuildPkg[VBOXSTUB_MAX_PACKAGES] = {0};
+ VBOXSTUBPKG stbPkg[VBOXSTUB_MAX_PACKAGES] = {0};
+ VBOXSTUBPKGHEADER stbHeader =
+ {
+ "vbox$tub", /* File magic. */
+ 1, /* Version. */
+ 0 /* No files yet. */
+ };
+
+ for (int i=1; i<argc; i++)
+ {
+ if (0 == stricmp(argv[i], "-out") && argc > i+1)
+ {
+ hr = ::StringCchCopy(szOutput, _MAX_PATH, argv[i+1]);
+ i++;
+ }
+
+ else if (0 == stricmp(argv[i], "-stub") && argc > i+1)
+ {
+ hr = ::StringCchCopy(szSetupStub, _MAX_PATH, argv[i+1]);
+ i++;
+ }
+
+ else if (0 == stricmp(argv[i], "-target-all") && argc > i+1)
+ {
+ hr = ::StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
+ stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_ALL;
+ stbHeader.byCntPkgs++;
+ i++;
+ }
+
+ else if (0 == stricmp(argv[i], "-target-x86") && argc > i+1)
+ {
+ hr = ::StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
+ stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_X86;
+ stbHeader.byCntPkgs++;
+ i++;
+ }
+
+ else if (0 == stricmp(argv[i], "-target-amd64") && argc > i+1)
+ {
+ hr = ::StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
+ stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_AMD64;
+ stbHeader.byCntPkgs++;
+ i++;
+ }
+ else
+ {
+ printf("ERROR: Invalid parameter: %s\n", argv[i]);
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+ if (FAILED(hr))
+ {
+ printf("ERROR: StringCchCopy failed: %#x\n", hr);
+ break;
+ }
+ }
+ if (FAILED(hr))
+ break;
+
+ if (stbHeader.byCntPkgs <= 0)
+ {
+ printf("ERROR: No packages defined! Exiting.\n");
+ break;
+ }
+
+ printf("Stub: %s\n", szSetupStub);
+ printf("Output: %s\n", szOutput);
+ printf("# Packages: %d\n", stbHeader.byCntPkgs);
+
+ if (!::CopyFile(szSetupStub, szOutput, FALSE))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ printf("ERROR: Could not create stub loader: 0x%08x\n", hr);
+ break;
+ }
+
+ hUpdate = ::BeginUpdateResource(szOutput, FALSE);
+
+ PVBOXSTUBPKG pPackage = stbPkg;
+ char szHeaderName[_MAX_PATH] = {0};
+
+ for (BYTE i=0; i<stbHeader.byCntPkgs; i++)
+ {
+ printf("Integrating (Platform %d): %s\n", stbBuildPkg[i].byArch, stbBuildPkg[i].szSourcePath);
+
+ /* Construct resource name. */
+ hr = ::StringCchPrintf(pPackage->szResourceName, _MAX_PATH, "BIN_%02d", i);
+ pPackage->byArch = stbBuildPkg[i].byArch;
+
+ /* Construct final name used when extracting. */
+ hr = ::StringCchCopy(pPackage->szFileName, _MAX_PATH, MyPathFilename(stbBuildPkg[i].szSourcePath));
+
+ /* Integrate header into binary. */
+ hr = ::StringCchPrintf(szHeaderName, _MAX_PATH, "HDR_%02d", i);
+ hr = UpdateResource(hUpdate, RT_RCDATA, szHeaderName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pPackage, sizeof(VBOXSTUBPKG));
+
+ /* Integrate file into binary. */
+ hr = IntegrateFile(hUpdate, RT_RCDATA, pPackage->szResourceName, stbBuildPkg[i].szSourcePath);
+ if (FAILED(hr))
+ {
+ printf("ERROR: Could not integrate binary %s (%s): 0x%08x\n",
+ pPackage->szResourceName, pPackage->szFileName, hr);
+ rc = 1;
+ }
+
+ pPackage++;
+ }
+
+ if (FAILED(hr))
+ break;
+
+ if (!::UpdateResource(hUpdate, RT_RCDATA, "MANIFEST", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &stbHeader, sizeof(VBOXSTUBPKGHEADER)))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ break;
+ }
+
+ if (!::EndUpdateResource(hUpdate, FALSE))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ break;
+ }
+
+ printf("Integration done!\n");
+
+ } while (0);
+
+ hUpdate = NULL;
+
+ if (FAILED(hr))
+ {
+ printf("ERROR: Building failed! Last error: %d\n", GetLastError());
+ rc = 1;
+ }
+ return rc;
+}