Index: trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/Makefile.kmk	(revision 34098)
+++ trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/Makefile.kmk	(revision 34098)
@@ -0,0 +1,44 @@
+# $Id$
+## @file
+# Sub-Makefile for the Windows Guest Additions Installer.
+#
+
+#
+# Copyright (C) 2010 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.
+#
+
+SUB_DEPTH = ../../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+#
+# Build template for NSIS plugins.
+# Must always be built in 32-bit, since NSIS is 32-bit only.
+#
+TEMPLATE_NSISPLUGIN = NSIS Plugin
+TEMPLATE_NSISPLUGIN_EXTENDS = VBOXGUESTR3DLL
+TEMPLATE_NSISPLUGIN_BLD_TRG = win
+TEMPLATE_NSISPLUGIN_BLD_TRG_ARCH = x86 # Force always building in 32-bit.
+
+#
+# NSIS plugins always have to be compiled in 32-bit!
+#
+DLLS += VBoxGuestInstallHelper
+VBoxGuestInstallHelper_TEMPLATE = NSISPLUGIN
+ifdef VBOX_SIGN_ADDITIONS # (See the parent makefile.)
+ VBoxGuestInstallHelper_NOINST  = true
+endif
+VBoxGuestInstallHelper_DEFS     = _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1
+VBoxGuestInstallHelper_SOURCES  = \
+	VBoxGuestInstallHelper.cpp \
+	VBoxGuestInstallHelper.rc
+
+include $(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp	(revision 34098)
+++ trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp	(revision 34098)
@@ -0,0 +1,182 @@
+/* $Id$ */
+/** @file
+ * VBoxGuestInstallHelper - Various helper routines for Windows guest installer.
+ */
+
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <Strsafe.h>
+#include "exdll.h"
+
+/* Required structures/defines of VBoxTray. */
+#include "../../VBoxTray/VBoxTrayMsg.h"
+
+HINSTANCE g_hInstance;
+HWND g_hwndParent;
+
+#define VBOXINSTALLHELPER_EXPORT extern "C" void __declspec(dllexport)
+
+/**
+ * Pops (gets) a value from the internal NSIS stack.
+ * Since the supplied popstring() method easily can cause buffer
+ * overflows, use VBoxPopString() instead!
+ *
+ * @return  HRESULT
+ * @param   pszDest     Pointer to pre-allocated string to store result.
+ * @param   cchDest     Size (in characters) of pre-allocated string.
+ */
+static HRESULT VBoxPopString(TCHAR *pszDest, size_t cchDest)
+{
+    HRESULT hr = S_OK;
+    if (!g_stacktop || !*g_stacktop)
+        hr = ERROR_EMPTY;
+    else
+    {
+        stack_t *pStack = (*g_stacktop);
+        if (pStack)
+        {
+            hr = StringCchCopy(pszDest, cchDest, pStack->text);
+            if (SUCCEEDED(hr))
+            {
+                *g_stacktop = pStack->next;
+                GlobalFree((HGLOBAL)pStack);
+            }
+        }
+    }
+    return hr;
+}
+
+static HRESULT VBoxPopULong(ULONG *pulValue)
+{
+    HRESULT hr = S_OK;
+    if (!g_stacktop || !*g_stacktop)
+        hr = ERROR_EMPTY;
+    else
+    {
+        stack_t *pStack = (*g_stacktop);
+        if (pStack)
+        {
+            *pulValue = strtoul(pStack->text, NULL, 10 /* Base */);
+
+            *g_stacktop = pStack->next;
+            GlobalFree((HGLOBAL)pStack);
+        }
+    }
+    return hr;
+}
+
+HANDLE VBoIPCConnect()
+{
+    HANDLE hPipe = NULL;
+    while (1)
+    {
+        hPipe = CreateFile(VBOXTRAY_PIPE_IPC,   /* Pipe name. */
+                           GENERIC_READ |       /* Read and write access. */
+                           GENERIC_WRITE,
+                           0,                   /* No sharing. */
+                           NULL,                /* Default security attributes. */
+                           OPEN_EXISTING,       /* Opens existing pipe. */
+                           0,                   /* Default attributes. */
+                           NULL);               /* No template file. */
+
+        /* Break if the pipe handle is valid. */
+        if (hPipe != INVALID_HANDLE_VALUE)
+            break;
+
+        /* Exit if an error other than ERROR_PIPE_BUSY occurs. */
+        if (GetLastError() != ERROR_PIPE_BUSY)
+            return NULL;
+
+        /* All pipe instances are busy, so wait for 20 seconds. */
+        if (!WaitNamedPipe(VBOXTRAY_PIPE_IPC, 20000))
+            return NULL;
+    }
+
+    /* The pipe connected; change to message-read mode. */
+    DWORD dwMode = PIPE_READMODE_MESSAGE;
+    BOOL fSuccess = SetNamedPipeHandleState(hPipe,    /* Pipe handle. */
+                                            &dwMode,  /* New pipe mode. */
+                                            NULL,     /* Don't set maximum bytes. */
+                                            NULL);    /* Don't set maximum time. */
+    if (!fSuccess)
+        return NULL;
+    return hPipe;
+}
+
+void VBoxIPCDisconnect(HANDLE hPipe)
+{
+    CloseHandle(hPipe);
+}
+
+HRESULT VBoxIPCWriteMessage(HANDLE hPipe, BYTE *pMessage, DWORD cbMessage)
+{
+    HRESULT hr = S_OK;
+    DWORD cbWritten = 0;
+    if (!WriteFile(hPipe, pMessage, cbMessage - cbWritten, &cbWritten, 0))
+        hr = HRESULT_FROM_WIN32(GetLastError());
+    return hr;
+}
+
+/**
+ * Shows a balloon message using VBoxTray's notification area in the
+ * Windows task bar.
+ *
+ * @param   hwndParent          Window handle of parent.
+ * @param   string_size         Size of variable string.
+ * @param   variables           The actual variable string.
+ * @param   stacktop            Pointer to a pointer to the current stack.
+ */
+VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size,
+                                               TCHAR *variables, stack_t **stacktop)
+{
+	EXDLL_INIT();
+
+    VBOXTRAYIPCHEADER hdr;
+    hdr.ulMsg = VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG;
+    hdr.ulVer = 1;
+
+    VBOXTRAYIPCMSG_SHOWBALLOONMSG msg;
+    HRESULT hr = VBoxPopString(msg.szBody, sizeof(msg.szBody) / sizeof(TCHAR));
+    if (SUCCEEDED(hr))
+        hr = VBoxPopString(msg.szTitle, sizeof(msg.szTitle) / sizeof(TCHAR));
+    if (SUCCEEDED(hr))
+        hr = VBoxPopULong(&msg.ulType);
+    if (SUCCEEDED(hr))
+        hr = VBoxPopULong(&msg.ulShowMS);
+
+    if (SUCCEEDED(hr))
+    {
+        msg.ulFlags = 0;
+
+        HANDLE hPipe = VBoIPCConnect();
+        if (hPipe)
+        {
+            hr = VBoxIPCWriteMessage(hPipe, (BYTE*)&hdr, sizeof(VBOXTRAYIPCHEADER));
+            if (SUCCEEDED(hr))
+                hr = VBoxIPCWriteMessage(hPipe, (BYTE*)&msg, sizeof(VBOXTRAYIPCMSG_SHOWBALLOONMSG));
+            VBoxIPCDisconnect(hPipe);
+        }
+    }
+
+    /* Push simple return value on stack. */
+    SUCCEEDED(hr) ? pushstring("0") : pushstring("1");
+}
+
+BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID lpReserved)
+{
+    g_hInstance = (HINSTANCE)hInst;
+	return TRUE;
+}
+
Index: trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.rc	(revision 34098)
+++ trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.rc	(revision 34098)
@@ -0,0 +1,51 @@
+/* $Id$ */
+/** @file
+ * VBoxGuestInstallHelper - Resource file containing version info.
+ */
+
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+   FILEVERSION          VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   PRODUCTVERSION       VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   FILEFLAGSMASK        0x3fL
+   FILEFLAGS            0x0L
+   FILEOS               0x40004L
+   FILETYPE             0x2L
+   FILESUBTYPE          0x0L
+BEGIN
+   BLOCK "StringFileInfo"
+   BEGIN
+      BLOCK "040904b0"
+      BEGIN
+         VALUE "CompanyName",      VBOX_RC_COMPANY_NAME
+         VALUE "FileDescription",  "VirtualBox Guest Install Helper\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxGuestInstallHelper\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxGuestInstallHelper.dll\0"
+         VALUE "ProductName",      VBOX_PRODUCT " Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
+
Index: trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/exdll.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/exdll.h	(revision 34098)
+++ trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/exdll.h	(revision 34098)
@@ -0,0 +1,101 @@
+/** Taken from:
+ *  http://nsis.sourceforge.net/Examples/Plugin/exdll.h
+ */
+#ifndef _EXDLL_H_
+#define _EXDLL_H_
+
+#include <windows.h>
+
+#if defined(__GNUC__)
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+
+// only include this file from one place in your DLL.
+// (it is all static, if you use it in two places it will fail)
+
+#define EXDLL_INIT()           {  \
+        g_stringsize=string_size; \
+        g_stacktop=stacktop;      \
+        g_variables=variables; }
+
+typedef struct _stack_t {
+  struct _stack_t *next;
+  char text[1]; // this should be the length of string_size
+} stack_t;
+
+
+static unsigned int g_stringsize;
+static stack_t **g_stacktop;
+static char *g_variables;
+
+static int __stdcall popstring(char *str) UNUSED; // 0 on success, 1 on empty stack
+static void __stdcall pushstring(const char *str) UNUSED;
+static char * __stdcall getuservariable(const int varnum) UNUSED;
+static void __stdcall setuservariable(const int varnum, const char *var) UNUSED;
+
+enum
+{
+INST_0,         // $0
+INST_1,         // $1
+INST_2,         // $2
+INST_3,         // $3
+INST_4,         // $4
+INST_5,         // $5
+INST_6,         // $6
+INST_7,         // $7
+INST_8,         // $8
+INST_9,         // $9
+INST_R0,        // $R0
+INST_R1,        // $R1
+INST_R2,        // $R2
+INST_R3,        // $R3
+INST_R4,        // $R4
+INST_R5,        // $R5
+INST_R6,        // $R6
+INST_R7,        // $R7
+INST_R8,        // $R8
+INST_R9,        // $R9
+INST_CMDLINE,   // $CMDLINE
+INST_INSTDIR,   // $INSTDIR
+INST_OUTDIR,    // $OUTDIR
+INST_EXEDIR,    // $EXEDIR
+INST_LANG,      // $LANGUAGE
+__INST_LAST
+};
+
+// utility functions (not required but often useful)
+static int __stdcall popstring(char *str)
+{
+  stack_t *th;
+  if (!g_stacktop || !*g_stacktop) return 1;
+  th=(*g_stacktop);
+  lstrcpyA(str,th->text);
+  *g_stacktop = th->next;
+  GlobalFree((HGLOBAL)th);
+  return 0;
+}
+
+static void __stdcall pushstring(const char *str)
+{
+  stack_t *th;
+  if (!g_stacktop) return;
+  th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize);
+  lstrcpynA(th->text,str,g_stringsize);
+  th->next=*g_stacktop;
+  *g_stacktop=th;
+}
+
+static char * __stdcall getuservariable(const int varnum)
+{
+  if (varnum < 0 || varnum >= __INST_LAST) return NULL;
+  return g_variables+varnum*g_stringsize;
+}
+
+static void __stdcall setuservariable(const int varnum, const char *var)
+{
+	if (var != NULL && varnum >= 0 && varnum < __INST_LAST)
+		lstrcpyA(g_variables + varnum*g_stringsize, var);
+}
+#endif//_EXDLL_H_
Index: trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk	(revision 34097)
+++ trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk	(revision 34098)
@@ -21,8 +21,10 @@
 # Include Sub-Makefiles.
 include $(PATH_SUB_CURRENT)/Loader/Makefile.kmk
