Author: hbelusca
Date: Tue Dec 24 13:33:51 2013
New Revision: 61370
URL: 
http://svn.reactos.org/svn/reactos?rev=61370&view=rev
Log:
[NTVDM]
Load VDDs registered in HKLM\SYSTEM\CurrentControlSet\Control\VirtualDeviceDrivers key,
value "VDD" (of type REG_MULTI_SZ).
I still don't call FreeLibrary to unload them at the end of NTVDM's lifetime
(otherwise we would have to store their handles in an array).
Modified:
    branches/ntvdm/subsystems/ntvdm/vddsup.c
Modified: branches/ntvdm/subsystems/ntvdm/vddsup.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/vddsup.c…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/vddsup.c    [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/vddsup.c    [iso-8859-1] Tue Dec 24 13:33:51 2013
@@ -16,6 +16,8 @@
 #include "bop.h"
 #include "registers.h"
+#include <isvbop.h>
+
 typedef VOID (WINAPI *VDD_PROC)(VOID);
 typedef struct _VDD_MODULE
@@ -24,13 +26,10 @@
     VDD_PROC DispatchRoutine;
 } VDD_MODULE, *PVDD_MODULE;
-/* BOP Identifiers */
-#define BOP_3RDPARTY    0x58    // 3rd-party VDD BOP
-
 /* PRIVATE VARIABLES **********************************************************/
 // TODO: Maybe use a linked list.
-// But the number of elements must be <= MAXUSHORT
+// But the number of elements must be <= MAXUSHORT (MAXWORD)
 #define MAX_VDD_MODULES 0xFF + 1
 VDD_MODULE VDDList[MAX_VDD_MODULES] = {{NULL}};
@@ -77,11 +76,21 @@
             /* Clear the Carry Flag (no error happened so far) */
             setCF(0);
+            /* Retrieve the next free entry in the table (used later on) */
+            Entry = GetNextFreeVDDEntry();
+            if (Entry >= MAX_VDD_MODULES)
+            {
+                DPRINT1("Failed to create a new VDD module entry\n");
+                Success = FALSE;
+                RetVal = 4;
+                goto Quit;
+            }
+
             /* Retrieve the VDD name in DS:SI */
             DllName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI());
             /* Retrieve the initialization routine API name in ES:DI (optional -->
ES=DI=0) */
-            if (getES() != 0 || getDI() != 0)
+            if (TO_LINEAR(getES(), getDI()) != 0)
                 InitRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getES(), getDI());
             /* Retrieve the dispatch routine API name in DS:BX */
@@ -139,14 +148,6 @@
             /* If we arrived there, that means everything is OK */
             /* Register the VDD DLL */
-            Entry = GetNextFreeVDDEntry();
-            if (Entry == MAX_VDD_MODULES)
-            {
-                DPRINT1("Failed to create a new VDD module entry\n");
-                Success = FALSE;
-                RetVal = 4;
-                goto Quit;
-            }
             VDDList[Entry].hDll = hDll;
             VDDList[Entry].DispatchRoutine = DispatchRoutine;
@@ -232,12 +233,110 @@
     }
 }
+BOOL LoadInstallableVDD(VOID)
+{
+#define ERROR_MEMORYVDD L"Insufficient memory to load installable Virtual Device
Drivers."
+#define ERROR_REGVDD    L"Virtual Device Driver format in the registry is
invalid."
+#define ERROR_LOADVDD   L"An installable Virtual Device Driver failed Dll
initialization."
+
+    BOOL  Success = TRUE;
+    LONG  Error   = 0;
+    DWORD Type    = 0;
+    DWORD BufSize = 0;
+
+    HKEY    hVDDKey;
+    LPCWSTR VDDKeyName   =
L"SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers";
+    LPWSTR  VDDValueName = L"VDD";
+    LPWSTR  VDDList      = NULL;
+
+    HANDLE hVDD;
+
+    /* Open the VDD registry key */
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                      VDDKeyName,
+                      0,
+                      KEY_QUERY_VALUE,
+                      &hVDDKey) != ERROR_SUCCESS)
+    {
+        DisplayMessage(ERROR_REGVDD);
+        return FALSE;
+    }
+
+    /*
+     * Retrieve the size of the VDD registry value
+     * and check that it's of REG_MULTI_SZ type.
+     */
+    Error = RegQueryValueExW(hVDDKey,
+                             VDDValueName,
+                             NULL,
+                             &Type,
+                             NULL,
+                             &BufSize);
+    if (Error != ERROR_SUCCESS || Type != REG_MULTI_SZ)
+    {
+        DisplayMessage(ERROR_REGVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Allocate the buffer */
+    BufSize = (BufSize < 2*sizeof(WCHAR) ? 2*sizeof(WCHAR) : BufSize);
+    VDDList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufSize);
+    if (VDDList == NULL)
+    {
+        DisplayMessage(ERROR_MEMORYVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Retrieve the list of VDDs to load */
+    if (RegQueryValueExW(hVDDKey,
+                         VDDValueName,
+                         NULL,
+                         NULL,
+                         (LPBYTE)VDDList,
+                         &BufSize) != ERROR_SUCCESS)
+    {
+        DisplayMessage(ERROR_REGVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Load the VDDs */
+    VDDValueName = VDDList;
+    while (*VDDList)
+    {
+        DPRINT1("Loading VDD '%S'...", VDDList);
+        hVDD = LoadLibraryW(VDDList);
+        if (hVDD == NULL)
+        {
+            DbgPrint("Failed\n");
+            DisplayMessage(ERROR_LOADVDD);
+        }
+        else
+        {
+            DbgPrint("Succeeded\n");
+        }
+        /* Go to next string */
+        VDDList += wcslen(VDDList) + 1;
+    }
+    VDDList = VDDValueName;
+
+Quit:
+    if (VDDList) HeapFree(GetProcessHeap(), 0, VDDList);
+    RegCloseKey(hVDDKey);
+    return Success;
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 VOID VDDSupInitialize(VOID)
 {
     /* Register the 3rd-party VDD BOP Handler */
     RegisterBop(BOP_3RDPARTY, ThirdPartyVDDBop);
+
+    /* Load the installable VDDs from the registry */
+    LoadInstallableVDD();
 }
 /* EOF */