ReactOS  0.4.13-dev-544-gede3fdd
vddsup.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/vddsup.c
5  * PURPOSE: Virtual Device Drivers (VDD) Support
6  * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "ntvdm.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include "emulator.h"
17 #include "vddsup.h"
18 
19 #include "cpu/bop.h"
20 #include <isvbop.h>
21 
22 typedef VOID (WINAPI *VDD_PROC)(VOID);
23 
24 typedef struct _VDD_MODULE
25 {
29 
30 // WARNING: A structure with the same name exists in nt_vdd.h,
31 // however it is not declared because its inclusion was prevented
32 // with #define NO_NTVDD_COMPAT, see ntvdm.h
33 typedef struct _VDD_USER_HANDLERS
34 {
36 
43 
44 /* PRIVATE VARIABLES **********************************************************/
45 
46 // TODO: Maybe use a linked list.
47 // But the number of elements must be <= MAXUSHORT (MAXWORD)
48 #define MAX_VDD_MODULES 0xFF + 1
50 
51 // Valid handles of VDD DLLs start at 1 and finish at MAX_VDD_MODULES
52 #define ENTRY_TO_HANDLE(Entry) ((Entry) + 1)
53 #define HANDLE_TO_ENTRY(Handle) ((Handle) - 1)
54 #define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES)
55 
57 
58 /* PRIVATE FUNCTIONS **********************************************************/
59 
61 {
63  for (Entry = 0; Entry < ARRAYSIZE(VDDList); ++Entry)
64  {
65  if (VDDList[Entry].hDll == NULL) break;
66  }
67  return Entry;
68 }
69 
71 {
72  /* Get the Function Number and skip it */
73  BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
74  setIP(getIP() + 1);
75 
76  switch (FuncNum)
77  {
78  /* RegisterModule */
79  case 0:
80  {
81  BOOL Success = TRUE;
82  WORD RetVal = 0;
83  WORD Entry = 0;
84  LPCSTR DllName = NULL,
85  InitRoutineName = NULL,
86  DispatchRoutineName = NULL;
87  HMODULE hDll = NULL;
88  VDD_PROC InitRoutine = NULL,
89  DispatchRoutine = NULL;
90 
91  DPRINT("RegisterModule() called\n");
92 
93  /* Clear the Carry Flag (no error happened so far) */
94  setCF(0);
95 
96  /* Retrieve the next free entry in the table (used later on) */
98  if (Entry >= MAX_VDD_MODULES)
99  {
100  DPRINT1("Failed to create a new VDD module entry\n");
101  Success = FALSE;
102  RetVal = 4;
103  goto Quit;
104  }
105 
106  /* Retrieve the VDD name in DS:SI */
107  DllName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI());
108 
109  /* Retrieve the initialization routine API name in ES:DI (optional --> ES=DI=0) */
110  if (TO_LINEAR(getES(), getDI()) != 0)
111  InitRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getES(), getDI());
112 
113  /* Retrieve the dispatch routine API name in DS:BX */
114  DispatchRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getBX());
115 
116  DPRINT1("DllName = '%s' - InitRoutineName = '%s' - DispatchRoutineName = '%s'\n",
117  (DllName ? DllName : "n/a"),
118  (InitRoutineName ? InitRoutineName : "n/a"),
119  (DispatchRoutineName ? DispatchRoutineName : "n/a"));
120 
121  /* Load the VDD DLL */
122  hDll = LoadLibraryA(DllName);
123  if (hDll == NULL)
124  {
125  DWORD LastError = GetLastError();
126  Success = FALSE;
127 
128  if (LastError == ERROR_NOT_ENOUGH_MEMORY)
129  {
130  DPRINT1("Not enough memory to load DLL '%s'\n", DllName);
131  RetVal = 4;
132  goto Quit;
133  }
134  else
135  {
136  DPRINT1("Failed to load DLL '%s'; last error = %d\n", DllName, LastError);
137  RetVal = 1;
138  goto Quit;
139  }
140  }
141 
142  /* Load the initialization routine if needed */
143  if (InitRoutineName)
144  {
145  InitRoutine = (VDD_PROC)GetProcAddress(hDll, InitRoutineName);
146  if (InitRoutine == NULL)
147  {
148  DPRINT1("Failed to load the initialization routine '%s'\n", InitRoutineName);
149  Success = FALSE;
150  RetVal = 3;
151  goto Quit;
152  }
153  }
154 
155  /* Load the dispatch routine */
156  DispatchRoutine = (VDD_PROC)GetProcAddress(hDll, DispatchRoutineName);
157  if (DispatchRoutine == NULL)
158  {
159  DPRINT1("Failed to load the dispatch routine '%s'\n", DispatchRoutineName);
160  Success = FALSE;
161  RetVal = 2;
162  goto Quit;
163  }
164 
165  /* If we reached this point, that means everything is OK */
166 
167  /* Register the VDD DLL */
168  VDDList[Entry].hDll = hDll;
169  VDDList[Entry].DispatchRoutine = DispatchRoutine;
170 
171  /* Call the initialization routine if needed */
172  if (InitRoutine) InitRoutine();
173 
174  /* We succeeded. RetVal will contain a valid VDD DLL handle */
175  Success = TRUE;
176  RetVal = ENTRY_TO_HANDLE(Entry); // Convert the entry to a valid handle
177 
178 Quit:
179  if (!Success)
180  {
181  /* Unload the VDD DLL */
182  if (hDll) FreeLibrary(hDll);
183 
184  /* Set the Carry Flag to indicate that an error happened */
185  setCF(1);
186  }
187  // else
188  // {
189  // /* Clear the Carry Flag (success) */
190  // setCF(0);
191  // }
192  setAX(RetVal);
193  break;
194  }
195 
196  /* UnRegisterModule */
197  case 1:
198  {
199  WORD Handle = getAX();
200  WORD Entry = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry
201 
202  DPRINT("UnRegisterModule() called\n");
203 
204  /* Sanity checks */
205  if (!IS_VALID_HANDLE(Handle) || VDDList[Entry].hDll == NULL)
206  {
207  DPRINT1("Invalid VDD DLL Handle: %d\n", Entry);
208  /* Stop the VDM */
210  return;
211  }
212 
213  /* Unregister the VDD DLL */
214  FreeLibrary(VDDList[Entry].hDll);
215  VDDList[Entry].hDll = NULL;
217  break;
218  }
219 
220  /* DispatchCall */
221  case 2:
222  {
223  WORD Handle = getAX();
224  WORD Entry = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry
225 
226  DPRINT("DispatchCall() called\n");
227 
228  /* Sanity checks */
229  if (!IS_VALID_HANDLE(Handle) ||
230  VDDList[Entry].hDll == NULL ||
231  VDDList[Entry].DispatchRoutine == NULL)
232  {
233  DPRINT1("Invalid VDD DLL Handle: %d\n", Entry);
234  /* Stop the VDM */
236  return;
237  }
238 
239  /* Call the dispatch routine */
241  break;
242  }
243 
244  default:
245  {
246  DPRINT1("Unknown 3rd-party VDD BOP Function: 0x%02X\n", FuncNum);
247  setCF(1);
248  break;
249  }
250  }
251 }
252 
254 {
255 // FIXME: These strings should be localized.
256 #define ERROR_MEMORYVDD L"Insufficient memory to load installable Virtual Device Drivers."
257 #define ERROR_REGVDD L"Virtual Device Driver format in the registry is invalid."
258 #define ERROR_LOADVDD L"An installable Virtual Device Driver failed Dll initialization."
259 
260  BOOL Success = TRUE;
261  LONG Error = 0;
262  DWORD Type = 0;
263  DWORD BufSize = 0;
264 
265  HKEY hVDDKey;
266  LPCWSTR VDDKeyName = L"SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers";
267  LPWSTR VDDValueName = L"VDD";
268  LPWSTR VDDList = NULL;
269 
270  HANDLE hVDD;
271 
272  /* Try to open the VDD registry key */
274  VDDKeyName,
275  0,
277  &hVDDKey);
279  {
280  /* If the key just doesn't exist, don't do anything else */
281  return TRUE;
282  }
283  else if (Error != ERROR_SUCCESS)
284  {
285  /* The key exists but there was an access error: display an error and quit */
287  return FALSE;
288  }
289 
290  /*
291  * Retrieve the size of the VDD registry value
292  * and check that it's of REG_MULTI_SZ type.
293  */
294  Error = RegQueryValueExW(hVDDKey,
295  VDDValueName,
296  NULL,
297  &Type,
298  NULL,
299  &BufSize);
301  {
302  /* If the value just doesn't exist, don't do anything else */
303  Success = TRUE;
304  goto Quit;
305  }
306  else if (Error != ERROR_SUCCESS || Type != REG_MULTI_SZ)
307  {
308  /*
309  * The value exists but there was an access error or
310  * is of the wrong type: display an error and quit.
311  */
313  Success = FALSE;
314  goto Quit;
315  }
316 
317  /* Allocate the buffer */
318  BufSize = (BufSize < 2*sizeof(WCHAR) ? 2*sizeof(WCHAR) : BufSize);
319  VDDList = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, BufSize);
320  if (VDDList == NULL)
321  {
323  Success = FALSE;
324  goto Quit;
325  }
326 
327  /* Retrieve the list of VDDs to load */
328  if (RegQueryValueExW(hVDDKey,
329  VDDValueName,
330  NULL,
331  NULL,
332  (LPBYTE)VDDList,
333  &BufSize) != ERROR_SUCCESS)
334  {
336  Success = FALSE;
337  goto Quit;
338  }
339 
340  /* Load the VDDs */
341  VDDValueName = VDDList;
342  while (*VDDList)
343  {
344  DPRINT1("Loading VDD '%S'...", VDDList);
345  hVDD = LoadLibraryW(VDDList);
346  if (hVDD == NULL)
347  {
348  DbgPrint("Failed\n");
350  }
351  else
352  {
353  DbgPrint("Succeeded\n");
354  }
355  /* Go to next string */
356  VDDList += wcslen(VDDList) + 1;
357  }
358  VDDList = VDDValueName;
359 
360 Quit:
361  if (VDDList) RtlFreeHeap(RtlGetProcessHeap(), 0, VDDList);
362  RegCloseKey(hVDDKey);
363  return Success;
364 }
365 
366 /* PUBLIC FUNCTIONS ***********************************************************/
367 
368 /*
369  * NOTE: This function can be called multiple times by the same VDD, if
370  * it wants to install different hooks for a same action. The most recent
371  * registered hooks are called first.
372  */
373 BOOL
374 WINAPI
376  IN PFNVDD_UCREATE Ucr_Handler,
377  IN PFNVDD_UTERMINATE Uterm_Handler,
378  IN PFNVDD_UBLOCK Ublock_Handler,
379  IN PFNVDD_URESUME Uresume_Handler)
380 {
381  PVDD_USER_HANDLERS UserHook;
382 
383  /* Check validity of the VDD handle */
384  if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE)
385  {
387  return FALSE;
388  }
389 
390  // NOTE: If we want that a VDD can install hooks only once, it's here
391  // that we need to check whether a hook entry is already registered.
392 
393  /* Create and initialize a new hook entry... */
394  UserHook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*UserHook));
395  if (UserHook == NULL)
396  {
398  return FALSE;
399  }
400 
401  UserHook->hVdd = hVdd;
402  UserHook->Ucr_Handler = Ucr_Handler;
403  UserHook->Uterm_Handler = Uterm_Handler;
404  UserHook->Ublock_Handler = Ublock_Handler;
405  UserHook->Uresume_Handler = Uresume_Handler;
406 
407  /* ... and add it at the top of the list of hooks */
408  InsertHeadList(&VddUserHooksList, &UserHook->Entry);
409 
410  return TRUE;
411 }
412 
413 /*
414  * NOTE: This function uninstalls the latest installed hooks for a given VDD.
415  * It can be called multiple times by the same VDD to uninstall many hooks
416  * installed by multiple invocations of VDDInstallUserHook.
417  */
418 BOOL
419 WINAPI
421 {
422  PLIST_ENTRY Pointer;
423  PVDD_USER_HANDLERS UserHook;
424 
425  /* Check validity of the VDD handle */
426  if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE)
427  {
429  return FALSE;
430  }
431 
432  /* Uninstall the latest installed hooks */
433  for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink)
434  {
435  UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry);
436  if (UserHook->hVdd == hVdd)
437  {
438  RemoveEntryList(&UserHook->Entry);
439  RtlFreeHeap(RtlGetProcessHeap(), 0, UserHook);
440  return TRUE;
441  }
442  }
443 
445  return FALSE;
446 }
447 
448 /*
449  * Internal functions for calling the VDD user hooks.
450  * Their names come directly from the Windows 2kX DDK.
451  */
452 
454 {
455  PLIST_ENTRY Pointer;
456  PVDD_USER_HANDLERS UserHook;
457 
458  /* Call the hooks starting from the most recent ones */
459  for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink)
460  {
461  UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry);
462  if (UserHook->Ucr_Handler) UserHook->Ucr_Handler(DosPDB);
463  }
464 }
465 
467 {
468  PLIST_ENTRY Pointer;
469  PVDD_USER_HANDLERS UserHook;
470 
471  /* Call the hooks starting from the most recent ones */
472  for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink)
473  {
474  UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry);
475  if (UserHook->Uterm_Handler) UserHook->Uterm_Handler(DosPDB);
476  }
477 }
478 
480 {
481  PLIST_ENTRY Pointer;
482  PVDD_USER_HANDLERS UserHook;
483 
484  /* Call the hooks starting from the most recent ones */
485  for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink)
486  {
487  UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry);
488  if (UserHook->Ublock_Handler) UserHook->Ublock_Handler();
489  }
490 }
491 
493 {
494  PLIST_ENTRY Pointer;
495  PVDD_USER_HANDLERS UserHook;
496 
497  /* Call the hooks starting from the most recent ones */
498  for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink)
499  {
500  UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry);
501  if (UserHook->Uresume_Handler) UserHook->Uresume_Handler();
502  }
503 }
504 
505 
506 
508 {
509  /* Register the 3rd-party VDD BOP Handler */
511 
512  /* Load the installable VDDs from the registry */
514 }
515 
516 /* EOF */
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define IN
Definition: typedefs.h:38
VOID WINAPI setIP(USHORT)
Definition: registers.c:471
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
#define TRUE
Definition: types.h:120
LIST_ENTRY Entry
Definition: vddsup.c:35
BOOL WINAPI VDDInstallUserHook(IN HANDLE hVdd, IN PFNVDD_UCREATE Ucr_Handler, IN PFNVDD_UTERMINATE Uterm_Handler, IN PFNVDD_UBLOCK Ublock_Handler, IN PFNVDD_URESUME Uresume_Handler)
Definition: vddsup.c:375
Type
Definition: Type.h:6
#define ERROR_SUCCESS
Definition: deptool.c:10
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
static LIST_ENTRY VddUserHooksList
Definition: vddsup.c:56
struct _Entry Entry
Definition: kefuncs.h:640
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define DbgPrint
Definition: loader.c:25
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
Definition: bop.c:29
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define ERROR_LOADVDD
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define BOP_3RDPARTY
Definition: isvbop.h:30
VDD_PROC DispatchRoutine
Definition: vddsup.c:27
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
static USHORT GetNextFreeVDDEntry(VOID)
Definition: vddsup.c:60
#define ENTRY_TO_HANDLE(Entry)
Definition: vddsup.c:52
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
static BOOL LoadInstallableVDD(VOID)
Definition: vddsup.c:253
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
unsigned int BOOL
Definition: ntddk_ex.h:94
PFNVDD_URESUME Uresume_Handler
Definition: vddsup.c:41
long LONG
Definition: pedump.c:60
VOID VDDCreateUserHook(USHORT DosPDB)
Definition: vddsup.c:453
#define REG_MULTI_SZ
Definition: nt_native.h:1501
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
#define LoadLibraryW(x)
Definition: compat.h:404
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
BOOL WINAPI VDDDeInstallUserHook(IN HANDLE hVdd)
Definition: vddsup.c:420
#define BufSize
Definition: FsRtlTunnel.c:28
const char * LPCSTR
Definition: xmlstorage.h:183
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID VDDSupInitialize(VOID)
Definition: vddsup.c:507
VOID(WINAPI * PFNVDD_UBLOCK)(VOID)
Definition: nt_vdd.h:51
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
#define FreeLibrary(x)
Definition: compat.h:405
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
USHORT WINAPI getES(VOID)
Definition: registers.c:522
USHORT WINAPI getIP(VOID)
Definition: registers.c:464
#define WINAPI
Definition: msvc.h:8
struct _VDD_USER_HANDLERS VDD_USER_HANDLERS
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL Error
Definition: chkdsk.c:66
#define SetLastError(x)
Definition: compat.h:409
PFNVDD_UCREATE Ucr_Handler
Definition: vddsup.c:38
#define ERROR_REGVDD
#define TO_LINEAR(seg, off)
Definition: emulator.h:22
struct _VDD_MODULE * PVDD_MODULE
static const WCHAR L[]
Definition: oid.c:1250
#define ERROR_MEMORYVDD
VOID(WINAPI * PFNVDD_URESUME)(VOID)
Definition: nt_vdd.h:54
#define VOID
Definition: acefi.h:82
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
unsigned char BYTE
Definition: mem.h:68
Definition: typedefs.h:117
VOID EmulatorTerminate(VOID)
Definition: emulator.c:503
uint16_t * LPWORD
Definition: typedefs.h:54
#define IS_VALID_HANDLE(Handle)
Definition: vddsup.c:54
unsigned short USHORT
Definition: pedump.c:61
struct _VDD_MODULE VDD_MODULE
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define MAX_VDD_MODULES
Definition: vddsup.c:48
PFNVDD_UTERMINATE Uterm_Handler
Definition: vddsup.c:39
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define DPRINT1
Definition: precomp.h:8
HMODULE hDll
Definition: vddsup.c:26
PFNVDD_UBLOCK Ublock_Handler
Definition: vddsup.c:40
struct _VDD_USER_HANDLERS * PVDD_USER_HANDLERS
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
VOID(WINAPI * PFNVDD_UCREATE)(USHORT DosPDB)
Definition: nt_vdd.h:45
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
#define GetProcAddress(x, y)
Definition: compat.h:410
#define HANDLE_TO_ENTRY(Handle)
Definition: vddsup.c:53
WCHAR * LPWSTR
Definition: xmlstorage.h:184
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
VOID VDDResumeUserHook(VOID)
Definition: vddsup.c:492
USHORT WINAPI getCS(VOID)
Definition: registers.c:480
BYTE * PBYTE
Definition: pedump.c:66
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
VOID VDDBlockUserHook(VOID)
Definition: vddsup.c:479
VOID(WINAPI * VDD_PROC)(VOID)
Definition: vddsup.c:22
base of all file and directory entries
Definition: entries.h:82
VOID(WINAPI * PFNVDD_UTERMINATE)(USHORT DosPDB)
Definition: nt_vdd.h:48
static VDD_MODULE VDDList[MAX_VDD_MODULES]
Definition: vddsup.c:49
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
HANDLE hVdd
Definition: testvdd.c:87
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
static VOID WINAPI ThirdPartyVDDBop(LPWORD Stack)
Definition: vddsup.c:70