+include $(PATH_SUB_CURRENT)/InstallHelper/Makefile.kmk
 
 # Globals
 VBOX_PATH_WIN_ADD_INS_SRC := $(PATH_SUB_CURRENT)
 VBOX_PATH_ADDITIONS.win.x86 := $(PATH_OUT_BASE)/win.x86/$(KBUILD_TYPE)/bin/additions
+VBOX_WITH_GUEST_INSTALL_HELPER := 1 # Use our guest install helper DLL.
 
 ## @todo VBOX_WIN_ADD_INS_OUT_DIR := $(PATH_TARGET)/Additions/Installer/win
@@ -149,4 +151,5 @@
 	-E 'PATH_OUT=$(subst /,\,$(PATH_OUT))' \
 	-E 'PATH_TARGET=$(subst /,\,$(PATH_TARGET))' \
+	-E 'PATH_TARGET_X86=$(subst /,\,$(PATH_OUT_BASE)/win.x86/$(KBUILD_TYPE)/obj)' \
 	-E 'VBOX_PATH_ADDITIONS_WIN_X86=$(subst /,\,$(VBOX_PATH_ADDITIONS.win.x86))' \
 	-E 'VBOX_VENDOR=$(VBOX_VENDOR)' \
@@ -162,4 +165,5 @@
 	-E 'VBOX_NSIS_ICON_FILE=$(subst /,\,$(VBOX_NSIS_ICON_FILE))' \
 	-E 'VBOX_WITH_CROGL=$(if $(VBOX_WITH_CROGL),1,0)' \
+	-E 'VBOX_WITH_GUEST_INSTALL_HELPER=$(if $(VBOX_WITH_GUEST_INSTALL_HELPER),1,0)' \
 	-E 'VBOX_WITH_WDDM=$(if $(VBOX_WITH_WDDM),1,0)' \
 	-E 'VBOX_BRAND_WIN_ADD_INST_DLGBMP=$(subst /,\,$(VBOX_BRAND_WIN_ADD_INST_DLGBMP))' \
