Index: trunk/src/VBox/Additions/WINNT/Installer/ISO/AUTORUN.INF
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/ISO/AUTORUN.INF	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/ISO/AUTORUN.INF	(revision 31634)
@@ -0,0 +1,11 @@
+;
+; Copyright (C) 2006-2010 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+[autorun]
+open=VBoxWindowsAdditions.exe
+icon=VBoxWindowsAdditions.exe
+label=VirtualBox Guest Additions
Index: trunk/src/VBox/Additions/WINNT/Installer/ISO/ReadmeDrivers.txt
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/ISO/ReadmeDrivers.txt	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/ISO/ReadmeDrivers.txt	(revision 31634)
@@ -0,0 +1,19 @@
+Oracle VM VirtualBox Guest Additions
+
+Where have the Windows drivers gone?
+- The Windows Guest Additions drivers were removed from this directory to
+  save space on your hard drive. To get the files you have to extract them
+  from the Windows Guest Additions installers:
+
+  To extract the 32-bit drivers to "C:\Drivers", do the following:
+  VBoxWindowsAdditions-x86 /extract /D=C:\Drivers
+
+  For the 64-bit drivers:
+  VBoxWindowsAdditions-amd64 /extract /D=C:\Drivers
+
+  Note: The extraction routine will create an additional sub directory
+  with the selected architecture (x86 or amd64) to prevent mixing up
+  the drivers.
+
+  To get further help with the command line parameteres of the installer,
+  type: VBoxWindowsAdditions-<arch> /?
Index: trunk/src/VBox/Additions/WINNT/Installer/Loader/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Loader/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/Loader/Makefile.kmk	(revision 31634)
@@ -0,0 +1,53 @@
+# $Id$
+## @file
+# Sub-Makefile for the Guest Additions loader.
+#
+
+#
+# Copyright (C) 2008 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+# This has to be 32-bit, so don't include it in the 64-bit build.
+if "$(KBUILD_TARGET_ARCH)" == "x86"
+ PROGRAMS.x86 += VBoxWindowsAdditions
+ VBoxWindowsAdditions_TEMPLATE= VBOXGUESTR3EXE
+ VBoxWindowsAdditions_DEFS    = _WIN32_WINNT=0x0400 _UNICODE UNICODE
+ VBoxWindowsAdditions_SOURCES = \
+ 	VBoxWindowsAdditions.cpp \
+ 	VBoxWindowsAdditions.rc
+
+ VBoxWindowsAdditions_LDFLAGS  = \
+ 	/DISALLOWLIB:msvcrt.lib \
+ 	/DISALLOWLIB:msvcprt.lib \
+ 	/DISALLOWLIB:libcmt.lib
+
+ VBoxWindowsAdditions_LIBS     = \
+ 	$(PATH_TOOL_$(TEMPLATE_VBOXR3EXE_TOOL)_LIB)/oldnames.lib \
+ 	$(PATH_TOOL_$(TEMPLATE_VBOXR3EXE_TOOL)_LIB)/libcmt.lib \
+	$(PATH_TOOL_$(TEMPLATE_VBOXR3EXE_TOOL)_LIB)/libcpmt.lib
+
+ # Version stuff.
+ VBoxWindowsAdditions.cpp_DEFS += VBOX_SVN_REV=$(VBOX_SVN_REV)
+ VBoxWindowsAdditions.cpp_DEPS = $(VBOX_SVN_REV_KMK)
+
+ # The icon location is configurable.
+ VBoxWindowsAdditions.rc_INCS += $(PATH_VBoxWindowsAdditions)
+ VBoxWindowsAdditions.rc_DEPS += $(PATH_VBoxWindowsAdditions)/VBoxWindowsAdditions-icon.rc
+ VBoxWindowsAdditions.rc_CLEAN = $(PATH_VBoxWindowsAdditions)/VBoxWindowsAdditions-icon.rc
+
+
+ # Icon include file.
+$$(PATH_VBoxWindowsAdditions)/VBoxWindowsAdditions-icon.rc: $(VBOX_WINDOWS_ADDITIONS_ICON_FILE) Makefile.kmk | $$(dir $$@)
+	$(RM) -f $@
+	$(APPEND) $@ 'IDI_VIRTUALBOX ICON DISCARDABLE "$(subst /,\\,$(VBOX_WINDOWS_ADDITIONS_ICON_FILE))"'
+
+endif # x86 only
+
+include	$(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.cpp	(revision 31634)
@@ -0,0 +1,141 @@
+/* $Id$ */
+/** @file
+ * VBoxWindowsAdditions - The Windows Guest Additions Loader
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+LPFN_ISWOW64PROCESS fnIsWow64Process;
+
+BOOL IsWow64 ()
+{
+    BOOL bIsWow64 = FALSE;
+    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+    if (NULL != fnIsWow64Process)
+    {
+        if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
+        {
+            _tprintf(_T("ERROR: Could not determine process type!\n"));
+
+            /* Error in retrieving process type - assume that we're running on 32bit. */
+            return FALSE;
+        }
+    }
+    return bIsWow64;
+}
+
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+    int iRet = 0;
+
+    LPWSTR *pszArgList = NULL;
+    int nArgs = 0;
+
+    TCHAR szCurDir[_MAX_PATH + 1] = { 0 };
+    GetCurrentDirectory(_MAX_PATH, szCurDir);
+
+    SHELLEXECUTEINFOW TempInfo = { 0 };
+    TempInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
+
+    TCHAR szModule[_MAX_PATH + 1] = { 0 };
+    TCHAR szApp[_MAX_PATH + 1] = { 0 };
+    TCHAR szProg[_MAX_PATH + 1] = { 0 };
+
+    pszArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs);
+    if (0 == GetModuleFileName(NULL, szModule, _MAX_PATH))
+    {
+        /* Module not found, use a default name. */
+        _stprintf(szModule, _T("%ws"), (pszArgList != NULL) ? pszArgList[0] : _T("VBoxWindowsAdditions.exe"));
+    }
+
+    TCHAR* pcExt = wcsrchr(szModule, _T('.'));
+    if (NULL != pcExt)
+        wcsncpy(szApp, szModule, (pcExt - szModule));
+
+    if (IsWow64()) /* 64bit Windows. */
+    {
+        _stprintf(szProg, _T("%ws-amd64.exe"), szApp);
+    }
+    else /* 32bit Windows. */
+    {
+        _stprintf(szProg, _T("%ws-x86.exe"), szApp);
+    }
+
+    /* Construct parameter list. */
+    TCHAR *pszParams = (TCHAR*)LocalAlloc(LPTR, _MAX_PATH*sizeof(TCHAR));
+    TCHAR szDelim = _T(' ');
+
+    if (pszParams)
+    {
+        wcsncat(pszParams, szProg,
+                        __min(wcslen(szProg),_MAX_PATH-wcslen(pszParams)));
+        wcsncat(pszParams, &szDelim,
+                        __min(1,_MAX_PATH-wcslen(pszParams)));
+
+        if (nArgs > 1)
+        {
+            for (int i=0; i<nArgs-1; i++)
+            {
+                if (i > 0)
+                {
+                    wcsncat(pszParams, &szDelim,
+                        __min(1,_MAX_PATH-wcslen(pszParams)));
+                }
+                wcsncat(pszParams, pszArgList[i+1],
+                        __min(wcslen(pszArgList[i+1]),_MAX_PATH-wcslen(pszParams)));
+            }
+        }
+    }
+
+    /* Struct for ShellExecute. */
+    TempInfo.fMask = 0;
+    TempInfo.hwnd = NULL;
+    TempInfo.lpVerb =L"runas" ;
+    TempInfo.lpFile = szProg;
+    TempInfo.lpParameters = pszParams;
+    TempInfo.lpDirectory = szCurDir;
+    TempInfo.nShow = SW_NORMAL;
+
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    DWORD dwRes = 0;
+
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+
+    dwRes = CreateProcessW(szProg, pszParams, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    if (!dwRes && GetLastError() == 740) /* 740 = ERROR_ELEVATION_REQUIRED -> Only for Windows Vista. */
+    {
+        if (FALSE == ::ShellExecuteExW(&TempInfo))
+        {
+            _tprintf (_T("ERROR: Could not launch program! Code: %ld\n"), GetLastError());
+            iRet = 1;
+        }
+    }
+
+    if (pszParams)
+        LocalFree(pszParams);
+
+    if (pszArgList)
+        LocalFree(pszArgList);
+
+    return iRet;
+}
+
Index: trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.rc	(revision 31634)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+#include "resource.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 Additions Loader\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxWindowsAdditions\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxWindowsAdditions.exe\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions Loader\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
+
+#include "VBoxWindowsAdditions-icon.rc"
Index: trunk/src/VBox/Additions/WINNT/Installer/Loader/resource.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Loader/resource.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/Loader/resource.h	(revision 31634)
@@ -0,0 +1,13 @@
+/* $Id$ */
+/** @file
+ * AutoStartMenu - resource header file.
+ */
+
+/*
+ * Copyright (C) 2008 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#define IDI_VIRTUALBOX 101
Index: trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk	(revision 31634)
@@ -0,0 +1,207 @@
+# $Id$
+## @file
+# Sub-Makefile for the Windows Guest Additions Installer.
+#
+
+#
+# Copyright (C) 2006-2007 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+# Include Sub-Makefiles.
+include $(PATH_SUB_CURRENT)/Loader/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
+
+## @todo VBOX_WIN_ADD_INS_OUT_DIR := $(PATH_TARGET)/Additions/Installer/win
+
+DLLS += VBCoInst
+VBCoInst_TEMPLATE = VBOXGUESTR3DLL
+ifdef VBOX_SIGN_ADDITIONS # (See the parent makefile.)
+ VBCoInst_NOINST  = true
+endif
+VBCoInst_DEFS     = _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1 UNICODE
+VBCoInst_LDFLAGS  = /subsystem:console,4.10
+VBCoInst_SOURCES  = \
+	VBCoInst.cpp \
+	VBCoInst.def \
+	VBCoInst.rc
+
+PROGRAMS += VBoxDrvInst
+VBoxDrvInst_TEMPLATE= VBOXGUESTR3EXE
+VBoxDrvInst_DEFS    = _WIN32_WINNT=0x0400 _UNICODE UNICODE
+VBoxDrvInst_DEFS   += VBOX_SVN_REV=$(VBOX_SVN_REV)
+VBoxDrvInst_DEPS    = $(VBOX_SVN_REV_KMK)
+VBoxDrvInst_SDKS    = WINPSDK W2K3DDK
+VBoxDrvInst_LIBS    = \
+	$(PATH_SDK_W2K3DDK_LIB)/setupapi.lib \
+	$(PATH_SDK_W2K3DDK_LIB)/newdev.lib
+VBoxDrvInst_SOURCES = \
+	VBoxDrvInst.cpp \
+	VBoxDrvInst.rc
+
+PROGRAMS += VBoxGuestDrvInst
+VBoxGuestDrvInst_TEMPLATE= VBOXGUESTR3EXE
+VBoxGuestDrvInst_DEFS    =  _WIN32_WINNT=0x0400 UNICODE
+VBoxGuestDrvInst_SOURCES = \
+	VBoxGuestDrvInst.cpp \
+	VBoxGuestDrvInst.rc
+
+PROGRAMS += RegCleanup
+RegCleanup_TEMPLATE = VBOXGUESTR3EXE
+RegCleanup_DEFS     = _WIN32_WINNT=0x0400 UNICODE
+RegCleanup_SOURCES  = \
+	RegCleanup.cpp \
+	RegCleanup.rc
+
+
+#
+# The installer.
+#
+PACKING     += $(PATH_BIN)/additions/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH).exe
+OTHER_CLEAN += \
+	$(PATH_BIN)/additions/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH).exe \
+	$(PATH_BIN)/additions/VBoxWHQLFake.exe
+
+DRIVER_FILES := \
+	$(PATH_BIN)/additions/VBoxGuestDrvInst.exe \
+	$(PATH_BIN)/additions/RegCleanup.exe \
+	$(PATH_BIN)/additions/VBoxMouse.sys \
+	$(PATH_BIN)/additions/VBoxGuest.sys \
+	$(PATH_BIN)/additions/VBoxVideo.sys \
+	$(PATH_BIN)/additions/VBoxDisp.dll \
+	$(PATH_BIN)/additions/VBoxSF.sys \
+	$(PATH_BIN)/additions/VBoxMRXNP.dll \
+	$(PATH_BIN)/additions/VBoxTray.exe \
+	$(PATH_BIN)/additions/VBoxControl.exe \
+	$(PATH_BIN)/additions/VBoxWHQLFake.exe \
+	$(PATH_BIN)/additions/VBoxService.exe
+ifeq ($(KBUILD_TARGET_ARCH),x86)
+DRIVER_FILES += \
+	$(PATH_BIN)/additions/VBoxMouseNT.sys \
+	$(PATH_BIN)/additions/VBoxGuestNT.sys
+endif
+DRIVER_FILES += \
+	$(PATH_BIN)/additions/VBoxVideo.inf \
+	$(PATH_BIN)/additions/VBoxGuest.inf
+ifdef VBOX_SIGN_ADDITIONS
+DRIVER_FILES += \
+	$(PATH_BIN)/additions/VBoxVideo.cat \
+	$(PATH_BIN)/additions/VBoxGuest.cat
+endif
+ifdef VBOX_WITH_CROGL
+DRIVER_FILES += \
+	$(PATH_BIN)/additions/VBoxOGLarrayspu.dll \
+	$(PATH_BIN)/additions/VBoxOGLcrutil.dll \
+	$(PATH_BIN)/additions/VBoxOGLerrorspu.dll \
+	$(PATH_BIN)/additions/VBoxOGLpackspu.dll \
+	$(PATH_BIN)/additions/VBoxOGLpassthroughspu.dll \
+	$(PATH_BIN)/additions/VBoxOGLfeedbackspu.dll \
+	$$(PATH_BIN)/additions/VBoxOGL.dll
+ ifeq ($(KBUILD_TARGET_ARCH),amd64)
+    # Also include 32-bit DLLs on 64-bit guests to enable
+    # running 32-bit OpenGL apps on that.
+    DRIVER_FILES += \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLarrayspu.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLcrutil.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLerrorspu.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLpackspu.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLpassthroughspu.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGLfeedbackspu.dll \
+		$(VBOX_PATH_ADDITIONS.win.x86)/VBoxOGL.dll
+ endif
+endif
+
+VB_WIN_ADD_NSIS_ENV := \
+	-E 'PATH_OUT=$(subst /,\,$(PATH_OUT))' \
+	-E 'PATH_TARGET=$(subst /,\,$(PATH_TARGET))' \
+	-E 'VBOX_PATH_ADDITIONS_WIN_X86=$(subst /,\,$(VBOX_PATH_ADDITIONS.win.x86))' \
+	-E 'VBOX_VENDOR=$(VBOX_VENDOR)' \
+	-E 'VBOX_VENDOR_SHORT=$(VBOX_VENDOR_SHORT)' \
+	-E 'VBOX_PRODUCT=$(VBOX_PRODUCT)' \
+	-E 'VBOX_C_YEAR=$(VBOX_C_YEAR)' \
+	-E 'VBOX_VERSION_STRING=$(VBOX_VERSION_STRING)' \
+	-E 'VBOX_VERSION_MAJOR=$(VBOX_VERSION_MAJOR)' \
+	-E 'VBOX_VERSION_MINOR=$(VBOX_VERSION_MINOR)' \
+	-E 'VBOX_VERSION_BUILD=$(VBOX_VERSION_BUILD)' \
+	-E 'VBOX_SVN_REV=$(VBOX_SVN_REV)' \
+	-E 'VBOX_WINDOWS_ADDITIONS_ICON_FILE=$(subst /,\,$(VBOX_WINDOWS_ADDITIONS_ICON_FILE))' \
+	-E 'VBOX_NSIS_ICON_FILE=$(subst /,\,$(VBOX_NSIS_ICON_FILE))' \
+	-E 'VBOX_WITH_CROGL=$(if $(VBOX_WITH_CROGL),1,0)' \
+	-E 'VBOX_BRAND_WIN_ADD_INST_DLGBMP=$(subst /,\,$(VBOX_BRAND_WIN_ADD_INST_DLGBMP))' \
+	-E 'VBOX_BRAND_LICENSE_RTF=$(subst /,\,$(VBOX_BRAND_LICENSE_RTF))' \
+	$(foreach lang,$(VBOX_INSTALLER_ADD_LANGUAGES),-E 'VBOX_BRAND_$(lang)_LICENSE_RTF=$(VBOX_BRAND_$(lang)_LICENSE_RTF)') \
+	-E 'BUILD_TYPE=$(KBUILD_TYPE)' \
+	-E 'BUILD_TARGET_ARCH=$(KBUILD_TARGET_ARCH)'
+
+ifdef VBOX_SIGNING_MODE
+#
+# This is a hack to sign the uninstaller.
+# See http://nsis.sourceforge.net/Signing_an_Uninstaller for more details.
+#
+OTHER_CLEAN += $(PATH_TARGET)/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH)-uninst.exe
+
+$(PATH_TARGET)/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH)-uninst.exe: \
+		$(PATH_SUB_CURRENT)/VBoxGuestAdditions.nsi \
+		$(DRIVER_FILES) \
+		$(VBOX_WINDOWS_ADDITIONS_ICON_FILE) \
+		$(VBOX_NSIS_ICON_FILE) \
+		$(VBOX_VERSION_STAMP)\
+		| $$(dir $$@)
+	$(call MSG_L1,Creating $@, from $<)
+	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_WIN_ADD_INS_SRC) \
+		$(VB_WIN_ADD_NSIS_ENV) \
+		-- $(EXEC_X86_WIN32) $(VBOX_PATH_NSIS)/makensis.exe /NOCD /V2 \
+			$(if $(VBOX_SIGN_ADDITIONS),'/DVBOX_SIGN_ADDITIONS=1') \
+			$(if $(VBOX_INSTALLER_ADD_LANGUAGES),'/DVBOX_INSTALLER_ADD_LANGUAGES=1') \
+			$(foreach lang,$(VBOX_INSTALLER_ADD_LANGUAGES),'/DVBOX_BRAND_$(lang)_LICENSE_RTF=1') \
+			'/DUNINSTALLER_ONLY=1' \
+			'$(subst /,\,$<)'
+
+OTHER_CLEAN += $(PATH_TARGET)/uninst.exe
+$(PATH_TARGET)/uninst.exe: $(PATH_TARGET)/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH)-uninst.exe | $$(dir $$@)
+	$(call MSG_L1,Creating $@, from $<)
+	$(QUIET)$(RM) -f $@
+	- $<
+	$(TEST) -f $@
+	$(call VBOX_SIGN_FILE_FN,$@)
+endif
+
+WHQLFAKE := $(PATH_SUB_CURRENT)/VBoxWHQLFake.au3
+
+$(PATH_BIN)/additions/VBoxWHQLFake.exe:
+	$(call MSG_L1,Creating $@, from $<)
+	$(QUIET)$(EXEC_X86_WIN32) $(VBOX_PATH_AUTOIT3)/Aut2Exe/Aut2exe.exe \
+		/in $(WHQLFAKE) \
+		/out $(PATH_BIN)/additions/VBoxWHQLFake.exe \
+		/icon $(VBOX_WINDOWS_ADDITIONS_ICON_FILE) \
+		/comp 4 \
+		/unicode
+
+$(PATH_BIN)/additions/VBoxWindowsAdditions-$(KBUILD_TARGET_ARCH).exe: \
+		$(PATH_SUB_CURRENT)/VBoxGuestAdditions.nsi \
+		$(DRIVER_FILES) \
+		$(VBOX_WINDOWS_ADDITIONS_ICON_FILE) \
+		$(VBOX_NSIS_ICON_FILE) \
+		$(if $(VBOX_SIGNING_MODE),$(PATH_TARGET)/uninst.exe) \
+		$(VBOX_VERSION_STAMP)
+	$(call MSG_L1,Creating $@, from $<)
+	$(QUIET)$(REDIRECT) -C $(VBOX_PATH_WIN_ADD_INS_SRC) \
+		$(VB_WIN_ADD_NSIS_ENV) \
+		-- $(EXEC_X86_WIN32) $(VBOX_PATH_NSIS)/makensis.exe /NOCD /V2 \
+			$(if $(VBOX_SIGN_ADDITIONS),'/DVBOX_SIGN_ADDITIONS=1') \
+			$(if $(VBOX_SIGNING_MODE),'/DEXTERNAL_UNINSTALLER=1') \
+			$(if $(VBOX_INSTALLER_ADD_LANGUAGES),'/DVBOX_INSTALLER_ADD_LANGUAGES=1') \
+			$(foreach lang,$(VBOX_INSTALLER_ADD_LANGUAGES),'/DVBOX_BRAND_$(lang)_LICENSE_RTF=1') \
+			'$(subst /,\,$<)'
+	$(call VBOX_SIGN_FILE_FN,$@)
+
+include $(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.cpp	(revision 31634)
@@ -0,0 +1,83 @@
+/** @file
+ *
+ * delinvalid - remove "InvalidDisplay" key on NT4
+ *
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+/*
+ Purpose:
+
+ Delete the "InvalidDisplay" key which causes the display
+ applet to be started on every boot. For some reason this key
+ isn't removed after setting the proper resolution and even not when
+ doing a driver reinstall. Removing it doesn't seem to do any harm.
+ The key is inserted by windows on first reboot after installing
+ the VBox video driver using the VirtualBox utility.
+ It's not inserted when using the Display applet for installation.
+ There seems to be a subtle problem with the VirtualBox util.
+ */
+
+//#define _UNICODE
+
+#include <windows.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <DEVGUID.h>
+#include <stdio.h>
+
+#include "tchar.h"
+#include "string.h"
+
+/*******************************************************************************
+ *   Defined Constants And Macros                                               *
+ *******************************************************************************/
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+BOOL isNT4 (void)
+{
+    OSVERSIONINFO OSversion;
+
+    OSversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    ::GetVersionEx(&OSversion);
+
+    switch (OSversion.dwPlatformId)
+    {
+    case VER_PLATFORM_WIN32s:
+    case VER_PLATFORM_WIN32_WINDOWS:
+        return FALSE;
+    case VER_PLATFORM_WIN32_NT:
+        if (OSversion.dwMajorVersion == 4)
+            return TRUE;
+        else return FALSE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+    int rc = 0;
+
+    /* This program is only for installing drivers on NT4 */
+    if (!isNT4())
+    {
+        printf("This program only runs on NT4\n");
+        return -1;
+    }
+
+    /* Delete the "InvalidDisplay" key which causes the display
+     applet to be started on every boot. For some reason this key
+     isn't removed after setting the proper resolution and even not when
+     doing a driverreinstall.  */
+    RegDeleteKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\InvalidDisplay"));
+    RegDeleteKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"));
+
+    return rc;
+}
Index: trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/RegCleanup.rc	(revision 31634)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 RegCleanup\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxRegCleanup\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxRegCleanup.exe\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: trunk/src/VBox/Additions/WINNT/Installer/ReplaceDLL.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/ReplaceDLL.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/ReplaceDLL.nsh	(revision 31634)
@@ -0,0 +1,149 @@
+
+
+; Macro - Upgrade DLL File
+; Written by Joost Verburg
+; ------------------------
+;
+; Parameters:
+; LOCALFILE   - Location of the new DLL file (on the compiler system)
+; DESTFILE    - Location of the DLL file that should be upgraded
+;              (on the user's system)
+; TEMPBASEDIR - Directory on the user's system to store a temporary file
+;               when the system has to be rebooted.
+;               For Win9x support, this should be on the same volume as the
+;               DESTFILE!
+;               The Windows temp directory could be located on any volume,
+;               so you cannot use  this directory.
+;
+; Define REPLACEDLL_NOREGISTER if you want to upgrade a DLL that does not
+; have to be registered.
+;
+; Note: If you want to support Win9x, you can only use
+;       short filenames (8.3).
+;
+; Example of usage:
+; !insertmacro ReplaceDLL "dllname.dll" "$SYSDIR\dllname.dll" "$SYSDIR"
+;
+
+!macro ReplaceDLL LOCALFILE DESTFILE TEMPBASEDIR
+
+  Push $R0
+  Push $R1
+  Push $R2
+  Push $R3
+  Push $R4
+  Push $R5
+
+  ;------------------------
+  ;Unique number for labels
+
+  !define REPLACEDLL_UNIQUE ${__LINE__}
+
+  ;------------------------
+  ;Copy the parameters used on run-time to a variable
+  ;This allows the usage of variables as paramter
+
+  StrCpy $R4 "${DESTFILE}"
+  StrCpy $R5 "${TEMPBASEDIR}"
+
+  ;------------------------
+  ;Check file and version
+  ;
+  IfFileExists $R4 0 replacedll.copy_${REPLACEDLL_UNIQUE}
+  
+  ;ClearErrors
+  ;  GetDLLVersionLocal "${LOCALFILE}" $R0 $R1
+  ;  GetDLLVersion $R4 $R2 $R3
+  ;IfErrors replacedll.upgrade_${REPLACEDLL_UNIQUE}
+  ;
+  ;IntCmpU $R0 $R2 0 replacedll.done_${REPLACEDLL_UNIQUE}
+  ;  replacedll.upgrade_${REPLACEDLL_UNIQUE}
+  ;IntCmpU $R1 $R3 replacedll.done_${REPLACEDLL_UNIQUE}
+  ;  replacedll.done_${REPLACEDLL_UNIQUE}
+  ;  replacedll.upgrade_${REPLACEDLL_UNIQUE}
+
+  ;------------------------
+  ;Let's replace the DLL!
+
+  SetOverwrite try
+
+  ;replacedll.upgrade_${REPLACEDLL_UNIQUE}:
+    !ifndef REPLACEDLL_NOREGISTER
+      ;Unregister the DLL
+      UnRegDLL $R4
+    !endif
+
+  ;------------------------
+  ;Try to copy the DLL directly
+
+  ClearErrors
+    StrCpy $R0 $R4
+    Call :replacedll.file_${REPLACEDLL_UNIQUE}
+  IfErrors 0 replacedll.noreboot_${REPLACEDLL_UNIQUE}
+
+  ;------------------------
+  ;DLL is in use. Copy it to a temp file and Rename it on reboot.
+
+  GetTempFileName $R0 $R5
+    Call :replacedll.file_${REPLACEDLL_UNIQUE}
+  Rename /REBOOTOK $R0 $R4
+
+  ;------------------------
+  ;Register the DLL on reboot
+
+  !ifndef REPLACEDLL_NOREGISTER
+    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" \
+      "Register $R4" 'rundll32.exe "$R4",DllRegisterServer'
+  !endif
+
+  Goto replacedll.done_${REPLACEDLL_UNIQUE}
+
+  ;------------------------
+  ;DLL does not exist - just extract
+
+  replacedll.copy_${REPLACEDLL_UNIQUE}:
+    StrCpy $R0 $R4
+    Call :replacedll.file_${REPLACEDLL_UNIQUE}
+
+  ;------------------------
+  ;Register the DLL
+
+  replacedll.noreboot_${REPLACEDLL_UNIQUE}:
+    !ifndef REPLACEDLL_NOREGISTER
+      RegDLL $R4
+    !endif
+
+  ;------------------------
+  ;Done
+
+  replacedll.done_${REPLACEDLL_UNIQUE}:
+
+  Pop $R5
+  Pop $R4
+  Pop $R3
+  Pop $R2
+  Pop $R1
+  Pop $R0
+
+  ;------------------------
+  ;End
+
+  Goto replacedll.end_${REPLACEDLL_UNIQUE}
+
+  ;------------------------
+  ;Called to extract the DLL
+
+  replacedll.file_${REPLACEDLL_UNIQUE}:
+    File /oname=$R0 "${LOCALFILE}"
+    Return
+
+  replacedll.end_${REPLACEDLL_UNIQUE}:
+
+ ;------------------------
+ ;Restore settings
+
+ SetOverwrite lastused
+ 
+ !undef REPLACEDLL_UNIQUE
+
+!macroend
Index: trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.cpp	(revision 31634)
@@ -0,0 +1,331 @@
+// 45678901234567890123456789012345678901234567890123456789012345678901234567890
+//+---------------------------------------------------------------------------
+//
+//  Microsoft Windows
+//  Copyright (C) Microsoft Corporation, 1999.
+//
+//  File:       COINST.C
+//
+//  Contents:   co-installer hook.
+//
+//  Notes:      For a complete description of CoInstallers, please see the
+//                 Microsoft Windows 2000 DDK Documentation
+//
+//  Author:     keithga   4 June 1999
+//
+// Revision History:
+//              Added FriendlyName interface (Eliyas Yakub Aug 2, 1999)
+//
+//----------------------------------------------------------------------------
+
+#undef UNICODE
+#if !defined(_UNICODE) && defined(UNICODE)
+#define _UNICODE
+#endif
+
+#include <windows.h>
+#include <setupapi.h>
+#include <stdio.h>
+#include <tchar.h>
+
+// #define LOG_ENABLED
+
+#ifdef LOG_ENABLED
+#include <stdio.h>
+
+static VOID _dprintf(LPSTR String, ...)
+{
+    va_list va;
+
+    va_start(va, String);
+
+    CHAR Buffer[1024];
+    if (strlen(String) < 1000)
+    {
+        _vsntprintf (Buffer, sizeof(Buffer), String, va);
+
+        FILE *f = fopen ("\\coinst.log", "ab");
+        if (f)
+        {
+            fprintf (f, "%s", Buffer);
+            fclose (f);
+        }
+    }
+
+    va_end (va);
+}
+#define dprintf(a) _dprintf a
+#else
+#define dprintf(a) do {} while (0)
+#endif /* LOG_ENABLED */
+
+//+---------------------------------------------------------------------------
+//
+// WARNING!
+//
+// A Coinstaller must not generate any popup to the user.
+//     it should provide appropriate defaults.
+//
+//  OutputDebugString should be fine...
+//
+#if DBG
+#define DbgOut(Text) OutputDebugString(TEXT("CoInstaller: " Text "\n"))
+#else
+#define DbgOut(Text)
+#endif
+
+/** strip the filename and leave the slash. */
+void StripFilename (TCHAR *psz)
+{
+    TCHAR *pchSep = NULL;
+    TCHAR *pch = psz;
+
+    /* strip of the filename. */
+    for (; *pch; pch++)
+    {
+        if (*pch == '\\' || *pch == '/' || *pch == ':')
+            pchSep = pch + 1;
+    }
+    if (pchSep)
+        *pchSep = '\0';
+    else
+    {
+        psz[0] = '.';
+        psz[1] = '\0';
+    }
+}
+
+/**
+ Check the installation type.
+ This function checks if the currently used
+ INF file not OEMxx.inf. If yes, the user installs the guest additions by hand,
+ if no this is an automated installation.
+ */
+BOOL CheckForNormalInstall (TCHAR *psz)
+{
+    TCHAR *pchSep = NULL;
+    TCHAR *pch = psz;
+
+    /* strip of the filename. */
+    for (; *pch; pch++)
+    {
+        if (*pch == '\\' || *pch == '/' || *pch == ':')
+            pchSep = pch + 1;
+    }
+    if (pchSep)
+    {
+        if (*pchSep == 'o' || *pchSep == 'O')
+            return FALSE;
+        return TRUE;
+    }
+    return TRUE; /* We shouldn't end here... */
+}
+
+ULONG startMouseInstallation (TCHAR *pszVBoxGuestInfName)
+{
+    TCHAR szAppCmd[MAX_PATH];
+    STARTUPINFO sInfo = { 0 };
+    PROCESS_INFORMATION pInfo = { 0 };
+    BOOL fNotAutomated;
+
+    dprintf(("startMouseInstallation: filename = %s\n", pszVBoxGuestInfName));
+
+    /* Check if we do an automated install */
+    fNotAutomated = CheckForNormalInstall(pszVBoxGuestInfName);
+
+    StripFilename(pszVBoxGuestInfName);
+
+    dprintf(("startMouseInstallation: fNotAutomated = %d, filename = %s\n", fNotAutomated, pszVBoxGuestInfName));
+
+    if (fNotAutomated)
+    {
+        /* This is a normal guest installation done by inserting the ISO */
+        _sntprintf(szAppCmd, sizeof(szAppCmd), TEXT("rundll32.exe SETUPAPI.DLL,InstallHinfSection VBoxMouse 132 %sVBoxMouse.inf"), pszVBoxGuestInfName);
+
+        sInfo.cb = sizeof(STARTUPINFO);
+
+        if (CreateProcess(NULL, szAppCmd, NULL, //lpProcessAttributes
+                          NULL, //lpThreadAttributes
+                          FALSE, //bInheritHandles
+                          0, //dwCreationFlags
+                          NULL, //lpEnvironment
+                          NULL, //lpCurrentDirectory,
+                          &sInfo, //lpStartupInfo,
+                          &pInfo)) //lpProcessInformation
+        {
+            DWORD dwExitCode = 0;
+
+            /* Wait for rundll32 to finish and then check the exit code; only then do we know if it succeeded or not! */
+            WaitForSingleObject(pInfo.hProcess, INFINITE);
+            if (GetExitCodeProcess(pInfo.hProcess, &dwExitCode) != 0 && dwExitCode == 0)
+            {
+                //
+                // hook the filter into the mouse class
+                //
+
+                dprintf(("startMouseInstallation: hooking\n"));
+
+                // first determine the GUID of the Mouse class
+                GUID guid;
+                DWORD numGuids;
+                if (SetupDiClassGuidsFromNameEx("Mouse", &guid, 1, &numGuids, NULL, NULL) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+                {
+                    // get the corresponding class registry key
+                    HKEY hkey = SetupDiOpenClassRegKeyEx(&guid, KEY_READ | KEY_WRITE, DIOCR_INSTALLER, NULL, NULL);
+                    if (hkey)
+                    {
+                        // hardcoded value, ours + the standard filter
+                        RegSetValueEx(hkey, "UpperFilters", 0, REG_MULTI_SZ, (const BYTE*)"VBoxMouse\0mouclass\0\0", 20);
+                        RegCloseKey(hkey);
+                    }
+                }
+                CloseHandle(pInfo.hProcess);
+                CloseHandle(pInfo.hThread);
+                dprintf(("startMouseInstallation: return ok\n"));
+                return 0;
+            }
+            CloseHandle(pInfo.hProcess);
+            CloseHandle(pInfo.hThread);
+        } /* CreateProcess() */
+    } /* fNotAutomated */
+    else
+    {
+        /* This is an automated installation */
+
+        //
+        // hook the filter into the mouse class
+        //
+
+        dprintf(("startMouseInstallation: automated\n"));
+
+        // first determine the GUID of the Mouse class
+        GUID guid;
+        DWORD numGuids;
+        if (SetupDiClassGuidsFromNameEx("Mouse", &guid, 1, &numGuids, NULL, NULL) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+        {
+            // get the corresponding class registry key
+            HKEY hkey = SetupDiOpenClassRegKeyEx(&guid, KEY_READ | KEY_WRITE, DIOCR_INSTALLER, NULL, NULL);
+            if (hkey)
+            {
+                // hardcoded value, ours + the standard filter
+                RegSetValueEx(hkey, "UpperFilters", 0, REG_MULTI_SZ, (const BYTE*)"VBoxMouse\0mouclass\0\0", 20);
+                RegCloseKey(hkey);
+            }
+        }
+        return 0;
+    }
+
+    /* bitch to debug output */
+    return -1;
+}
+
+//+---------------------------------------------------------------------------
+//
+//  Function:   VBoxCoInstaller
+//
+//  Purpose:    Responds to co-installer messages
+//
+//  Arguments:
+//      InstallFunction   [in]
+//      DeviceInfoSet     [in]
+//      DeviceInfoData    [in]
+//      Context           [inout]
+//
+//  Returns:    NO_ERROR, ERROR_DI_POSTPROCESSING_REQUIRED, or an error code.
+//
+//  This co-installer is used to install the mouse filter after installation of
+//  the VBoxGuest driver
+extern "C"
+HRESULT WINAPI
+VBoxCoInstaller (
+        IN DI_FUNCTION InstallFunction,
+        IN HDEVINFO DeviceInfoSet,
+        IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
+        IN OUT PCOINSTALLER_CONTEXT_DATA Context
+)
+{
+    dprintf((__DATE__ __TIME__ "VBoxCoInstaller InstallFunction 0x%02X\n", InstallFunction));
+
+    switch (InstallFunction)
+    {
+        case DIF_INSTALLDEVICE:
+        {
+            SP_DEVINSTALL_PARAMS DeviceInstallParams;
+            DeviceInstallParams.cbSize = sizeof (DeviceInstallParams);
+
+            if (!SetupDiGetDeviceInstallParams (DeviceInfoSet,
+                            DeviceInfoData,
+                            &DeviceInstallParams))
+            {
+                dprintf(("Failed to get DeviceInstallParams\n"));
+                return NO_ERROR;
+            }
+
+            /* Reboot the system and do not dynamically load the driver. */
+            DeviceInstallParams.Flags |= DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG;
+
+            if (!SetupDiSetDeviceInstallParams (DeviceInfoSet,
+                            DeviceInfoData,
+                            &DeviceInstallParams))
+            {
+                dprintf(("Failed to set DeviceInstallParams\n"));
+                return NO_ERROR;
+            }
+
+            return NO_ERROR;
+        }
+
+        //        case DIF_REMOVE:
+        //        {
+        //            return NO_ERROR;
+        //        } break;
+#if 0
+        /* This request is only sent when the installation of the VBoxGuest
+         succeeded. Because VBoxMouse needs VBoxGuest to work this is
+         a nice installation prerequisite check, too. */
+        case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
+        {
+            SP_DRVINFO_DATA DriverInfoData;
+            SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
+            HRESULT Status;
+
+            /* Get the path to the VBoxGuest INF. The VBoxMouse INF is in the same
+             directory. */
+            DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
+            if (!SetupDiGetSelectedDriver(DeviceInfoSet,
+                            DeviceInfoData,
+                            &DriverInfoData))
+            {
+                return NO_ERROR; /* Should return an error here? */
+            }
+
+            DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
+            if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
+                            DeviceInfoData,
+                            &DriverInfoData,
+                            &DriverInfoDetailData,
+                            sizeof(SP_DRVINFO_DETAIL_DATA),
+                            NULL))
+            {
+                if ((Status = GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
+                {
+                    // We don't need the extended information.  Ignore.
+                }
+                else
+                {
+                    return NO_ERROR; /* Should return an error here? */
+                }
+            }
+
+            startMouseInstallation(DriverInfoDetailData.InfFileName);
+            break;
+        }
+#endif
+
+        default:
+        break;
+    }
+
+    return NO_ERROR;
+}
+
Index: trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.def
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.def	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.def	(revision 31634)
@@ -0,0 +1,15 @@
+;
+; VBCoInst -- Guest Additions Driver Co Installation Module
+; Copyright (C) 2006-2007 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+LIBRARY  VBCOINST
+
+EXPORTS
+   VBoxCoInstaller
+
+
+
Index: trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBCoInst.rc	(revision 31634)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 CoInst\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxCoInst\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxCoInst.exe\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.cpp	(revision 31634)
@@ -0,0 +1,2200 @@
+/*++
+
+ Copyright (c) Microsoft Corporation.  All rights reserved.
+
+ Module Name:
+
+ VBoxDrvInst.cpp
+
+ Abstract:
+
+ Command-line interface for installing / uninstalling device drivers
+ with a given Hardware-ID (and .INF-file).
+
+ --*/
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#include <VBox/version.h>
+
+#include <windows.h>
+#include <setupapi.h>
+#include <newdev.h>
+#include <regstr.h>
+#include <cfgmgr32.h>
+#include <devguid.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <string.h>
+
+/*#define _DEBUG*/
+
+typedef int (*fnCallback) (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context);
+
+struct IdEntry
+{
+    LPCTSTR szString; /* string looking for */
+    LPCTSTR szWild; /* first wild character if any */
+    BOOL bInstanceId;
+};
+
+#define INSTANCEID_PREFIX_CHAR TEXT('@')    /* character used to prefix instance ID's */
+#define CLASS_PREFIX_CHAR      TEXT('=')    /* character used to prefix class name */
+#define WILD_CHAR              TEXT('*')    /* wild character */
+#define QUOTE_PREFIX_CHAR      TEXT('\'')   /* prefix character to ignore wild characters */
+#define SPLIT_COMMAND_SEP      TEXT(":=")   /* whole word, indicates end of id's */
+
+/* @todo Split this program into several modules:
+
+ - Main
+ - Utility functions
+ - Dynamic API loading
+ - Installation / uninstallation routines
+ - ...
+ */
+
+/* Exit codes */
+#define EXIT_OK      (0)
+#define EXIT_REBOOT  (1)
+#define EXIT_FAIL    (2)
+#define EXIT_USAGE   (3)
+
+/* Dynamic loaded libs */
+HMODULE g_hSetupAPI = NULL;
+HMODULE g_hNewDev = NULL;
+HMODULE g_hCfgMgr = NULL;
+
+/* Function pointers for dynamic loading of some API calls NT4 hasn't ... */
+typedef BOOL (WINAPI *fnSetupDiCreateDeviceInfo) (HDEVINFO DeviceInfoSet, PCTSTR DeviceName, LPGUID ClassGuid, PCTSTR DeviceDescription, HWND hwndParent, DWORD CreationFlags,
+                                                  PSP_DEVINFO_DATA DeviceInfoData);
+fnSetupDiCreateDeviceInfo g_pfnSetupDiCreateDeviceInfo = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiOpenDeviceInfo) (HDEVINFO DeviceInfoSet, PCTSTR DeviceInstanceId, HWND hwndParent, DWORD OpenFlags, PSP_DEVINFO_DATA DeviceInfoData);
+fnSetupDiOpenDeviceInfo g_pfnSetupDiOpenDeviceInfo = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
+fnSetupDiEnumDeviceInfo g_pfnSetupDiEnumDeviceInfo = NULL;
+
+/***/
+
+typedef HDEVINFO (WINAPI *fnSetupDiCreateDeviceInfoList) (LPGUID ClassGuid, HWND hwndParent);
+fnSetupDiCreateDeviceInfoList g_pfnSetupDiCreateDeviceInfoList = NULL;
+
+typedef HDEVINFO (WINAPI *fnSetupDiCreateDeviceInfoListEx) (LPGUID ClassGuid, HWND hwndParent, PCTSTR MachineName, PVOID Reserved);
+fnSetupDiCreateDeviceInfoListEx g_pfnSetupDiCreateDeviceInfoListEx = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiDestroyDriverInfoList) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType);
+fnSetupDiDestroyDriverInfoList g_pfnSetupDiDestroyDriverInfoList = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet);
+fnSetupDiDestroyDeviceInfoList g_pfnSetupDiDestroyDeviceInfoList = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiGetDeviceInfoListDetail) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData);
+fnSetupDiGetDeviceInfoListDetail g_pfnSetupDiGetDeviceInfoListDetail = NULL;
+
+/***/
+
+typedef BOOL (WINAPI *fnSetupDiSetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, CONST BYTE *PropertyBuffer, DWORD PropertyBufferSize);
+fnSetupDiSetDeviceRegistryProperty g_pfnSetupDiSetDeviceRegistryProperty = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer,
+                                                           DWORD PropertyBufferSize, PDWORD RequiredSize);
+fnSetupDiGetDeviceRegistryProperty g_pfnSetupDiGetDeviceRegistryProperty = NULL;
+
+/***/
+
+typedef BOOL (WINAPI *fnSetupDiCallClassInstaller) (DI_FUNCTION InstallFunction, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData);
+fnSetupDiCallClassInstaller g_pfnSetupDiCallClassInstaller = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiClassGuidsFromNameEx) (PCTSTR ClassName, LPGUID ClassGuidList, DWORD ClassGuidListSize, PDWORD RequiredSize, PCTSTR MachineName, PVOID Reserved);
+fnSetupDiClassGuidsFromNameEx g_pfnSetupDiClassGuidsFromNameEx = NULL;
+
+typedef HDEVINFO (WINAPI *fnSetupDiGetClassDevsEx) (LPGUID ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags, HDEVINFO DeviceInfoSet, PCTSTR MachineName, PVOID Reserved);
+fnSetupDiGetClassDevsEx g_pfnSetupDiGetClassDevsEx = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiSetClassInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_CLASSINSTALL_HEADER ClassInstallParams, DWORD ClassInstallParamsSize);
+fnSetupDiSetClassInstallParams g_pfnSetupDiSetClassInstallParams = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiGetDeviceInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS DeviceInstallParams);
+fnSetupDiGetDeviceInstallParams g_pfnSetupDiGetDeviceInstallParams = NULL;
+
+typedef HKEY (WINAPI *fnSetupDiOpenDevRegKey) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Scope, DWORD HwProfile, DWORD KeyType, REGSAM samDesired);
+fnSetupDiOpenDevRegKey g_pfnSetupDiOpenDevRegKey = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiBuildDriverInfoList) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType);
+fnSetupDiBuildDriverInfoList g_pfnSetupDiBuildDriverInfoList = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiEnumDriverInfo) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType, DWORD MemberIndex, PSP_DRVINFO_DATA DriverInfoData);
+fnSetupDiEnumDriverInfo g_pfnSetupDiEnumDriverInfo = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiGetDriverInfoDetail) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData, PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
+                                                     DWORD DriverInfoDetailDataSize, PDWORD RequiredSize);
+fnSetupDiGetDriverInfoDetail g_pfnSetupDiGetDriverInfoDetail = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiSetSelectedDriver) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData);
+fnSetupDiSetSelectedDriver g_pfnSetupDiSetSelectedDriver = NULL;
+
+typedef BOOL (WINAPI *fnSetupDiSetDeviceInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS DeviceInstallParams);
+fnSetupDiSetDeviceInstallParams g_pfnSetupDiSetDeviceInstallParams = NULL;
+
+typedef CONFIGRET (WINAPI *fnCM_Get_Device_ID_Ex) (DEVINST dnDevInst, PTCHAR Buffer, ULONG BufferLen, ULONG ulFlags, HMACHINE hMachine);
+fnCM_Get_Device_ID_Ex g_pfnCM_Get_Device_ID_Ex = NULL;
+
+typedef BOOL (WINAPI* fnSetupCopyOEMInf) (PCTSTR SourceInfFileName, PCTSTR OEMSourceMediaLocation, DWORD OEMSourceMediaType, DWORD CopyStyle, PTSTR DestinationInfFileName,
+                                          DWORD DestinationInfFileNameSize, PDWORD RequiredSize, PTSTR DestinationInfFileNameComponent);
+fnSetupCopyOEMInf g_pfnSetupCopyOEMInf = NULL;
+
+typedef BOOL (WINAPI* fnUpdateDriverForPlugAndPlayDevices) (HWND hwndParent, LPCTSTR HardwareId, LPCTSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired);
+fnUpdateDriverForPlugAndPlayDevices g_pfnUpdateDriverForPlugAndPlayDevices = NULL;
+
+#define VBOX_LOAD_API( a_hModule, a_Func )                                 \
+{                                                                          \
+    g_pfn##a_Func = (fn##a_Func)GetProcAddress(a_hModule, "##a_Func");     \
+    _tprintf (_T("API call ##a_Func loaded: %p\n"), g_pfn##a_Func);  \
+}
+
+int LoadAPICalls ()
+{
+    int rc = ERROR_SUCCESS;
+    OSVERSIONINFO OSinfo;
+    OSinfo.dwOSVersionInfoSize = sizeof(OSinfo);
+    GetVersionEx(&OSinfo);
+
+#ifdef _DEBUG
+    _tprintf (_T("Loading API calls ...\n"));
+#endif
+
+    /* Use unicode calls where available. */
+    if (OSinfo.dwMajorVersion >= 5) /* APIs available only on W2K and up! */
+    {
+        g_hSetupAPI = LoadLibrary(_T("SetupAPI"));
+        if (NULL == g_hSetupAPI)
+        {
+            _tprintf(_T("ERROR: SetupAPI.dll not found! Return code: %d\n"), GetLastError());
+            rc = ERROR_NOT_INSTALLED;
+        }
+        else
+        {
+            g_pfnSetupDiCreateDeviceInfoList = (fnSetupDiCreateDeviceInfoList)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoList");
+            g_pfnSetupDiCreateDeviceInfo = (fnSetupDiCreateDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoW");
+            g_pfnSetupDiSetDeviceRegistryProperty = (fnSetupDiSetDeviceRegistryProperty)GetProcAddress(g_hSetupAPI, "SetupDiSetDeviceRegistryPropertyW");
+            g_pfnSetupDiCallClassInstaller = (fnSetupDiCallClassInstaller)GetProcAddress(g_hSetupAPI, "SetupDiCallClassInstaller");
+            g_pfnSetupDiDestroyDeviceInfoList = (fnSetupDiDestroyDeviceInfoList)GetProcAddress(g_hSetupAPI, "SetupDiDestroyDeviceInfoList");
+            g_pfnSetupDiClassGuidsFromNameEx = (fnSetupDiClassGuidsFromNameEx)GetProcAddress(g_hSetupAPI, "SetupDiClassGuidsFromNameExW");
+            g_pfnSetupDiGetDeviceRegistryProperty = (fnSetupDiGetDeviceRegistryProperty)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceRegistryPropertyW");
+            g_pfnSetupDiGetClassDevsEx = (fnSetupDiGetClassDevsEx)GetProcAddress(g_hSetupAPI, "SetupDiGetClassDevsExW");
+            g_pfnSetupDiCreateDeviceInfoListEx = (fnSetupDiCreateDeviceInfoListEx)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoListExW");
+            g_pfnSetupDiOpenDeviceInfo = (fnSetupDiOpenDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiOpenDeviceInfoW");
+            g_pfnSetupDiGetDeviceInfoListDetail = (fnSetupDiGetDeviceInfoListDetail)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceInfoListDetailW");
+            g_pfnSetupDiEnumDeviceInfo = (fnSetupDiEnumDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiEnumDeviceInfo");
+            g_pfnSetupDiSetClassInstallParams = (fnSetupDiSetClassInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiSetClassInstallParamsW");
+            g_pfnSetupDiGetDeviceInstallParams = (fnSetupDiGetDeviceInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceInstallParamsW");
+            g_pfnSetupDiOpenDevRegKey = (fnSetupDiOpenDevRegKey)GetProcAddress(g_hSetupAPI, "SetupDiOpenDevRegKey");
+            g_pfnSetupDiBuildDriverInfoList = (fnSetupDiBuildDriverInfoList)GetProcAddress(g_hSetupAPI, "SetupDiBuildDriverInfoList");
+            g_pfnSetupDiEnumDriverInfo = (fnSetupDiEnumDriverInfo)GetProcAddress(g_hSetupAPI, "SetupDiEnumDriverInfoW");
+            g_pfnSetupDiGetDriverInfoDetail = (fnSetupDiGetDriverInfoDetail)GetProcAddress(g_hSetupAPI, "SetupDiGetDriverInfoDetailW");
+            g_pfnSetupDiDestroyDriverInfoList = (fnSetupDiDestroyDriverInfoList)GetProcAddress(g_hSetupAPI, "SetupDiDestroyDriverInfoList");
+            g_pfnSetupDiSetSelectedDriver = (fnSetupDiSetSelectedDriver)GetProcAddress(g_hSetupAPI, "SetupDiSetSelectedDriverW");
+            g_pfnSetupDiSetDeviceInstallParams = (fnSetupDiSetDeviceInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiSetDeviceInstallParamsW");
+            g_pfnSetupCopyOEMInf = (fnSetupCopyOEMInf)GetProcAddress(g_hSetupAPI, "SetupCopyOEMInfW");
+        }
+
+        if (rc == ERROR_SUCCESS)
+        {
+            g_hNewDev = LoadLibrary(_T("NewDev"));
+            if (NULL != g_hNewDev)
+            {
+                g_pfnUpdateDriverForPlugAndPlayDevices = (fnUpdateDriverForPlugAndPlayDevices)GetProcAddress(g_hNewDev, "UpdateDriverForPlugAndPlayDevicesW");
+            }
+            else
+            {
+                _tprintf(_T("ERROR: NewDev.dll not found! Return code: %d\n"), GetLastError());
+                rc = ERROR_FILE_NOT_FOUND;
+            }
+        }
+
+        if (rc == ERROR_SUCCESS)
+        {
+            g_hCfgMgr = LoadLibrary(_T("CfgMgr32"));
+            if (NULL != g_hCfgMgr)
+            {
+                g_pfnCM_Get_Device_ID_Ex = (fnCM_Get_Device_ID_Ex)GetProcAddress(g_hCfgMgr, "CM_Get_Device_ID_ExW");
+            }
+            else
+            {
+                _tprintf(_T("ERROR: NewDev.dll not found! Return code: %d\n"), GetLastError());
+                rc = ERROR_FILE_NOT_FOUND;
+            }
+        }
+    }
+    else if (OSinfo.dwMajorVersion <= 4) /* Windows NT 4.0. */
+    {
+        /* Nothing to do here yet. */
+    }
+    else /* Other platforms */
+    {
+        _tprintf(_T("ERROR: Platform not supported yet!\n"));
+        rc = ERROR_NOT_SUPPORTED;
+    }
+
+    return rc;
+}
+
+void FreeAPICalls ()
+{
+#ifdef _DEBUG
+    _tprintf (_T("Freeing API calls ...\n"));
+#endif
+
+    if (NULL != g_hSetupAPI)
+        FreeLibrary(g_hSetupAPI);
+
+    if (NULL != g_hNewDev)
+        FreeLibrary(g_hNewDev);
+
+    if (NULL != g_hCfgMgr)
+        FreeLibrary(g_hCfgMgr);
+}
+
+bool GetErrorMsg (DWORD a_dwLastError, _TCHAR* a_pszMsg, DWORD a_dwBufSize)
+{
+    if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, a_dwLastError, 0, a_pszMsg, a_dwBufSize, NULL) == 0)
+    {
+        _stprintf(a_pszMsg, _T("Unknown error!\n"), a_dwLastError);
+        return false;
+    }
+    else
+    {
+        _TCHAR* p = _tcschr(a_pszMsg, _T('\r'));
+
+        if (p != NULL)
+            *p = _T('\0');
+    }
+
+    return true;
+}
+
+/* @todo Add exception handling instead of crappy goto's! */
+
+int CreateDevice (_TCHAR* a_pszHwID, GUID a_devClass)
+{
+    int iRet = EXIT_OK;
+    HDEVINFO devInfoSet;
+    SP_DEVINFO_DATA devInfoData;
+    DWORD dwErr = 0;
+    _TCHAR szErrMsg[_MAX_PATH + 1] = { 0 };
+
+    _tprintf(_T("Creating device ...\n"));
+
+    devInfoSet = g_pfnSetupDiCreateDeviceInfoList(&a_devClass, NULL);
+    if (devInfoSet == INVALID_HANDLE_VALUE)
+    {
+        _tprintf(_T("Could not build device info list!\n"));
+        return EXIT_FAIL;
+    }
+
+    devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+    if (FALSE == g_pfnSetupDiCreateDeviceInfo(devInfoSet, a_pszHwID, &a_devClass, NULL, NULL, DICD_GENERATE_ID, &devInfoData))
+    {
+        dwErr = GetLastError();
+
+        switch (dwErr)
+        {
+
+        case ERROR_DEVINST_ALREADY_EXISTS:
+
+            _tprintf(_T("Device already exists.\n"));
+            break;
+
+        case ERROR_CLASS_MISMATCH:
+
+            _tprintf(_T("ERROR: Device does not match to class ID!\n"));
+            break;
+
+        case ERROR_INVALID_USER_BUFFER:
+
+            _tprintf(_T("ERROR: Invalid user buffer!\n"));
+            break;
+
+        case ERROR_INVALID_DEVINST_NAME:
+
+            _tprintf(_T("ERROR: Invalid device instance name!\n"));
+            break;
+
+        default:
+
+            GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg));
+            _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg);
+            break;
+        }
+
+        iRet = EXIT_FAIL;
+        goto InstallCleanup;
+    }
+
+    if (FALSE == g_pfnSetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, (LPBYTE)a_pszHwID, (DWORD)((_tcsclen(a_pszHwID) + 2) * sizeof(_TCHAR))))
+    {
+        dwErr = GetLastError();
+        _tprintf(_T("Could not set device registry info!\n"));
+        iRet = EXIT_FAIL;
+        goto InstallCleanup;
+    }
+
+    if (FALSE == g_pfnSetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))
+    {
+        dwErr = GetLastError();
+        _tprintf(_T("Could not register device!\n"));
+        iRet = EXIT_FAIL;
+        goto InstallCleanup;
+    }
+
+    InstallCleanup: g_pfnSetupDiDestroyDeviceInfoList(devInfoSet);
+
+    return iRet;
+}
+
+int InstallDriver (_TCHAR* a_pszInfFile, _TCHAR* a_pszHwID, _TCHAR* a_pszDevClass)
+{
+    DWORD dwErr = 0;
+    BOOL bReboot = FALSE;
+
+    _TCHAR szInf[_MAX_PATH] = { 0 }; /* Full path + .INF file */
+    _TCHAR szInfPath[_MAX_PATH] = { 0 }; /* Full path to .INF file */
+    GUID devClassArr[32]; /* The device class GUID  array */
+    DWORD dwReqSize = 0; /* Number of GUIDs in array after lookup */
+
+    _tprintf(_T("Installing driver ...\n"));
+    _tprintf(_T("HardwareID: %ws\n"), a_pszHwID);
+    _tprintf(_T("Device class name: %ws\n"), a_pszDevClass);
+
+    /* Retrieve GUID of device class */
+    /* Not used here: g_pfnSetupDiClassNameFromGuidEx( ... ) */
+    if (FALSE == g_pfnSetupDiClassGuidsFromNameEx(a_pszDevClass, devClassArr, 32, &dwReqSize, NULL, NULL))
+    {
+        _tprintf(_T("Could not retrieve device class GUID! Error: %ld\n"), GetLastError());
+        return EXIT_FAIL;
+    }
+    else
+    {
+        /* Do not fail if dwReqSize is 0. For whatever reason Windows Server 2008 Core does not have the "Media"
+           device class installed. Maybe they stripped down too much? :-/ */
+        if (dwReqSize <= 0)
+        {
+            _tprintf(_T("WARNING: No device class with this name found! ReqSize: %ld, Error: %ld\n"), dwReqSize, GetLastError());
+        }
+        else
+        {
+            _tprintf(_T("Number of GUIDs found: %ld\n"), dwReqSize);
+        }
+
+        /* Not needed for now!
+        if (EXIT_FAIL == CreateDevice (a_pszHwID, devClassArr[0]))
+            return EXIT_FAIL;*/
+    }
+
+    _TCHAR* pcFile = NULL;
+    if (0 == GetFullPathName(a_pszInfFile, _MAX_PATH, szInf, &pcFile))
+    {
+        dwErr = GetLastError();
+
+        _tprintf(_T("ERROR: INF-Path too long / could not be retrieved!\n"));
+        return EXIT_FAIL;
+    }
+
+    /* Extract path from path+INF */
+    if (pcFile != NULL)
+        _tcsnccpy(szInfPath, szInf, pcFile - szInf);
+
+    _tprintf(_T("INF-File: %ws\n"), szInf);
+    _tprintf(_T("INF-Path: %ws\n"), szInfPath);
+
+    _tprintf(_T("Updating driver for plug'n play devices ...\n"));
+    if (!g_pfnUpdateDriverForPlugAndPlayDevices(NULL, a_pszHwID, szInf, INSTALLFLAG_FORCE, &bReboot))
+    {
+        DWORD dwErr = GetLastError();
+        _TCHAR szErrMsg[_MAX_PATH + 1] = { 0 };
+
+        if (dwErr == ERROR_NO_SUCH_DEVINST)
+        {
+            _TCHAR szDestInf[_MAX_PATH] = { 0 };
+            _tprintf(_T("The device is not plugged in (yet), pre-installing drivers ...\n"));
+
+            if (FALSE == g_pfnSetupCopyOEMInf(szInf, szInfPath, SPOST_PATH, 0, szDestInf, sizeof(szDestInf), NULL, NULL))
+            {
+                dwErr = GetLastError();
+                GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg));
+                _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg);
+                return EXIT_FAIL;
+            }
+
+            _tprintf(_T("OK. Installed to: %ws\n"), szDestInf);
+            return EXIT_OK;
+        }
+
+        switch (dwErr)
+        {
+
+        case ERROR_INVALID_FLAGS:
+
+            _tprintf(_T("ERROR: The value specified for InstallFlags is invalid!\n"));
+            break;
+
+        case ERROR_NO_MORE_ITEMS:
+
+            _tprintf(
+                     _T(
+                        "ERROR: The function found a match for the HardwareId value, but the specified driver was not a better match than the current driver and the caller did not specify the INSTALLFLAG_FORCE flag!\n"));
+            break;
+
+        case ERROR_FILE_NOT_FOUND:
+
+            _tprintf(_T("ERROR: File not found!\n"));
+            break;
+
+        case ERROR_IN_WOW64:
+
+            _tprintf(_T("ERROR: The calling application is a 32-bit application attempting to execute in a 64-bit environment, which is not allowed!"));
+            break;
+
+        case ERROR_NO_DRIVER_SELECTED:
+
+            _tprintf(_T("ERROR: No driver in .INF-file selected!\n"));
+            break;
+
+        case ERROR_SECTION_NOT_FOUND:
+
+            _tprintf(_T("ERROR: Section in .INF-file was not found!\n"));
+            break;
+
+        default:
+
+            /* Try error lookup with GetErrorMsg() */
+            GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg));
+            _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg);
+            break;
+        }
+
+        return EXIT_FAIL;
+    }
+
+    _tprintf(_T("Installation successful.\n"));
+
+    return EXIT_OK;
+}
+
+/*++
+
+ Routine Description:
+
+ Determine if this is instance id or hardware id and if there's any wildcards
+ instance ID is prefixed by '@'
+ wildcards are '*'
+
+
+ Arguments:
+
+ Id - ptr to string to check
+
+ Return Value:
+
+ IdEntry
+
+ --*/
+IdEntry GetIdType (LPCTSTR Id)
+{
+    IdEntry Entry;
+
+    Entry.bInstanceId = FALSE;
+    Entry.szWild = NULL;
+    Entry.szString = Id;
+
+    if (Entry.szString[0] == INSTANCEID_PREFIX_CHAR)
+    {
+        Entry.bInstanceId = TRUE;
+        Entry.szString = CharNext(Entry.szString);
+    }
+    if (Entry.szString[0] == QUOTE_PREFIX_CHAR)
+    {
+        /* prefix to treat rest of string literally */
+        Entry.szString = CharNext(Entry.szString);
+    }
+    else
+    {
+        /* see if any wild characters exist */
+        Entry.szWild = _tcschr(Entry.szString, WILD_CHAR);
+    }
+    return Entry;
+}
+
+/*++
+
+ Routine Description:
+
+ Get an index array pointing to the MultiSz passed in
+
+ Arguments:
+
+ MultiSz - well formed multi-sz string
+
+ Return Value:
+
+ array of strings. last entry+1 of array contains NULL
+ returns NULL on failure
+
+ --*/
+LPTSTR * GetMultiSzIndexArray (LPTSTR MultiSz)
+{
+    LPTSTR scan;
+    LPTSTR * array;
+    int elements;
+
+    for (scan = MultiSz, elements = 0; scan[0]; elements++)
+    {
+        scan += lstrlen(scan) + 1;
+    }
+    array = new LPTSTR[elements + 2];
+    if (!array)
+    {
+        return NULL;
+    }
+    array[0] = MultiSz;
+    array++;
+    if (elements)
+    {
+        for (scan = MultiSz, elements = 0; scan[0]; elements++)
+        {
+            array[elements] = scan;
+            scan += lstrlen(scan) + 1;
+        }
+    }
+    array[elements] = NULL;
+    return array;
+}
+
+/*++
+
+ Routine Description:
+
+ Deletes the string array allocated by GetDevMultiSz/GetRegMultiSz/GetMultiSzIndexArray
+
+ Arguments:
+
+ Array - pointer returned by GetMultiSzIndexArray
+
+ Return Value:
+
+ None
+
+ --*/
+void DelMultiSz (LPTSTR * Array)
+{
+    if (Array)
+    {
+        Array--;
+        if (Array[0])
+        {
+            delete[] Array[0];
+        }
+        delete[] Array;
+    }
+}
+
+/*++
+
+ Routine Description:
+
+ Get a multi-sz device property
+ and return as an array of strings
+
+ Arguments:
+
+ Devs    - HDEVINFO containing DevInfo
+ DevInfo - Specific device
+ Prop    - SPDRP_HARDWAREID or SPDRP_COMPATIBLEIDS
+
+ Return Value:
+
+ array of strings. last entry+1 of array contains NULL
+ returns NULL on failure
+
+ --*/
+LPTSTR * GetDevMultiSz (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Prop)
+{
+    LPTSTR buffer;
+    DWORD size;
+    DWORD reqSize;
+    DWORD dataType;
+    LPTSTR * array;
+    DWORD szChars;
+
+    size = 8192; /* initial guess, nothing magic about this */
+    buffer = new TCHAR[(size / sizeof(TCHAR)) + 2];
+    if (!buffer)
+    {
+        return NULL;
+    }
+    while (!g_pfnSetupDiGetDeviceRegistryProperty(Devs, DevInfo, Prop, &dataType, (LPBYTE)buffer, size, &reqSize))
+    {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+        {
+            goto failed;
+        }
+        if (dataType != REG_MULTI_SZ)
+        {
+            goto failed;
+        }
+        size = reqSize;
+        delete[] buffer;
+        buffer = new TCHAR[(size / sizeof(TCHAR)) + 2];
+        if (!buffer)
+        {
+            goto failed;
+        }
+    }
+    szChars = reqSize / sizeof(TCHAR);
+    buffer[szChars] = TEXT('\0');
+    buffer[szChars + 1] = TEXT('\0');
+    array = GetMultiSzIndexArray(buffer);
+    if (array)
+    {
+        return array;
+    }
+
+    failed: if (buffer)
+    {
+        delete[] buffer;
+    }
+    return NULL;
+}
+
+/*++
+
+ Routine Description:
+
+ Compare a single item against wildcard
+ I'm sure there's better ways of implementing this
+ Other than a command-line management tools
+ it's a bad idea to use wildcards as it implies
+ assumptions about the hardware/instance ID
+ eg, it might be tempting to enumerate root\* to
+ find all root devices, however there is a CfgMgr
+ API to query status and determine if a device is
+ root enumerated, which doesn't rely on implementation
+ details.
+
+ Arguments:
+
+ Item - item to find match for eg a\abcd\c
+ MatchEntry - eg *\*bc*\*
+
+ Return Value:
+
+ TRUE if any match, otherwise FALSE
+
+ --*/
+BOOL WildCardMatch (LPCTSTR Item, const IdEntry & MatchEntry)
+{
+    LPCTSTR scanItem;
+    LPCTSTR wildMark;
+    LPCTSTR nextWild;
+    size_t matchlen;
+
+    /* Before attempting anything else,
+     try and compare everything up to first wild */
+    //
+    if (!MatchEntry.szWild)
+    {
+        return _tcsicmp(Item, MatchEntry.szString) ? FALSE : TRUE;
+    }
+    if (_tcsnicmp(Item, MatchEntry.szString, MatchEntry.szWild - MatchEntry.szString) != 0)
+    {
+        return FALSE;
+    }
+    wildMark = MatchEntry.szWild;
+    scanItem = Item + (MatchEntry.szWild - MatchEntry.szString);
+
+    for (; wildMark[0];)
+    {
+        /* If we get here, we're either at or past a wildcard */
+        if (wildMark[0] == WILD_CHAR)
+        {
+            /* So skip wild chars */
+            wildMark = CharNext(wildMark);
+            continue;
+        }
+
+        /* Find next wild-card */
+        nextWild = _tcschr(wildMark, WILD_CHAR);
+
+        if (nextWild)
+        {
+            /* Substring */
+            matchlen = nextWild - wildMark;
+        }
+        else
+        {
+            /* Last portion of match */
+            size_t scanlen = lstrlen(scanItem);
+            matchlen = lstrlen(wildMark);
+
+            if (scanlen < matchlen)
+            {
+                return FALSE;
+            }
+
+            return _tcsicmp(scanItem + scanlen - matchlen, wildMark) ? FALSE : TRUE;
+        }
+
+        if (_istalpha(wildMark[0]))
+        {
+            /* Scan for either lower or uppercase version of first character */
+            TCHAR u = _totupper(wildMark[0]);
+            TCHAR l = _totlower(wildMark[0]);
+            while (scanItem[0] && scanItem[0] != u && scanItem[0] != l)
+            {
+                scanItem = CharNext(scanItem);
+            }
+
+            if (!scanItem[0])
+            {
+                /* Ran out of string */
+                return FALSE;
+            }
+        }
+        else
+        {
+            /* Scan for first character (no case) */
+            scanItem = _tcschr(scanItem, wildMark[0]);
+            if (!scanItem)
+            {
+                /* Ran out of string */
+                return FALSE;
+            }
+        }
+
+        /* Try and match the sub-string at wildMark against scanItem */
+        if (_tcsnicmp(scanItem, wildMark, matchlen) != 0)
+        {
+            /* Nope, try again */
+            scanItem = CharNext(scanItem);
+            continue;
+        }
+
+        /* Substring matched */
+        scanItem += matchlen;
+        wildMark += matchlen;
+    }
+    return (wildMark[0] ? FALSE : TRUE);
+}
+
+/*++
+
+ Routine Description:
+
+ Compares all strings in Array against Id
+ Use WildCardMatch to do real compare
+
+ Arguments:
+
+ Array - pointer returned by GetDevMultiSz
+ MatchEntry - string to compare against
+
+ Return Value:
+
+ TRUE if any match, otherwise FALSE
+
+ --*/
+BOOL WildCompareHwIds (LPTSTR * Array, const IdEntry & MatchEntry)
+{
+    if (Array)
+    {
+        while (Array[0])
+        {
+            if (WildCardMatch(Array[0], MatchEntry))
+            {
+                return TRUE;
+            }
+            Array++;
+        }
+    }
+    return FALSE;
+}
+
+/*++
+
+ Routine Description:
+
+ Generic enumerator for devices that will be passed the following arguments:
+ <id> [<id>...]
+ =<class> [<id>...]
+ where <id> can either be @instance-id, or hardware-id and may contain wildcards
+ <class> is a class name
+
+ Arguments:
+
+ BaseName - name of executable
+ Machine  - name of machine to enumerate
+ Flags    - extra enumeration flags (eg DIGCF_PRESENT)
+ argc/argv - remaining arguments on command line
+ Callback - function to call for each hit
+ Context  - data to pass function for each hit
+
+ Return Value:
+
+ EXIT_xxxx
+
+ --*/
+int EnumerateDevices (LPCTSTR BaseName, LPCTSTR Machine, DWORD Flags, int argc, LPTSTR argv[], fnCallback Callback, LPVOID Context)
+{
+    HDEVINFO devs = INVALID_HANDLE_VALUE;
+    IdEntry * templ = NULL;
+    int failcode = EXIT_FAIL;
+    int retcode;
+    int argIndex;
+    DWORD devIndex;
+    SP_DEVINFO_DATA devInfo;
+    SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
+    BOOL doSearch = FALSE;
+    BOOL match;
+    BOOL all = FALSE;
+    GUID cls;
+    DWORD numClass = 0;
+    int skip = 0;
+
+    if (!argc)
+    {
+        return EXIT_USAGE;
+    }
+
+    templ = new IdEntry[argc];
+    if (!templ)
+    {
+        goto final;
+    }
+
+    /* Determine if a class is specified */
+    if (argc > skip && argv[skip][0] == CLASS_PREFIX_CHAR && argv[skip][1])
+    {
+        if (!g_pfnSetupDiClassGuidsFromNameEx(argv[skip] + 1, &cls, 1, &numClass, Machine, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+        {
+            goto final;
+        }
+        if (!numClass)
+        {
+            failcode = EXIT_OK;
+            goto final;
+        }
+        skip++;
+    }
+
+    if (argc > skip && argv[skip][0] == WILD_CHAR && !argv[skip][1])
+    {
+        /* Catch convinient case of specifying a single argument '*' */
+        all = TRUE;
+        skip++;
+    }
+    else if (argc <= skip)
+    {
+        /* At least one parameter, but no <id>'s */
+        all = TRUE;
+    }
+
+    /* Determine if any instance id's were specified */
+
+    /* Note, if =<class> was specified with no id's
+     we'll mark it as not doSearch
+     but will go ahead and add them all */
+    for (argIndex = skip; argIndex < argc; argIndex++)
+    {
+        templ[argIndex] = GetIdType(argv[argIndex]);
+        if (templ[argIndex].szWild || !templ[argIndex].bInstanceId)
+        {
+            /* Anything other than simple bInstanceId's require a search */
+            doSearch = TRUE;
+        }
+    }
+    if (doSearch || all)
+    {
+        /* Add all id's to list
+         If there's a class, filter on specified class */
+        devs = g_pfnSetupDiGetClassDevsEx(numClass ? &cls : NULL, NULL, NULL, (numClass ? 0 : DIGCF_ALLCLASSES) | Flags, NULL, Machine, NULL);
+
+    }
+    else
+    {
+        /* Blank list, we'll add instance id's by hand */
+        devs = g_pfnSetupDiCreateDeviceInfoListEx(numClass ? &cls : NULL, NULL, Machine, NULL);
+    }
+    if (devs == INVALID_HANDLE_VALUE)
+    {
+        goto final;
+    }
+    for (argIndex = skip; argIndex < argc; argIndex++)
+    {
+        /* Add explicit instances to list (even if enumerated all,
+         this gets around DIGCF_PRESENT)
+         do this even if wildcards appear to be detected since they
+         might actually be part of the instance ID of a non-present device */
+        if (templ[argIndex].bInstanceId)
+        {
+            g_pfnSetupDiOpenDeviceInfo(devs, templ[argIndex].szString, NULL, 0, NULL);
+        }
+    }
+
+    devInfoListDetail.cbSize = sizeof(devInfoListDetail);
+    if (!g_pfnSetupDiGetDeviceInfoListDetail(devs, &devInfoListDetail))
+    {
+        goto final;
+    }
+
+    /* Now enumerate them */
+    if (all)
+    {
+        doSearch = FALSE;
+    }
+
+    devInfo.cbSize = sizeof(devInfo);
+    for (devIndex = 0; g_pfnSetupDiEnumDeviceInfo(devs, devIndex, &devInfo); devIndex++)
+    {
+
+        if (doSearch)
+        {
+            for (argIndex = skip, match = FALSE; (argIndex < argc) && !match; argIndex++)
+            {
+                TCHAR devID[MAX_DEVICE_ID_LEN];
+                LPTSTR *hwIds = NULL;
+                LPTSTR *compatIds = NULL;
+
+                /* Determine instance ID */
+                if (g_pfnCM_Get_Device_ID_Ex(devInfo.DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle) != CR_SUCCESS)
+                {
+                    devID[0] = TEXT('\0');
+                }
+
+                if (templ[argIndex].bInstanceId)
+                {
+                    /* Match on the instance ID */
+                    if (WildCardMatch(devID, templ[argIndex]))
+                        match = TRUE;
+
+                }
+                else
+                {
+                    /* Determine hardware ID's and search for matches */
+                    hwIds = GetDevMultiSz(devs, &devInfo, SPDRP_HARDWAREID);
+                    compatIds = GetDevMultiSz(devs, &devInfo, SPDRP_COMPATIBLEIDS);
+
+                    if (WildCompareHwIds(hwIds, templ[argIndex]) || WildCompareHwIds(compatIds, templ[argIndex]))
+                    {
+                        match = TRUE;
+                    }
+                }
+                DelMultiSz(hwIds);
+                DelMultiSz(compatIds);
+            }
+        }
+        else
+        {
+            match = TRUE;
+        }
+        if (match)
+        {
+            retcode = Callback(devs, &devInfo, devIndex, Context);
+            if (retcode)
+            {
+                failcode = retcode;
+                goto final;
+            }
+        }
+    }
+
+    failcode = EXIT_OK;
+
+    final: if (templ)
+    {
+        delete[] templ;
+    }
+    if (devs != INVALID_HANDLE_VALUE)
+    {
+        g_pfnSetupDiDestroyDeviceInfoList(devs);
+    }
+    return failcode;
+
+}
+
+/*++
+
+ Routine Description:
+
+ Callback for use by Remove
+ Invokes DIF_REMOVE
+ uses g_pfnSetupDiCallClassInstaller so cannot be done for remote devices
+ Don't use CM_xxx API's, they bypass class/co-installers and this is bad.
+
+ Arguments:
+
+ Devs    )_ uniquely identify the device
+ DevInfo )
+ Index    - index of device
+ Context  - GenericContext
+
+ Return Value:
+
+ EXIT_xxxx
+
+ --*/
+int UninstallCallback (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context)
+{
+    SP_REMOVEDEVICE_PARAMS rmdParams;
+    SP_DEVINSTALL_PARAMS devParams;
+    LPCTSTR action = NULL;
+
+    /* Need hardware ID before trying to remove, as we wont have it after */
+    TCHAR devID[MAX_DEVICE_ID_LEN];
+    SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
+
+    devInfoListDetail.cbSize = sizeof(devInfoListDetail);
+
+    if ((!g_pfnSetupDiGetDeviceInfoListDetail(Devs, &devInfoListDetail)) || (g_pfnCM_Get_Device_ID_Ex(DevInfo->DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle)
+            != CR_SUCCESS))
+    {
+        /* Skip this */
+        return EXIT_OK;
+    }
+
+    rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+    rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+    rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
+    rmdParams.HwProfile = 0;
+
+    if (!g_pfnSetupDiSetClassInstallParams(Devs, DevInfo, &rmdParams.ClassInstallHeader, sizeof(rmdParams)) || !g_pfnSetupDiCallClassInstaller(DIF_REMOVE, Devs, DevInfo))
+    {
+        /* Failed to invoke DIF_REMOVE, TODO! */
+        _tprintf(_T("Failed to invoke interface!\n"));
+        return EXIT_FAIL;
+    }
+
+    /* See if device needs reboot */
+    devParams.cbSize = sizeof(devParams);
+    if (g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &devParams) && (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)))
+    {
+        /* Reboot required */
+        _tprintf(_T("To fully uninstall, a reboot is required!\n"));
+    }
+    else
+    {
+        /* Appears to have succeeded */
+        _tprintf(_T("Uninstall succeeded!\n"));
+    }
+
+    return EXIT_OK;
+}
+
+/*++
+
+ Routine Description:
+
+ Find the driver that is associated with the current device
+ We can do this either the quick way (available in WinXP)
+ or the long way that works in Win2k.
+
+ Arguments:
+
+ Devs    )_ uniquely identify device
+ DevInfo )
+
+ Return Value:
+
+ TRUE if we managed to determine and select current driver
+
+ --*/
+BOOL FindCurrentDriver (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, PSP_DRVINFO_DATA DriverInfoData)
+{
+    SP_DEVINSTALL_PARAMS deviceInstallParams;
+    WCHAR SectionName[LINE_LEN];
+    WCHAR DrvDescription[LINE_LEN];
+    WCHAR MfgName[LINE_LEN];
+    WCHAR ProviderName[LINE_LEN];
+    HKEY hKey = NULL;
+    DWORD RegDataLength;
+    DWORD RegDataType;
+    DWORD c;
+    BOOL match = FALSE;
+    long regerr;
+
+    ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
+    deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+
+    if (!g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams))
+    {
+        printf("Could not retrieve install params!");
+        return FALSE;
+    }
+
+#ifdef DI_FLAGSEX_INSTALLEDDRIVER
+
+    /* Set the flags that tell g_pfnSetupDiBuildDriverInfoList to just put the
+     currently installed driver node in the list, and that it should allow
+     excluded drivers. This flag introduced in WinXP. */
+    deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
+
+    if (g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams))
+    {
+        /* We were able to specify this flag, so proceed the easy way
+         We should get a list of no more than 1 driver */
+        if (!g_pfnSetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER))
+        {
+            return FALSE;
+        }
+        if (!g_pfnSetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, 0, DriverInfoData))
+        {
+            return FALSE;
+        }
+
+        /* We've selected the current driver */
+        return TRUE;
+    }
+
+    deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
+
+#endif
+
+    /* The following method works in Win2k, but it's slow and painful.
+     First, get driver key - if it doesn't exist, no driver */
+    hKey = g_pfnSetupDiOpenDevRegKey(Devs, DevInfo, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ
+    );
+
+    if (hKey == INVALID_HANDLE_VALUE)
+    {
+
+        _tprintf(_T("No associated driver found in registry!"));
+
+        /* No such value exists, so there can't be an associated driver */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Obtain path of INF - we'll do a search on this specific INF */
+    RegDataLength = sizeof(deviceInstallParams.DriverPath); /* Bytes!!! */
+    regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFPATH, NULL, &RegDataType, (PBYTE)deviceInstallParams.DriverPath, &RegDataLength);
+
+    if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ))
+    {
+
+        _tprintf(_T("No associated .inf path found in registry!"));
+
+        /* No such value exists, so no associated driver */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Obtain name of Provider to fill into DriverInfoData */
+    RegDataLength = sizeof(ProviderName); /* Bytes!!! */
+    regerr = RegQueryValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, NULL, &RegDataType, (PBYTE)ProviderName, &RegDataLength);
+
+    if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ))
+    {
+        /* No such value exists, so we don't have a valid associated driver */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Obtain name of section - for final verification */
+    RegDataLength = sizeof(SectionName); /* Bytes!!! */
+    regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFSECTION, NULL, &RegDataType, (PBYTE)SectionName, &RegDataLength);
+
+    if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ))
+    {
+        /* No such value exists, so we don't have a valid associated driver */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Driver description (need not be same as device description) - for final verification */
+    RegDataLength = sizeof(DrvDescription); /* Bytes!!! */
+    regerr = RegQueryValueEx(hKey, REGSTR_VAL_DRVDESC, NULL, &RegDataType, (PBYTE)DrvDescription, &RegDataLength);
+
+    RegCloseKey(hKey);
+
+    if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ))
+    {
+        /* No such value exists, so we don't have a valid associated driver */
+        return FALSE;
+    }
+
+    /* Manufacturer (via SPDRP_MFG, don't access registry directly!) */
+    if (!g_pfnSetupDiGetDeviceRegistryProperty(Devs, DevInfo, SPDRP_MFG, NULL, /* Datatype is guaranteed to always be REG_SZ */
+    (PBYTE)MfgName, sizeof(MfgName), /* Bytes!!! */
+    NULL))
+    {
+        /* No such value exists, so we don't have a valid associated driver */
+        return FALSE;
+    }
+
+    /* Now search for drivers listed in the INF */
+    deviceInstallParams.Flags |= DI_ENUMSINGLEINF;
+    deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
+
+    if (!g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams))
+    {
+        return FALSE;
+    }
+    if (!g_pfnSetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER))
+    {
+        return FALSE;
+    }
+
+    /* Find the entry in the INF that was used to install the driver for this device */
+    for (c = 0; g_pfnSetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, c, DriverInfoData); c++)
+    {
+        if ((_tcscmp(DriverInfoData->MfgName, MfgName) == 0) && (_tcscmp(DriverInfoData->ProviderName, ProviderName) == 0))
+        {
+            /* These two fields match, try more detailed info to ensure we have the exact driver entry used */
+            SP_DRVINFO_DETAIL_DATA detail;
+            detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
+            if (!g_pfnSetupDiGetDriverInfoDetail(Devs, DevInfo, DriverInfoData, &detail, sizeof(detail), NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+            {
+                continue;
+            }
+            if ((_tcscmp(detail.SectionName, SectionName) == 0) && (_tcscmp(detail.DrvDescription, DrvDescription) == 0))
+            {
+                match = TRUE;
+                break;
+            }
+        }
+    }
+    if (!match)
+    {
+        g_pfnSetupDiDestroyDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER);
+    }
+    return match;
+}
+
+/*++
+
+ Routine Description:
+
+ if Context provided, Simply count
+ otherwise dump files indented 2
+
+ Arguments:
+
+ Context      - DWORD Count
+ Notification - SPFILENOTIFY_QUEUESCAN
+ Param1       - scan
+
+ Return Value:
+
+ none
+
+ --*/
+UINT DumpDeviceDriversCallback (IN PVOID Context, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2)
+{
+    LPDWORD count = (LPDWORD)Context;
+    LPTSTR file = (LPTSTR)Param1;
+    if (count)
+    {
+        count[0]++;
+    }
+    else
+    {
+        _tprintf(TEXT("%s\n"), file);
+    }
+
+    return NO_ERROR;
+}
+
+/*++
+
+ Routine Description:
+
+ Dump information about what files were installed for driver package
+ <tab>Installed using OEM123.INF section [abc.NT]
+ <tab><tab>file...
+
+ Arguments:
+
+ Devs    )_ uniquely identify device
+ DevInfo )
+
+ Return Value:
+
+ none
+
+ --*/
+int DeleteOEMInfCallback (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context)
+{
+    /* Do this by 'searching' for the current driver
+     mimmicing a copy-only install to our own file queue
+     and then parsing that file queue */
+    SP_DEVINSTALL_PARAMS deviceInstallParams;
+    SP_DRVINFO_DATA driverInfoData;
+    SP_DRVINFO_DETAIL_DATA driverInfoDetail;
+    HSPFILEQ queueHandle = INVALID_HANDLE_VALUE;
+    DWORD count;
+    DWORD scanResult;
+    int success = EXIT_FAIL;
+
+    ZeroMemory(&driverInfoData,sizeof(driverInfoData));
+    driverInfoData.cbSize = sizeof(driverInfoData);
+
+    if (!FindCurrentDriver(Devs, DevInfo, &driverInfoData))
+        return EXIT_FAIL;
+
+    _tprintf(_T("Driver files found!\n"));
+
+    /* Get useful driver information */
+    driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
+    if (!g_pfnSetupDiGetDriverInfoDetail(Devs, DevInfo, &driverInfoData, &driverInfoDetail, sizeof(SP_DRVINFO_DETAIL_DATA), NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    {
+        /* No information about driver or section */
+        _tprintf(_T("No information about driver or section!\n"));
+        goto final;
+    }
+
+    if (!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0])
+    {
+        _tprintf(_T("Driver or section name is empty!\n"));
+        goto final;
+    }
+
+    _tprintf(_T("Desc: %s\n"), driverInfoDetail.DrvDescription);
+    _tprintf(_T("SecName: %s\n"), driverInfoDetail.SectionName);
+    _tprintf(_T("INF-File: %s\n"), driverInfoDetail.InfFileName);
+
+    /* Pretend to do the file-copy part of a driver install
+     to determine what files are used
+     the specified driver must be selected as the active driver */
+    if (!g_pfnSetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData))
+        goto final;
+
+    /* Create a file queue so we can look at this queue later */
+    queueHandle = SetupOpenFileQueue();
+
+    if (queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE)
+    {
+        goto final;
+    }
+
+    /* Modify flags to indicate we're providing our own queue */
+    ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
+    deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+    if (!g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams))
+        goto final;
+
+    /* We want to add the files to the file queue, not install them! */
+    deviceInstallParams.FileQueue = queueHandle;
+    deviceInstallParams.Flags |= DI_NOVCP;
+
+    if (!g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams))
+        goto final;
+
+    /* Now fill queue with files that are to be installed this involves all class/co-installers */
+    if (!g_pfnSetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo))
+        goto final;
+
+    /* We now have a list of delete/rename/copy files
+     iterate the copy queue twice - 1st time to get # of files
+     2nd time to get files (WinXP has API to get # of files, but we want this to work
+     on Win2k too */
+    count = 0;
+    scanResult = 0;
+
+    /* Call once to count (NOT YET IMPLEMENTED!) */
+    //SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult);
+    //FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName);
+
+    /* Call again to dump the files (NOT YET IMPLEMENTED!) */
+    //SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult);
+
+    if (!DeleteFile(driverInfoDetail.InfFileName))
+        scanResult = GetLastError();
+    else
+    {
+        DWORD index = 0;
+
+        index = lstrlen(driverInfoDetail.InfFileName);
+        if (index > 3)
+        {
+            lstrcpy(driverInfoDetail.InfFileName + index - 3, TEXT( "pnf" ) );
+
+            if (!DeleteFile(driverInfoDetail.InfFileName))
+                scanResult = GetLastError();
+        }
+    }
+
+    success = EXIT_OK;
+
+    final:
+
+    g_pfnSetupDiDestroyDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER);
+
+    if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE)
+    {
+        SetupCloseFileQueue(queueHandle);
+    }
+
+    if (EXIT_OK != success)
+    {
+        _tprintf(_T("Something went wrong while delete the OEM INF-files!\n\n"));
+    }
+
+    return success;
+
+}
+
+int UninstallDriver (_TCHAR* a_pszHwID)
+{
+    _tprintf(_T("Uninstalling device: %ws\n"), a_pszHwID);
+
+    _tprintf(_T("Removing driver files ...\n\n"));
+    int iRet = EnumerateDevices(NULL, NULL, DIGCF_PRESENT, 1, &a_pszHwID, DeleteOEMInfCallback, NULL);
+
+    if (EXIT_OK != iRet)
+        return iRet;
+
+    _tprintf(_T("Uninstalling driver ...\n\n"));
+    iRet = EnumerateDevices(NULL, NULL, DIGCF_PRESENT, 1, &a_pszHwID, UninstallCallback, NULL);
+
+    return iRet;
+}
+
+int ExecuteInfFile (_TCHAR* a_pszSection, int a_iMode, _TCHAR* a_pszInf)
+{
+    _tprintf(_T("Executing INF-File: %ws (%ws) ...\n"), a_pszInf, a_pszSection);
+
+    /* Executed by the installer that already has proper privileges. */
+    _TCHAR szCommandLine[_MAX_PATH + 1] = { 0 };
+    swprintf(szCommandLine, sizeof(szCommandLine), TEXT( "%ws %d %ws" ), a_pszSection, a_iMode, a_pszInf);
+
+#ifdef _DEBUG
+    _tprintf (_T( "Commandline: %ws\n"), szCommandLine);
+#endif
+
+    InstallHinfSection(NULL, NULL, szCommandLine, SW_SHOW);
+
+    return EXIT_OK;
+}
+
+int AddNetworkProvider (TCHAR* a_pszProvider, int a_iOrder)
+{
+    TCHAR szKeyValue[512] = { 0 };
+    TCHAR szNewKeyValue[512] = { 0 };
+    HKEY hKey = NULL;
+    DWORD disp, dwType;
+    int rc;
+
+    _tprintf(_T("Adding network provider: %ws (Order = %d)\n"), a_pszProvider, a_iOrder);
+
+    /* Note: HWOrder is not accessible in Windows 2000; it is updated automatically anyway. */
+    TCHAR *pszKey = _T("System\\CurrentControlSet\\Control\\NetworkProvider\\Order");
+
+    rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp);
+    if (rc != ERROR_SUCCESS)
+    {
+        _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), pszKey, rc);
+        return EXIT_FAIL;
+    }
+    DWORD cbKeyValue = sizeof(szKeyValue);
+
+    rc = RegQueryValueEx(hKey, _T("ProviderOrder"), NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue);
+    if (rc != ERROR_SUCCESS || dwType != REG_SZ)
+    {
+        _tprintf(_T("RegQueryValueEx failed with %d dwType = 0x%x!\n"), rc, dwType);
+        return EXIT_FAIL;
+    }
+
+#ifdef _DEBUG
+    _tprintf(_T("Key value: %ws\n"), szKeyValue);
+#endif
+
+    /* Create entire new list. */
+    int iPos = 0;
+
+    TCHAR* pszToken = wcstok(szKeyValue, _T(","));
+    TCHAR* pszNewToken = NULL;
+    while (pszToken != NULL)
+    {
+        pszNewToken = wcstok(NULL, _T(","));
+
+        /* Append new provider name (at beginning if a_iOrder=0). */
+        if (iPos == a_iOrder)
+        {
+            wcscat(szNewKeyValue, a_pszProvider);
+            wcscat(szNewKeyValue, _T(","));
+            iPos++;
+        }
+
+        if (0 != wcsicmp(pszToken, a_pszProvider))
+        {
+            wcscat(szNewKeyValue, pszToken);
+            wcscat(szNewKeyValue, _T(","));
+            iPos++;
+        }
+
+#ifdef _DEBUG
+        _tprintf (_T("Temp new key value: %ws\n"), szNewKeyValue);
+#endif
+
+        pszToken = pszNewToken;
+    }
+
+    /* Append as last item if needed. */
+    if (a_iOrder >= iPos)
+        wcscat(szNewKeyValue, a_pszProvider);
+
+    /* Last char a delimiter? Cut off ... */
+    if (szNewKeyValue[wcslen(szNewKeyValue) - 1] == ',')
+        szNewKeyValue[wcslen(szNewKeyValue) - 1] = '\0';
+
+    size_t iNewLen = (wcslen(szNewKeyValue) * sizeof(WCHAR)) + sizeof(WCHAR);
+
+    _tprintf(_T("New provider list (%u bytes): %ws\n"), iNewLen, szNewKeyValue);
+
+    rc = RegSetValueExW(hKey, _T("ProviderOrder"), 0, REG_SZ, (LPBYTE)szNewKeyValue, (DWORD)iNewLen);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        _tprintf(_T("RegSetValueEx failed with %d!\n"), rc);
+        return EXIT_FAIL;
+    }
+
+    rc = RegCloseKey(hKey);
+
+    if (rc == ERROR_SUCCESS)
+    {
+        _tprintf(_T("Network provider successfully installed!\n"), rc);
+        rc = EXIT_OK;
+    }
+
+    return rc;
+}
+
+int AddStringToMultiSZ (TCHAR* a_pszSubKey, TCHAR* a_pszKeyValue, TCHAR* a_pszValueToAdd, int a_iOrder)
+{
+    TCHAR szKeyValue[512] = { 0 };
+    TCHAR szNewKeyValue[512] = { 0 };
+    HKEY hKey = NULL;
+    DWORD disp, dwType;
+    int rc = 0;
+
+    _tprintf(_T("Adding MULTI_SZ string: %ws to %ws\\%ws (Order = %d)\n"), a_pszValueToAdd, a_pszSubKey, a_pszKeyValue, a_iOrder);
+
+    rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, a_pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp);
+    if (rc != ERROR_SUCCESS)
+    {
+       _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), a_pszSubKey, rc);
+       return EXIT_FAIL;
+    }
+    DWORD cbKeyValue = sizeof(szKeyValue);
+
+    rc = RegQueryValueEx(hKey, a_pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue);
+    if (rc != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
+    {
+       _tprintf(_T("RegQueryValueEx failed with %d, dwType = 0x%x!\n"), rc, dwType);
+       return EXIT_FAIL;
+    }
+
+    /* Look if the network provider is already in the list. */
+    int iPos = 0;
+    size_t cb = 0;
+
+    /* Replace delimiting "\0"'s with "," to make tokenizing work. */
+    for (int i=0; i<cbKeyValue/sizeof(TCHAR);i++)
+        if (szKeyValue[i] == '\0') szKeyValue[i] = ',';
+
+    TCHAR* pszToken = wcstok(szKeyValue, _T(","));
+    TCHAR* pszNewToken = NULL;
+    TCHAR* pNewKeyValuePos = szNewKeyValue;
+    while (pszToken != NULL)
+    {
+       pszNewToken = wcstok(NULL, _T(","));
+
+       /* Append new value (at beginning if a_iOrder=0). */
+       if (iPos == a_iOrder)
+       {
+           memcpy(pNewKeyValuePos, a_pszValueToAdd, wcslen(a_pszValueToAdd)*sizeof(TCHAR));
+
+           cb += (wcslen(a_pszValueToAdd) + 1) * sizeof(TCHAR);  /* Add trailing zero as well. */
+           pNewKeyValuePos += wcslen(a_pszValueToAdd) + 1;
+           iPos++;
+       }
+
+       if (0 != wcsicmp(pszToken, a_pszValueToAdd))
+       {
+           memcpy(pNewKeyValuePos, pszToken, wcslen(pszToken)*sizeof(TCHAR));
+           cb += (wcslen(pszToken) + 1) * sizeof(TCHAR);  /* Add trailing zero as well. */
+           pNewKeyValuePos += wcslen(pszToken) + 1;
+           iPos++;
+       }
+
+       pszToken = pszNewToken;
+    }
+
+    /* Append as last item if needed. */
+    if (a_iOrder >= iPos)
+    {
+        memcpy(pNewKeyValuePos, a_pszValueToAdd, wcslen(a_pszValueToAdd)*sizeof(TCHAR));
+        cb += wcslen(a_pszValueToAdd) * sizeof(TCHAR);  /* Add trailing zero as well. */
+    }
+
+    rc = RegSetValueExW(hKey, a_pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szNewKeyValue, (DWORD)cb);
+
+    if (rc != ERROR_SUCCESS)
+    {
+       _tprintf(_T("RegSetValueEx failed with %d!\n"), rc);
+       return EXIT_FAIL;
+    }
+
+    rc = RegCloseKey(hKey);
+
+    if (rc == ERROR_SUCCESS)
+    {
+       _tprintf(_T("Value successfully written (%u bytes)!\n"), cb);
+       rc = EXIT_OK;
+    }
+
+    return rc;
+}
+
+int RemoveStringFromMultiSZ (TCHAR* a_pszSubKey, TCHAR* a_pszKeyValue, TCHAR* a_pszValueToRemove)
+{
+    // @todo Make string sizes dynamically allocated!
+
+    TCHAR szKeyValue[1024];
+    HKEY hkey;
+    DWORD disp, dwType;
+    int rc;
+
+    TCHAR *pszKey = a_pszSubKey;
+
+    _tprintf(_T("Removing MULTI_SZ string: %ws from %ws\\%ws ...\n"), a_pszValueToRemove, a_pszSubKey, a_pszKeyValue);
+
+    rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp);
+    if (rc != ERROR_SUCCESS)
+    {
+        _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), pszKey, rc);
+        return EXIT_FAIL;
+    }
+    DWORD cbKeyValue = sizeof(szKeyValue);
+
+    rc = RegQueryValueEx(hkey, a_pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue);
+    if (rc != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
+    {
+        _tprintf(_T("RegQueryValueEx failed with %d dwType = 0x%x!\n"), rc, dwType);
+        return EXIT_FAIL;
+    }
+
+#ifdef _DEBUG
+    _tprintf(_T("Current key len: %d\n"), cbKeyValue);
+#endif
+
+    TCHAR szCurString[1024] = { 0 };
+    TCHAR szFinalString[1024] = { 0 };
+    int iIndex = 0;
+    int iNewIndex = 0;
+    for (int i = 0; i < cbKeyValue / sizeof(TCHAR); i++)
+    {
+        if (szKeyValue[i] != _T('\0'))
+            szCurString[iIndex++] = szKeyValue[i];
+
+        if ((!szKeyValue[i] == _T('\0')) && szKeyValue[i + 1] == _T('\0'))
+        {
+            if (NULL == wcsstr(szCurString, a_pszValueToRemove))
+            {
+                wcscat(&szFinalString[iNewIndex], szCurString);
+
+                if (iNewIndex == 0)
+                    iNewIndex = iIndex;
+                else iNewIndex += iIndex;
+
+                szFinalString[++iNewIndex] = _T('\0');
+            }
+
+            iIndex = 0;
+            ZeroMemory( szCurString, sizeof(szCurString));
+        }
+    }
+
+    szFinalString[++iNewIndex] = _T('\0');
+
+#ifdef _DEBUG
+    _tprintf(_T("New key len: %d\n"), iNewIndex * sizeof(TCHAR));
+    _tprintf(_T("New key value: %ws\n"), szFinalString);
+#endif
+
+    rc = RegSetValueExW(hkey, a_pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szFinalString, iNewIndex * sizeof(TCHAR));
+
+    if (rc != ERROR_SUCCESS)
+    {
+        _tprintf(_T("RegSetValueEx failed with %d!\n"), rc);
+        return EXIT_FAIL;
+    }
+
+    rc = RegCloseKey(hkey);
+
+    if (rc == ERROR_SUCCESS)
+    {
+        _tprintf(_T("Value successfully removed!\n"), rc);
+        rc = EXIT_OK;
+    }
+
+    return rc;
+}
+
+int CreateService (TCHAR* a_pszStartStopName,
+                   TCHAR* a_pszDisplayName,
+                   int a_iServiceType,
+                   int a_iStartType,
+                   TCHAR* a_pszBinPath,
+                   TCHAR* a_pszLoadOrderGroup,
+                   TCHAR* a_pszDependencies,
+                   TCHAR* a_pszLogonUser,
+                   TCHAR* a_pszLogonPw)
+{
+    int rc = ERROR_SUCCESS;
+
+    _tprintf(_T("Installing service %ws (%ws) ...\n"), a_pszDisplayName, a_pszStartStopName);
+
+    SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
+    if (hSCManager == NULL)
+    {
+        _tprintf(_T("Could not get handle to SCM! Error: %ld\n"), GetLastError());
+        return EXIT_FAIL;
+    }
+
+    /* Fixup end of multistring */
+    TCHAR szDepend[ _MAX_PATH ] = { 0 };        /* @todo Use dynamically allocated string here! */
+    if (a_pszDependencies != NULL)
+    {
+        _tcsnccpy (szDepend, a_pszDependencies, wcslen(a_pszDependencies));
+        DWORD len = (DWORD)wcslen (szDepend);
+        szDepend [len + 1] = 0;
+
+        /* Replace comma separator on null separator */
+        for (DWORD i = 0; i < len; i++)
+        {
+            if (',' == szDepend [i])
+                szDepend [i] = 0;
+        }
+    }
+
+    DWORD dwTag = 0xDEADBEAF;
+    SC_HANDLE hService = CreateService (hSCManager,             // SCManager database
+                                        a_pszStartStopName,     // name of service
+                                        a_pszDisplayName,       // name to display
+                                        SERVICE_ALL_ACCESS,     // desired access
+                                        a_iServiceType,         // service type
+                                        a_iStartType,           // start type
+                                        SERVICE_ERROR_NORMAL,   // error control type
+                                        a_pszBinPath,           // service's binary
+                                        a_pszLoadOrderGroup,    // ordering group
+                                        (a_pszLoadOrderGroup != NULL) ? &dwTag : NULL,    // tag identifier
+                                        (a_pszDependencies != NULL) ? szDepend : NULL,    // dependencies
+                                        (a_pszLogonUser != NULL) ? a_pszLogonUser: NULL,  // account
+                                        (a_pszLogonPw != NULL) ? a_pszLogonPw : NULL);    // password
+    if (NULL == hService)
+    {
+        DWORD dwErr = GetLastError();
+        switch (dwErr)
+        {
+
+        case ERROR_SERVICE_EXISTS:
+        {
+            _tprintf(_T("Service already exists. No installation required. Updating the service config.\n"));
+
+            hService = OpenService (hSCManager,             // SCManager database
+                                    a_pszStartStopName,     // name of service
+                                    SERVICE_ALL_ACCESS);    // desired access
+            if (NULL == hService)
+            {
+                dwErr = GetLastError();
+                _tprintf(_T("Could not open service! Error: %ld\n"), dwErr);
+            }
+            else
+            {
+                BOOL Result = ChangeServiceConfig (hService,               // service handle
+                                                   a_iServiceType,         // service type
+                                                   a_iStartType,           // start type
+                                                   SERVICE_ERROR_NORMAL,   // error control type
+                                                   a_pszBinPath,           // service's binary
+                                                   a_pszLoadOrderGroup,    // ordering group
+                                                   (a_pszLoadOrderGroup != NULL) ? &dwTag : NULL,    // tag identifier
+                                                   (a_pszDependencies != NULL) ? szDepend : NULL,    // dependencies
+                                                   (a_pszLogonUser != NULL) ? a_pszLogonUser: NULL,  // account
+                                                   (a_pszLogonPw != NULL) ? a_pszLogonPw : NULL,     // password
+                                                   a_pszDisplayName);      // name to display
+                if (Result)
+                {
+                    _tprintf(_T("The service config has been successfully updated.\n"));
+                }
+                else
+                {
+                    dwErr = GetLastError();
+                    _tprintf(_T("Could not change service config! Error: %ld\n"), dwErr);
+                }
+
+                CloseServiceHandle (hService);
+            }
+
+            /* This entire branch do not return an error to avoid installations failures,
+             * if updating service parameters. Better to have a running system with old
+             * parameters and the failure information in the installation log.
+             */
+            break;
+        }
+
+        case ERROR_INVALID_PARAMETER:
+
+            _tprintf(_T("Invalid parameter specified!\n"));
+            rc = EXIT_FAIL;
+            break;
+
+        default:
+
+            _tprintf(_T("Could not create service! Error: %ld\n"), dwErr);
+            rc = EXIT_FAIL;
+            break;
+        }
+
+        if (rc == EXIT_FAIL)
+            goto cleanup;
+    }
+    else
+    {
+        CloseServiceHandle (hService);
+        _tprintf(_T("Installation of service successful!\n"));
+    }
+
+cleanup:
+
+    if (hSCManager != NULL)
+        CloseServiceHandle (hSCManager);
+
+    return rc;
+}
+
+int DelService (TCHAR* a_pszStartStopName)
+{
+    int rc = ERROR_SUCCESS;
+
+    _tprintf(_T("Deleting service '%ws' ...\n"), a_pszStartStopName);
+
+    SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+    SC_HANDLE hService = NULL;
+    if (hSCManager == NULL)
+    {
+        _tprintf(_T("Could not get handle to SCM! Error: %ld\n"), GetLastError());
+        rc = EXIT_FAIL;
+    }
+    else
+    {
+        hService = OpenService(hSCManager, a_pszStartStopName, SERVICE_ALL_ACCESS);
+        if (NULL == hService)
+        {
+            _tprintf(_T("Could not open service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());
+            rc = EXIT_FAIL;
+        }
+    }
+
+    if (hService != NULL)
+    {
+        if (LockServiceDatabase(hSCManager))
+        {
+            if (FALSE == DeleteService(hService))
+            {
+                DWORD dwErr = GetLastError();
+                switch (dwErr)
+                {
+
+                case ERROR_SERVICE_MARKED_FOR_DELETE:
+
+                    _tprintf(_T("Service '%ws' already marked for deletion.\n"), a_pszStartStopName);
+                    break;
+
+                default:
+
+                    _tprintf(_T("Could not delete service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());
+                    rc = EXIT_FAIL;
+                    break;
+                }
+            }
+            else
+            {
+                _tprintf(_T("Service '%ws' successfully removed!\n"), a_pszStartStopName);
+            }
+            UnlockServiceDatabase(hSCManager);
+        }
+        else
+        {
+            _tprintf(_T("Unable to lock service database! Error: %ld\n"), GetLastError());
+            rc = EXIT_FAIL;
+        }
+        CloseServiceHandle(hService);
+    }
+
+    if (hSCManager != NULL)
+        CloseServiceHandle(hSCManager);
+
+    return rc;
+}
+
+DWORD RegistryWrite(HKEY hRootKey,
+                    const _TCHAR *pszSubKey,
+                    const _TCHAR *pszValueName,
+                    DWORD dwType,
+                    const BYTE *pbData,
+                    DWORD cbData)
+{
+    DWORD lRet;
+    HKEY hKey;
+    lRet = RegCreateKeyEx (hRootKey,
+                           pszSubKey,
+                           0,           /* Reserved */
+                           NULL,        /* lpClass [in, optional] */
+                           0,           /* dwOptions [in] */
+                           KEY_WRITE,
+                           NULL,        /* lpSecurityAttributes [in, optional] */
+                           &hKey,
+                           NULL);       /* lpdwDisposition [out, optional] */
+    if (lRet != ERROR_SUCCESS)
+    {
+        _tprintf(_T("Could not open registry key! Error: %ld\n"), GetLastError());
+    }
+    else
+    {
+        lRet = RegSetValueEx(hKey, pszValueName, 0, dwType, (BYTE*)pbData, cbData);
+        if (lRet != ERROR_SUCCESS)
+            _tprintf(_T("Could not write to registry! Error: %ld\n"), GetLastError());
+        RegCloseKey(hKey);
+
+    }
+    return lRet;
+}
+
+void PrintHelp (void)
+{
+    _tprintf(_T("Installs / Uninstalls VirtualBox drivers for Windows XP/2K/Vista\n"));
+    _tprintf(_T("Version: %d.%d.%d.%d\n\n"), VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
+    _tprintf(_T("Syntax:\n"));
+    _tprintf(_T("\tTo install: VBoxDrvInst /i <HardwareID> <INF-File> <Device Class>\n"));
+    _tprintf(_T("\tTo uninstall: VBoxDrvInst /u <HardwareID>\n"));
+    _tprintf(_T("\tTo execute an INF-File: VBoxDrvInst /inf <INF-File>\n"));
+    _tprintf(_T("\tTo add a network provider: VBoxDrvInst /addnetprovider <Name> [Order]\n\n"));
+    _tprintf(_T("\tTo write registry values: VBoxDrvInst /registry write <root> <sub key> <key name> <key type> <value> [type] [size]\n\n"));
+    _tprintf(_T("Examples:\n"));
+    _tprintf(_T("\tVBoxDrvInst /i \"PCI\\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00\" VBoxVideo.inf Display\n"));
+    _tprintf(_T("\tVBoxDrvInst /addnetprovider VboxSF 1\n\n"));
+}
+
+int __cdecl _tmain (int argc, _TCHAR* argv[])
+{
+    int rc;
+    OSVERSIONINFO OSinfo;
+
+    _TCHAR szHwID[_MAX_PATH] = { 0 }; /* Hardware ID. */
+    _TCHAR szINF[_MAX_PATH] = { 0 }; /* Complete path to INF file.*/
+    _TCHAR szDevClass[_MAX_PATH] = { 0 }; /* Device class. */
+    _TCHAR szProvider[_MAX_PATH] = { 0 }; /* The network provider name for the registry. */
+
+    rc = LoadAPICalls();
+    if (   rc == ERROR_SUCCESS
+        && argc >= 2)
+    {
+        OSinfo.dwOSVersionInfoSize = sizeof(OSinfo);
+        GetVersionEx(&OSinfo);
+
+        if (0 == _tcsicmp(argv[1], _T("/i")))
+        {
+            if (argc < 5)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                if (OSinfo.dwMajorVersion < 5)
+                {
+                    _tprintf(_T("ERROR: Platform not supported yet!\n"));
+                    rc = ERROR_NOT_SUPPORTED;
+                }
+
+                if (rc == ERROR_SUCCESS)
+                {
+                    _stprintf(szHwID, _T("%ws"), argv[2]);
+                    _stprintf(szINF, _T("%ws"), argv[3]);
+                    _stprintf(szDevClass, _T("%ws"), argv[4]);
+
+                    rc = InstallDriver(szINF, szHwID, szDevClass);
+                }
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/u")))
+        {
+            if (argc < 3)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                if (OSinfo.dwMajorVersion < 5)
+                {
+                    _tprintf(_T("ERROR: Platform not supported yet!\n"));
+                    rc = ERROR_NOT_SUPPORTED;
+                }
+
+                if (rc == ERROR_SUCCESS)
+                {
+                    _stprintf(szHwID, _T("%ws"), argv[2]);
+                    rc = UninstallDriver(szHwID);
+                }
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/inf")))
+        {
+            if (argc < 3)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                if (OSinfo.dwMajorVersion < 5)
+                {
+                    _tprintf(_T("ERROR: Platform not supported yet!\n"));
+                    rc = ERROR_NOT_SUPPORTED;
+                }
+
+                if (rc == ERROR_SUCCESS)
+                {
+                    _stprintf(szINF, _T("%ws"), argv[2]);
+                    rc = ExecuteInfFile(_T("DefaultInstall"), 132, szINF);
+                }
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/addnetprovider")))
+        {
+            if (argc < 3)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+
+                int iOrder = 0;
+                if (argc > 3)
+                    iOrder = _ttoi(argv[3]);
+                _stprintf(szProvider, _T("%ws"), argv[2]);
+                rc = AddNetworkProvider(szProvider, iOrder);
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/reg_addmultisz")))
+        {
+            if (argc < 6)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                rc = AddStringToMultiSZ(argv[2], argv[3], argv[4], _ttoi(argv[5]));
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/reg_delmultisz")))
+        {
+            if (argc < 5)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                rc = RemoveStringFromMultiSZ(argv[2], argv[3], argv[4]);
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/createsvc")))
+        {
+            if (argc < 7)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                rc = CreateService(
+                         argv[2],
+                         argv[3],
+                         _ttoi(argv[4]),
+                         _ttoi(argv[5]),
+                         argv[6],
+                         (argc > 7) ? argv[7] : NULL,
+                         (argc > 8) ? argv[8] : NULL,
+                         (argc > 9) ? argv[9] : NULL,
+                         (argc > 10) ? argv[10] : NULL);
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/delsvc")))
+        {
+            if (argc < 3)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                rc = DelService(argv[2]);
+            }
+        }
+        else if (0 == _tcsicmp(argv[1], _T("/registry")))
+        {
+            if (argc < 8)
+            {
+                rc = EXIT_USAGE;
+            }
+            else
+            {
+                /** @todo add a handleRegistry(argc, argv) method to keep things cleaner */
+                if (0 == _tcsicmp(argv[2], _T("write")))
+                {
+                    HKEY hRootKey = HKEY_LOCAL_MACHINE;  /** @todo needs to be expanded (argv[3]) */
+                    DWORD dwValSize;
+                    BYTE *pbVal = NULL;
+                    DWORD dwVal;
+
+                    if (argc > 8)
+                    {
+                        if (0 == _tcsicmp(argv[8], _T("dword")))
+                        {
+                            dwVal = _ttol(argv[7]);
+                            pbVal = (BYTE*)&dwVal;
+                            dwValSize = sizeof(DWORD);
+                        }
+                    }
+                    if (pbVal == NULL) /* By default interpret value as string */
+                    {
+                        pbVal = (BYTE*)argv[7];
+                        dwValSize = _tcslen(argv[7]);
+                    }
+                    if (argc > 9)
+                        dwValSize = _ttol(argv[9]);      /* Get the size in bytes of the value we want to write */
+                    rc = RegistryWrite(hRootKey,
+                                       argv[4],          /* Sub key */
+                                       argv[5],          /* Value name */
+                                       REG_BINARY,       /** @todo needs to be expanded (argv[6]) */
+                                       pbVal,            /* The value itself */
+                                       dwValSize);       /* Size of the value */
+                }
+                /*else if (0 == _tcsicmp(argv[2], _T("read")))
+                {
+                }
+                else if (0 == _tcsicmp(argv[2], _T("del")))
+                {
+                }*/
+                else
+                    rc = EXIT_USAGE;
+            }
+        }
+    }
+
+    if (rc == EXIT_USAGE)
+        PrintHelp();
+
+    FreeAPICalls();
+    return rc;
+}
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.rc	(revision 31634)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 Driver Installer\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxDrvInst\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxDrvInst.exe\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditions.nsi
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditions.nsi	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditions.nsi	(revision 31634)
@@ -0,0 +1,1126 @@
+
+!if $%BUILD_TYPE% == "debug"
+  !define _DEBUG     ; Turn this on to get extra output
+!endif
+
+; Defines for special functions
+!define WHQL_FAKE    ; Turns on the faking of non WHQL signed / approved drivers.
+                     ; Needs the VBoxWHQLFake.exe in the additions output directory!
+
+!define VENDOR_ROOT_KEY "SOFTWARE\$%VBOX_VENDOR_SHORT%"
+
+!define PRODUCT_NAME "$%VBOX_PRODUCT% Guest Additions"
+!define PRODUCT_DESC "$%VBOX_PRODUCT% Guest Additions"
+!define PRODUCT_VERSION "$%VBOX_VERSION_MAJOR%.$%VBOX_VERSION_MINOR%.$%VBOX_VERSION_BUILD%.0"
+!define PRODUCT_PUBLISHER " $%VBOX_VENDOR%"
+!define PRODUCT_COPYRIGHT "(C) $%VBOX_C_YEAR% $%VBOX_VENDOR%"
+!define PRODUCT_OUTPUT "VBoxWindowsAdditions-$%BUILD_TARGET_ARCH%.exe"
+!define PRODUCT_WEB_SITE "http://www.virtualbox.org"
+!define PRODUCT_INSTALL_KEY "${VENDOR_ROOT_KEY}\VirtualBox Guest Additions"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+
+VIProductVersion "${PRODUCT_VERSION}"
+VIAddVersionKey "FileVersion" "$%VBOX_VERSION_STRING%"
+VIAddVersionKey "ProductName" "${PRODUCT_NAME}"
+VIAddVersionKey "ProductVersion" "${PRODUCT_VERSION}"
+VIAddVersionKey "CompanyName" "${PRODUCT_PUBLISHER}"
+VIAddVersionKey "FileDescription" "${PRODUCT_DESC}"
+VIAddVersionKey "LegalCopyright" "${PRODUCT_COPYRIGHT}"
+VIAddVersionKey "InternalName" "${PRODUCT_OUTPUT}"
+
+; This registry key will hold the mouse driver path before install (NT4 only)
+!define ORG_MOUSE_PATH "MousePath"
+
+!include "LogicLib.nsh"
+!include "FileFunc.nsh"
+  !insertmacro GetParameters
+  !insertmacro GetOptions
+!include "WordFunc.nsh"
+  !insertmacro WordFind
+  !insertmacro StrFilter
+
+!include "nsProcess.nsh"
+!include "Library.nsh"
+!include "strstr.nsh"         ; Function "strstr"
+!include "servicepack.nsh"    ; Function "GetServicePack"
+!include "winver.nsh"         ; Function for determining Windows version
+!define REPLACEDLL_NOREGISTER ; Replace in use DLL function
+!include "ReplaceDLL.nsh"
+!include "dumplog.nsh"        ; Dump log to file function
+
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  !include "x64.nsh"
+!endif
+
+; Use modern UI (MUI)
+!include "MUI.nsh"
+
+; MUI Settings
+!define MUI_WELCOMEFINISHPAGE_BITMAP "$%VBOX_BRAND_WIN_ADD_INST_DLGBMP%"
+!define MUI_ABORTWARNING
+!define MUI_WELCOMEPAGE_TITLE_3LINES "Welcome to the ${PRODUCT_NAME} Additions Setup"
+
+; API defines
+!define SM_CLEANBOOT 67
+
+; Icons
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  !define MUI_ICON "$%VBOX_NSIS_ICON_FILE%"
+  !define MUI_UNICON "$%VBOX_NSIS_ICON_FILE%"
+!else   ; 64-bit
+  !define MUI_ICON "$%VBOX_WINDOWS_ADDITIONS_ICON_FILE%"
+  !define MUI_UNICON "$%VBOX_WINDOWS_ADDITIONS_ICON_FILE%"
+!endif
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+; License page
+!insertmacro MUI_PAGE_LICENSE "$(VBOX_LICENSE)"
+!define MUI_LICENSEPAGE_RADIOBUTTONS
+; Directory page
+!insertmacro MUI_PAGE_DIRECTORY
+; Components Page
+!insertmacro MUI_PAGE_COMPONENTS
+; Instfiles page
+!insertmacro MUI_PAGE_INSTFILES
+
+!ifndef _DEBUG
+  !define MUI_FINISHPAGE_TITLE_3LINES   ; Have a bit more vertical space for text
+  !insertmacro MUI_PAGE_FINISH          ; Only show in release mode - useful information for debugging!
+!endif
+
+; Uninstaller pages
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Define languages we will use
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "French"
+!insertmacro MUI_LANGUAGE "German"
+
+; Set branding text which appears on the horizontal line at the bottom
+BrandingText "VirtualBox Windows Additions"
+
+; Set license language
+LicenseLangString VBOX_LICENSE ${LANG_ENGLISH} "$%VBOX_BRAND_LICENSE_RTF%"
+
+; If license files not available (OSE / PUEL) build, then use the English one as default.
+!ifdef VBOX_BRAND_fr_FR_LICENSE_RTF
+ LicenseLangString VBOX_LICENSE ${LANG_FRENCH} "$%VBOX_BRAND_fr_FR_LICENSE_RTF%"
+!else
+ LicenseLangString VBOX_LICENSE ${LANG_FRENCH} "$%VBOX_BRAND_LICENSE_RTF%"
+!endif
+!ifdef VBOX_BRAND_de_DE_LICENSE_RTF
+ LicenseLangString VBOX_LICENSE ${LANG_GERMAN} "$%VBOX_BRAND_de_DE_LICENSE_RTF%"
+!else
+ LicenseLangString VBOX_LICENSE ${LANG_GERMAN} "$%VBOX_BRAND_LICENSE_RTF%"
+!endif
+
+!insertmacro MUI_RESERVEFILE_LANGDLL
+; MUI end ------
+
+; Language files
+!include "Languages\English.nsh"
+!include "Languages\French.nsh"
+!include "Languages\German.nsh"
+
+; Variables and output files
+Name "${PRODUCT_NAME} $%VBOX_VERSION_STRING%"
+!ifdef UNINSTALLER_ONLY
+!echo "Uninstaller only!"
+OutFile "$%PATH_TARGET%\VBoxWindowsAdditions-$%BUILD_TARGET_ARCH%-uninst.exe"
+!else
+OutFile "VBoxWindowsAdditions-$%BUILD_TARGET_ARCH%.exe"
+!endif
+
+!if $%BUILD_TARGET_ARCH% == "x86" ; 32-bit
+  InstallDir  "$PROGRAMFILES32\$%VBOX_VENDOR_SHORT%\VirtualBox Guest Additions"
+!else       ; 64-bit
+  InstallDir  "$PROGRAMFILES64\$%VBOX_VENDOR_SHORT%\VirtualBox Guest Additions"
+!endif
+
+InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
+ShowInstDetails show
+ShowUnInstDetails show
+RequestExecutionLevel highest
+
+Var g_iSystemMode       ; Current system mode (0 = Normal boot, 1 = Fail-safe boot, 2 = Fail-safe with network boot)
+Var g_strSystemDir      ; Windows system directory
+Var g_strCurUser        ; Current user using the system
+Var g_strAddVerMaj      ; Installed Guest Additions: Major version
+Var g_strAddVerMin      ; Installed Guest Additions: Minor version
+Var g_strAddVerBuild    ; Installed Guest Additions: Build number
+Var g_strAddVerRev      ; Installed Guest Additions: SVN revision
+Var g_strWinVersion     ; Current Windows version we're running on
+Var g_bLogEnable        ; Do logging when installing? "true" or "false"
+Var g_bFakeWHQL         ; Cmd line: Fake Windows to install non WHQL certificated drivers (only for W2K and XP currently!!) ("/unsig_drv")
+Var g_bUninstall        ; Cmd line: Just uninstall any previous Guest Additions and exit
+Var g_bRebootOnExit     ; Cmd line: Auto-Reboot on successful installation. Good for unattended installations ("/reboot")
+Var g_iScreenBpp        ; Cmd line: Screen depth ("/depth=X")
+Var g_iScreenX          ; Cmd line: Screen resolution X ("/resx=X")
+Var g_iScreenY          ; Cmd line: Screen resolution Y ("/resy=Y")
+Var g_iSfOrder          ; Cmd line: Order of Shared Folders network provider (0=first, 1=second, ...)
+Var g_bNoVideoDrv       ; Cmd line: Do not install the VBoxVideo driver
+Var g_bNoGuestDrv       ; Cmd line: Do not install the VBoxGuest driver
+Var g_bNoMouseDrv       ; Cmd line: Do not install the VBoxMouse driver
+Var g_bWithAutoLogon    ; Cmd line: Install VBoxGINA / VBoxCredProv for auto logon support
+Var g_bWithD3D          ; Cmd line: Install Direct3D support
+Var g_bOnlyExtract      ; Cmd line: Only extract all files, do *not* install them. Only valid with param "/D" (target directory)
+
+; Platform parts of this installer
+!include "VBoxGuestAdditionsCommon.nsh"
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit only
+!include "VBoxGuestAdditionsNT4.nsh"
+!endif
+!include "VBoxGuestAdditionsW2KXP.nsh"
+!include "VBoxGuestAdditionsVista.nsh"
+!include "VBoxGuestAdditionsUninstall.nsh"    ; Product uninstallation
+!include "VBoxGuestAdditionsUninstallOld.nsh" ; Uninstallation of deprecated versions which must be removed first
+
+Function HandleCommandLine
+
+  Push $0                                     ; Command line (without process name)
+  Push $1                                     ; Number of parameters
+  Push $2                                     ; Current parameter index
+  Push $3                                     ; Current parameter pair (name=value)
+  Push $4                                     ; Current parameter name
+  Push $5                                     ; Current parameter value (if present)
+
+  StrCpy $1 "0"                               ; Init param counter
+  StrCpy $2 "1"                               ; Init current param counter
+
+  ${GetParameters} $0                         ; Extract command line
+  ${If} $0 == ""                              ; If no parameters at all exit
+    Goto exit
+  ${EndIf}
+
+  ; Enable for debugging
+  ;MessageBox MB_OK "CmdLine: $0"
+
+  ${WordFind} $0 " " "#" $1                   ; Get number of parameters in cmd line
+  ${If} $0 == $1                              ; If result matches the input then
+    StrCpy $1 "1"                             ; no delimeter was found. Correct to 1 word total.
+  ${EndIf}
+
+  ${While} $2 <= $1                           ; Loop through all params
+
+    ${WordFind} $0 " " "+$2" $3               ; Get current name=value pair
+    ${WordFind} $3 "=" "+1" $4                ; Get current param name
+    ${WordFind} $3 "=" "+2" $5                ; Get current param value
+
+    ${StrFilter} $4 "-" "" "" $4              ; Transfor param name to lowercase
+
+    ; Enable for debugging
+    ;MessageBox MB_OK "#$2 of #$1, param='$3', name=$4, val=$5"
+
+    ${Switch} $4
+
+      ${Case} '/d' ; NSIS: /D=<instdir> switch, skip
+        ${Break}
+
+      ${Case} '/depth'
+      ${Case} 'depth'
+        StrCpy $g_iScreenBpp $5
+        ${Break}
+
+      ${Case} '/extract'
+        StrCpy $g_bOnlyExtract "true"
+        ${Break}
+
+      ${Case} '/help'
+      ${Case} '/H'
+      ${Case} '/h'
+      ${Case} '/?'
+        Goto usage
+        ${Break}
+
+      ${Case} '/l'
+      ${Case} '/log'
+      ${Case} '/logging'
+        StrCpy $g_bLogEnable "true"
+      ${Break}
+
+      ${Case} '/ncrc' ; NSIS: /NCRC switch, skip
+        ${Break}
+
+      ${Case} '/no_videodrv'
+        StrCpy $g_bNoVideoDrv "true"
+      ${Break}
+
+      ${Case} '/no_guestdrv'
+        StrCpy $g_bNoGuestDrv "true"
+      ${Break}
+
+      ${Case} '/no_mousedrv'
+        StrCpy $g_bNoMouseDrv "true"
+      ${Break}
+
+      ${Case} '/reboot'
+        StrCpy $g_bRebootOnExit "true"
+        ${Break}
+
+      ${Case} '/s' ; NSIS: /S switch, skip
+        ${Break}
+
+      ${Case} '/sforder'
+      ${Case} 'sforder'
+        StrCpy $g_iSfOrder $5
+        ${Break}
+
+    !ifdef WHQL_FAKE
+      ${Case} '/unsig_drv'
+        StrCpy $g_bFakeWHQL "true"
+      ${Break}
+    !endif
+
+      ${Case} '/uninstall'
+        StrCpy $g_bUninstall "true"
+        ${Break}
+
+      ${Case} '/with_autologon'
+        StrCpy $g_bWithAutoLogon "true"
+        ${Break}
+
+    !if $%VBOX_WITH_CROGL% == "1"
+      ${Case} '/with_d3d'
+      ${Case} '/with_direct3d'
+        StrCpy $g_bWithD3D "true"
+        ${Break}
+    !endif
+
+      ${Case} '/xres'
+      ${Case} 'xres'
+        StrCpy $g_iScreenX $5
+        ${Break}
+
+      ${Case} '/yres'
+      ${Case} 'yres'
+        StrCpy $g_iScreenY $5
+        ${Break}
+
+      ${Default}                              ; Unknown parameter, print usage message
+        goto usage
+        ${Break}
+
+    ${EndSwitch}
+    IntOp $2 $2 + 1
+
+  ${EndWhile}
+  Goto exit
+
+usage:
+
+  MessageBox MB_OK "${PRODUCT_NAME} Installer$\r$\n$\r$\n \
+                    Usage: VBoxWindowsAdditions-$%BUILD_TARGET_ARCH% [OPTIONS] [/l] [/S] [/D=<PATH>]$\r$\n$\r$\n \
+                    Options:$\r$\n \
+                    /depth=BPP$\tSets the guest's display color depth (bits per pixel)$\r$\n \
+                    /extract$\t$\tOnly extract installation files$\r$\n \
+                    /uninstall$\t$\tJust uninstalls the Guest Additions and exits$\r$\n \
+                    /with_autologon$\tInstalls auto-logon support$\r$\n \
+                    /with_d3d$\tInstalls D3D support$\r$\n \
+                    /xres=X$\t$\tSets the guest's display resolution (width in pixels)$\r$\n \
+                    /yres=Y$\t$\tSets the guest's display resolution (height in pixels)$\r$\n \
+                    $\r$\n \
+                    Installer parameters:$\r$\n \
+                    /l$\t$\tEnables logging$\r$\n \
+                    /S$\t$\tSilent install$\r$\n \
+                    /D=<PATH>$\tSets the default install path$\r$\n \
+                    $\r$\n \
+                    Note: Order of options and installer parameters are mandatory."
+
+  ; No stack restore needed, we're about to quit
+  Quit
+
+done:
+
+  IfSilent 0 +2
+    LogText "Installer is in silent mode!"
+
+  LogText "Property: XRes: $g_iScreenX"
+  LogText "Property: YRes: $g_iScreenY"
+  LogText "Property: BPP: $g_iScreenBpp"
+  LogText "Property: Logging enabled: $g_bLogEnable"
+
+exit:
+
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+
+Function CheckForOldGuestAdditions
+
+  Push $0
+  Push $1
+  Push $2
+
+begin:
+
+sun_check:
+
+  ; Check for old "Sun VirtualBox Guest Additions"
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sun VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" sun_xvm_check     ; If string is empty, Sun additions are probably not installed (anymore).
+
+  MessageBox MB_YESNO $(VBOX_SUN_FOUND) /SD IDYES IDYES sun_uninstall
+    Pop $2
+    Pop $1
+    Pop $0
+    MessageBox MB_ICONSTOP $(VBOX_SUN_ABORTED) /SD IDOK
+    Quit
+
+sun_uninstall:
+
+  Call Uninstall_Sun
+  Goto success
+
+sun_xvm_check:
+
+  ; Check for old "innotek" Guest Additions" before rebranding to "Sun"
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sun xVM VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" innotek_check     ; If string is empty, Sun xVM additions are probably not installed (anymore).
+
+  MessageBox MB_YESNO $(VBOX_SUN_FOUND) /SD IDYES IDYES sun_xvm_uninstall
+    Pop $2
+    Pop $1
+    Pop $0
+    MessageBox MB_ICONSTOP $(VBOX_SUN_ABORTED) /SD IDOK
+    Quit
+
+sun_xvm_uninstall:
+
+  Call Uninstall_SunXVM
+  Goto success
+
+innotek_check:
+
+  ; Check for old "innotek" Guest Additions" before rebranding to "Sun"
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\innotek VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" exit     ; If string is empty, Guest Additions are probably not installed (anymore).
+
+  MessageBox MB_YESNO $(VBOX_INNOTEK_FOUND) /SD IDYES IDYES innotek_uninstall
+    Pop $2
+    Pop $1
+    Pop $0
+    MessageBox MB_ICONSTOP $(VBOX_INNOTEK_ABORTED) /SD IDOK
+    Quit
+
+innotek_uninstall:
+
+  Call Uninstall_Innotek
+  Goto success
+
+success:
+
+  ; Nothing to do here yet
+
+exit:
+
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+
+Function CheckArchitecture
+
+  System::Call "kernel32::GetCurrentProcess() i .s"
+  System::Call "kernel32::IsWow64Process(i s, *i .r0)"
+  DetailPrint "Running on 64bit: $0"
+
+!if $%BUILD_TARGET_ARCH% == "amd64"   ; 64-bit
+  IntCmp $0 0 not_32bit_platform
+!else   ; 32-bit
+  IntCmp $0 1 not_64bit_platform
+!endif
+
+  Goto exit
+
+not_32bit_platform:
+
+  MessageBox MB_ICONSTOP $(VBOX_NOTICE_ARCH_AMD64) /SD IDOK
+  Quit
+
+not_64bit_platform:
+
+  MessageBox MB_ICONSTOP $(VBOX_NOTICE_ARCH_X86) /SD IDOK
+  Quit
+
+exit:
+
+FunctionEnd
+
+Function PrepareForUpdate
+
+  StrCmp $g_strAddVerMaj "1" v1     ; Handle major version "v1.x"
+  StrCmp $g_strAddVerMaj "2" v2     ; Handle major version "v2.x"
+  StrCmp $g_strAddVerMaj "3" v3     ; Handle major version "v3.x"
+  Goto exit
+
+v3:
+
+  Goto exit
+
+v2:
+
+  Goto exit
+
+v1:
+
+  StrCmp $g_strAddVerMin "5" v1_5   ; Handle major version "v1.5.x"
+  StrCmp $g_strAddVerMin "6" v1_6   ; Handle major version "v1.6.x"
+
+v1_5:
+
+  Goto exit
+
+v1_6:
+
+  Goto exit
+
+exit:
+
+FunctionEnd
+
+Function Common_CopyFiles
+
+  SetOutPath "$INSTDIR"
+  SetOverwrite on
+
+  FILE "$%PATH_OUT%\bin\additions\VBoxDrvInst.exe"
+
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.cat"
+!endif
+
+  FILE "iexplore.ico"
+
+FunctionEnd
+
+; Main Files
+Section $(VBOX_COMPONENT_MAIN) SEC01
+
+  SectionIn RO ; Section cannot be unselected (read-only)
+
+  SetOutPath "$INSTDIR"
+  SetOverwrite on
+
+  ; Because this NSIS installer is always built in 32-bit mode, we have to
+  ; do some tricks for the Windows paths
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ; Because the next two lines will crash at the license page (??) we have to re-enable that here again
+  ${DisableX64FSRedirection}
+  SetRegView 64
+!endif
+
+  StrCpy $g_strSystemDir "$SYSDIR"
+  DetailPrint "System Directory: $g_strSystemDir"
+
+  Call EnableLog
+  Call PrepareForUpdate
+
+  DetailPrint "Version: $%VBOX_VERSION_STRING%"
+  ${If} $g_strAddVerMaj != ""
+    DetailPrint "Previous version: $g_strAddVerMaj.$g_strAddVerMin.$g_strAddVerBuild (Rev $g_strAddVerRev)"
+  ${Else}
+    DetailPrint "No previous version of ${PRODUCT_NAME} detected."
+  ${EndIf}
+  DetailPrint "Handled Windows version: $g_strWinVersion"
+
+!ifdef _DEBUG
+  DetailPrint "Debug!"
+!endif
+
+  ; Which OS we are using?
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  StrCmp $g_strWinVersion "nt4" nt4
+!endif
+  StrCmp $g_strWinVersion "2k" w2k
+  StrCmp $g_strWinVersion "vista" vista
+
+  Goto notsupported
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+nt4:      ; Windows NT4
+
+  Call GetServicePack
+  Pop $R0   ; Major version
+  Pop $R1   ; Minor version
+
+  ; At least Service Pack 6 installed?
+  StrCmp $R0 "6" +3
+    MessageBox MB_YESNO $(VBOX_NT4_NO_SP6) /SD IDYES IDYES +2
+    Quit
+
+  ; Copy some common files ...
+  Call Common_CopyFiles
+
+  Call NT_Main
+  goto success
+!endif
+
+vista:  ; Windows Vista (fall through, needs stuff from w2k label, too)
+
+  ; Copy some common files ...
+  Call Common_CopyFiles
+
+  Call W2K_Main     ; First install stuff from Windows 2000 / XP
+  Call Vista_Main   ; ... and some specific stuff for Vista
+  goto success
+
+w2k:    ; Windows 2000 and XP ...
+
+  ; Copy some common files ...
+  Call Common_CopyFiles
+
+  Call W2K_Main
+  goto success
+
+notsupported:
+
+  MessageBox MB_ICONSTOP $(VBOX_PLATFORM_UNSUPPORTED) /SD IDOK
+  goto exit
+
+success:
+
+  ; Write a registry key with version and installation path for later lookup
+  WriteRegStr HKLM "${PRODUCT_INSTALL_KEY}" "Version" "$%VBOX_VERSION_STRING%"
+  WriteRegStr HKLM "${PRODUCT_INSTALL_KEY}" "Revision" "$%VBOX_SVN_REV%"
+  WriteRegStr HKLM "${PRODUCT_INSTALL_KEY}" "InstallDir" "$INSTDIR"
+
+!ifndef _DEBUG
+  SetRebootFlag true  ; This will show a reboot page at end of installation
+!endif
+
+exit:
+
+  Call WriteLogUI
+
+SectionEnd
+
+; Auto-logon support (section is hidden at the moment -- only can be enabled via command line switch)
+Section /o -$(VBOX_COMPONENT_AUTOLOGON) SEC02
+
+  ; Because this NSIS installer is always built in 32-bit mode, we have to
+  ; do some tricks for the Windows paths.
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ; Because the next two lines will crash at the license page (??) we have to re-enable that here again
+  ${DisableX64FSRedirection}
+  SetRegView 64
+!endif
+
+  Call GetWindowsVersion
+  Pop $R0 ; Windows Version
+
+  DetailPrint "Installing auto-logon support ..."
+
+  ; Another GINA already is installed? Check if this is ours, otherwise let the user decide (unless it's a silent setup)
+  ; whether to replace it with the VirtualBox one or not.
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon" "GinaDLL"
+  ${If} $0 != ""
+    ${If} $0 != "VBoxGINA.dll"
+      MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1 $(VBOX_COMPONENT_AUTOLOGON_WARN_3RDPARTY) /SD IDYES IDYES install
+      goto exit
+    ${EndIf}
+  ${EndIf}
+
+install:
+
+  ; Do we need VBoxCredProv or VBoxGINA?
+  ${If}   $R0 == 'Vista'
+  ${OrIf} $R0 == '7'
+    !insertmacro ReplaceDLL "$%PATH_OUT%\bin\additions\VBoxCredProv.dll" "$g_strSystemDir\VBoxCredProv.dll" "$INSTDIR"
+    WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}" "" "VBoxCredProv" ; adding to (default) key
+    WriteRegStr HKCR "CLSID\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}" "" "VBoxCredProv"                       ; adding to (Default) key
+    WriteRegStr HKCR "CLSID\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}\InprocServer32" "" "VBoxCredProv.dll"    ; adding to (Default) key
+    WriteRegStr HKCR "CLSID\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}\InprocServer32" "ThreadingModel" "Apartment"
+  ${Else}
+    !insertmacro ReplaceDLL "$%PATH_OUT%\bin\additions\VBoxGINA.dll" "$g_strSystemDir\VBoxGINA.dll" "$INSTDIR"
+    WriteRegStr HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon" "GinaDLL" "VBoxGINA.dll"
+  ${EndIf}
+
+exit:
+
+SectionEnd
+
+; Prepares the access rights for replacing a WRP protected file
+Function PrepareWRPFile
+
+  Pop $0
+  IfFileExists "$g_strSystemDir\takeown.exe" 0 +2
+    nsExec::ExecToLog '"$g_strSystemDir\takeown.exe" /F "$0"'
+  AccessControl::SetFileOwner "$0" "(S-1-5-32-545)"
+  Pop $1
+  DetailPrint "Setting file owner for '$0': $1"
+  AccessControl::GrantOnFile "$0" "(S-1-5-32-545)" "FullAccess"
+  Pop $1
+  DetailPrint "Setting access rights for '$0': $1"
+
+FunctionEnd
+
+; Direct3D support
+!if $%VBOX_WITH_CROGL% == "1"
+Section /o $(VBOX_COMPONENT_D3D) SEC03
+
+  Push $R0
+
+  Call GetWindowsVersion
+  Pop $R0 ; Windows Version
+
+  ; If we're not in safe mode, print a warning and do nothing here
+  ${If} $g_iSystemMode == '0'
+    DetailPrint "System is not in safe mode, D3D support will not be installed!"
+    Return
+  ${EndIf}
+
+  ; Do not install on < XP
+  ${If}   $R0 == 'NT 3'
+  ${OrIf} $R0 == 'NT 4'
+  ${OrIf} $R0 == '2000'
+  ${OrIf} $R0 == ''
+    DetailPrint "Direct3D guest support not available on this platform!"
+    Return
+  ${EndIf}
+
+  !define LIBRARY_IGNORE_VERSION ; Install in every case
+  SetOverwrite on
+
+  ${If} $g_strSystemDir == ''
+    StrCpy $g_strSystemDir "$SYSDIR"
+  ${EndIf}
+
+  ; crOpenGL: Do *not* install 64-bit files - they don't work yet (use !define LIBRARY_X64 later)
+  ;           Only 32-bit apps on 64-bit work (see next block)
+  !if $%BUILD_TARGET_ARCH% == "x86"
+    SetOutPath $g_strSystemDir
+    DetailPrint "Installing Direct3D support ..."
+    FILE "$%PATH_OUT%\bin\additions\libWine.dll"
+    FILE "$%PATH_OUT%\bin\additions\VBoxD3D8.dll"
+    FILE "$%PATH_OUT%\bin\additions\VBoxD3D9.dll"
+    FILE "$%PATH_OUT%\bin\additions\wined3d.dll"
+
+    ; Update DLL cache
+    SetOutPath "$g_strSystemDir\dllcache"
+    IfFileExists "$g_strSystemDir\dllcache\msd3d8.dll" +1
+      CopyFiles /SILENT "$g_strSystemDir\dllcache\d3d8.dll" "$g_strSystemDir\dllcache\msd3d8.dll"
+    IfFileExists "$g_strSystemDir\dllcache\msd3d9.dll" +1
+      CopyFiles /SILENT "$g_strSystemDir\dllcache\d3d9.dll" "$g_strSystemDir\dllcache\msd3d9.dll"
+
+    Push "$g_strSystemDir\dllcache\d3d8.dll"
+    Call PrepareWRPFile
+
+    Push "$g_strSystemDir\dllcache\d3d9.dll"
+    Call PrepareWRPFile
+
+    ; Exchange DLLs
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d8.dll" "$g_strSystemDir\dllcache\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d9.dll" "$g_strSystemDir\dllcache\d3d9.dll" "$TEMP"
+
+    ; If exchange above failed, do it on reboot
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d8.dll" "$g_strSystemDir\dllcache\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d9.dll" "$g_strSystemDir\dllcache\d3d9.dll" "$TEMP"
+
+    ; Save original DLLs ...
+    SetOutPath $g_strSystemDir
+    IfFileExists "$g_strSystemDir\msd3d8.dll" +1
+      CopyFiles /SILENT "$g_strSystemDir\d3d8.dll" "$g_strSystemDir\msd3d8.dll"
+    IfFileExists "$g_strSystemDir\msd3d8.dll" +1
+      CopyFiles /SILENT "$g_strSystemDir\d3d9.dll" "$g_strSystemDir\msd3d9.dll"
+
+    Push "$g_strSystemDir\d3d8.dll"
+    Call PrepareWRPFile
+
+    Push "$g_strSystemDir\d3d9.dll"
+    Call PrepareWRPFile
+
+    ; Exchange DLLs
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d8.dll" "$g_strSystemDir\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d9.dll" "$g_strSystemDir\d3d9.dll" "$TEMP"
+
+    ; If exchange above failed, do it on reboot
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d8.dll" "$g_strSystemDir\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%PATH_OUT%\bin\additions\d3d9.dll" "$g_strSystemDir\d3d9.dll" "$TEMP"
+  !endif
+
+  !if $%BUILD_TARGET_ARCH% == "amd64"
+    ; Only 64-bit installer: Also copy 32-bit DLLs on 64-bit target arch in
+    ; Wow64 node (32-bit sub system)
+    ${EnableX64FSRedirection}
+    SetOutPath $SYSDIR
+    DetailPrint "Installing Direct3D support (Wow64) ..."
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\libWine.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxD3D8.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxD3D9.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\wined3d.dll"
+
+    ; Update DLL cache
+    SetOutPath "$SYSDIR\dllcache"
+    IfFileExists "$SYSDIR\dllcache\msd3d8.dll" +1
+      CopyFiles /SILENT "$SYSDIR\dllcache\d3d8.dll" "$SYSDIR\dllcache\msd3d8.dll"
+    IfFileExists "$SYSDIR\dllcache\msd3d9.dll" +1
+      CopyFiles /SILENT "$SYSDIR\dllcache\d3d9.dll" "$SYSDIR\dllcache\msd3d9.dll"
+
+    Push "$SYSDIR\dllcache\d3d8.dll"
+    Call PrepareWRPFile
+
+    Push "$SYSDIR\dllcache\d3d9.dll"
+    Call PrepareWRPFile
+
+    ; Exchange DLLs
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d8.dll" "$SYSDIR\dllcache\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d9.dll" "$SYSDIR\dllcache\d3d9.dll" "$TEMP"
+
+    ; If exchange above failed, do it on reboot
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d8.dll" "$SYSDIR\dllcache\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d9.dll" "$SYSDIR\dllcache\d3d9.dll" "$TEMP"
+
+    ; Save original DLLs ...
+    SetOutPath $SYSDIR
+    IfFileExists "$SYSDIR\dllcache\msd3d8.dll" +1
+      CopyFiles /SILENT "$SYSDIR\d3d8.dll" "$SYSDIR\msd3d8.dll"
+    IfFileExists "$SYSDIR\dllcache\msd3d9.dll" +1
+      CopyFiles /SILENT "$SYSDIR\d3d9.dll" "$SYSDIR\msd3d9.dll"
+
+    Push "$SYSDIR\d3d8.dll"
+    Call PrepareWRPFile
+
+    Push "$SYSDIR\d3d9.dll"
+    Call PrepareWRPFile
+
+    ; Exchange DLLs
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d8.dll" "$SYSDIR\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED NOREBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d9.dll" "$SYSDIR\d3d9.dll" "$TEMP"
+
+    ; If exchange above failed, do it on reboot
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d8.dll" "$SYSDIR\d3d8.dll" "$TEMP"
+    !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d9.dll" "$SYSDIR\d3d9.dll" "$TEMP"
+
+    ${DisableX64FSRedirection}
+  !endif ; amd64
+  Goto done
+
+error:
+  ; @todo
+  Goto exit
+
+done:
+  MessageBox MB_ICONINFORMATION|MB_OK $(VBOX_WFP_WARN_REPLACE) /SD IDOK
+  Goto exit
+
+  Pop $R0
+
+exit:
+
+SectionEnd
+!endif ; VBOX_WITH_CROGL
+
+;Assign language strings to sections
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} $(VBOX_COMPONENT_MAIN_DESC)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} $(VBOX_COMPONENT_AUTOLOGON_DESC)
+!if $%VBOX_WITH_CROGL% == "1"
+  !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} $(VBOX_COMPONENT_D3D_DESC)
+!endif
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+Section -Content
+
+  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+
+SectionEnd
+
+Section -StartMenu
+
+  CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
+  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" "" "$INSTDIR\iexplore.ico"
+  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
+
+SectionEnd
+
+; This section is called after all the files are in place
+Section -Post
+
+!ifdef _DEBUG
+  DetailPrint "Doing post install ..."
+!endif
+
+!ifdef EXTERNAL_UNINSTALLER
+  SetOutPath "$INSTDIR"
+  FILE "$%PATH_TARGET%\uninst.exe"
+!else
+  WriteUninstaller "$INSTDIR\uninst.exe"
+!endif
+
+  ; Write uninstaller in "Add / Remove programs"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+
+  ; Tune TcpWindowSize for a better network throughput
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" "TcpWindowSize" 64240
+
+  DetailPrint "Installation completed."
+
+SectionEnd
+
+; This function is called when a critical error occured
+Function .onInstFailed
+
+  MessageBox MB_ICONSTOP $(VBOX_ERROR_INST_FAILED) /SD IDOK
+  StrCpy $g_bLogEnable "true"
+  Call WriteLogUI
+  SetErrorLevel 1
+
+FunctionEnd
+
+; This function is called when installation was successful!
+Function .onInstSuccess
+
+  ; Nothing to do here yet ...
+
+FunctionEnd
+
+; This function is called at the very beginning of installer execution
+Function .onInit
+
+  ; Init values
+  StrCpy $g_iSystemMode "0"
+  StrCpy $g_strAddVerMaj "0"
+  StrCpy $g_strAddVerMin "0"
+  StrCpy $g_strAddVerBuild "0"
+  StrCpy $g_strAddVerRev "0"
+
+  StrCpy $g_bLogEnable "false"
+  StrCpy $g_bFakeWHQL "false"
+  StrCpy $g_bUninstall "false"
+  StrCpy $g_bRebootOnExit "false"
+  StrCpy $g_iScreenX "0"
+  StrCpy $g_iScreenY "0"
+  StrCpy $g_iScreenBpp "0"
+  StrCpy $g_iSfOrder "0"
+  StrCpy $g_bNoVideoDrv "false"
+  StrCpy $g_bNoGuestDrv "false"
+  StrCpy $g_bNoMouseDrv "false"
+  StrCpy $g_bWithAutoLogon "false"
+  StrCpy $g_bWithD3D "false"
+  StrCpy $g_bOnlyExtract "false"
+
+  SetErrorLevel 0
+  ClearErrors
+
+!ifndef UNINSTALLER_ONLY
+
+  ; Handle command line
+  Call HandleCommandLine
+
+  ; Retrieve Windows version and store result in $g_strWinVersion
+  Call GetWindowsVer
+
+  ; Retrieve system mode and store result in
+  System::Call 'user32::GetSystemMetrics(i ${SM_CLEANBOOT}) i .r0'
+  StrCpy $g_iSystemMode $0
+  DetailPrint "System mode: $g_iSystemMode"
+
+  ; Get user Name
+  AccessControl::GetCurrentUserName
+  Pop $g_strCurUser
+  DetailPrint "Current user: $g_strCurUser"
+
+  ; Only uninstall?
+  StrCmp $g_bUninstall "true" uninstall
+
+  ; Only extract files?
+  StrCmp $g_bOnlyExtract "true" extract_files
+
+  ; Set section bits
+  ${If} $g_bWithAutoLogon == "true" ; Auto-logon support
+    SectionSetFlags ${SEC02} ${SF_SELECTED}
+  ${EndIf}
+!if $%VBOX_WITH_CROGL% == "1"
+  ${If} $g_bWithD3D == "true" ; D3D support
+    SectionSetFlags ${SEC03} ${SF_SELECTED}
+  ${EndIf}
+!endif
+
+  ; Display language selection dialog (will be hidden in silent mode!)
+  !ifdef VBOX_INSTALLER_ADD_LANGUAGES
+    !insertmacro MUI_LANGDLL_DISPLAY
+  !endif
+
+  ; Do some checks before we actually start ...
+  Call IsUserAdmin
+
+  ; Check if there's already another instance of the installer is running -
+  ; important for preventing NT4 to spawn the installer twice
+  System::Call 'kernel32::CreateMutexA(i 0, i 0, t "VBoxGuestInstaller") ?e'
+  Pop $R0
+  StrCmp $R0 0 +1 exit
+
+  ; Check for correct architecture
+  Call CheckArchitecture
+
+  ; Because this NSIS installer is always built in 32-bit mode, we have to
+  ; do some tricks for the Windows paths for checking for old additions
+  ; in block below.
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ${DisableX64FSRedirection}
+  SetRegView 64
+!endif
+
+  ; Check for old additions
+  Call CheckForOldGuestAdditions
+  Call GetAdditionsVersion
+
+  ; Due to some bug in NSIS the license page won't be displayed if we're in
+  ; 64-bit registry view, so as a workaround switch back to 32-bit (Wow6432Node)
+  ; mode for now.
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ${EnableX64FSRedirection}
+  SetRegView 32
+!endif
+
+  Goto done
+
+uninstall:
+
+  Call Uninstall_Innotek
+  Call Uninstall
+  MessageBox MB_ICONINFORMATION|MB_OK $(VBOX_UNINST_SUCCESS) /SD IDOK
+  Goto exit
+
+extract_files:
+
+  Call ExtractFiles
+  MessageBox MB_OK|MB_ICONINFORMATION $(VBOX_EXTRACTION_COMPLETE) /SD IDOK
+  Goto exit
+
+!else ; UNINSTALLER_ONLY
+
+  ;
+  ; If UNINSTALLER_ONLY is defined, we're only interested in uninst.exe
+  ; so we can sign it.
+  ;
+  ; Note that the Quit causes the exit status to be 2 instead of 0.
+  ;
+  WriteUninstaller "$%PATH_TARGET%\uninst.exe"
+  Goto exit
+
+!endif ; UNINSTALLER_ONLY
+
+exit:    ; Abort installer for some reason
+
+  Quit
+
+done:
+
+FunctionEnd
+
+;
+; The uninstaller is built separately when doing code signing.
+; For some reason NSIS still finds the Uninstall section even
+; when EXTERNAL_UNINSTALLER is defined. This causes a silly warning.
+;
+!ifndef EXTERNAL_UNINSTALLER
+
+Function un.onUninstSuccess
+
+  HideWindow
+  MessageBox MB_ICONINFORMATION|MB_OK $(VBOX_UNINST_SUCCESS) /SD IDOK
+
+FunctionEnd
+
+Function un.onInit
+
+  Call un.IsUserAdmin
+
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 $(VBOX_UNINST_CONFIRM) /SD IDYES IDYES proceed
+  Quit
+
+proceed:
+
+  ; Because this NSIS installer is always built in 32-bit mode, we have to
+  ; do some tricks for the Windows paths.
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ${DisableX64FSRedirection}
+  SetRegView 64
+!endif
+
+  ; Set system directory.
+  StrCpy $g_strSystemDir "$SYSDIR"
+
+  ; Retrieve Windows version we're running on and store it in $g_strWinVersion
+  Call un.GetWindowsVer
+
+FunctionEnd
+
+Function .onSelChange
+
+  Push $0
+
+  ; Section: D3D
+  SectionGetFlags ${SEC03} $0
+
+  ${If} $0 == ${SF_SELECTED}
+    ; If we're not in safe mode, print a warning and don't install D3D support
+    ${If} $g_iSystemMode == '0'
+        IntOp $0 $0 & ${SECTION_OFF} ; Unselect section again
+        SectionSetFlags ${SEC03} $0
+        MessageBox MB_ICONINFORMATION|MB_OK $(VBOX_COMPONENT_D3D_NO_SM) /SD IDOK
+        Return
+    ${EndIf}
+  ${EndIf}
+
+  Pop $0
+
+FunctionEnd
+
+Section Uninstall
+
+!ifdef _DEBUG
+  ; Enable logging
+  Call un.EnableLog
+!endif
+
+  ; Because this NSIS installer is always built in 32-bit mode, we have to
+  ; do some tricks for the Windows paths.
+!if $%BUILD_TARGET_ARCH% == "amd64"
+  ; Do *not* add this line in .onInit - it will crash at the license page (??) because of a weird NSIS bug.
+  ${DisableX64FSRedirection}
+  SetRegView 64
+!endif
+
+  ; Call the uninstall main function.
+  Call un.Uninstall
+
+  ; ... and remove the local install directory
+  Call un.UninstallInstDir
+
+!ifndef _DEBUG
+  SetAutoClose true
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 $(VBOX_REBOOT_REQUIRED) /SD IDNO IDYES restart
+  StrCmp $g_bRebootOnExit "true" restart
+!endif
+
+  Goto exit
+
+restart:
+
+  DetailPrint "Rebooting ..."
+  Reboot
+
+exit:
+
+SectionEnd
+
+; !EXTERNAL_UNINSTALLER
+!endif
+
+;Direct the output to our bin dir
+!cd "$%PATH_OUT%\bin\additions"
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsCommon.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsCommon.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsCommon.nsh	(revision 31634)
@@ -0,0 +1,438 @@
+
+!ifndef UNINSTALLER_ONLY
+Function ExtractFiles
+
+  ; @todo: Use a define for all the file specs to group the files per module
+  ; and keep the redundancy low.
+
+  Push $0
+  StrCpy "$0" "$INSTDIR\$%BUILD_TARGET_ARCH%"
+
+  ; Video driver
+  SetOutPath "$0\VBoxVideo"
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.cat"
+!endif
+  FILE "$%PATH_OUT%\bin\additions\VBoxDisp.dll"
+
+!if $%VBOX_WITH_CROGL% == "1"
+  ; crOpenGL
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLarrayspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLcrutil.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLerrorspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLpackspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLpassthroughspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLfeedbackspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGL.dll"
+
+  ; Do *not* install 64-bit d3d files - they don't work yet.
+  !if $%BUILD_TARGET_ARCH% == "x86"
+    SetOutPath "$0\VBoxVideo\OpenGL"
+    FILE "$%PATH_OUT%\bin\additions\d3d8.dll"
+    FILE "$%PATH_OUT%\bin\additions\d3d9.dll"
+    FILE "$%PATH_OUT%\bin\additions\libWine.dll"
+    FILE "$%PATH_OUT%\bin\additions\VBoxD3D8.dll"
+    FILE "$%PATH_OUT%\bin\additions\VBoxD3D9.dll"
+    FILE "$%PATH_OUT%\bin\additions\wined3d.dll"
+  !endif
+
+  !if $%BUILD_TARGET_ARCH% == "amd64"
+    ; Only 64-bit installer: Also copy 32-bit DLLs on 64-bit target
+    SetOutPath "$0\VBoxVideo\OpenGL\SysWow64"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d8.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\d3d9.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\libWine.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLarrayspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLcrutil.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLerrorspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLpackspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLpassthroughspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLfeedbackspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGL.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxD3D8.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxD3D9.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\wined3d.dll"
+  !endif
+!endif
+
+  ; Mouse driver
+  SetOutPath "$0\VBoxMouse"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.cat"
+!endif
+
+!if $%BUILD_TARGET_ARCH% == "x86"
+  SetOutPath "$0\VBoxMouse\NT4"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouseNT.sys"
+!endif
+
+  ; Guest driver
+  SetOutPath "$0\VBoxGuest"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.cat"
+!endif
+  FILE "$%PATH_OUT%\bin\additions\VBCoInst.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxTray.exe"
+  FILE "$%PATH_OUT%\bin\additions\VBoxHook.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxControl.exe"
+
+!if $%BUILD_TARGET_ARCH% == "x86"
+  SetOutPath "$0\VBoxGuest\NT4"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuestNT.sys"
+!endif
+
+  ; VBoxService
+  SetOutPath "$0\Bin"
+  FILE "$%PATH_OUT%\bin\additions\VBoxService.exe"
+!if $%BUILD_TARGET_ARCH% == "x86"
+  FILE "$%PATH_OUT%\bin\additions\VBoxServiceNT.exe"
+!endif
+
+  ; Shared Folders
+  SetOutPath "$0\VBoxSF"
+  FILE "$%PATH_OUT%\bin\additions\VBoxSF.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMRXNP.dll"
+
+  ; AMD PCNet driver
+  SetOutPath "$0\Network\AMD"
+  FILE "..\Network\AMD\netamd.inf"
+  FILE "..\Network\AMD\pcntpci5.cat"
+  FILE "..\Network\AMD\PCNTPCI5.sys"
+
+  ; Auto-Logon
+  SetOutPath "$0\AutoLogon"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGINA.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxCredProv.dll"
+
+  ; Misc tools
+  SetOutPath "$0\Tools"
+  FILE "$%PATH_OUT%\bin\additions\VBoxDrvInst.exe"
+
+!if $%BUILD_TARGET_ARCH% == "x86"
+  SetOutPath "$0\Tools\NT4"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuestDrvInst.exe"
+  FILE "$%PATH_OUT%\bin\additions\RegCleanup.exe"
+!endif
+
+  Pop $0
+
+FunctionEnd
+!endif ; UNINSTALLER_ONLY
+
+!macro EnableLog un
+Function ${un}EnableLog
+
+!ifdef _DEBUG
+  Goto log
+!endif
+
+  StrCmp $g_bLogEnable "true" log
+  Goto exit
+
+log:
+
+  LogSet on
+  LogText "Start logging."
+
+exit:
+
+FunctionEnd
+!macroend
+!insertmacro EnableLog ""
+!insertmacro EnableLog "un."
+
+!macro WriteLogUI un
+Function ${un}WriteLogUI
+
+  IfSilent exit
+
+!ifdef _DEBUG
+  Goto log
+!endif
+
+  StrCmp $g_bLogEnable "true" log
+  Goto exit
+
+log:
+
+  ; Dump log to see what happend
+  StrCpy $0 "$INSTDIR\${un}install_ui.log"
+  Push $0
+  Call ${un}DumpLog
+
+exit:
+
+FunctionEnd
+!macroend
+!insertmacro WriteLogUI ""
+!insertmacro WriteLogUI "un."
+
+!macro GetWindowsVer un
+Function ${un}GetWindowsVer
+
+  ; Check if we are running on w2k or above. For other windows versions (>XP) it may be necessary to change winver.nsh
+  ; Get the Windows version
+  Call ${un}GetWindowsVersion
+  Pop $R3     ; Windows Version
+
+  Push $R3    ; The windows version string
+  Push "NT"   ; String to search for. Win 2k family returns no string containing 'NT'
+  Call ${un}StrStr
+  Pop $R0
+  StrCmp $R0 '' no_nt4  ; Not NT 3.XX or 4.XX
+
+  ; Ok we know it is NT. Must be a string like NT X.XX
+  Push $R3    ; The windows version string
+  Push "4."   ; String to search for
+  Call ${un}StrStr
+  Pop $R0
+  StrCmp $R0 "" no_nt4 nt4   ; If empty -> not NT 4
+
+no_nt4:
+
+  StrCmp $R3 "2000" w2k_xp
+  StrCmp $R3 "XP" w2k_xp
+  StrCmp $R3 "2003" w2k_xp
+  StrCmp $R3 "Vista" vista
+  StrCmp $R3 "7" vista
+  Goto unknown
+
+nt4:        ; NT 4.0
+
+  StrCpy $g_strWinVersion "nt4"
+  goto exit
+
+w2k_xp:     ; NT 5.0, 5.1 or 5.2
+
+  StrCpy $g_strWinVersion "2k"
+  goto exit
+
+vista:      ; NT 6.0 or 6.1 (Vista or Windows 7)
+
+  StrCpy $g_strWinVersion "vista"
+  goto exit
+
+unknown:
+
+  StrCpy $g_strWinVersion "unknown"
+  goto exit
+
+exit:
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro GetWindowsVer ""
+!insertmacro GetWindowsVer "un."
+
+!macro GetAdditionsVersion un
+Function ${un}GetAdditionsVersion
+
+  Push $0
+  Push $1
+
+  ; Get additions version
+  ReadRegStr $0 HKLM "SOFTWARE\$%VBOX_VENDOR_SHORT%\VirtualBox Guest Additions" "Version"
+
+  ; Get revision
+  ReadRegStr $g_strAddVerRev HKLM "SOFTWARE\$%VBOX_VENDOR_SHORT%\VirtualBox Guest Additions" "Revision"
+
+  ; Extract major version
+  Push "$0"       ; String
+  Push "."        ; SubString
+  Push ">"        ; SearchDirection
+  Push "<"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $g_strAddVerMaj
+
+  ; Extract minor version
+  Push "$0"       ; String
+  Push "."        ; SubString
+  Push ">"        ; SearchDirection
+  Push ">"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $1          ; Got first part (e.g. "1.5")
+
+  Push "$1"       ; String
+  Push "."        ; SubString
+  Push ">"        ; SearchDirection
+  Push "<"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $g_strAddVerMin   ; Extracted second part (e.g. "5" from "1.5")
+
+  ; Extract build number
+  Push "$0"       ; String
+  Push "."        ; SubString
+  Push "<"        ; SearchDirection
+  Push ">"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $g_strAddVerBuild
+
+exit:
+
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro GetAdditionsVersion ""
+!insertmacro GetAdditionsVersion "un."
+
+!macro IsUserAdmin un
+Function ${un}IsUserAdmin
+
+  ; Check if current user has admin rights
+  UserInfo::GetAccountType
+  Pop $0
+  StrCmp $0 "Admin" is_admin 0
+    MessageBox MB_ICONSTOP $(VBOX_NOADMIN)
+    Abort
+
+is_admin:
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro IsUserAdmin ""
+!insertmacro IsUserAdmin "un."
+
+!macro StopVBoxService un
+Function ${un}StopVBoxService
+
+  Push $0   ; Temp results
+  Push $1
+  Push $2   ; Image name of VBoxService
+  Push $3   ; Safety counter
+
+  StrCpy $3 "0" ; Init counter
+  DetailPrint "Stopping VBoxService ..."
+
+svc_stop:
+
+  LogText "Stopping VBoxService (as service) ..."
+  ${If} $g_strWinVersion == "nt4"
+   nsExec::Exec '"$SYSDIR\net.exe" stop VBoxService'
+  ${Else}
+   nsExec::Exec '"$SYSDIR\SC.exe" stop VBoxService'
+  ${EndIf}
+  Sleep "1000"           ; Wait a bit
+
+exe_stop:
+
+!ifdef _DEBUG
+  DetailPrint "Stopping VBoxService (as exe) ..."
+!endif
+
+exe_stop_loop:
+
+  IntCmp $3 10 exit      ; Only try this loop 10 times max
+  IntOp  $3 $3 + 1       ; Increment
+
+  LogText "Try: $3"
+
+  ${If} $g_strWinVersion == "nt4"
+    StrCpy $2 "VBoxServiceNT.exe"
+  ${Else}
+    StrCpy $2 "VBoxService.exe"
+  ${EndIf}
+
+  ${nsProcess::FindProcess} $2 $0
+  StrCmp $0 0 0 exit
+
+  ${nsProcess::KillProcess} $2 $0
+  Sleep "1000"           ; Wait a bit
+  Goto exe_stop_loop
+
+exit:
+
+  DetailPrint "Stopping VBoxService done."
+
+  Pop $3
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro StopVBoxService ""
+!insertmacro StopVBoxService "un."
+
+!macro StopVBoxTray un
+Function ${un}StopVBoxTray
+
+  Push $0   ; Temp results
+  Push $1   ; Safety counter
+
+  StrCpy $1 "0" ; Init counter
+  DetailPrint "Stopping VBoxTray ..."
+
+exe_stop:
+
+  IntCmp $1 10 exit      ; Only try this loop 10 times max
+  IntOp  $1 $1 + 1       ; Increment
+
+  ${nsProcess::FindProcess} "VBoxTray.exe" $0
+  StrCmp $0 0 0 exit
+
+  ${nsProcess::KillProcess} "VBoxTray.exe" $0
+  Sleep "1000"           ; Wait a bit
+  Goto exe_stop
+
+exit:
+
+  DetailPrint "Stopping VBoxTray done."
+
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro StopVBoxTray ""
+!insertmacro StopVBoxTray "un."
+
+!macro WriteRegBinR ROOT KEY NAME VALUE
+  WriteRegBin "${ROOT}" "${KEY}" "${NAME}" "${VALUE}"
+!macroend
+
+!macro AbortShutdown un
+Function ${un}AbortShutdown
+
+  Push $0
+
+  ; Try to abort the shutdown
+  nsExec::ExecToLog '"$g_strSystemDir\shutdown.exe" -a' $0
+
+  Pop $0
+
+FunctionEnd
+!macroend
+
+; Insert function as an installer and uninstaller function.
+!insertmacro AbortShutdown ""
+!insertmacro AbortShutdown "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsNT4.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsNT4.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsNT4.nsh	(revision 31634)
@@ -0,0 +1,258 @@
+
+Function NT_SetVideoResolution
+
+  ; Check for all required parameters
+  StrCmp $g_iScreenX "0" missingParms
+  StrCmp $g_iScreenY "0" missingParms
+  StrCmp $g_iScreenBpp "0" missingParms
+  Goto haveParms
+
+missingParms:
+
+  DetailPrint "Missing display parameters for NT, setting default (640x480, 8 BPP) ..."
+
+  StrCpy $g_iScreenX '640'   ; Default value
+  StrCpy $g_iScreenY '480'   ; Default value
+  StrCpy $g_iScreenBpp '8'   ; Default value
+
+  ; Write setting into registry to show the desktop applet on next boot
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\GraphicsDrivers\NewDisplay" "" ""
+
+haveParms:
+
+  DetailPrint "Setting display parameters for NT ($g_iScreenXx$g_iScreenY, $g_iScreenBpp BPP) ..."
+
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.BitsPerPel" $g_iScreenBpp
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.Flags" 0x00000000
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.VRefresh" 0x00000001
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.XPanning" 0x00000000
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.XResolution" $g_iScreenX
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.YPanning" 0x00000000
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\vboxvideo\Device0" "DefaultSettings.YResolution" $g_iScreenY
+
+FunctionEnd
+
+Function NT_SaveMouseDriverInfo
+
+  Push $0
+
+  ; !!! NOTE !!!
+  ; Due to some re-branding (see functions Uninstall_Sun, Uninstall_Innotek and
+  ; Uninstall_SunXVM) the installer *has* to transport the very first saved i8042prt
+  ; value to the current installer's "uninstall" directory in both mentioned
+  ; functions above, otherwise NT4 will be screwed because it then would store
+  ; "VBoxMouseNT.sys" as the original i8042prt driver which obviously isn't there
+  ; after uninstallation anymore.
+  ; !!! NOTE !!!
+
+  ; Save current mouse driver info so we may restore it on uninstallation
+  ; But first check if we already installed the additions otherwise we will
+  ; overwrite it with the VBoxMouseNT.sys
+  ReadRegStr $0 HKLM "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH}
+  StrCmp $0 "" 0 exists
+
+  DetailPrint "Saving mouse driver info ..."
+  ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath"
+  WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH} $0
+  Goto exit
+
+exists:
+
+  DetailPrint "Mouse driver info already saved."
+  Goto exit
+
+exit:
+
+!ifdef _DEBUG
+  DetailPrint "Mouse driver info: $0"
+!endif
+
+  Pop $0
+
+FunctionEnd
+
+Function NT_Prepare
+
+  ; Stop / kill VBoxService
+  Call StopVBoxService
+
+  ; Stop / kill VBoxTray
+  Call StopVBoxTray
+
+  ; Delete VBoxService from registry
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxService"
+
+  ; Delete old VBoxService.exe from install directory (replaced by VBoxTray.exe)
+  Delete /REBOOTOK "$INSTDIR\VBoxService.exe"
+
+FunctionEnd
+
+Function NT_CopyFiles
+
+  DetailPrint "Copying files..."
+
+  SetOutPath "$INSTDIR"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuestDrvInst.exe"
+  FILE "$%PATH_OUT%\bin\additions\RegCleanup.exe"
+
+  ; The files to install for NT 4, they go into the system directories
+  SetOutPath "$SYSDIR"
+  FILE "$%PATH_OUT%\bin\additions\VBoxDisp.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxTray.exe"
+  FILE "$%PATH_OUT%\bin\additions\VBoxHook.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxControl.exe"
+
+  ; VBoxService
+  FILE "$%PATH_OUT%\bin\additions\VBoxServiceNT.exe"
+
+  ; The drivers into the "drivers" directory
+  SetOutPath "$SYSDIR\drivers"
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouseNT.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuestNT.sys"
+  ;FILE "$%PATH_OUT%\bin\additions\VBoxSFNT.sys" ; Shared Folders not available on NT4!
+
+FunctionEnd
+
+Function NT_InstallFiles
+
+  DetailPrint "Installing Drivers..."
+
+  ; Install guest driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /createsvc "VBoxGuest" "VBoxGuest Support Driver" 1 1 "$SYSDIR\drivers\VBoxGuestNT.sys" "Base"'
+
+  ; Bugfix: Set "Start" to 1, otherwise, VBoxGuest won't start on boot-up!
+  ; Bugfix: Correct invalid "ImagePath" (\??\C:\WINNT\...)
+  WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\VBoxGuest" "Start" 1
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxGuest" "ImagePath" "System32\Drivers\VBoxGuestNT.sys"
+
+  ; Run VBoxTray when Windows NT starts
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxTray" '"$SYSDIR\VBoxTray.exe"'
+
+  ; Video driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxGuestDrvInst.exe" /i'
+  Pop $0                      ; Ret value
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+  DetailPrint "Installing VirtualBox service ..."
+
+  ; Create the VBoxService service
+  ; No need to stop/remove the service here! Do this only on uninstallation!
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /createsvc "VBoxService" "VirtualBox Guest Additions Service" 16 2 "system32\VBoxServiceNT.exe" "Base"'
+
+   ; Create the Shared Folders service ...
+  ;nsSCM::Install /NOUNLOAD "VBoxSF" "VirtualBox Shared Folders" 1 1 "$SYSDIR\drivers\VBoxSFNT.sys" "Network" "" "" ""
+  ;Pop $0                      ; Ret value
+
+!ifdef _DEBUG
+  ;DetailPrint "SCM::Install VBoxSFNT.sys: $0"
+!endif
+
+  ;IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+  ; ... and the link to the network provider
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "DeviceName" "\Device\VBoxMiniRdr"
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "Name" "VirtualBox Shared Folders"
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "ProviderPath" "$SYSDIR\VBoxMRXNP.dll"
+
+  ; Add the shared folders network provider
+  ;nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /addnetprovider VBoxSF'
+  ;Pop $0                      ; Ret value
+
+!ifdef _DEBUG
+  ;DetailPrint "VBoxDrvInst::AddProvider VBoxSF: $0"
+!endif
+
+  ;IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+  Goto done
+
+error:
+  Abort "ERROR: Could not install files for Windows NT! Installation aborted."
+
+done:
+
+FunctionEnd
+
+Function NT_Main
+
+  SetOutPath "$INSTDIR"
+
+  Call NT_Prepare
+  Call NT_CopyFiles
+
+  ; This removes the flag "new display driver installed on the next bootup
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" "VBoxGuestInst" '"$INSTDIR\RegCleanup.exe"'
+
+  Call NT_SaveMouseDriverInfo
+  Call NT_InstallFiles
+  Call NT_SetVideoResolution
+
+  ; Write mouse driver name to registry overwriting the default name
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" "System32\DRIVERS\VBoxMouseNT.sys"
+
+FunctionEnd
+
+!macro NT_UninstallInstDir un
+Function ${un}NT_UninstallInstDir
+
+  ; Delete remaining files
+  Delete /REBOOTOK "$INSTDIR\VBoxGuestDrvInst.exe"
+  Delete /REBOOTOK "$INSTDIR\RegCleanup.exe"
+
+FunctionEnd
+!macroend
+!insertmacro NT_UninstallInstDir ""
+!insertmacro NT_UninstallInstDir "un."
+
+!macro NT_Uninstall un
+Function ${un}NT_Uninstall
+
+  Push $0
+
+  ; Remove the guest driver service
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxGuest'
+  Delete /REBOOTOK "$SYSDIR\drivers\VBoxGuestNT.sys"
+
+  ; Delete the VBoxService service
+  Call ${un}StopVBoxService
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxService'
+  Pop $0    ; Ret value
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxService"
+  Delete /REBOOTOK "$SYSDIR\VBoxServiceNT.exe"
+
+  ; Delete the VBoxTray app
+  Call ${un}StopVBoxTray
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxTray"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" "VBoxTrayDel" "$SYSDIR\cmd.exe /c del /F /Q $SYSDIR\VBoxTray.exe"
+  Delete /REBOOTOK "$SYSDIR\VBoxTray.exe"    ; If it can't be removed cause it's running, try next boot with "RunOnce" key above!
+  Delete /REBOOTOK "$SYSDIR\VBoxHook.dll"
+
+  ; Delete the VBoxControl utility
+  Delete /REBOOTOK "$SYSDIR\VBoxControl.exe"
+
+  ; Delete the VBoxVideo service
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxVideo'
+
+  ; Delete the VBox video driver files
+  Delete /REBOOTOK "$SYSDIR\drivers\VBoxVideo.sys"
+  Delete /REBOOTOK "$SYSDIR\VBoxDisp.dll"
+
+  ; Get original mouse driver info and restore it
+  ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH}
+  ; If we still got our driver stored in $0 then this will *never* work, so
+  ; warn the user and set it to the default driver to not screw up NT4 here
+  ${If} $0 == "System32\DRIVERS\VBoxMouseNT.sys"
+    WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" "System32\DRIVERS\i8042prt.sys"
+    DetailPrint "Old mouse driver is set to VBoxMouseNT.sys, defaulting to i8042prt.sys ..."
+  ${Else}
+    WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" $0
+  ${EndIf}
+  Delete /REBOOTOK "$SYSDIR\drivers\VBoxMouseNT.sys"
+
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro NT_Uninstall ""
+!insertmacro NT_Uninstall "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstall.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstall.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstall.nsh	(revision 31634)
@@ -0,0 +1,209 @@
+
+; @todo Replace this crappy stuff with a "VBoxDrvInst /delnetprovider".
+!macro RemoveFromProvider un
+Function ${un}RemoveFromProvider
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  Push $5
+  Push $6
+
+  ReadRegStr $1 HKLM "$R0" "ProviderOrder"
+  StrCpy $5 $1 1 -1 # copy last char
+  StrCmp $5 "," +2 # if last char != ,
+  StrCpy $1 "$1," # append ,
+  Push $1
+  Push "$0,"
+  Call ${un}StrStr ; Find `$0,` in $1
+  Pop $2 ; pos of our dir
+  StrCmp $2 "" unRemoveFromPath_done
+  ; else, it is in path
+  # $0 - path to add
+  # $1 - path var
+  StrLen $3 "$0,"
+  StrLen $4 $2
+  StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
+  StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
+  StrCpy $3 $5$6
+
+  StrCpy $5 $3 1 -1 # copy last char
+  StrCmp $5 "," 0 +2 # if last char == ,
+  StrCpy $3 $3 -1 # remove last char
+
+  WriteRegStr HKLM "$R0" "ProviderOrder" $3
+
+unRemoveFromPath_done:
+  Pop $6
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Pop $0
+FunctionEnd
+!macroend
+!insertmacro RemoveFromProvider ""
+!insertmacro RemoveFromProvider "un."
+
+!macro RemoveProvider un
+Function ${un}RemoveProvider
+  Push $R0
+  StrCpy $R0 "VBoxSF"
+  Push $R0
+  StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder"
+  Call ${un}RemoveFromProvider
+  StrCpy $R0 "VBoxSF"
+  Push $R0
+  StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order"
+  Call ${un}RemoveFromProvider
+  Pop $R0
+FunctionEnd
+!macroend
+!insertmacro RemoveProvider ""
+!insertmacro RemoveProvider "un."
+
+!macro UninstallCommon un
+Function ${un}UninstallCommon
+
+  Delete /REBOOTOK "$INSTDIR\install.log"
+  Delete /REBOOTOK "$INSTDIR\uninst.exe"
+  Delete /REBOOTOK "$INSTDIR\${PRODUCT_NAME}.url"
+
+  ; Remove common files
+  Delete /REBOOTOK "$INSTDIR\VBoxDrvInst.exe"
+
+  Delete /REBOOTOK "$INSTDIR\VBoxVideo.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  Delete /REBOOTOK "$INSTDIR\VBoxVideo.cat"
+!endif
+
+  Delete /REBOOTOK "$INSTDIR\VBoxGINA.dll"
+  Delete /REBOOTOK "$INSTDIR\iexplore.ico"
+
+  ; Delete registry keys
+  DeleteRegKey /ifempty HKLM "${PRODUCT_INSTALL_KEY}"
+  DeleteRegKey /ifempty HKLM "${VENDOR_ROOT_KEY}"
+
+  ; Delete desktop & start menu entries
+  Delete "$DESKTOP\${PRODUCT_NAME} Guest Additions.lnk"
+  Delete "$SMPROGRAMS\${PRODUCT_NAME} Guest Additions\Uninstall.lnk"
+  Delete "$SMPROGRAMS\${PRODUCT_NAME} Guest Additions\Website.lnk"
+  RMDIR "$SMPROGRAMS\${PRODUCT_NAME} Guest Additions"
+
+  ; Delete Guest Additions directory (only if completely empty)
+  RMDir /REBOOTOK "$INSTDIR"
+
+  ; Delete vendor installation directory (only if completely empty)
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  RMDir /REBOOTOK "$PROGRAMFILES32\$%VBOX_VENDOR_SHORT%"
+!else   ; 64-bit
+  RMDir /REBOOTOK "$PROGRAMFILES64\$%VBOX_VENDOR_SHORT%"
+!endif
+
+  ; Remove registry entries
+  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+
+FunctionEnd
+!macroend
+!insertmacro UninstallCommon ""
+!insertmacro UninstallCommon "un."
+
+!macro Uninstall un
+Function ${un}Uninstall
+
+  DetailPrint "Uninstalling system files ..."
+  DetailPrint "Handled Windows version: $g_strWinVersion"
+  DetailPrint "System Directory: $g_strSystemDir"
+
+  ; Which OS are we using?
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  StrCmp $g_strWinVersion "nt4" nt4
+!endif
+  StrCmp $g_strWinVersion "2k" w2k
+  StrCmp $g_strWinVersion "vista" vista
+
+  Goto notsupported
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+nt4:
+
+  Call ${un}NT_Uninstall
+  goto common
+!endif
+
+w2k:
+
+  Call ${un}W2K_Uninstall
+  goto common
+
+vista:
+
+  Call ${un}W2K_Uninstall
+  Call ${un}Vista_Uninstall
+  goto common
+
+notsupported:
+
+  MessageBox MB_ICONSTOP $(VBOX_PLATFORM_UNSUPPORTED) /SD IDOK
+  Goto exit
+
+common:
+
+exit:
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall ""
+!insertmacro Uninstall "un."
+
+!macro UninstallInstDir un
+Function ${un}UninstallInstDir
+
+  DetailPrint "Uninstalling directory ..."
+  DetailPrint "Handled Windows version: $g_strWinVersion"
+  DetailPrint "System Directory: $g_strSystemDir"
+
+  ; Which OS are we using?
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  StrCmp $g_strWinVersion "nt4" nt4
+!endif
+  StrCmp $g_strWinVersion "2k" w2k
+  StrCmp $g_strWinVersion "vista" vista
+
+  Goto notsupported
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+nt4:
+
+  Call ${un}NT_UninstallInstDir
+  goto common
+!endif
+
+w2k:
+
+  Call ${un}W2K_UninstallInstDir
+  goto common
+
+vista:
+
+  Call ${un}W2K_UninstallInstDir
+  Call ${un}Vista_UninstallInstDir
+  goto common
+
+notsupported:
+
+  MessageBox MB_ICONSTOP $(VBOX_PLATFORM_UNSUPPORTED) /SD IDOK
+  Goto exit
+
+common:
+
+  Call ${un}UninstallCommon
+
+exit:
+
+FunctionEnd
+!macroend
+!insertmacro UninstallInstDir ""
+!insertmacro UninstallInstDir "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstallOld.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstallOld.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsUninstallOld.nsh	(revision 31634)
@@ -0,0 +1,345 @@
+
+!macro Uninstall_RunExtUnInstaller un
+Function ${un}Uninstall_RunExtUnInstaller
+
+  Pop  $0
+  Push $1
+  Push $2
+
+  ; Try to run the current uninstaller
+  StrCpy $1 "$0\uninst.exe"
+  IfFileExists "$1" run 0
+    MessageBox MB_OK "VirtualBox Guest Additions uninstaller not found! Path = $1" /SD IDOK
+    StrCpy $0 1 ; Tell the caller that we were not able to start the uninstaller
+    Goto exit
+
+run:
+
+  ; Always try to run in silent mode
+  Goto run_uninst_silent
+
+run_uninst_silent:
+
+  ExecWait '"$1" /S _?=$0' $2 ; Silently run uninst.exe in it's dir and don't copy it to a temp. location
+  Goto handle_result
+
+run_uninst:
+
+  ExecWait '"$1" _?=$0' $2 ; Run uninst.exe in it's dir and don't copy it to a temp. location
+  Goto handle_result
+
+handle_result:
+
+  ; Note that here a race might going on after the user clicked on
+  ; "Reboot now" in the installer ran above and this installer cleaning
+  ; up aftwards.
+
+  ; ... so try to abort the current reboot / shutdown caused by the installer ran before
+  Call ${un}AbortShutdown
+
+;!ifdef _DEBUG
+;      MessageBox MB_OK 'Debug Message: Uninstaller was called, result is: $2' /SD IDOK
+;!endif
+
+  ${Switch} $2 ; Check exit codes
+    ${Case} 1  ; Aborted by user
+      StrCpy $0 1 ; Tell the caller that we were aborted by the user
+      ${Break}
+    ${Case} 2  ; Aborted by script (that might be okay)
+      StrCpy $0 0 ; All went well
+      ${Break}
+    ${Default} ; Normal exixt
+      StrCpy $0 0 ; All went well
+      ${Break}
+  ${EndSwitch}
+  Goto exit
+
+exit:
+
+  Pop $2
+  Pop $1
+  Push $0
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall_RunExtUnInstaller ""
+!insertmacro Uninstall_RunExtUnInstaller "un."
+
+!macro Uninstall_WipeInstallationDirectory un
+Function ${un}Uninstall_WipeInstallationDirectory
+
+  Pop  $0
+  Push $1
+  Push $2
+
+  ; Do some basic sanity checks for not screwing up too fatal ...
+  DetailPrint "Removing old installation directory ($0) ..."
+  ${If} $0    != $PROGRAMFILES
+  ${AndIf} $0 != $PROGRAMFILES32
+  ${AndIf} $0 != $PROGRAMFILES64
+  ${AndIf} $0 != $COMMONFILES32
+  ${AndIf} $0 != $COMMONFILES64
+  ${AndIf} $0 != $WINDIR
+  ${AndIf} $0 != $SYSDIR
+    DetailPrint "Wiping ($0) ..."
+    Goto wipe
+  ${EndIf}
+  Goto wipe_abort
+
+wipe:
+
+  RMDir /r /REBOOTOK "$0"
+  StrCpy $0 0 ; All went well
+  Goto exit
+
+wipe_abort:
+
+  DetailPrint "Won't remove directory ($0)!"
+  StrCpy $0 1 ; Signal some failure
+  Goto exit
+
+exit:
+
+  Pop $2
+  Pop $1
+  Push $0
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall_WipeInstallationDirectory ""
+!insertmacro Uninstall_WipeInstallationDirectory "un."
+
+; This function cleans up an old Sun installation
+!macro Uninstall_Sun un
+Function ${un}Uninstall_Sun
+
+  Push $0
+  Push $1
+  Push $2
+
+  ; Get current installation path
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sun VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" exit
+
+  ; Extract path
+  Push "$0"       ; String
+  Push "\"        ; SubString
+  Push "<"        ; SearchDirection
+  Push "<"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $1          ; $1 only contains the full path
+
+  StrCmp $1 "" exit
+
+  ; Save current i8042prt info to new uninstall registry path
+  ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Sun VirtualBox Guest Additions" ${ORG_MOUSE_PATH}
+  WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH} $0
+
+  ; Try to wipe current installation directory
+  Push $1 ; Push uninstaller path to stack
+  Call ${un}Uninstall_WipeInstallationDirectory
+  Pop $2  ; Get uninstaller exit code from stack
+  StrCmp $2 0 common exit ; Only process common part if exit code is 0, otherwise exit
+
+common:
+
+  ; Make sure everything is cleaned up in case the old uninstaller did forget something
+  DeleteRegKey HKLM "SOFTWARE\Sun\VirtualBox Guest Additions"
+  DeleteRegKey /ifempty HKLM "SOFTWARE\Sun"
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Sun VirtualBox Guest Additions"
+  Delete /REBOOTOK "$1\netamd.inf"
+  Delete /REBOOTOK "$1\pcntpci5.cat"
+  Delete /REBOOTOK "$1\PCNTPCI5.sys"
+
+  ; Try to remove old installation directory if empty
+  RMDir /r /REBOOTOK "$SMPROGRAMS\Sun VirtualBox Guest Additions"
+  RMDir /REBOOTOK "$1"
+
+  ; Get original mouse driver info and restore it
+  ;ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH}
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" $0
+  ;Delete "$SYSDIR\drivers\VBoxMouseNT.sys"
+
+  ; Delete vendor installation directory (only if completely empty)
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  RMDir /REBOOTOK "$PROGRAMFILES32\Sun"
+!else   ; 64-bit
+  RMDir /REBOOTOK "$PROGRAMFILES64\Sun"
+!endif
+
+exit:
+
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall_Sun ""
+!insertmacro Uninstall_Sun "un."
+
+; This function cleans up an old xVM Sun installation
+!macro Uninstall_SunXVM un
+Function ${un}Uninstall_SunXVM
+
+  Push $0
+  Push $1
+  Push $2
+
+  ; Get current installation path
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sun xVM VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" exit
+
+  ; Extract path
+  Push "$0"       ; String
+  Push "\"        ; SubString
+  Push "<"        ; SearchDirection
+  Push "<"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $1          ; $1 only contains the full path
+
+  StrCmp $1 "" exit
+
+  ; Save current i8042prt info to new uninstall registry path
+  ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Sun xVM VirtualBox Guest Additions" ${ORG_MOUSE_PATH}
+  WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH} $0
+
+  ; Try to wipe current installation directory
+  Push $1 ; Push uninstaller path to stack
+  Call ${un}Uninstall_WipeInstallationDirectory
+  Pop $2  ; Get uninstaller exit code from stack
+  StrCmp $2 0 common exit ; Only process common part if exit code is 0, otherwise exit
+
+common:
+
+  ; Make sure everything is cleaned up in case the old uninstaller did forget something
+  DeleteRegKey HKLM "SOFTWARE\Sun\xVM VirtualBox Guest Additions"
+  DeleteRegKey /ifempty HKLM "SOFTWARE\Sun"
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Sun xVM VirtualBox Guest Additions"
+  Delete /REBOOTOK "$1\netamd.inf"
+  Delete /REBOOTOK "$1\pcntpci5.cat"
+  Delete /REBOOTOK "$1\PCNTPCI5.sys"
+
+  ; Try to remove old installation directory if empty
+  RMDir /r /REBOOTOK "$SMPROGRAMS\Sun xVM VirtualBox Guest Additions"
+  RMDir /REBOOTOK "$1"
+
+  ; Delete vendor installation directory (only if completely empty)
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  RMDir /REBOOTOK "$PROGRAMFILES32\Sun"
+!else   ; 64-bit
+  RMDir /REBOOTOK "$PROGRAMFILES64\Sun"
+!endif
+
+  ; Get original mouse driver info and restore it
+  ;ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH}
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" $0
+  ;Delete "$SYSDIR\drivers\VBoxMouseNT.sys"
+
+exit:
+
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall_SunXVM ""
+!insertmacro Uninstall_SunXVM "un."
+
+; This function cleans up an old innotek installation.
+!macro Uninstall_Innotek un
+Function ${un}Uninstall_Innotek
+
+  Push $0
+  Push $1
+  Push $2
+
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\innotek VirtualBox Guest Additions" "UninstallString"
+  StrCmp $0 "" exit
+
+  ; Extract path
+  Push "$0"       ; String
+  Push "\"        ; SubString
+  Push "<"        ; SearchDirection
+  Push "<"        ; StrInclusionDirection
+  Push "0"        ; IncludeSubString
+  Push "0"        ; Loops
+  Push "0"        ; CaseSensitive
+  Call ${un}StrStrAdv
+  Pop $1          ; $1 only contains the full path
+
+  StrCmp $1 "" exit
+
+  ; Save current i8042prt info to new uninstall registry path
+  ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\innotek VirtualBox Guest Additions" ${ORG_MOUSE_PATH}
+  WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH} $0
+
+  ; Try to wipe current installation directory
+  Push $1 ; Push uninstaller path to stack
+  Call ${un}Uninstall_WipeInstallationDirectory
+  Pop $2  ; Get uninstaller exit code from stack
+  StrCmp $2 0 common exit ; Only process common part if exit code is 0, otherwise exit
+
+common:
+
+  ; Remove left over files which were not entirely catched by the formerly running
+  ; uninstaller
+  DeleteRegKey HKLM "SOFTWARE\innotek\VirtualBox Guest Additions"
+  DeleteRegKey HKLM "SOFTWARE\innotek"
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\innotek VirtualBox Guest Additions"
+  Delete /REBOOTOK "$1\VBoxGuestDrvInst.exe"
+  Delete /REBOOTOK "$1\VBoxMouseInst.exe"
+  Delete /REBOOTOK "$1\VBoxSFDrvInst.exe"
+  Delete /REBOOTOK "$1\RegCleanup.exe"
+  Delete /REBOOTOK "$1\VBoxService.exe"
+  Delete /REBOOTOK "$1\VBoxMouseInst.exe"
+  Delete /REBOOTOK "$1\innotek VirtualBox Guest Additions.url"
+  Delete /REBOOTOK "$1\uninst.exe"
+  Delete /REBOOTOK "$1\iexplore.ico"
+  Delete /REBOOTOK "$1\install.log"
+  Delete /REBOOTOK "$1\VBCoInst.dll"
+  Delete /REBOOTOK "$1\VBoxControl.exe"
+  Delete /REBOOTOK "$1\VBoxDisp.dll"
+  Delete /REBOOTOK "$1\VBoxGINA.dll"
+  Delete /REBOOTOK "$1\VBoxGuest.cat"
+  Delete /REBOOTOK "$1\VBoxGuest.inf"
+  Delete /REBOOTOK "$1\VBoxGuest.sys"
+  Delete /REBOOTOK "$1\VBoxMouse.inf"
+  Delete /REBOOTOK "$1\VBoxMouse.sys"
+  Delete /REBOOTOK "$1\VBoxVideo.cat"
+  Delete /REBOOTOK "$1\VBoxVideo.inf"
+  Delete /REBOOTOK "$1\VBoxVideo.sys"
+
+  ; Try to remove old installation directory if empty
+  RMDir /r /REBOOTOK "$SMPROGRAMS\innotek VirtualBox Guest Additions"
+  RMDir /REBOOTOK "$1"
+
+  ; Delete vendor installation directory (only if completely empty)
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  RMDir /REBOOTOK "$PROGRAMFILES32\innotek"
+!else   ; 64-bit
+  RMDir /REBOOTOK "$PROGRAMFILES64\innotek"
+!endif
+
+  ; Get original mouse driver info and restore it
+  ;ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" ${ORG_MOUSE_PATH}
+  ;WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\i8042prt" "ImagePath" $0
+  ;Delete "$SYSDIR\drivers\VBoxMouseNT.sys"
+
+exit:
+
+  Pop $2
+  Pop $1
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro Uninstall_Innotek ""
+!insertmacro Uninstall_Innotek "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsVista.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsVista.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsVista.nsh	(revision 31634)
@@ -0,0 +1,89 @@
+
+Function Vista_CopyFiles
+
+  SetOutPath "$INSTDIR"
+  SetOverwrite on
+
+  ; The files are for Vista only, they go into the application directory
+
+  ; VBoxNET drivers are not tested yet - commented out until officially supported and released
+  ;FILE "$%PATH_OUT%\bin\additions\VBoxNET.inf"
+  ;FILE "$%PATH_OUT%\bin\additions\VBoxNET.sys"
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  ; AMD PCNet network driver
+  FILE "..\Network\AMD\netamd.inf"
+  FILE "..\Network\AMD\pcntpci5.cat"
+  FILE "..\Network\AMD\PCNTPCI5.sys"
+!endif
+
+FunctionEnd
+
+Function Vista_InstallFiles
+
+  DetailPrint "Installing Drivers for Vista / Windows 7 ..."
+
+  SetOutPath "$INSTDIR"
+
+  ; VBoxNET drivers are not tested yet - commented out until officially supported and released
+  ;nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /i "PCI\VEN_1022&DEV_2000&SUBSYS_20001022&REV_40" "$INSTDIR\VBoxNET.inf" "Net"'
+  ;Pop $0                      ; Ret value
+  ;IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+  ;Goto done
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  ; AMD PCnet drivers
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /i "PCI\VEN_1022&DEV_2000&SUBSYS_20001022&REV_40" "$INSTDIR\netamd.inf" "Net"'
+  Pop $0                      ; Ret value
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+!endif
+
+  Goto done
+
+error:
+  Abort "ERROR: Could not install files for Vista / Windows 7! Installation aborted."
+
+done:
+
+FunctionEnd
+
+Function Vista_Main
+
+  Call Vista_CopyFiles
+  Call Vista_InstallFiles
+
+FunctionEnd
+
+!macro Vista_UninstallInstDir un
+Function ${un}Vista_UninstallInstDir
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  Delete /REBOOTOK "$INSTDIR\netamd.inf"
+  Delete /REBOOTOK "$INSTDIR\pcntpci5.cat"
+  Delete /REBOOTOK "$INSTDIR\PCNTPCI5.sys"
+!endif
+
+FunctionEnd
+!macroend
+!insertmacro Vista_UninstallInstDir ""
+!insertmacro Vista_UninstallInstDir "un."
+
+!macro Vista_Uninstall un
+Function ${un}Vista_Uninstall
+
+   ; Remove credential provider
+   DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}"
+   DeleteRegKey HKCR "CLSID\{275D3BCC-22BB-4948-A7F6-3A3054EBA92B}"
+   Delete /REBOOTOK "$g_strSystemDir\VBoxCredProv.dll"
+
+!if $%BUILD_TARGET_ARCH% == "x86"       ; 32-bit
+  ; Remove network card driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /u "PCI\VEN_1022&DEV_2000&SUBSYS_20001022&REV_40"'
+  Pop $0    ; Ret value
+  ; @todo Add error handling here!
+!endif
+
+FunctionEnd
+!macroend
+!insertmacro Vista_Uninstall ""
+!insertmacro Vista_Uninstall "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsW2KXP.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsW2KXP.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsW2KXP.nsh	(revision 31634)
@@ -0,0 +1,562 @@
+
+Function W2K_SetVideoResolution
+
+  ; NSIS only supports global vars, even in functions -- great
+  Var /GLOBAL i
+  Var /GLOBAL tmp
+  Var /GLOBAL tmppath
+  Var /GLOBAL win_ver
+  Var /GLOBAL dev_id
+  Var /GLOBAL dev_desc
+
+  ; Check for all required parameters
+  StrCmp $g_iScreenX "0" exit
+  StrCmp $g_iScreenY "0" exit
+  StrCmp $g_iScreenBpp "0" exit
+
+  Call GetWindowsVersion
+  Pop $win_ver ; Now contains Windows version
+
+  DetailPrint "Setting display parameters ($g_iScreenXx$g_iScreenY, $g_iScreenBpp BPP) ..."
+
+  ; Enumerate all video devices (up to 32 at the moment, use key "MaxObjectNumber" key later)
+  ${For} $i 0 32
+
+    ReadRegStr $tmp HKLM "HARDWARE\DEVICEMAP\VIDEO" "\Device\Video$i"
+    StrCmp $tmp "" dev_not_found
+
+    ; Extract path to video settings
+    ; Ex: \Registry\Machine\System\CurrentControlSet\Control\Video\{28B74D2B-F0A9-48E0-8028-D76F6BB1AE65}\0000
+    ; Or: \Registry\Machine\System\CurrentControlSet\Control\Video\vboxvideo\Device0
+    ; Result: Machine\System\CurrentControlSet\Control\Video\{28B74D2B-F0A9-48E0-8028-D76F6BB1AE65}\0000
+    Push "$tmp"     ; String
+    Push "\"        ; SubString
+    Push ">"        ; SearchDirection
+    Push ">"        ; StrInclusionDirection
+    Push "0"        ; IncludeSubString
+    Push "2"        ; Loops
+    Push "0"        ; CaseSensitive
+    Call StrStrAdv
+    Pop $tmppath    ; $1 only contains the full path
+    StrCmp $tmppath "" dev_not_found
+
+    ; Get device description
+    ReadRegStr $dev_desc HKLM "$tmppath" "Device Description"
+!ifdef _DEBUG
+    DetailPrint "Registry path: $tmppath"
+    DetailPrint "Registry path to device name: $temp"
+!endif
+    DetailPrint "Detected video device: $dev_desc"
+
+    ${If} $dev_desc == "VirtualBox Graphics Adapter"
+      DetailPrint "VirtualBox video device found!"
+      Goto dev_found
+    ${EndIf}
+  ${Next}
+  Goto dev_not_found
+
+dev_found:
+
+  ; If we're on Windows 2000, skip the ID detection ...
+  StrCmp $win_ver "2000" change_res
+  Goto dev_found_detect_id
+
+dev_found_detect_id:
+
+  StrCpy $i 0 ; Start at index 0
+  DetailPrint "Detecting device ID ..."
+
+dev_found_detect_id_loop:
+
+  ; Resolve real path to hardware instance "{GUID}"
+  EnumRegKey $dev_id HKLM "SYSTEM\CurrentControlSet\Control\Video" $i
+  StrCmp $dev_id "" dev_not_found ; No more entries? Jump out
+!ifdef _DEBUG
+  DetailPrint "Got device ID: $dev_id"
+!endif
+  ReadRegStr $dev_desc HKLM "SYSTEM\CurrentControlSet\Control\Video\$dev_id\0000" "Device Description" ; Try to read device name
+  ${If} $dev_desc == "VirtualBox Graphics Adapter"
+    DetailPrint "Device ID of $dev_desc: $dev_id"
+    Goto change_res
+  ${EndIf}
+
+  IntOp $i $i + 1 ; Increment index
+  goto dev_found_detect_id_loop
+
+dev_not_found:
+
+  DetailPrint "No VirtualBox video device (yet) detected! No custom mode set."
+  Goto exit
+
+change_res:
+
+!ifdef _DEBUG
+  DetailPrint "Device description: $dev_desc"
+  DetailPrint "Device ID: $dev_id"
+!endif
+
+  Var /GLOBAL reg_path_device
+  Var /GLOBAL reg_path_monitor
+
+  DetailPrint "Custom mode set: Platform is '$win_ver'."
+  ${If} $win_ver == "2000"
+  ${OrIf} $win_ver == "Vista"
+    StrCpy $reg_path_device "SYSTEM\CurrentControlSet\SERVICES\VBoxVideo\Device0"
+    StrCpy $reg_path_monitor "SYSTEM\CurrentControlSet\SERVICES\VBoxVideo\Device0\Mon00000001"
+  ${ElseIf} $win_ver == "XP"
+  ${OrIf} $win_ver == "7"
+    StrCpy $reg_path_device "SYSTEM\CurrentControlSet\Control\Video\$dev_id\0000"
+    StrCpy $reg_path_monitor "SYSTEM\CurrentControlSet\Control\VIDEO\$dev_id\0000\Mon00000001"
+  ${Else}
+    DetailPrint "Custom mode set: Platform '$win_ver' not supported yet."
+    Goto exit
+  ${EndIf}
+
+  ; Write the new value in the adapter config (VBoxVideo.sys) using hex values in binary format
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /registry write HKLM $reg_path_device CustomXRes REG_BIN $g_iScreenX DWORD'
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /registry write HKLM $reg_path_device CustomYRes REG_BIN $g_iScreenY DWORD'
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /registry write HKLM $reg_path_device CustomBPP REG_BIN $g_iScreenBpp DWORD'
+
+  ; ... and tell Windows to use that mode on next start!
+  WriteRegDWORD HKCC $reg_path_device "DefaultSettings.XResolution" "$g_iScreenX"
+  WriteRegDWORD HKCC $reg_path_device "DefaultSettings.YResolution" "$g_iScreenY"
+  WriteRegDWORD HKCC $reg_path_device "DefaultSettings.BitsPerPixel" "$g_iScreenBpp"
+
+  WriteRegDWORD HKCC $reg_path_monitor "DefaultSettings.XResolution" "$g_iScreenX"
+  WriteRegDWORD HKCC $reg_path_monitor "DefaultSettings.YResolution" "$g_iScreenY"
+  WriteRegDWORD HKCC $reg_path_monitor "DefaultSettings.BitsPerPixel" "$g_iScreenBpp"
+
+  DetailPrint "Custom mode set to $g_iScreenXx$g_iScreenY, $g_iScreenBpp BPP on next restart."
+
+exit:
+
+FunctionEnd
+
+Function W2K_Prepare
+
+  ; Stop / kill VBoxService
+  Call StopVBoxService
+
+  ; Stop / kill VBoxTray
+  Call StopVBoxTray
+
+  ; Delete VBoxService from registry
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxService"
+
+  ; Delete old VBoxService.exe from install directory (replaced by VBoxTray.exe)
+  Delete /REBOOTOK "$INSTDIR\VBoxService.exe"
+
+FunctionEnd
+
+Function W2K_CopyFiles
+
+  SetOutPath "$INSTDIR"
+
+  ; Video driver
+  FILE "$%PATH_OUT%\bin\additions\VBoxVideo.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxDisp.dll"
+
+  ; Mouse driver
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxMouse.cat"
+!endif
+
+  ; Guest driver
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.sys"
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.inf"
+!ifdef VBOX_SIGN_ADDITIONS
+  FILE "$%PATH_OUT%\bin\additions\VBoxGuest.cat"
+!endif
+
+  ; Guest driver files
+  FILE "$%PATH_OUT%\bin\additions\VBCoInst.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxTray.exe"
+  FILE "$%PATH_OUT%\bin\additions\VBoxControl.exe"	; Not used by W2K and up, but required by the .INF file
+
+  ; WHQL fake
+!ifdef WHQL_FAKE
+  FILE "$%PATH_OUT%\bin\additions\VBoxWHQLFake.exe"
+!endif
+
+  SetOutPath $g_strSystemDir
+
+  ; VBoxService
+  FILE "$%PATH_OUT%\bin\additions\VBoxService.exe" ; Only used by W2K and up (for Shared Folders at the moment)
+
+!if $%VBOX_WITH_CROGL% == "1"
+  ; crOpenGL
+  SetOutPath $g_strSystemDir
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLarrayspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLcrutil.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLerrorspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLpackspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLpassthroughspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGLfeedbackspu.dll"
+  FILE "$%PATH_OUT%\bin\additions\VBoxOGL.dll"
+
+  !if $%BUILD_TARGET_ARCH% == "amd64"
+    ; Only 64-bit installer: Also copy 32-bit DLLs on 64-bit target arch in
+    ; Wow64 node (32-bit sub system).
+    ${EnableX64FSRedirection}
+    SetOutPath $SYSDIR
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLarrayspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLcrutil.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLerrorspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLpackspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLpassthroughspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGLfeedbackspu.dll"
+    FILE "$%VBOX_PATH_ADDITIONS_WIN_X86%\VBoxOGL.dll"
+    ${DisableX64FSRedirection}
+  !endif
+
+!endif ; VBOX_WITH_CROGL
+
+FunctionEnd
+
+!ifdef WHQL_FAKE
+
+Function W2K_WHQLFakeOn
+
+  StrCmp $g_bFakeWHQL "true" do
+  Goto exit
+
+do:
+
+  DetailPrint "Turning off WHQL protection..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxWHQLFake.exe" "ignore"'
+
+exit:
+
+FunctionEnd
+
+Function W2K_WHQLFakeOff
+
+  StrCmp $g_bFakeWHQL "true" do
+  Goto exit
+
+do:
+
+  DetailPrint "Turning back on WHQL protection..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxWHQLFake.exe" "warn"'
+
+exit:
+
+FunctionEnd
+
+!endif
+
+Function W2K_InstallFiles
+
+  ; The Shared Folder IFS goes to the system directory
+  FILE /oname=$g_strSystemDir\drivers\VBoxSF.sys "$%PATH_OUT%\bin\additions\VBoxSF.sys"
+  !insertmacro ReplaceDLL "$%PATH_OUT%\bin\additions\VBoxMRXNP.dll" "$g_strSystemDir\VBoxMRXNP.dll" "$INSTDIR"
+  AccessControl::GrantOnFile "$g_strSystemDir\VBoxMRXNP.dll" "(BU)" "GenericRead"
+
+  ; The VBoxTray hook DLL also goes to the system directory; it might be locked
+  !insertmacro ReplaceDLL "$%PATH_OUT%\bin\additions\VBoxHook.dll" "$g_strSystemDir\VBoxHook.dll" "$INSTDIR"
+  AccessControl::GrantOnFile "$g_strSystemDir\VBoxHook.dll" "(BU)" "GenericRead"
+
+  DetailPrint "Installing Drivers..."
+
+drv_video:
+
+  StrCmp $g_bNoVideoDrv "true" drv_guest
+  SetOutPath "$INSTDIR"
+  DetailPrint "Installing video driver ..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /i "PCI\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00" "$INSTDIR\VBoxVideo.inf" "Display"'
+  Pop $0                      ; Ret value
+  LogText "Video driver result: $0"
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+drv_guest:
+
+  StrCmp $g_bNoGuestDrv "true" drv_mouse
+  DetailPrint "Installing guest driver ..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /i "PCI\VEN_80EE&DEV_CAFE&SUBSYS_00000000&REV_00" "$INSTDIR\VBoxGuest.inf" "Media"'
+  Pop $0                      ; Ret value
+  LogText "Guest driver result: $0"
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+drv_mouse:
+
+  StrCmp $g_bNoMouseDrv "true" vbox_service
+  DetailPrint "Installing mouse filter ..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /inf "$INSTDIR\VBoxMouse.inf"'
+  Pop $0                      ; Ret value
+  LogText "Mouse driver returned: $0"
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+vbox_service:
+
+  DetailPrint "Installing VirtualBox service ..."
+
+  ; Create the VBoxService service
+  ; No need to stop/remove the service here! Do this only on uninstallation!
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /createsvc "VBoxService" "VirtualBox Guest Additions Service" 16 2 "system32\VBoxService.exe" "Base"'
+  Pop $0                      ; Ret value
+  LogText "VBoxService returned: $0"
+
+  ; Set service description
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxService" "Description" "Manages VM runtime information, time synchronization, remote sysprep execution and miscellaneous utilities for guest operating systems."
+
+sf:
+
+  DetailPrint "Installing Shared Folders service ..."
+
+  ; Create the Shared Folders service ...
+  ; No need to stop/remove the service here! Do this only on uninstallation!
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /createsvc "VBoxSF" "VirtualBox Shared Folders" 2 1 "system32\drivers\VBoxSF.sys" "NetworkProvider"'
+
+  ; ... and the link to the network provider
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "DeviceName" "\Device\VBoxMiniRdr"
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "Name" "VirtualBox Shared Folders"
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\VBoxSF\NetworkProvider" "ProviderPath" "$SYSDIR\VBoxMRXNP.dll"
+
+  ; Add default network providers (if not present or corrupted)
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /addnetprovider WebClient'
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /addnetprovider LanmanWorkstation'
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /addnetprovider RDPNP'
+
+  ; Add the shared folders network provider
+  DetailPrint "Adding network provider (Order = $g_iSfOrder) ..."
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /addnetprovider VBoxSF $g_iSfOrder'
+  Pop $0                      ; Ret value
+  IntCmp $0 0 +1 error error  ; Check ret value (0=OK, 1=Error)
+
+!if $%VBOX_WITH_CROGL% == "1"
+cropengl:
+
+  DetailPrint "Installing 3D OpenGL support ..."
+  WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Version" 2
+  WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "DriverVersion" 1
+  WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Flags" 1
+  WriteRegStr   HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Dll" "VBoxOGL.dll"
+
+  ; Write additional keys required for Windows 7 & XP 64-bit (but for 32-bit stuff)
+  Push $R0
+  Call GetWindowsVersion
+  Pop $R0 ; Windows Version
+  ${If} $R0 == '7'
+  ${OrIf} $R0 == 'XP'
+    WriteRegDWORD HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Version" 2
+    WriteRegDWORD HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "DriverVersion" 1
+    WriteRegDWORD HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Flags" 1
+    WriteRegStr   HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL" "Dll" "VBoxOGL.dll"
+  ${EndIf}
+  Pop $R0
+!endif
+
+  Goto done
+
+error:
+
+  Abort "ERROR: Could not install files for Windows 2000 / XP / Vista! Installation aborted."
+
+done:
+
+FunctionEnd
+
+Function W2K_Main
+
+  SetOutPath "$INSTDIR"
+  SetOverwrite on
+
+  Call W2K_Prepare
+  Call W2K_CopyFiles
+
+!ifdef WHQL_FAKE
+  Call W2K_WHQLFakeOn
+!endif
+
+  Call W2K_InstallFiles
+
+!ifdef WHQL_FAKE
+  Call W2K_WHQLFakeOff
+!endif
+
+  Call W2K_SetVideoResolution
+
+FunctionEnd
+
+!macro W2K_UninstallInstDir un
+Function ${un}W2K_UninstallInstDir
+
+  Delete /REBOOTOK "$INSTDIR\VBoxVideo.sys"
+  Delete /REBOOTOK "$INSTDIR\VBoxVideo.inf"
+  Delete /REBOOTOK "$INSTDIR\VBoxVideo.cat"
+  Delete /REBOOTOK "$INSTDIR\VBoxDisp.dll"
+
+  Delete /REBOOTOK "$INSTDIR\VBoxMouse.sys"
+  Delete /REBOOTOK "$INSTDIR\VBoxMouse.inf"
+  Delete /REBOOTOK "$INSTDIR\VBoxMouse.cat"
+
+  Delete /REBOOTOK "$INSTDIR\VBoxTray.exe"
+
+  Delete /REBOOTOK "$INSTDIR\VBoxGuest.sys"
+  Delete /REBOOTOK "$INSTDIR\VBoxGuest.inf"
+  Delete /REBOOTOK "$INSTDIR\VBoxGuest.cat"
+
+  Delete /REBOOTOK "$INSTDIR\VBCoInst.dll"
+  Delete /REBOOTOK "$INSTDIR\VBoxControl.exe"
+  Delete /REBOOTOK "$INSTDIR\VBoxService.exe" ; File from an older installation maybe, not present here anymore
+
+  ; WHQL fake
+!ifdef WHQL_FAKE
+  Delete /REBOOTOK "$INSTDIR\VBoxWHQLFake.exe"
+!endif
+
+  ; Log file
+  Delete /REBOOTOK "$INSTDIR\install.log"
+  Delete /REBOOTOK "$INSTDIR\install_ui.log"
+
+FunctionEnd
+!macroend
+!insertmacro W2K_UninstallInstDir ""
+!insertmacro W2K_UninstallInstDir "un."
+
+!macro W2K_Uninstall un
+Function ${un}W2K_Uninstall
+
+  Push $0
+
+  ; Remove VirtualBox graphics adapter & PCI base drivers
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /u "PCI\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00"'
+  Pop $0    ; Ret value
+  ; @todo Add error handling here!
+
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /u "PCI\VEN_80EE&DEV_CAFE&SUBSYS_00000000&REV_00"'
+  Pop $0    ; Ret value
+  ; @todo Add error handling here!
+
+  ; @todo restore old drivers
+
+  ; Remove video driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxVideo'
+  Delete /REBOOTOK "$g_strSystemDir\drivers\VBoxVideo.sys"
+  Delete /REBOOTOK "$g_strSystemDir\VBoxDisp.dll"
+
+  ; Remove mouse driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxMouse'
+  Pop $0    ; Ret value
+  Delete /REBOOTOK "$g_strSystemDir\drivers\VBoxMouse.sys"
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /reg_delmultisz "SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}" "UpperFilters" "VBoxMouse"'
+  Pop $0    ; Ret value
+  ; @todo Add error handling here!
+
+  ; Delete the VBoxService service
+  Call ${un}StopVBoxService
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxService'
+  Pop $0    ; Ret value
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxService"
+  Delete /REBOOTOK "$g_strSystemDir\VBoxService.exe"
+
+  ; GINA
+  Delete /REBOOTOK "$g_strSystemDir\VBoxGINA.dll"
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon" "GinaDLL"
+  ${If} $0 == "VBoxGINA.dll"
+    DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon" "GinaDLL"
+  ${EndIf}
+
+  ; Delete VBoxTray
+  Call ${un}StopVBoxTray
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxTray"
+
+  ; Remove guest driver
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxGuest'
+  Pop $0    ; Ret value
+  Delete /REBOOTOK "$g_strSystemDir\drivers\VBoxGuest.sys"
+  Delete /REBOOTOK "$g_strSystemDir\vbcoinst.dll"
+  Delete /REBOOTOK "$g_strSystemDir\VBoxTray.exe"
+  Delete /REBOOTOK "$g_strSystemDir\VBoxHook.dll"
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "VBoxTray"      ; Remove VBoxTray autorun
+  Delete /REBOOTOK "$g_strSystemDir\VBoxControl.exe"
+
+  ; Remove shared folders driver
+  call ${un}RemoveProvider                        ; Remove Shared Folders network provider from registry
+                                                  ; @todo Add a /delnetprovider to VBoxDrvInst for doing this job!
+  nsExec::ExecToLog '"$INSTDIR\VBoxDrvInst.exe" /delsvc VBoxSF'
+  Delete /REBOOTOK "$g_strSystemDir\VBoxMRXNP.dll"        ; The network provider DLL will be locked
+  Delete /REBOOTOK "$g_strSystemDir\drivers\VBoxSF.sys"
+
+!if $%VBOX_WITH_CROGL% == "1"
+
+  DetailPrint "Removing 3D graphics support ..."
+  !if $%BUILD_TARGET_ARCH% == "x86"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLarrayspu.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLcrutil.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLerrorspu.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLpackspu.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLpassthroughspu.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGLfeedbackspu.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxOGL.dll"
+
+    ; Remove D3D stuff
+    ; @todo add a feature flag to only remove if installed explicitly
+    Delete /REBOOTOK "$g_strSystemDir\libWine.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxD3D8.dll"
+    Delete /REBOOTOK "$g_strSystemDir\VBoxD3D9.dll"
+    Delete /REBOOTOK "$g_strSystemDir\wined3d.dll"
+    ; Update DLL cache
+    IfFileExists "$g_strSystemDir\dllcache\msd3d8.dll" 0 +2
+      Delete /REBOOTOK "$g_strSystemDir\dllcache\d3d8.dll"
+      Rename /REBOOTOK "$g_strSystemDir\dllcache\msd3d8.dll" "$g_strSystemDir\dllcache\d3d8.dll"
+    IfFileExists g_strSystemDir\dllcache\msd3d9.dll" 0 +2
+      Delete /REBOOTOK "$g_strSystemDir\dllcache\d3d9.dll"
+      Rename /REBOOTOK "$g_strSystemDir\dllcache\msd3d9.dll" "$g_strSystemDir\dllcache\d3d9.dll"
+    ; Restore original DX DLLs
+    IfFileExists "$g_strSystemDir\msd3d8.dll" 0 +2
+      Delete /REBOOTOK "$g_strSystemDir\d3d8.dll"
+      Rename /REBOOTOK "$g_strSystemDir\msd3d8.dll" "$g_strSystemDir\d3d8.dll"
+    IfFileExists "$g_strSystemDir\msd3d9.dll" 0 +2
+      Delete /REBOOTOK "$g_strSystemDir\d3d9.dll"
+      Rename /REBOOTOK "$g_strSystemDir\msd3d9.dll" "$g_strSystemDir\d3d9.dll"
+
+  !else ; amd64
+
+    ; Only 64-bit installer: Also remove 32-bit DLLs on 64-bit target arch in Wow64 node
+    ${EnableX64FSRedirection}
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLarrayspu.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLcrutil.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLerrorspu.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLpackspu.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLpassthroughspu.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGLfeedbackspu.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxOGL.dll"
+
+    ; Remove D3D stuff
+    ; @todo add a feature flag to only remove if installed explicitly
+    Delete /REBOOTOK "$SYSDIR\libWine.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxD3D8.dll"
+    Delete /REBOOTOK "$SYSDIR\VBoxD3D9.dll"
+    Delete /REBOOTOK "$SYSDIR\wined3d.dll"
+    ; Update DLL cache
+    IfFileExists "$SYSDIR\dllcache\msd3d8.dll" 0 +2
+      Delete /REBOOTOK "$SYSDIR\dllcache\d3d8.dll"
+      Rename /REBOOTOK "$SYSDIR\dllcache\msd3d8.dll" "$SYSDIR\dllcache\d3d8.dll"
+    IfFileExists "$SYSDIR\dllcache\msd3d9.dll" 0 +2
+      Delete /REBOOTOK "$SYSDIR\dllcache\d3d9.dll"
+      Rename /REBOOTOK "$SYSDIR\dllcache\msd3d9.dll" "$SYSDIR\dllcache\d3d9.dll"
+    ; Restore original DX DLLs
+    IfFileExists "$SYSDIR\msd3d8.dll" 0 +2
+      Delete /REBOOTOK "$SYSDIR\d3d8.dll"
+      Rename /REBOOTOK "$SYSDIR\msd3d8.dll" "$SYSDIR\d3d8.dll"
+    IfFileExists "$SYSDIR\msd3d9.dll" 0 +2
+      Delete /REBOOTOK "$SYSDIR\d3d9.dll"
+      Rename /REBOOTOK "$SYSDIR\msd3d9.dll" "$SYSDIR\d3d9.dll"      
+    DeleteRegKey HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL"      
+    ${DisableX64FSRedirection}    
+  !endif ; amd64
+
+  DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\VBoxOGL"
+
+!endif ; VBOX_WITH_CROGL
+
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro W2K_Uninstall ""
+!insertmacro W2K_Uninstall "un."
+
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp	(revision 31634)
@@ -0,0 +1,472 @@
+/** @file
+ *
+ * instdrvmain - Install guest drivers on NT4
+ *
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+/**
+ * @todo
+ * The spacing in this file is horrible! Here are some simple rules:
+ * - tabs are forbidden
+ * - indentation is 4 spaces
+ */
+
+
+#include <windows.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <DEVGUID.h>
+#include <stdio.h>
+
+#include "tchar.h"
+#include "string.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+
+/** The video service name. */
+#define  VBOXGUEST_VIDEO_NAME    "VBoxVideo"
+
+/** The video inf file name */
+#define  VBOXGUEST_VIDEO_INF_NAME    "VBoxVideo.inf"
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+/**
+ * Do some cleanup of data we used. Called by installVideoDriver()
+ */
+void closeAndDestroy(HDEVINFO hDevInfo, HINF hInf)
+{
+  SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
+  SetupDiDestroyDeviceInfoList(hDevInfo);
+  SetupCloseInfFile(hInf);
+}
+
+
+/**
+ * Install the VBox video driver.
+ *
+ * @returns TRUE on success.
+ * @returns FALSE on failure.
+ * @param   szDriverDir     The base directory where we find the INF.
+ */
+BOOL installVideoDriver(TCHAR* szDriverDir)
+{
+  HDEVINFO hDevInfo;
+  SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
+  SP_DRVINFO_DATA drvInfoData={0};
+  SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};
+
+  DWORD cbReqSize;
+
+  /* Vars used for reading the INF */
+  HINF hInf;
+  TCHAR szServiceSection[LINE_LEN];
+  INFCONTEXT serviceContext;
+  TCHAR szServiceData[LINE_LEN];
+  TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...
+
+  SP_DEVINFO_DATA deviceInfoData;
+  DWORD configFlags;
+
+  HKEY hkey;
+  DWORD disp;
+  TCHAR regKeyName[LINE_LEN];
+
+  BOOL rc;
+
+  /* Create an empty list */
+  hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
+                                         NULL);
+
+  if (hDevInfo == INVALID_HANDLE_VALUE)
+    return FALSE;
+
+  memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
+  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+
+  rc=SetupDiGetDeviceInstallParams(hDevInfo,
+                                   NULL,
+                                   &DeviceInstallParams);
+
+  if(!rc)
+    return FALSE;
+
+  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+  DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
+    DI_DONOTCALLCONFIGMG |
+    DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */
+
+
+  /* Path to inf file */
+  wsprintf(DeviceInstallParams.DriverPath,
+           TEXT("%ws\\%ws"),
+           szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
+
+  rc=SetupDiSetDeviceInstallParams(hDevInfo,
+                                   NULL,
+                                   &DeviceInstallParams);
+  if(!rc)
+    return FALSE;
+
+  /* Read the drivers from the inf file */
+  if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
+    {
+      SetupDiDestroyDeviceInfoList(hDevInfo);
+      return FALSE;
+    }
+
+  /* Get the first found driver.
+     Our Inf file only contains one so this is fine  */
+  drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
+  if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
+                                  0, &drvInfoData)){
+    SetupDiDestroyDeviceInfoList(hDevInfo);
+    return FALSE;
+  }
+
+  /* Get necessary driver details */
+  DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
+  if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
+                                    NULL,
+                                    &drvInfoData,
+                                    &DriverInfoDetailData,
+                                    DriverInfoDetailData.cbSize,
+                                    &cbReqSize)
+        &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
+    {
+      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
+      SetupDiDestroyDeviceInfoList(hDevInfo);
+      return FALSE;
+    }
+
+  hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
+                          NULL, INF_STYLE_WIN4, NULL);
+
+  if (hInf == INVALID_HANDLE_VALUE)
+    {
+      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
+      SetupDiDestroyDeviceInfoList(hDevInfo);
+      return FALSE;
+    }
+
+  /* First install the service */
+  wsprintf(szServiceSection, TEXT("%ws.Services"),
+           DriverInfoDetailData.SectionName);
+
+  if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
+    {
+      /* No service line?? Can't be... */
+      closeAndDestroy(hDevInfo, hInf);
+      return FALSE;
+    }
+
+  /* Get the name */
+  SetupGetStringField(&serviceContext,
+                      1,
+                      szServiceData,
+                      sizeof(szServiceData),
+                      NULL);
+
+  wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);
+
+  memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
+  deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+  if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
+      ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr,                      //Create new
+                                 (LPGUID) &GUID_DEVCLASS_DISPLAY,
+                                 NULL, //Do we need a description here?
+                                 NULL, //No user interface
+                                 0,
+                                 &deviceInfoData) &&
+         SetupDiRegisterDeviceInfo(hDevInfo,
+                                   &deviceInfoData,
+                                   0,
+                                   NULL,
+                                   NULL,
+                                   NULL)) )
+    {
+      /* We created a new key in the registry */
+
+      memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
+      DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+
+      SetupDiGetDeviceInstallParams(hDevInfo,
+                                    &deviceInfoData,
+                                    &DeviceInstallParams);
+
+      DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
+        DI_DONOTCALLCONFIGMG |
+        DI_ENUMSINGLEINF; //Use our INF file only
+
+      /* Path to inf file */
+      wsprintf(DeviceInstallParams.DriverPath,
+               TEXT("%ws\\%ws"),
+               szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
+
+      SetupDiSetDeviceInstallParams(hDevInfo,
+                                    &deviceInfoData,
+                                    &DeviceInstallParams);
+
+
+      if(!SetupDiBuildDriverInfoList(hDevInfo,
+                                     &deviceInfoData,
+                                     SPDIT_CLASSDRIVER))
+        {
+          closeAndDestroy(hDevInfo, hInf);
+          return FALSE;
+        }
+
+      drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
+      if (!SetupDiEnumDriverInfo(hDevInfo,
+                                 &deviceInfoData,
+                                 SPDIT_CLASSDRIVER,
+                                 0,
+                                 &drvInfoData))
+        {
+          closeAndDestroy(hDevInfo, hInf);
+          return FALSE;
+        }
+
+      if(!SetupDiSetSelectedDriver(hDevInfo,
+                                   &deviceInfoData,
+                                   &drvInfoData))
+        {
+          closeAndDestroy(hDevInfo, hInf);
+          return FALSE;
+        }
+
+      if(!SetupDiInstallDevice(hDevInfo,
+                               &deviceInfoData))
+        {
+          closeAndDestroy(hDevInfo, hInf);
+          return FALSE;
+        }
+    }
+
+  /* Make sure the device is enabled */
+  if (SetupDiGetDeviceRegistryProperty(hDevInfo,
+                                       &deviceInfoData, SPDRP_CONFIGFLAGS,
+                                       NULL, (LPBYTE) &configFlags,
+                                       sizeof(DWORD),
+                                       NULL)
+      && (configFlags & CONFIGFLAG_DISABLED))
+    {
+      configFlags &= ~CONFIGFLAG_DISABLED;
+
+      SetupDiSetDeviceRegistryProperty(hDevInfo,
+                                       &deviceInfoData,
+                                       SPDRP_CONFIGFLAGS,
+                                       (LPBYTE) &configFlags,
+                                       sizeof(DWORD));
+    }
+
+  wsprintf(regKeyName,
+           TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
+           szServiceData, 0); //We only have one device
+
+  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                     regKeyName,
+                     0,
+                     NULL,
+                     REG_OPTION_NON_VOLATILE,
+                     KEY_READ | KEY_WRITE,
+                     NULL,
+                     &hkey,
+                     &disp) == ERROR_SUCCESS)
+    {
+      /* Insert description */
+      RegSetValueEx(hkey,
+                    TEXT("Device Description"),
+                    0,
+                    REG_SZ,
+                    (LPBYTE) DriverInfoDetailData.DrvDescription,
+                    (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
+                    sizeof(TCHAR) );
+
+      TCHAR szSoftwareSection[LINE_LEN];
+
+      wsprintf(szSoftwareSection,
+               TEXT("%ws.SoftwareSettings"),
+               szServiceData);
+
+      if (!SetupInstallFromInfSection(NULL,
+                                      hInf,
+                                      szSoftwareSection,
+                                      SPINST_REGISTRY,
+                                      hkey,
+                                      NULL,
+                                      0,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      NULL))
+        {
+          RegCloseKey(hkey);
+          closeAndDestroy(hDevInfo, hInf);
+          return FALSE;
+        }
+
+      RegCloseKey(hkey);
+    }
+
+  /* Install OpenGL stuff */
+  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                     TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
+                     0,
+                     NULL,
+                     REG_OPTION_NON_VOLATILE,
+                     KEY_READ | KEY_WRITE,
+                     NULL,
+                     &hkey,
+                     &disp) == ERROR_SUCCESS)
+    {
+      /* Do installation here if ever necessary. Currently there is no OpenGL stuff */
+
+      RegCloseKey(hkey);
+    }
+
+
+  /* Cleanup */
+  closeAndDestroy(hDevInfo, hInf);
+
+#if 0
+  /* If this key is inserted into the registry, windows will show the desktop
+     applet on next boot. We decide in the installer if we want that so the code
+     is disabled here. */
+  /* Set registry keys so windows picks up the changes */
+  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
+                     0,
+                     NULL,
+                     REG_OPTION_NON_VOLATILE,
+                     KEY_READ | KEY_WRITE,
+                     NULL,
+                     &hkey,
+                     &disp) == ERROR_SUCCESS)
+    {
+      RegCloseKey(hkey);
+    }
+#endif
+
+  /* We must reboot at some point */
+  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
+                     0,
+                     NULL,
+                     REG_OPTION_NON_VOLATILE,
+                     KEY_READ | KEY_WRITE,
+                     NULL,
+                     &hkey,
+                     &disp) == ERROR_SUCCESS)
+    {
+      RegCloseKey(hkey);
+    }
+
+  return TRUE;
+}
+
+
+void displayHelpAndExit(char *programName)
+{
+    printf("Installs VirtualBox Guest Additions for Windows NT 4.0\n\n");
+    printf("Syntax: %s [/i|/u]\n", programName);
+    printf("\n\t/i  - perform Guest Additions installation\n");
+    printf("\t/u:  - perform Guest Additions uninstallation\n");
+    exit(1);
+}
+
+/**
+ * Check if we are running on NT4.
+ *
+ * @returns TRUE if NT 4.
+ * @returns FALSE otherwise.
+ */
+BOOL isNT4(void)
+{
+    OSVERSIONINFO osVersion;
+
+    osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&osVersion);
+
+    switch (osVersion.dwPlatformId)
+    {
+        case VER_PLATFORM_WIN32s:
+        case VER_PLATFORM_WIN32_WINDOWS:
+            return FALSE;
+        case VER_PLATFORM_WIN32_NT:
+            if (osVersion.dwMajorVersion == 4)
+                return TRUE;
+            else
+                return FALSE;
+        default:
+            break;
+    }
+    return FALSE;
+}
+
+/**
+ *  Video driver uninstallation will be added later if necessary.
+ */
+int uninstallDrivers(void)
+{
+    return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+    BOOL rc=FALSE;
+    TCHAR szInstallDir[MAX_PATH];
+    HMODULE hExe = GetModuleHandle(NULL);
+
+  /** @todo r=bird:
+   * And by the way, we're only missing the coding style dmik uses now
+   * and this file would contain the complete set.  */
+  if(2!=argc || (stricmp(argv[1], "/i") && stricmp(argv[1], "/u")))
+    displayHelpAndExit(argv[0]);
+
+  /* This program is only for installing drivers on NT4 */
+  if(!isNT4()){
+    printf("This program only runs on NT4\n");
+    return -1;
+  }
+
+  if (!GetModuleFileName(hExe, &szInstallDir[0], sizeof(szInstallDir)))
+    {
+      printf("GetModuleFileName failed! rc = %d\n", GetLastError());
+      return -1;
+    }
+
+  TCHAR *lastBackslash = wcsrchr(szInstallDir, L'\\');
+
+  if (!lastBackslash)
+    {
+      printf("Invalid path name!\n");
+      return -1;
+    }
+
+  *lastBackslash=L'\0';
+
+  /* Install video driver. Mouse driver installation is done by overwriting
+     the image path in the setup script. */
+  if(!stricmp(argv[1], "/i")){
+    rc=installVideoDriver(szInstallDir);
+  }
+  else{
+    /* No video driver uninstallation yet. Do we need it? */
+  }
+
+  if(FALSE==rc)
+    printf("Some failure occurred during driver installation.\n");
+  return !rc; /* Return != 0 on failure. */
+}
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.rc	(revision 31634)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 Driver Installer\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxGuestDrvInst\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxGuestDrvInst.exe\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: trunk/src/VBox/Additions/WINNT/Installer/VBoxWHQLFake.au3
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/VBoxWHQLFake.au3	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/VBoxWHQLFake.au3	(revision 31634)
@@ -0,0 +1,59 @@
+; VBoxFakeWHQL - Turns off / on the WHQL for installing unsigned drivers.
+; Currently only tested with Win2K / XP!
+;
+; Copyright (C) 2008-2010 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+; Strings for localization
+; When using an OS with another language, you have to provide the correct
+; strings for it. English and German is provided below.
+;
+; @todo Needs to be improved to handle the stuff without language strings in
+; the future!
+
+;$sysprop_Title = "System Properties"
+;$drvsig_Title = "Driver Signing Options"
+
+$sysprop_Title = "Systemeigenschaften"
+$drvsig_Title = "Treibersignaturoptionen"
+
+$ok_Title  = "OK"
+
+If $CmdLine[0] < 1 Then
+	MsgBox ( 0, "ERROR", "Please specify 'ignore', 'warn' or 'block' as parameter!" )
+	Exit
+EndIf
+
+Run("control.exe sysdm.cpl")
+If WinWait($sysprop_Title, "", 5) = 0 Then
+   WinClose("[ACTIVE]", "")
+   Exit
+EndIf
+
+ControlCommand($sysprop_Title, "", "SysTabControl321", "TabRight", "")
+ControlCommand($sysprop_Title, "", "SysTabControl321", "TabRight", "")
+
+Sleep(200)                                      ; Wait a while for tab switchig above
+ControlClick($sysprop_Title, "", 14007)         ; Button 'Driver Signing'
+
+WinWait($drvsig_Title, "", 5)
+
+If $CmdLine[1] = "ignore" Then
+   ControlClick($drvsig_Title, "", 1000)       ; 'Ignore' radio button
+ElseIf $CmdLine[1] = "warn" Then
+   ControlClick($drvsig_Title, "", 1001)       ; 'Warn' radio button
+ElseIf $CmdLine[1] = "block" Then
+   ControlClick($drvsig_Title, "", 1002)       ; 'Block' radio button
+Else
+   Exit
+EndIf
+
+ControlClick($drvsig_Title, "", 1)     ; 'OK' button (ID=1) of dialog 'Driver Signing Options'
+
+WinWait($sysprop_Title, "", 5)
+ControlClick($sysprop_Title, "", 1)    ; 'OK' button (ID=1) of 'System Properties'
+
+
Index: trunk/src/VBox/Additions/WINNT/Installer/dumplog.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/dumplog.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/dumplog.nsh	(revision 31634)
@@ -0,0 +1,50 @@
+!define LVM_GETITEMCOUNT 0x1004
+!define LVM_GETITEMTEXT 0x102D
+
+!macro DumpLog un
+Function ${un}DumpLog
+  Exch $5
+  Push $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  Push $6
+
+  FindWindow $0 "#32770" "" $HWNDPARENT
+  GetDlgItem $0 $0 1016
+  StrCmp $0 0 error
+  FileOpen $5 $5 "w"
+  StrCmp $5 0 error
+    SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
+    System::Alloc ${NSIS_MAX_STRLEN}
+    Pop $3
+    StrCpy $2 0
+    System::Call "*(i, i, i, i, i, i, i, i, i) i \
+      (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
+    loop: StrCmp $2 $6 done
+      System::Call "User32::SendMessageA(i, i, i, i) i \
+        ($0, ${LVM_GETITEMTEXT}, $2, r1)"
+      System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
+      FileWrite $5 "$4$\r$\n"
+      IntOp $2 $2 + 1
+      Goto loop
+    done:
+      FileClose $5
+      System::Free $1
+      System::Free $3
+      Goto exit
+  error:
+    MessageBox MB_OK "Could not create Log-File!" /SD IDOK
+  exit:
+    Pop $6
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+    Exch $5
+FunctionEnd
+!macroend
+!insertmacro DumpLog ""
+!insertmacro DumpLog "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/servicepack.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/servicepack.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/servicepack.nsh	(revision 31634)
@@ -0,0 +1,29 @@
+;-------------------------------------------------------------------------------
+; GetServicePack
+; Author: Alessio Garbi (e-Project srl) <agarbi@e-project.it>
+;
+; input:
+;			none
+; output:
+;    	top of stack: last service pack major version
+;    	top of stack-1: last service pack minor version
+; note:
+;			If no service pack installed returns major ver "0" and minor ver "0"
+;			Function tested with Win 95, 98SE, NT4, 2000, XP, 2003 (lang ITA and ENG)
+
+!macro GetServicePack un
+Function ${un}GetServicePack
+	Push $R0
+	Push $R1
+
+	ReadRegDWORD $R0 HKLM "System\CurrentControlSet\Control\Windows" "CSDVersion"
+	IntOp $R1 $R0 % 256			;get minor version
+	IntOp $R0 $R0 / 256			;get major version
+
+	Exch $R1
+	Exch
+	Exch $R0
+FunctionEnd
+!macroend
+!insertmacro GetServicePack ""
+!insertmacro GetServicePack "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/strstr.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/strstr.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/strstr.nsh	(revision 31634)
@@ -0,0 +1,306 @@
+; StrStr
+ ; input, top of stack = string to search for
+ ;        top of stack-1 = string to search in
+ ; output, top of stack (replaces with the portion of the string remaining)
+ ; modifies no other variables.
+ ;
+ ; Usage:
+ ;   Push "this is a long ass string"
+ ;   Push "ass"
+ ;   Call StrStr
+ ;   Pop $R0
+ ;  ($R0 at this point is "ass string")
+
+
+!macro StrStr un
+ Function ${un}StrStr
+   Exch $R1 ; st=haystack,old$R1, $R1=needle
+   Exch    ; st=old$R1,haystack
+   Exch $R2 ; st=old$R1,old$R2, $R2=haystack
+   Push $R3
+   Push $R4
+   Push $R5
+   StrLen $R3 $R1
+   StrCpy $R4 0
+   ; $R1=needle
+   ; $R2=haystack
+   ; $R3=len(needle)
+   ; $R4=cnt
+   ; $R5=tmp
+   loop:
+     StrCpy $R5 $R2 $R3 $R4
+     StrCmp $R5 $R1 done
+     StrCmp $R5 "" done
+     IntOp $R4 $R4 + 1
+     Goto loop
+ done:
+   StrCpy $R1 $R2 "" $R4
+   Pop $R5
+   Pop $R4
+   Pop $R3
+   Pop $R2
+   Exch $R1
+ FunctionEnd
+!macroend
+!insertmacro StrStr ""
+!insertmacro StrStr "un."
+
+!macro StrStrAdv un
+Function ${un}StrStrAdv
+
+  ; After this point:
+  ; $0 = String (input)
+  ; $1 = SubString (input)
+  ; $2 = SearchDirection (input)
+  ; $3 = StrInclusionDirection (input)
+  ; $4 = IncludeSubString (input)
+  ; $5 = Loops (input)
+  ; $6 = CaseSensitive (input)
+  ; $7 = StringLength (temp)
+  ; $8 = StrToSearchLength (temp)
+  ; $9 = CurrentLoop (temp)
+  ; $R0 = EndCharPos (temp)
+  ; $R1 = StartCharPos (temp)
+  ; $R2 = ResultVar (output)
+  ; $R3 = Temp (temp)
+
+  ; Get input from user
+
+  Exch $6
+  Exch
+  Exch $5
+  Exch
+  Exch 2
+  Exch $4
+  Exch 2
+  Exch 3
+  Exch $3
+  Exch 3
+  Exch 4
+  Exch $2
+  Exch 4
+  Exch 5
+  Exch $1
+  Exch 5
+  Exch 6
+  Exch $0
+  Exch 6
+  Push $7
+  Push $8
+  Push $9
+  Push $R3
+  Push $R2
+  Push $R1
+  Push $R0
+
+  ; Clean $R0-$R3 variables
+  StrCpy $R0 ""
+  StrCpy $R1 ""
+  StrCpy $R2 ""
+  StrCpy $R3 ""
+
+  ; Verify if we have the correct values on the variables
+  ${If} $0 == ``
+    SetErrors ;AdvStrStr_StrToSearch not found
+    Goto AdvStrStr_End
+  ${EndIf}
+
+  ${If} $1 == ``
+    SetErrors ;No text to search
+    Goto AdvStrStr_End
+  ${EndIf}
+
+  ${If} $2 != <
+    StrCpy $2 >
+  ${EndIf}
+
+  ${If} $3 != <
+    StrCpy $3 >
+  ${EndIf}
+
+  ${If} $4 <> 0
+    StrCpy $4 1
+  ${EndIf}
+
+  ${If} $5 <= 0
+    StrCpy $5 0
+  ${EndIf}
+
+  ${If} $6 <> 1
+    StrCpy $6 0
+  ${EndIf}
+
+  ; Find "AdvStrStr_String" length
+  StrLen $7 $0
+
+  ; Then find "AdvStrStr_SubString" length
+  StrLen $8 $1
+
+  ; Now set up basic variables
+
+  ${If} $2 == <
+    IntOp $R1 $7 - $8
+    StrCpy $R2 $7
+  ${Else}
+    StrCpy $R1 0
+    StrCpy $R2 $8
+  ${EndIf}
+
+  StrCpy $9 0 ; First loop
+
+  ;Let's begin the search
+
+  ${Do}
+    ; Step 1: If the starting or ending numbers are negative
+    ;         or more than AdvStrStr_StringLen, we return
+    ;         error
+
+    ${If} $R1 < 0
+      StrCpy $R1 ``
+      StrCpy $R2 ``
+      StrCpy $R3 ``
+      SetErrors ;AdvStrStr_SubString not found
+      Goto AdvStrStr_End
+    ${ElseIf} $R2 > $7
+      StrCpy $R1 ``
+      StrCpy $R2 ``
+      StrCpy $R3 ``
+      SetErrors ;AdvStrStr_SubString not found
+      Goto AdvStrStr_End
+    ${EndIf}
+
+    ; Step 2: Start the search depending on
+    ;         AdvStrStr_SearchDirection. Chop down not needed
+    ;         characters.
+
+    ${If} $R1 <> 0
+      StrCpy $R3 $0 `` $R1
+    ${EndIf}
+
+    ${If} $R2 <> $7
+      ${If} $R1 = 0
+        StrCpy $R3 $0 $8
+      ${Else}
+        StrCpy $R3 $R3 $8
+      ${EndIf}
+    ${EndIf}
+
+    ; Step 3: Make sure that's the string we want
+
+    ; Case-Sensitive Support <- Use "AdvStrStr_Temp"
+    ; variable because it won't be used anymore
+
+    ${If} $6 == 1
+      System::Call `kernel32::lstrcmpA(ts, ts) i.s` `$R3` `$1`
+      Pop $R3
+      ${If} $R3 = 0
+        StrCpy $R3 1 ; Continue
+      ${Else}
+        StrCpy $R3 0 ; Break
+      ${EndIf}
+    ${Else}
+      ${If} $R3 == $1
+        StrCpy $R3 1 ; Continue
+      ${Else}
+        StrCpy $R3 0 ; Break
+      ${EndIf}
+    ${EndIf}
+
+    ; After the comparasion, confirm that it is the
+    ; value we want.
+
+    ${If} $R3 = 1
+
+      ;We found it, return except if the user has set up to
+      ;search for another one:
+      ${If} $9 >= $5
+
+        ;Now, let's see if the user wants
+        ;AdvStrStr_SubString to appear:
+        ${If} $4 == 0
+          ;Return depends on AdvStrStr_StrInclusionDirection
+          ${If} $3 == <
+            ; RTL
+            StrCpy $R0 $0 $R1
+          ${Else}
+            ; LTR
+            StrCpy $R0 $0 `` $R2
+          ${EndIf}
+          ${Break}
+        ${Else}
+          ;Return depends on AdvStrStr_StrInclusionDirection
+          ${If} $3 == <
+            ; RTL
+            StrCpy $R0 $0 $R2
+          ${Else}
+            ; LTR
+            StrCpy $R0 $0 `` $R1
+          ${EndIf}
+          ${Break}
+        ${EndIf}
+      ${Else}
+        ;If the user wants to have more loops, let's do it so!
+        IntOp $9 $9 + 1
+
+        ${If} $2 == <
+          IntOp $R1 $R1 - 1
+          IntOp $R2 $R2 - 1
+        ${Else}
+          IntOp $R1 $R1 + 1
+          IntOp $R2 $R2 + 1
+        ${EndIf}
+      ${EndIf}
+    ${Else}
+      ; Step 4: We didn't find it, so do steps 1 thru 3 again
+
+      ${If} $2 == <
+        IntOp $R1 $R1 - 1
+        IntOp $R2 $R2 - 1
+      ${Else}
+        IntOp $R1 $R1 + 1
+        IntOp $R2 $R2 + 1
+      ${EndIf}
+    ${EndIf}
+  ${Loop}
+
+  AdvStrStr_End:
+
+  ;Add 1 to AdvStrStr_EndCharPos to be supportable
+  ;by "StrCpy"
+
+  IntOp $R2 $R2 - 1
+
+  ;Return output to user
+
+  Exch $R0
+  Exch
+  Pop $R1
+  Exch
+  Pop $R2
+  Exch
+  Pop $R3
+  Exch
+  Pop $9
+  Exch
+  Pop $8
+  Exch
+  Pop $7
+  Exch
+  Pop $6
+  Exch
+  Pop $5
+  Exch
+  Pop $4
+  Exch
+  Pop $3
+  Exch
+  Pop $2
+  Exch
+  Pop $1
+  Exch
+  Pop $0
+
+FunctionEnd
+!macroend
+!insertmacro StrStrAdv ""
+!insertmacro StrStrAdv "un."
Index: trunk/src/VBox/Additions/WINNT/Installer/winver.nsh
===================================================================
--- trunk/src/VBox/Additions/WINNT/Installer/winver.nsh	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/Installer/winver.nsh	(revision 31634)
@@ -0,0 +1,103 @@
+; GetWindowsVersion
+;
+; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/
+; Updated by Joost Verburg
+;
+; Returns on top of stack
+;
+; Windows Version (95, 98, ME, NT x.x, 2000, XP, 2003, Vista)
+; or
+; '' (Unknown Windows Version)
+;
+; Usage:
+;   Call GetWindowsVersion
+;   Pop $R0
+;   ; at this point $R0 is "NT 4.0" or whatnot
+
+!macro GetWindowsVersion un
+Function ${un}GetWindowsVersion
+
+  Push $R0
+  Push $R1
+
+  ClearErrors
+
+  ReadRegStr $R0 HKLM \
+  "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
+
+  IfErrors 0 lbl_winnt
+
+  ; we are not NT
+  ReadRegStr $R0 HKLM \
+  "SOFTWARE\Microsoft\Windows\CurrentVersion" VersionNumber
+
+  StrCpy $R1 $R0 1
+  StrCmp $R1 '4' 0 lbl_error
+
+  StrCpy $R1 $R0 3
+
+  StrCmp $R1 '4.0' lbl_win32_95
+  StrCmp $R1 '4.9' lbl_win32_ME lbl_win32_98
+
+  lbl_win32_95:
+    StrCpy $R0 '95'
+  Goto lbl_done
+
+  lbl_win32_98:
+    StrCpy $R0 '98'
+  Goto lbl_done
+
+  lbl_win32_ME:
+    StrCpy $R0 'ME'
+  Goto lbl_done
+
+  lbl_winnt:
+
+  StrCpy $R1 $R0 1
+
+  StrCmp $R1 '3' lbl_winnt_x
+  StrCmp $R1 '4' lbl_winnt_x
+
+  StrCpy $R1 $R0 3
+
+  StrCmp $R1 '5.0' lbl_winnt_2000
+  StrCmp $R1 '5.1' lbl_winnt_XP
+  StrCmp $R1 '5.2' lbl_winnt_2003
+  StrCmp $R1 '6.0' lbl_winnt_vista
+  StrCmp $R1 '6.1' lbl_winnt_7 lbl_error
+
+  lbl_winnt_x:
+    StrCpy $R0 "NT $R0" 6
+  Goto lbl_done
+
+  lbl_winnt_2000:
+    Strcpy $R0 '2000'
+  Goto lbl_done
+
+  lbl_winnt_XP:
+    Strcpy $R0 'XP'
+  Goto lbl_done
+
+  lbl_winnt_2003:
+    Strcpy $R0 '2003'
+  Goto lbl_done
+
+  lbl_winnt_vista:
+    Strcpy $R0 'Vista'
+  Goto lbl_done
+
+  lbl_winnt_7:
+    Strcpy $R0 '7'
+  Goto lbl_done
+
+  lbl_error:
+    Strcpy $R0 ''
+  lbl_done:
+
+  Pop $R1
+  Exch $R0
+
+FunctionEnd
+!macroend
+!insertmacro GetWindowsVersion ""
+!insertmacro GetWindowsVersion "un."
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/Makefile.kmk	(revision 31634)
@@ -0,0 +1,20 @@
+# $Id$
+## @file
+# Sub-Makefile for the Windows guest shared folders.
+#
+
+#
+# Copyright (C) 2006-2007 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+# Include sub-makefile(s).
+include $(PATH_SUB_CURRENT)/redirector/Makefile.kmk
+
+include	$(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/Makefile.kmk	(revision 31634)
@@ -0,0 +1,21 @@
+# $Id$
+## @file
+# Sub-Makefile for the Windows guest shared folder redirectory.
+#
+
+#
+# Copyright (C) 2006-2007 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+# Include sub-makefiles.
+include $(PATH_SUB_CURRENT)/dll/Makefile.kmk
+include $(PATH_SUB_CURRENT)/sys/Makefile.kmk
+
+include	$(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/Makefile.kmk	(revision 31634)
@@ -0,0 +1,36 @@
+# $Id$
+## @file
+# Sub-Makefile for the VirtualBox Windows Guest Shared Folders Network Provider.
+#
+
+#
+# Copyright (C) 2006-2007 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+DLLS += VBoxMRXNP
+VBoxMRXNP_TEMPLATE    = VBOXGUESTR3DLL
+VBoxMRXNP_SDKS        = WINDDK
+VBoxMRXNP_DEFS        = LOG_TO_BACKDOOR _WIN32_WINNT=0x0500 UNICODE WIN32_LEAN_AND_MEAN=1
+
+VBoxMRXNP_INCS        = \
+	$(PATH_SUB_ROOT)/WINNT/SharedFolders/include
+
+VBoxMRXNP_SOURCES     = \
+	dllmain.cpp \
+	vboxmrxp.cpp \
+	vboxmrxp.rc \
+	vboxmrxp.def
+
+VBoxMRXNP_LIBS     = \
+	$(VBOX_LIB_IPRT_GUEST_R3) \
+	$(VBOX_LIB_VBGL_R3) \
+	$(VBOX_LIB_IPRT_GUEST_R3)
+
+include	$(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/dllmain.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/dllmain.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/dllmain.cpp	(revision 31634)
@@ -0,0 +1,63 @@
+/*++
+
+Copyright (c) 1989-1999  Microsoft Corporation
+
+Module Name:
+
+    dllmain.c
+
+Abstract:
+
+    This module implements the initialization routines for network
+    provider interface
+
+Notes:
+
+    This module has been built and tested only in UNICODE environment
+
+--*/
+
+#include <windows.h>
+#include <process.h>
+
+#include "vboxmrxp.h"
+
+// NOTE:
+//
+// Function:    DllMain
+//
+// Return:  TRUE  => Success
+//      FALSE => Failure
+
+BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
+{
+    BOOL    bStatus = TRUE;
+
+    switch (fdwReason) {
+    case DLL_PROCESS_ATTACH:
+
+        RTR3Init();
+        VbglR3Init();
+        LogRel(("VBOXNP: DLL loaded.\n"));
+        break;
+
+    case DLL_PROCESS_DETACH:
+
+        LogRel(("VBOXNP: DLL unloaded.\n"));
+        VbglR3Term();
+        /// @todo RTR3Term();
+        break;
+
+    case DLL_THREAD_ATTACH:
+        break;
+
+    case DLL_THREAD_DETACH:
+        break;
+
+    default:
+        break;
+    }
+
+    return(bStatus);
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.cpp	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.cpp	(revision 31634)
@@ -0,0 +1,2146 @@
+/*++
+
+ Copyright (c) 1989-1999  Microsoft Corporation
+
+ Module Name:
+
+ ifsmrxnp.c
+
+ Abstract:
+
+ This module implements the routines required for interaction with network
+ provider router interface in NT
+
+ Notes:
+
+ This module has been built and tested only in UNICODE environment
+
+ --*/
+
+#include <windows.h>
+#include <windef.h>
+#include <winbase.h>
+#include <winsvc.h>
+#include <winnetwk.h>
+#include <npapi.h>
+#include <devioctl.h>
+#include <stdio.h>
+
+#include "vboxmrxp.h"
+
+#define WNNC_DRIVER( major, minor ) ( major * 0x00010000 + minor )
+
+ULONG SendToMiniRdr (IN ULONG IoctlCode, IN PVOID InputDataBuf, IN ULONG InputDataLen, IN PVOID OutputDataBuf, IN PULONG pOutputDataLen)
+/*++
+
+ Routine Description:
+
+ This routine sends a device ioctl to the Mini Rdr.
+
+ Arguments:
+
+ IoctlCode      - Function code for the Mini Rdr driver
+
+ InputDataBuf   - Input buffer pointer
+
+ InputDataLen   - Lenth of the input buffer
+
+ OutputDataBuf  - Output buffer pointer
+
+ pOutputDataLen - Pointer to the length of the output buffer
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ --*/
+{
+    HANDLE DeviceHandle; // The mini rdr device handle
+    BOOL rc;
+    ULONG Status;
+    DWORD cbOut = 0;
+
+    if (!pOutputDataLen)
+        pOutputDataLen = &cbOut;
+
+    Status = WN_SUCCESS;
+
+    // Grab a handle to the redirector device object
+
+    DeviceHandle = CreateFile(DD_MRX_VBOX_USERMODE_DEV_NAME_U, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, (HANDLE)NULL );
+
+    if (INVALID_HANDLE_VALUE != DeviceHandle)
+    {
+        rc = DeviceIoControl(DeviceHandle, IoctlCode, InputDataBuf, InputDataLen, OutputDataBuf, *pOutputDataLen, pOutputDataLen, NULL );
+
+        if (!rc)
+        {
+            Status = GetLastError();
+            Log(("VBOXNP: SendToMiniRdr: Returning error from DeviceIoctl! Status = %d \n", Status));
+        }
+        else
+        {
+            Log(("VBOXNP: SendToMiniRdr: The DeviceIoctl call succeded\n"));
+        }
+        CloseHandle(DeviceHandle);
+    }
+    else
+    {
+        Status = GetLastError();
+        static int sLogged = 0;
+        if (!sLogged)
+        {
+            LogRel(("VBOXNP: SendToMiniRdr: Error opening device! Status = %lx\n", Status));
+            sLogged++;
+        }
+    }
+
+    return Status;
+}
+
+DWORD APIENTRY
+NPGetCaps (DWORD nIndex)
+/*++
+
+ Routine Description:
+
+ This routine returns the capaboilities of the Null Mini redirector
+ network provider implementation
+
+ Arguments:
+
+ nIndex - category of capabilities desired
+
+ Return Value:
+
+ the appropriate capabilities
+
+ --*/
+{
+    DWORD rc = 0;
+
+    Log(("VBOXNP: GetNetCaps: Index = 0x%lx\n", nIndex));
+
+    switch (nIndex)
+    {
+    case WNNC_SPEC_VERSION:
+        rc = WNNC_SPEC_VERSION51;
+        break;
+
+    case WNNC_NET_TYPE:
+        rc = WNNC_NET_RDR2SAMPLE;
+        break;
+
+    case WNNC_DRIVER_VERSION:
+        rc = WNNC_DRIVER(1, 0);
+        break;
+
+    case WNNC_CONNECTION:
+        SendToMiniRdr(IOCTL_MRX_VBOX_START, NULL, 0, NULL, NULL);
+        rc = WNNC_CON_GETCONNECTIONS | WNNC_CON_CANCELCONNECTION | WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3;
+        break;
+
+    case WNNC_ENUMERATION:
+        rc = WNNC_ENUM_LOCAL | WNNC_ENUM_GLOBAL | WNNC_ENUM_SHAREABLE;
+        break;
+
+    case WNNC_START:
+        rc = 1;
+        break;
+
+    case WNNC_DIALOG:
+        rc = WNNC_DLG_GETRESOURCEPARENT | WNNC_DLG_GETRESOURCEINFORMATION;
+        break;
+
+    case WNNC_USER:
+    case WNNC_ADMIN:
+    default:
+        rc = 0;
+        break;
+    }
+
+    return rc;
+}
+
+DWORD APIENTRY
+NPLogonNotify (PLUID lpLogonId,
+               LPCWSTR lpAuthentInfoType,
+               LPVOID lpAuthentInfo,
+               LPCWSTR lpPreviousAuthentInfoType,
+               LPVOID lpPreviousAuthentInfo,
+               LPWSTR lpStationName,
+               LPVOID StationHandle,
+               LPWSTR *lpLogonScript)
+/*++
+
+ Routine Description:
+
+ This routine handles the logon notifications
+
+ Arguments:
+
+ lpLogonId -- the associated LUID
+
+ lpAuthenInfoType - the authentication information type
+
+ lpAuthenInfo  - the authentication Information
+
+ lpPreviousAuthentInfoType - the previous aunthentication information type
+
+ lpPreviousAuthentInfo - the previous authentication information
+
+ lpStationName - the logon station name
+
+ LPVOID - logon station handle
+
+ lpLogonScript - the logon script to be executed.
+
+ Return Value:
+
+ WN_SUCCESS
+
+ Notes:
+
+ This capability has not been implemented in the sample.
+
+ --*/
+{
+    Log(("VBOXNP: NPLogonNotify: Called.\n"));
+    *lpLogonScript = NULL;
+
+    return WN_SUCCESS;
+}
+
+DWORD APIENTRY
+NPPasswordChangeNotify (LPCWSTR lpAuthentInfoType,
+                        LPVOID lpAuthentInfo,
+                        LPCWSTR lpPreviousAuthentInfoType,
+                        LPVOID lpPreviousAuthentInfo,
+                        LPWSTR lpStationName,
+                        LPVOID StationHandle,
+                        DWORD dwChangeInfo)
+/*++
+
+ Routine Description:
+
+ This routine handles the password change notifications
+
+ Arguments:
+
+ lpAuthenInfoType - the authentication information type
+
+ lpAuthenInfo  - the authentication Information
+
+ lpPreviousAuthentInfoType - the previous aunthentication information type
+
+ lpPreviousAuthentInfo - the previous authentication information
+
+ lpStationName - the logon station name
+
+ LPVOID - logon station handle
+
+ dwChangeInfo - the password change information.
+
+ Return Value:
+
+ WN_NOT_SUPPORTED
+
+ Notes:
+
+ This capability has not been implemented in the sample.
+
+ --*/
+{
+    Log(("VBOXNP: NPPasswordChangeNotify: Called.\n"));
+    SetLastError(WN_NOT_SUPPORTED);
+
+    return WN_NOT_SUPPORTED;
+}
+
+DWORD APIENTRY
+NPAddConnection (LPNETRESOURCE lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
+/*++
+
+ Routine Description:
+
+ This routine adds a connection to the list of connections associated
+ with this network provider
+
+ Arguments:
+
+ lpNetResource - the NETRESOURCE struct
+
+ lpPassword  - the password
+
+ lpUserName - the user name
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ --*/
+{
+    Log(("VBOXNP: NPAddConnection: Called.\n"));
+    return NPAddConnection3(NULL, lpNetResource, lpPassword, lpUserName, 0);
+}
+
+DWORD APIENTRY
+NPAddConnection3 (HWND hwndOwner, LPNETRESOURCE lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
+/*++
+
+ Routine Description:
+
+ This routine adds a connection to the list of connections associated
+ with this network provider
+
+ Arguments:
+
+ hwndOwner - the owner handle
+
+ lpNetResource - the NETRESOURCE struct
+
+ lpPassword  - the password
+
+ lpUserName - the user name
+
+ dwFlags - flags for the connection
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ --*/
+{
+    DWORD Status;
+    WCHAR ConnectionName[128];
+    WCHAR wszScratch[128];
+    WCHAR LocalName[3];
+    DWORD CopyBytes = 0;
+    BOOLEAN fLocalName = TRUE;
+
+    Log(("VBOXNP: NPAddConnection3: dwFlags = 0x%x\n", dwFlags));
+    Log(("VBOXNP: NPAddConnection3: Local Name:  %ls\n", lpNetResource->lpLocalName ));
+    Log(("VBOXNP: NPAddConnection3: Remote Name: %ls\n", lpNetResource->lpRemoteName ));
+
+    Status = WN_SUCCESS;
+
+    if (lpNetResource->dwType != RESOURCETYPE_DISK && lpNetResource->dwType != RESOURCETYPE_ANY)
+    {
+        Log(("VBOXNP: NPAddConnection3: Incorrect net resource type %d\n", lpNetResource->dwType));
+        return WN_BAD_NETNAME;
+    }
+
+    //  \device\miniredirector\;<DriveLetter>:\Server\Share
+
+    if (lpNetResource->lpLocalName == NULL)
+    {
+        fLocalName = FALSE;
+        lstrcpy(ConnectionName, DD_MRX_VBOX_FS_DEVICE_NAME_U );
+        lstrcat(ConnectionName,L"\\;" );
+    }
+    else
+        if ( lstrlen( lpNetResource->lpLocalName )> 1 )
+        {
+            if ( lpNetResource->lpLocalName[1] == L':' )
+            {
+                // LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpNetResource->lpLocalName[0], 0 ) );
+                LocalName[0] = (WCHAR) toupper(lpNetResource->lpLocalName[0]);
+                LocalName[1] = L':';
+                LocalName[2] = L'\0';
+                lstrcpy( ConnectionName, DD_MRX_VBOX_FS_DEVICE_NAME_U );
+                lstrcat( ConnectionName, L"\\;" );
+                lstrcat( ConnectionName, LocalName );
+            }
+            else
+                Status = WN_BAD_LOCALNAME;
+        }
+        else
+            Status = WN_BAD_LOCALNAME;
+
+    // format proper server name
+    if ( lpNetResource->lpRemoteName[0] == L'\\' && lpNetResource->lpRemoteName[1] == L'\\' )
+    {
+        if (lstrlen (ConnectionName) + lstrlen (lpNetResource->lpRemoteName) <= sizeof (ConnectionName) / sizeof (WCHAR))
+        {
+            /* No need for (lstrlen + 1), because 'lpNetResource->lpRemoteName' leading \ is not copied. */
+            lstrcat( ConnectionName, lpNetResource->lpRemoteName + 1 );
+        }
+        else
+        {
+            Status = WN_BAD_NETNAME;
+        }
+    }
+    else
+    {
+        Status = WN_BAD_NETNAME;
+    }
+
+    Log(("VBOXNP: NPAddConnection3: Full Connect Name: %ls\n", ConnectionName ));
+    Log(("VBOXNP: NPAddConnection3: Full Connect Name Length: %d\n", ( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ) ));
+
+    if ( Status == WN_SUCCESS )
+    {
+        if ( fLocalName
+                && QueryDosDevice( LocalName, wszScratch, sizeof (wszScratch) / sizeof (WCHAR) ))
+        {
+            Log(("VBOXNP: NPAddConnection3: Connection \"%ls\" already connected.\n", ConnectionName));
+            Status = WN_ALREADY_CONNECTED;
+        }
+        else
+            if (   !fLocalName
+                || GetLastError() == ERROR_FILE_NOT_FOUND)
+            {
+                Status = SendToMiniRdr( IOCTL_MRX_VBOX_ADDCONN, ConnectionName,
+                                        ( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ),
+                                        NULL, &CopyBytes );
+
+                if (Status == WN_SUCCESS)
+                {
+                    if ( fLocalName
+                            && !DefineDosDevice( DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM,
+                                                 lpNetResource->lpLocalName,
+                                                 ConnectionName ) )
+                    {
+                        Status = GetLastError();
+                    }
+                }
+                else Status = WN_BAD_NETNAME;
+            }
+            else Status = WN_ALREADY_CONNECTED;
+    }
+
+    Log(("VBOXNP: NPAddConnection3: Returned 0x%lx\n", Status));
+    return Status;
+}
+
+DWORD APIENTRY
+NPCancelConnection (LPWSTR lpName, BOOL fForce)
+/*++
+
+ Routine Description:
+
+ This routine cancels ( deletes ) a connection from the list of connections
+ associated with this network provider
+
+ Arguments:
+
+ lpName - name of the connection
+
+ fForce - forcefully delete the connection
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ --*/
+
+{
+    WCHAR LocalName[3];
+    WCHAR RemoteName[128];
+    WCHAR ConnectionName[128];
+    ULONG CopyBytes;
+    DWORD Status = WN_NOT_CONNECTED;
+
+    Log(("VBOXNP: NPCancelConnection: Name = %ls\n", lpName ));
+
+    if (lstrlen(lpName) > 1)
+    {
+        if (lpName[1] == L':')
+        {
+            // LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpName[0], 0 ) );
+            LocalName[0] = (WCHAR)toupper(lpName[0]);
+            LocalName[1] = L':';
+            LocalName[2] = L'\0';
+
+            CopyBytes = sizeof (RemoteName) - sizeof (WCHAR); /* Trailing NULL. */
+            Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETCONN, LocalName, sizeof(LocalName), (PVOID)RemoteName, &CopyBytes);
+            if (Status == WN_SUCCESS && CopyBytes > 0)
+            {
+                RemoteName[CopyBytes] = L'\0';
+
+                if (lstrlen (DD_MRX_VBOX_FS_DEVICE_NAME_U) + 2 + lstrlen (LocalName) + lstrlen (RemoteName) + 1 > sizeof (ConnectionName) / sizeof (WCHAR))
+                {
+                    return WN_BAD_NETNAME;
+                }
+
+                lstrcpy(ConnectionName, DD_MRX_VBOX_FS_DEVICE_NAME_U );
+                lstrcat(ConnectionName,L"\\;" );
+                lstrcat( ConnectionName, LocalName );
+                lstrcat( ConnectionName, RemoteName );
+                CopyBytes = 0;
+                Status = SendToMiniRdr( IOCTL_MRX_VBOX_DELCONN, ConnectionName,
+                        ( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ),
+                        NULL, &CopyBytes );
+                if ( Status == WN_SUCCESS )
+                {
+                    if ( !DefineDosDevice( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
+                                    LocalName,
+                                    ConnectionName ) )
+                    {
+                        Status = GetLastError( );
+                    }
+                }
+            }
+            else
+            {
+                Status = WN_NOT_CONNECTED;
+            }
+        }
+        else
+        {
+            BOOLEAN Verifier;
+
+            Verifier = ( lpName[0] == L'\\' );
+            Verifier &= ( lpName[1] == L'V' ) || ( lpName[1] == L'v' );
+            Verifier &= ( lpName[2] == L'B' ) || ( lpName[2] == L'b' );
+            Verifier &= ( lpName[3] == L'O' ) || ( lpName[3] == L'o' );
+            Verifier &= ( lpName[4] == L'X' ) || ( lpName[4] == L'x' );
+            Verifier &= ( lpName[5] == L'S' ) || ( lpName[5] == L's' );
+            /* Both vboxsvr & vboxsrv are now accepted */
+            if (( lpName[6] == L'V' ) || ( lpName[6] == L'v'))
+            {
+                Verifier &= ( lpName[6] == L'V' ) || ( lpName[6] == L'v' );
+                Verifier &= ( lpName[7] == L'R' ) || ( lpName[7] == L'r' );
+            }
+            else
+            {
+                Verifier &= ( lpName[6] == L'R' ) || ( lpName[6] == L'r' );
+                Verifier &= ( lpName[7] == L'V' ) || ( lpName[7] == L'v' );
+            }
+            Verifier &= ( lpName[8] == L'\\') || ( lpName[8] == 0 );
+
+            if (Verifier)
+            {
+                /* full remote path */
+                if (lstrlen (DD_MRX_VBOX_FS_DEVICE_NAME_U) + 2 + lstrlen (lpName) + 1 > sizeof (ConnectionName) / sizeof (WCHAR))
+                {
+                    return WN_BAD_NETNAME;
+                }
+
+                lstrcpy( ConnectionName, DD_MRX_VBOX_FS_DEVICE_NAME_U );
+                lstrcat( ConnectionName, L"\\;" );
+                lstrcat( ConnectionName, lpName );
+                CopyBytes = 0;
+                Status = SendToMiniRdr( IOCTL_MRX_VBOX_DELCONN, ConnectionName,
+                        ( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ),
+                        NULL, &CopyBytes );
+            }
+            else
+            Status = WN_NOT_CONNECTED;
+        }
+    }
+
+    Log(("VBOXNP: NPCancelConnection: Returned 0x%lx\n", Status));
+    return Status;
+}
+
+DWORD APIENTRY
+NPGetConnection (LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpBufferSize)
+/*++
+
+ Routine Description:
+
+ This routine returns the information associated with a connection
+
+ Arguments:
+
+ lpLocalName - local name associated with the connection
+
+ lpRemoteName - the remote name associated with the connection
+
+ lpBufferSize - the remote name buffer size
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ --*/
+{
+    DWORD Status, len;
+    ULONG CopyBytes;
+    WCHAR RemoteName[128];
+    WCHAR LocalName[3];
+
+    Status = WN_NOT_CONNECTED;
+
+    Log(("VBOXNP: NPGetConnection: Called\n" ));
+    Log(("VBOXNP: NPGetConnection: lpLocalName = %ls\n", lpLocalName));
+
+    if (lstrlen(lpLocalName) > 1)
+    {
+        if (lpLocalName[1] == L':')
+        {
+            CopyBytes = sizeof (RemoteName) - sizeof (WCHAR);
+            RemoteName[CopyBytes / sizeof (WCHAR)] = 0;
+            // LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpLocalName[0], 0 ) );
+            LocalName[0] = (WCHAR)toupper(lpLocalName[0]);
+            LocalName[1] = L':';
+            LocalName[2] = L'\0';
+            Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETCONN, LocalName, 3 * sizeof(WCHAR), (PVOID)RemoteName, &CopyBytes);
+            if (Status != NO_ERROR)
+            {
+                /* The device specified by lpLocalName is not redirected by this provider. */
+                Status = WN_NOT_CONNECTED;
+            }
+        }
+    }
+    if (Status == WN_SUCCESS)
+    {
+        if (CopyBytes > 0)
+        {
+            /* Return the local name (X:) instead of UNC path \\VBOXSVR\folder to prevent
+             * VBOXSVR name resolutions and therefore large delays.
+             */
+
+            Log(("VBOXNP: NPGetConnection: CopyBytes: %d, RemoteName: %ls\n", CopyBytes, RemoteName));
+
+            CopyBytes = (lstrlen (RemoteName) + 1) * sizeof (WCHAR); /* Including the trailing 0. */
+
+            len = sizeof(WCHAR) + CopyBytes; /* Including the leading '\'. */
+
+            if (*lpBufferSize >= len)
+            {
+                lpRemoteName[0] = L'\\';
+                CopyMemory( &lpRemoteName[1], RemoteName, CopyBytes );
+
+                Log(("VBOXNP: NPGetConnection: returning lpRemoteName: %ls\n", lpRemoteName));
+            }
+            else
+            {
+                if (*lpBufferSize != 0)
+                {
+                    /* Log only real errors. Do not log a 0 bytes try. */
+                    Log(("VBOXNP: NPGetConnection: Buffer overflow: *lpBufferSize = %d, len = %d\n", *lpBufferSize, len));
+                }
+
+                Status = WN_MORE_DATA;
+            }
+
+            *lpBufferSize = len;
+        }
+        else
+        {
+            Status = WN_NO_NETWORK;
+        }
+    }
+
+    if ((Status != WN_SUCCESS) &&
+        (Status != WN_MORE_DATA))
+    {
+        Log(("VBOXNP: NPGetConnection: Returned error 0x%lx\n", Status));
+    }
+
+    return Status;
+}
+
+static WCHAR vboxToUpper(WCHAR wc)
+{
+    /* The CharUpper parameter is a pointer to a null-terminated string,
+     * or specifies a single character. If the high-order word of this
+     * parameter is zero, the low-order word must contain a single character to be converted.
+     */
+    return (WCHAR)CharUpper((LPTSTR)wc);
+}
+
+static const WCHAR *vboxSkipServerPrefix(const WCHAR *lpRemoteName, const WCHAR *lpPrefix)
+{
+    while (*lpPrefix)
+    {
+        if (vboxToUpper(*lpPrefix) != vboxToUpper(*lpRemoteName))
+        {
+            /* Not a prefix */
+            return NULL;
+        }
+
+        lpPrefix++;
+        lpRemoteName++;
+    }
+
+    return lpRemoteName;
+}
+
+static const WCHAR *vboxSkipServerName(const WCHAR *lpRemoteName)
+{
+    int cLeadingBackslashes = 0;
+    while (*lpRemoteName == L'\\')
+    {
+        lpRemoteName++;
+        cLeadingBackslashes++;
+    }
+
+    if (cLeadingBackslashes == 0 || cLeadingBackslashes == 2)
+    {
+        const WCHAR *lpAfterPrefix = vboxSkipServerPrefix(lpRemoteName, MRX_VBOX_SERVER_NAME_U);
+
+        if (!lpAfterPrefix)
+        {
+            lpAfterPrefix = vboxSkipServerPrefix(lpRemoteName, MRX_VBOX_SERVER_NAME_ALT_U);
+        }
+
+        return lpAfterPrefix;
+    }
+
+    return NULL;
+}
+
+#define NEWENUM
+
+#ifdef NEWENUM
+/* Enumerate shared folders as hierarchy:
+ * VBOXSVR(container)
+ * +--------------------+
+ * |                     \
+ * Folder1(connectable)  FolderN(connectable)
+ */
+typedef struct _NPENUMCTX
+{
+    ULONG index; /* Index of last entry returned. */
+    DWORD dwScope;
+    DWORD dwOriginalScope;
+    DWORD dwType;
+    DWORD dwUsage;
+    bool fRoot;
+} NPENUMCTX;
+
+DWORD APIENTRY
+NPOpenEnum (DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCE lpNetResource, LPHANDLE lphEnum)
+/*++
+
+ Routine Description:
+
+ This routine opens a handle for enumeration of resources.
+
+ Arguments:
+
+ dwScope - the scope of enumeration (RESOURCE_CONNECTED, RESOURCE_GLOBALNET or RESOURCE_CONTEXT)
+
+ dwType  - the type of resources to be enumerated (RESOURCETYPE_DISK only supported)
+
+ dwUsage - the usage parameter (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER, or zero to match all the flags)
+
+ lpNetResource - pointer to the container to perform the enumeration.
+                 If dwScope is RESOURCE_CONNECTED or RESOURCE_CONTEXT, this parameter will be NULL.
+
+ lphEnum - aptr. for passing nack the enumeration handle
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ --*/
+{
+    DWORD Status;
+
+    Log(("VBOXNP: NPOpenEnum: dwScope 0x%08X, dwType 0x%08X, dwUsage 0x%08X, lpNetResource %p\n",
+         dwScope, dwType, dwUsage, lpNetResource));
+
+    if (dwUsage == 0)
+    {
+        /* The bitmask may be zero to match all of the flags. */
+        dwUsage = RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER;
+    }
+
+    *lphEnum = NULL;
+
+    /* Allocate the context structure. */
+    NPENUMCTX *pCtx = (NPENUMCTX *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NPENUMCTX));
+
+    if (pCtx == NULL)
+    {
+        Status = WN_OUT_OF_MEMORY;
+    }
+    else
+    {
+        if (lpNetResource && lpNetResource->lpRemoteName)
+        {
+            Log(("VBOXNP: NPOpenEnum: lpRemoteName %ls\n", lpNetResource->lpRemoteName));
+        }
+
+        switch (dwScope)
+        {
+            case 6: /* Advertised as WNNC_ENUM_SHAREABLE. This returns C$ system shares.
+                     * NpEnumResource will return NO_MORE_ENTRIES.
+                     */
+            {
+                if (lpNetResource == NULL || lpNetResource->lpRemoteName == NULL)
+                {
+                    /* If it is NULL or if the lpRemoteName field of the NETRESOURCE is NULL,
+                     * the provider should enumerate the top level of its network.
+                     * But system shares can't be on top level.
+                     */
+                    Status = WN_NOT_CONTAINER;
+                    break;
+                }
+
+                const WCHAR *lpAfterName = vboxSkipServerName(lpNetResource->lpRemoteName);
+                if (   lpAfterName == NULL
+                    || (*lpAfterName != L'\\' && *lpAfterName != 0))
+                {
+                    Status = WN_NOT_CONTAINER;
+                    break;
+                }
+
+                /* Valid server name. */
+
+                pCtx->index = 0;
+                pCtx->dwScope = 6;
+                pCtx->dwOriginalScope = dwScope;
+                pCtx->dwType = dwType;
+                pCtx->dwUsage = dwUsage;
+
+                Status = WN_SUCCESS;
+                break;
+            }
+            case RESOURCE_GLOBALNET: /* All resources on the network. */
+            {
+                if (lpNetResource == NULL || lpNetResource->lpRemoteName == NULL)
+                {
+                    /* If it is NULL or if the lpRemoteName field of the NETRESOURCE is NULL,
+                     * the provider should enumerate the top level of its network.
+                     */
+                    pCtx->fRoot = true;
+                }
+                else
+                {
+                    /* Enumerate lpNetResource->lpRemoteName container, which can be only the VBOXSVR container. */
+                    const WCHAR *lpAfterName = vboxSkipServerName(lpNetResource->lpRemoteName);
+                    if (   lpAfterName == NULL
+                        || (*lpAfterName != L'\\' && *lpAfterName != 0))
+                    {
+                        Status = WN_NOT_CONTAINER;
+                        break;
+                    }
+
+                    /* Valid server name. */
+                    pCtx->fRoot = false;
+                }
+
+                pCtx->index = 0;
+                pCtx->dwScope = RESOURCE_GLOBALNET;
+                pCtx->dwOriginalScope = dwScope;
+                pCtx->dwType = dwType;
+                pCtx->dwUsage = dwUsage;
+
+                Status = WN_SUCCESS;
+                break;
+            }
+
+            case RESOURCE_CONNECTED: /* All currently connected resources. */
+            case RESOURCE_CONTEXT: /* The interpretation of this is left to the provider. Treat this as RESOURCE_GLOBALNET. */
+            {
+                pCtx->index = 0;
+                pCtx->dwScope = RESOURCE_CONNECTED;
+                pCtx->dwOriginalScope = dwScope;
+                pCtx->dwType = dwType;
+                pCtx->dwUsage = dwUsage;
+                pCtx->fRoot = false; /* Actually ignored for RESOURCE_CONNECTED. */
+
+                Status = WN_SUCCESS;
+                break;
+            }
+
+            default:
+                Log(("VBOXNP: NPOpenEnum: unsupported scope 0x%lx\n", dwScope));
+                Status = WN_NOT_SUPPORTED;
+                break;
+        }
+    }
+
+    if (Status != WN_SUCCESS)
+    {
+        Log(("VBOXNP: NPOpenEnum: Returned error 0x%lx\n", Status));
+        if (pCtx)
+        {
+            HeapFree(GetProcessHeap(), 0, pCtx);
+        }
+    }
+    else
+    {
+        Log(("VBOXNP: NPOpenEnum: pCtx %p\n", pCtx));
+        *lphEnum = pCtx;
+    }
+
+    return (Status);
+}
+
+DWORD APIENTRY
+NPEnumResource (HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
+/*++
+
+ Routine Description:
+
+ This routine uses the handle obtained by a call to NPOpenEnum for
+ enuerating the connected shares
+
+ Arguments:
+
+ hEnum  - the enumeration handle
+
+ lpcCount - the number of resources requested/returned
+
+ lpBuffer - the buffer for passing back the NETRESOURCE entries
+
+ lpBufferSize - the size of the buffer
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ WN_NO_MORE_ENTRIES - if the enumeration has exhausted the entries
+
+ WN_MORE_DATA - if more data is available
+
+ --*/
+{
+    DWORD Status = WN_SUCCESS;
+    NPENUMCTX *pCtx = (NPENUMCTX *)hEnum;
+
+    BYTE ConnectionList[26];
+    ULONG CopyBytes;
+    WCHAR LocalName[3];
+    WCHAR RemoteName[128];
+
+    ULONG SpaceNeeded;
+
+    Log(("VBOXNP: NPEnumResource: hEnum %p, lpcCount %p, lpBuffer %p, lpBufferSize %p.\n",
+         hEnum, lpcCount, lpBuffer, lpBufferSize));
+
+    if (pCtx == NULL)
+    {
+        Log(("VBOXNP: NPEnumResource: WN_BAD_HANDLE\n"));
+        return WN_BAD_HANDLE;
+    }
+
+    if (lpcCount == NULL || lpBuffer == NULL)
+    {
+        Log(("VBOXNP: NPEnumResource: WN_BAD_VALUE\n"));
+        return WN_BAD_VALUE;
+    }
+
+    Log(("VBOXNP: NPEnumResource: *lpcCount 0x%x, *lpBufferSize 0x%x, pCtx->index %d\n",
+         *lpcCount, *lpBufferSize, pCtx->index));
+
+    LPNETRESOURCE pNetResource = (LPNETRESOURCE)lpBuffer;
+    ULONG SpaceAvailable = *lpBufferSize;
+    ULONG EntriesCopied = 0;
+    PWCHAR StringZone = (PWCHAR)((PBYTE)lpBuffer + *lpBufferSize);
+
+    if (pCtx->dwScope == RESOURCE_CONNECTED)
+    {
+        Log(("VBOXNP: NPEnumResource: RESOURCE_CONNECTED\n"));
+
+        memset (ConnectionList, 0, sizeof (ConnectionList));
+        CopyBytes = sizeof(ConnectionList);
+        Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETLIST, NULL, 0, ConnectionList, &CopyBytes);
+
+        if (Status == WN_SUCCESS && CopyBytes > 0)
+        {
+            while (EntriesCopied < *lpcCount && pCtx->index < RTL_NUMBER_OF(ConnectionList))
+            {
+                if (ConnectionList[pCtx->index])
+                {
+                    LocalName[0] = L'A' + (WCHAR)pCtx->index;
+                    LocalName[1] = L':';
+                    LocalName[2] = L'\0';
+                    memset (RemoteName, 0, sizeof (RemoteName));
+                    CopyBytes = sizeof(RemoteName);
+                    Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETCONN, LocalName, sizeof(LocalName), RemoteName, &CopyBytes);
+
+                    if (Status != WN_SUCCESS || CopyBytes == 0)
+                    {
+                        Status = WN_NO_MORE_ENTRIES;
+                        break;
+                    }
+
+                    // Determine the space needed for this entry...
+                    SpaceNeeded = sizeof(NETRESOURCE); // resource struct
+                    SpaceNeeded += 3 * sizeof(WCHAR); // local name
+                    SpaceNeeded += 2 * sizeof(WCHAR) + CopyBytes; // remote name: \ + name + 0
+                    SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); // provider name
+
+                    if (SpaceNeeded > SpaceAvailable)
+                    {
+                        break;
+                    }
+
+                    SpaceAvailable -= SpaceNeeded;
+
+                    pNetResource->dwScope = RESOURCE_CONNECTED;
+                    pNetResource->dwType = RESOURCETYPE_DISK;
+                    pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+                    pNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
+
+                    // setup string area at opposite end of buffer
+                    SpaceNeeded -= sizeof(NETRESOURCE);
+                    StringZone = (PWCHAR)((PBYTE)StringZone - SpaceNeeded);
+                    PWCHAR NewStringZone = StringZone;
+                    // copy local name
+                    pNetResource->lpLocalName = StringZone;
+                    *StringZone++ = L'A' + (WCHAR)pCtx->index;
+                    *StringZone++ = L':';
+                    *StringZone++ = L'\0';
+                    // copy remote name
+                    pNetResource->lpRemoteName = StringZone;
+                    *StringZone++ = L'\\';
+                    CopyMemory( StringZone, RemoteName, CopyBytes );
+                    StringZone += CopyBytes / sizeof(WCHAR);
+                    *StringZone++ = L'\0';
+                    // copy comment
+                    pNetResource->lpComment = 0;
+                    // copy provider name
+                    pNetResource->lpProvider = StringZone;
+                    CopyMemory(StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof (MRX_VBOX_PROVIDER_NAME_U));
+
+                    EntriesCopied++;
+
+                    // set new bottom of string zone
+                    StringZone = NewStringZone;
+                    Log(("VBOXNP: NPEnumResource: lpRemoteName: %ls\n", pNetResource->lpRemoteName));
+
+                    pNetResource++;
+                }
+
+                pCtx->index++;
+            }
+        }
+        else
+        {
+            Status = WN_NO_MORE_ENTRIES;
+        }
+    }
+    else if (pCtx->dwScope == RESOURCE_GLOBALNET)
+    {
+        Log(("VBOXNP: NPEnumResource: RESOURCE_GLOBALNET: root %d\n", pCtx->fRoot));
+
+        if (pCtx->fRoot)
+        {
+            /* VBOXSVR container. */
+            if (pCtx->index > 0)
+            {
+                Status = WN_NO_MORE_ENTRIES;
+            }
+            else
+            {
+                /* Return VBOXSVR server.
+                 * Determine the space needed for this entry.
+                 */
+                SpaceNeeded = sizeof(NETRESOURCE);
+                SpaceNeeded += 2 * sizeof(WCHAR) + sizeof(MRX_VBOX_SERVER_NAME_U); /* \\ + server name */
+                SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* provider name */
+
+                if (SpaceNeeded > SpaceAvailable)
+                {
+                    /* Do nothing. */
+                }
+                else
+                {
+                    SpaceAvailable -= SpaceNeeded;
+
+                    memset (pNetResource, 0, sizeof (*pNetResource));
+
+                    pNetResource->dwScope = RESOURCE_GLOBALNET;
+                    pNetResource->dwType = RESOURCETYPE_ANY;
+                    pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
+                    pNetResource->dwUsage = RESOURCEUSAGE_CONTAINER;
+
+                    // setup string area at opposite end of buffer
+                    SpaceNeeded -= sizeof(NETRESOURCE);
+                    StringZone = (PWCHAR)((PBYTE)StringZone - SpaceNeeded);
+                    // local name
+                    pNetResource->lpLocalName = 0;
+                    // remote name
+                    pNetResource->lpRemoteName = StringZone;
+                    *StringZone++ = L'\\';
+                    *StringZone++ = L'\\';
+                    CopyMemory( StringZone, MRX_VBOX_SERVER_NAME_U, sizeof(MRX_VBOX_SERVER_NAME_U) );
+                    StringZone += sizeof(MRX_VBOX_SERVER_NAME_U) / sizeof(WCHAR);
+                    // comment
+                    pNetResource->lpComment = 0;
+                    // provider name
+                    pNetResource->lpProvider = StringZone;
+                    CopyMemory(StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof (MRX_VBOX_PROVIDER_NAME_U));
+
+                    EntriesCopied++;
+
+                    pCtx->index++;
+                }
+            }
+        }
+        else
+        {
+            /* Shares of VBOXSVR. */
+            memset (ConnectionList, 0, sizeof (ConnectionList));
+            CopyBytes = sizeof(ConnectionList);
+            Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETGLOBALLIST, NULL, 0, ConnectionList, &CopyBytes);
+
+            if (Status == WN_SUCCESS && CopyBytes > 0)
+            {
+                while (EntriesCopied < *lpcCount && pCtx->index < RTL_NUMBER_OF(ConnectionList))
+                {
+                    if (ConnectionList[pCtx->index])
+                    {
+                        memset (RemoteName, 0, sizeof (RemoteName));
+                        CopyBytes = sizeof(RemoteName);
+                        Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETGLOBALCONN, &ConnectionList[pCtx->index], sizeof(ConnectionList[pCtx->index]), RemoteName, &CopyBytes);
+
+                        if (Status != WN_SUCCESS || CopyBytes == 0)
+                        {
+                            Status = WN_NO_MORE_ENTRIES;
+                            break;
+                        }
+
+                        // Determine the space needed for this entry...
+                        SpaceNeeded = sizeof(NETRESOURCE); // resource struct
+                        SpaceNeeded += 3 * sizeof(WCHAR) + sizeof(MRX_VBOX_SERVER_NAME_U) + CopyBytes; /* remote name: \\ + vboxsvr + \ + name + 0. */
+                        SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); // provider name
+
+                        if (SpaceNeeded > SpaceAvailable)
+                        {
+                            break;
+                        }
+
+                        SpaceAvailable -= SpaceNeeded;
+
+                        pNetResource->dwScope = pCtx->dwOriginalScope;
+                        pNetResource->dwType = RESOURCETYPE_DISK;
+                        pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+                        pNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
+
+                        // setup string area at opposite end of buffer
+                        SpaceNeeded -= sizeof(NETRESOURCE);
+                        StringZone = (PWCHAR)((PBYTE)StringZone - SpaceNeeded);
+                        PWCHAR NewStringZone = StringZone;
+                        // copy local name
+                        pNetResource->lpLocalName = 0;
+                        // copy remote name
+                        pNetResource->lpRemoteName = StringZone;
+                        *StringZone++ = L'\\';
+                        *StringZone++ = L'\\';
+                        lstrcpy(StringZone, MRX_VBOX_SERVER_NAME_U );
+                        StringZone += sizeof(MRX_VBOX_SERVER_NAME_U) / sizeof(WCHAR) - 1;
+                        *StringZone++ = L'\\';
+                        CopyMemory( StringZone, RemoteName, CopyBytes );
+                        StringZone += CopyBytes / sizeof(WCHAR);
+                        *StringZone++ = L'\0';
+                        // copy comment
+                        pNetResource->lpComment = 0;
+                        // copy provider name
+                        pNetResource->lpProvider = StringZone;
+                        CopyMemory(StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof (MRX_VBOX_PROVIDER_NAME_U));
+
+                        EntriesCopied++;
+
+                        // set new bottom of string zone
+                        StringZone = NewStringZone;
+                        Log(("VBOXNP: NPEnumResource: lpRemoteName: %ls\n", pNetResource->lpRemoteName));
+
+                        pNetResource++;
+                    }
+
+                    pCtx->index++;
+                }
+            }
+            else
+            {
+                Status = WN_NO_MORE_ENTRIES;
+            }
+        }
+    }
+    else if (pCtx->dwScope == 6)
+    {
+        Log(("VBOXNP: NPEnumResource: dwScope 6\n"));
+        Status = WN_NO_MORE_ENTRIES;
+    }
+    else
+    {
+        Log(("VBOXNP: NPEnumResource: invalid dwScope 0x%x\n", pCtx->dwScope));
+        return WN_BAD_HANDLE;
+    }
+
+    *lpcCount = EntriesCopied;
+
+    if (EntriesCopied == 0 && Status == WN_SUCCESS)
+    {
+        if (pCtx->index >= RTL_NUMBER_OF(ConnectionList))
+        {
+            Status = WN_NO_MORE_ENTRIES;
+        }
+        else
+        {
+            Log(("VBOXNP: NPEnumResource: More Data Needed - %d\n", SpaceNeeded));
+            *lpBufferSize = SpaceNeeded;
+            Status = WN_MORE_DATA;
+        }
+    }
+
+    Log(("VBOXNP: NPEnumResource: Entries returned - %d, Status %d\n", EntriesCopied, Status));
+    return Status;
+}
+DWORD APIENTRY
+NPCloseEnum (HANDLE hEnum)
+/*++
+
+ Routine Description:
+
+ This routine closes the handle for enumeration of resources.
+
+ Arguments:
+
+ hEnum  - the enumeration handle
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ --*/
+{
+    DWORD Status = WN_SUCCESS;
+    NPENUMCTX *pCtx = (NPENUMCTX *)hEnum;
+
+    Log(("VBOXNP: NPCloseEnum: hEnum %p\n", hEnum));
+
+    if (pCtx)
+    {
+        HeapFree(GetProcessHeap(), 0, pCtx);
+    }
+
+    Log(("VBOXNP: NPCloseEnum: returns\n"));
+    return WN_SUCCESS;
+}
+#else
+DWORD APIENTRY
+NPOpenEnum (DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCE lpNetResource, LPHANDLE lphEnum)
+/*++
+
+ Routine Description:
+
+ This routine opens a handle for enumeration of resources. The only capability
+ implemented in the sample is for enumerating connected shares
+
+ Arguments:
+
+ dwScope - the scope of enumeration
+
+ dwType  - the type of resources to be enumerated
+
+ dwUsage - the usage parameter
+
+ lpNetResource - a pointer to the desired NETRESOURCE struct.
+
+ lphEnum - aptr. for passing nack the enumeration handle
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ The sample only supports the notion of enumerating connected shares
+
+ The handle passed back is merely the index of the last entry returned
+
+ --*/
+{
+    DWORD Status;
+
+    Log(("VBOXNP: NPOpenEnum: Called.\n"));
+
+    *lphEnum = NULL;
+
+    switch (dwScope)
+    {
+    case RESOURCE_GLOBALNET:
+    case RESOURCE_CONNECTED:
+    {
+        DWORD *lpdwEnum = NULL;
+        lpdwEnum = (DWORD *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DWORD) * 2);
+
+        if (lpdwEnum != NULL)
+        {
+            lpdwEnum[0] = 0;
+            lpdwEnum[1] = dwScope;
+            *lphEnum = lpdwEnum;
+
+            Status = WN_SUCCESS;
+        }
+        else
+        {
+            Status = WN_OUT_OF_MEMORY;
+        }
+        break;
+    }
+        break;
+
+    case RESOURCE_CONTEXT:
+    default:
+        Status = WN_NOT_SUPPORTED;
+        break;
+    }
+
+    if (Status != WN_SUCCESS)
+        Log(("VBOXNP: NPOpenEnum: Returned error 0x%lx\n", Status));
+
+    return (Status);
+}
+
+DWORD APIENTRY
+NPEnumResource (HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
+/*++
+
+ Routine Description:
+
+ This routine uses the handle obtained by a call to NPOpenEnum for
+ enuerating the connected shares
+
+ Arguments:
+
+ hEnum  - the enumeration handle
+
+ lpcCount - the number of resources returned
+
+ lpBuffer - the buffere for passing back the entries
+
+ lpBufferSize - the size of the buffer
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ WN_NO_MORE_ENTRIES - if the enumeration has exhausted the entries
+
+ WN_MORE_DATA - if nmore data is available
+
+ Notes:
+
+ The sample only supports the notion of enumerating connected shares
+
+ The handle passed back is merely the index of the last entry returned
+
+ --*/
+{
+    DWORD Status = WN_SUCCESS;
+    BYTE byConnectionList[26];
+    ULONG CopyBytes;
+    ULONG EntriesCopied;
+    ULONG i;
+    LPNETRESOURCE pNetResource;
+    ULONG SpaceNeeded;
+    ULONG SpaceAvailable;
+    WCHAR wzLocalName[3];
+    WCHAR wzRemoteName[128];
+    PWCHAR pwcStringZone;
+    DWORD dwScope = 0;
+
+    Log(("VBOXNP: NPEnumResource: Called.\n"));
+
+    if ((lpcCount == NULL) || (lpBufferSize == NULL) || (lpBuffer == NULL))
+    {
+        Log(("VBOXNP: NPEnumResource: Has invalid parameter(s)!\n"));
+        return WN_NO_MORE_ENTRIES;
+    }
+
+    if (hEnum != NULL)
+        dwScope = ((DWORD*)hEnum)[1];
+
+    Log(("VBOXNP: NPEnumResource: Count Requested %d\n", *lpcCount));
+    Log(("VBOXNP: NPEnumResource: Scope %ld\n", dwScope));
+
+    pNetResource = (LPNETRESOURCE)lpBuffer;
+    SpaceAvailable = *lpBufferSize;
+    EntriesCopied = 0;
+    pwcStringZone = (PWCHAR)((PBYTE)lpBuffer + *lpBufferSize);
+
+    /*
+     * Returns the already connected resources of each driver letter (A-Z).
+     */
+    if (dwScope == RESOURCE_CONNECTED)
+    {
+        Log(("VBOXNP: NPEnumResource: Scope = Resource connected.\n"));
+
+        CopyBytes = 26;
+        Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETLIST, NULL, 0, (PVOID)byConnectionList, &CopyBytes);
+
+        if (Status == WN_SUCCESS && CopyBytes > 0)
+        {
+            for (i = *((PULONG)hEnum); EntriesCopied < *lpcCount, i < 26; i++)
+            {
+                if (byConnectionList[i])
+                {
+                    CopyBytes = 128;
+                    wzLocalName[0] = L'A' + (WCHAR)i;
+                    wzLocalName[1] = L':';
+                    wzLocalName[2] = L'\0';
+                    Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETCONN, wzLocalName, 3 * sizeof(WCHAR), (PVOID)wzRemoteName, &CopyBytes);
+
+                    // if something strange happended then just say there are no more entries
+                    if (Status != WN_SUCCESS || CopyBytes == 0)
+                    {
+                        Status = WN_NO_MORE_ENTRIES;
+                        break;
+                    }
+                    // Determine the space needed for this entry...
+
+                    SpaceNeeded = sizeof(NETRESOURCE); // resource struct
+                    SpaceNeeded += 3 * sizeof(WCHAR); // local name
+                    SpaceNeeded += 2 * sizeof(WCHAR) + CopyBytes; // remote name
+                    SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); // provider name
+
+                    if (SpaceNeeded > SpaceAvailable)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        SpaceAvailable -= SpaceNeeded;
+
+                        pNetResource->dwScope = RESOURCE_CONNECTED;
+                        pNetResource->dwType = RESOURCETYPE_DISK;
+                        pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+                        pNetResource->dwUsage = 0;
+
+                        // setup string area at opposite end of buffer
+                        SpaceNeeded -= sizeof(NETRESOURCE);
+                        pwcStringZone = (PWCHAR)((PBYTE)pwcStringZone - SpaceNeeded);
+                        // copy local name
+                        pNetResource->lpLocalName = pwcStringZone;
+                        *pwcStringZone++ = L'A' + (WCHAR)i;
+                        *pwcStringZone++ = L':';
+                        *pwcStringZone++ = L'\0';
+                        // copy remote name
+                        pNetResource->lpRemoteName = pwcStringZone;
+                        *pwcStringZone++ = L'\\';
+                        CopyMemory( pwcStringZone, wzRemoteName, CopyBytes );
+                        pwcStringZone += CopyBytes / sizeof(WCHAR);
+                        *pwcStringZone++ = L'\0';
+                        // copy comment
+                        pNetResource->lpComment = 0;
+                        // copy provider name
+                        pNetResource->lpProvider = pwcStringZone;
+                        lstrcpy(pwcStringZone, MRX_VBOX_PROVIDER_NAME_U );
+
+                        EntriesCopied++;
+                        // set new bottom of string zone
+                        pwcStringZone = (PWCHAR)((PBYTE)pwcStringZone - SpaceNeeded);
+                    }
+                    pNetResource++;
+                }
+            }
+        }
+        else
+        {
+            Status = WN_NO_MORE_ENTRIES;
+        }
+    }
+    else if (dwScope == RESOURCE_GLOBALNET)
+    {
+        Log(("VBOXNP: NPEnumResource: Scope =  Resource global net.\n"));
+
+        CopyBytes = 26;
+        Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETGLOBALLIST, NULL, 0, (PVOID)byConnectionList, &CopyBytes);
+
+        if (Status == WN_SUCCESS && CopyBytes > 0)
+        {
+            for (i = *((PULONG)hEnum); EntriesCopied < *lpcCount, i < 26; i++)
+            {
+                if (byConnectionList[i])
+                {
+                    CopyBytes = 128;
+
+                    Status = SendToMiniRdr(IOCTL_MRX_VBOX_GETGLOBALCONN, &byConnectionList[i], sizeof(byConnectionList[i]), (PVOID)wzRemoteName, &CopyBytes);
+
+                    // if something strange happended then just say there are no more entries
+                    if (Status != WN_SUCCESS || CopyBytes == 0)
+                    {
+                        Status = WN_NO_MORE_ENTRIES;
+                        break;
+                    }
+                    // Determine the space needed for this entry...
+
+                    SpaceNeeded = sizeof(NETRESOURCE); // resource struct
+                    SpaceNeeded += 11 * sizeof(WCHAR) + CopyBytes; // remote name
+                    SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); // provider name
+
+                    if (SpaceNeeded > SpaceAvailable)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        SpaceAvailable -= SpaceNeeded;
+
+                        pNetResource->dwScope = RESOURCE_GLOBALNET;
+                        pNetResource->dwType = RESOURCETYPE_DISK;
+                        pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+                        pNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
+
+                        // setup string area at opposite end of buffer
+                        SpaceNeeded -= sizeof(NETRESOURCE);
+                        pwcStringZone = (PWCHAR)((PBYTE)pwcStringZone - SpaceNeeded);
+                        // copy local name
+                        pNetResource->lpLocalName = 0;
+                        // copy remote name
+                        pNetResource->lpRemoteName = pwcStringZone;
+                        *pwcStringZone++ = L'\\';
+                        *pwcStringZone++ = L'\\';
+                        *pwcStringZone++ = L'V';
+                        *pwcStringZone++ = L'B';
+                        *pwcStringZone++ = L'O';
+                        *pwcStringZone++ = L'X';
+                        *pwcStringZone++ = L'S';
+                        *pwcStringZone++ = L'V';
+                        *pwcStringZone++ = L'R';
+                        *pwcStringZone++ = L'\\';
+                        CopyMemory( pwcStringZone, wzRemoteName, CopyBytes );
+                        pwcStringZone += CopyBytes / sizeof(WCHAR);
+                        *pwcStringZone++ = L'\0';
+                        // copy comment
+                        pNetResource->lpComment = 0;
+                        // copy provider name
+                        pNetResource->lpProvider = pwcStringZone;
+                        lstrcpy(pwcStringZone, MRX_VBOX_PROVIDER_NAME_U );
+
+                        EntriesCopied++;
+                        // set new bottom of string zone
+                        pwcStringZone = (PWCHAR)((PBYTE)pwcStringZone - SpaceNeeded);
+                        Log(("VBOXNP: NPEnumResource: StringZone: %ls\n", pwcStringZone));
+                    }
+                    pNetResource++;
+                }
+            }
+        }
+        else
+        {
+            Status = WN_NO_MORE_ENTRIES;
+        }
+    }
+    else return WN_NO_MORE_ENTRIES;
+
+    *lpcCount = EntriesCopied;
+    if (EntriesCopied == 0 && Status == WN_SUCCESS)
+    {
+        if (i > 25)
+        {
+            Status = WN_NO_MORE_ENTRIES;
+        }
+        else
+        {
+            Log(("VBOXNP: NPEnumResource: More Data Needed - %d\n", SpaceNeeded));
+            Status = WN_MORE_DATA;
+            *lpBufferSize = SpaceNeeded;
+        }
+    }
+    // update entry index
+    *(PULONG)hEnum = i;
+
+    Log(("VBOXNP: NPEnumResource: Entries returned - %d\n", EntriesCopied));
+
+    return Status;
+}
+
+DWORD APIENTRY
+NPCloseEnum (HANDLE hEnum)
+/*++
+
+ Routine Description:
+
+ This routine closes the handle for enumeration of resources.
+
+ Arguments:
+
+ hEnum  - the enumeration handle
+
+ Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+ Notes:
+
+ The sample only supports the notion of enumerating connected shares
+
+ --*/
+{
+    Log(("VBOXNP: NPCloseEnum: Called.\n"));
+
+    if (NULL != (PVOID)hEnum)
+        HeapFree(GetProcessHeap(), 0, (PVOID)hEnum);
+
+    Log(("VBOXNP: NPCloseEnum: Memory freed.\n"));
+    return WN_SUCCESS;
+}
+#endif
+
+DWORD APIENTRY
+NPGetResourceParent (LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize)
+/*++
+
+ Routine Description:
+
+ This routine returns the information about net resource parent
+
+ Arguments:
+
+ lpNetResource - the NETRESOURCE struct
+
+ lpBuffer - the buffer for passing back the parent information
+
+ lpBufferSize - the buffer size
+
+ Return Value:
+
+ Notes:
+
+ --*/
+{
+    Log(("VBOXNP: NPGetResourceParent: lpNetResource %p, lpBuffer %p, lpBufferSize %p\n",
+         lpNetResource, lpBuffer, lpBufferSize));
+    /* Contruct a new NETRESOURCE which is syntactically a parent of lpNetResource,
+     * then call NPGetResourceInformation to actually fill the buffer.
+     */
+    if (!lpNetResource || !lpNetResource->lpRemoteName || !lpBufferSize)
+    {
+        return WN_BAD_NETNAME;
+    }
+
+    const WCHAR *lpAfterName = vboxSkipServerName(lpNetResource->lpRemoteName);
+    if (   lpAfterName == NULL
+        || (*lpAfterName != L'\\' && *lpAfterName != 0))
+    {
+        Log(("VBOXNP: NPGetResourceParent: WN_BAD_NETNAME\n"));
+        return WN_BAD_NETNAME;
+    }
+
+    DWORD RemoteNameLength = lstrlen(lpNetResource->lpRemoteName);
+
+    DWORD SpaceNeeded = sizeof (NETRESOURCE);
+    SpaceNeeded += (RemoteNameLength + 1) * sizeof (WCHAR);
+
+    NETRESOURCE *pParent = (NETRESOURCE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SpaceNeeded);
+
+    if (!pParent)
+    {
+        return WN_OUT_OF_MEMORY;
+    }
+
+    pParent->lpRemoteName = (WCHAR *)((PBYTE)pParent + sizeof (NETRESOURCE));
+    lstrcpy(pParent->lpRemoteName, lpNetResource->lpRemoteName);
+
+    /* Remove last path component of the pParent->lpRemoteName. */
+    WCHAR *pLastSlash = pParent->lpRemoteName + RemoteNameLength;
+    if (*pLastSlash == L'\\')
+    {
+        /* \\server\share\path\, skip last slash immediately. */
+        pLastSlash--;
+    }
+
+    while (pLastSlash != pParent->lpRemoteName)
+    {
+        if (*pLastSlash == L'\\')
+        {
+            break;
+        }
+
+        pLastSlash--;
+    }
+
+    DWORD Status = WN_SUCCESS;
+
+    if (   pLastSlash == pParent->lpRemoteName
+        || pLastSlash == pParent->lpRemoteName + 1)
+    {
+        /* It is a leading backslash. Construct "no parent" NETRESOURCE. */
+        NETRESOURCE *pNetResource = (NETRESOURCE *)lpBuffer;
+
+        SpaceNeeded = sizeof(NETRESOURCE);
+        SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* remote name */
+        SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* provider name */
+
+        if (SpaceNeeded > *lpBufferSize)
+        {
+            Log(("VBOXNP: NPGetResourceParent: WN_MORE_DATA 0x%x\n", SpaceNeeded));
+            *lpBufferSize = SpaceNeeded;
+            Status = WN_MORE_DATA;
+        }
+        else
+        {
+            memset (pNetResource, 0, sizeof (*pNetResource));
+
+            pNetResource->dwType = RESOURCETYPE_ANY;
+            pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
+            pNetResource->dwUsage = RESOURCEUSAGE_CONTAINER;
+
+            /* Setup string area at opposite end of buffer. */
+            WCHAR *StringZone = (WCHAR *)((PBYTE)lpBuffer + *lpBufferSize);
+            StringZone = (PWCHAR)((PBYTE)StringZone - (SpaceNeeded - sizeof(NETRESOURCE)));
+
+            pNetResource->lpRemoteName = StringZone;
+            CopyMemory (StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof(MRX_VBOX_PROVIDER_NAME_U));
+            StringZone += sizeof(MRX_VBOX_PROVIDER_NAME_U) / sizeof(WCHAR);
+
+            /* Provider. */
+            pNetResource->lpProvider = StringZone;
+            CopyMemory (StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof(MRX_VBOX_PROVIDER_NAME_U));
+            StringZone += sizeof(MRX_VBOX_PROVIDER_NAME_U) / sizeof(WCHAR);
+
+            Log(("VBOXNP: NPGetResourceParent: no parent, strings %p/%p\n",
+                 StringZone, (PBYTE)lpBuffer + *lpBufferSize));
+        }
+    }
+    else
+    {
+        /* Make the parent remote name and get its information. */
+        *pLastSlash = 0;
+
+        LPWSTR lpSystem = NULL;
+        Status = NPGetResourceInformation (pParent, lpBuffer, lpBufferSize, &lpSystem);
+    }
+
+    if (pParent)
+    {
+        HeapFree(GetProcessHeap(), 0, pParent);
+    }
+    return Status;
+}
+
+DWORD APIENTRY
+NPGetResourceInformation (LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize, LPWSTR *lplpSystem)
+/*
+
+ Routine Description:
+
+ Separates the part of a network resource accessed through the WNet API from the part accessed
+ through APIs specific to the resource type.
+
+ Arguments:
+
+ lpNetResource - network resource for which information is required.
+                 The lpRemoteName field specifies the remote name of the resource.
+
+ lpBuffer - a single NETRESOURCE structure and associated strings. The lpRemoteName field should be
+            returned in the same format as that returned from an enumeration by the NPEnumResource
+            function, so that the caller can perform a case-sensitive string comparison.
+
+ lpBufferSize - the buffer size. If the buffer is too small for the result, the function places the
+                required buffer size at this location and returns the error WN_MORE_DATA.
+
+ lplpSystem - On a successful return, a pointer to a null-terminated string in the output buffer
+              specifying that part of the resource that is accessed through system APIs specific
+              to the resource type, rather than through the WNet API. If there is no such part,
+              lplpSystem is set to NULL.
+
+ */
+{
+    Log(("VBOXNP: NPGetResourceInformation: lpNetResource %p, lpBuffer %p, lpBufferSize %p, lplpSystem %p\n",
+         lpNetResource, lpBuffer, lpBufferSize, lplpSystem));
+
+    if (   lpNetResource == NULL
+        || lpNetResource->lpRemoteName == NULL
+        || lpBufferSize == NULL)
+    {
+        Log(("VBOXNP: NPGetResourceInformation: WN_BAD_VALUE\n"));
+        return WN_BAD_VALUE;
+    }
+
+    Log(("VBOXNP: NPGetResourceInformation: lpRemoteName %ls, *lpBufferSize 0x%x\n",
+         lpNetResource->lpRemoteName, *lpBufferSize));
+
+    const WCHAR *lpAfterName = vboxSkipServerName(lpNetResource->lpRemoteName);
+    if (   lpAfterName == NULL
+        || (*lpAfterName != L'\\' && *lpAfterName != 0))
+    {
+        Log(("VBOXNP: NPGetResourceInformation: WN_BAD_NETNAME\n"));
+        return WN_BAD_NETNAME;
+    }
+
+    if (lpNetResource->dwType != 0 && lpNetResource->dwType != RESOURCETYPE_DISK)
+    {
+        /* The caller passed in a nonzero dwType that does not match
+         * the actual type of the network resource.
+         */
+        return WN_BAD_DEV_TYPE;
+    }
+
+    /*
+     * If the input remote resource name was "\\server\share\dir1\dir2",
+     * then the output NETRESOURCE contains information about the resource "\\server\share".
+     * The lpRemoteName, lpProvider, dwType, dwDisplayType, and dwUsage fields are returned
+     * containing values, all other fields being set to NULL.
+     */
+    DWORD SpaceNeeded;
+    WCHAR *StringZone = (WCHAR *)((PBYTE)lpBuffer + *lpBufferSize);
+    NETRESOURCE *pNetResource = (NETRESOURCE *)lpBuffer;
+
+    /* Check what kind of the resource is that by parsing path components.
+     * lpAfterName points to first WCHAR after a valid server name.
+     */
+
+    if (lpAfterName[0] == 0 || lpAfterName[1] == 0)
+    {
+        /* "\\VBOXSVR" or "\\VBOXSVR\" */
+        SpaceNeeded = sizeof(NETRESOURCE);
+        SpaceNeeded += 2 * sizeof(WCHAR) + sizeof(MRX_VBOX_SERVER_NAME_U); /* \\ + server name */
+        SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* provider name */
+
+        if (SpaceNeeded > *lpBufferSize)
+        {
+            Log(("VBOXNP: NPGetResourceInformation: WN_MORE_DATA 0x%x\n", SpaceNeeded));
+            *lpBufferSize = SpaceNeeded;
+            return WN_MORE_DATA;
+        }
+
+        memset (pNetResource, 0, sizeof (*pNetResource));
+
+        pNetResource->dwType = RESOURCETYPE_ANY;
+        pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
+        pNetResource->dwUsage = RESOURCEUSAGE_CONTAINER;
+
+        /* Setup string area at opposite end of buffer. */
+        StringZone = (PWCHAR)((PBYTE)StringZone - (SpaceNeeded - sizeof(NETRESOURCE)));
+
+        /* The remote name is the server. */
+        pNetResource->lpRemoteName = StringZone;
+        *StringZone++ = L'\\';
+        *StringZone++ = L'\\';
+        CopyMemory (StringZone, MRX_VBOX_SERVER_NAME_U, sizeof(MRX_VBOX_SERVER_NAME_U));
+        StringZone += sizeof(MRX_VBOX_SERVER_NAME_U) / sizeof(WCHAR);
+
+        /* Provider. */
+        pNetResource->lpProvider = StringZone;
+        CopyMemory (StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof(MRX_VBOX_PROVIDER_NAME_U));
+        StringZone += sizeof(MRX_VBOX_PROVIDER_NAME_U) / sizeof(WCHAR);
+
+        Log(("VBOXNP: NPGetResourceInformation: lpRemoteName: %ls, strings %p/%p\n",
+             pNetResource->lpRemoteName, StringZone, (PBYTE)lpBuffer + *lpBufferSize));
+
+        if (lplpSystem)
+        {
+            *lplpSystem = NULL;
+        }
+        return WN_SUCCESS;
+    }
+
+    /* *lpAfterName == L'\\', could be share or share + path.
+     * Check if there are more path components after the share name.
+     */
+    const WCHAR *lp = lpAfterName + 1;
+    while (*lp && *lp != L'\\')
+    {
+        lp++;
+    }
+
+    if (*lp == 0)
+    {
+        /* It is a share only: \\vboxsvr\share */
+        SpaceNeeded = sizeof(NETRESOURCE);
+        SpaceNeeded += 2 * sizeof(WCHAR) + sizeof(MRX_VBOX_SERVER_NAME_U); /* \\ + server name with trailing nul */
+        SpaceNeeded += (lp - lpAfterName) * sizeof(WCHAR); /* The share name with leading \\ */
+        SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* provider name */
+
+        if (SpaceNeeded > *lpBufferSize)
+        {
+            Log(("VBOXNP: NPGetResourceInformation: WN_MORE_DATA 0x%x\n", SpaceNeeded));
+            *lpBufferSize = SpaceNeeded;
+            return WN_MORE_DATA;
+        }
+
+        memset (pNetResource, 0, sizeof (*pNetResource));
+
+        pNetResource->dwType = RESOURCETYPE_DISK;
+        pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+        pNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
+
+        /* Setup string area at opposite end of buffer. */
+        StringZone = (PWCHAR)((PBYTE)StringZone - (SpaceNeeded - sizeof(NETRESOURCE)));
+
+        /* The remote name is the server + share. */
+        pNetResource->lpRemoteName = StringZone;
+        *StringZone++ = L'\\';
+        *StringZone++ = L'\\';
+        CopyMemory (StringZone, MRX_VBOX_SERVER_NAME_U, sizeof(MRX_VBOX_SERVER_NAME_U) - sizeof (WCHAR));
+        StringZone += sizeof(MRX_VBOX_SERVER_NAME_U) / sizeof(WCHAR) - 1;
+        CopyMemory (StringZone, lpAfterName, (lp - lpAfterName + 1) * sizeof(WCHAR));
+        StringZone += lp - lpAfterName + 1;
+
+        /* Provider. */
+        pNetResource->lpProvider = StringZone;
+        CopyMemory (StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof(MRX_VBOX_PROVIDER_NAME_U));
+        StringZone += sizeof(MRX_VBOX_PROVIDER_NAME_U) / sizeof(WCHAR);
+
+        Log(("VBOXNP: NPGetResourceInformation: lpRemoteName: %ls, strings %p/%p\n",
+             pNetResource->lpRemoteName, StringZone, (PBYTE)lpBuffer + *lpBufferSize));
+
+        if (lplpSystem)
+        {
+            *lplpSystem = NULL;
+        }
+        return WN_SUCCESS;
+    }
+
+    /* \\vboxsvr\share\path */
+    SpaceNeeded = sizeof(NETRESOURCE);
+    SpaceNeeded += 2 * sizeof(WCHAR) + sizeof(MRX_VBOX_SERVER_NAME_U); /* \\ + server name with trailing nul */
+    SpaceNeeded += (lp - lpAfterName) * sizeof(WCHAR); /* The share name with leading \\ */
+    SpaceNeeded += sizeof(MRX_VBOX_PROVIDER_NAME_U); /* provider name */
+    SpaceNeeded += (lstrlen(lp) + 1) * sizeof (WCHAR); /* path string for lplpSystem */
+
+    if (SpaceNeeded > *lpBufferSize)
+    {
+        Log(("VBOXNP: NPGetResourceInformation: WN_MORE_DATA 0x%x\n", SpaceNeeded));
+        *lpBufferSize = SpaceNeeded;
+        return WN_MORE_DATA;
+    }
+
+    memset (pNetResource, 0, sizeof (*pNetResource));
+
+    pNetResource->dwType = RESOURCETYPE_DISK;
+    pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+    pNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
+
+    /* Setup string area at opposite end of buffer. */
+    StringZone = (PWCHAR)((PBYTE)StringZone - (SpaceNeeded - sizeof(NETRESOURCE)));
+
+    /* The remote name is the server + share. */
+    pNetResource->lpRemoteName = StringZone;
+    *StringZone++ = L'\\';
+    *StringZone++ = L'\\';
+    CopyMemory (StringZone, MRX_VBOX_SERVER_NAME_U, sizeof(MRX_VBOX_SERVER_NAME_U) - sizeof (WCHAR));
+    StringZone += sizeof(MRX_VBOX_SERVER_NAME_U) / sizeof(WCHAR) - 1;
+    CopyMemory (StringZone, lpAfterName, (lp - lpAfterName) * sizeof(WCHAR));
+    StringZone += lp - lpAfterName;
+    *StringZone++ = 0;
+
+    /* Provider. */
+    pNetResource->lpProvider = StringZone;
+    CopyMemory (StringZone, MRX_VBOX_PROVIDER_NAME_U, sizeof(MRX_VBOX_PROVIDER_NAME_U));
+    StringZone += sizeof(MRX_VBOX_PROVIDER_NAME_U) / sizeof(WCHAR);
+
+    if (lplpSystem)
+    {
+        *lplpSystem = StringZone;
+    }
+
+    lstrcpy(StringZone, lp);
+    StringZone += lstrlen(lp) + 1;
+
+    Log(("VBOXNP: NPGetResourceInformation: lpRemoteName: %ls, strings %p/%p\n",
+         pNetResource->lpRemoteName, StringZone, (PBYTE)lpBuffer + *lpBufferSize));
+    Log(("VBOXNP: NPGetResourceInformation: *lplpSystem: %ls\n", *lplpSystem));
+
+    return WN_SUCCESS;
+}
+
+DWORD APIENTRY
+NPGetUniversalName (LPCWSTR lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize)
+/*++
+
+ Routine Description:
+
+ This routine returns the information associated net resource
+
+ Arguments:
+
+ lpLocalPath - the local path name
+
+ dwInfoLevel  - the desired info level
+
+ lpBuffer - the buffer for the univeral name
+
+ lpBufferSize - the buffer size
+
+ Return Value:
+
+ WN_SUCCESS if successful
+
+ Notes:
+
+ --*/
+{
+    DWORD dwStatus;
+
+    DWORD BufferRequired = 0;
+    DWORD RemoteNameLength = 0;
+    DWORD RemainingPathLength = 0;
+
+    WCHAR LocalDrive[3];
+
+    const WCHAR *lpRemainingPath;
+    WCHAR *lpString;
+
+    Log(("VBOXNP: NPGetUniversalName: lpLocalPath = %ls, InfoLevel = %d, *lpBufferSize = %d\n", lpLocalPath, dwInfoLevel, *lpBufferSize));
+
+    /* Check is input parameter is OK. */
+    if (   dwInfoLevel != UNIVERSAL_NAME_INFO_LEVEL
+        && dwInfoLevel != REMOTE_NAME_INFO_LEVEL)
+    {
+        Log(("VBOXNP: NPGetUniversalName: Bad dwInfoLevel value: %d\n", dwInfoLevel));
+        return WN_BAD_LEVEL;
+    }
+
+    /* The 'lpLocalPath' is "X:\something". Extract the "X:" to pass to NPGetConnection. */
+    if (   lpLocalPath == NULL
+        || lpLocalPath[0] == 0
+        || lpLocalPath[1] != L':')
+    {
+        Log(("VBOXNP: NPGetUniversalName: Bad lpLocalPath.\n"));
+        return WN_BAD_LOCALNAME;
+    }
+
+    LocalDrive[0] = lpLocalPath[0];
+    LocalDrive[1] = lpLocalPath[1];
+    LocalDrive[2] = 0;
+
+    /* Length of the original path without the driver letter, including trailing NULL. */
+    lpRemainingPath = &lpLocalPath[2];
+    RemainingPathLength = (DWORD)((wcslen (lpRemainingPath) + 1) * sizeof(WCHAR));
+
+    /* Build the required structure in place of the supplied buffer. */
+    if (dwInfoLevel == UNIVERSAL_NAME_INFO_LEVEL)
+    {
+        LPUNIVERSAL_NAME_INFOW pUniversalNameInfo = (LPUNIVERSAL_NAME_INFOW)lpBuffer;
+
+        BufferRequired = sizeof (UNIVERSAL_NAME_INFOW);
+
+        if (*lpBufferSize >= BufferRequired)
+        {
+            /* Enough place for the structure. */
+            pUniversalNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(UNIVERSAL_NAME_INFOW));
+
+            /* At least so many bytes are available for obtaining the remote name. */
+            RemoteNameLength = *lpBufferSize - BufferRequired;
+        }
+        else
+        {
+            RemoteNameLength = 0;
+        }
+
+        /* Put the remote name directly to the buffer if possible and get the name length. */
+        dwStatus = NPGetConnection (LocalDrive, RemoteNameLength? pUniversalNameInfo->lpUniversalName: NULL, &RemoteNameLength);
+
+        if (   dwStatus != WN_SUCCESS
+            && dwStatus != WN_MORE_DATA)
+        {
+            if (dwStatus != WN_NOT_CONNECTED)
+            {
+                Log(("VBOXNP: NPGetUniversalName: NPGetConnection returned error 0x%lx\n", dwStatus));
+            }
+            return dwStatus;
+        }
+
+        if (RemoteNameLength < sizeof (WCHAR))
+        {
+            Log(("VBOXNP: NPGetUniversalName: Remote name is empty.\n"));
+            return WN_NO_NETWORK;
+        }
+
+        /* Adjust for actual remote name length. */
+        BufferRequired += RemoteNameLength;
+
+        /* And for required place for remaining path. */
+        BufferRequired += RemainingPathLength;
+
+        if (*lpBufferSize < BufferRequired)
+        {
+            Log(("VBOXNP: NPGetUniversalName: WN_MORE_DATA BufferRequired: %d\n", BufferRequired));
+            *lpBufferSize = BufferRequired;
+            return WN_MORE_DATA;
+        }
+
+        /* Enough memory in the buffer. Add '\' and remaining path to the remote name. */
+        lpString = &pUniversalNameInfo->lpUniversalName[RemoteNameLength / sizeof (WCHAR)];
+        lpString--; /* Trailing NULL */
+
+        CopyMemory( lpString, lpRemainingPath, RemainingPathLength);
+    }
+    else
+    {
+        LPREMOTE_NAME_INFOW pRemoteNameInfo = (LPREMOTE_NAME_INFOW)lpBuffer;
+        WCHAR *lpDelimiter;
+
+        BufferRequired = sizeof (REMOTE_NAME_INFOW);
+
+        if (*lpBufferSize >= BufferRequired)
+        {
+            /* Enough place for the structure. */
+            pRemoteNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(REMOTE_NAME_INFOW));
+            pRemoteNameInfo->lpConnectionName = NULL;
+            pRemoteNameInfo->lpRemainingPath = NULL;
+
+            /* At least so many bytes are available for obtaining the remote name. */
+            RemoteNameLength = *lpBufferSize - BufferRequired;
+        }
+        else
+        {
+            RemoteNameLength = 0;
+        }
+
+        /* Put the remote name directly to the buffer if possible and get the name length. */
+        dwStatus = NPGetConnection (LocalDrive, RemoteNameLength? pRemoteNameInfo->lpUniversalName: NULL, &RemoteNameLength);
+
+        if (   dwStatus != WN_SUCCESS
+            && dwStatus != WN_MORE_DATA)
+        {
+            if (dwStatus != WN_NOT_CONNECTED)
+            {
+                Log(("VBOXNP: NPGetUniversalName: NPGetConnection returned error 0x%lx\n", dwStatus));
+            }
+            return dwStatus;
+        }
+
+        if (RemoteNameLength < sizeof (WCHAR))
+        {
+            Log(("VBOXNP: NPGetUniversalName: Remote name is empty.\n"));
+            return WN_NO_NETWORK;
+        }
+
+        /* Adjust for actual remote name length. */
+        BufferRequired += RemoteNameLength;
+
+        /* And for required place for remaining path. */
+        BufferRequired += RemainingPathLength;
+
+        /* lpConnectionName, which is the remote name. */
+        BufferRequired += RemoteNameLength;
+
+        /* lpRemainingPath. */
+        BufferRequired += RemainingPathLength;
+
+        if (*lpBufferSize < BufferRequired)
+        {
+            Log(("VBOXNP: NPGetUniversalName: WN_MORE_DATA BufferRequired: %d\n", BufferRequired));
+            *lpBufferSize = BufferRequired;
+            return WN_MORE_DATA;
+        }
+
+        /* Enough memory in the buffer. Add \ and remaining path to the remote name. */
+        lpString = &pRemoteNameInfo->lpUniversalName[RemoteNameLength / sizeof (WCHAR)];
+        lpString--; /* Trailing NULL */
+
+        lpDelimiter = lpString; /* Delimiter will be inserted later. For now keep the NULL terminated string. */
+
+        CopyMemory( lpString, lpRemainingPath, RemainingPathLength);
+        lpString += RemainingPathLength / sizeof (WCHAR);
+
+        *lpDelimiter = 0;
+
+        pRemoteNameInfo->lpConnectionName = lpString;
+        CopyMemory( lpString, pRemoteNameInfo->lpUniversalName, RemoteNameLength);
+        lpString += RemoteNameLength / sizeof (WCHAR);
+
+        pRemoteNameInfo->lpRemainingPath = lpString;
+        CopyMemory( lpString, lpRemainingPath, RemainingPathLength);
+
+        *lpDelimiter = L'\\';
+    }
+
+    Log(("VBOXNP: NPGetUniversalName: WN_SUCCESS\n"));
+    return WN_SUCCESS;
+}
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.def
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.def	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.def	(revision 31634)
@@ -0,0 +1,24 @@
+;
+; Copyright (C) 2006-2007 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+LIBRARY	VBOXMRXNP
+
+EXPORTS
+	NPGetCaps			        @13
+	NPAddConnection			    @17
+	NPAddConnection3		    @38
+	NPCancelConnection		    @18
+	NPGetConnection			    @12
+	NPOpenEnum			        @33
+	NPEnumResource			    @34
+	NPCloseEnum			        @35
+	NPGetUniversalName		    @40
+	NPGetResourceParent		    @41
+	NPGetResourceInformation	@52
+	NPLogonNotify			    @500
+	NPPasswordChangeNotify		@501
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.h	(revision 31634)
@@ -0,0 +1,43 @@
+/*++
+
+ Copyright (c) 1989-1999  Microsoft Corporation
+
+ Module Name:
+
+ nulmrxnp.h
+
+ Abstract:
+
+ This module includes all network provider router interface related
+ definitions for the sample
+
+ Notes:
+
+ This module has been built and tested only in UNICODE environment
+
+ --*/
+
+#ifndef _NULMRXNP_H_
+#define _NULMRXNP_H_
+
+#include "..\sys\nulmrx.h"
+
+#include <iprt/alloc.h>
+#include <iprt/initterm.h>
+#include <iprt/string.h>
+#include <iprt/log.h>
+#include <VBox/version.h>
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxGuestLib.h>
+#include <VBox/Log.h>
+
+#define MRX_VBOX_SERVER_NAME_U     L"VBOXSVR"
+#define MRX_VBOX_SERVER_NAME_ALT_U L"VBOXSRV"
+
+typedef struct _NULMRXNP_ENUMERATION_HANDLE_
+{
+    INT LastIndex;
+} NULMRXNP_ENUMERATION_HANDLE, *PNULMRXNP_ENUMERATION_HANDLE;
+
+#endif
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/dll/vboxmrxp.rc	(revision 31634)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 Shared Folders Minirdr NP\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxMRXNP.DLL\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxMRXNP.DLL\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/Makefile.kmk	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/Makefile.kmk	(revision 31634)
@@ -0,0 +1,90 @@
+# $Id$
+## @file
+# Sub-Makefile for the VirtualBox Windows Guest Shared Folders FSD.
+#
+
+#
+# Copyright (C) 2006-2007 Oracle Corporation
+#
+# Oracle Corporation confidential
+# All rights reserved
+#
+
+SUB_DEPTH = ../../../../../../..
+include	$(KBUILD_PATH)/subheader.kmk
+
+#
+# rdbss
+#
+LIBRARIES += rdbss
+rdbss_TEMPLATE       = VBOXGUESTR0
+rdbss_SOURCES        = rdbss/rdbss.def
+
+#
+# VBoxSF
+#
+SYSMODS += VBoxSF
+VBoxSF_TEMPLATE    = VBOXGUESTR0
+VBoxSF_DEFS        = LOG_TO_BACKDOOR VBOX_WITH_HGCM IN_RING0 VBOX_GUEST
+VBoxSF_DEFS       += VBOX_ASYNC_RW VBOX_FAIL_FASTIO
+
+VBoxSF_SDKS.x86    = WINDDKW2K
+VBoxSF_SDKS.amd64  = WINDDKWLH
+
+VBoxSF_INCS        = \
+	../../../../common/VBoxGuestLib
+VBoxSF_LDFLAGS.x86   = -Entry:DriverEntry@8
+VBoxSF_LDFLAGS.amd64 = -Entry:DriverEntry
+VBoxSF_CFLAGS      = -wd4005
+VBoxSF_SOURCES     =  \
+	devctrl.c \
+	devfcb.c \
+	downlvli.c \
+	ea.c \
+	fileinfo.c \
+	init.c \
+	locks.c \
+	netroot.c \
+	notimpl.c \
+	openclos.c \
+	read.c \
+	rename.c \
+	srvcall.c \
+	transprt.c \
+	write.c \
+	vbsfhlp.c \
+	wmlkm.c \
+	rdbss_vbox.c \
+ 	VBoxSF.rc
+
+VBoxSF_LIBS.x86  = \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/fre/rxce.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/fre/rdbsslib.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/fre/copysup.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/ntoskrnl.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/hal.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/ksecdd.lib \
+	$(PATH_SDK_WINDDKW2K_LIB.x86)/BufferOverflowK.lib
+
+VBoxSF_LIBS.amd64  = \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/rxce.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/rdbsslib.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/copysup.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/ntoskrnl.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/hal.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/ksecdd.lib \
+	$(PATH_SDK_WINDDKWLH_LIB.amd64)/BufferOverflowK.lib
+
+VBoxSF_LIBS = \
+	$(VBOX_LIB_VBGL_R0) \
+	$(VBOX_LIB_IPRT_GUEST_R0)
+
+## Use with checked RDBSS libraries
+##	$(PATH_SDK_W2K3DDKX86_LIB)/bufferoverflowk.lib \
+
+##        rdbss.asm \
+##	$(PATH_LIB)/rdbss$(VBOXW32GUEST_SUFF_LIB)
+
+
+include	$(KBUILD_PATH)/subfooter.kmk
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.inf
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.inf	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.inf	(revision 31634)
@@ -0,0 +1,77 @@
+;
+; INF file for installing the VirtualBox Windows guest driver
+;
+; Copyright (C) 2006-2007 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+[Version]
+Signature="$Windows NT$"
+Class=System
+ClassGuid={ce4a90b5-1d8c-435d-b349-232ce55cb17f}
+Provider=%SUN%
+;edit-DriverVer=08/26/2008,2.00.0000
+DriverPackageType=Network
+;cat CatalogFile=VBoxSF.cat
+
+;cat [SourceDisksNames]
+;cat 1 = %VBoxSF.MediaDesc%
+;cat
+;cat [SourceDisksFiles]
+;cat VBoxSF.sys = 1
+
+[DestinationDirs]
+DefaultDestDir      = 12 ; drivers
+VBoxMRXNP_CopyFiles = 11 ; system32
+
+[Manufacturer]
+;x86   %SUN%=VBoxSF
+;amd64 %SUN%=VBoxSF, NTamd64
+
+;x86   [VBoxSF]
+;amd64 [VBoxSF.NTamd64]
+%VBoxSF.DeviceDesc%=VBoxSF_Install,PCI\VEN_80ee&DEV_cafe
+
+[VBoxSF_Install]
+CopyFiles = VBoxSF_CopyFiles, VBoxMRXNP_CopyFiles
+AddReg = VBoxMRXNP_Add_Reg
+
+[VBoxSF_CopyFiles]
+VBoxSF.sys
+
+[VBoxMRXNP_CopyFiles]
+VBoxMRXNP.dll
+
+[VBoxSF_Install.Services]
+AddService = VBoxSF, 0x00000002, VBoxSF_ServiceInstallSection
+DelService = VBoxMRXNP, 0x00000004
+
+[VBoxSF_ServiceInstallSection]
+DisplayName    = %VBoxSF_svcdesc%
+ServiceType    = 0x00000001 ; kernel driver
+StartType      = 0x00000003 ; demand start
+ErrorControl   = 0x00000001 ; normal error handling
+ServiceBinary  = %12%\VBoxSF.sys
+
+[VBoxMRXNP_Add_Reg]
+HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Run, VBoxMRXNP, 0x00000000, %11%\VBoxMRXNP.exe
+
+[VBoxSF_Install.CoInstallers]
+AddReg = VBoxSF_Install_CoInstallers_reg
+CopyFiles = VBox_CoInstaller_CopyFiles
+
+[VBox_CoInstaller_CopyFiles]
+vbcoinst.dll
+
+[VBoxSF_Install_CoInstallers_reg]
+HKR,,CoInstallers32,0x00010000,"vbcoinst.dll,VBoxCoInstaller"
+
+[Strings]
+SUN = "Sun Microsystems, Inc."
+VBoxSF.DeviceDesc = "VirtualBox Device"
+VBoxSF_svcdesc = "VirtualBox Shared Folders Driver"
+VBoxMRXNP_svcdesc = "VirtualBox Network Provider Service"
+
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.rc
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.rc	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/VBoxSF.rc	(revision 31634)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#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 Shared Folders Minirdr\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "VBoxSF.sys\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "VBoxSF.sys\0"
+         VALUE "ProductName",      "VirtualBox Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devctrl.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devctrl.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devctrl.c	(revision 31634)
@@ -0,0 +1,76 @@
+/*++
+
+ Copyright (c) 1989 - 1999   Microsoft Corporation
+
+ Module Name:
+
+ devctrl.c
+
+ Abstract:
+
+ This module implements DeviceIoControl operations.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+//  The local debug trace level
+//
+
+RXDT_DefineCategory (DEVCTRL);
+
+#define Dbg                              (DEBUG_TRACE_DEVCTRL)
+
+//
+//  forwards & code allocation pragmas
+//
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, VBoxMRxIoCtl)
+#endif
+
+NTSTATUS VBoxMRxIoCtl (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine performs an IOCTL operation.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ Notes:
+
+
+ --*/
+{
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+#ifndef VBOX
+    UNICODE_STRING RootName;
+#endif
+    VBoxMRxGetDeviceExtension(RxContext,pDeviceExtension);
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    ULONG IoControlCode = LowIoContext->ParamsFor.FsCtl.FsControlCode;
+    PUNICODE_STRING RemainingName = pSrvOpen->pAlreadyPrefixedName;
+#ifndef VBOX
+    UNICODE_STRING StatsFile;
+#endif
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+
+    Log(("VBOXSF: VBoxMRxIoCtl: IoControlCode = 0x%x\n", IoControlCode));
+    PAGED_CODE();
+
+    return Status;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devfcb.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devfcb.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/devfcb.c	(revision 31634)
@@ -0,0 +1,741 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ devfcb.c
+
+ Abstract:
+
+ This module implements the mechanism for deleting an established connection
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+#include "rdbss_vbox.h"
+
+//
+//  The local debug trace level
+//
+
+#define Dbg                              (DEBUG_TRACE_DEVFCB)
+
+//#define FIXED_CONNECT_NAME L"\\;0:\\vboxsvr\\share"
+#define FIXED_CONNECT_NAME L"\\;0:"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, VBoxMRxDevFcbXXXControlFile)
+#endif
+
+NTSYSAPI
+NTSTATUS NTAPI
+ZwSetSecurityObject (IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor);
+
+NTSTATUS VBoxMRxDevFcbXXXControlFile (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine handles all the device FCB related FSCTL's in the mini rdr
+
+ Arguments:
+
+ RxContext - Describes the Fsctl and Context.
+
+ Return Value:
+
+ a valid NTSTATUS code.
+
+ Notes:
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFobx;
+    UCHAR MajorFunctionCode = RxContext->MajorFunction;
+    VBoxMRxGetDeviceExtension(RxContext,pDeviceExtension);
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    ULONG ControlCode = 0;
+
+    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: MajorFunctionCode = %x\n", MajorFunctionCode));
+
+    switch (MajorFunctionCode)
+    {
+    case IRP_MJ_FILE_SYSTEM_CONTROL:
+    {
+        switch (LowIoContext->ParamsFor.FsCtl.MinorFunction)
+        {
+        case IRP_MN_USER_FS_REQUEST:
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: ControlCode = %x\n", ControlCode));
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+
+        default: //minor function != IRP_MN_USER_FS_REQUEST
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+        }
+        break;
+    }
+
+    case IRP_MJ_DEVICE_CONTROL:
+    {
+
+        ControlCode = LowIoContext->ParamsFor.IoCtl.IoControlCode;
+
+        switch (ControlCode)
+        {
+        case IOCTL_MRX_VBOX_ADDCONN:
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
+            Status = VBoxMRxCreateConnection(RxContext, &RxContext->PostRequest);
+            break;
+
+        case IOCTL_MRX_VBOX_DELCONN:
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
+            Status = VBoxMRxDeleteConnection(RxContext, &RxContext->PostRequest);
+            break;
+
+        case IOCTL_MRX_VBOX_GETLIST:
+        {
+            ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+            PVOID pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
+
+            if ((cbOut >= _MRX_MAX_DRIVE_LETTERS) && (NULL != pbOut))
+            {
+                BOOLEAN GotMutex = FALSE;
+
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections ...\n"));
+
+                if (NULL == pDeviceExtension)
+                    break;
+
+                GotMutex = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+
+                RtlCopyMemory (pbOut, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
+
+                if (GotMutex)
+                    ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+
+                RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Nothing to copy, cbOut is too small (%d bytes)\n", cbOut));
+                RxContext->InformationToReturn = 0;
+            }
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /*
+         * Returns the root IDs of shared folder mappings.
+         */
+        case IOCTL_MRX_VBOX_GETGLOBALLIST:
+        {
+            ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+            uint8_t *pbOut = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
+
+            if (NULL == pDeviceExtension)
+                break;
+
+            RxContext->InformationToReturn = 0;
+            if ((cbOut >= _MRX_MAX_DRIVE_LETTERS) && (NULL != pbOut))
+            {
+                SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
+                uint32_t cMappings = RT_ELEMENTS(mappings);
+                int vboxRC;
+
+                vboxRC = vboxCallQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings);
+                if (vboxRC == VINF_SUCCESS)
+                {
+                    uint32_t i;
+
+                    RtlZeroMemory(pbOut, _MRX_MAX_DRIVE_LETTERS);
+                    for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
+                    {
+                        pbOut[i] = mappings[i].root;
+                        pbOut[i] |= 0x80; /* mark active *//** @todo fix properly */
+                    }
+
+                    RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
+                }
+                else
+                {
+                    Status = VBoxErrorToNTStatus(vboxRC);
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST Error: 0x%08x\n", Status));
+                }
+            }
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /*
+         * Translates a local connection name (e.g. drive "S:") to the
+         * corresponding remote name (e.g. \\vboxsrv\share).
+         */
+        case IOCTL_MRX_VBOX_GETCONN:
+        {
+            ULONG ulConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+            PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+
+            ULONG ulRemoteNameLen = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+            PULONG pulRemoteName = (PULONG)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+            Log(
+                ("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, RemoteName = 0x%x, Len = %d\n", ulConnectNameLen / sizeof(WCHAR), pwcConnectName, ulConnectNameLen, pulRemoteName, ulRemoteNameLen));
+
+            if (NULL == pDeviceExtension)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            /* Insert the local connection name. */
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections ...\n"));
+            if ((ulConnectNameLen > sizeof(WCHAR)) && (NULL != pwcConnectName))
+            {
+                ULONG ulLocalConnectionNameLen;
+
+                uint32_t idx = *pwcConnectName - L'A';
+
+                ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index = %d\n", idx));
+
+                if ((idx < 0) || (idx >= RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName)))
+                {
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
+                    ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                if (NULL == pDeviceExtension->wszLocalConnectionName[idx])
+                {
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
+                    ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                    Status = STATUS_BAD_NETWORK_NAME;
+                    break;
+                }
+
+                ulLocalConnectionNameLen = pDeviceExtension->wszLocalConnectionName[idx]->Length;
+
+                Log(
+                    ("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n", ulLocalConnectionNameLen / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
+
+                if ((pDeviceExtension->cLocalConnections[idx]) && (ulLocalConnectionNameLen <= ulRemoteNameLen))
+                {
+                    RtlZeroMemory (pulRemoteName, ulRemoteNameLen);
+                    RtlCopyMemory (pulRemoteName, pDeviceExtension->wszLocalConnectionName[idx]->Buffer, ulLocalConnectionNameLen);
+
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Size = %d\n", ulLocalConnectionNameLen / sizeof(WCHAR), pulRemoteName, ulLocalConnectionNameLen));
+                    RxContext->InformationToReturn = ulLocalConnectionNameLen;
+                }
+                else
+                {
+                    Status = STATUS_BUFFER_TOO_SMALL;
+                    RxContext->InformationToReturn = ulLocalConnectionNameLen;
+                }
+
+                ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: No connection name found!\n"));
+                Status = STATUS_BAD_NETWORK_NAME;
+            }
+
+            break;
+        }
+
+        case IOCTL_MRX_VBOX_GETGLOBALCONN:
+        {
+            ULONG ReturnedSize = 0;
+            uint8_t *pConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+            ULONG RemoteNameLen = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+            PULONG RemoteName = (PULONG)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+            PSHFLSTRING pString;
+            int vboxRC;
+            uint32_t cbString = sizeof(SHFLSTRING) + RemoteNameLen;
+
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d, RemoteName = 0x%x, Len = %d\n", *pConnectId, RemoteName, RemoteNameLen));
+
+            pString = (PSHFLSTRING)vbsfAllocNonPagedMem(cbString);
+            if (!pString)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                break;
+            }
+            memset(pString, 0, cbString);
+            ShflStringInitBuffer(pString, RemoteNameLen); /** @todo r=andy This function does not have an effect ...? */
+
+            vboxRC = vboxCallQueryMapName(&pDeviceExtension->hgcmClient, (*pConnectId) & ~0x80 /** @todo fix properly */, pString, cbString);
+            if (vboxRC == VINF_SUCCESS)
+            {
+                if (pString->u16Length < RemoteNameLen)
+                {
+                    ReturnedSize = pString->u16Length;
+                    RtlCopyMemory( RemoteName, pString->String.ucs2, pString->u16Length);
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Size = %d\n", ReturnedSize / sizeof(WCHAR), RemoteName, ReturnedSize));
+                }
+            }
+            else
+                Status = VBoxErrorToNTStatus(vboxRC);
+
+            vbsfFreeNonPagedMem(pString);
+
+            if (ReturnedSize)
+            {
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                Status = STATUS_BAD_NETWORK_NAME;
+            }
+            RxContext->InformationToReturn = ReturnedSize;
+            break;
+        }
+
+        case IOCTL_MRX_VBOX_START:
+        {
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Called.\n"));
+            switch (VBoxMRxState)
+            {
+            case MRX_VBOX_STARTABLE:
+
+                /* The correct sequence of start events issued by the workstation
+                 service would have avoided this. We can recover from this
+                 by actually invoking RxStartMiniRdr. */
+
+                if (capFobx)
+                {
+                    Status = STATUS_INVALID_DEVICE_REQUEST;
+                    break;;
+                }
+
+                /* Set global VBoxMRxState variable to MRX_VBOX_STARTABLE and fall through to the next case. */
+                InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
+
+                /* Lack of break is intentional. */
+
+            case MRX_VBOX_START_IN_PROGRESS:
+                Status = VBoxRxStartMinirdr(RxContext, &RxContext->PostRequest);
+
+                if (Status == STATUS_REDIRECTOR_STARTED)
+                    Status = STATUS_SUCCESS;
+                else if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
+                    Status = STATUS_MORE_PROCESSING_REQUIRED;
+
+                /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
+                if (Status == STATUS_SUCCESS)
+                {
+                    SECURITY_DESCRIPTOR SecurityDescriptor;
+                    OBJECT_ATTRIBUTES InitializedAttributes;
+                    HANDLE hDevice;
+                    IO_STATUS_BLOCK IoStatusBlock;
+                    UNICODE_STRING UserModeDeviceName;
+
+                    RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+
+                    /* Create empty security descriptor */
+                    RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
+                    Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%x!\n", Status));
+                        return Status;
+                    }
+                    RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
+                    InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
+
+                    /* Open our symbolic link device name */
+                    Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        Log(
+                            ("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%x!\n", DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
+                        return Status;
+                    }
+
+                    /* Override the discretionary access control list (DACL) settings */
+                    Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%x!\n", Status));
+                        return Status;
+                    }
+
+                    Status = ZwClose(hDevice);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%x\n", Status));
+                        return Status;
+                    }
+                }
+                break;
+
+            case MRX_VBOX_STARTED:
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
+                Status = STATUS_SUCCESS;
+                break;
+
+            default:
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n", VBoxMRxState));
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%x\n", Status));
+            break;
+        }
+
+        case IOCTL_MRX_VBOX_STOP:
+        {
+            MRX_VBOX_STATE CurrentState;
+
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Called.\n"));
+            if (capFobx)
+            {
+                Status = STATUS_INVALID_DEVICE_REQUEST;
+                break;
+            }
+
+            if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
+            {
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n", RxContext->RxDeviceObject->NumberOfActiveFcbs));
+                Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
+                break;
+            }
+
+            CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
+
+            Status = VBoxRxStopMinirdr(RxContext, &RxContext->PostRequest);
+            Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%x\n", Status));
+
+            if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
+                Status = STATUS_MORE_PROCESSING_REQUIRED;
+
+            break;
+        }
+
+        default:
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+        }
+        break;
+    }
+
+    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+    {
+        Status = STATUS_INVALID_DEVICE_REQUEST;
+        break;
+    }
+
+    default:
+        AssertMsgFailed(("VBOXSF: VBoxMRxDevFcbXXXControlFile: Unimplemented major function!"));
+        Status = STATUS_INVALID_DEVICE_REQUEST;
+        break;
+    }
+
+    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: Status = %08lx, Info = %08lx\n", Status, RxContext->InformationToReturn));
+    return Status;
+}
+
+HANDLE GetConnectionHandle (IN PUNICODE_STRING ConnectionName)
+{
+
+    NTSTATUS Status;
+    HANDLE Handle;
+    IO_STATUS_BLOCK IoStatusBlock;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+#ifndef VBOX
+    UNICODE_STRING FileName;
+#endif
+
+    // Connection name should get checked to be certain our device is in the path
+
+    Log(("VBOXSF: GetConnectionHandle: Called.\n"));
+
+    InitializeObjectAttributes(&ObjectAttributes, ConnectionName, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+    Status = ZwCreateFile(&Handle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, // Allocation size
+                          FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT, NULL, // Ptr to EA Buffer
+                          0); // Length of EA buffer
+
+    Log(("VBOXSF: GetConnectionHandle: ZwCreateFile returned 0x%x\n", Status));
+
+    if ((STATUS_SUCCESS == Status) && (INVALID_HANDLE_VALUE != Handle))
+    {
+        Log(("VBOXSF: GetConnectionHandle: ZwCreateFile returned success\n"));
+    }
+    else
+    {
+        Handle = INVALID_HANDLE_VALUE;
+        Log(("VBOXSF: GetConnectionHandle: ZwCreateFile returned invalid handle!\n"));
+    }
+
+    return Handle;
+}
+
+NTSTATUS DoCreateConnection (IN PRX_CONTEXT RxContext, ULONG CreateDisposition)
+{
+
+    NTSTATUS Status = STATUS_SUCCESS;
+    HANDLE Handle;
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+    PWCHAR ConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+    UNICODE_STRING FileName;
+
+    VBoxMRxGetDeviceExtension(RxContext,pDeviceExtension);
+
+    if (NULL == pDeviceExtension)
+        return STATUS_INVALID_PARAMETER;
+
+    if ((0 == ConnectNameLen) || (NULL == ConnectName))
+    {
+        Log(("VBOXSF: DoCreateConnection: Connection name / length is invalid!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    // The sample code passes in only the filename in the Ioctl data buffer.
+    //  An actual implementation could pass in stuff like EAs, security
+    // credentials, etc
+
+    Log(("VBOXSF: DoCreateConnection: Name = %.*ls, Length = %d\n", ConnectNameLen / sizeof(WCHAR), ConnectName, ConnectNameLen));
+
+    FileName.Buffer = ConnectName;
+    FileName.Length = (USHORT)ConnectNameLen;
+    FileName.MaximumLength = (USHORT)ConnectNameLen;
+
+    Handle = GetConnectionHandle(&FileName);
+
+    if (INVALID_HANDLE_VALUE != Handle)
+    {
+        PWCHAR pwcLC;
+        ULONG i;
+
+        Log(("VBOXSF: DoCreateConnection: GetConnectionHandle returned success!\n"));
+        ZwClose(Handle);
+
+        /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
+        pwcLC = (PWCHAR)ConnectName;
+        for (i = 0; i < ConnectNameLen && *pwcLC != L':'; i += sizeof(WCHAR), pwcLC++)
+            ;
+
+        if (i >= sizeof(WCHAR) && i < ConnectNameLen)
+        {
+            pwcLC--; /* Go back to the drive letter, "X" for example. */
+            if (*pwcLC >= L'A' && *pwcLC <= L'Z') /* Are we in range? */
+            {
+                uint32_t idx = *pwcLC - L'A'; /* Get the index based on the driver letter numbers (26). */
+                PUNICODE_STRING pRemoteName;
+
+                ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+
+                if ((idx < 0) || (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections)))
+                {
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
+                    ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                    return STATUS_BAD_NETWORK_NAME;
+                }
+
+                pDeviceExtension->cLocalConnections[idx] = TRUE;
+
+                if (NULL != pDeviceExtension->wszLocalConnectionName[idx])
+                    Log(("VBOXSF: DoCreateConnection: LocalConnectionName at index %d is NOT empty!\n", idx));
+
+                /*pDeviceExtension->LocalConnectionName[idx] = (PUNICODE_STRING)ExAllocatePool(PagedPool, sizeof(UNICODE_STRING) + ConnectNameLen /* more than enough );*/
+                pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + ConnectNameLen);
+
+                if (NULL == pDeviceExtension->wszLocalConnectionName[idx])
+                    Log(("VBOXSF: DoCreateConnection: LocalConnectionName at index %d NOT allocated!\n", idx));
+
+                pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
+
+                pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
+                pRemoteName->Length = (USHORT)(ConnectNameLen - i - sizeof(WCHAR));
+                pRemoteName->MaximumLength = pRemoteName->Length;
+                RtlCopyMemory(&pRemoteName->Buffer[0], pwcLC+2, pRemoteName->Length);
+
+                Log(("VBOXSF: DoCreateConnection: RemoteName %.*ls, Len = %d\n", pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
+                ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+            }
+        }
+    }
+    else
+    {
+        Log(("VBOXSF: DoCreateConnection: GetConnectionHandle returned failure!\n"));
+        Status = STATUS_BAD_NETWORK_NAME;
+    }
+
+    return (Status);
+}
+
+NTSTATUS VBoxMRxCreateConnection (IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
+/*++
+
+ Routine Description:
+
+
+ Arguments:
+
+ IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
+
+ Return Value:
+
+ RXSTATUS
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
+    BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxCreateConnection: Called.\n"));
+
+    if (!Wait)
+    {
+        //just post right now!
+        *PostToFsp = TRUE;
+        return STATUS_PENDING;
+    }
+
+    Status = DoCreateConnection(RxContext, (ULONG)FILE_OPEN_IF);
+    return Status;
+}
+
+NTSTATUS DoDeleteConnection (PUNICODE_STRING FileName)
+{
+    HANDLE Handle;
+    NTSTATUS Status;
+    PFILE_OBJECT pFileObject;
+    PNET_ROOT NetRoot;
+    PV_NET_ROOT VNetRoot;
+    PFOBX Fobx;
+
+    Log(("VBOXSF: DoDeleteConnection: Called.\n"));
+
+    Handle = GetConnectionHandle(FileName);
+
+    if (INVALID_HANDLE_VALUE != Handle)
+    {
+        Log(("VBOXSF: DoDeleteConnection: GetConnectionHandle returned success\n"));
+
+        Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
+
+        Log(("VBOXSF: DoDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n", Status));
+        if (NT_SUCCESS(Status))
+        {
+
+            // Got the FileObject. Now get an Fobx
+            Fobx = (PFOBX)pFileObject->FsContext2;
+            if (NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
+            {
+                VNetRoot = (PV_NET_ROOT)(Fobx);
+                NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
+                Log(("Calling RxFinalizeConnection\n"));
+                Status = VBoxRxFinalizeConnection(NetRoot, VNetRoot, TRUE);
+            }
+            else
+            {
+                ASSERT(FALSE);
+                Status = STATUS_INVALID_DEVICE_REQUEST;
+            }
+
+            ObDereferenceObject(pFileObject);
+        }
+
+        ZwClose(Handle);
+    }
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxDeleteConnection (IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
+/*++
+
+ Routine Description:
+
+ This routine deletes a single vnetroot.
+
+ Arguments:
+
+ IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
+
+ Return Value:
+
+ RXSTATUS
+
+ --*/
+{
+    NTSTATUS Status;
+    UNICODE_STRING FileName;
+    BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    PWCHAR ConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+    ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+    VBoxMRxGetDeviceExtension(RxContext,pDeviceExtension);
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxDeleteConnection: ConnectName = %.*ls\n", ConnectNameLen / sizeof(WCHAR), ConnectName));
+
+    if (!Wait)
+    {
+        //just post right now!
+        *PostToFsp = TRUE;
+        return (STATUS_PENDING);
+    }
+
+    FileName.Buffer = ConnectName;
+    FileName.Length = (USHORT)ConnectNameLen;
+    FileName.MaximumLength = (USHORT)ConnectNameLen;
+
+    Status = DoDeleteConnection(&FileName);
+
+    if (NT_SUCCESS(Status))
+    {
+        PWCHAR pwcLC;
+        ULONG i;
+
+        for (i = 0, pwcLC = ConnectName; i < ConnectNameLen && *pwcLC != L':'; i += sizeof(WCHAR), pwcLC++)
+            ;
+
+        if (i >= sizeof(WCHAR) && i < ConnectNameLen)
+        {
+            pwcLC--;
+            if (*pwcLC >= L'A' && *pwcLC <= L'Z')
+            {
+                uint32_t idx = *pwcLC - L'A';
+
+                ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+
+                pDeviceExtension->cLocalConnections[idx] = FALSE;
+
+                /* Free saved name */
+                /*Assert(pDeviceExtension->LocalConnectionName[idx]);
+                 ExFreePool(pDeviceExtension->LocalConnectionName[idx]);
+                 pDeviceExtension->LocalConnectionName[idx] = NULL;*/
+                if (pDeviceExtension->wszLocalConnectionName[idx])
+                {
+                    vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
+                    pDeviceExtension->wszLocalConnectionName[idx] = NULL;
+                }
+
+                ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+            }
+        }
+    }
+
+    return Status;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/downlvli.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/downlvli.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/downlvli.c	(revision 31634)
@@ -0,0 +1,157 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ DownLvlI.c
+
+ Abstract:
+
+ This module implements downlevel fileinfo, volinfo, and dirctrl.
+
+ --*/
+
+#include "precomp.h"
+#include <iprt/fs.h>
+#pragma hdrstop
+
+//
+//  The local debug trace level
+//
+
+RXDT_DefineCategory (DOWNLVLI);
+#define Dbg                 (DEBUG_TRACE_DOWNLVLI)
+
+NTSTATUS VBoxMRxSetEndOfFile (IN OUT struct _RX_CONTEXT * RxContext, IN OUT PLARGE_INTEGER pNewFileSize, OUT PLARGE_INTEGER pNewAllocationSize)
+/*++
+
+ Routine Description:
+
+ This routine handles requests to truncate or extend the file
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot, pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PRTFSOBJINFO pObjInfo = 0;
+    uint32_t cbBuffer;
+    int vboxRC;
+
+    Log(("VBOXSF: VBoxMRxSetEndOfFile: New size = %RX64 (0x%x), pNewAllocationSize = 0x%x\n", pNewFileSize->QuadPart, pNewFileSize, pNewAllocationSize));
+
+    cbBuffer = sizeof(RTFSOBJINFO);
+    pObjInfo = (PRTFSOBJINFO)vbsfAllocNonPagedMem(cbBuffer);
+    if (pObjInfo == 0)
+    {
+        AssertFailed();
+        return STATUS_NO_MEMORY;
+    }
+    memset(pObjInfo, 0, cbBuffer);
+
+    pObjInfo->cbObject = pNewFileSize->QuadPart;
+    Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
+    vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)pObjInfo);
+    AssertRC(vboxRC);
+
+    Log(("VBOXSF: VBoxMRxSetEndOfFile: vboxCallFSInfo returned %d\n", vboxRC));
+
+    Status = VBoxErrorToNTStatus(vboxRC);
+    if (Status == STATUS_SUCCESS)
+    {
+        Log(("VBOXSF: VBoxMRxSetEndOfFile: vboxCallFSInfo new allocation size = %RX64\n", pObjInfo->cbAllocated));
+
+        /* Return new allocation size */
+        pNewAllocationSize->QuadPart = pObjInfo->cbAllocated;
+    }
+
+    if (pObjInfo)
+        vbsfFreeNonPagedMem((PVOID)pObjInfo);
+
+    Log(("VBOXSF: VBoxMRxSetEndOfFile: Returned %d\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxTruncateFile (IN OUT struct _RX_CONTEXT * RxContext)
+/*++
+
+ Routine Description:
+
+ This routine handles requests to truncate the file
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxTruncateFile not implemented!\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+ULONG VBoxMRxExtendFile (IN OUT struct _RX_CONTEXT * RxContext, IN OUT PLARGE_INTEGER pNewFileSize, OUT PLARGE_INTEGER pNewAllocationSize)
+/*++
+
+ Routine Description:
+
+ This routine handles requests to extend the file for cached IO.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxExtendFile new size = %RX64\n", pNewFileSize->QuadPart));
+    return VBoxMRxSetEndOfFile(RxContext, pNewFileSize, pNewAllocationSize);
+}
+
+NTSTATUS VBoxMRxExtendStub (IN OUT struct _RX_CONTEXT * RxContext, IN OUT PLARGE_INTEGER pNewFileSize, OUT PLARGE_INTEGER pNewAllocationSize)
+/*++
+
+Routine Description:
+
+   This routine handles MRxExtendForCache and MRxExtendForNonCache requests. Since the write
+   itself will extend the file, we can pretty much just get out quickly.
+
+Arguments:
+
+    RxContext - the RDBSS context
+
+Return Value:
+
+    RXSTATUS - The return status for the operation
+
+--*/
+{
+    /* Note: On Windows hosts VBoxMRxSetEndOfFile returns ACCESS_DENIED if the file has been
+     *       opened in APPEND mode. Therefore it is better to not call host at all and implement
+     *       this MrxExtend* request just like in mrxsmb DDK sample.
+     */
+    Log(("VBOXSF: VBoxMRxExtendStub new size = %RX64\n", pNewFileSize->QuadPart));
+
+    pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
+
+    return(STATUS_SUCCESS);
+}
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/ea.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/ea.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/ea.c	(revision 31634)
@@ -0,0 +1,109 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ ea.c
+
+ Abstract:
+
+ This module implements 'extended attributes' on a file handle
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+//  The local debug trace level
+//
+
+#define Dbg                              (DEBUG_TRACE_EA)
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, VBoxMRxQueryEaInformation)
+#endif
+
+#ifdef VBOX
+/*
+ * We don't support extended attributes as the host OS might not know the concept at all
+ *
+ */
+#endif
+
+//
+//  Extended Attributes (EA) functionality
+//
+
+NTSTATUS VBoxMRxQueryEaInformation (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine queries IFS for extended attributes like
+ scatter-gather list and filename for an IFS handle.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ Notes:
+
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+    RxCaptureParamBlock;
+
+    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
+    PFILE_FULL_EA_INFORMATION pEaInfo = (PFILE_FULL_EA_INFORMATION)RxContext->Info.Buffer;
+    ULONG BufferLength = RxContext->Info.LengthRemaining;
+    ULONG UserEaListLength = RxContext->QueryEa.UserEaListLength;
+    PUCHAR UserEaList = RxContext->QueryEa.UserEaList;
+    PFILE_GET_EA_INFORMATION pGetEaInfo = (PFILE_GET_EA_INFORMATION)UserEaList;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxQueryEaInformation: Ea buffer len remaining is %d\n", RxContext->Info.LengthRemaining));
+
+    return (Status);
+}
+
+NTSTATUS VBoxMRxSetEaInformation (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine sets the EA information for this FCB
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ Notes:
+
+
+ --*/
+{
+    PAGED_CODE();
+
+    UNREFERENCED_PARAMETER(RxContext);
+
+    Log(("VBOXSF: VBoxMRxSetEaInformation: Not implemented!\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/fileinfo.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/fileinfo.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/fileinfo.c	(revision 31634)
@@ -0,0 +1,1684 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ fileinfo.c
+
+ Abstract:
+
+ This module implements the mini redirector call down routines pertaining to retrieval/
+ update of file/directory/volume information.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+/** Macro for copying a SHFLSTRING file name into a FILE_DIRECTORY_INFORMATION structure. */
+#define INIT_FILE_NAME(obj, str) \
+    do { \
+        ULONG cbLength = (str).u16Length; \
+        (obj)->FileNameLength = cbLength; \
+        RtlCopyMemory((obj)->FileName, &(str).String.ucs2[0], cbLength + 2); \
+    } while (0)
+
+NTSTATUS VBoxMRxQueryDirectory (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine does a directory query. Only the NT-->NT path is implemented.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    FILE_INFORMATION_CLASS FileInformationClass;
+    PCHAR Buffer;
+    PLONG pLengthRemaining;
+    LONG CopySize;
+    RxCaptureFobx;
+    RxCaptureFcb;
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot, pNetRootExtension);
+    PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+    PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
+    int vboxRC;
+    uint8_t *pHGCMBuffer;
+    uint32_t index, fSFFlags, cFiles, u32BufSize;
+    LONG cbHGCMBuffer, cbMaxSize;
+    PSHFLDIRINFO pDirEntry;
+    ULONG *pNextOffset = 0;
+    PSHFLSTRING ParsedPath = 0;
+
+    if (NULL == pVBoxFobx)
+    {
+        Log(("VBOXSF: QueryDirectory: pVBoxFobx is invalid!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    FileInformationClass = RxContext->Info.FileInformationClass;
+    Log(("VBOXSF: QueryDirectory: FileInformationClass %d\n", FileInformationClass));
+
+    Buffer = (PCHAR)RxContext->Info.Buffer;
+    cbMaxSize = RxContext->Info.Length;
+    pLengthRemaining = (PULONG) & RxContext->Info.LengthRemaining;
+
+    Log(("VBOXSF: QueryDirectory: vboxFobx = 0x%08x VBox file handle = 0x%08x\n", pVBoxFobx, pVBoxFobx->hFile));
+
+    if (NULL == DirectoryName)
+        return STATUS_INVALID_PARAMETER;
+
+    if (DirectoryName->Length == 0)
+    {
+        Log(("VBOXSF: QueryDirectory: DirectoryName = \\ (null string)\n"));
+    }
+    else Log(("VBOXSF: QueryDirectory: DirectoryName = %.*ls\n", DirectoryName->Length / sizeof(WCHAR), DirectoryName->Buffer));
+
+    if (NULL == Template)
+        return STATUS_INVALID_PARAMETER;
+
+    if (Template->Length == 0)
+    {
+        Log(("VBOXSF: QueryDirectory: Template = \\ (null string)\n"));
+    }
+    else Log(("VBOXSF: QueryDirectory: Template = %.*ls\n", Template->Length / sizeof(WCHAR), Template->Buffer));
+
+    cbHGCMBuffer = RT_MAX(cbMaxSize, PAGE_SIZE);
+    Log(("VBOXSF: QueryDirectory: Allocating HGCMBuffer = %d\n", cbHGCMBuffer));
+    pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+    if (pHGCMBuffer == NULL)
+    {
+        AssertFailed();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Assume start from the beginning. */
+    index = 0;
+    if (RxContext->QueryDirectory.IndexSpecified == TRUE)
+    {
+        Log(("VBOXSF: QueryDirectory: Index specified %d\n", index));
+        index = RxContext->QueryDirectory.FileIndex;
+    }
+    fSFFlags = SHFL_LIST_NONE;
+    if (RxContext->QueryDirectory.ReturnSingleEntry == TRUE)
+    {
+        Log(("VBOXSF: QueryDirectory: Query single entry\n"));
+        fSFFlags |= SHFL_LIST_RETURN_ONE;
+    }
+
+    if (Template->Length)
+    {
+        ULONG ParsedPathSize, len;
+
+        /* Calculate length required for parsed path. */
+        ParsedPathSize = sizeof(*ParsedPath) + (DirectoryName->Length + Template->Length + 3 * sizeof(WCHAR));
+        Log(("VBOXSF: QueryDirectory: ParsedPathSize = %d\n", ParsedPathSize));
+
+        ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+        if (!ParsedPath)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto end;
+        }
+        RtlZeroMemory (ParsedPath, ParsedPathSize);
+        ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+        ParsedPath->u16Size = DirectoryName->Length + Template->Length + sizeof(WCHAR);
+        ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* Without terminating null. */
+
+        len = 0;
+        if (DirectoryName->Length)
+        {
+            /* Copy directory name into ParsedPath. */
+            RtlCopyMemory (ParsedPath->String.ucs2, DirectoryName->Buffer, DirectoryName->Length);
+            len = DirectoryName->Length / sizeof(WCHAR);
+
+            /* Add terminating backslash. */
+            ParsedPath->String.ucs2[len] = L'\\';
+            len++;
+            ParsedPath->u16Length += sizeof(WCHAR);
+            ParsedPath->u16Size += sizeof(WCHAR);
+        }
+        RtlCopyMemory (&ParsedPath->String.ucs2[len], Template->Buffer, Template->Length);
+        Log(("VBOXSF: QueryDirectory: ParsedPath = %.*ls\n", ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
+    }
+
+    cFiles = 0;
+    /* vboxCallDirInfo requires a pointer to uint32_t. */
+    u32BufSize = cbHGCMBuffer;
+
+    Log(("VBOXSF: QueryDirectory: CallDirInfo: File = 0x%08x, Flags = 0x%08x, Index = %d\n", pVBoxFobx->hFile, fSFFlags, index));
+    Log(("VBOXSF: QueryDirectory: u32BufSize before CallDirInfo = %d\n", u32BufSize));
+    vboxRC = vboxCallDirInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, ParsedPath, fSFFlags, index, &u32BufSize, (PSHFLDIRINFO)pHGCMBuffer, &cFiles);
+    Log(("VBOXSF: QueryDirectory: u32BufSize after CallDirInfo = %d\n", u32BufSize));
+    Log(("VBOXSF: QueryDirectory: CallDirInfo returned %Rrc\n", vboxRC));
+
+    switch (vboxRC)
+    {
+    case VINF_SUCCESS:
+        /* Nothing to do here. */
+        break;
+    case VERR_NO_TRANSLATION:
+        Log(("VBOXSF: QueryDirectory: Host could not translate entry!\n"));
+        break;
+    case VERR_NO_MORE_FILES:
+        if (cFiles <= 0) /* VERR_NO_MORE_FILES appears at the first lookup when just returning the current dir ".".
+                          * So we also have to check for the cFiles counter. */
+        {
+            /* Not an error, but we have to handle the return value. */
+            Log(("VBOXSF: QueryDirectory: Host reported no more files!\n"));
+
+            if (RxContext->QueryDirectory.InitialQuery)
+            {
+                /* First call. MSDN on FindFirstFile: "If the function fails because no matching files
+                 * can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND."
+                 * So map this rc to file not found.
+                 */
+                Status = STATUS_NO_SUCH_FILE;
+            }
+            else
+            {
+                /* Search continued. */
+                Status = STATUS_NO_MORE_FILES;
+            }
+        }
+        break;
+    case VERR_FILE_NOT_FOUND:
+        Status = STATUS_NO_SUCH_FILE;
+        Log(("VBOXSF: QueryDirectory: no such file!\n"));
+        break;
+    default:
+        Status = VBoxErrorToNTStatus(vboxRC);
+        Log(("VBOXSF: QueryDirectory: Error %Rrc from CallDirInfo (cFiles=%d)!\n", vboxRC, cFiles));
+        break;
+    }
+
+    if (Status != STATUS_SUCCESS)
+        goto end;
+
+    /* Verify that the returned buffer length is not greater than the original one. */
+    if (u32BufSize > (uint32_t)cbHGCMBuffer)
+    {
+        Log(("VBOXSF: QueryDirectory: returned buffer size (%u) is invalid!!!\n", u32BufSize));
+        Status = STATUS_INVALID_NETWORK_RESPONSE;
+        goto end;
+    }
+
+    /* How many bytes remain in the buffer. */
+    cbHGCMBuffer = u32BufSize;
+
+    pDirEntry = (PSHFLDIRINFO)pHGCMBuffer;
+    Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: QueryDirectory: cFiles=%d, Length=%d\n", cFiles, cbHGCMBuffer));
+    while ((*pLengthRemaining) && (cFiles > 0) && (pDirEntry != NULL))
+    {
+        int cbEntry = RT_OFFSETOF(SHFLDIRINFO, name.String) + pDirEntry->name.u16Size;
+
+        if (cbEntry > cbHGCMBuffer)
+        {
+            Log(("VBOXSF: QueryDirectory: Entry size (%d) exceeds the buffer size (%d)!!!\n", cbEntry, cbHGCMBuffer));
+            Status = STATUS_INVALID_NETWORK_RESPONSE;
+            goto end;
+        }
+
+        switch (FileInformationClass)
+        {
+        case FileDirectoryInformation:
+        {
+            PFILE_DIRECTORY_INFORMATION pDirInfo = (PFILE_DIRECTORY_INFORMATION)Buffer;
+            CopySize = sizeof(FILE_DIRECTORY_INFORMATION);
+
+            /* Struct already contains one char for null terminator. */
+            CopySize += pDirEntry->name.u16Size;
+
+            Log(("VBOXSF: QueryDirectory: FileDirectoryInformation Buffer=%08x\n", Buffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory( pDirInfo, CopySize );
+
+                pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                pDirInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                pDirInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                pDirInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                pDirInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                pDirInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
+
+                pDirInfo->FileIndex = index;
+                pDirInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                INIT_FILE_NAME(pDirInfo, pDirEntry->name);
+
+                /* Align to 8 byte boundary */
+                CopySize = RT_ALIGN(CopySize, sizeof(LONGLONG));
+                pDirInfo->NextEntryOffset = CopySize;
+                pNextOffset = &pDirInfo->NextEntryOffset;
+            }
+            else
+            {
+                pDirInfo->NextEntryOffset = 0; /* last item */
+                Status = STATUS_BUFFER_OVERFLOW;
+            }
+            break;
+        }
+
+        case FileFullDirectoryInformation:
+        {
+            PFILE_FULL_DIR_INFORMATION pDirInfo = (PFILE_FULL_DIR_INFORMATION)Buffer;
+            CopySize = sizeof(FILE_FULL_DIR_INFORMATION);
+
+            /* Struct already contains one char for null terminator. */
+            CopySize += pDirEntry->name.u16Size;
+
+            Log(("VBOXSF: QueryDirectory: FileFullDirectoryInformation Buffer=%08x\n", Buffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory( pDirInfo, CopySize );
+
+                pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                pDirInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                pDirInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                pDirInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                pDirInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                pDirInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
+
+                pDirInfo->EaSize = 0;
+                pDirInfo->FileIndex = index;
+                pDirInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                INIT_FILE_NAME(pDirInfo, pDirEntry->name);
+
+                /* Align to 8 byte boundary */
+                CopySize = RT_ALIGN(CopySize, sizeof(LONGLONG));
+                pDirInfo->NextEntryOffset = CopySize;
+                pNextOffset = &pDirInfo->NextEntryOffset;
+            }
+            else
+            {
+                pDirInfo->NextEntryOffset = 0; /* last item */
+                Status = STATUS_BUFFER_OVERFLOW;
+            }
+            break;
+        }
+
+        case FileBothDirectoryInformation:
+        {
+            PFILE_BOTH_DIR_INFORMATION pDirInfo = (PFILE_BOTH_DIR_INFORMATION)Buffer;
+            CopySize = sizeof(FILE_BOTH_DIR_INFORMATION);
+            /* struct already contains one char for null terminator */
+            CopySize += pDirEntry->name.u16Size;
+
+            Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation Buffer=%08x\n", Buffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory( pDirInfo, CopySize );
+
+                pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                pDirInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                pDirInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                pDirInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                pDirInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                pDirInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
+
+                pDirInfo->EaSize = 0;
+                pDirInfo->ShortNameLength = 0; /* @todo ? */
+                pDirInfo->FileIndex = index;
+                pDirInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                INIT_FILE_NAME(pDirInfo, pDirEntry->name);
+
+                Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation cbAlloc = %x cbObject = %x\n", pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
+                Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation CopySize = %d, name size=%d name len=%d\n", CopySize, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
+                Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation File name %.*ls (DirInfo)\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
+                Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation File name %.*ls (DirEntry)\n", pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
+
+                /* Align to 8 byte boundary. */
+                CopySize = RT_ALIGN(CopySize, sizeof(LONGLONG));
+                pDirInfo->NextEntryOffset = CopySize;
+                pNextOffset = &pDirInfo->NextEntryOffset;
+            }
+            else
+            {
+                pDirInfo->NextEntryOffset = 0; /* Last item. */
+                Status = STATUS_BUFFER_OVERFLOW;
+            }
+            break;
+        }
+
+        case FileIdBothDirectoryInformation:
+        {
+            PFILE_ID_BOTH_DIR_INFORMATION pDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)Buffer;
+            CopySize = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
+            /* struct already contains one char for null terminator */
+            CopySize += pDirEntry->name.u16Size;
+
+            Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation Buffer=%08x\n", Buffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory( pDirInfo, CopySize );
+
+                pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                pDirInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                pDirInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                pDirInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                pDirInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                pDirInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
+
+                pDirInfo->EaSize = 0;
+                pDirInfo->ShortNameLength = 0; /* @todo ? */
+                pDirInfo->EaSize = 0;
+                pDirInfo->FileId.QuadPart = 0;
+                pDirInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                INIT_FILE_NAME(pDirInfo, pDirEntry->name);
+
+                Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation cbAlloc = %x cbObject = %x\n", pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
+                Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation CopySize = %d, name size=%d name len=%d\n", CopySize, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
+                Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirInfo)\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
+                Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirEntry)\n", pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
+
+                /* Align to 8 byte boundary. */
+                CopySize = RT_ALIGN(CopySize, sizeof(LONGLONG));
+                pDirInfo->NextEntryOffset = CopySize;
+                pNextOffset = &pDirInfo->NextEntryOffset;
+            }
+            else
+            {
+                pDirInfo->NextEntryOffset = 0; /* Last item. */
+                Status = STATUS_BUFFER_OVERFLOW;
+            }
+            break;
+        }
+
+        case FileNamesInformation:
+        {
+            PFILE_NAMES_INFORMATION pDirInfo = (PFILE_NAMES_INFORMATION)Buffer;
+            CopySize = sizeof(FILE_NAMES_INFORMATION);
+
+            /* Struct already contains one char for null terminator. */
+            CopySize += pDirEntry->name.u16Size;
+
+            Log(("VBOXSF: QueryDirectory: FileNamesInformation Buffer=%08x\n", Buffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory( pDirInfo, CopySize );
+
+                pDirInfo->FileIndex = index;
+
+                INIT_FILE_NAME(pDirInfo, pDirEntry->name);
+
+                Log(("VBOXSF: QueryDirectory: FileNamesInformation File name %.*ls\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
+
+                /* Align to 8 byte boundary. */
+                CopySize = RT_ALIGN(CopySize, sizeof(LONGLONG));
+                pDirInfo->NextEntryOffset = CopySize;
+                pNextOffset = &pDirInfo->NextEntryOffset;
+            }
+            else
+            {
+                pDirInfo->NextEntryOffset = 0; /* Last item. */
+                Status = STATUS_BUFFER_OVERFLOW;
+            }
+            break;
+        }
+
+        default:
+            Log(("VBOXSF: QueryDirectory: Invalid FS information class %d!\n", FileInformationClass));
+            Status = STATUS_INVALID_PARAMETER;
+            goto end;
+        }
+
+        cbHGCMBuffer -= cbEntry;
+        pDirEntry = (PSHFLDIRINFO)((uintptr_t)pDirEntry + cbEntry);
+        Log(("VBOXSF: QueryDirectory: %d bytes left in HGCM buffer\n", cbHGCMBuffer));
+
+        if (*pLengthRemaining >= CopySize)
+        {
+            Buffer += CopySize;
+            *pLengthRemaining -= CopySize;
+        }
+        else break;
+
+        if (RxContext->QueryDirectory.ReturnSingleEntry)
+            break;
+
+        /* More left? */
+        if (cbHGCMBuffer <= 0)
+            break;
+
+        index++; /* File Index. */
+
+        cFiles--;
+    }
+    if (pNextOffset)
+        *pNextOffset = 0; /* Last pDirInfo->NextEntryOffset should be set to zero! */
+
+    end: if (pHGCMBuffer)
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+    if (ParsedPath)
+        vbsfFreeNonPagedMem(ParsedPath);
+
+    Log(("VBOXSF: QueryDirectory: Returned 0x%x\n", Status));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxQueryVolumeInformationWithFullBuffer (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine queries the volume information
+
+ Arguments:
+
+ pRxContext         - the RDBSS context
+
+ FsInformationClass - the kind of Fs information desired.
+
+ pBuffer            - the buffer for copying the information
+
+ pBufferLength      - the buffer length ( set to buffer length on input and set
+ to the remaining length on output)
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_INVALID_PARAMETER;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot, pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    ULONG OriginalLength = RxContext->Info.LengthRemaining;
+    FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
+    PVOID OriginalBuffer = RxContext->Info.Buffer;
+    ULONG BytesToCopy, cbMaxSize;
+
+    if (NULL != pVBoxFobx)
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: vboxFobx = %p, Handle = 0x%08x\n", pVBoxFobx, pVBoxFobx->hFile));
+
+    cbMaxSize = RxContext->Info.Length;
+
+    switch (FsInformationClass)
+    {
+    case FileFsVolumeInformation:
+    {
+        PFILE_FS_VOLUME_INFORMATION pVolInfo = (PFILE_FS_VOLUME_INFORMATION)OriginalBuffer;
+        PWCHAR pRootName;
+        ULONG RootNameLength;
+        PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+        PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+        PSHFLVOLINFO pSHFLVolInfo;
+        uint32_t cbHGCMBuffer;
+        uint8_t *pHGCMBuffer = NULL;
+        int vboxRC;
+
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
+        if (RxContext->Info.LengthRemaining < sizeof(FILE_FS_VOLUME_INFORMATION))
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Insufficient buffer size (%d)\n", RxContext->Info.LengthRemaining));
+            Status = STATUS_BUFFER_TOO_SMALL;
+            break;
+        }
+
+        if (NULL == pVBoxFobx)
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: pVBoxFobx is invalid!\n"));
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        RtlZeroMemory( pVolInfo, sizeof(FILE_FS_VOLUME_INFORMATION) );
+
+        RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
+        RootNameLength -= 2; /* remove leading backslash */
+
+        pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
+        pRootName++; /* remove leading backslash */
+
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Root name = %.*ls\n", RootNameLength / sizeof(WCHAR), pRootName));
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Prefix %ls has %d elements\n", VBOX_VOLNAME_PREFIX, RT_ELEMENTS(VBOX_VOLNAME_PREFIX)));
+
+        /* Query serial number. */
+        cbHGCMBuffer = sizeof(SHFLVOLINFO);
+        pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+        if (pHGCMBuffer == 0)
+        {
+            AssertFailed();
+            Status = STATUS_NO_MEMORY;
+            break;
+        }
+
+        vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
+        AssertRC(vboxRC);
+
+        if (vboxRC != VINF_SUCCESS)
+        {
+            Status = VBoxErrorToNTStatus(vboxRC);
+            vbsfFreeNonPagedMem(pHGCMBuffer);
+            break;
+        }
+
+        pSHFLVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
+        pVolInfo->VolumeSerialNumber = pSHFLVolInfo->ulSerial;
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+        pVolInfo->VolumeCreationTime.QuadPart = 0;
+        pVolInfo->VolumeLabelLength = RootNameLength + VBOX_VOLNAME_PREFIX_SIZE;
+        pVolInfo->SupportsObjects = FALSE;
+
+        RxContext->Info.LengthRemaining -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
+
+        if (RxContext->Info.LengthRemaining >= (LONG)pVolInfo->VolumeLabelLength)
+        {
+            BytesToCopy = pVolInfo->VolumeLabelLength;
+
+            /* Copy prefix */
+            RtlCopyMemory( &pVolInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, VBOX_VOLNAME_PREFIX_SIZE);
+
+            /* Copy share name (- 1 for zero terminator) */
+            RtlCopyMemory( &pVolInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, RootNameLength );
+        }
+        else
+        {
+            BytesToCopy = RxContext->Info.LengthRemaining;
+
+            /* Copy prefix */
+            RtlCopyMemory( &pVolInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, RT_MIN(BytesToCopy, VBOX_VOLNAME_PREFIX_SIZE) );
+
+            if (BytesToCopy > VBOX_VOLNAME_PREFIX_SIZE)
+            {
+                /* Copy share name (- 1 for zero terminator) */
+                RtlCopyMemory( &pVolInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, BytesToCopy - VBOX_VOLNAME_PREFIX_SIZE );
+            }
+        }
+
+        RxContext->Info.LengthRemaining -= BytesToCopy;
+        pVolInfo->VolumeLabelLength = BytesToCopy;
+
+        Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FileFsLabelInformation:
+    {
+        PFILE_FS_LABEL_INFORMATION pLabelInfo = (PFILE_FS_LABEL_INFORMATION)OriginalBuffer;
+        PWCHAR pRootName;
+        ULONG RootNameLength;
+        PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+        PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
+        if (RxContext->Info.LengthRemaining < sizeof(PFILE_FS_LABEL_INFORMATION))
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Insufficient buffer size (%d)\n", RxContext->Info.LengthRemaining));
+            Status = STATUS_BUFFER_TOO_SMALL;
+            break;
+        }
+        RtlZeroMemory( pLabelInfo, sizeof(FILE_FS_LABEL_INFORMATION) );
+
+        RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
+        RootNameLength -= 2; /* remove leading backslash */
+
+        pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
+        pRootName++; /* remove leading backslash */
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Root name = %.*ls\n", RootNameLength / sizeof(WCHAR), pRootName));
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Prefix %ls has %d elements\n", VBOX_VOLNAME_PREFIX, RT_ELEMENTS(VBOX_VOLNAME_PREFIX)));
+
+        pLabelInfo->VolumeLabelLength = RootNameLength + VBOX_VOLNAME_PREFIX_SIZE;
+        RxContext->Info.LengthRemaining -= FIELD_OFFSET(FILE_FS_LABEL_INFORMATION, VolumeLabel[0]);
+
+        if (RxContext->Info.LengthRemaining >= (LONG)pLabelInfo->VolumeLabelLength)
+        {
+            BytesToCopy = pLabelInfo->VolumeLabelLength;
+
+            /* Copy prefix */
+            RtlCopyMemory( &pLabelInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, VBOX_VOLNAME_PREFIX_SIZE);
+
+            /* Copy share name (- 1 for zero terminator) */
+            RtlCopyMemory( &pLabelInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, RootNameLength );
+        }
+        else
+        {
+            BytesToCopy = RxContext->Info.LengthRemaining;
+
+            /* Copy prefix */
+            RtlCopyMemory( &pLabelInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, RT_MIN(BytesToCopy, VBOX_VOLNAME_PREFIX_SIZE) );
+
+            if (BytesToCopy > VBOX_VOLNAME_PREFIX_SIZE)
+            {
+                /* Copy share name (- 1 for zero terminator) */
+                RtlCopyMemory( &pLabelInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, BytesToCopy - VBOX_VOLNAME_PREFIX_SIZE );
+            }
+        }
+        RxContext->Info.LengthRemaining -= BytesToCopy;
+        pLabelInfo->VolumeLabelLength = BytesToCopy;
+
+        Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FileFsFullSizeInformation:
+    case FileFsSizeInformation:
+    {
+        PFILE_FS_FULL_SIZE_INFORMATION pFullSizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)OriginalBuffer;
+        PFILE_FS_SIZE_INFORMATION pSizeInfo = (PFILE_FS_SIZE_INFORMATION)OriginalBuffer;
+        uint32_t cbHGCMBuffer;
+        uint8_t *pHGCMBuffer = NULL;
+        int vboxRC;
+        PSHFLVOLINFO pVolInfo;
+
+        if (FsInformationClass == FileFsFullSizeInformation)
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
+            BytesToCopy = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
+        }
+        else
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
+            BytesToCopy = sizeof(FILE_FS_SIZE_INFORMATION);
+        }
+
+        if (RxContext->Info.LengthRemaining < (LONG)BytesToCopy)
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation/FileFsSizeInformation: Insufficient buffer size (%d)!\n", RxContext->Info.LengthRemaining));
+            Status = STATUS_BUFFER_TOO_SMALL;
+            break;
+        }
+
+        if (NULL == pVBoxFobx)
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: pVBoxFobx is invalid!\n"));
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        RtlZeroMemory( pSizeInfo, BytesToCopy );
+
+        cbHGCMBuffer = sizeof(SHFLVOLINFO);
+        pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+        if (pHGCMBuffer == 0)
+        {
+            AssertFailed();
+            Status = STATUS_NO_MEMORY;
+            break;
+        }
+
+        vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
+        AssertRC(vboxRC);
+
+        if (vboxRC != VINF_SUCCESS)
+        {
+            Status = VBoxErrorToNTStatus(vboxRC);
+            vbsfFreeNonPagedMem(pHGCMBuffer);
+            break;
+        }
+
+        pVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
+
+        if (FsInformationClass == FileFsFullSizeInformation)
+        {
+            pFullSizeInfo->SectorsPerAllocationUnit = pVolInfo->ulBytesPerAllocationUnit / pVolInfo->ulBytesPerSector;
+            pFullSizeInfo->BytesPerSector = pVolInfo->ulBytesPerSector;
+            pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart = pVolInfo->ullAvailableAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
+            pFullSizeInfo->CallerAvailableAllocationUnits.QuadPart = pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart;
+            pFullSizeInfo->TotalAllocationUnits.QuadPart = pVolInfo->ullTotalAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
+
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: SectorsPerAllocationUnit       %08x\n", (ULONG)pFullSizeInfo->SectorsPerAllocationUnit));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: BytesPerSector                 %08x\n", (ULONG)pFullSizeInfo->BytesPerSector));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: ActualAvailableAllocationUnits %RX64\n", pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: TotalAllocationUnits           %RX64\n", pFullSizeInfo->TotalAllocationUnits.QuadPart));
+        }
+        else
+        {
+            pSizeInfo->SectorsPerAllocationUnit = pVolInfo->ulBytesPerAllocationUnit / pVolInfo->ulBytesPerSector;
+            pSizeInfo->BytesPerSector = pVolInfo->ulBytesPerSector;
+            pSizeInfo->AvailableAllocationUnits.QuadPart = pVolInfo->ullAvailableAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
+            pSizeInfo->TotalAllocationUnits.QuadPart = pVolInfo->ullTotalAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
+
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: SectorsPerAllocationUnit       %08x\n", (ULONG)pSizeInfo->SectorsPerAllocationUnit));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: BytesPerSector                 %08x\n", (ULONG)pSizeInfo->BytesPerSector));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: AvailableAllocationUnits       %RX64\n", pSizeInfo->AvailableAllocationUnits.QuadPart));
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: TotalAllocationUnits           %RX64\n", pSizeInfo->TotalAllocationUnits.QuadPart));
+        }
+
+        if (pHGCMBuffer)
+            vbsfFreeNonPagedMem(pHGCMBuffer);
+
+        RxContext->Info.LengthRemaining -= BytesToCopy;
+        Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FileFsDeviceInformation:
+    {
+        PFILE_FS_DEVICE_INFORMATION pDevInfo = (PFILE_FS_DEVICE_INFORMATION)OriginalBuffer;
+        PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
+
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsDeviceInformation: Type = 0x%x\n", NetRoot->DeviceType));
+        Status = STATUS_SUCCESS;
+
+        BytesToCopy = sizeof(FILE_FS_DEVICE_INFORMATION);
+        if (RxContext->Info.LengthRemaining >= (LONG)BytesToCopy)
+        {
+            pDevInfo->DeviceType = NetRoot->DeviceType;
+            pDevInfo->Characteristics = FILE_REMOTE_DEVICE;
+
+            if (NetRoot->Type == NET_ROOT_PIPE)
+            {
+                NetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            RxContext->Info.LengthRemaining -= BytesToCopy;
+        }
+        else
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsDeviceInformation: Buffer too small (%d vs %d)!\n", RxContext->Info.LengthRemaining, BytesToCopy));
+            Status = STATUS_BUFFER_TOO_SMALL;
+        }
+        break;
+    }
+
+    case FileFsAttributeInformation:
+    {
+        PFILE_FS_ATTRIBUTE_INFORMATION pAttribInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)OriginalBuffer;
+
+        BytesToCopy = sizeof(MRX_VBOX_FILESYS_NAME_U) + FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]);
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsAttributeInformation: BytesToCopy = %d\n", BytesToCopy));
+        if (RxContext->Info.LengthRemaining < (LONG)BytesToCopy)
+        {
+            Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsAttributeInformation: Buffer too small (%d)!\n", RxContext->Info.LengthRemaining));
+            Status = STATUS_BUFFER_TOO_SMALL;
+            break;
+        }
+
+        /** @todo set unicode, case sensitive etc? */
+        pAttribInfo->FileSystemAttributes = 0;
+        pAttribInfo->MaximumComponentNameLength = 255; /** @todo should query from the host */
+        pAttribInfo->FileSystemNameLength = sizeof(MRX_VBOX_FILESYS_NAME_U);
+        RtlCopyMemory( pAttribInfo->FileSystemName, MRX_VBOX_FILESYS_NAME_U, pAttribInfo->FileSystemNameLength);
+
+        RxContext->Info.LengthRemaining -= BytesToCopy;
+        Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FileFsControlInformation:
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsControlInformation (skipping ...)\n"));
+        break;
+
+    case FileFsObjectIdInformation:
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsObjectIdInformation (skipping ...)\n"));
+        break;
+
+    case FileFsMaximumInformation:
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsMaximumInformation (skipping ...)\n"));
+        break;
+
+    default:
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: Invalid parameter!\n"));
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+    }
+
+    Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: Returned 0x%x\n", Status));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxQueryVolumeInformation (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine queries the volume information. Since the NT server does not
+ handle bufferoverflow gracefully on query-fs-info, we allocate a buffer here
+ that is big enough to hold anything passed back; then we call the "real"
+ queryvolinfo routine.
+
+ Arguments:
+
+ pRxContext         - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PVOID OriginalBuffer = RxContext->Info.Buffer;
+    ULONG OriginalLength = RxContext->Info.LengthRemaining;
+    ULONG ReturnedLength;
+
+    BOOLEAN UsingSideBuffer = FALSE;
+    uint32_t cbSideBuffer = 0;
+
+    typedef struct
+    {
+        union
+        {
+            FILE_FS_LABEL_INFORMATION labelinfo;
+            FILE_FS_VOLUME_INFORMATION volumeinfo;
+            FILE_FS_SIZE_INFORMATION sizeinfo;
+            FILE_FS_DEVICE_INFORMATION deviceinfo;
+            FILE_FS_ATTRIBUTE_INFORMATION attributeinfo;
+        } Info;
+        WCHAR VolumeName[MAXIMUM_FILENAME_LENGTH];
+    } SideBuffer;
+
+    SideBuffer *pSideBuffer = NULL;
+
+    PAGED_CODE();
+
+    Log(
+        ("VBOXSF: VBoxMRxQueryVolumeInformation: rxContextBufferAddr = 0x%x, rxContextBufferLengthRem = %d, (SideBufferSize = %d)\n", RxContext->Info.Buffer, RxContext->Info.LengthRemaining, sizeof(SideBuffer)));
+    if (RxContext->Info.LengthRemaining < sizeof(SideBuffer))
+    {
+        /* I replace the buffer and length in the context with my stuff. */
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformation: Using Sidebuffer ...\n"));
+        UsingSideBuffer = TRUE;
+        RxContext->Info.Buffer = vbsfAllocNonPagedMem(sizeof(SideBuffer));
+        pSideBuffer = (SideBuffer *)RxContext->Info.Buffer;
+        RxContext->Info.LengthRemaining = sizeof(SideBuffer);
+    }
+
+    Status = VBoxMRxQueryVolumeInformationWithFullBuffer(RxContext);
+    Assert(Status != STATUS_PENDING);
+
+    Log(("VBOXSF: VBoxMRxQueryVolumeInformation: RxContext->Info.LengthRemaining = %d\n", RxContext->Info.LengthRemaining));
+
+    if (Status != STATUS_SUCCESS)
+    {
+        RxContext->Info.Buffer = OriginalBuffer;
+        RxContext->Info.LengthRemaining = OriginalLength;
+
+        Log(("VBOXSF: VBoxMRxQueryVolumeInformation: VBoxMRxQueryVolumeInformationWithFullBuffer failed with 0x%x\n", Status));
+        goto FINALLY;
+    }
+
+    if (UsingSideBuffer == TRUE)
+    {
+        ReturnedLength = sizeof(SideBuffer) - RxContext->Info.LengthRemaining;
+    }
+    else
+    {
+        ReturnedLength = OriginalLength - RxContext->Info.LengthRemaining;
+    }
+
+    Log(("VBOXSF: VBoxMRxQueryVolumeInformation: ReturnedLength = %d, OriginalLength = %d\n", ReturnedLength, OriginalLength));
+    if (ReturnedLength > OriginalLength)
+    {
+        Status = STATUS_BUFFER_OVERFLOW;
+        ReturnedLength = OriginalLength;
+    }
+
+    if (UsingSideBuffer == TRUE)
+    {
+        RtlCopyMemory(OriginalBuffer, pSideBuffer, ReturnedLength);
+    }
+
+    RxContext->Info.Buffer = OriginalBuffer;
+    RxContext->Info.LengthRemaining = OriginalLength - ReturnedLength;
+    Log(("VBOXSF: VBoxMRxQueryVolumeInformation: OriginalLength = %d, LengthRemaining = %d, Status = 0x%x\n", OriginalLength, RxContext->Info.LengthRemaining, Status));
+    Log(("VBOXSF: VBoxMRxQueryVolumeInformation: Final rxContextBufferAddr = 0x%x, rxContextBufferLengthRem = %d\n", RxContext->Info.Buffer, RxContext->Info.LengthRemaining));
+
+    FINALLY:
+
+    if (NULL != pSideBuffer)
+        vbsfFreeNonPagedMem(pSideBuffer);
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetVolumeInformation (IN OUT PRX_CONTEXT pRxContext)
+/*++
+
+ Routine Description:
+
+ This routine sets the volume information
+
+ Arguments:
+
+ pRxContext - the RDBSS context
+
+ FsInformationClass - the kind of Fs information desired.
+
+ pBuffer            - the buffer for copying the information
+
+ BufferLength       - the buffer length
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    Log(("VBOXSF: VBoxMRxSetVolumeInformation called.\n"));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxQueryFileInformation (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine does a query file info. Only the NT-->NT path is implemented.
+
+ The NT-->NT path works by just remoting the call basically without further ado.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG CopySize = 0;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
+
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot, pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+
+    uint8_t *pHGCMBuffer = 0;
+    int vboxRC = 0;
+    uint32_t cbHGCMBuffer, cbMaxSize = 0;
+    PRTFSOBJINFO pFileEntry = NULL;
+    PCHAR pInfoBuffer = NULL;
+    ULONG *pLengthRemaining = NULL;
+
+    pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
+    cbMaxSize = RxContext->Info.Length;
+    pLengthRemaining = (PULONG) & RxContext->Info.LengthRemaining;
+
+    if (NULL == pLengthRemaining)
+    {
+        Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid length pointer detected!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Log(("VBOXSF: VBoxMRxQueryFileInformation: InfoBuffer = 0x%08x, Size = %d bytes, LenRemain = %d bytes\n", pInfoBuffer, cbMaxSize, *pLengthRemaining));
+
+    if (NULL == pVBoxFobx)
+    {
+        Log(("VBOXSF: VBoxMRxQueryFileInformation: pVBoxFobx is invalid!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (NULL == pInfoBuffer)
+    {
+        Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid information buffer detected!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (pVBoxFobx->FileStandardInfo.Directory == TRUE)
+    {
+        Log(("VBOXSF: VBoxMRxQueryFileInformation: Directory -> Copy info retrieved during the create call\n"));
+        Status = STATUS_SUCCESS;
+
+        switch (FunctionalityRequested)
+        {
+
+        case FileBasicInformation:
+        {
+            PFILE_BASIC_INFORMATION pFileInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_BASIC_INFORMATION);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer = 0x%08x\n", pFileInfo));
+            if (*pLengthRemaining >= CopySize)
+            {
+                *pFileInfo = pVBoxFobx->FileBasicInfo;
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: File attributes: 0x%x\n", pFileInfo->FileAttributes));
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileStandardInformation:
+        {
+            PFILE_STANDARD_INFORMATION pFileInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_STANDARD_INFORMATION);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer = 0x%08x\n", pFileInfo));
+            if (*pLengthRemaining >= CopySize)
+            {
+                *pFileInfo = pVBoxFobx->FileStandardInfo;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileNamesInformation:
+        {
+            PFILE_NAMES_INFORMATION pFileInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_NAMES_INFORMATION);
+
+            /* Struct already contains one char for null terminator. */
+            CopySize += (FileName->Length + 1) * sizeof(WCHAR);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer = %08x\n", pFileInfo));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory (pFileInfo, CopySize);
+
+                pFileInfo->FileIndex = 0;
+                pFileInfo->FileNameLength = FileName->Length * sizeof(WCHAR);
+                RtlCopyMemory(pFileInfo->FileName, FileName->Buffer, pFileInfo->FileNameLength);
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileInternalInformation:
+        {
+            PFILE_INTERNAL_INFORMATION UsersBuffer = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer = 0x%08x\n", pInfoBuffer));
+
+            /*
+             *  Note: We use the address of the FCB to determine the
+             *  index number of the file.  If we have to maintain persistance between
+             *  file opens for this request, then we might have to do something
+             *  like checksuming the reserved fields on a FUNIQUE SMB response.
+             *
+
+             *
+             * NT64: the address of capFcb used to be stuffed into
+             *       IndexNumber.LowPart, with HighPart being zeroed.
+             *
+             *       Whoever is asking for this pointer value should be
+             *       prepared to deal with the returned 64-bit value.
+             */
+
+            CopySize = sizeof(FILE_INTERNAL_INFORMATION);
+
+            if (*pLengthRemaining >= CopySize)
+            {
+                UsersBuffer->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer overflow (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+        case FileEaInformation:
+        {
+            PFILE_EA_INFORMATION EaBuffer = (PFILE_EA_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer = 0x%08x\n", pInfoBuffer));
+
+            CopySize = sizeof(FILE_EA_INFORMATION);
+            if (*pLengthRemaining >= CopySize)
+            {
+                EaBuffer->EaSize = 0;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer overflow (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileNetworkOpenInformation:
+        {
+            PFILE_NETWORK_OPEN_INFORMATION pFileInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer = 0x%08x\n", pInfoBuffer));
+
+            CopySize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+            if (*pLengthRemaining >= CopySize)
+            {
+                pFileInfo->CreationTime = pVBoxFobx->FileBasicInfo.CreationTime;
+                pFileInfo->LastAccessTime = pVBoxFobx->FileBasicInfo.LastAccessTime;
+                pFileInfo->LastWriteTime = pVBoxFobx->FileBasicInfo.LastWriteTime;
+                pFileInfo->ChangeTime = pVBoxFobx->FileBasicInfo.ChangeTime;
+                pFileInfo->AllocationSize.QuadPart = 0; /* This is a directory, attribute not needed. */
+                pFileInfo->EndOfFile.QuadPart = 0; /* This is a directory, attribute not needed. */
+                pFileInfo->FileAttributes = pVBoxFobx->FileBasicInfo.FileAttributes;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        default:
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid filesystem information class %d!\n", FunctionalityRequested));
+            Status = STATUS_NOT_IMPLEMENTED;
+            goto end;
+        }
+    }
+    else /* Entry is a file. */
+    {
+        cbHGCMBuffer = RT_MAX(cbMaxSize, PAGE_SIZE);
+        pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+
+        if (pHGCMBuffer == 0)
+            return STATUS_NO_MEMORY;
+
+        Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
+        vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_FILE, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
+
+        if (vboxRC != VINF_SUCCESS)
+        {
+            Status = VBoxErrorToNTStatus(vboxRC);
+            goto end;
+        }
+
+        pFileEntry = (PRTFSOBJINFO)pHGCMBuffer;
+        Status = STATUS_SUCCESS;
+
+        switch (FunctionalityRequested)
+        {
+
+        case FileBasicInformation:
+        {
+            PFILE_BASIC_INFORMATION pFileInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_BASIC_INFORMATION);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                pFileInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
+                pFileInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
+                pFileInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
+                pFileInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
+
+                pFileInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: File attributes = 0x%x\n", pFileInfo->FileAttributes));
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileStandardInformation:
+        {
+            PFILE_STANDARD_INFORMATION pFileInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_STANDARD_INFORMATION);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                pFileInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
+                pFileInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
+
+                pFileInfo->NumberOfLinks = 1; /* @todo 0? */
+                pFileInfo->DeletePending = FALSE;
+
+                if (pFileEntry->Attr.fMode & RTFS_DOS_DIRECTORY)
+                    pFileInfo->Directory = TRUE;
+                else pFileInfo->Directory = FALSE;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileNamesInformation:
+        {
+            PFILE_NAMES_INFORMATION pFileInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
+
+            CopySize = sizeof(FILE_NAMES_INFORMATION);
+
+            /* Struct already contains one char for null terminator */
+            CopySize += (FileName->Length + 1) * sizeof(WCHAR);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                RtlZeroMemory (pFileInfo, CopySize);
+
+                pFileInfo->FileIndex = 0;
+                pFileInfo->FileNameLength = FileName->Length * sizeof(WCHAR);
+                RtlCopyMemory(pFileInfo->FileName, FileName->Buffer, pFileInfo->FileNameLength);
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileInternalInformation:
+        {
+            PFILE_INTERNAL_INFORMATION UsersBuffer = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer = 0x%08x\n", pInfoBuffer));
+
+            /* Note: We use the address of the FCB to determine the
+             index number of the file.  If we have to maintain persistance between
+             file opens for this request, then we might have to do something
+             like checksuming the reserved fields on a FUNIQUE SMB response.
+
+             NT64: the address of capFcb used to be stuffed into
+             IndexNumber.LowPart, with HighPart being zeroed.
+
+             Whoever is asking for this pointer value should be
+             prepared to deal with the returned 64-bit value. */
+            CopySize = sizeof(FILE_INTERNAL_INFORMATION);
+
+            if (*pLengthRemaining >= CopySize)
+            {
+                UsersBuffer->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileEaInformation:
+        {
+            PFILE_EA_INFORMATION EaBuffer = (PFILE_EA_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            CopySize = sizeof(FILE_EA_INFORMATION);
+
+            if (*pLengthRemaining >= CopySize)
+            {
+                EaBuffer->EaSize = 0;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileAttributeTagInformation:
+        {
+            PFILE_ATTRIBUTE_TAG_INFORMATION pAttrTag = (PFILE_ATTRIBUTE_TAG_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAttributeTagInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            CopySize = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
+            if (*pLengthRemaining >= CopySize)
+            {
+                pAttrTag->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
+                pAttrTag->ReparseTag = 0;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAttributeTagInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileEndOfFileInformation:
+        {
+            PFILE_END_OF_FILE_INFORMATION pEndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEndOfFileInformation: Buffer = %08x\n", pInfoBuffer));
+
+            CopySize = sizeof(FILE_END_OF_FILE_INFORMATION);
+            if (*pLengthRemaining >= CopySize)
+            {
+                pEndOfFileInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEndOfFileInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileAllocationInformation:
+        {
+            PFILE_ALLOCATION_INFORMATION pAllocInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAllocationInformation: Buffer = 0x%08x\n", pInfoBuffer));
+
+            CopySize = sizeof(FILE_ALLOCATION_INFORMATION);
+            if (*pLengthRemaining >= CopySize)
+            {
+                pAllocInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAllocationInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        case FileNetworkOpenInformation:
+        {
+            PFILE_NETWORK_OPEN_INFORMATION pFileInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
+            CopySize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer = 0x%08x\n", pInfoBuffer));
+            if (*pLengthRemaining >= CopySize)
+            {
+                pFileInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
+                pFileInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
+                pFileInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
+                pFileInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
+                pFileInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
+                pFileInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
+                pFileInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
+                Status = STATUS_BUFFER_TOO_SMALL;
+            }
+            break;
+        }
+
+        default:
+            Log(("VBOXSF: VBoxMRxQueryFileInformation: Unknown functionality requested (0x%x)!\n", FunctionalityRequested));
+            Status = STATUS_NOT_IMPLEMENTED;
+            goto end;
+        }
+    }
+
+    if (Status == STATUS_SUCCESS)
+    {
+        if (*pLengthRemaining < CopySize)
+        {
+            /* This situation must be already taken into account by the above code. */
+            AssertMsgFailed(("VBOXSF: VBoxMRxQueryFileInformation: Length remaing is below 0! (%d - %d)!\n", *pLengthRemaining, CopySize));
+            Status = STATUS_BUFFER_TOO_SMALL;
+        }
+        else
+        {
+            pInfoBuffer += CopySize;
+            *pLengthRemaining -= CopySize;
+        }
+    }
+
+    end: if (Status == STATUS_BUFFER_TOO_SMALL)
+        RxContext->InformationToReturn = CopySize;
+
+    if (pHGCMBuffer)
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+    if (Status == STATUS_SUCCESS)
+        Log(("VBOXSF: VBoxMRxQueryFileInformation: Success! Remaining length = %d\n", *pLengthRemaining));
+
+    Log(("VBOXSF: VBoxMRxQueryFileInformation: Returned 0x%x\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetFileInformation (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine does a set file info. Only the NT-->NT path is implemented.
+
+ The NT-->NT path works by just remoting the call basically without further ado.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot, pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
+    PVOID pBuffer = (PVOID)RxContext->Info.Buffer;
+    uint8_t *pHGCMBuffer = 0;
+    uint32_t cbBuffer = 0;
+    int vboxRC;
+
+    Log(("VBOXSF: VBoxMRxSetFileInformation called.\n"));
+
+    switch (FunctionalityRequested)
+    {
+    case FileBasicInformation:
+    {
+        PFILE_BASIC_INFORMATION pFileInfo = (PFILE_BASIC_INFORMATION)pBuffer;
+        PRTFSOBJINFO pSHFLFileInfo;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: CreationTime    %RX64\n", pFileInfo->CreationTime.QuadPart));
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: LastAccessTime  %RX64\n", pFileInfo->LastAccessTime.QuadPart));
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: LastWriteTime   %RX64\n", pFileInfo->LastWriteTime.QuadPart));
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: ChangeTime      %RX64\n", pFileInfo->ChangeTime.QuadPart));
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: FileAttributes  %RX32\n", pFileInfo->FileAttributes));
+
+        /* When setting file attributes, a value of -1 indicates to the server that it MUST NOT change this attribute
+         * for all subsequent operations on the same file handle.
+         */
+        if (pFileInfo->CreationTime.QuadPart == -1)
+        {
+            pVBoxFobx->fKeepCreationTime = TRUE;
+        }
+        if (pFileInfo->LastAccessTime.QuadPart == -1)
+        {
+            pVBoxFobx->fKeepLastAccessTime = TRUE;
+        }
+        if (pFileInfo->LastWriteTime.QuadPart == -1)
+        {
+            pVBoxFobx->fKeepLastWriteTime = TRUE;
+        }
+        if (pFileInfo->ChangeTime.QuadPart == -1)
+        {
+            pVBoxFobx->fKeepChangeTime = TRUE;
+        }
+
+        cbBuffer = sizeof(RTFSOBJINFO);
+        pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbBuffer);
+        if (pHGCMBuffer == 0)
+        {
+            AssertFailed();
+            return STATUS_NO_MEMORY;
+        }
+        RtlZeroMemory(pHGCMBuffer, cbBuffer);
+        pSHFLFileInfo = (PRTFSOBJINFO)pHGCMBuffer;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: keeps %d %d %d %d\n",
+              pVBoxFobx->fKeepCreationTime, pVBoxFobx->fKeepLastAccessTime, pVBoxFobx->fKeepLastWriteTime, pVBoxFobx->fKeepChangeTime));
+
+        /* The properties, that need to be changed, are set to something other than zero */
+        if (pFileInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
+            RTTimeSpecSetNtTime(&pSHFLFileInfo->BirthTime, pFileInfo->CreationTime.QuadPart);
+        if (pFileInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
+            RTTimeSpecSetNtTime(&pSHFLFileInfo->AccessTime, pFileInfo->LastAccessTime.QuadPart);
+        if (pFileInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
+            RTTimeSpecSetNtTime(&pSHFLFileInfo->ModificationTime, pFileInfo->LastWriteTime.QuadPart);
+        if (pFileInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
+            RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pFileInfo->ChangeTime.QuadPart);
+        if (pFileInfo->FileAttributes)
+            pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pFileInfo->FileAttributes);
+
+        Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
+        vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
+        AssertRC(vboxRC);
+
+        if (vboxRC != VINF_SUCCESS)
+        {
+            Status = VBoxErrorToNTStatus(vboxRC);
+            goto end;
+        }
+        else
+        {
+            /* Update our internal copy */
+            pVBoxFobx->FileBasicInfo = *pFileInfo;
+        }
+
+        break;
+    }
+
+    case FileDispositionInformation:
+    {
+        PFILE_DISPOSITION_INFORMATION pDispInfo = (PFILE_DISPOSITION_INFORMATION)pBuffer;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileDispositionInformation: Delete = %d\n", pDispInfo->DeleteFile));
+        if (pDispInfo->DeleteFile && capFcb->OpenCount == 1)
+            Status = VBoxMRxRemove(RxContext);
+        else Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FilePositionInformation:
+    {
+        PFILE_POSITION_INFORMATION pPosInfo = (PFILE_POSITION_INFORMATION)pBuffer;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FilePositionInformation: CurrentByteOffset = %RX64\n", pPosInfo->CurrentByteOffset.QuadPart));
+
+        /* Unsupported */
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+    }
+
+    case FileAllocationInformation:
+    {
+        PFILE_ALLOCATION_INFORMATION pAllocInfo = (PFILE_ALLOCATION_INFORMATION)pBuffer;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileAllocationInformation: AllocSize = %RX64\n", pAllocInfo->AllocationSize.QuadPart));
+
+        /* Pretend success */
+        Status = STATUS_SUCCESS;
+        break;
+    }
+
+    case FileEndOfFileInformation:
+    {
+        PFILE_END_OF_FILE_INFORMATION pEndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)pBuffer;
+        LARGE_INTEGER NewAllocationSize;
+
+        Log(("VBOXSF: VBoxMRxSetFileInformation: FileEndOfFileInformation: FileSize = %RX64\n", capFcb->Header.AllocationSize.QuadPart));
+        if (pEndOfFileInfo->EndOfFile.QuadPart > capFcb->Header.AllocationSize.QuadPart)
+        {
+            Status = VBoxMRxExtendFile(RxContext, &pEndOfFileInfo->EndOfFile, &NewAllocationSize);
+
+            Log(("VBOXSF: VBoxMRxSetFileInformation: FileEndOfFileInformation: AllocSize = %d AllocSizeHigh = %d\n", NewAllocationSize.LowPart, NewAllocationSize.HighPart));
+
+            //
+            //  Change the file allocation
+            //
+            capFcb->Header.AllocationSize.QuadPart = NewAllocationSize.QuadPart;
+        }
+        else
+        {
+            Status = VBoxMRxSetEndOfFile(RxContext, &pEndOfFileInfo->EndOfFile, &NewAllocationSize);
+        }
+        /** @todo is this really necessary? */
+        RxContext->Info.LengthRemaining -= sizeof(FILE_END_OF_FILE_INFORMATION);
+        break;
+    }
+
+    case FileLinkInformation:
+    {
+        PFILE_RENAME_INFORMATION pRenameInfo = (PFILE_RENAME_INFORMATION)pBuffer;
+
+        Log(
+            ("VBOXSF: VBoxMRxSetFileInformation: FileLinkInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = %.*ls\n", pRenameInfo->ReplaceIfExists, pRenameInfo->RootDirectory, pRenameInfo->FileNameLength
+                    / sizeof(WCHAR), pRenameInfo->FileName));
+        Status = STATUS_NOT_IMPLEMENTED;
+        break;
+    }
+
+    case FileRenameInformation:
+    {
+        PFILE_RENAME_INFORMATION pRenameInfo = (PFILE_RENAME_INFORMATION)pBuffer;
+
+        Log(
+            ("VBOXSF: VBoxMRxSetFileInformation: FileRenameInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = %.*ls\n", pRenameInfo->ReplaceIfExists, pRenameInfo->RootDirectory, pRenameInfo->FileNameLength
+                    / sizeof(WCHAR), pRenameInfo->FileName));
+        Status = VBoxMRxRename(RxContext, FileRenameInformation, pBuffer, RxContext->Info.Length);
+        break;
+    }
+
+    default:
+        Log(("VBOXSF: VBoxMRxSetFileInformation: Unknown functionality requested (0x%x)!\n", FunctionalityRequested));
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+    }
+
+    end:
+
+    if (pHGCMBuffer)
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+    Log(("VBOXSF: VBoxMRxSetFileInformation: Returned 0x%x\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetFileInformationAtCleanup (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine sets the file information on cleanup. the old rdr just swallows this operation (i.e.
+ it doesn't generate it). we are doing the same..........
+
+ Arguments:
+
+ pRxContext           - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    Log(("VBOXSF: VBoxMRxSetFileInformationAtCleanup\n"));
+    return (Status);
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/init.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/init.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/init.c	(revision 31634)
@@ -0,0 +1,1771 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ Init.c
+
+ Abstract:
+
+ This module implements the DRIVER_INITIALIZATION routine for
+ the null mini rdr.
+
+ --*/
+
+#include "precomp.h"
+#include "rdbss_vbox.h"
+#pragma  hdrstop
+
+#include "ntverp.h"
+#include "nulmrx.h"
+
+#ifdef VBOX
+#include "VBoxGuestR0LibSharedFolders.h"
+
+#if defined(DEBUG) || defined (LOG_ENABLED)
+static PCHAR MajorFunctionString(UCHAR MajorFunction, LONG MinorFunction);
+#endif
+#endif
+
+//
+// Global data declarations.
+//
+
+MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE;
+
+//
+//  Mini Redirector global variables.
+//
+
+//
+//  LogRate
+//
+ULONG LogRate = 0;
+
+//
+//  This is the minirdr dispatch table. It is initialized by
+//  VBoxMRxInitializeTables. This table will be used by the wrapper to call
+//  into this minirdr
+//
+
+struct _MINIRDR_DISPATCH VBoxMRxDispatch;
+
+//
+// Pointer to the device Object for this minirdr. Since the device object is
+// created by the wrapper when this minirdr registers, this pointer is
+// initialized in the DriverEntry routine below (see RxRegisterMinirdr)
+//
+
+PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
+
+#define VBOX_SF_STATIC_LIB
+
+//
+// declare the shadow debugtrace controlpoints
+//
+
+RXDT_DefineCategory (CREATE);
+RXDT_DefineCategory (CLEANUP);
+RXDT_DefineCategory (CLOSE);
+RXDT_DefineCategory (READ);
+RXDT_DefineCategory (WRITE);
+RXDT_DefineCategory (LOCKCTRL);
+RXDT_DefineCategory (FLUSH);
+RXDT_DefineCategory (PREFIX);
+RXDT_DefineCategory (FCBSTRUCTS);
+RXDT_DefineCategory (DISPATCH);
+RXDT_DefineCategory (EA);
+RXDT_DefineCategory (DEVFCB);
+RXDT_DefineCategory (INIT);
+
+//
+// The following enumerated values signify the current state of the minirdr
+// initialization. With the aid of this state information, it is possible
+// to determine which resources to deallocate, whether deallocation comes
+// as a result of a normal stop/unload, or as the result of an exception
+//
+
+typedef enum _MRX_VBOX_INIT_STATES
+{
+    MRX_VBOXINIT_UNINT, MRX_VBOXINIT_ALL_INITIALIZATION_COMPLETED, MRX_VBOXINIT_MINIRDR_REGISTERED, MRX_VBOXINIT_START
+} MRX_VBOX_INIT_STATES;
+
+//
+// function prototypes
+//
+
+NTSTATUS VBoxMRxInitializeTables (void);
+
+VOID VBoxMRxUnload (IN PDRIVER_OBJECT DriverObject);
+
+VOID VBoxMRxInitUnwind (IN PDRIVER_OBJECT DriverObject, IN MRX_VBOX_INIT_STATES VBoxMRxInitState);
+
+NTSTATUS VBoxMRxFsdDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+VOID VBoxMRxReadRegistryParameters ();
+
+#ifdef VBOX
+static int
+vboxCtlGuestFilterMask (uint32_t u32OrMask, uint32_t u32NotMask)
+{
+    int rc;
+    VMMDevCtlGuestFilterMask *req;
+
+    rc = VbglGRAlloc ((VMMDevRequestHeader**) &req, sizeof (*req),
+            VMMDevReq_CtlGuestFilterMask);
+
+    if (RT_FAILURE (rc))
+    {
+        Log (("VBOXSF: vboxCtlGuestFilterMask: "
+                        "VbglGRAlloc (CtlGuestFilterMask) failed rc=%Rrc\n", rc));
+        return -1;
+    }
+
+    req->u32OrMask = u32OrMask;
+    req->u32NotMask = u32NotMask;
+
+    rc = VbglGRPerform (&req->header);
+    VbglGRFree (&req->header);
+    if (RT_FAILURE (rc))
+    {
+        Log (("VBOXSF: vboxCtlGuestFilterMask: "
+                        "VbglGRPerform (CtlGuestFilterMask) failed rc=%Rrc\n", rc));
+        return -1;
+    }
+    return 0;
+}
+#endif
+
+static PFAST_IO_DISPATCH pfnRDBSSTable = NULL;
+
+BOOLEAN VBoxMrxFastIoRead (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus,
+                           IN struct _DEVICE_OBJECT *DeviceObject)
+{
+#ifdef VBOX_FAIL_FASTIO
+    Log(("VBOXSF: VBoxMrxFastIoRead\n"));
+    IoStatus->Information = 0;
+    IoStatus->Status = STATUS_NOT_IMPLEMENTED;
+    return FALSE;
+#else
+    BOOLEAN ret = FALSE;
+
+    Log(("VBOXSF: VBoxMrxFastIoRead: FileObject = 0x%x, QuadPart = %RX64, Len = %d, Buffer = 0x%x\n", FileObject, FileOffset->QuadPart, Length, Buffer));
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoRead)
+    {
+        /* Necessary to satisfy the driver verifier. APCs must be turned off when ExAcquireResourceExclusiveLite is called */
+        FsRtlEnterFileSystem();
+        ret = pfnRDBSSTable->FastIoRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
+        FsRtlExitFileSystem();
+    }
+
+    Log(("VBOXSF: VBoxMrxFastIoRead: Returned 0x%x\n", ret));
+    return ret;
+#endif /* !VBOX_FAIL_FASTIO */
+}
+
+BOOLEAN VBoxMrxFastIoWrite (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus,
+                            IN struct _DEVICE_OBJECT *DeviceObject)
+{
+#ifdef VBOX_FAIL_FASTIO
+    Log(("VBOXSF: VBoxMrxFastIoWrite\n"));
+    IoStatus->Information = 0;
+    IoStatus->Status = STATUS_NOT_IMPLEMENTED;
+    return FALSE;
+#else
+    BOOLEAN ret = FALSE;
+
+    Log(("VBOXSF: VBoxMrxFastIoWrite: FileObject = 0x%x, QuadPart = %RX64, Len = %d, Buffer = 0x%x\n", FileObject, FileOffset->QuadPart, Length, Buffer));
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoWrite)
+    {
+        /* Necessary to satisfy the driver verifier. APCs must be turned off when ExAcquireResourceExclusiveLite is called */
+        FsRtlEnterFileSystem();
+        ret = pfnRDBSSTable->FastIoWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
+        FsRtlExitFileSystem();
+    }
+
+    Log(("VBOXSF: VBoxMrxFastIoWrite: Returned 0x%x\n", ret));
+    return ret;
+#endif /* !VBOX_FAIL_FASTIO */
+}
+
+BOOLEAN VBoxMrxFastIoCheckIfPossible (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation,
+                                      OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoCheckIfPossible)
+    {
+        ret = pfnRDBSSTable->FastIoCheckIfPossible(FileObject, FileOffset, Length, Wait, LockKey, CheckForReadOperation, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoCheckIfPossible: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoQueryBasicInfo (IN struct _FILE_OBJECT *FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoQueryBasicInfo)
+    {
+        ret = pfnRDBSSTable->FastIoQueryBasicInfo(FileObject, Wait, Buffer, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoQueryBasicInfo: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoQueryStandardInfo (IN struct _FILE_OBJECT *FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus,
+                                        IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoQueryStandardInfo)
+    {
+        ret = pfnRDBSSTable->FastIoQueryStandardInfo(FileObject, Wait, Buffer, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoQueryStandardInfo: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoLock (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock,
+                           OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoLock)
+    {
+        ret = pfnRDBSSTable->FastIoLock(FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoLock: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoUnlockSingle (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus,
+                                   IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoUnlockSingle)
+    {
+        ret = pfnRDBSSTable->FastIoUnlockSingle(FileObject, FileOffset, Length, ProcessId, Key, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoUnlockSingle: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoUnlockAll (IN struct _FILE_OBJECT *FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoUnlockAll)
+    {
+        ret = pfnRDBSSTable->FastIoUnlockAll(FileObject, ProcessId, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoUnlockAll: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoUnlockAllByKey (IN struct _FILE_OBJECT *FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoUnlockAllByKey)
+    {
+        ret = pfnRDBSSTable->FastIoUnlockAllByKey(FileObject, ProcessId, Key, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoUnlockAllByKey: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoDeviceControl (IN struct _FILE_OBJECT *FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength,
+                                    IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoDeviceControl)
+    {
+        ret = pfnRDBSSTable->FastIoDeviceControl(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoDeviceControl: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+VOID VBoxMrxAcquireFileForNtCreateSection (IN struct _FILE_OBJECT *FileObject)
+{
+    if (pfnRDBSSTable && pfnRDBSSTable->AcquireFileForNtCreateSection)
+    {
+        pfnRDBSSTable->AcquireFileForNtCreateSection(FileObject);
+        Log(("VBOXSF: VBoxMrxAcquireFileForNtCreateSection: Called.\n"));
+    }
+}
+
+VOID VBoxMrxReleaseFileForNtCreateSection (IN struct _FILE_OBJECT *FileObject)
+{
+    if (pfnRDBSSTable && pfnRDBSSTable->ReleaseFileForNtCreateSection)
+    {
+        pfnRDBSSTable->ReleaseFileForNtCreateSection(FileObject);
+        Log(("VBOXSF: VBoxMrxReleaseFileForNtCreateSection: Called.\n"));
+    }
+}
+
+VOID VBoxMrxFastIoDetachDevice (IN struct _DEVICE_OBJECT *SourceDevice, IN struct _DEVICE_OBJECT *TargetDevice)
+{
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoDetachDevice)
+    {
+        pfnRDBSSTable->FastIoDetachDevice(SourceDevice, TargetDevice);
+        Log(("VBOXSF: VBoxMrxFastIoDetachDevice: Called.\n"));
+    }
+}
+
+BOOLEAN VBoxMrxFastIoQueryNetworkOpenInfo (IN struct _FILE_OBJECT *FileObject, IN BOOLEAN Wait, OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, OUT struct _IO_STATUS_BLOCK *IoStatus,
+                                           IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoQueryNetworkOpenInfo)
+    {
+        ret = pfnRDBSSTable->FastIoQueryNetworkOpenInfo(FileObject, Wait, Buffer, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoQueryNetworkOpenInfo: Called.\n"));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxMdlRead (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus,
+                        IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->MdlRead)
+    {
+        ret = pfnRDBSSTable->MdlRead(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxMdlRead: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxMdlReadComplete (IN struct _FILE_OBJECT *FileObject, IN PMDL MdlChain, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->MdlReadComplete)
+    {
+        ret = pfnRDBSSTable->MdlReadComplete(FileObject, MdlChain, DeviceObject);
+        Log(("VBOXSF: VBoxMrxMdlReadComplete: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxPrepareMdlWrite (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus,
+                                IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->PrepareMdlWrite)
+    {
+        ret = pfnRDBSSTable->PrepareMdlWrite(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject);
+        Log(("VBOXSF: VBoxMrxPrepareMdlWrite: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxMdlWriteComplete (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->MdlWriteComplete)
+    {
+        ret = pfnRDBSSTable->MdlWriteComplete(FileObject, FileOffset, MdlChain, DeviceObject);
+        Log(("VBOXSF: VBoxMrxMdlWriteComplete: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+NTSTATUS VBoxMrxAcquireForModWrite (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER EndingOffset, OUT struct _ERESOURCE **ResourceToRelease, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    NTSTATUS ret = STATUS_NOT_IMPLEMENTED;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->AcquireForModWrite)
+    {
+        ret = pfnRDBSSTable->AcquireForModWrite(FileObject, EndingOffset, ResourceToRelease, DeviceObject);
+        Log(("VBOXSF: VBoxMrxAcquireForModWrite: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+NTSTATUS VBoxMrxReleaseForModWrite (IN struct _FILE_OBJECT *FileObject, IN struct _ERESOURCE *ResourceToRelease, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    NTSTATUS ret = STATUS_NOT_IMPLEMENTED;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->ReleaseForModWrite)
+    {
+        ret = pfnRDBSSTable->ReleaseForModWrite(FileObject, ResourceToRelease, DeviceObject);
+        Log(("VBOXSF: VBoxMrxReleaseForModWrite: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+NTSTATUS VBoxMrxAcquireForCcFlush (IN struct _FILE_OBJECT *FileObject, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    NTSTATUS ret = STATUS_NOT_IMPLEMENTED;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->AcquireForCcFlush)
+    {
+        ret = pfnRDBSSTable->AcquireForCcFlush(FileObject, DeviceObject);
+        Log(("VBOXSF: VBoxMrxAcquireForCcFlush: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+NTSTATUS VBoxMrxReleaseForCcFlush (IN struct _FILE_OBJECT *FileObject, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    NTSTATUS ret = STATUS_NOT_IMPLEMENTED;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->ReleaseForCcFlush)
+    {
+        ret = pfnRDBSSTable->ReleaseForCcFlush(FileObject, DeviceObject);
+        Log(("VBOXSF: VBoxMrxReleaseForCcFlush: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoReadCompressed (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PVOID Buffer, OUT PMDL *MdlChain,
+                                     OUT PIO_STATUS_BLOCK IoStatus, OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, IN ULONG CompressedDataInfoLength, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoReadCompressed)
+    {
+        ret = pfnRDBSSTable->FastIoReadCompressed(FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus, CompressedDataInfo, CompressedDataInfoLength, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoReadCompressed: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoWriteCompressed (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, IN PVOID Buffer, OUT PMDL *MdlChain,
+                                      OUT PIO_STATUS_BLOCK IoStatus, IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo, IN ULONG CompressedDataInfoLength, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoWriteCompressed)
+    {
+        ret = pfnRDBSSTable->FastIoWriteCompressed(FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus, CompressedDataInfo, CompressedDataInfoLength, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoWriteCompressed: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxMdlReadCompleteCompressed (IN struct _FILE_OBJECT *FileObject, IN PMDL MdlChain, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->MdlReadCompleteCompressed)
+    {
+        ret = pfnRDBSSTable->MdlReadCompleteCompressed(FileObject, MdlChain, DeviceObject);
+        Log(("VBOXSF: VBoxMrxMdlReadCompleteCompressed: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxMdlWriteCompleteCompressed (IN struct _FILE_OBJECT *FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->MdlWriteCompleteCompressed)
+    {
+        ret = pfnRDBSSTable->MdlWriteCompleteCompressed(FileObject, FileOffset, MdlChain, DeviceObject);
+        Log(("VBOXSF: VBoxMrxMdlWriteCompleteCompressed: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+BOOLEAN VBoxMrxFastIoQueryOpen (IN struct _IRP *Irp, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, IN struct _DEVICE_OBJECT *DeviceObject)
+{
+    BOOLEAN ret = FALSE;
+
+    if (pfnRDBSSTable && pfnRDBSSTable->FastIoQueryOpen)
+    {
+        ret = pfnRDBSSTable->FastIoQueryOpen(Irp, NetworkInformation, DeviceObject);
+        Log(("VBOXSF: VBoxMrxFastIoQueryOpen: Returned 0x%x\n", ret));
+    }
+    return ret;
+}
+
+
+static FAST_IO_DISPATCH dispatchTable =
+{
+    sizeof(FAST_IO_DISPATCH),
+    VBoxMrxFastIoCheckIfPossible,
+    VBoxMrxFastIoRead,
+    VBoxMrxFastIoWrite,
+    VBoxMrxFastIoQueryBasicInfo,
+    VBoxMrxFastIoQueryStandardInfo,
+    VBoxMrxFastIoLock,
+    VBoxMrxFastIoUnlockSingle,
+    VBoxMrxFastIoUnlockAll,
+    VBoxMrxFastIoUnlockAllByKey,
+    VBoxMrxFastIoDeviceControl,
+    VBoxMrxAcquireFileForNtCreateSection,
+    VBoxMrxReleaseFileForNtCreateSection,
+    VBoxMrxFastIoDetachDevice,
+    VBoxMrxFastIoQueryNetworkOpenInfo,
+    VBoxMrxAcquireForModWrite,
+    VBoxMrxMdlRead,
+    VBoxMrxMdlReadComplete,
+    VBoxMrxPrepareMdlWrite,
+    VBoxMrxMdlWriteComplete,
+    VBoxMrxFastIoReadCompressed,
+    VBoxMrxFastIoWriteCompressed,
+    VBoxMrxMdlReadCompleteCompressed,
+    VBoxMrxMdlWriteCompleteCompressed,
+    VBoxMrxFastIoQueryOpen,
+    VBoxMrxReleaseForModWrite,
+    VBoxMrxAcquireForCcFlush,
+    VBoxMrxReleaseForCcFlush
+};
+
+static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength)
+{
+    BOOL PrefixOK;
+
+    /* The FilePathName here looks like: \vboxsrv\... */
+    if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv'unicode string. */
+    {
+        PrefixOK =  (FilePathName[0] == L'\\');
+        PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v');
+        PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b');
+        PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o');
+        PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x');
+        PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's');
+        /* Both vboxsvr & vboxsrv are now accepted */
+        if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v'))
+        {
+            PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v');
+            PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r');
+        }
+        else
+        {
+            PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r');
+            PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v');
+        }
+        if (PathNameLength > 8 * sizeof (WCHAR))
+        {
+            /* There is something after '\vboxsrv'. */
+            PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0);
+        }
+    }
+    else
+    {
+        PrefixOK = FALSE;
+    }
+
+    return PrefixOK;
+}
+
+#if 0
+static BOOL vboxIsPathToIntercept (const WCHAR *FilePathName, ULONG PathNameLength)
+{
+    BOOL PathToIntercept = FALSE;
+
+    /* Detect '\vboxsrv' */
+    if (PathNameLength == 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */
+    {
+        PathToIntercept = TRUE;
+    }
+
+    if (!PathToIntercept)
+    {
+        /* Detect '\vboxsrv\ipc$' */
+        if (PathNameLength >= 13 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv\ipc$' unicode string. */
+        {
+            const WCHAR *FilePathNameSuffix = &FilePathName[8];
+
+            PathToIntercept =  (FilePathNameSuffix[0] == L'\\');
+            PathToIntercept &= (FilePathNameSuffix[1] == L'I') || (FilePathNameSuffix[1] == L'i');
+            PathToIntercept &= (FilePathNameSuffix[2] == L'P') || (FilePathNameSuffix[2] == L'p');
+            PathToIntercept &= (FilePathNameSuffix[3] == L'C') || (FilePathNameSuffix[3] == L'c');
+            PathToIntercept &= (FilePathNameSuffix[4] == L'$') || (FilePathNameSuffix[4] == L'$');
+            if (PathNameLength > 13 * sizeof (WCHAR))
+            {
+                /* There is something after '\vboxsrv\IPC$'. */
+                PathToIntercept &= (FilePathNameSuffix[5] == L'\\') || (FilePathNameSuffix[5] == 0);
+            }
+        }
+    }
+
+    return PathToIntercept;
+}
+#endif
+
+static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    QUERY_PATH_REQUEST *pReq = NULL;
+    QUERY_PATH_REQUEST_EX *pReqEx = NULL;
+    QUERY_PATH_RESPONSE *pResp = NULL;
+
+    BOOL PrefixOK = FALSE;
+
+    PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
+
+    /* Make a local copy, it will be needed after the Irp completion. */
+    ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
+
+    Log(("VBoxSF::VBoxMRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n",
+         pDevObj, pDevObj->DeviceExtension, IoControlCode));
+
+    switch (IoControlCode)
+    {
+        case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */
+        case IOCTL_REDIR_QUERY_PATH:    /* XP and earlier */
+        {
+            /* This IOCTL is intercepted for 2 reasons:
+             * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them
+             *    will be routed to the VBox provider automatically without any prefix resolution
+             *    since the prefix is already in the prefix cache.
+             * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit,
+             *    because RDBSS will not be involved then.
+             */
+
+            const WCHAR *FilePathName = NULL;
+            ULONG PathNameLength = 0;
+
+            if (pIrp->RequestorMode != KernelMode)
+            {
+                /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying
+                 * that RequestorMode member of the IRP structure is KernelMode.
+                 */
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n",
+                      pStack->Parameters.DeviceIoControl.InputBufferLength));
+                /* Continue to RDBSS. */
+                break;
+            }
+
+            if (IoControlCode == IOCTL_REDIR_QUERY_PATH)
+            {
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess()));
+
+                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST))
+                {
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n",
+                          pStack->Parameters.DeviceIoControl.InputBufferLength));
+                    /* Continue to RDBSS. */
+                    break;
+                }
+
+                pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: PathNameLength = %d.\n", pReq->PathNameLength));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: SecurityContext = %p.\n", pReq->SecurityContext));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName));
+
+                FilePathName = pReq->FilePathName;
+                PathNameLength = pReq->PathNameLength;
+            }
+            else
+            {
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_REDIR_QUERY_PATH_EX: Called.\n"));
+
+                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX))
+                {
+                    Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n",
+                          pStack->Parameters.DeviceIoControl.InputBufferLength));
+                    /* Continue to RDBSS. */
+                    break;
+                }
+
+                pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: pSecurityContext = %p.\n", pReqEx->pSecurityContext));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: EaLength = %d.\n", pReqEx->EaLength));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: pEaBuffer = %p.\n", pReqEx->pEaBuffer));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: PathNameLength = %d.\n", pReqEx->PathName.Length));
+                Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer));
+
+                FilePathName = pReqEx->PathName.Buffer;
+                PathNameLength = pReqEx->PathName.Length;
+            }
+
+            pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer;
+
+            PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength);
+            Log(("VBoxSF::VBoxMRXDeviceControl PrefixOK %d\n", PrefixOK));
+
+            if (!PrefixOK)
+            {
+                /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN.
+                 * No need to involve RDBSS.
+                 */
+                Status = STATUS_BAD_NETWORK_NAME;
+
+                pIrp->IoStatus.Status = Status;
+                pIrp->IoStatus.Information = 0;
+
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+                Log(("VBoxSF::VBoxMRXDeviceControl: returned STATUS_BAD_NETWORK_NAME\n"));
+                return Status;
+            }
+
+            Log(("VBoxSF::VBoxMRXDeviceControl pResp %p verifying the path.\n", pResp));
+            if (pResp)
+            {
+                /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path.
+                 * Here it is assigned to the length of \vboxsrv prefix.
+                 */
+                pResp->LengthAccepted = 8 * sizeof (WCHAR);
+
+                Status = STATUS_SUCCESS;
+
+                pIrp->IoStatus.Status = Status;
+                pIrp->IoStatus.Information = 0;
+
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+                Log(("VBoxSF::VBoxMRXDeviceControl: claiming the path.\n"));
+                return Status;
+            }
+
+            /* No pResp pointer, should not happen. Just a precaution. */
+            Status = STATUS_INVALID_PARAMETER;
+
+            pIrp->IoStatus.Status = Status;
+            pIrp->IoStatus.Information = 0;
+
+            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+            Log(("VBoxSF::VBoxMRXDeviceControl: returned STATUS_INVALID_PARAMETER\n"));
+            return Status;
+        }
+
+        default:
+            break;
+    }
+
+    /* Pass the IOCTL to RDBSS. */
+    if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl)
+    {
+        Log(("VBoxSF::VBoxMRXDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl));
+        Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp);
+        Log(("VBoxSF::VBoxMRXDeviceControl RDBSS status %x\n", Status));
+    }
+    else
+    {
+        /* No RDBSS, should not happen. Just a precaution. */
+        Status = STATUS_NOT_IMPLEMENTED;
+
+        pIrp->IoStatus.Status = Status;
+        pIrp->IoStatus.Information = 0;
+
+        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+        Log(("VBoxSF::VBoxMRXDeviceControl: returned STATUS_NOT_IMPLEMENTED\n"));
+    }
+
+    return Status;
+}
+
+
+NTSTATUS DriverEntry (IN PDRIVER_OBJECT  DriverObject,
+                      IN PUNICODE_STRING RegistryPath)
+/*++
+
+ Routine Description:
+
+ This is the initialization routine for the mini redirector
+
+ Arguments:
+
+ DriverObject - Pointer to driver object created by the system.
+
+ Return Value:
+
+ RXSTATUS - The function value is the final status from the initialization
+ operation.
+
+ --*/
+{
+    NTSTATUS Status;
+    ULONG Controls = 0;
+    MRX_VBOX_INIT_STATES VBoxMRxInitState = MRX_VBOXINIT_UNINT;
+    UNICODE_STRING VBoxMRxName;
+    UNICODE_STRING UserModeDeviceName;
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
+    ULONG i;
+#ifdef VBOX
+    int vboxRC;
+    VBSFCLIENT hgcmClient =
+    {   0};
+#endif
+
+    Log(("VBOXSF: DriverEntry: Driver object 0x%08lx loaded!\n", DriverObject));
+
+#ifdef VBOX
+    /* Initialize VBox subsystem. */
+    vboxRC = vboxInit();
+    if (RT_FAILURE(vboxRC))
+    {
+        Status = STATUS_UNSUCCESSFUL;
+        Log(("VBOXSF: DriverEntry: ERROR while initializing Vbox subsystem (%Rrc)!\n", vboxRC));
+        return Status;
+    }
+
+    /* Set filter mask */
+    if (vboxCtlGuestFilterMask (VMMDEV_EVENT_HGCM, 0)) /** @todo r=bird: Why are we doing this? And more importantely, why are we clearing it further down. We're not the only HGCM user, are we? */
+    {
+        Log (("VBOXSF: DriverEntry: ERROR while setting guest event filter mask!\n"));
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Connect the HGCM client */
+    vboxRC = vboxConnect(&hgcmClient);
+    if (RT_FAILURE (vboxRC))
+    {
+        Status = STATUS_UNSUCCESSFUL;
+        Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n", vboxRC));
+        vboxCtlGuestFilterMask (0, VMMDEV_EVENT_HGCM);
+        vboxUninit();
+        return Status;
+    }
+#endif
+
+    if (DriverObject == NULL)
+    {
+        Status = STATUS_UNSUCCESSFUL;
+        Log(("VBOXSF: DriverEntry: Invalid driver object detected!\n"));
+        vboxCtlGuestFilterMask(0, VMMDEV_EVENT_HGCM);
+        vboxUninit();
+        return Status;
+    }
+
+    //
+    //  Setup Unload Routine
+    //
+
+    DriverObject->DriverUnload = VBoxMRxUnload;
+    DriverObject->FastIoDispatch = NULL;
+    DriverObject->DriverStartIo = NULL;
+
+    //
+    //setup the driver dispatch for people who come in here directly....like the browser
+    //
+
+    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+    {
+        DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch;
+    }
+
+#ifdef VBOX_SF_STATIC_LIB
+    Status = RxDriverEntry(DriverObject, RegistryPath);
+    if (Status != STATUS_SUCCESS)
+    {
+        Log(("VBOXSF: DriverEntry: Wrapper failed to initialize. Status = 0x%08lx\n", Status));
+        goto failure;
+    }
+#endif
+
+    try
+    {
+        VBoxMRxInitState = MRX_VBOXINIT_START;
+
+        //
+        //  Register this minirdr with the connection engine. Registration makes the connection
+        //  engine aware of the device name, driver object, and other characteristics.
+        //  If registration is successful, a new device object is returned
+        //
+        //
+
+
+        RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U);
+        /* don't set RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else UNC mappings don't work (including Windows explorer browsing) */
+
+        /** @todo set RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER and the system will crash on boot */
+        SetFlag(Controls,RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS);
+
+        Status = VBoxRxRegisterMinirdr(
+                &VBoxMRxDeviceObject, // where the new device object goes
+                DriverObject, // the Driver Object to register
+                &VBoxMRxDispatch, // the dispatch table for this driver
+                Controls, // dont register with unc and for mailslots
+                &VBoxMRxName, // the device name for this minirdr
+                sizeof(MRX_VBOX_DEVICE_EXTENSION), // IN ULONG DeviceExtensionSize,
+                FILE_DEVICE_NETWORK_FILE_SYSTEM, // IN ULONG DeviceType - disk ?
+                FILE_REMOTE_DEVICE // IN  ULONG DeviceCharacteristics
+        );
+
+        if (Status!=STATUS_SUCCESS)
+        {
+            Log(("VBOXSF: DriverEntry: Registering mini reader failed: 0x%08lx!\n", Status ));
+            try_return(Status);
+        }
+
+        //
+        //  Init the device extension data
+        //  NOTE: the device extension actually points to fields
+        //  in the RDBSS_DEVICE_OBJECT. Our space is past the end
+        //  of this struct !!
+        //
+
+        pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)
+        ((PBYTE)(VBoxMRxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT));
+
+        pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject;
+
+        // initialize local connection list
+        for (i = 0; i < RTL_NUMBER_OF(pDeviceExtension->cLocalConnections); i++)
+        {
+            pDeviceExtension->cLocalConnections[i] = FALSE;
+        }
+        // Mutex for synchronizining our connection list
+        ExInitializeFastMutex( &pDeviceExtension->mtxLocalCon );
+
+        // The device object has been created. Need to setup a symbolic
+        // link so that the device may be accessed from a Win32 user mode
+        // application.
+
+        RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+        Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink ...\n"));
+        Status = IoCreateSymbolicLink( &UserModeDeviceName, &VBoxMRxName);
+        if (Status != STATUS_SUCCESS)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Failed calling IoCreateSymbolicLink: 0x%08lx\n", Status ));
+            try_return(Status);
+        }
+        Log(("VBOXSF: DriverEntry: Symbolic link created.\n"));
+
+        VBoxMRxInitState = MRX_VBOXINIT_MINIRDR_REGISTERED;
+
+        //
+        // Build the dispatch tables for the minirdr
+        //
+
+        Status = VBoxMRxInitializeTables();
+
+        if (!NT_SUCCESS( Status ))
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: VBoxMRxInitializeTables failed: 0x%08lx\n", Status ));
+            try_return(Status);
+        }
+
+        //
+        // Get information from the registry
+        //
+        VBoxMRxReadRegistryParameters();
+
+        Log(("VBOXSF: VBoxMRxDriverEntry: First phase done!\n"));
+
+        try_exit:
+        NOTHING;
+    }
+    finally
+    {
+        if (Status != STATUS_SUCCESS)
+        {
+            VBoxMRxInitUnwind(DriverObject,VBoxMRxInitState);
+        }
+    }
+
+    if (Status != STATUS_SUCCESS)
+    {
+
+        Log(("VBOXSF: VBoxMRxDriverEntry: VBoxSF.sys failed to start with Status = 0x%08lx, VBoxMRxInitState = 0x%08lx\n", Status, VBoxMRxInitState));
+        goto failure;
+    }
+
+#ifdef VBOX
+    pDeviceExtension->pDriverObject = DriverObject;
+    pDeviceExtension->hgcmClient = hgcmClient;
+#endif
+
+    Log(("VBOXSF: VBoxMRxDriverEntry: FastIoDispatch address = 0x%x, DriverStartIo address = 0x%x\n", DriverObject->FastIoDispatch, DriverObject->DriverStartIo));
+
+    /* Wrap the fast io path */
+    if (DriverObject->FastIoDispatch)
+    {
+        Log(("VBOXSF: VBoxMRxDriverEntry: SizeOfFastIoDispatch = 0x%x (expected = 0x%x)\n", DriverObject->FastIoDispatch->SizeOfFastIoDispatch, sizeof(dispatchTable)));
+        pfnRDBSSTable = DriverObject->FastIoDispatch;
+        DriverObject->FastIoDispatch = &dispatchTable;
+
+        if (pfnRDBSSTable->FastIoCheckIfPossible == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoCheckIfPossible == NULL\n"));
+            dispatchTable.FastIoCheckIfPossible = NULL;
+        }
+        if (pfnRDBSSTable->FastIoRead == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoRead == NULL\n"));
+            dispatchTable.FastIoRead = NULL;
+        }
+        if (pfnRDBSSTable->FastIoWrite == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoWrite == NULL\n"));
+            dispatchTable.FastIoWrite = NULL;
+        }
+        if (pfnRDBSSTable->FastIoQueryBasicInfo == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoQueryBasicInfo == NULL\n"));
+            dispatchTable.FastIoQueryBasicInfo = NULL;
+        }
+        if (pfnRDBSSTable->FastIoQueryStandardInfo == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoQueryStandardInfo == NULL\n"));
+            dispatchTable.FastIoQueryStandardInfo = NULL;
+        }
+        if (pfnRDBSSTable->FastIoLock == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoLock == NULL\n"));
+            dispatchTable.FastIoLock = NULL;
+        }
+        if (pfnRDBSSTable->FastIoUnlockSingle == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoUnlockSingle == NULL\n"));
+            dispatchTable.FastIoUnlockSingle = NULL;
+        }
+        if (pfnRDBSSTable->FastIoUnlockAll == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoUnlockAll == NULL\n"));
+            dispatchTable.FastIoUnlockAll = NULL;
+        }
+        if (pfnRDBSSTable->FastIoUnlockAllByKey == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoUnlockAllByKey == NULL\n"));
+            dispatchTable.FastIoUnlockAllByKey = NULL;
+        }
+        if (pfnRDBSSTable->FastIoDeviceControl == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoDeviceControl == NULL\n"));
+            dispatchTable.FastIoDeviceControl = NULL;
+        }
+        if (pfnRDBSSTable->AcquireFileForNtCreateSection == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: AcquireFileForNtCreateSection == NULL\n"));
+            dispatchTable.AcquireFileForNtCreateSection = NULL;
+        }
+        if (pfnRDBSSTable->ReleaseFileForNtCreateSection == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: ReleaseFileForNtCreateSection == NULL\n"));
+            dispatchTable.ReleaseFileForNtCreateSection = NULL;
+        }
+        if (pfnRDBSSTable->FastIoDetachDevice == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoDetachDevice == NULL\n"));
+            dispatchTable.FastIoDetachDevice = NULL;
+        }
+        if (pfnRDBSSTable->FastIoQueryNetworkOpenInfo == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoQueryNetworkOpenInfo == NULL\n"));
+            dispatchTable.FastIoQueryNetworkOpenInfo = NULL;
+        }
+        if (pfnRDBSSTable->AcquireForModWrite == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: AcquireForModWrite == NULL\n"));
+            dispatchTable.AcquireForModWrite = NULL;
+        }
+        if (pfnRDBSSTable->MdlRead == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: MdlRead == NULL\n"));
+            dispatchTable.MdlRead = NULL;
+        }
+        if (pfnRDBSSTable->MdlReadComplete == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: MdlReadComplete == NULL\n"));
+            dispatchTable.MdlReadComplete = NULL;
+        }
+        if (pfnRDBSSTable->PrepareMdlWrite == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: PrepareMdlWrite == NULL\n"));
+            dispatchTable.PrepareMdlWrite = NULL;
+        }
+        if (pfnRDBSSTable->MdlWriteComplete == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: MdlWriteComplete == NULL\n"));
+            dispatchTable.MdlWriteComplete = NULL;
+        }
+        if (pfnRDBSSTable->FastIoReadCompressed == NULL)
+        {
+            Log(("VVBOXSF: VBoxMRxDriverEntry: Function Table: FastIoReadCompressed == NULL\n"));
+            dispatchTable.FastIoReadCompressed = NULL;
+        }
+        if (pfnRDBSSTable->FastIoWriteCompressed == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoWriteCompressed == NULL\n"));
+            dispatchTable.FastIoWriteCompressed = NULL;
+        }
+        if (pfnRDBSSTable->MdlReadCompleteCompressed == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: MdlReadCompleteCompressed == NULL\n"));
+            dispatchTable.MdlReadCompleteCompressed = NULL;
+        }
+        if (pfnRDBSSTable->MdlWriteCompleteCompressed == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: MdlWriteCompleteCompressed == NULL\n"));
+            dispatchTable.MdlWriteCompleteCompressed = NULL;
+        }
+        if (pfnRDBSSTable->FastIoQueryOpen == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: FastIoQueryOpen == NULL\n"));
+            dispatchTable.FastIoQueryOpen = NULL;
+        }
+        if (pfnRDBSSTable->ReleaseForModWrite == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: ReleaseForModWrite == NULL\n"));
+            dispatchTable.ReleaseForModWrite = NULL;
+        }
+        if (pfnRDBSSTable->AcquireForCcFlush == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: AcquireForCcFlush == NULL\n"));
+            dispatchTable.AcquireForCcFlush = NULL;
+        }
+        if (pfnRDBSSTable->ReleaseForCcFlush == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxDriverEntry: Function Table: ReleaseForCcFlush == NULL\n"));
+            dispatchTable.ReleaseForCcFlush = NULL;
+        }
+    }
+
+    /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution
+     * by other redirectors. These additional name resolutions cause long delays.
+     */
+    Log(("VBOXSF: VBoxMRxDriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n",
+         VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension));
+    pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl;
+
+    Log(("VBOXSF: VBoxMRxDriverEntry: Init successful!\n"));
+    return STATUS_SUCCESS;
+
+    failure:
+
+#ifdef VBOX
+    Log(("VBOXSF: VBoxMRxDriverEntry: Failure! Status = 0x%08X\n", Status));
+
+    vboxDisconnect (&hgcmClient);
+    vboxCtlGuestFilterMask (0, VMMDEV_EVENT_HGCM);
+    vboxUninit();
+#endif
+    VBoxMRxInitUnwind(DriverObject, VBoxMRxInitState);
+
+    return Status;
+}
+
+VOID VBoxMRxInitUnwind (IN PDRIVER_OBJECT DriverObject, IN MRX_VBOX_INIT_STATES VBoxMRxInitState)
+/*++
+
+ Routine Description:
+
+ This routine does the common uninit work for unwinding from a bad driver entry or for unloading.
+
+ Arguments:
+
+ VBoxMRxInitState - tells how far we got into the intialization
+
+ Return Value:
+
+ None
+
+ --*/
+
+{
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxInitUnwind: VBoxMRxInitState = 0x%x\n", VBoxMRxInitState));
+    switch (VBoxMRxInitState)
+    {
+    case MRX_VBOXINIT_ALL_INITIALIZATION_COMPLETED:
+
+        //Nothing extra to do...this is just so that the constant in RxUnload doesn't change.......
+        //lack of break intentional
+
+    case MRX_VBOXINIT_MINIRDR_REGISTERED:
+        VBoxRxUnregisterMinirdr(VBoxMRxDeviceObject);
+
+        //lack of break intentional
+
+    case MRX_VBOXINIT_START:
+        break;
+    }
+
+}
+
+VOID VBoxMRxUnload (IN PDRIVER_OBJECT DriverObject)
+/*++
+
+ Routine Description:
+
+ This is the unload routine for the Exchange mini redirector.
+
+ Arguments:
+
+ DriverObject - pointer to the driver object for the VBoxMRx
+
+ Return Value:
+
+ None
+
+ --*/
+
+{
+    PRX_CONTEXT RxContext;
+    NTSTATUS Status;
+    UNICODE_STRING UserModeDeviceName;
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxUnload: Called.\n"));
+#ifdef VBOX
+    pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)
+    ((PBYTE)(VBoxMRxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT));
+
+    vboxDisconnect (&pDeviceExtension->hgcmClient);
+    vboxUninit ();
+    vboxCtlGuestFilterMask (0, VMMDEV_EVENT_HGCM);
+#endif
+
+    VBoxMRxInitUnwind(DriverObject, MRX_VBOXINIT_ALL_INITIALIZATION_COMPLETED);
+    RxContext = VBoxRxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP);
+
+    if (RxContext != NULL)
+    {
+        Status = VBoxRxStopMinirdr(RxContext, &RxContext->PostRequest);
+
+        if (Status == STATUS_SUCCESS)
+        {
+            MRX_VBOX_STATE State;
+
+            State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
+
+            if (State != MRX_VBOX_STARTABLE)
+            {
+                Status = STATUS_REDIRECTOR_STARTED;
+            }
+        }
+
+        VBoxRxDereferenceAndDeleteRxContext(RxContext);
+    }
+    else
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+    Status = IoDeleteSymbolicLink(&UserModeDeviceName);
+    if (Status != STATUS_SUCCESS)
+    {
+        Log(("VBOXSF: VBoxMRxUnload: Could not delete symbolic link!\n"));
+    }
+
+#ifdef VBOX_SF_STATIC_LIB
+    RxUnload(DriverObject);
+#endif
+    Log(("VBOXSF: VBoxMRxUnload: VBoxSF.sys driver object 0x%08lx unoaded\n", DriverObject));
+}
+
+NTSTATUS VBoxMRxInitializeTables (void)
+/*++
+
+ Routine Description:
+
+ This routine sets up the mini redirector dispatch vector and also calls
+ to initialize any other tables needed.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxInitializeTables: Called.\n"));
+
+    //
+    // Ensure that the Exchange mini redirector context satisfies the size constraints
+    //
+    //ASSERT(sizeof(MRX_VBOX_RX_CONTEXT) <= MRX_CONTEXT_SIZE);
+
+    //
+    // Build the local minirdr dispatch table and initialize
+    //
+
+    ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
+
+    //
+    // null mini redirector extension sizes and allocation policies.
+    //
+
+
+    VBoxMRxDispatch.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION);
+
+    VBoxMRxDispatch.MRxSrvCallSize = 0;
+    VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION);
+    VBoxMRxDispatch.MRxVNetRootSize = 0;
+    VBoxMRxDispatch.MRxFcbSize = 0;
+    VBoxMRxDispatch.MRxSrvOpenSize = 0;
+    VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX);
+
+    // Mini redirector cancel routine ..
+
+    VBoxMRxDispatch.MRxCancel = NULL;
+
+    //
+    // Mini redirector Start/Stop. Each mini-rdr can be started or stopped
+    // while the others continue to operate.
+    //
+
+    VBoxMRxDispatch.MRxStart = VBoxMRxStart;
+    VBoxMRxDispatch.MRxStop = VBoxMRxStop;
+    VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile;
+
+    //
+    // Mini redirector name resolution.
+    //
+
+    VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall;
+    VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify;
+    VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot;
+    VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState;
+    VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName;
+    VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall;
+    VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot;
+    VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot;
+
+    //
+    // File System Object Creation/Deletion.
+    //
+
+    VBoxMRxDispatch.MRxCreate = VBoxMRxCreate;
+    VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen;
+    VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen;
+    VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub;
+    VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub;
+    VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate;
+    VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx;
+    VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen;
+    VBoxMRxDispatch.MRxFlush = VBoxMRxFlush;
+    VBoxMRxDispatch.MRxForceClosed = VBoxMRxForcedClose;
+    VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb;
+    VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx;
+
+    //
+    // File System Objects query/Set
+    //
+
+    VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory;
+    VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInformation;
+    VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInformation;
+    VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInformation;
+    VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySecurityInformation;
+    VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSecurityInformation;
+    VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInformation;
+    VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInformation;
+    VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInformationAtCleanup;
+
+    //
+    // Buffering state change
+    //
+
+    VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState;
+
+    //
+    // File System Object I/O
+    //
+
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl;
+
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory;
+
+    //
+    // Miscellanous
+    //
+
+    VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest;
+
+    Log(("VBOXSF: VBoxMRxInitializeTables: Success.\n"));
+    return (STATUS_SUCCESS);
+}
+
+NTSTATUS VBoxMRxStart (PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
+/*++
+
+ Routine Description:
+
+ This routine completes the initialization of the mini redirector fromn the
+ RDBSS perspective. Note that this is different from the initialization done
+ in DriverEntry. Any initialization that depends on RDBSS should be done as
+ part of this routine while the initialization that is independent of RDBSS
+ should be done in the DriverEntry routine.
+
+ Arguments:
+
+ RxContext - Supplies the Irp that was used to startup the rdbss
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    MRX_VBOX_STATE CurrentState;
+
+    Log(("VBOXSF: VBoxMRxStart: Called.\n"));
+
+    CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS);
+
+    if (CurrentState == MRX_VBOX_START_IN_PROGRESS)
+    {
+        Log(("VBOXSF: VBoxMRxStart: Start in progress -> started\n"));
+        Status = STATUS_SUCCESS;
+    }
+    else if (VBoxMRxState == MRX_VBOX_STARTED)
+    {
+        Log(("VBOXSF: VBoxMRxStart: Already started!\n"));
+        Status = STATUS_REDIRECTOR_STARTED;
+    }
+    else
+    {
+        Log(("VBOXSF: VBoxMRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState));
+        Status = STATUS_UNSUCCESSFUL;
+    }
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxStop (PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
+/*++
+
+ Routine Description:
+
+ This routine is used to activate the mini redirector from the RDBSS perspective
+
+ Arguments:
+
+ RxContext - the context that was used to start the mini redirector
+
+ pContext  - the null mini rdr context passed in at registration time.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxStop: Called.\n"));
+    return (STATUS_SUCCESS);
+}
+
+NTSTATUS VBoxMRxInitializeSecurity (VOID)
+/*++
+
+ Routine Description:
+
+ This routine initializes the null miniredirector security .
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ Note:
+
+ This API can only be called from a FS process.
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxInitializeSecurity: Called.\n"));
+    return Status;
+}
+
+NTSTATUS VBoxMRxUninitializeSecurity (VOID)
+/*++
+
+ Routine Description:
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ Note:
+
+ This API can only be called from a FS process.
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxUninitializeSecurity: Called.\n"));
+    return Status;
+}
+
+NTSTATUS VBoxMRxFsdDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+
+/*++
+
+ Routine Description:
+
+ This routine implements the FSD dispatch for the mini DRIVER object.
+
+ Arguments:
+
+ DeviceObject - Supplies the device object for the packet being processed.
+
+ Irp - Supplies the Irp being processed
+
+ Return Value:
+
+ RXSTATUS - The Fsd status for the Irp
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    UCHAR MajorFunctionCode = IrpSp->MajorFunction;
+    ULONG MinorFunctionCode = IrpSp->MinorFunction;
+
+    Log(("VBOXSF: VBoxMRxFsdDispatch: Called.\n"));
+
+    Assert(DeviceObject == (PDEVICE_OBJECT)VBoxMRxDeviceObject);
+    if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject)
+    {
+        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        Log(("VBOXSF: VBoxMRxFsdDispatch: Invalid device request detected, this in no error!\n"));
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    Log(("%s\n", MajorFunctionString(MajorFunctionCode, MinorFunctionCode)));
+
+    Status = VBoxRxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp);
+    Log(("VBOXSF: VBoxMRxFsdDispatch: Returned 0x%x\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxGetUlongRegistryParameter (HANDLE ParametersHandle, PWCHAR ParameterName, PULONG ParamUlong, BOOLEAN LogFailure)
+/*++
+
+ Routine Description:
+
+ This routine is called to read a ULONG param from t he registry.
+
+ Arguments:
+
+ ParametersHandle - the handle of the containing registry "folder"
+ ParameterName    - name of the parameter to be read
+ ParamUlong       - where to store the value, if successful
+ LogFailure       - if TRUE and the registry stuff fails, log an error
+
+ Return Value:
+
+ RXSTATUS - STATUS_SUCCESS
+
+ --*/
+{
+    ULONG Storage[16];
+    PKEY_VALUE_PARTIAL_INFORMATION Value;
+    ULONG ValueSize;
+    UNICODE_STRING UnicodeString;
+    NTSTATUS Status;
+    ULONG BytesRead;
+
+    PAGED_CODE(); //INIT
+
+    Log(("VBOXSF: VBoxMRxGetUlongRegistryParameter: Called.\n"));
+
+    Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
+    ValueSize = sizeof(Storage);
+
+    RtlInitUnicodeString(&UnicodeString, ParameterName);
+
+    Status = ZwQueryValueKey(ParametersHandle, &UnicodeString, KeyValuePartialInformation, Value, ValueSize, &BytesRead);
+
+    if (NT_SUCCESS(Status))
+    {
+        if (Value->Type == REG_DWORD)
+        {
+            PULONG ConfigValue = (PULONG) & Value->Data[0];
+            *ParamUlong = *((PULONG)ConfigValue);
+            Log(("BOXSF: VBoxMRxGetUlongRegistryParameter: Read registry value %.*ls = 0x%08lx\n", UnicodeString.Length / sizeof(WCHAR), UnicodeString.Buffer, *ParamUlong));
+            return (STATUS_SUCCESS);
+        }
+        else
+        {
+            Status = STATUS_INVALID_PARAMETER;
+        }
+    }
+
+    if (LogFailure)
+        Log(("VBOXSF: VBoxMRxGetUlongRegistryParameter: Failure!\n"));
+
+    return Status;
+}
+
+VOID VBoxMRxReadRegistryParameters ()
+{
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING ParametersRegistryKeyName;
+    HANDLE ParametersHandle;
+    ULONG Temp;
+
+    Log(("VBOXSF: VBoxMRxReadRegistryParameters: Called.\n"));
+    RtlInitUnicodeString(&ParametersRegistryKeyName, NULL_MINIRDR_PARAMETERS);
+    InitializeObjectAttributes(&ObjectAttributes, &ParametersRegistryKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL
+    );
+
+    Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        Status = VBoxMRxGetUlongRegistryParameter(ParametersHandle,L"LogRate" ,
+        (PULONG)&Temp,
+        FALSE
+        );
+    }
+    if (NT_SUCCESS(Status)) LogRate = Temp;
+
+    ZwClose(ParametersHandle);
+}
+
+#if defined(DEBUG) || defined (LOG_ENABLED)
+static PCHAR PnPMinorFunctionString(LONG MinorFunction)
+{
+    switch (MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_START_DEVICE";
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_REMOVE_DEVICE";
+        case IRP_MN_REMOVE_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_REMOVE_DEVICE";
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_CANCEL_REMOVE_DEVICE";
+        case IRP_MN_STOP_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_STOP_DEVICE";
+        case IRP_MN_QUERY_STOP_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_STOP_DEVICE";
+        case IRP_MN_CANCEL_STOP_DEVICE:
+            return "IRP_MJ_PNP - IRP_MN_CANCEL_STOP_DEVICE";
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_RELATIONS";
+        case IRP_MN_QUERY_INTERFACE:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_INTERFACE";
+        case IRP_MN_QUERY_CAPABILITIES:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_CAPABILITIES";
+        case IRP_MN_QUERY_RESOURCES:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCES";
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_TEXT";
+        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+            return "IRP_MJ_PNP - IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
+        case IRP_MN_READ_CONFIG:
+            return "IRP_MJ_PNP - IRP_MN_READ_CONFIG";
+        case IRP_MN_WRITE_CONFIG:
+            return "IRP_MJ_PNP - IRP_MN_WRITE_CONFIG";
+        case IRP_MN_EJECT:
+            return "IRP_MJ_PNP - IRP_MN_EJECT";
+        case IRP_MN_SET_LOCK:
+            return "IRP_MJ_PNP - IRP_MN_SET_LOCK";
+        case IRP_MN_QUERY_ID:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_ID";
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_PNP_DEVICE_STATE";
+        case IRP_MN_QUERY_BUS_INFORMATION:
+            return "IRP_MJ_PNP - IRP_MN_QUERY_BUS_INFORMATION";
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+            return "IRP_MJ_PNP - IRP_MN_DEVICE_USAGE_NOTIFICATION";
+        case IRP_MN_SURPRISE_REMOVAL:
+            return "IRP_MJ_PNP - IRP_MN_SURPRISE_REMOVAL";
+        default:
+            return "IRP_MJ_PNP - unknown_pnp_irp";
+    }
+}
+
+static PCHAR MajorFunctionString(UCHAR MajorFunction, LONG MinorFunction)
+{
+    switch (MinorFunction)
+    {
+    case IRP_MJ_CREATE:
+        return "IRP_MJ_CREATE";
+    case IRP_MJ_CREATE_NAMED_PIPE:
+        return "IRP_MJ_CREATE_NAMED_PIPE";
+    case IRP_MJ_CLOSE:
+        return "IRP_MJ_CLOSE";
+    case IRP_MJ_READ:
+        return "IRP_MJ_READ";
+    case IRP_MJ_WRITE:
+        return "IRP_MJ_WRITE";
+    case IRP_MJ_QUERY_INFORMATION:
+        return "IRP_MJ_QUERY_INFORMATION";
+    case IRP_MJ_SET_INFORMATION:
+        return "IRP_MJ_SET_INFORMATION";
+    case IRP_MJ_QUERY_EA:
+        return "IRP_MJ_QUERY_EA";
+    case IRP_MJ_SET_EA:
+        return "IRP_MJ_SET_EA";
+    case IRP_MJ_FLUSH_BUFFERS:
+        return "IRP_MJ_FLUSH_BUFFERS";
+    case IRP_MJ_QUERY_VOLUME_INFORMATION:
+        return "IRP_MJ_QUERY_VOLUME_INFORMATION";
+    case IRP_MJ_SET_VOLUME_INFORMATION:
+        return "IRP_MJ_SET_VOLUME_INFORMATION";
+    case IRP_MJ_DIRECTORY_CONTROL:
+        return "IRP_MJ_DIRECTORY_CONTROL";
+    case IRP_MJ_FILE_SYSTEM_CONTROL:
+        return "IRP_MJ_FILE_SYSTEM_CONTROL";
+    case IRP_MJ_DEVICE_CONTROL:
+        return "IRP_MJ_DEVICE_CONTROL";
+    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+        return "IRP_MJ_INTERNAL_DEVICE_CONTROL";
+    case IRP_MJ_SHUTDOWN:
+        return "IRP_MJ_SHUTDOWN";
+    case IRP_MJ_LOCK_CONTROL:
+        return "IRP_MJ_LOCK_CONTROL";
+    case IRP_MJ_CLEANUP:
+        return "IRP_MJ_CLEANUP";
+    case IRP_MJ_CREATE_MAILSLOT:
+        return "IRP_MJ_CREATE_MAILSLOT";
+    case IRP_MJ_QUERY_SECURITY:
+        return "IRP_MJ_QUERY_SECURITY";
+    case IRP_MJ_SET_SECURITY:
+        return "IRP_MJ_SET_SECURITY";
+    case IRP_MJ_POWER:
+        return "IRP_MJ_POWER";
+    case IRP_MJ_SYSTEM_CONTROL:
+        return "IRP_MJ_SYSTEM_CONTROL";
+    case IRP_MJ_DEVICE_CHANGE:
+        return "IRP_MJ_DEVICE_CHANGE";
+    case IRP_MJ_QUERY_QUOTA:
+        return "IRP_MJ_QUERY_QUOTA";
+    case IRP_MJ_SET_QUOTA:
+        return "IRP_MJ_SET_QUOTA";
+    case IRP_MJ_PNP:
+        return PnPMinorFunctionString(MinorFunction);
+
+    default:
+        return "unknown_pnp_irp";
+    }
+}
+
+#endif
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/locks.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/locks.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/locks.c	(revision 31634)
@@ -0,0 +1,173 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ locks.c
+
+ Abstract:
+
+ This module implements the mini redirector call down routines pertaining to locks
+ of file system objects.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, VBoxMRxLocks)
+#pragma alloc_text(PAGE, VBoxMRxCompleteBufferingStateChangeRequest)
+#pragma alloc_text(PAGE, VBoxMRxFlush)
+#endif
+
+NTSTATUS VBoxMRxLocks (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine handles network requests for filelocks
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+#ifndef VBOX
+    PDEVICE_OBJECT deviceObject;
+#endif
+
+    PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = (PMRX_VBOX_NETROOT_EXTENSION)pNetRoot->Context;
+    uint32_t fLock = 0;
+
+    int vboxRC;
+
+    Log(("VBOXSF: VBoxMRxLocks: Called.\n"));
+
+    switch (LowIoContext->Operation)
+    {
+    default:
+        AssertMsgFailed(("VBOXSF: VBoxMRxLocks: Unsupported lock/unlock type %d detected!\n", LowIoContext->Operation));
+        return STATUS_NOT_IMPLEMENTED;
+
+    case LOWIO_OP_UNLOCK_MULTIPLE:
+        /* @todo Remove multiple locks listed in LowIoContext.ParamsFor.Locks.LockList. */
+        Log(("VBOXSF: VBoxMRxLocks: Unsupported lock/unlock type %d detected!\n", LowIoContext->Operation));
+        return STATUS_NOT_IMPLEMENTED;
+
+        /* Reading is allowed, writing isn't */
+    case LOWIO_OP_SHAREDLOCK:
+        fLock = SHFL_LOCK_SHARED | SHFL_LOCK_PARTIAL;
+        break;
+
+        /* Reading and writing not allowed */
+    case LOWIO_OP_EXCLUSIVELOCK:
+        fLock = SHFL_LOCK_EXCLUSIVE | SHFL_LOCK_PARTIAL;
+        break;
+
+    case LOWIO_OP_UNLOCK:
+        fLock = SHFL_LOCK_CANCEL | SHFL_LOCK_PARTIAL;
+        break;
+    }
+
+    if (LowIoContext->ParamsFor.Locks.Flags & LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)
+    {
+        fLock |= SHFL_LOCK_NOWAIT;
+    }
+    else
+    {
+        fLock |= SHFL_LOCK_WAIT;
+    }
+
+    /* Do the actual flushing of file buffers */
+    vboxRC = vboxCallLock(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, LowIoContext->ParamsFor.Locks.ByteOffset, LowIoContext->ParamsFor.Locks.Length, fLock);
+    AssertRC(vboxRC);
+    Status = VBoxErrorToNTStatus(vboxRC);
+
+    Log(("VBOXSF: VBoxMRxLocks: Returned 0x%x\n", Status));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxCompleteBufferingStateChangeRequest (IN OUT PRX_CONTEXT RxContext, IN OUT PMRX_SRV_OPEN SrvOpen, IN PVOID pContext)
+/*++
+
+ Routine Description:
+
+ This routine is called to assert the locks that the wrapper has buffered. currently, it is synchronous!
+
+
+ Arguments:
+
+ RxContext - the open instance
+ SrvOpen   - tells which fcb is to be used.
+ LockEnumerator - the routine to call to get the locks
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    Log(("VBOXSF: VBoxMRxCompleteBufferingStateChangeRequest: Called.\n"));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxFlush (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine handles network requests for file flush
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+#ifndef VBOX
+    PDEVICE_OBJECT deviceObject;
+#endif
+
+    PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = (PMRX_VBOX_NETROOT_EXTENSION)pNetRoot->Context;
+
+    int vboxRC;
+
+    Log(("VBOXSF: VBoxMRxFlush: Called.\n"));
+
+    /* Do the actual flushing of file buffers */
+    vboxRC = vboxCallFlush(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
+    AssertRC(vboxRC);
+
+    Status = VBoxErrorToNTStatus(vboxRC);
+
+    return (Status);
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/minip.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/minip.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/minip.h	(revision 31634)
@@ -0,0 +1,76 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ minip.h
+
+ Abstract:
+
+ Macros and definitions private to the null mini driver.
+
+ Notes:
+
+ This module has been built and tested only in UNICODE environment
+
+ --*/
+
+#ifndef _NULLMINIP_H_
+#define _NULLMINIP_H_
+
+NTHALAPI
+VOID
+KeStallExecutionProcessor (
+        IN ULONG MicroSeconds
+);
+
+#ifndef min
+#define min(a, b)       ((a) > (b) ? (b) : (a))
+#endif
+
+#define RX_VERIFY( f )  if( (f) ) ; else ASSERT( 1==0 )
+
+//
+//  Set or Validate equal
+//
+#define SetOrValidate(x,y,f)                                \
+        if( f ) (x) = (y); else ASSERT( (x) == (y) )
+
+//
+//  RXCONTEXT data - mini-rdr context stored for async completions
+//  NOTE: sizeof this struct should be == MRX_CONTEXT_SIZE !!
+//
+
+typedef struct _MRX_VBOX_COMPLETION_CONTEXT
+{
+    //
+    //  IoStatus.Information
+    //
+    ULONG Information;
+
+    //
+    //  IoStatus.Status
+    //
+    NTSTATUS Status;
+
+    //
+    //  Outstanding I/Os
+    //
+    ULONG OutstandingIOs;
+
+    //
+    //  I/O type
+    //
+    ULONG IoType;
+
+} MRX_VBOX_COMPLETION_CONTEXT, *PMRX_VBOX_COMPLETION_CONTEXT;
+
+#define IO_TYPE_SYNCHRONOUS     0x00000001
+#define IO_TYPE_ASYNC           0x00000010
+
+#define VBoxMRxGetMinirdrContext(pRxContext)     \
+        ((PMRX_VBOX_COMPLETION_CONTEXT)(&(pRxContext)->MRxContext[0]))
+
+#endif // _NULLMINIP_H_
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxglobs.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxglobs.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxglobs.h	(revision 31634)
@@ -0,0 +1,463 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ mrxglobs.h
+
+ Abstract:
+
+ The global include file for MRX_VBOX mini-redirector
+
+ --*/
+
+#ifndef _MRXGLOBS_H_
+#define _MRXGLOBS_H_
+
+#ifdef VBOX
+#include "VBoxGuestR0LibSharedFolders.h"
+#endif
+
+extern PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
+#define RxNetNameTable (*(*___MINIRDR_IMPORTS_NAME).pRxNetNameTable)
+
+// The following enum type defines the various states associated with the null
+// mini redirector. This is used during initialization
+
+typedef enum _MRX_VBOX_STATE_
+{
+    MRX_VBOX_STARTABLE, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTED
+} MRX_VBOX_STATE, *PMRX_VBOX_STATE;
+
+extern MRX_VBOX_STATE VBoxMRxState;
+extern ULONG LogRate;
+extern ULONG VBoxMRxVersion;
+
+//
+//  Reg keys
+//
+#define NULL_MINIRDR_PARAMETERS \
+    L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VBoxMRx\\Parameters"
+
+/*
+ * Maximum drive letters (A - Z).
+ */
+#define _MRX_MAX_DRIVE_LETTERS 26
+
+//
+// typedef our device extension - stores state global to the driver
+//
+typedef struct _MRX_VBOX_DEVICE_EXTENSION
+{
+    //
+    //  Back-pointer to owning device object
+    //
+    PRDBSS_DEVICE_OBJECT pDeviceObject;
+
+    //
+    //  Count of active nodes
+    //  Driver can be unloaded if ActiveNodes == 0
+    //
+    ULONG ulActiveNodes;
+
+    /*
+     * Keep a list of local connections used.
+     * The size (_MRX_MAX_DRIVE_LETTERS = 26) of the array presents the available drive letters C: - Z: of Windows.
+     */
+    CHAR cLocalConnections[_MRX_MAX_DRIVE_LETTERS];
+    PUNICODE_STRING wszLocalConnectionName[_MRX_MAX_DRIVE_LETTERS];
+    FAST_MUTEX mtxLocalCon;
+
+#ifdef VBOX
+    /* The HGCM client information. */
+    VBSFCLIENT hgcmClient;
+    /* Poller thread flags */
+    ULONG ulPollerThreadFlags;
+
+    /* Poller thread handle */
+    PKTHREAD pPollerThread;
+
+    /* Redirector driver object pointer */
+    PDRIVER_OBJECT pDriverObject;
+#endif
+
+    NTSTATUS (* pfnRDBSSDeviceControl) (PDEVICE_OBJECT pDevObj, PIRP pIrp);
+
+} MRX_VBOX_DEVICE_EXTENSION, *PMRX_VBOX_DEVICE_EXTENSION;
+
+//
+// NET_ROOT extension - stores state global to a root
+//
+typedef struct _MRX_VBOX_NETROOT_EXTENSION
+{
+    /* The HGCM client information. */
+    VBSFCLIENT *phgcmClient;
+    VBSFMAP map;
+
+} MRX_VBOX_NETROOT_EXTENSION, *PMRX_VBOX_NETROOT_EXTENSION;
+
+// A pointer to an instance of MRX_VBOX_FOBX is stored in the context field
+// of MRX_FOBXs handled by the SMB mini rdr. Depending upon the file type
+// i.e., file or directory the appropriate context information is stored.
+
+typedef struct _MRX_VBOX_FOBX_
+{
+    SHFLHANDLE hFile;
+    PMRX_SRV_CALL pSrvCall;
+    FILE_BASIC_INFORMATION FileBasicInfo;
+    FILE_STANDARD_INFORMATION FileStandardInfo;
+    BOOLEAN fKeepCreationTime;
+    BOOLEAN fKeepLastAccessTime;
+    BOOLEAN fKeepLastWriteTime;
+    BOOLEAN fKeepChangeTime;
+
+} MRX_VBOX_FOBX, *PMRX_VBOX_FOBX;
+
+//
+//  Macros to get & validate extensions
+//
+
+#define VBoxMRxGetDeviceExtension(RxContext,pExt)        \
+        PMRX_VBOX_DEVICE_EXTENSION pExt = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)(RxContext->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT))
+
+#define VBoxMRxGetNetRootExtension(pNetRoot,pExt)        \
+        PMRX_VBOX_NETROOT_EXTENSION pExt = (((pNetRoot) == NULL) ? NULL : (PMRX_VBOX_NETROOT_EXTENSION)((pNetRoot)->Context))
+
+#define VBoxMRxGetFcbExtension(pFcb,pExt)                \
+        PMRX_VBOX_FCB_EXTENSION pExt = (((pFcb) == NULL) ? NULL : (PMRX_VBOX_FCB_EXTENSION)((pFcb)->Context))
+
+#define VBoxMRxGetSrvOpenExtension(pSrvOpen)  \
+        (((pSrvOpen) == NULL) ? NULL : (PMRX_VBOX_SRV_OPEN)((pSrvOpen)->Context))
+
+#define VBoxMRxGetFileObjectExtension(pFobx)  \
+        (((pFobx) == NULL) ? NULL : (PMRX_VBOX_FOBX)((pFobx)->Context))
+
+//
+// forward declarations for all dispatch vector methods.
+//
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern NTSTATUS
+VBoxMRxStart (
+        IN OUT struct _RX_CONTEXT * RxContext,
+        IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
+);
+
+extern NTSTATUS
+VBoxMRxStop (
+        IN OUT struct _RX_CONTEXT * RxContext,
+        IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
+);
+
+extern NTSTATUS
+VBoxMRxMinirdrControl (
+        IN OUT PRX_CONTEXT RxContext,
+        IN OUT PVOID pContext,
+        IN OUT PUCHAR SharedBuffer,
+        IN ULONG InputBufferLength,
+        IN ULONG OutputBufferLength,
+        OUT PULONG CopyBackLength
+);
+
+extern NTSTATUS
+VBoxMRxDevFcb (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxDevFcbXXXControlFile (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCreate (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCollapseOpen (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxShouldTryToCollapseThisOpen (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxRead (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxWrite (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxLocks(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxFlush(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxFsCtl(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+NTSTATUS
+VBoxMRxIoCtl(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxNotifyChangeDirectory(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxComputeNewBufferingState(
+        IN OUT PMRX_SRV_OPEN pSrvOpen,
+        IN PVOID pMRxContext,
+        OUT ULONG *pNewBufferingState);
+
+extern NTSTATUS
+VBoxMRxFlush (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCloseWithDelete (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxZeroExtend (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxSetEndOfFile(
+        IN OUT struct _RX_CONTEXT * RxContext,
+        IN OUT PLARGE_INTEGER pNewFileSize,
+        OUT PLARGE_INTEGER pNewAllocationSize
+);
+
+extern NTSTATUS
+VBoxMRxTruncate (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCleanupFobx (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCloseSrvOpen (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxClosedSrvOpenTimeOut (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxQueryDirectory (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxQueryEaInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxSetEaInformation (
+        IN OUT struct _RX_CONTEXT * RxContext
+);
+
+extern NTSTATUS
+VBoxMRxQuerySecurityInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxSetSecurityInformation (
+        IN OUT struct _RX_CONTEXT * RxContext
+);
+
+extern NTSTATUS
+VBoxMRxQueryVolumeInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxSetVolumeInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxLowIOSubmit (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCreateVNetRoot(
+        IN OUT PMRX_CREATENETROOT_CONTEXT pContext
+);
+
+extern NTSTATUS
+VBoxMRxFinalizeVNetRoot(
+        IN OUT PMRX_V_NET_ROOT pVirtualNetRoot,
+        IN PBOOLEAN ForceDisconnect);
+
+extern NTSTATUS
+VBoxMRxFinalizeNetRoot(
+        IN OUT PMRX_NET_ROOT pNetRoot,
+        IN PBOOLEAN ForceDisconnect);
+
+extern NTSTATUS
+VBoxMRxUpdateNetRootState(
+        IN PMRX_NET_ROOT pNetRoot);
+
+VOID
+VBoxMRxExtractNetRootName(
+        IN PUNICODE_STRING FilePathName,
+        IN PMRX_SRV_CALL SrvCall,
+        OUT PUNICODE_STRING NetRootName,
+        OUT PUNICODE_STRING RestOfName OPTIONAL
+);
+
+extern NTSTATUS
+VBoxMRxCreateSrvCall(
+        PMRX_SRV_CALL pSrvCall,
+        PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext);
+
+extern NTSTATUS
+VBoxMRxFinalizeSrvCall(
+        PMRX_SRV_CALL pSrvCall,
+        BOOLEAN Force);
+
+extern NTSTATUS
+VBoxMRxSrvCallWinnerNotify(
+        IN OUT PMRX_SRV_CALL pSrvCall,
+        IN BOOLEAN ThisMinirdrIsTheWinner,
+        IN OUT PVOID pSrvCallContext);
+
+extern NTSTATUS
+VBoxMRxQueryFileInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxQueryNamedPipeInformation (
+        IN OUT PRX_CONTEXT RxContext,
+        IN FILE_INFORMATION_CLASS FileInformationClass,
+        IN OUT PVOID Buffer,
+        IN OUT PULONG pLengthRemaining
+);
+
+extern NTSTATUS
+VBoxMRxSetFileInformation (
+        IN OUT PRX_CONTEXT RxContext
+);
+
+extern NTSTATUS
+VBoxMRxSetNamedPipeInformation (
+        IN OUT PRX_CONTEXT RxContext,
+        IN FILE_INFORMATION_CLASS FileInformationClass,
+        IN PVOID pBuffer,
+        IN ULONG BufferLength
+);
+
+NTSTATUS
+VBoxMRxSetFileInformationAtCleanup(
+        IN OUT PRX_CONTEXT RxContext
+);
+
+NTSTATUS
+VBoxMRxDeallocateForFcb (
+        IN OUT PMRX_FCB pFcb
+);
+
+NTSTATUS
+VBoxMRxDeallocateForFobx (
+        IN OUT PMRX_FOBX pFobx
+);
+
+extern NTSTATUS
+VBoxMRxForcedClose (
+        IN OUT PMRX_SRV_OPEN SrvOpen
+);
+
+extern ULONG
+VBoxMRxExtendFile (
+        IN OUT struct _RX_CONTEXT * RxContext,
+        IN OUT PLARGE_INTEGER pNewFileSize,
+        OUT PLARGE_INTEGER pNewAllocationSize
+);
+
+extern NTSTATUS
+VBoxMRxExtendStub (
+        IN OUT struct _RX_CONTEXT * RxContext,
+        IN OUT PLARGE_INTEGER pNewFileSize,
+        OUT PLARGE_INTEGER pNewAllocationSize
+);
+
+extern NTSTATUS
+VBoxMRxTruncateFile(
+        IN OUT struct _RX_CONTEXT * RxContext
+);
+
+extern NTSTATUS
+VBoxMRxCompleteBufferingStateChangeRequest (
+        IN OUT PRX_CONTEXT RxContext,
+        IN OUT PMRX_SRV_OPEN SrvOpen,
+        IN PVOID pContext
+);
+
+extern NTSTATUS
+VBoxMRxExtendForCache (
+        IN OUT PRX_CONTEXT RxContext,
+        IN OUT PFCB Fcb,
+        OUT PLONGLONG pNewFileSize
+);
+
+extern
+NTSTATUS
+VBoxMRxInitializeSecurity (VOID);
+
+extern
+NTSTATUS
+VBoxMRxUninitializeSecurity (VOID);
+
+extern
+NTSTATUS
+VBoxMRxInitializeTransport(VOID);
+
+extern
+NTSTATUS
+VBoxMRxUninitializeTransport(VOID);
+
+#ifdef __cplusplus
+}
+;
+#endif
+
+#define VBoxMRxMakeSrvOpenKey(Tid,Fid) \
+        (PVOID)(((ULONG)(Tid) << 16) | (ULONG)(Fid))
+
+#include "mrxprocs.h"   // crossreferenced routines
+#endif _MRXGLOBS_H_
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxprocs.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxprocs.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/mrxprocs.h	(revision 31634)
@@ -0,0 +1,50 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ mrxprocs.h
+
+ Abstract:
+
+ The module contains the prototype definitions for all cross referenced
+ routines.
+
+ --*/
+
+#ifndef _MRXPROCS_H_
+#define _MRXPROCS_H_
+
+//cross-referenced internal routines
+
+//from rename.c
+NTSTATUS VBoxMRxRename(
+        IN PRX_CONTEXT RxContext,
+        IN FILE_INFORMATION_CLASS FileInformationClass,
+        IN PVOID pBuffer,
+        IN ULONG BufferLength);
+
+NTSTATUS VBoxMRxRemove(IN PRX_CONTEXT RxContext);
+
+// from usrcnnct.c
+NTSTATUS
+VBoxMRxDeleteConnection (
+IN PRX_CONTEXT RxContext,
+OUT PBOOLEAN PostToFsp
+);
+
+NTSTATUS
+VBoxMRxCreateConnection (
+IN PRX_CONTEXT RxContext,
+OUT PBOOLEAN PostToFsp
+);
+
+NTSTATUS
+VBoxMRxDoConnection(
+IN PRX_CONTEXT RxContext,
+ULONG CreateDisposition
+);
+
+#endif   // _MRXPROCS_H_
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/netroot.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/netroot.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/netroot.c	(revision 31634)
@@ -0,0 +1,456 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ netroot.c
+
+ Abstract:
+
+ This module implements the routines for creating the net root.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// Forward declarations ...
+//
+
+NTSTATUS VBoxMRxUpdateNetRootState (IN OUT PMRX_NET_ROOT pNetRoot)
+/*++
+
+ Routine Description:
+
+ This routine updates the mini redirector state associated with a net root.
+
+ Arguments:
+
+ pNetRoot - the net root instance.
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ Notes:
+
+ By diffrentiating the mini redirector state from the net root condition it is possible
+ to permit a variety of reconnect strategies. It is conceivable that the RDBSS considers
+ a net root to be good while the underlying mini redirector might mark it as invalid
+ and reconnect on the fly.
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    Log(("VBOXSF: VBoxMRxUpdateNetRootState: Called.\n"));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxInitializeNetRootEntry (IN PMRX_NET_ROOT pNetRoot)
+/*++
+
+ Routine Description:
+
+ This routine initializes a new net root.
+ It also validates rootnames. Eg: attempts to create a
+ file in a root that has not been created will fail.
+
+ Arguments:
+
+ pNetRoot - the net root
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ Notes:
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = (PMRX_VBOX_NETROOT_EXTENSION)pNetRoot->Context;
+
+    Log(("VBOXSF: VBoxMRxInitializeNetRootEntry: Called.\n"));
+    return Status;
+}
+
+NTSTATUS VBoxUpdateNetRoot (PMRX_NET_ROOT pNetRoot)
+/*++
+
+ Routine Description:
+
+ This routine initializes the wrapper data structure corresponding to a
+ given net root entry.
+
+ Arguments:
+
+ pNetRootEntry - the server entry
+
+ Return Value:
+
+ STATUS_SUCCESS if successful
+
+ --*/
+{
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxUpdateNetRoot: NetRoot = 0x%x Type = 0x%x\n", pNetRoot, pNetRoot->Type));
+
+    switch (pNetRoot->Type)
+    {
+    case NET_ROOT_DISK:
+        pNetRoot->DeviceType = RxDeviceType(DISK);
+        break;
+
+    case NET_ROOT_PIPE:
+        pNetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
+        break;
+    case NET_ROOT_COMM:
+        pNetRoot->DeviceType = RxDeviceType(SERIAL_PORT);
+        break;
+    case NET_ROOT_PRINT:
+        pNetRoot->DeviceType = RxDeviceType(PRINTER);
+        break;
+    case NET_ROOT_MAILSLOT:
+        pNetRoot->DeviceType = RxDeviceType(MAILSLOT);
+        break;
+    case NET_ROOT_WILD:
+        /* We get this type when for example Windows Media player opens an MP3 file.
+         * This NetRoot has the same remote path (\\vboxsrv\dir) as other NetRoots,
+         * which were created earlier and which were NET_ROOT_DISK.
+         *
+         * In the beginning of the function (UpdateNetRoot) the DDK sample sets
+         * pNetRoot->Type of newly created NetRoots using a value previously
+         * pstored in a NetRootExtension. One NetRootExtensions is used for a single
+         * remote path and reused by a few NetRoots, if they point to the same path.
+         *
+         * To simplify things we just set the type to DISK here (we do not support
+         * anything else anyway), and update the DeviceType correspondingly.
+         */
+        pNetRoot->Type = NET_ROOT_DISK;
+        pNetRoot->DeviceType = RxDeviceType(DISK);
+        break;
+    default:
+        AssertMsgFailed(("VBOXSF: VBoxUpdateNetRoot: Invalid net root type! Type = 0x%x\n", pNetRoot->Type));
+        break;
+    }
+
+    Log(("VBOXSF: VBoxUpdateNetRoot: leaving pNetRoot->DeviceType = 0x%x\n", pNetRoot->DeviceType));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxCreateVNetRoot (IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
+/*++
+
+ Routine Description:
+
+ This routine patches the RDBSS created net root instance with the information required
+ by the mini redirector.
+
+ Arguments:
+
+ pVNetRoot - the virtual net root instance.
+
+ pCreateNetRootContext - the net root context for calling back
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ Notes:
+
+ --*/
+{
+    NTSTATUS Status;
+    PRX_CONTEXT pRxContext = pCreateNetRootContext->RxContext;
+    PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
+    VBoxMRxGetDeviceExtension(pRxContext, pDeviceExtension);
+    VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot, pNetRootExtension);
+
+    PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
+    PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+
+    BOOLEAN fTreeConnectOpen = TRUE; // RxContext->Create.ThisIsATreeConnectOpen;
+    BOOLEAN fInitializeNetRoot;
+
+    Log(("VBOXSF: VBoxMRxCreateVNetRoot: pNetRoot = %p, fTreeConnectOpen = %d\n", pNetRoot, pRxContext->Create.ThisIsATreeConnectOpen));
+
+    /* IMPORTANT:
+     *
+     * This function must always call 'pCreateNetRootContext->Callback(pCreateNetRootContext)' before
+     * returning and then return STATUS_PENDING. Otherwise Win64 will hang.
+     */
+
+    if (pNetRoot->Type == NET_ROOT_MAILSLOT || pNetRoot->Type == NET_ROOT_PIPE)
+    {
+        /* DDK sample returns this status code. And our driver does get such NetRoots. */
+        Log(("VBOXSF: VBoxMRxCreateVNetRoot: Mailslot or Pipe open (%d) not supported!\n", pNetRoot->Type));
+        pVNetRoot->Context = NULL;
+
+        Status = STATUS_NOT_SUPPORTED;
+        goto l_Exit;
+    }
+
+    // The V_NET_ROOT is associated with a NET_ROOT. The two cases of interest are as
+    // follows
+    // 1) the V_NET_ROOT and the associated NET_ROOT are being newly created.
+    // 2) a new V_NET_ROOT associated with an existing NET_ROOT is being created.
+    //
+    // These two cases can be distinguished by checking if the context associated with
+    // NET_ROOT is NULL. Since the construction of NET_ROOT's/V_NET_ROOT's are serialized
+    // by the wrapper this is a safe check.
+    // ( The wrapper cannot have more then one thread tryingto initialize the same
+    // NET_ROOT).
+    //
+    // The above is not really true in our case. Since we have asked the wrapper,
+    // to manage our netroot extension, the netroot context will always be non-NULL.
+    // We will distinguish the cases by checking our root state in the context...
+    //
+
+    if (pNetRoot->Context == NULL)
+    {
+        fInitializeNetRoot = TRUE;
+    }
+    else
+    {
+        VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+        /* Detect an already initialized NetRoot.
+         * pNetRootExtension is actually the pNetRoot->Context and it is not null.
+         */
+        fInitializeNetRoot = pNetRootExtension->phgcmClient == NULL;
+    }
+
+    Assert((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) && (NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));
+
+    Status = STATUS_SUCCESS;
+
+    // update the net root state to be good.
+
+    if (fInitializeNetRoot)
+    {
+        PWCHAR pRootName;
+        ULONG RootNameLength;
+        int vboxRC;
+        PSHFLSTRING ParsedPath = 0;
+        ULONG ParsedPathSize;
+
+        pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
+
+        // validate the fixed netroot name
+
+        RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
+        if (!RootNameLength)
+        {
+            /* Refuse a netroot path with an empty shared folder name */
+            Log(("VBOXSF: VBoxMRxCreateVNetRoot: Invalid shared folder name! (length=0)\n"));
+            pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
+
+            Status = STATUS_BAD_NETWORK_NAME;
+            goto l_Exit;
+        }
+
+        RootNameLength -= 2; /* remove leading backslash */
+
+        pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
+        pRootName++; /* remove leading backslash */
+
+        if (pNetRootExtension->phgcmClient == NULL)
+        {
+            Log(("VBOXSF: VBoxMRxCreateVNetRoot: Initialize netroot length = %d, name = %.*ls\n", RootNameLength, RootNameLength / sizeof(WCHAR), pRootName));
+
+            /* Calculate length required for parsed path.
+             */
+            ParsedPathSize = sizeof(*ParsedPath) + RootNameLength + sizeof(WCHAR);
+
+            ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+            if (!ParsedPath)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto l_Exit;
+            }
+            memset(ParsedPath, 0, ParsedPathSize);
+
+            ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+            ParsedPath->u16Size = (uint16_t)RootNameLength + sizeof(WCHAR);
+            ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
+            RtlCopyMemory(ParsedPath->String.ucs2, pRootName, ParsedPath->u16Length);
+
+            vboxRC = vboxCallMapFolder(&pDeviceExtension->hgcmClient, ParsedPath, &pNetRootExtension->map);
+            vbsfFreeNonPagedMem(ParsedPath);
+            if (vboxRC != VINF_SUCCESS)
+            {
+                Log(("VBOXSF: VBoxMRxCreateVNetRoot: vboxCallMapFolder failed with %d\n", vboxRC));
+                Status = STATUS_BAD_NETWORK_NAME;
+            }
+            else
+            {
+                Status = STATUS_SUCCESS;
+                pNetRootExtension->phgcmClient = &pDeviceExtension->hgcmClient;
+            }
+        }
+    }
+    else Log(("VBOXSF: VBoxMRxCreateVNetRoot: Creating V_NET_ROOT on existing NET_ROOT!\n"));
+
+    if ((Status == STATUS_SUCCESS) && fInitializeNetRoot)
+    {
+        //
+        //  A new NET_ROOT and associated V_NET_ROOT are being created !
+        //
+        Status = VBoxMRxInitializeNetRootEntry(pNetRoot);
+        Log(("VBOXSF: VBoxMRxCreateVNetRoot: NulMRXInitializeNetRootEntry called, Status = 0x%lx\n", Status));
+    }
+
+    VBoxUpdateNetRoot(pNetRoot);
+
+l_Exit:
+    if (Status != STATUS_PENDING)
+    {
+        Log(("VBOXSF: VBoxMRxCreateVNetRoot: Returning 0x%lx\n", Status));
+        pCreateNetRootContext->VirtualNetRootStatus = Status;
+        if (fInitializeNetRoot)
+            pCreateNetRootContext->NetRootStatus = Status;
+        else pCreateNetRootContext->NetRootStatus = Status;
+
+        // Callback the RDBSS for resumption.
+        pCreateNetRootContext->Callback(pCreateNetRootContext);
+
+        // Map the error code to STATUS_PENDING since this triggers
+        // the synchronization mechanism in the RDBSS.
+        Status = STATUS_PENDING;
+    }
+
+    Log(("VBOXSF: VBoxMRxCreateVNetRoot: Returned STATUS_PENDING\n"));
+    return Status;
+}
+
+NTSTATUS VBoxMRxFinalizeVNetRoot (IN PMRX_V_NET_ROOT pVNetRoot, IN PBOOLEAN ForceDisconnect)
+/*++
+
+ Routine Description:
+
+
+ Arguments:
+
+ pVNetRoot - the virtual net root
+
+ ForceDisconnect - disconnect is forced
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
+    VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot, pNetRootExtension);
+    int vboxRC;
+
+    Log(("VBOXSF: VBoxMRxFinalizeVNetRoot: Address = 0x%lx\n", pVNetRoot));
+
+    if (pNetRootExtension->phgcmClient)
+    {
+        vboxRC = vboxCallUnmapFolder(pNetRootExtension->phgcmClient, &pNetRootExtension->map);
+        if (vboxRC != VINF_SUCCESS)
+        {
+            Log(("VBOXSF: VBoxMRxFinalizeVNetRoot: vboxCallMapFolder failed with %d\n", vboxRC));
+        }
+        pNetRootExtension->phgcmClient = NULL;
+    }
+
+    //
+    //  This is called when all outstanding handles on this
+    //  root have been cleaned up ! We can now zap the netroot
+    //  extension...
+    //
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxFinalizeNetRoot (IN PMRX_NET_ROOT pNetRoot, IN PBOOLEAN ForceDisconnect)
+/*++
+
+ Routine Description:
+
+
+ Arguments:
+
+ pVirtualNetRoot - the virtual net root
+
+ ForceDisconnect - disconnect is forced
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxFinalizeNetRoot: Called.\n"));
+    //
+    //  This is called when all outstanding handles on this
+    //  root have been cleaned up ! We can now zap the netroot
+    //  extension...
+    //
+    return (Status);
+}
+
+VOID VBoxMRxExtractNetRootName (IN PUNICODE_STRING FilePathName, IN PMRX_SRV_CALL SrvCall, OUT PUNICODE_STRING NetRootName, OUT PUNICODE_STRING RestOfName OPTIONAL
+    )
+/*++
+
+ Routine Description:
+
+ This routine parses the input name into srv, netroot, and the
+ rest.
+
+ Arguments:
+
+
+ --*/
+{
+    UNICODE_STRING xRestOfName;
+
+    ULONG length = FilePathName->Length;
+    PWCH w = FilePathName->Buffer;
+    PWCH wlimit = (PWCH)(((PCHAR)w) + length);
+    PWCH wlow;
+
+    Log(("VBOXSF: VBoxMRxExtractNetRootName: Called.\n"));
+
+    w += (SrvCall->pSrvCallName->Length / sizeof(WCHAR));
+    NetRootName->Buffer = wlow = w;
+    for (;;)
+    {
+        if (w >= wlimit)
+            break;
+        if ((*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow))
+        {
+            break;
+        }
+        w++;
+    }
+
+    NetRootName->Length = NetRootName->MaximumLength = (USHORT)((PCHAR)w - (PCHAR)wlow);
+
+    //w = FilePathName->Buffer;
+    //NetRootName->Buffer = w++;
+
+    if (!RestOfName)
+        RestOfName = &xRestOfName;
+    RestOfName->Buffer = w;
+    RestOfName->Length = (USHORT)RestOfName->MaximumLength = (USHORT)((PCHAR)wlimit - (PCHAR)w);
+
+    Log(("VBOXSF: VBoxMRxExtractNetRootName: FilePath = %.*ls\n", FilePathName->Length / sizeof(WCHAR), FilePathName->Buffer));
+    Log(("VBOXSF: VBoxMRxExtractNetRootName: Srv = %.*ls, Root = %.*ls, Rest = %.*ls\n", SrvCall->pSrvCallName->Length / sizeof(WCHAR), SrvCall->pSrvCallName->Buffer, NetRootName->Length
+            / sizeof(WCHAR), NetRootName->Buffer, RestOfName->Length / sizeof(WCHAR), RestOfName->Buffer));
+
+    return;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/notimpl.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/notimpl.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/notimpl.c	(revision 31634)
@@ -0,0 +1,110 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ notimpl.c
+
+ Abstract:
+
+ This module includes prototypes of the functionality that has not been
+ implemented in the null mini rdr.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// File System Control funcitonality
+//
+
+
+NTSTATUS VBoxMRxFsCtl (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine performs an FSCTL operation (remote) on a file across the network
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+
+ --*/
+{
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+
+    Log(("VBOXSF: VBoxMRxFsCtl: Returned 0x%08lx\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxNotifyChangeDirectoryCancellation (PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine is invoked when a directory change notification operation is cancelled.
+ This example doesn't support it.
+
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+
+    UNREFERENCED_PARAMETER(RxContext);
+
+    Log(("VBoxMRxNotifyChangeDirectoryCancellation\n"));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxNotifyChangeDirectory (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine performs a directory change notification operation.
+ This example doesn't support it.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation [not implemented]
+
+ --*/
+{
+
+    UNREFERENCED_PARAMETER(RxContext);
+
+    Log(("VBoxMRxNotifyChangeDirectory\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS VBoxMRxQuerySecurityInformation (IN OUT PRX_CONTEXT RxContext)
+{
+    Log(("VBoxMRxQuerySecurityInformation \n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS VBoxMRxSetSecurityInformation (IN OUT struct _RX_CONTEXT * RxContext)
+{
+    Log(("VBoxMRxSetSecurityInformation \n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/nulmrx.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/nulmrx.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/nulmrx.h	(revision 31634)
@@ -0,0 +1,119 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ nulmrx.h
+
+ Abstract:
+
+ This header exports all symbols and definitions shared between
+ user-mode clients of nulmrx and the driver itself.
+
+ Notes:
+
+ This module has been built and tested only in UNICODE environment
+
+ --*/
+
+#ifndef _MRX_VBOX_H_
+#define _MRX_VBOX_H_
+
+/** ULONG tags used by the FSD. */
+#define TAG_PP                          'PfsV'
+#define TAG_FCB                         'FfsV'
+#define TAG_CCB                         'CfsV'
+#define TAG_IRPCTX                      'IfsV'
+
+// Device name for this driver
+#define MRX_VBOX_DEVICE_NAME_A "VBoxMiniRdr"
+#define MRX_VBOX_DEVICE_NAME_U L"VBoxMiniRdr"
+
+// Provider name for this driver
+#define MRX_VBOX_PROVIDER_NAME_A "VirtualBox Shared Folders"
+#define MRX_VBOX_PROVIDER_NAME_U L"VirtualBox Shared Folders"
+
+// File system name
+#define MRX_VBOX_FILESYS_NAME_A "VBoxSharedFolderFS"
+#define MRX_VBOX_FILESYS_NAME_U L"VBoxSharedFolderFS"
+
+// The following constant defines the length of the above name.
+#define MRX_VBOX_DEVICE_NAME_A_LENGTH (15)
+
+// The following constant defines the path in the ob namespace
+#define DD_MRX_VBOX_FS_DEVICE_NAME_U L"\\Device\\VBoxMiniRdr"
+
+/* File system volume name prefix */
+#define VBOX_VOLNAME_PREFIX     L"VBOX_"
+#define VBOX_VOLNAME_PREFIX_SIZE        (sizeof(VBOX_VOLNAME_PREFIX) - sizeof(VBOX_VOLNAME_PREFIX[0]))
+
+#ifndef MRX_VBOX_DEVICE_NAME
+#define MRX_VBOX_DEVICE_NAME
+
+//
+//  The Devicename string required to access the nullmini device
+//  from User-Mode. Clients should use DD_MRX_VBOX_USERMODE_DEV_NAME_U.
+//
+//  WARNING The next two strings must be kept in sync. Change one and you must
+//  change the other. These strings have been chosen such that they are
+//  unlikely to coincide with names of other drivers.
+//
+#define DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U     L"\\??\\VBoxMiniRdrDN"
+#define DD_MRX_VBOX_USERMODE_DEV_NAME_U            L"\\\\.\\VBoxMiniRdrDN"
+
+//
+//  Prefix needed for disk filesystems
+//
+#define DD_MRX_VBOX_MINIRDR_PREFIX                 L"\\;E:"
+
+#endif // MRX_VBOX_DEVICE_NAME
+//
+// BEGIN WARNING WARNING WARNING WARNING
+//  The following are from the ddk include files and cannot be changed
+
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 // from ddk\inc\ntddk.h
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+
+// END WARNING WARNING WARNING WARNING
+
+#define IOCTL_MRX_VBOX_BASE FILE_DEVICE_NETWORK_FILE_SYSTEM
+
+#define _MRX_VBOX_CONTROL_CODE(request, method, access) \
+                CTL_CODE(IOCTL_MRX_VBOX_BASE, request, method, access)
+
+//
+//  IOCTL codes supported by NullMini Device.
+//
+
+#define IOCTL_CODE_ADDCONN          100
+#define IOCTL_CODE_GETCONN          101
+#define IOCTL_CODE_DELCONN          102
+#define IOCTL_CODE_GETLIST          103
+#define IOCTL_CODE_GETGLOBALLIST    104
+#define IOCTL_CODE_GETGLOBALCONN    105
+#define IOCTL_CODE_START            106
+#define IOCTL_CODE_STOP             107
+
+//
+//  Following is the IOCTL definition and associated structs.
+//  for IOCTL_CODE_SAMPLE1
+//
+#define IOCTL_MRX_VBOX_ADDCONN          _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_ADDCONN, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_GETCONN          _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_GETCONN, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_DELCONN          _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_DELCONN, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_GETLIST          _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_GETLIST, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_GETGLOBALLIST    _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_GETGLOBALLIST, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_GETGLOBALCONN    _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_GETGLOBALCONN, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_MRX_VBOX_START            _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_START, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_MRX_VBOX_STOP             _MRX_VBOX_CONTROL_CODE(IOCTL_CODE_STOP, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif // _MRX_VBOX_H_
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/openclos.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/openclos.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/openclos.c	(revision 31634)
@@ -0,0 +1,1526 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ openclos.c
+
+ Abstract:
+
+ This module implements the mini redirector call down routines pertaining to opening/
+ closing of file/directories.
+
+ --*/
+
+#include "precomp.h"
+#include "rdbss_vbox.h"
+#pragma hdrstop
+
+static UNICODE_STRING UnicodeBackslash = { 2, 4,L"\\" };
+
+//
+//  forwards & pragmas
+//
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+NTSTATUS VBoxMRxProcessCreate (IN PRX_CONTEXT RxContext, IN PUNICODE_STRING RemainingName, IN FILE_BASIC_INFORMATION *pFileBasicInfo, IN FILE_STANDARD_INFORMATION *pFileStandardInfo,
+                               IN PVOID EaBuffer, IN ULONG EaLength, OUT ULONG *pulCreateAction, OUT SHFLHANDLE *pHandle);
+
+NTSTATUS VBoxMRxCreateFileSuccessTail (PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, ULONG CreateAction, FILE_BASIC_INFORMATION* pFileBasicInfo,
+                                       FILE_STANDARD_INFORMATION* pFileStandardInfo, SHFLHANDLE Handle);
+
+VOID VBoxMRxSetSrvOpenFlags (PRX_CONTEXT RxContext, RX_FILE_TYPE StorageType, PMRX_SRV_OPEN SrvOpen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, VBoxMRxCreate)
+#pragma alloc_text(PAGE, VBoxMRxShouldTryToCollapseThisOpen)
+#pragma alloc_text(PAGE, VBoxMRxProcessCreate)
+#pragma alloc_text(PAGE, VBoxMRxCreateFileSuccessTail)
+#pragma alloc_text(PAGE, VBoxMRxSetSrvOpenFlags)
+#endif
+
+NTSTATUS VBoxMRxShouldTryToCollapseThisOpen (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine determines if the mini knows of a good reason not
+ to try collapsing on this open. Presently, the only reason would
+ be if this were a copychunk open.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+ SUCCESS --> okay to try collapse
+ other (MORE_PROCESSING_REQUIRED) --> dont collapse
+
+ --*/
+{
+#ifdef VBOX_SHFL_WITH_COLLAPSE
+    NTSTATUS Status = STATUS_SUCCESS;
+#else
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+#endif
+
+    Log(("VBoxMRxShouldTryToCollapseThisOpen returned %x\n", Status));
+
+    PAGED_CODE();
+
+    return Status;
+}
+
+BOOLEAN VBoxMRxIsStreamFile (PUNICODE_STRING FileName, PUNICODE_STRING AdjustFileName)
+/*++
+
+ Routine Description:
+
+ This routine checks if it is a stream file and return the root file name if true.
+
+ Arguments:
+
+ FileName - the file name needs to be parsed
+ AdjustFileName - the file name contains only root name of the stream
+
+ Return Value:
+
+ BOOLEAN - stream file
+
+ --*/
+{
+    USHORT i;
+    BOOLEAN IsStream = FALSE;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBoxMRxIsStreamFile %.*ls\n", FileName->Length / sizeof(WCHAR), FileName->Buffer));
+
+    for (i = 0; i < FileName->Length / sizeof(WCHAR); i++)
+    {
+        if (FileName->Buffer[i] == L':')
+        {
+            IsStream = TRUE;
+            break;
+        }
+    }
+
+    if (AdjustFileName != NULL)
+    {
+        if (IsStream)
+        {
+            AdjustFileName->Length = AdjustFileName->MaximumLength = i * sizeof(WCHAR);
+            AdjustFileName->Buffer = FileName->Buffer;
+        }
+        else
+        {
+            AdjustFileName->Length = AdjustFileName->MaximumLength = 0;
+            AdjustFileName->Buffer = NULL;
+        }
+    }
+
+    return IsStream;
+}
+
+#define NulMRxGetFcbExtension(pFcb,pExt)                \
+        PNULMRX_FCB_EXTENSION pExt = (((pFcb) == NULL) ? NULL : (PNULMRX_FCB_EXTENSION)((pFcb)->Context))
+
+#define NulMRxGetNetRootExtension(pNetRoot,pExt)        \
+        PNULMRX_NETROOT_EXTENSION pExt = (((pNetRoot) == NULL) ? NULL : (PNULMRX_NETROOT_EXTENSION)((pNetRoot)->Context))
+
+typedef struct _NULMRX_FCB_EXTENSION_
+{
+    //
+    //  Node type code and size
+    //
+    NODE_TYPE_CODE NodeTypeCode;
+    NODE_BYTE_SIZE NodeByteSize;
+
+} NULMRX_FCB_EXTENSION, *PNULMRX_FCB_EXTENSION;
+
+//
+// NET_ROOT extension - stores state global to a root
+//
+typedef struct _NULMRX_NETROOT_EXTENSION
+{
+    //
+    //  Node type code and size
+    //
+    NODE_TYPE_CODE NodeTypeCode;
+    NODE_BYTE_SIZE NodeByteSize;
+
+} NULMRX_NETROOT_EXTENSION, *PNULMRX_NETROOT_EXTENSION;
+
+NTSTATUS NulMRxProcessCreate (IN PNULMRX_FCB_EXTENSION pFcbExtension, IN PVOID EaBuffer, IN ULONG EaLength, OUT PLONGLONG pEndOfFile, OUT PLONGLONG pAllocationSize)
+/*++
+
+ Routine Description:
+
+ This routine processes a create calldown.
+
+ Arguments:
+
+ pFcbExtension   -   ptr to the FCB extension
+ EaBuffer        -   ptr to the EA param buffer
+ EaLength        -   len of EaBuffer
+ pEndOfFile      -   return end of file value
+ pAllocationSize -   return allocation size (which maybe > EOF)
+
+ Notes:
+
+ It is possible to create a file with no EAs
+
+ Return Value:
+
+ None
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxDbgTrace(0, Dbg, ("NulMRxInitializeFcbExtension\n"));
+
+    *pAllocationSize = *pEndOfFile = 0;
+    return Status;
+}
+
+VOID NulMRxSetSrvOpenFlags (PRX_CONTEXT RxContext, RX_FILE_TYPE StorageType, PMRX_SRV_OPEN SrvOpen)
+{
+    PMRX_SRV_CALL SrvCall = (PMRX_SRV_CALL)RxContext->Create.pSrvCall;
+
+    //
+    //  set this only if cache manager will be used for mini-rdr handles !
+    //
+    SrvOpen->BufferingFlags |= (FCB_STATE_FILESIZECACHEING_ENABLED | FCB_STATE_FILETIMECACHEING_ENABLED | FCB_STATE_WRITEBUFFERING_ENABLED | FCB_STATE_LOCK_BUFFERING_ENABLED
+            | FCB_STATE_READBUFFERING_ENABLED |
+#if (NTDDI_VERSION >= NTDDI_VISTA)      /* Correct spelling for Vista 6001 SDK. */
+            FCB_STATE_WRITECACHING_ENABLED | FCB_STATE_READCACHING_ENABLED);
+#else
+    FCB_STATE_WRITECACHEING_ENABLED |
+    FCB_STATE_READCACHEING_ENABLED);
+#endif
+}
+
+NTSTATUS NulMRxCreateFileSuccessTail (PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, ULONG CreateAction, FILE_BASIC_INFORMATION* pFileBasicInfo,
+                                      FILE_STANDARD_INFORMATION* pFileStandardInfo)
+/*++
+
+ Routine Description:
+
+ This routine finishes the initialization of the fcb and srvopen for a
+ successful open.
+
+ Arguments:
+
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
+
+    FCB_INIT_PACKET InitPacket;
+
+    RxDbgTrace(0, Dbg, ("MRxExCreateFileSuccessTail\n"));
+    PAGED_CODE();
+
+    ASSERT(NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN);
+    ASSERT(NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT);
+
+    if (*MustRegainExclusiveResource)
+    { //this is required because of oplock breaks
+        RxAcquireExclusiveFcb(RxContext, capFcb);
+        *MustRegainExclusiveResource = FALSE;
+    }
+
+    // This Fobx should be cleaned up by the wrapper
+    RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
+    if (RxContext->pFobx == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    ASSERT(RxIsFcbAcquiredExclusive(capFcb));
+    RxDbgTrace(0, Dbg, ("Storagetype %08lx/Action %08lx\n", StorageType, CreateAction));
+
+    RxContext->Create.ReturnedCreateInformation = CreateAction;
+
+    RxFormInitPacket(InitPacket, &pFileBasicInfo->FileAttributes, &pFileStandardInfo->NumberOfLinks, &pFileBasicInfo->CreationTime, &pFileBasicInfo->LastAccessTime, &pFileBasicInfo->LastWriteTime,
+                     &pFileBasicInfo->ChangeTime, &pFileStandardInfo->AllocationSize, &pFileStandardInfo->EndOfFile, &pFileStandardInfo->EndOfFile);
+
+    if (capFcb->OpenCount == 0)
+    {
+        RxFinishFcbInitialization(capFcb, RDBSS_STORAGE_NTC(StorageType), &InitPacket);
+    }
+    else
+    {
+
+        ASSERT(StorageType == 0 || NodeType(capFcb) == RDBSS_STORAGE_NTC(StorageType));
+
+    }
+
+    NulMRxSetSrvOpenFlags(RxContext, StorageType, SrvOpen);
+
+    RxContext->pFobx->OffsetOfNextEaToReturn = 1;
+    //transition happens later
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxCreate (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine opens a file across the network
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    BOOLEAN fMustRegainExclusiveResource = FALSE;
+    RX_FILE_TYPE StorageType = FileTypeFile;
+    ULONG CreateAction = FILE_CREATED;
+    FILE_BASIC_INFORMATION FileBasicInfo;
+    FILE_STANDARD_INFORMATION FileStandardInfo;
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
+    PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
+    PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
+    PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+    PVOID EaBuffer = RxContext->Create.EaBuffer;
+    ULONG EaLength = RxContext->Create.EaLength;
+    VBoxMRxGetNetRootExtension(NetRoot,pNetRootExtension);
+    SHFLHANDLE Handle = SHFL_HANDLE_NIL;
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxCreate: %x length=%d\n", RemainingName, RemainingName->Length));
+
+    if (RemainingName->Length)
+    {
+#ifdef VBOX_GUEST
+        Log(("VBOXSF: VBoxMRxCreate: Attempt to open %.*ls Len is %d\n", RemainingName->Length/sizeof(WCHAR), RemainingName->Buffer, RemainingName->Length ));
+#else
+        Log(("VBOXSF: VBoxMRxCreate: Attempt to open %wZ Len is %d\n", RemainingName, RemainingName->Length));
+#endif
+    }
+    else
+    {
+        if (FlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH))
+        {
+            Log(("VBOXSF: VBoxMRxCreate: Empty name -> Only backslash used\n"));
+            RemainingName = &UnicodeBackslash;
+        }
+    }
+
+    switch (NetRoot->Type)
+    {
+    case NET_ROOT_MAILSLOT:
+    case NET_ROOT_PIPE:
+    case NET_ROOT_PRINT:
+    default:
+        Log(("VBOXSF: VBoxMRxCreate: Type %d not supported or invalid open\n", NetRoot->Type));
+        Status = STATUS_NOT_SUPPORTED;
+        goto Exit;
+
+    case NET_ROOT_WILD: /** @todo what's this?? */
+    case NET_ROOT_DISK:
+        break;
+    }
+
+    FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+    //
+    //  Squirrel away the scatter list in the FCB extension.
+    //  This is done only for data files.
+    //
+    Status = VBoxMRxProcessCreate(RxContext, RemainingName, &FileBasicInfo, &FileStandardInfo, EaBuffer, EaLength, &CreateAction, &Handle);
+    if (Status != STATUS_SUCCESS)
+    {
+        //
+        //  error..
+        //
+        Log(("VBOXSF: VBoxMRxCreate: Failed to initialize scatter list!\n"));
+        goto Exit;
+    }
+
+    //
+    //  Complete CreateFile contract
+    //
+    Log(("VBOXSF: VBoxMRxCreate: EOF is %d AllocSize is %d\n", (ULONG)FileStandardInfo.EndOfFile.QuadPart, (ULONG)FileStandardInfo.AllocationSize.QuadPart));
+
+    Status = VBoxMRxCreateFileSuccessTail(RxContext, &fMustRegainExclusiveResource, StorageType, CreateAction, &FileBasicInfo, &FileStandardInfo, Handle);
+
+    if (Status != STATUS_SUCCESS)
+    {
+        //
+        //  alloc error..
+        //
+        Log(("VBOXSF: VBoxMRxCreate: Failed to allocate Fobx!\n"));
+        goto Exit;
+    }
+
+    if (!RxIsFcbAcquiredExclusive(capFcb))
+    {
+        Assert(!RxIsFcbAcquiredShared(capFcb));
+        VboxRxAcquireExclusiveFcbResourceInMRx(capFcb);
+    }
+
+    Assert(Status != (STATUS_PENDING));
+    Assert(RxIsFcbAcquiredExclusive(capFcb));
+
+    Log(("VBOXSF: VBoxMRxCreate: NetRoot is 0x%x, Fcb is 0x%x, SrvOpen is 0x%x, Fobx is 0x%x\n", NetRoot, capFcb, SrvOpen, RxContext->pFobx));
+    Log(("VBOXSF: VBoxMRxCreate: Exit with status=%08lx\n", Status));
+
+    Exit: return (Status);
+}
+
+NTSTATUS VBoxMRxProcessCreate (IN PRX_CONTEXT RxContext, IN PUNICODE_STRING RemainingName, IN FILE_BASIC_INFORMATION *pFileBasicInfo, IN FILE_STANDARD_INFORMATION *pFileStandardInfo,
+                               IN PVOID EaBuffer, IN ULONG EaLength, OUT ULONG *pulCreateAction, OUT SHFLHANDLE *pHandle)
+/*++
+
+ Routine Description:
+
+ This routine processes a create calldown.
+
+ Arguments:
+
+ pFcbExtension   -   ptr to the FCB extension
+ EaBuffer        -   ptr to the EA param buffer
+ EaLength        -   len of EaBuffer
+ pEndOfFile      -   return end of file value
+ pAllocationSize -   return allocation size (which maybe > EOF)
+
+ Notes:
+
+ It is possible to create a file with no EAs
+
+ Return Value:
+
+ None
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    VBoxMRxGetNetRootExtension(capFcb->pNetRoot,pNetRootExtension);
+
+    int vboxRC = VINF_SUCCESS;
+
+    /* Various boolean flags. */
+    struct
+    {
+        ULONG CreateDirectory :1;
+        ULONG SequentialOnly :1;
+        ULONG NoIntermediateBuffering :1;
+        ULONG OpenDirectory :1;
+        ULONG IsPagingFile :1;
+        ULONG OpenTargetDirectory :1;
+        ULONG DirectoryFile :1;
+        ULONG NonDirectoryFile :1;
+        ULONG NoEaKnowledge :1;
+        ULONG DeleteOnClose :1;
+        ULONG TemporaryFile :1;
+        ULONG FileNameOpenedDos :1;
+        ULONG PostIrp :1;
+        ULONG OplockPostIrp :1;
+        ULONG TrailingBackslash :1;
+        ULONG FirstLoop :1;
+        ULONG SeparatorEncountered :1;
+        ULONG DriveAcquired :1;
+    } bf;
+
+    ACCESS_MASK DesiredAccess;
+    ULONG Options;
+    UCHAR FileAttributes;
+    ULONG ShareAccess;
+    ULONG CreateDisposition;
+    SHFLCREATEPARMS *pCreateParms = 0;
+
+    Log(("VBOXSF: VBoxMRxProcessCreate\n"));
+    Log(("VBOXSF: VBoxMRxProcessCreate: FileAttributes = %08x\n", RxContext->Create.NtCreateParameters.FileAttributes));
+    Log(("VBOXSF: VBoxMRxProcessCreate: CreateOptions = %08x\n", RxContext->Create.NtCreateParameters.CreateOptions));
+
+    RtlZeroMemory (&bf, sizeof (bf));
+
+    DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess;
+    Options = RxContext->Create.NtCreateParameters.CreateOptions & FILE_VALID_OPTION_FLAGS;
+    FileAttributes = (UCHAR)(RxContext->Create.NtCreateParameters.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
+    ShareAccess = RxContext->Create.NtCreateParameters.ShareAccess;
+
+    /* Extended attributes are not supported! */
+    if (EaLength)
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: Unsupported: extended attributes!\n"));
+        Status = STATUS_NOT_SUPPORTED;
+        goto failure;
+    }
+
+    /* We do not support opens by file ids yet. */
+    if (FlagOn(Options, FILE_OPEN_BY_FILE_ID))
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: Unsupported: file open by id!\n"));
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto failure;
+    }
+
+    /* Mask out unsupported attribute bits. */
+    FileAttributes &= (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE);
+
+    bf.DirectoryFile = BooleanFlagOn(Options, FILE_DIRECTORY_FILE);
+    bf.NonDirectoryFile = BooleanFlagOn(Options, FILE_NON_DIRECTORY_FILE);
+    bf.SequentialOnly = BooleanFlagOn(Options, FILE_SEQUENTIAL_ONLY);
+    bf.NoIntermediateBuffering = BooleanFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING);
+    bf.NoEaKnowledge = BooleanFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
+    bf.DeleteOnClose = BooleanFlagOn(Options, FILE_DELETE_ON_CLOSE);
+    if (bf.DeleteOnClose)
+        Log(("VBOXSF: VBoxMRxProcessCreate: Delete on close!\n"));
+
+    CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;
+
+    bf.IsPagingFile = BooleanFlagOn(capFcb->FcbState, FCB_STATE_PAGING_FILE);
+    if (bf.IsPagingFile)
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: Unsupported: paging file!\n"));
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto failure;
+    }
+
+    bf.CreateDirectory = (BOOLEAN)(bf.DirectoryFile && ((CreateDisposition == FILE_CREATE) || (CreateDisposition == FILE_OPEN_IF)));
+
+    bf.OpenDirectory = (BOOLEAN)(bf.DirectoryFile && ((CreateDisposition == FILE_OPEN) || (CreateDisposition == FILE_OPEN_IF)));
+
+    bf.TemporaryFile = BooleanFlagOn(RxContext->Create.NtCreateParameters.FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
+
+    if (FlagOn(capFcb->FcbState, FCB_STATE_TEMPORARY))
+        bf.TemporaryFile = TRUE;
+
+    Log(("VBOXSF: VBoxMRxProcessCreate: bf.TemporaryFile %d, bf.CreateDirectory %d, bf.DirectoryFile = %d\n", (ULONG)bf.TemporaryFile, (ULONG)bf.CreateDirectory, (ULONG)bf.DirectoryFile));
+
+    /* Check consistency in specified flags. */
+    if (bf.TemporaryFile && bf.CreateDirectory) /* Directories with temporary flag set are not allowed! */
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: Not allowed: Temporary directories!\n"));
+        Status = STATUS_INVALID_PARAMETER;
+        goto failure;
+    }
+
+    if (bf.DirectoryFile && bf.NonDirectoryFile)
+    {
+        AssertMsgFailed(("VBOXSF: VBoxMRxProcessCreate: Unsupported combination: dir && !dir\n"));
+        Status = STATUS_INVALID_PARAMETER;
+        goto failure;
+    }
+
+    /* Initialize create parameters. */
+    pCreateParms = (SHFLCREATEPARMS *)vbsfAllocNonPagedMem(sizeof(SHFLCREATEPARMS));
+    if (!pCreateParms)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failure;
+    }
+
+    RtlZeroMemory (pCreateParms, sizeof (SHFLCREATEPARMS));
+
+    pCreateParms->Handle = SHFL_HANDLE_NIL;
+    pCreateParms->Result = SHFL_NO_RESULT;
+
+    if (bf.OpenTargetDirectory)
+    {
+        pCreateParms->CreateFlags |= SHFL_CF_OPEN_TARGET_DIRECTORY;
+    }
+
+    if (bf.DirectoryFile)
+    {
+        if (CreateDisposition != FILE_CREATE && CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OPEN_IF)
+        {
+            AssertMsgFailed(("VBOXSF: VBoxMRxProcessCreate: Invalid disposition %x for directory!\n", CreateDisposition));
+            Status = STATUS_INVALID_PARAMETER;
+            goto failure;
+        }
+
+        pCreateParms->CreateFlags |= SHFL_CF_DIRECTORY;
+    }
+
+    Log(("VBOXSF: VBoxMRxProcessCreate: CreateDisposition = %08x\n", CreateDisposition));
+
+    switch (CreateDisposition)
+    {
+    case FILE_SUPERSEDE:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
+        break;
+
+    case FILE_OPEN:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
+        break;
+
+    case FILE_CREATE:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
+        break;
+
+    case FILE_OPEN_IF:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
+        break;
+
+    case FILE_OVERWRITE:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
+        break;
+
+    case FILE_OVERWRITE_IF:
+        pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        Log(("VBOXSF: VBoxMRxProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
+        break;
+
+    default:
+        AssertMsgFailed(("VBOXSF: VBoxMRxProcessCreate: Unexpected create disposition: 0x%08X\n", CreateDisposition));
+        Status = STATUS_INVALID_PARAMETER;
+        goto failure;
+    }
+
+    Log(("VBOXSF: VBoxMRxProcessCreate: DesiredAccess = 0x%08x\n", DesiredAccess));
+    Log(("VBOXSF: VBoxMRxProcessCreate: ShareAccess   = 0x%08x\n", ShareAccess));
+
+    if (DesiredAccess & FILE_READ_DATA)
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: FILE_READ_DATA\n"));
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ;
+    }
+
+    if (DesiredAccess & FILE_WRITE_DATA)
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: FILE_WRITE_DATA\n"));
+        /* FILE_WRITE_DATA means write access regardless of FILE_APPEND_DATA bit.
+         */
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
+    }
+    else if (DesiredAccess & FILE_APPEND_DATA)
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: FILE_APPEND_DATA\n"));
+        /* FILE_APPEND_DATA without FILE_WRITE_DATA means append only mode.
+         *
+         * Both write and append access flags are required for shared folders,
+         * as on Windows FILE_APPEND_DATA implies write access.
+         */
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE | SHFL_CF_ACCESS_APPEND;
+    }
+
+    if (DesiredAccess & FILE_READ_ATTRIBUTES)
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_READ;
+    if (DesiredAccess & FILE_WRITE_ATTRIBUTES)
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_WRITE;
+
+    if (ShareAccess & (FILE_SHARE_READ | FILE_SHARE_WRITE))
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYNONE;
+    else if (ShareAccess & FILE_SHARE_READ)
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE;
+    else if (ShareAccess & FILE_SHARE_WRITE)
+        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYREAD;
+    else pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYALL;
+
+    /* Set initial allocation size. */
+    pCreateParms->Info.cbObject = RxContext->Create.NtCreateParameters.AllocationSize.QuadPart;
+
+    if (FileAttributes == 0)
+        FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+    pCreateParms->Info.Attr.fMode = NTToVBoxFileAttributes(FileAttributes);
+
+#ifdef VBOX_FAKE_IO_CREATE
+    {
+        LARGE_INTEGER liSystemTime;
+        pFileBasicInfo->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+        KeQuerySystemTime(&liSystemTime);
+        pFileBasicInfo->CreationTime = liSystemTime;
+        pFileBasicInfo->LastAccessTime = liSystemTime;
+        pFileBasicInfo->LastWriteTime = liSystemTime;
+        pFileBasicInfo->ChangeTime = liSystemTime;
+        pFileStandardInfo->AllocationSize.QuadPart = 0;
+        pFileStandardInfo->EndOfFile.QuadPart = 0;
+        pFileStandardInfo->NumberOfLinks = 0;
+
+        *pulCreateAction = FILE_CREATED;
+
+        *pHandle = (SHFLHANDLE)0xABCDEF00;
+    }
+#else
+    {
+        PSHFLSTRING ParsedPath = 0;
+        ULONG ParsedPathSize;
+
+        /* Calculate length required for parsed path.
+         */
+        ParsedPathSize = sizeof(*ParsedPath) + (RemainingName->Length + sizeof(WCHAR));
+
+        Log(("VBOXSF: VBoxMRxProcessCreate: ParsedPathSize = %d\n", ParsedPathSize));
+
+        ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+        if (NULL == ParsedPath)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto failure;
+        }
+
+        ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+        ParsedPath->u16Size = RemainingName->Length + sizeof(WCHAR);
+        ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
+        RtlCopyMemory (ParsedPath->String.ucs2, RemainingName->Buffer, ParsedPath->u16Length);
+        Log(("ParsedPath: %.*ls\n", ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
+
+        /* Call host. */
+        Log(("VBOXSF: VBoxMRxProcessCreate: vboxCallCreate called.\n"));
+        vboxRC = vboxCallCreate(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, pCreateParms);
+        vbsfFreeNonPagedMem(ParsedPath);
+    }
+
+    Log(("VBOXSF: VBoxMRxProcessCreate: vboxCallCreate returns vboxRC = %Rrc, Result = %x\n", vboxRC, pCreateParms->Result));
+    if (RT_FAILURE(vboxRC))
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: vboxCallCreate failed with %Rrc\n", vboxRC));
+        /* Map some VBoxRC to STATUS codes expected by the system. */
+        switch (vboxRC)
+        {
+
+        case VERR_ALREADY_EXISTS:
+            {
+                *pulCreateAction = FILE_EXISTS;
+                Status = STATUS_OBJECT_NAME_COLLISION;
+            }
+            goto failure;
+            break;
+
+        /* On POSIX systems, the "mkdir" command returns VERR_FILE_NOT_FOUND when
+           doing a recursive directory create. Handle this case in the next switch below. */
+        case VERR_FILE_NOT_FOUND:
+
+            pCreateParms->Result = SHFL_PATH_NOT_FOUND;
+            break;
+
+        default:
+            {
+                *pulCreateAction = FILE_DOES_NOT_EXIST;
+                Status = VBoxErrorToNTStatus(vboxRC);
+            }
+            goto failure;
+            break;
+        }
+    }
+
+    /*
+     * The request succeeded. Analyze host response,
+     */
+    switch (pCreateParms->Result)
+    {
+    case SHFL_PATH_NOT_FOUND:
+    {
+        /* Path to object does not exist. */
+        Log(("VBOXSF: VBoxMRxProcessCreate: Path not found\n"));
+        *pulCreateAction = FILE_DOES_NOT_EXIST;
+        Status = STATUS_OBJECT_PATH_NOT_FOUND;
+        goto failure;
+    }
+
+    case SHFL_FILE_NOT_FOUND:
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: File not found\n"));
+        *pulCreateAction = FILE_DOES_NOT_EXIST;
+        if (pCreateParms->Handle == SHFL_HANDLE_NIL)
+        {
+            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+            goto failure;
+        }
+
+        /* Here we can only have the OpenTargetDirectory mode. */
+        if (!bf.OpenTargetDirectory)
+        {
+            Log(("VBOXSF: VBoxMRxProcessCreate: File not found but have a handle!\n"));
+            Status = STATUS_UNSUCCESSFUL;
+            goto failure;
+        }
+        /* File components does not exist but target directory was opened. */
+        break;
+    }
+
+    case SHFL_FILE_EXISTS:
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: File exists, Handle = %08x\n", pCreateParms->Handle));
+        if (pCreateParms->Handle == SHFL_HANDLE_NIL)
+        {
+            *pulCreateAction = FILE_EXISTS;
+            if (CreateDisposition == FILE_CREATE)
+            {
+                /* File was not opened because we requested a create. */
+                Status = STATUS_OBJECT_NAME_COLLISION;
+                goto failure;
+            }
+
+            /* Actually we should not go here, unless we have no rights to open the object. */
+            Log(("VBOXSF: VBoxMRxProcessCreate: Existing file was not opened!\n"));
+            Status = STATUS_ACCESS_DENIED;
+            goto failure;
+        }
+
+        if (bf.OpenTargetDirectory)
+        {
+            *pulCreateAction = FILE_EXISTS;
+        }
+        else
+        {
+            *pulCreateAction = FILE_OPENED;
+        }
+
+        /* Existing file was opened. Go check flags and create FCB. */
+        break;
+    }
+
+    case SHFL_FILE_CREATED:
+    {
+        /* A new file was created. */
+
+        Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);
+
+        *pulCreateAction = FILE_CREATED;
+
+        /* Go check flags and create FCB. */
+        break;
+    }
+
+    case SHFL_FILE_REPLACED:
+    {
+        /* Existing file was replaced or overwriting. */
+
+        Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);
+
+        if (CreateDisposition == FILE_SUPERSEDE)
+        {
+            *pulCreateAction = FILE_SUPERSEDED;
+        }
+        else
+        {
+            *pulCreateAction = FILE_OVERWRITTEN;
+        }
+        /* Go check flags and create FCB. */
+        break;
+    }
+
+    default:
+    {
+        Log(("VBOXSF: VBoxMRxProcessCreate: Invalid CreateResult from host (0x%08X)\n", pCreateParms->Result));
+        *pulCreateAction = FILE_DOES_NOT_EXIST;
+        Status = STATUS_OBJECT_PATH_NOT_FOUND;
+        goto failure;
+    }
+    }
+
+    /* Check flags. */
+    if (bf.NonDirectoryFile && FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
+    {
+        /* Caller wanted only a file, but the object is a directory. */
+        Log(("VBOXSF: VBoxMRxProcessCreate: File is a directory!\n"));
+        Status = STATUS_FILE_IS_A_DIRECTORY;
+        goto failure;
+    }
+
+    if (bf.DirectoryFile && !FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
+    {
+        /* Caller wanted only a directory, but the object is not a directory. */
+        Log(("VBOXSF: VBoxMRxProcessCreate: File is not a directory!\n"));
+        Status = STATUS_NOT_A_DIRECTORY;
+        goto failure;
+    }
+
+    *pHandle = pCreateParms->Handle;
+
+    /* Translate attributes */
+    pFileBasicInfo->FileAttributes = VBoxToNTFileAttributes(pCreateParms->Info.Attr.fMode);
+
+    /* Translate file times */
+    pFileBasicInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.BirthTime); /* ridiculous name */
+    pFileBasicInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.AccessTime);
+    pFileBasicInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ModificationTime);
+    pFileBasicInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ChangeTime);
+
+    if (!FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
+    {
+        Assert(!FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY));
+        pFileStandardInfo->AllocationSize.QuadPart = pCreateParms->Info.cbAllocated;
+        pFileStandardInfo->EndOfFile.QuadPart = pCreateParms->Info.cbObject;
+        pFileStandardInfo->Directory = FALSE;
+
+        Log(("VBOXSF: VBoxMRxProcessCreate: AllocationSize = %RX64, EndOfFile = %RX64\n", pCreateParms->Info.cbAllocated, pCreateParms->Info.cbObject));
+    }
+    else
+    {
+        Assert(FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY));
+        pFileStandardInfo->AllocationSize.QuadPart = 0;
+        pFileStandardInfo->EndOfFile.QuadPart = 0;
+        pFileStandardInfo->Directory = TRUE;
+    }
+    pFileStandardInfo->NumberOfLinks = 0;
+    pFileStandardInfo->DeletePending = FALSE;
+#endif
+
+    vbsfFreeNonPagedMem(pCreateParms);
+    return Status;
+
+    failure:
+
+    Log(("VBOXSF: VBoxMRxProcessCreate: Returned with status = 0x%08lx\n", Status));
+    if (pCreateParms && pCreateParms->Handle != SHFL_HANDLE_NIL)
+    {
+#ifndef VBOX_FAKE_IO_CREATE
+        vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pCreateParms->Handle);
+#endif
+        *pHandle = SHFL_HANDLE_NIL;
+    }
+
+    if (pCreateParms)
+        vbsfFreeNonPagedMem(pCreateParms);
+
+    return Status;
+}
+
+VOID VBoxMRxSetSrvOpenFlags (PRX_CONTEXT RxContext, RX_FILE_TYPE StorageType, PMRX_SRV_OPEN SrvOpen)
+{
+    PMRX_SRV_CALL SrvCall = (PMRX_SRV_CALL)RxContext->Create.pSrvCall;
+
+    //
+    //  set this only if cache manager will be used for mini-rdr handles !
+    //
+    Log(("VBoxMRxSetSrvOpenFlags %x\n", SrvOpen->BufferingFlags));
+#if 0
+    /* This seems to be the root cause of the strange bug checks when enabling
+     * the driver verifier.
+     */
+    SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHEING_ENABLED |
+            FCB_STATE_FILESIZECACHEING_ENABLED |
+            FCB_STATE_FILETIMECACHEING_ENABLED |
+            FCB_STATE_WRITEBUFFERING_ENABLED |
+            FCB_STATE_LOCK_BUFFERING_ENABLED |
+            FCB_STATE_READBUFFERING_ENABLED |
+            FCB_STATE_READCACHEING_ENABLED);
+#endif
+}
+
+NTSTATUS VBoxMRxCreateFileSuccessTail (PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, ULONG CreateAction, FILE_BASIC_INFORMATION* pFileBasicInfo,
+                                       FILE_STANDARD_INFORMATION* pFileStandardInfo, SHFLHANDLE Handle)
+/*++
+
+ Routine Description:
+
+ This routine finishes the initialization of the fcb and srvopen for a
+ successful open.
+
+ Arguments:
+
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
+    PMRX_VBOX_FOBX pVBoxFobx;
+
+    FCB_INIT_PACKET InitPacket;
+
+    Log(("VBOXSF: VBoxMRxCreateFileSuccessTail\n"));
+    PAGED_CODE();
+
+    Assert(NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN);
+    Assert(NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT);
+
+    if (*MustRegainExclusiveResource)
+    { //this is required because of oplock breaks
+        VboxRxAcquireExclusiveFcbResourceInMRx(capFcb);
+        *MustRegainExclusiveResource = FALSE;
+    }
+
+    // This Fobx should be cleaned up by the wrapper
+    RxContext->pFobx = VboxRxCreateNetFobx(RxContext, SrvOpen);
+    if (RxContext->pFobx == NULL)
+    {
+        AssertFailed();
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    Assert(VBoxRxIsFcbAcquiredExclusive(capFcb));
+    Log(("VBOXSF: VBoxMRxCreateFileSuccessTail: StorageType = 0x%08lx, Action = 0x%08lx\n", StorageType, CreateAction));
+
+    RxContext->Create.ReturnedCreateInformation = CreateAction;
+
+    RxFormInitPacket(InitPacket, &pFileBasicInfo->FileAttributes, &pFileStandardInfo->NumberOfLinks, &pFileBasicInfo->CreationTime, &pFileBasicInfo->LastAccessTime, &pFileBasicInfo->LastWriteTime,
+                     &pFileBasicInfo->ChangeTime, &pFileStandardInfo->AllocationSize, &pFileStandardInfo->EndOfFile, &pFileStandardInfo->EndOfFile);
+
+    if (capFcb->OpenCount == 0)
+    {
+        VboxRxFinishFcbInitialization(capFcb, RDBSS_STORAGE_NTC(StorageType), &InitPacket);
+    }
+    else
+    {
+        Assert(StorageType == 0 || NodeType(capFcb) == RDBSS_STORAGE_NTC(StorageType));
+    }
+
+    VBoxMRxSetSrvOpenFlags(RxContext, StorageType, SrvOpen);
+
+    RxContext->pFobx->OffsetOfNextEaToReturn = 1;
+    //transition happens later
+
+    pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
+    Assert(pVBoxFobx);
+    if (pVBoxFobx)
+    {
+        Log(("VBOXSF: VBoxMRxCreateFileSuccessTail: VBoxFobx = %p\n", pVBoxFobx));
+        pVBoxFobx->hFile = Handle;
+        pVBoxFobx->pSrvCall = RxContext->Create.pSrvCall;
+        pVBoxFobx->FileStandardInfo = *pFileStandardInfo;
+        pVBoxFobx->FileBasicInfo = *pFileBasicInfo;
+        pVBoxFobx->fKeepCreationTime = FALSE;
+        pVBoxFobx->fKeepLastAccessTime = FALSE;
+        pVBoxFobx->fKeepLastWriteTime = FALSE;
+        pVBoxFobx->fKeepChangeTime = FALSE;
+    }
+    else return STATUS_INSUFFICIENT_RESOURCES;
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxCollapseOpen (IN OUT PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine collapses a open locally
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+#ifdef VBOX_SHFL_WITH_COLLAPSE
+    NTSTATUS Status;
+
+    RxCaptureFcb;
+    RxCaptureRequestPacket;
+
+    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
+    PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
+    PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
+
+    Log(("VBOXSF: VBoxMRxCollapseOpen: Old Fobx = %p, old VBoxFobx = %p\n", RxContext->pFobx, pVBoxFobx));
+
+    RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
+    pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
+
+    Log(("VBOXSF: VBoxMRxCollapseOpen: New Fobx = %p, new VBoxFobx = %p\n", RxContext->pFobx, pVBoxFobx));
+
+    if (RxContext->pFobx != NULL)
+    {
+        SHFLCREATEPARMS CreateParms;
+        PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+        int vboxRC;
+        VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+        VBoxMRxGetNetRootExtension(capFcb->pNetRoot,pNetRootExtension);
+        FILE_BASIC_INFORMATION * pFileBasicInfo;
+        FILE_STANDARD_INFORMATION* pFileStandardInfo;
+
+        Assert(RxIsFcbAcquiredExclusive(capFcb));
+
+        RxContext->pFobx->OffsetOfNextEaToReturn = 1;
+        capReqPacket->IoStatus.Information = FILE_OPENED;
+        Status = STATUS_SUCCESS;
+
+        /* Initialize create parameters. */
+        RtlZeroMemory (&CreateParms, sizeof (SHFLCREATEPARMS));
+
+        CreateParms.Handle = SHFL_HANDLE_NIL;
+        CreateParms.Result = SHFL_NO_RESULT;
+
+        /* Assume it's a directory; open existing, read-only access, deny-none sharing */
+        --> incorrect
+        CreateParms.CreateFlags = SHFL_CF_OPEN_TARGET_DIRECTORY
+        | SHFL_CF_DIRECTORY
+        | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW
+        | SHFL_CF_ACCESS_READ
+        | SHFL_CF_ACCESS_DENYNONE;
+        {
+            PSHFLSTRING ParsedPath = 0;
+            ULONG ParsedPathSize;
+
+            /* Calculate length required for parsed path.
+             */
+            ParsedPathSize = sizeof(*ParsedPath) + (RemainingName->Length + sizeof(WCHAR));
+
+            Log(("ParsedPathSize %d\n", ParsedPathSize));
+
+            ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+            if (NULL == ParsedPath)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+            ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+            ParsedPath->u16Size = RemainingName->Length + sizeof(WCHAR);
+            ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
+            RtlCopyMemory (ParsedPath->String.ucs2, RemainingName->Buffer, ParsedPath->u16Length);
+
+            /* Call host. */
+            vboxRC = vboxCallCreate (&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, &CreateParms);
+
+            if (ParsedPath)
+            vbsfFreeNonPagedMem (ParsedPath);
+        }
+
+        Log(("VBoxMRxCollapseOpen result %Rrc Result=%x\n", vboxRC, CreateParms.Result));
+        if (RT_FAILURE(vboxRC))
+        {
+            /* A host/guest communication error occurred while processing the request. */
+            AssertMsgFailed(("VBOXSF: vboxCallCreate failed with %Rrc\n", vboxRC));
+            return STATUS_UNSUCCESSFUL;
+        }
+
+        /*
+         * The request succeeded. Analyze host response,
+         */
+        switch (CreateParms.Result)
+        {
+            case SHFL_PATH_NOT_FOUND:
+            {
+                /* Path to object does not exist. */
+                Log(("VBOXSF: Path not found\n"));
+                return STATUS_OBJECT_PATH_NOT_FOUND;
+            }
+
+            case SHFL_FILE_NOT_FOUND:
+            {
+                Log(("VBOXSF: File not found\n"));
+                return STATUS_OBJECT_NAME_NOT_FOUND;
+            }
+            case SHFL_FILE_EXISTS:
+            {
+                Log(("VBOXSF: Object exists.\n"));
+                break; /* existing dir opened */
+            }
+
+            default:
+            {
+                Log(("VBOXSF: VBoxSF: invalid CreateResult from host %08X\n", CreateParms.Result));
+                return STATUS_OBJECT_PATH_NOT_FOUND;
+            }
+        }
+
+        pFileBasicInfo = &pVBoxFobx->FileBasicInfo;
+        pFileStandardInfo = &pVBoxFobx->FileStandardInfo;
+
+        /* Translate attributes */
+        pFileBasicInfo->FileAttributes = VBoxToNTFileAttributes(CreateParms.Info.Attr.fMode);
+
+        /* Translate file times */
+        pFileBasicInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&CreateParms.Info.BirthTime); /* ridiculous name */
+        pFileBasicInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&CreateParms.Info.AccessTime);
+        pFileBasicInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&CreateParms.Info.ModificationTime);
+        pFileBasicInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&CreateParms.Info.ChangeTime);
+
+        Assert(FlagOn(CreateParms.Info.Attr.fMode, RTFS_DOS_DIRECTORY));
+        pFileStandardInfo->AllocationSize.QuadPart = 0;
+        pFileStandardInfo->EndOfFile.QuadPart = 0;
+        pFileStandardInfo->Directory = TRUE;
+        pFileStandardInfo->NumberOfLinks = 0;
+        pFileStandardInfo->DeletePending = FALSE;
+
+        Log(("VBOXSF: VBoxMRxCollapseOpen VBoxFobx=%p\n", pVBoxFobx));
+        pVBoxFobx->hFile = CreateParms.Handle;
+        pVBoxFobx->pSrvCall = RxContext->Create.pSrvCall;
+        pVBoxFobx->FileStandardInfo = *pFileStandardInfo;
+        pVBoxFobx->FileBasicInfo = *pFileBasicInfo;
+    }
+    else
+    {
+        Status = (STATUS_INSUFFICIENT_RESOURCES);
+        AssertFailed();
+    }
+
+    return Status;
+#else
+
+#ifdef DEBUG
+    RxCaptureFcb;
+    RxCaptureRequestPacket;
+
+    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
+    PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
+    PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
+
+    Log(("VBOXSF: VBoxMRxCollapseOpen: Old Fobx = %p, old VBoxFobx = %p -> Not implemented!\n", RxContext->pFobx, pVBoxFobx));
+#endif
+    return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+NTSTATUS VBoxMRxComputeNewBufferingState (IN OUT PMRX_SRV_OPEN pMRxSrvOpen, IN PVOID pMRxContext, OUT PULONG pNewBufferingState)
+/*++
+
+ Routine Description:
+
+ This routine maps specific oplock levels into the appropriate RDBSS
+ buffering state flags
+
+ Arguments:
+
+ pMRxSrvOpen - the MRX SRV_OPEN extension
+
+ pMRxContext - the context passed to RDBSS at Oplock indication time
+
+ pNewBufferingState - the place holder for the new buffering state
+
+ Return Value:
+
+
+ Notes:
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    Log(("VBOXSF: VBoxMRxComputeNewBufferingState \n"));
+    return (Status);
+}
+
+NTSTATUS VBoxMRxDeallocateForFcb (IN OUT PMRX_FCB pFcb)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxDeallocateForFcb\n"));
+
+    return (Status);
+}
+
+NTSTATUS VBoxMRxTruncate (IN PRX_CONTEXT pRxContext)
+/*++
+
+ Routine Description:
+
+ This routine truncates the contents of a file system object
+
+ Arguments:
+
+ pRxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    Log(("VBoxMRxTruncate\n"));
+    AssertMsgFailed(("Found a truncate"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS VBoxMRxCleanupFobx (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine cleansup a file system object...normally a noop. unless it's a pipe in which case
+ we do the close at cleanup time and mark the file as being not open.
+
+ Arguments:
+
+ pRxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
+    NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
+    PMRX_SRV_OPEN pSrvOpen = NULL;
+    BOOLEAN SearchHandleOpen = FALSE;
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxCleanupFobx: capFcb = %p, capFobx = %p\n", capFcb, capFobx));
+    Assert(capFcb);
+    Assert(capFobx);
+
+    pSrvOpen = capFobx->pSrvOpen;
+    Assert(pSrvOpen);
+
+    Assert(NodeType(pSrvOpen) == RDBSS_NTC_SRVOPEN);
+    Assert(NodeTypeIsFcb(capFcb));
+
+    if (NULL == pVBoxFobx)
+        return STATUS_INVALID_PARAMETER;
+
+    Log(("VBOXSF: VBoxMRxCleanupFobx: vboxFobx = %p, Handle = 0x%08x\n", pVBoxFobx, pVBoxFobx->hFile));
+
+    /* Close file */
+    if (!((capFcb->pNetRoot->Type != NET_ROOT_PIPE) && !SearchHandleOpen))
+    {
+        if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
+        {
+            PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+            VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+            VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+
+#ifndef VBOX_FAKE_IO_CREATE
+            int vboxRC = vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
+            AssertRC(vboxRC);
+#endif
+
+            pVBoxFobx->hFile = SHFL_HANDLE_NIL;
+        }
+    }
+
+    if (FlagOn(capFcb->FcbState, FCB_STATE_ORPHANED))
+    {
+        Log(("VBOXSF: VBoxMRxCleanupFobx: File orphaned\n"));
+        return (STATUS_SUCCESS);
+    }
+
+    if ((capFcb->pNetRoot->Type != NET_ROOT_PIPE) && !SearchHandleOpen)
+    {
+        Log(("VBOXSF: VBoxMRxCleanupFobx: File not for closing at cleanup\n"));
+        return (STATUS_SUCCESS);
+    }
+
+    Log(("VBOXSF: VBoxMRxCleanupFobx: Returned with status = 0x%08lx\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxForcedClose (IN PMRX_SRV_OPEN pSrvOpen)
+/*++
+
+ Routine Description:
+
+ This routine closes a file system object
+
+ Arguments:
+
+ pSrvOpen - the instance to be closed
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ Notes:
+
+
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxForcedClose\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS VBoxMRxCloseSrvOpen (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine closes a file across the network
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    int vboxRC = 0;
+    PMRX_SRV_OPEN pSrvOpen = NULL;
+    PUNICODE_STRING RemainingName = NULL;
+    NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    PAGED_CODE();
+
+    Log(("VBOXSF: VBoxMRxCloseSrvOpen: capFcb = %p, capFobx = %p\n", capFcb, capFobx));
+    Log(("VBOXSF: VBoxMRxCloseSrvOpen: pVBoxFobx = 0x%08x\n", pVBoxFobx));
+
+    Assert(capFcb);
+    Assert(capFobx);
+
+    pSrvOpen = capFobx->pSrvOpen;
+    Assert(pSrvOpen);
+
+    RemainingName = pSrvOpen->pAlreadyPrefixedName;
+    Log(("VBOXSF: VBoxMRxCloseSrvOpen: Remaining name = %.*ls, Len = %d\n", RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, RemainingName->Length));
+
+    if (NULL == pVBoxFobx)
+        return STATUS_INVALID_PARAMETER;
+
+    /* If we renamed or delete the file/dir, then it's already closed */
+    if (FlagOn(pSrvOpen->Flags, (SRVOPEN_FLAG_FILE_RENAMED | SRVOPEN_FLAG_FILE_DELETED)))
+    {
+        Assert(pVBoxFobx->hFile == SHFL_HANDLE_NIL);
+
+        Log(("VBOXSF: VBoxMRxCloseSrvOpen: File was renamed; ignore close!\n"));
+        return STATUS_SUCCESS;
+    }
+
+    /* Close file */
+    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
+    {
+#ifndef VBOX_FAKE_IO_CREATE
+        vboxRC = vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
+        AssertRC(vboxRC);
+#endif
+        pVBoxFobx->hFile = SHFL_HANDLE_NIL;
+    }
+
+    if (capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE)
+        Log(("VBOXSF: VBoxMRxCloseSrvOpen: Delete on close. Open count = %d\n", capFcb->OpenCount));
+
+    /* Remove file or directory if delete action is pending. */
+    if ((capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE) && capFcb->OpenCount == 0)
+    {
+        Status = VBoxMRxRemove(RxContext);
+    }
+
+    return (Status);
+}
+
+NTSTATUS VBoxMRxDeallocateForFobx (IN OUT PMRX_FOBX pFobx)
+{
+    Log(("VBOXSF: VBoxMRxDeallocateForFobx\n"));
+
+    return (STATUS_SUCCESS);
+}
+
+NTSTATUS VBoxMRxRemove (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine removes a file or directory
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+    int vboxRC;
+    PSHFLSTRING ParsedPath = 0;
+    ULONG ParsedPathSize;
+    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxRemove Delete %.*ls. open count = %d!!\n", RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, capFcb->OpenCount));
+
+    /* Close file first if not already done. */
+    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
+    {
+#ifndef VBOX_FAKE_IO_CREATE
+        vboxRC = vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
+        AssertRC(vboxRC);
+#endif
+        pVBoxFobx->hFile = SHFL_HANDLE_NIL;
+    }
+
+    /* Calculate length required for parsed path.
+     */
+    ParsedPathSize = sizeof(*ParsedPath) + (RemainingName->Length + sizeof(WCHAR));
+
+    Log(("ParsedPathSize %d\n", ParsedPathSize));
+
+    ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+    if (!ParsedPath)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+    Log(("Setup ParsedPath\n"));
+    ParsedPath->u16Size = RemainingName->Length + sizeof(WCHAR);
+    ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
+    RtlCopyMemory (ParsedPath->String.ucs2, RemainingName->Buffer, ParsedPath->u16Length);
+
+    /* Call host. */
+#ifdef VBOX_FAKE_IO_DELETE
+    vboxRC = VINF_SUCCESS;
+#else
+    vboxRC = vboxCallRemove(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, (pVBoxFobx->FileStandardInfo.Directory) ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE);
+#endif
+
+    if (ParsedPath)
+        vbsfFreeNonPagedMem(ParsedPath);
+
+    Status = VBoxErrorToNTStatus(vboxRC);
+    if (vboxRC != VINF_SUCCESS)
+        Log(("vboxCallRemove failed with %d (status=%d)\n", vboxRC, Status));
+
+    if (vboxRC == VINF_SUCCESS)
+        SetFlag(pSrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED);
+
+    return Status;
+}
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/precomp.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/precomp.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/precomp.h	(revision 31634)
@@ -0,0 +1,39 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+
+ --*/
+
+#define MINIRDR__NAME NulMRx
+#define ___MINIRDR_IMPORTS_NAME (NulMRxDeviceObject->RdbssExports)
+
+#include <ntifs.h>
+
+#include "rx.h"
+
+#include "nodetype.h"
+#include "netevent.h"
+
+#include <windef.h>
+
+#include "nulmrx.h"
+#include "minip.h"
+#include <lmcons.h>     // from the Win32 SDK
+#include "mrxglobs.h"
+
+#ifdef VBOX
+#define try __try
+#define leave __leave
+#define finally __finally
+#define except __except
+/* bird: Added this to kill warnings about using unprototyped functions.
+ *       I hope it doesn't break anything... */
+#include "vbsfhlp.h"
+
+////#define VBOX_FAKE_IO
+////#define VBOX_FAKE_IO_READ_WRITE
+////#define VBOX_FAKE_IO_CREATE
+////#define VBOX_FAKE_IO_DELETE
+
+#endif
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss.asm
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss.asm	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss.asm	(revision 31634)
@@ -0,0 +1,92 @@
+;
+; Export definitions
+;
+; Copyright (C) 2006-2007 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+;*******************************************************************************
+;* Header Files                                                                *
+;*******************************************************************************
+%include "VBox/asmdefs.mac"
+
+extern __imp__RxAcquireExclusiveFcbResourceInMRx
+extern __imp__RxCreateNetFobx
+extern __imp__RxCreateRxContext
+extern __imp__RxDereferenceAndDeleteRxContext_Real
+extern __imp__RxDispatchToWorkerThread
+extern __imp__RxFinalizeConnection
+extern __imp__RxFinishFcbInitialization
+extern __imp__RxFsdDispatch
+extern __imp__RxGetFileSizeWithLock
+extern __imp__RxGetFileSizeWithLock
+extern __imp__RxLowIoGetBufferAddress
+extern __imp__RxRegisterMinirdr
+extern __imp__RxStartMinirdr
+extern __imp__RxStopMinirdr
+extern __imp__RxpUnregisterMinirdr
+extern __imp__RxGetRDBSSProcess
+
+
+BEGINPROC   RxAcquireExclusiveFcbResourceInMRx@4
+    jmp     dword [__imp__RxAcquireExclusiveFcbResourceInMRx]
+ENDPROC     RxAcquireExclusiveFcbResourceInMRx@4
+
+BEGINPROC   RxCreateNetFobx@8
+    jmp     dword [__imp__RxCreateNetFobx]
+ENDPROC     RxCreateNetFobx@8
+
+BEGINPROC   RxCreateRxContext@12
+    jmp     dword [__imp__RxCreateRxContext]
+ENDPROC     RxCreateRxContext@12
+
+BEGINPROC   RxDereferenceAndDeleteRxContext_Real@4
+    jmp     dword [__imp__RxDereferenceAndDeleteRxContext_Real]
+ENDPROC     RxDereferenceAndDeleteRxContext_Real@4
+
+BEGINPROC   RxDispatchToWorkerThread@16
+    jmp     dword [__imp__RxDispatchToWorkerThread]
+ENDPROC     RxDispatchToWorkerThread@16
+
+BEGINPROC   RxFinalizeConnection@12
+    jmp     dword [__imp__RxFinalizeConnection]
+ENDPROC     RxFinalizeConnection@12
+
+BEGINPROC   RxFinishFcbInitialization@12
+    jmp     dword [__imp__RxFinishFcbInitialization]
+ENDPROC     RxFinishFcbInitialization@12
+
+BEGINPROC   RxFsdDispatch@8
+    jmp     dword [__imp__RxFsdDispatch]
+ENDPROC     RxFsdDispatch@8
+
+BEGINPROC   RxGetFileSizeWithLock@8
+    jmp     dword [__imp__RxGetFileSizeWithLock]
+ENDPROC     RxGetFileSizeWithLock@8
+
+BEGINPROC   RxGetRDBSSProcess@0
+    jmp     dword [__imp__RxGetRDBSSProcess]
+ENDPROC     RxGetRDBSSProcess@0
+
+BEGINPROC   RxLowIoGetBufferAddress@4
+    jmp     dword [__imp__RxLowIoGetBufferAddress]
+ENDPROC     RxLowIoGetBufferAddress@4
+
+BEGINPROC   RxRegisterMinirdr@32
+    jmp     dword [__imp__RxRegisterMinirdr]
+ENDPROC     RxRegisterMinirdr@32
+
+BEGINPROC   RxStartMinirdr@8
+    jmp     dword [__imp__RxStartMinirdr]
+ENDPROC     RxStartMinirdr@8
+
+BEGINPROC   RxStopMinirdr@8
+    jmp     dword [__imp__RxStopMinirdr]
+ENDPROC     RxStopMinirdr@8
+
+BEGINPROC   RxpUnregisterMinirdr@4
+    jmp     dword [__imp__RxpUnregisterMinirdr]
+ENDPROC     RxpUnregisterMinirdr@4
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss/rdbss.def
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss/rdbss.def	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss/rdbss.def	(revision 31634)
@@ -0,0 +1,134 @@
+;
+; Export definitions
+;
+; Copyright (C) 2006-2007 Oracle Corporation
+;
+; Oracle Corporation confidential
+; All rights reserved
+;
+
+LIBRARY RDBSS.SYS
+
+EXPORTS
+    RxAcquireExclusiveFcbResourceInMRx
+    RxAcquireSharedFcbResourceInMRx
+    RxAcquireSharedFcbResourceInMRxEx
+    RxAssert
+    RxAssociateContextWithMid
+    RxCancelTimerRequest
+    RxCeAllocateIrpWithMDL
+    RxCeBuildAddress
+    RxCeBuildConnection
+    RxCeBuildConnectionOverMultipleTransports
+    RxCeBuildTransport
+    RxCeBuildVC
+    RxCeCancelConnectRequest
+    RxCeFreeIrp
+    RxCeInitiateVCDisconnect
+    RxCeQueryAdapterStatus
+    RxCeQueryInformation
+    RxCeQueryTransportInformation
+    RxCeSend
+    RxCeSendDatagram
+    RxCeTearDownAddress
+    RxCeTearDownConnection
+    RxCeTearDownTransport
+    RxCeTearDownVC
+    RxChangeBufferingState
+    RxCompleteRequest
+    RxCompleteRequest_Real
+    RxCreateMidAtlas
+    RxCreateNetFcb
+    RxCreateNetFobx
+    RxCreateNetRoot
+    RxCreateRxContext
+    RxCreateSrvCall
+    RxCreateSrvOpen
+    RxCreateVNetRoot
+    RxDbgBreakPoint
+    RxDereference
+    RxDereferenceAndDeleteRxContext_Real
+    RxDestroyMidAtlas
+    RxDispatchToWorkerThread
+    RxFinalizeConnection
+    RxFinalizeNetFcb
+    RxFinalizeNetFobx
+    RxFinalizeNetRoot
+    RxFinalizeSrvCall
+    RxFinalizeSrvOpen
+    RxFinalizeVNetRoot
+    RxFinishFcbInitialization
+    RxForceFinalizeAllVNetRoots
+    RxFsdDispatch
+    RxFsdPostRequest
+    RxGetFileSizeWithLock
+    RxGetRDBSSProcess
+    RxIndicateChangeOfBufferingState
+    RxIndicateChangeOfBufferingStateForSrvOpen
+    RxInferFileType
+    RxInitializeContext
+    RxLockEnumerator
+    RxLogEventDirect
+    RxLogEventWithAnnotation
+    RxLogEventWithBufferDirect
+    RxLowIoCompletion
+    RxLowIoGetBufferAddress
+    RxMakeLateDeviceAvailable
+    RxMapAndDissociateMidFromContext
+    RxMapMidToContext
+    RxMapSystemBuffer
+    RxNameCacheActivateEntry
+    RxNameCacheAddNameCacheControlToGlobalList
+    RxNameCacheCheckEntry
+    RxNameCacheCreateEntry
+    RxNameCacheExpireAndFinalizeEx
+    RxNameCacheExpireEntry
+    RxNameCacheExpireEntryWithShortName
+    RxNameCacheFetchEntry
+    RxNameCacheFinalize
+    RxNameCacheFinalizeEx
+    RxNameCacheFreeActiveListEntries
+    RxNameCacheFreeEntry
+    RxNameCacheFreeNotifiedFreeList
+    RxNameCacheInitialize
+    RxNameCacheInitializeEx
+    RxNameCacheNotifyFreeListEntries
+    RxNameCacheRemoveNameCacheCtlFromGlobalList
+    RxNameCacheScavengeNameCaches
+    RxNewMapUserBuffer
+    RxPostOneShotTimerRequest
+    RxPostRecurrentTimerRequest
+    RxPostToWorkerThread
+    RxPrefixTableLookupName
+    RxPrepareContextForReuse
+    RxPrepareToReparseSymbolicLink
+    RxPurgeAllFobxs
+    RxPurgeRelatedFobxs
+    RxReassociateMid
+    RxReference
+    RxRegisterMinirdr
+    RxReleaseFcbResourceForThreadInMRx
+    RxReleaseFcbResourceInMRx
+    RxResumeBlockedOperations_Serially
+    RxScavengeAllFobxs
+    RxScavengeFobxsForNetRoot
+    RxSetDomainForMailslotBroadcast
+    RxSetMinirdrCancelRoutine
+    RxSetSrvCallDomainName
+    RxSpinDownMRxDispatcher
+    RxStartMinirdr = _RxStartMinirdr@8
+    RxStopMinirdr
+    RxpAcquirePrefixTableLockExclusive
+    RxpAcquirePrefixTableLockShared
+    RxpDereferenceAndFinalizeNetFcb
+    RxpDereferenceNetFcb
+    RxpReferenceNetFcb
+    RxpReleasePrefixTableLock
+    RxpTrackDereference
+    RxpTrackReference
+    RxpUnregisterMinirdr
+    _RxAllocatePoolWithTag
+    _RxCheckMemoryBlock
+    _RxFreePool
+    __RxFillAndInstallFastIoDispatch
+    __RxSynchronizeBlockingOperationsMaybeDroppingFcbLock
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.c	(revision 31634)
@@ -0,0 +1,99 @@
+#include "rdbss_vbox.h"
+#pragma hdrstop
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* KeXXXXXXX or ExXXXXXXXXX */
+
+NTSTATUS VBoxRxRegisterMinirdr (PRDBSS_DEVICE_OBJECT *DeviceObject, PDRIVER_OBJECT DriverObject, PMINIRDR_DISPATCH MrdrDispatch, ULONG Controls, PUNICODE_STRING DeviceName, ULONG DeviceExtensionSize,
+                                DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics)
+{
+    return RxRegisterMinirdr(DeviceObject, DriverObject, MrdrDispatch, Controls, DeviceName, DeviceExtensionSize, DeviceType, DeviceCharacteristics);
+    return STATUS_SUCCESS;
+}
+
+VOID VBoxRxUnregisterMinirdr (PRDBSS_DEVICE_OBJECT RxDeviceObject)
+{
+    RxUnregisterMinirdr(RxDeviceObject);
+}
+
+NTSTATUS VBoxRxStartMinirdr (PRX_CONTEXT RxContext, PBOOLEAN PostToFsp)
+{
+    return RxStartMinirdr(RxContext, PostToFsp);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxRxStopMinirdr (PRX_CONTEXT RxContext, PBOOLEAN PostToFsp)
+{
+    return RxStopMinirdr(RxContext, PostToFsp);
+    return STATUS_SUCCESS;
+}
+
+PRX_CONTEXT VBoxRxCreateRxContext (PIRP Irp, PRDBSS_DEVICE_OBJECT RxDeviceObject, ULONG InitialContextFlags)
+{
+    return RxCreateRxContext(Irp, RxDeviceObject, InitialContextFlags);
+}
+
+VOID VBoxRxDereferenceAndDeleteRxContext (PRX_CONTEXT RxContext)
+{
+    RxDereferenceAndDeleteRxContext(RxContext);
+}
+
+NTSTATUS VBoxRxFinalizeConnection (OUT PNET_ROOT NetRoot, OUT PV_NET_ROOT VNetRoot, LOGICAL Level)
+{
+    return RxFinalizeConnection(NetRoot, VNetRoot, Level);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxRxFsdDispatch (PRDBSS_DEVICE_OBJECT RxDeviceObject, PIRP Irp)
+{
+    return RxFsdDispatch(RxDeviceObject, Irp);
+    return STATUS_SUCCESS;
+}
+
+VOID VBoxRxGetFileSizeWithLock (PFCB Fcb, OUT PLONGLONG FileSize)
+{
+    RxGetFileSizeWithLock(Fcb, FileSize);
+}
+
+PVOID VBoxRxLowIoGetBufferAddress (IN PRX_CONTEXT RxContext)
+{
+    return RxLowIoGetBufferAddress(RxContext);
+}
+
+NTSTATUS VBoxRxDispatchToWorkerThread (OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject, WORK_QUEUE_TYPE WorkQueueType, PRX_WORKERTHREAD_ROUTINE Routine, PVOID pContext)
+{
+    return RxDispatchToWorkerThread(pMRxDeviceObject, WorkQueueType, Routine, pContext);
+    return STATUS_SUCCESS;
+}
+
+/* FCB stuff */
+
+VOID VboxRxFinishFcbInitialization (PMRX_FCB MrxFcb, RDBSS_STORAGE_TYPE_CODES RdbssStorageType, PFCB_INIT_PACKET InitPacket)
+{
+    RxFinishFcbInitialization(MrxFcb, RdbssStorageType, InitPacket);
+}
+
+NTSTATUS VboxRxAcquireExclusiveFcbResourceInMRx (PMRX_FCB pFcb)
+{
+    return RxAcquireExclusiveFcbResourceInMRx(pFcb);
+    return STATUS_SUCCESS;
+}
+
+BOOLEAN VBoxRxIsFcbAcquiredExclusive (PMRX_FCB pFcb)
+{
+    // ExIsResourceAcquiredExclusive is obsolete since W2K and XP!
+    return ExIsResourceAcquiredExclusiveLite(RX_GET_MRX_FCB(pFcb)->Header.Resource);
+}
+
+/* FOBX stuff */
+
+PMRX_FOBX VboxRxCreateNetFobx (OUT PRX_CONTEXT RxContext, IN PMRX_SRV_OPEN MrxSrvOpen)
+{
+    return RxCreateNetFobx(RxContext, MrxSrvOpen);
+    return NULL;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rdbss_vbox.h	(revision 31634)
@@ -0,0 +1,32 @@
+#include "precomp.h"
+
+NTSTATUS VBoxRxRegisterMinirdr (PRDBSS_DEVICE_OBJECT *DeviceObject, PDRIVER_OBJECT DriverObject, PMINIRDR_DISPATCH MrdrDispatch, ULONG Controls, PUNICODE_STRING DeviceName, ULONG DeviceExtensionSize,
+                                DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics);
+
+VOID VBoxRxUnregisterMinirdr (PRDBSS_DEVICE_OBJECT RxDeviceObject);
+
+NTSTATUS VBoxRxStartMinirdr (PRX_CONTEXT RxContext, PBOOLEAN PostToFsp);
+
+NTSTATUS VBoxRxStopMinirdr (PRX_CONTEXT RxContext, PBOOLEAN PostToFsp);
+
+PRX_CONTEXT VBoxRxCreateRxContext (PIRP Irp, PRDBSS_DEVICE_OBJECT RxDeviceObject, ULONG InitialContextFlags);
+
+VOID VBoxRxDereferenceAndDeleteRxContext_Real (PRX_CONTEXT RxContext);
+
+NTSTATUS VBoxRxFinalizeConnection (OUT PNET_ROOT NetRoot, OUT PV_NET_ROOT VNetRoot, LOGICAL Level);
+
+NTSTATUS VBoxRxFsdDispatch (PRDBSS_DEVICE_OBJECT RxDeviceObject, PIRP Irp);
+
+VOID VBoxRxGetFileSizeWithLock (PFCB Fcb, OUT PLONGLONG FileSize);
+
+PVOID VBoxRxLowIoGetBufferAddress (IN PRX_CONTEXT RxContext);
+
+NTSTATUS VBoxRxDispatchToWorkerThread (OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject, WORK_QUEUE_TYPE WorkQueueType, PRX_WORKERTHREAD_ROUTINE Routine, PVOID pContext);
+
+VOID VboxRxFinishFcbInitialization (PMRX_FCB MrxFcb, RDBSS_STORAGE_TYPE_CODES RdbssStorageType, PFCB_INIT_PACKET InitPacket);
+
+NTSTATUS VboxRxAcquireExclusiveFcbResourceInMRx (PMRX_FCB pFcb);
+
+BOOLEAN VBoxRxIsFcbAcquiredExclusive (PMRX_FCB pFcb);
+
+PMRX_FOBX VboxRxCreateNetFobx (OUT PRX_CONTEXT RxContext, IN PMRX_SRV_OPEN MrxSrvOpen);
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/read.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/read.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/read.c	(revision 31634)
@@ -0,0 +1,189 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ read.c
+
+ Abstract:
+
+ This module implements the mini redirector call down routines pertaining to read
+ of file system objects.
+
+ --*/
+
+#include "precomp.h"
+#include <VBox/log.h>
+#include "rdbss_vbox.h"
+
+#pragma hdrstop
+
+static NTSTATUS VBoxMRxReadInternal (IN PRX_CONTEXT RxContext)
+/*++
+
+ Routine Description:
+
+ This routine handles network read requests.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+    PMDL OriginalDataMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
+
+    PVOID pbUserBuffer = VBoxRxLowIoGetBufferAddress(RxContext);
+    uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
+    RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
+    LONGLONG FileSize = 0;
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = (PMRX_VBOX_NETROOT_EXTENSION)pNetRoot->Context;
+    BOOLEAN SynchronousIo = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
+#ifndef VBOX
+    PDEVICE_OBJECT deviceObject;
+#endif
+
+    PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    Log(("VBOXSF: VBoxMRxRead: SynchronousIo = %d\n", SynchronousIo));
+    Log(("VBOXSF: VBoxMRxRead: NetRoot is 0x%x, Fcb is 0x%x\n", pNetRoot, capFcb));
+
+    VBoxRxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
+
+    //
+    //  NB: This should be done by the wrapper ! It does this
+    //  only if READCACHING is enabled on the FCB !!
+    //
+#if (NTDDI_VERSION >= NTDDI_VISTA)      /* Correct spelling for Vista 6001 SDK. */
+    if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHING_ENABLED))
+#else
+    if (!FlagOn(capFcb->FcbState,FCB_STATE_READCACHEING_ENABLED))
+#endif
+    {
+        //
+        // If the read starts beyond End of File, return EOF.
+        //
+
+        if (ByteOffset >= FileSize)
+        {
+            Log(("VBOXSF: VBoxMRxRead: End of File\n", 0 ));
+            Status = STATUS_END_OF_FILE;
+            goto Exit;
+        }
+
+        //
+        //  If the read extends beyond EOF, truncate the read
+        //
+
+        if (ByteCount > FileSize - ByteOffset)
+        {
+            ByteCount = (ULONG)(FileSize - ByteOffset);
+        }
+    }
+
+    Log(("VBOXSF: VBoxMRxRead: UserBuffer is 0x%x\n", pbUserBuffer));
+    Log(("VBOXSF: VBoxMRxRead: ByteCount is %d, ByteOffset is %x\n", ByteCount, ByteOffset));
+
+    Assert((OriginalDataMdl != NULL && (RxMdlIsLocked(OriginalDataMdl) || RxMdlSourceIsNonPaged(OriginalDataMdl))) || (OriginalDataMdl == NULL && LowIoContext->ParamsFor.ReadWrite.ByteCount == 0));
+
+    if (OriginalDataMdl == NULL || LowIoContext->ParamsFor.ReadWrite.ByteCount == 0)
+    {
+        AssertFailed();
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* @todo async io !!!! */
+    SynchronousIo = TRUE;
+
+    if (SynchronousIo)
+    {
+        int vboxRC;
+
+        /* Do the actual reading */
+#ifdef VBOX_FAKE_IO_READ_WRITE
+        Status = STATUS_SUCCESS;
+        memset(pbUserBuffer, 0, ByteCount);
+#else
+        vboxRC = vboxCallRead(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
+        AssertRC(vboxRC);
+
+        Status = VBoxErrorToNTStatus(vboxRC);
+#endif
+        if (Status != STATUS_SUCCESS)
+            ByteCount = 0; /* Nothing read */
+
+        Log(("VBOXSF: VBoxMRxRead: This I/O is sync!\n"));
+
+        RxContext->InformationToReturn = ByteCount;
+
+        /* Never call RxLowIoCompletion here!! */
+    }
+    else
+    {
+        Log(("VBOXSF: VBoxMRxRead: This I/O is async!\n"));
+    }
+
+    Log(("VBOXSF: VBoxMRxRead: Status = %x Info = %x\n",RxContext->IoStatusBlock.Status,RxContext->IoStatusBlock.Information));
+
+    Exit:
+
+    return (Status);
+}
+
+
+static VOID VBoxMRxReadWorker (VOID *pv)
+{
+    PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
+
+    Log(("VBOXSF: VBoxMRxReadWorker: calling the worker\n"));
+
+    RxContext->IoStatusBlock.Status = VBoxMRxReadInternal (RxContext);
+
+    Log(("VBOXSF: VBoxMRxReadWorker: Status %x\n", RxContext->IoStatusBlock.Status));
+
+    RxLowIoCompletion (RxContext);
+}
+
+
+#ifdef VBOX_ASYNC_RW
+NTSTATUS
+VBoxMRxRead (
+      IN PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
+                                      VBoxMRxReadWorker,
+                                      RxContext);
+
+    Log(("VBOXSF: VBoxMRxRead: RxDispatchToWorkerThread: Status %x\n", Status));
+
+    if (Status == STATUS_SUCCESS)
+    {
+        Status = STATUS_PENDING;
+    }
+
+    return Status;
+}
+#else
+NTSTATUS
+VBoxMRxRead (
+      IN PRX_CONTEXT RxContext)
+{
+    RxContext->IoStatusBlock.Status = VBoxMRxReadInternal (RxContext);
+    return RxContext->IoStatusBlock.Status;
+}
+#endif /* !VBOX_ASYNC_RW */
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rename.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rename.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/rename.c	(revision 31634)
@@ -0,0 +1,129 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ rename.c
+
+ Abstract:
+
+ This module implements rename in the null minirdr.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef VBOX
+NTSTATUS
+#endif
+VBoxMRxRename (IN PRX_CONTEXT RxContext, IN FILE_INFORMATION_CLASS FileInformationClass, IN PVOID pBuffer, IN ULONG BufferLength)
+/*++
+
+ Routine Description:
+
+ This routine does a rename. since the real NT-->NT path is not implemented at the server end,
+ we implement just the downlevel path.
+
+ Arguments:
+
+ RxContext - the RDBSS context
+ FILE_INFO_CLASS - must be rename....shouldn't really pass this
+ pBuffer - pointer to the new name
+ bufferlength - and the size
+
+ Return Value:
+
+ NTSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+    PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
+    PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen, capFcb);
+    PFILE_RENAME_INFORMATION RenameInformation = (PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+    PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    int vboxRC;
+    PSHFLSTRING SrcPath = 0, DestPath = 0;
+    ULONG ParsedPathSize, flags;
+
+    Assert(FileInformationClass == FileRenameInformation);
+
+    Log(("VBOXSF: VBoxMRxRename: FileName = %.*ls\n", RenameInformation->FileNameLength / sizeof(WCHAR), &RenameInformation->FileName[0]));
+
+    /* Must close the file before renaming it! */
+    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
+    {
+        vboxRC = vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
+        AssertRC(vboxRC);
+        pVBoxFobx->hFile = SHFL_HANDLE_NIL;
+    }
+
+    /* Mark it as renamed, so we do nothing during close */
+    SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED);
+
+    /* Calculate length required for destination path.
+     */
+    ParsedPathSize = sizeof(*DestPath) + (RenameInformation->FileNameLength + sizeof(WCHAR));
+
+    Log(("VBOXSF: VBoxMRxRename: ParsedPathSize = %d\n", ParsedPathSize));
+
+    DestPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+
+    if (NULL == DestPath)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    RtlZeroMemory(DestPath, ParsedPathSize);
+    ShflStringInitBuffer(DestPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+    Log(("VBOXSF: VBoxMRxRename: Setting up destination path ...\n"));
+    DestPath->u16Size = (USHORT)(RenameInformation->FileNameLength + sizeof(WCHAR));
+    DestPath->u16Length = DestPath->u16Size - sizeof(WCHAR); /* without terminating null */
+    RtlCopyMemory(DestPath->String.ucs2, RenameInformation->FileName, DestPath->u16Length);
+    Log(("VBOXSF: VBoxMRxRename: Destination path = %.*ls\n", DestPath->u16Length / sizeof(WCHAR), &DestPath->String.ucs2[0]));
+
+    /* Calculate length required for source path
+     */
+    ParsedPathSize = sizeof(*DestPath) + (RemainingName->Length + sizeof(WCHAR));
+    Log(("VBOXSF: VBoxMRxRename: ParsedPathSize = %d\n", ParsedPathSize));
+
+    SrcPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+
+    if (NULL == SrcPath)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    RtlZeroMemory(SrcPath, ParsedPathSize);
+    ShflStringInitBuffer(SrcPath, ParsedPathSize - sizeof(SHFLSTRING));
+
+    Log(("VBOXSF: VBoxMRxRename: Setting up source path ...\n"));
+    SrcPath->u16Size = RemainingName->Length + sizeof(WCHAR);
+    SrcPath->u16Length = SrcPath->u16Size - sizeof(WCHAR); /* without terminating null */
+    RtlCopyMemory(SrcPath->String.ucs2, RemainingName->Buffer, SrcPath->u16Length);
+    Log(("VBOXSF: VBoxMRxRename: Source path = %.*ls\n", SrcPath->u16Length / sizeof(WCHAR), &SrcPath->String.ucs2[0]));
+
+    /* Call host. */
+    flags = (pVBoxFobx->FileStandardInfo.Directory) ? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
+    if (RenameInformation->ReplaceIfExists)
+        flags |= SHFL_RENAME_REPLACE_IF_EXISTS;
+
+    Log(("VBOXSF: VBoxMRxRename: Calling vboxCallRename ...\n", SrcPath->u16Length / sizeof(WCHAR), &SrcPath->String.ucs2[0]));
+    vboxRC = vboxCallRename(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, SrcPath, DestPath, flags);
+
+    vbsfFreeNonPagedMem(SrcPath);
+    vbsfFreeNonPagedMem(DestPath);
+
+    Status = VBoxErrorToNTStatus(vboxRC);
+    if (vboxRC != VINF_SUCCESS)
+        Log(("VBOXSF: VBoxMRxRename: vboxCallRename failed with %d (Status = %x)!\n", vboxRC, Status));
+
+    Log(("VBOXSF: VBoxMRxRename: Returned 0x%lx\n", Status));
+    return (Status);
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/srvcall.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/srvcall.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/srvcall.c	(revision 31634)
@@ -0,0 +1,243 @@
+/*
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ srvcall.c
+
+ Abstract:
+
+ This module implements the routines for handling the creation/manipulation of
+ server entries in the connection engine database. It also contains the routines
+ for parsing the negotiate response from  the server.
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+VOID ExecuteCreateSrvCall (PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
+/*++
+
+ Routine Description:
+
+ This routine patches the RDBSS created srv call instance with the
+ information required by the mini redirector.
+
+ Arguments:
+
+ CallBackContext  - the call back context in RDBSS for continuation.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status;
+    PWCHAR pSrvName = 0;
+    BOOLEAN Verifier;
+
+    PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = pCallbackContext;
+    PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(SCCBC->SrvCalldownStructure);
+    PMRX_SRV_CALL pSrvCall = SrvCalldownStructure->SrvCall;
+
+    Assert(pSrvCall);
+    Assert(NodeType(pSrvCall) == RDBSS_NTC_SRVCALL);
+
+    /* Validate the server name with the test name of 'vboxsvr'. */
+    Log(("VBOXSF: ExecuteCreateSrvCall: Connection Name %.*ls Length: %d, pSrvCall = %p\n", pSrvCall->pSrvCallName->Length / sizeof(WCHAR), pSrvCall->pSrvCallName->Buffer, pSrvCall->pSrvCallName->Length, pSrvCall));
+
+    if (pSrvCall->pPrincipalName && pSrvCall->pPrincipalName->Length)
+        Log(("VBOXSF: ExecuteCreateSrvCall: Principal name = %.*ls\n", pSrvCall->pPrincipalName->Length / sizeof(WCHAR), pSrvCall->pPrincipalName->Buffer));
+
+    if (pSrvCall->pDomainName && pSrvCall->pDomainName->Length)
+        Log(("VBOXSF: ExecuteCreateSrvCall: Domain name = %.*ls\n", pSrvCall->pDomainName->Length / sizeof(WCHAR), pSrvCall->pDomainName->Buffer));
+
+    if (pSrvCall->pSrvCallName->Length >= 14)
+    {
+        pSrvName = pSrvCall->pSrvCallName->Buffer;
+
+        Verifier = (pSrvName[0] == L'\\');
+        Verifier &= (pSrvName[1] == L'V') || (pSrvName[1] == L'v');
+        Verifier &= (pSrvName[2] == L'B') || (pSrvName[2] == L'b');
+        Verifier &= (pSrvName[3] == L'O') || (pSrvName[3] == L'o');
+        Verifier &= (pSrvName[4] == L'X') || (pSrvName[4] == L'x');
+        Verifier &= (pSrvName[5] == L'S') || (pSrvName[5] == L's');
+        /* Both vboxsvr & vboxsrv are now accepted */
+        if ((pSrvName[6] == L'V') || (pSrvName[6] == L'v'))
+        {
+            Verifier &= (pSrvName[6] == L'V') || (pSrvName[6] == L'v');
+            Verifier &= (pSrvName[7] == L'R') || (pSrvName[7] == L'r');
+        }
+        else
+        {
+            Verifier &= (pSrvName[6] == L'R') || (pSrvName[6] == L'r');
+            Verifier &= (pSrvName[7] == L'V') || (pSrvName[7] == L'v');
+        }
+        Verifier &= (pSrvName[8] == L'\\') || (pSrvName[8] == 0);
+    }
+    else
+    {
+        Verifier = FALSE;
+    }
+
+    if (Verifier)
+    {
+        Log(("VBOXSF: ExecuteCreateSrvCall: Verifier succeeded!\n"));
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        Log(("VBOXSF: ExecuteCreateSrvCall: Verifier failed!\n"));
+        Status = STATUS_BAD_NETWORK_PATH;
+    }
+
+    SCCBC->Status = Status;
+    SrvCalldownStructure->CallBack(SCCBC);
+}
+
+NTSTATUS VBoxMRxCreateSrvCall (PMRX_SRV_CALL pSrvCall, PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
+/*++
+
+ Routine Description:
+
+ This routine patches the RDBSS created srv call instance with the information required
+ by the mini redirector.
+
+ Arguments:
+
+ RxContext        - Supplies the context of the original create/ioctl
+
+ CallBackContext  - the call back context in RDBSS for continuation.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status;
+
+    PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(pCallbackContext->SrvCalldownStructure);
+
+    Assert(pSrvCall);
+    Assert(NodeType(pSrvCall) == RDBSS_NTC_SRVCALL);
+
+    Log(("VBOXSF: VBoxMRxCreateSrvCall: Called %p.\n", pSrvCall));
+
+    //
+    // If this request was made on behalf of the RDBSS, do ExecuteCreatSrvCall
+    // immediately. If the request was made from somewhere else, create a work item
+    // and place it on a queue for a worker thread to process later. This distinction
+    // is made to simplify transport handle management.
+    //
+    if (IoGetCurrentProcess() == RxGetRDBSSProcess())
+    {
+        Log(("VBOXSF: VBoxMRxCreateSrvCall: Called in context of RDBSS process\n"));
+
+        //
+        // Peform the processing immediately because RDBSS is the initiator of this
+        // request
+        //
+
+        ExecuteCreateSrvCall(pCallbackContext);
+    }
+    else
+    {
+        Log(("VBOXSF: VBoxMRxCreateSrvCall: Dispatching to worker thread\n"));
+
+        //
+        // Dispatch the request to a worker thread because the redirected drive
+        // buffering sub-system (RDBSS) was not the initiator
+        //
+
+        Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, (PWORKER_THREAD_ROUTINE)ExecuteCreateSrvCall, /* explicit cast for first parameter type */
+        pCallbackContext);
+
+        if (Status == STATUS_SUCCESS)
+        {
+            Log(("VBOXSF: VBoxMRxCreateSrvCall: queued!\n"));
+        }
+        else
+        {
+            pCallbackContext->Status = Status;
+            SrvCalldownStructure->CallBack(pCallbackContext);
+        }
+    }
+
+    //
+    // The wrapper expects PENDING.
+    //
+    return STATUS_PENDING;
+}
+
+NTSTATUS VBoxMRxFinalizeSrvCall (PMRX_SRV_CALL pSrvCall, BOOLEAN Force)
+/*++
+
+ Routine Description:
+
+ This routine destroys a given server call instance
+
+ Arguments:
+
+ pSrvCall  - the server call instance to be disconnected.
+
+ Force     - TRUE if a disconnection is to be enforced immediately.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxFinalizeSrvCall called %p, ctx = %p.\n", pSrvCall, pSrvCall->Context));
+    pSrvCall->Context = NULL;
+
+    return (Status);
+}
+
+NTSTATUS VBoxMRxSrvCallWinnerNotify (IN PMRX_SRV_CALL pSrvCall, IN BOOLEAN ThisMinirdrIsTheWinner, IN OUT PVOID pSrvCallContext)
+/*++
+
+ Routine Description:
+
+ This routine finalizes the mini rdr context associated with an RDBSS Server call instance
+
+ Arguments:
+
+ pSrvCall               - the Server Call
+
+ ThisMinirdrIsTheWinner - TRUE if this mini rdr is the choosen one.
+
+ pSrvCallContext  - the server call context created by the mini redirector.
+
+ Return Value:
+
+ RXSTATUS - The return status for the operation
+
+ Notes:
+
+ The two phase construction protocol for Server calls is required because of parallel
+ initiation of a number of mini redirectors. The RDBSS finalizes the particular mini
+ redirector to be used in communicating with a given server based on quality of
+ service criterion.
+
+ --*/
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: VBoxMRxSrvCallWinnerNotify called %p.\n", pSrvCall));
+    if (ThisMinirdrIsTheWinner)
+    {
+        Log(("VBOXSF: VBoxMRxSrvCallWinnerNotify: VboxSF.sys is the winner!\n"));
+    }
+
+    pSrvCall->Context = (PVOID)0xDEADBEEF;
+
+    return (Status);
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/transprt.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/transprt.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/transprt.c	(revision 31634)
@@ -0,0 +1,51 @@
+/*++
+
+ Copyright (c) 1989 - 1999 Microsoft Corporation
+
+ Module Name:
+
+ transport.c
+
+ Abstract:
+
+ This module implements all transport related functions in the SMB connection engine
+
+ --*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+NTSTATUS VBoxMRxInitializeTransport ()
+/*++
+
+ Routine Description:
+
+ This routine initializes the transport related data structures
+
+ Returns:
+
+ STATUS_SUCCESS if the transport data structures was successfully initialized
+
+ Notes:
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxInitializeTransport: Called.\n"));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxUninitializeTransport ()
+/*++
+
+ Routine Description:
+
+ This routine uninitializes the transport related data structures
+
+ Notes:
+
+ --*/
+{
+    Log(("VBOXSF: VBoxMRxUninitializeTransport: Called.\n"));
+    return STATUS_SUCCESS;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vboxsf.ini
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vboxsf.ini	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vboxsf.ini	(revision 31634)
@@ -0,0 +1,16 @@
+\registry\machine\system\currentcontrolset\services\VBoxSF
+    Description = VBoxSF
+    DisplayName = VBoxSF
+    ErrorControl = REG_DWORD 0x00000001
+    Group = Network
+    ImagePath = System32\DRIVERS\VBoxSF.sys
+    LastLoadStatus = REG_DWORD 0
+    Start = REG_DWORD 0x00000001
+    Type = REG_DWORD 0x00000002
+
+\registry\machine\system\currentcontrolset\services\VBoxSF\NetworkProvider
+    DeviceName = \Device\VBoxMiniRdr
+    Name = VirtualBox Shared Folders
+    ProviderPath = System32\VBoxMRXNP.dll
+
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhdrs.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhdrs.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhdrs.h	(revision 31634)
@@ -0,0 +1,70 @@
+/** @file
+ *
+ * VirtualBox Windows Guest Shared Folders
+ *
+ * File System Driver main header
+ *
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#ifndef __VBOXHDRS__H
+#define __VBOXHDRS__H
+
+#include "VBoxGuestR0LibSharedFolders.h"
+
+/*
+ * UNICODE name of the virtual drive device and FSD device.
+ */
+#define VBOXSF_DEVICE_NAME_U L"VBoxSharedFolders"
+
+/*
+ * The path in the ob namespace for a virtual drive device.
+ * ? is replaced with a drive letter.
+ */
+#define VBOXSF_DEVICE_NAME_TEMPLATE_U L"\\Device\\" VBOXSF_DEVICE_NAME_U L"?"
+
+#if 0 /** @todo r=bird: defined in two .c files but with different parameter lists. dunno who uses them.
+       * Vitali / Sander, please fix when you got time. */
+NTSTATUS vbsfFsdStartPollerThread (void);
+void vbsfFsdStopPollerThread (void);
+#endif
+
+NTSTATUS
+FatMountVolume (
+        IN struct _VOLUME_DEVICE_OBJECT *pVdo
+);
+
+typedef struct _VBSFDIRENT
+{
+    ULONG64 FileSize;
+    ULONG64 AllocationSize;
+
+    ULONG64 LastAccessTime;
+    ULONG64 CreationTime;
+    ULONG64 LastWriteTime;
+
+    UCHAR Attributes;
+
+#if 0
+    FAT8DOT3 FileName; //  offset =  0
+    UCHAR Attributes; //  offset = 11
+    UCHAR NtByte; //  offset = 12
+    UCHAR CreationMSec; //  offset = 13
+    FAT_TIME_STAMP CreationTime; //  offset = 14
+    FAT_DATE LastAccessDate; //  offset = 18
+    union
+    {
+        USHORT ExtendedAttributes; //  offset = 20
+        USHORT FirstClusterOfFileHi; //  offset = 20
+    };
+    FAT_TIME_STAMP LastWriteTime; //  offset = 22
+    USHORT FirstClusterOfFile; //  offset = 26
+    ULONG32 FileSize; //  offset = 28
+#endif
+} VBSFDIRENT; //  sizeof = 32
+typedef VBSFDIRENT *PVBSFDIRENT;
+
+#endif /* __VBOXHDRS__H */
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.c	(revision 31634)
@@ -0,0 +1,343 @@
+/** @file
+ *
+ * VirtualBox Windows Guest Shared Folders
+ *
+ * File System Driver system helpers
+ *
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#include <ntifs.h>
+#include <ntdddisk.h>
+
+#include "vbsfhdrs.h"
+#include "vbsfhlp.h"
+
+#ifdef DEBUG
+static int s_iAllocRefCount = 0;
+#endif
+
+void vbsfHlpSleep (ULONG ulMillies)
+{
+    KEVENT event;
+    LARGE_INTEGER dueTime;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+    dueTime.QuadPart = -10000 * (int)ulMillies;
+
+    KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &dueTime);
+}
+
+/**
+ * Convert VBox IRT file attributes to NT file attributes
+ *
+ * @returns NT file attributes
+ * @param   fMode       IRT file attributes
+ *
+ */
+uint32_t VBoxToNTFileAttributes (uint32_t fMode)
+{
+    uint32_t FileAttributes = 0;
+
+    if (fMode & RTFS_DOS_READONLY)
+        FileAttributes |= FILE_ATTRIBUTE_READONLY;
+    if (fMode & RTFS_DOS_HIDDEN)
+        FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+    if (fMode & RTFS_DOS_SYSTEM)
+        FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
+    if (fMode & RTFS_DOS_DIRECTORY)
+        FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+    if (fMode & RTFS_DOS_ARCHIVED)
+        FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
+    if (fMode & RTFS_DOS_NT_TEMPORARY)
+        FileAttributes |= FILE_ATTRIBUTE_TEMPORARY;
+    if (fMode & RTFS_DOS_NT_SPARSE_FILE)
+        FileAttributes |= FILE_ATTRIBUTE_SPARSE_FILE;
+    if (fMode & RTFS_DOS_NT_REPARSE_POINT)
+        FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+    if (fMode & RTFS_DOS_NT_COMPRESSED)
+        FileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
+    //    if (fMode & RTFS_DOS_NT_OFFLINE)
+    if (fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED)
+        FileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+    if (fMode & RTFS_DOS_NT_ENCRYPTED)
+        FileAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
+    if (fMode & RTFS_DOS_NT_NORMAL)
+    {
+        FileAttributes |= FILE_ATTRIBUTE_NORMAL;
+    }
+    return FileAttributes;
+}
+
+/**
+ * Convert VBox IRT file attributes to NT file attributes
+ *
+ * @returns NT file attributes
+ * @param   fMode       IRT file attributes
+ *
+ */
+uint32_t NTToVBoxFileAttributes (uint32_t fMode)
+{
+    uint32_t FileAttributes = 0;
+
+    if (fMode & FILE_ATTRIBUTE_READONLY)
+        FileAttributes |= RTFS_DOS_READONLY;
+    if (fMode & FILE_ATTRIBUTE_HIDDEN)
+        FileAttributes |= RTFS_DOS_HIDDEN;
+    if (fMode & FILE_ATTRIBUTE_SYSTEM)
+        FileAttributes |= RTFS_DOS_SYSTEM;
+    if (fMode & FILE_ATTRIBUTE_DIRECTORY)
+        FileAttributes |= RTFS_DOS_DIRECTORY;
+    if (fMode & FILE_ATTRIBUTE_ARCHIVE)
+        FileAttributes |= RTFS_DOS_ARCHIVED;
+    if (fMode & FILE_ATTRIBUTE_TEMPORARY)
+        FileAttributes |= RTFS_DOS_NT_TEMPORARY;
+    if (fMode & FILE_ATTRIBUTE_SPARSE_FILE)
+        FileAttributes |= RTFS_DOS_NT_SPARSE_FILE;
+    if (fMode & FILE_ATTRIBUTE_REPARSE_POINT)
+        FileAttributes |= RTFS_DOS_NT_REPARSE_POINT;
+    if (fMode & FILE_ATTRIBUTE_COMPRESSED)
+        FileAttributes |= RTFS_DOS_NT_COMPRESSED;
+    if (fMode & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
+        FileAttributes |= RTFS_DOS_NT_NOT_CONTENT_INDEXED;
+    if (fMode & FILE_ATTRIBUTE_ENCRYPTED)
+        FileAttributes |= RTFS_DOS_NT_ENCRYPTED;
+    if (fMode & FILE_ATTRIBUTE_NORMAL)
+    {
+        FileAttributes |= RTFS_DOS_NT_NORMAL;
+    }
+    return FileAttributes;
+}
+
+NTSTATUS vbsfHlpCreateDriveLetter (WCHAR Letter, UNICODE_STRING *pDeviceName)
+{
+    UNICODE_STRING driveName;
+    RtlInitUnicodeString(&driveName,L"\\??\\_:" );
+
+    /* Replace '_' with actual drive letter */
+    driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
+
+    return IoCreateSymbolicLink (&driveName, pDeviceName);
+}
+
+NTSTATUS vbsfHlpDeleteDriveLetter (WCHAR Letter)
+{
+    UNICODE_STRING driveName;
+    RtlInitUnicodeString(&driveName,L"\\??\\_:" );
+
+    /* Replace '_' with actual drive letter */
+    driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
+
+    return IoDeleteSymbolicLink (&driveName);
+}
+
+    /**
+     * Convert VBox error code to NT status code
+     *
+     * @returns NT status code
+     * @param   vboxRC          VBox error code
+     *
+     */
+NTSTATUS VBoxErrorToNTStatus (int vboxRC)
+{
+    NTSTATUS Status;
+
+    switch (vboxRC)
+    {
+    case VINF_SUCCESS:
+        Status = STATUS_SUCCESS;
+        break;
+
+    case VERR_ACCESS_DENIED:
+        Status = STATUS_ACCESS_DENIED;
+        break;
+
+    case VERR_NO_MORE_FILES:
+        Status = STATUS_NO_MORE_FILES;
+        break;
+
+    case VERR_PATH_NOT_FOUND:
+        Status = STATUS_OBJECT_PATH_NOT_FOUND;
+        break;
+
+    case VERR_FILE_NOT_FOUND:
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+        break;
+
+    case VERR_DIR_NOT_EMPTY:
+        Status = STATUS_DIRECTORY_NOT_EMPTY;
+        break;
+
+    case VERR_SHARING_VIOLATION:
+        Status = STATUS_SHARING_VIOLATION;
+        break;
+
+    case VERR_FILE_LOCK_VIOLATION:
+        Status = STATUS_FILE_LOCK_CONFLICT;
+        break;
+
+    case VERR_FILE_LOCK_FAILED:
+        Status = STATUS_LOCK_NOT_GRANTED;
+        break;
+
+    case VINF_BUFFER_OVERFLOW:
+        Status = STATUS_BUFFER_OVERFLOW;
+        break;
+
+    case VERR_EOF:
+    case VINF_EOF:
+        Status = STATUS_END_OF_FILE;
+        break;
+
+    case VERR_READ_ERROR:
+    case VERR_WRITE_ERROR:
+    case VERR_FILE_IO_ERROR:
+        Status = STATUS_UNEXPECTED_IO_ERROR;
+        break;
+
+    case VERR_WRITE_PROTECT:
+        Status = STATUS_MEDIA_WRITE_PROTECTED;
+        break;
+
+    case VERR_ALREADY_EXISTS:
+        Status = STATUS_OBJECT_NAME_COLLISION;
+        break;
+
+    case VERR_NOT_A_DIRECTORY:
+        Status = STATUS_NOT_A_DIRECTORY;
+        break;
+
+    case VERR_SEEK:
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+
+    case VERR_INVALID_PARAMETER:
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+
+    case VERR_NOT_SUPPORTED:
+        Status = STATUS_NOT_SUPPORTED;
+        break;
+
+    default:
+        /* @todo error handling */
+        Status = STATUS_INVALID_PARAMETER;
+        AssertMsgFailed(("Unexpected vbox error %d\n", vboxRC));
+        break;
+    }
+    return Status;
+}
+
+PVOID vbsfAllocNonPagedMem (ULONG ulSize)
+{
+    PVOID pMemory = NULL;
+
+#ifdef DEBUG
+    s_iAllocRefCount = s_iAllocRefCount + 1;
+    Log(("vbsfAllocNonPagedMem: RefCnt after incrementing: %d\n", s_iAllocRefCount));
+#endif
+
+    Assert(ulSize > sizeof(void *));
+
+    /* Tag is reversed (a.k.a "SHFL") to display correctly in debuggers, so search for "SHFL" */
+    pMemory = ExAllocatePoolWithTag(NonPagedPool, ulSize, 'LFHS');
+
+    if (NULL != pMemory)
+    {
+        RtlZeroMemory(pMemory, ulSize);
+#ifdef DEBUG
+        Log(("vbsfAllocNonPagedMem: Allocated %d bytes of memory at %p.\n", ulSize, pMemory));
+#endif
+    }
+    else
+    {
+#ifdef DEBUG
+        Log(("vbsfAllocNonPagedMem: ERROR: Could not allocate %d bytes of memory!\n", ulSize));
+#endif
+    }
+
+    return pMemory;
+}
+
+void vbsfFreeNonPagedMem (PVOID lpMem)
+{
+#ifdef DEBUG
+    s_iAllocRefCount = s_iAllocRefCount - 1;
+    Log(("vbsfFreeNonPagedMem: RefCnt after decrementing: %d\n", s_iAllocRefCount));
+#endif
+
+    Assert(lpMem);
+
+    /* MSDN: The ExFreePoolWithTag routine issues a bug check if the specified value for Tag does not match the tag value passed
+     to the routine that originally allocated the memory block. Otherwise, the behavior of this routine is identical to ExFreePool. */
+    ExFreePoolWithTag(lpMem, 'LFHS');
+    lpMem = NULL;
+}
+
+winVersion_t vboxQueryWinVersion ()
+{
+    static winVersion_t winVersion = UNKNOWN_WINVERSION;
+    ULONG majorVersion;
+    ULONG minorVersion;
+    ULONG buildNumber;
+
+    if (winVersion != UNKNOWN_WINVERSION)
+        return winVersion;
+
+    PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL);
+
+    Log(("VBoxVideo::vboxQueryWinVersion: running on Windows NT version %d.%d, build %d\n", majorVersion, minorVersion, buildNumber));
+
+    if (majorVersion >= 5)
+    {
+        if (minorVersion >= 1)
+        {
+            winVersion = WINXP;
+        }
+        else
+        {
+            winVersion = WIN2K;
+        }
+    }
+    else if (majorVersion == 4)
+    {
+        winVersion = WINNT4;
+    }
+    else
+    {
+        Log(("VBoxVideo::vboxQueryWinVersion: NT4 required!\n"));
+    }
+    return winVersion;
+}
+
+#if 0 //def DEBUG
+/**
+ * Callback for RTLogFormatV which writes to the backdoor.
+ * See PFNLOGOUTPUT() for details.
+ */
+static DECLCALLBACK(size_t) rtLogBackdoorOutput(void *pv, const char *pachChars, size_t cbChars)
+{
+    RTLogWriteUser(pachChars, cbChars);
+    return cbChars;
+}
+
+int RTLogBackdoorPrintf1(const char *pszFormat, ...)
+{
+    va_list args;
+
+    LARGE_INTEGER time;
+
+    KeQueryTickCount(&time);
+
+    RTLogBackdoorPrintf("T=%RX64 ", time.QuadPart);
+    va_start(args, pszFormat);
+    RTLogFormatV(rtLogBackdoorOutput, NULL, pszFormat, args);
+    va_end(args);
+
+    return 0;
+}
+#endif
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/vbsfhlp.h	(revision 31634)
@@ -0,0 +1,61 @@
+/** @file
+ *
+ * VirtualBox Windows Guest Shared Folders
+ *
+ * File System Driver system helpers
+ *
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * Oracle Corporation confidential
+ * All rights reserved
+ */
+
+#ifndef __VBSFHLP__H
+#define __VBSFHLP__H
+
+#include <ntifs.h>
+#include <ntverp.h>
+
+// Windows version identifier
+typedef enum
+{
+    UNKNOWN_WINVERSION = 0, WINNT4 = 1, WIN2K = 2, WINXP = 3
+} winVersion_t;
+
+void vbsfHlpSleep (ULONG ulMillies);
+NTSTATUS vbsfHlpCreateDriveLetter (WCHAR Letter, UNICODE_STRING *pDeviceName);
+NTSTATUS vbsfHlpDeleteDriveLetter (WCHAR Letter);
+
+/**
+ * Convert VBox IRT file attributes to NT file attributes
+ *
+ * @returns NT file attributes
+ * @param   fMode       IRT file attributes
+ *
+ */
+uint32_t VBoxToNTFileAttributes (uint32_t fMode);
+
+/**
+ * Convert VBox IRT file attributes to NT file attributes
+ *
+ * @returns NT file attributes
+ * @param   fMode       IRT file attributes
+ *
+ */
+uint32_t NTToVBoxFileAttributes (uint32_t fMode);
+
+/**
+ * Convert VBox error code to NT status code
+ *
+ * @returns NT status code
+ * @param   vboxRC          VBox error code
+ *
+ */
+NTSTATUS VBoxErrorToNTStatus (int vboxRC);
+
+PVOID vbsfAllocNonPagedMem (ULONG ulSize);
+void vbsfFreeNonPagedMem (PVOID lpMem);
+
+winVersion_t vboxQueryWinVersion ();
+
+#endif /* __VBSFHLP__H */
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.c	(revision 31634)
@@ -0,0 +1,138 @@
+/*++
+
+Copyright (c) 1996-1998  Microsoft Corporation
+
+Module Name:
+
+    cldskwmi.c
+
+Abstract:
+
+    km wmi tracing code.
+
+    Will be shared between our drivers.
+
+
+Environment:
+
+    kernel mode only
+
+Notes:
+
+
+
+Comments:
+
+        This code is a quick hack to enable WMI tracing in cluster drivers.
+        It should eventually go away.
+
+        WmlTinySystemControl will be replaced with WmilibSystemControl from wmilib.sys .
+
+        WmlTrace or equivalent will be added to the kernel in addition to IoWMIWriteEvent(&TraceBuffer);
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+//#include <ntos.h>
+//#include <ntrtl.h>
+//#include <nturtl.h>
+
+
+// #include <wmistr.h>
+// #include <evntrace.h>
+
+// #include "wmlkm.h"
+
+BOOLEAN
+WmlpFindGuid(
+    __in PVOID GuidList,
+    __in ULONG GuidCount,
+    __in LPVOID Guid,
+    __out PULONG GuidIndex
+    )
+/*++
+
+Routine Description:
+
+    This routine will search the list of guids registered and return
+    the index for the one that was registered.
+
+Arguments:
+
+    GuidList is the list of guids to search
+
+    GuidCount is the count of guids in the list
+
+    Guid is the guid being searched for
+
+    *GuidIndex returns the index to the guid
+
+Return Value:
+
+    TRUE if guid is found else FALSE
+
+--*/
+{
+
+    return(FALSE);
+}
+
+
+NTSTATUS
+WmlTinySystemControl(
+    __inout PVOID WmiLibInfo,
+    __in PVOID DeviceObject,
+    __in PVOID Irp
+    )
+/*++
+
+Routine Description:
+
+    Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
+    all wmi requests received, forwarding them if they are not for this
+    driver or determining if the guid is valid and if so passing it to
+    the driver specific function for handing wmi requests.
+
+Arguments:
+
+    WmiLibInfo has the WMI information control block
+
+    DeviceObject - Supplies a pointer to the device object for this request.
+
+    Irp - Supplies the Irp making the request.
+
+Return Value:
+
+    status
+
+--*/
+
+{
+    return(STATUS_WMI_GUID_NOT_FOUND);
+}
+
+ULONG
+WmlTrace(
+    __in ULONG Type,
+    __in LPVOID TraceGuid,
+    __in ULONG64 LoggerHandle,
+    ... // Pairs: Address, Length
+    )
+{
+    return STATUS_SUCCESS;
+}
+
+
+ULONG
+WmlPrintf(
+    __in ULONG Type,
+    __in LPCGUID TraceGuid,
+    __in ULONG64 LoggerHandle,
+    __in PCWSTR FormatString,
+    ... // printf var args
+    )
+{
+    return STATUS_SUCCESS;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.h	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/wmlkm.h	(revision 31634)
@@ -0,0 +1,80 @@
+/*++
+
+Copyright (c) 1999  Microsoft Corporation
+
+Module Name:
+
+    wmlkm.h
+
+Abstract:
+
+    Kernel mode definitions for an easy wmi tracing.
+
+
+Comments:
+
+    Needs to be moved to wmilib\inc when DCR is approved
+
+--*/
+#ifndef WMLKM_H
+#define WMLKM_H 1
+
+#pragma warning(disable: 4201) // error C4201: nonstandard extension used : nameless struct/union
+#include <wmistr.h>
+#include <evntrace.h>
+
+#include "wmlmacro.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_TRACE_GUIDS_PER_CONTROL  3
+
+typedef struct _WML_CONTROL_GUID_REG {
+    GUID        Guid;
+    GUID        TraceGuids[MAX_TRACE_GUIDS_PER_CONTROL];
+    ULONG       EnableFlags;
+    ULONG       EnableLevel;
+    TRACEHANDLE LoggerHandle;
+} WML_CONTROL_GUID_REG, *PWML_CONTROL_GUID_REG;
+
+typedef struct _WML_TINY_INFO {
+    PWML_CONTROL_GUID_REG    ControlGuids;
+    ULONG                    GuidCount;
+    PDEVICE_OBJECT           LowerDeviceObject;
+    PUNICODE_STRING          DriverRegPath;
+} WML_TINY_INFO, *PWML_TINY_INFO;
+
+
+NTSTATUS
+WmlTinySystemControl(
+    IN OUT PWML_TINY_INFO WmiLibInfo,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+ULONG
+WmlTrace(
+    IN ULONG Type,
+    IN LPCGUID TraceGuid,
+    IN TRACEHANDLE LoggerHandle,
+    ... // Pairs: Address, Length
+    );
+
+ULONG
+WmlPrintf(
+    IN ULONG Type,
+    IN LPCGUID TraceGuid,
+    IN TRACEHANDLE LoggerHandle,
+    IN PCHAR FormatString,
+    ... // var args
+    );
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // WMLKM_H
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/write.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/write.c	(revision 31634)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/redirector/sys/write.c	(revision 31634)
@@ -0,0 +1,175 @@
+/*++
+
+Copyright (c) 1989 - 1999 Microsoft Corporation
+
+Module Name:
+
+    write.c
+
+Abstract:
+
+    This module implements the mini redirector call down routines pertaining
+    to write of file system objects.
+
+--*/
+
+#include "precomp.h"
+#include "rdbss_vbox.h"
+#pragma hdrstop
+
+
+static NTSTATUS
+VBoxMRxWriteInternal (
+      IN PRX_CONTEXT RxContext)
+
+/*++
+
+Routine Description:
+
+   This routine opens a file across the network.
+
+Arguments:
+
+    RxContext - the RDBSS context
+
+Return Value:
+
+    RXSTATUS - The return status for the operation
+
+--*/
+
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    PLOWIO_CONTEXT  LowIoContext  = &RxContext->LowIoContext;
+    PMDL            OriginalDataMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
+
+    PVOID           pbUserBuffer = VBoxRxLowIoGetBufferAddress(RxContext);
+    uint32_t        ByteCount = (LowIoContext->ParamsFor).ReadWrite.ByteCount;
+    RXVBO           ByteOffset = (LowIoContext->ParamsFor).ReadWrite.ByteOffset;
+    LONGLONG        FileSize = 0;
+    PMRX_NET_ROOT   pNetRoot = capFcb->pNetRoot;
+    VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
+    BOOLEAN         SynchronousIo = !BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION);
+#ifndef VBOX
+    PDEVICE_OBJECT  deviceObject;
+#endif
+    VBoxMRxGetDeviceExtension(RxContext, pDeviceExtension);
+    PMRX_VBOX_FOBX  pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    Log(("VBOXSF: VBoxMRxWrite: SynchronousIo = %d\n", SynchronousIo));
+    Log(("VBOXSF: VBoxMRxWrite: NetRoot is 0x%x Fcb is 0x%x\n", pNetRoot, capFcb));
+
+    Assert(  ( OriginalDataMdl != NULL
+               &&
+               (    RxMdlIsLocked(OriginalDataMdl)
+                 || RxMdlSourceIsNonPaged(OriginalDataMdl)
+               )
+             )
+           ||
+             (
+                OriginalDataMdl == NULL
+                &&
+                LowIoContext->ParamsFor.ReadWrite.ByteCount == 0
+             )
+          );
+
+    if (    OriginalDataMdl == NULL
+        ||  LowIoContext->ParamsFor.ReadWrite.ByteCount == 0)
+    {
+        AssertFailed();
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    //
+    //  Lengths that are not sector aligned will be rounded up to
+    //  the next sector boundary. The rounded up length should be
+    //  < AllocationSize.
+    //
+    VBoxRxGetFileSizeWithLock((PFCB)capFcb,&FileSize);
+
+    Log(("VBOXSF: VBoxMRxWrite: UserBuffer is 0x%x\n", pbUserBuffer ));
+    Log(("VBOXSF: VBoxMRxWrite: ByteCount is %d, ByteOffset is %d\n", ByteCount, ByteOffset ));
+
+    /* @todo async io !!!! */
+    SynchronousIo = TRUE;
+
+    if( SynchronousIo )
+    {
+        int vboxRC;
+        PMDL pMdlBuf = NULL;
+
+#ifdef VBOX_FAKE_IO_READ_WRITE
+        Status =  STATUS_SUCCESS;
+#else
+        vboxRC = vboxCallWrite(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
+        AssertRC(vboxRC);
+
+        Status = VBoxErrorToNTStatus(vboxRC);
+#endif
+        if (Status != STATUS_SUCCESS)
+            ByteCount = 0;  /* Nothing written */
+
+        Log(("VBOXSF: VBoxMRxWrite: This I/O is sync!\n"));
+
+        RxContext->InformationToReturn = ByteCount;
+
+        /* Never call RxLowIoCompletion here!! */
+    }
+    else {
+        Log(("VBOXSF: VBoxMRxWrite: This I/O is async!\n"));
+    }
+
+    Log(("VBOXSF: VBoxMRxWrite: Status = %x, Info = %x\n",RxContext->IoStatusBlock.Status,RxContext->IoStatusBlock.Information));
+
+#ifndef VBOX
+Exit:
+#endif
+    return(Status);
+}
+
+static VOID VBoxMRxWriteWorker (VOID *pv)
+{
+    PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
+
+    Log(("VBOXSF: VBoxMRxWriteWorker: calling the worker\n"));
+
+    RxContext->IoStatusBlock.Status = VBoxMRxWriteInternal (RxContext);
+
+    Log(("VBOXSF: VBoxMRxWriteWorker: Status %x\n", RxContext->IoStatusBlock.Status));
+
+    RxLowIoCompletion (RxContext);
+}
+
+
+#ifdef VBOX_ASYNC_RW
+NTSTATUS
+VBoxMRxWrite (
+      IN PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
+                                      VBoxMRxWriteWorker,
+                                      RxContext);
+
+    Log(("VBOXSF: VBoxMRxWrite: RxDispatchToWorkerThread: Status %x\n", Status));
+
+    if (Status == STATUS_SUCCESS)
+    {
+        Status = STATUS_PENDING;
+    }
+
+    return Status;
+}
+#else
+NTSTATUS
+VBoxMRxWrite (
+      IN PRX_CONTEXT RxContext)
+{
+    RxContext->IoStatusBlock.Status = VBoxMRxWriteInternal (RxContext);
+    return RxContext->IoStatusBlock.Status;
+}
+#endif /* !VBOX_ASYNC_RW */
