ReactOS  0.4.13-dev-687-g023794c
testvdd.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Virtual DOS Machine
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Testing VDD for NTVDM
5  * COPYRIGHT: Copyright 2015-2018 Hermes Belusca-Maito
6  */
7 
8 /* INCLUDES *******************************************************************/
9 
10 #include <stdio.h>
11 
12 #include <windows.h>
13 #include <vddsvc.h>
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 
19 /* DEBUGGING HELPERS **********************************************************/
20 
21 // Enable this define to use DPRINT1 instead of MessageBox
22 // #define DBG_SILENT
23 
24 #ifdef DBG_SILENT
25 
26  #define VDD_DBG(...) \
27  do { \
28  DPRINT1(__VA_ARGS__); \
29  DbgPrint("\n"); \
30  } while(0)
31 
32 #else
33 
34  static VOID
36  {
37  #ifndef WIN2K_COMPLIANT
38  CHAR StaticBuffer[256];
39  LPSTR Buffer = StaticBuffer; // Use the static buffer by default.
40  #else
41  CHAR Buffer[2048]; // Large enough. If not, increase it by hand.
42  #endif
43  size_t MsgLen;
45 
47 
48  #ifndef WIN2K_COMPLIANT
49  /*
50  * Retrieve the message length and if it is too long, allocate
51  * an auxiliary buffer; otherwise use the static buffer.
52  */
53  MsgLen = _vscprintf(Format, Parameters) + 1; // NULL-terminated
54  if (MsgLen > ARRAYSIZE(StaticBuffer))
55  {
56  Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MsgLen * sizeof(WCHAR));
57  if (Buffer == NULL)
58  {
59  /* Allocation failed, use the static buffer and display a suitable error message */
60  Buffer = StaticBuffer;
61  Format = "DisplayMessage()\nOriginal message is too long and allocating an auxiliary buffer failed.";
62  MsgLen = strlen(Format);
63  }
64  }
65  #else
66  MsgLen = ARRAYSIZE(Buffer);
67  #endif
68 
69  /* Display the message */
71  MessageBoxA(NULL, Buffer, "Test VDD", MB_OK);
72 
73  #ifndef WIN2K_COMPLIANT
74  /* Free the buffer if needed */
75  if (Buffer != StaticBuffer) HeapFree(GetProcessHeap(), 0, Buffer);
76  #endif
77 
79  }
80 
81  #define VDD_DBG VddDbgMsg
82 #endif
83 
84 
85 /* GLOBALS ********************************************************************/
86 
88 
89 
90 /* VDD I/O PORTS TESTING ******************************************************/
91 
92 /*
93  * Port hooks (serial ports) -- Each port range is for testing different port handlers.
94  */
95 #define NUM_PORTS 4
96 
98 {
99  {0x3F8, 0x3FF},
100  {0x2F8, 0x2FF},
101  {0x3E8, 0x3EF},
102  {0x2E8, 0x2EF}
103 };
104 
105 VOID
106 WINAPI
108  OUT PUCHAR Data)
109 {
110  *Data = 0;
111  VDD_DBG("0x%08x (BYTE 0x%02x) <-- Port 0x%04x", Data, *Data, Port);
112 }
113 
114 VOID
115 WINAPI
117  IN UCHAR Data)
118 {
119  VDD_DBG("(BYTE 0x%02x) --> Port 0x%04x", Data, Port);
120 }
121 
122 VOID
123 WINAPI
125  OUT PUSHORT Data)
126 {
127  *Data = 0;
128  VDD_DBG("0x%08x (WORD 0x%04x) <-- Port 0x%04x", Data, *Data, Port);
129 }
130 
131 VOID
132 WINAPI
134  IN USHORT Data)
135 {
136  VDD_DBG("(WORD 0x%04x) --> Port 0x%04x", Data, Port);
137 }
138 
139 
140 VOID
141 WINAPI
143  OUT PUCHAR Data,
144  IN USHORT Count)
145 {
146  VDD_DBG("0x%08x (BYTESTR[%u]) <-- Port 0x%04x", Data, Count, Port);
147  while (Count--) *Data++ = 0;
148 }
149 
150 VOID
151 WINAPI
153  IN PUCHAR Data,
154  IN USHORT Count)
155 {
156  VDD_DBG("0x%08x (BYTESTR[%u]) --> Port 0x%04x", Data, Count, Port);
157 }
158 
159 VOID
160 WINAPI
162  OUT PUSHORT Data,
163  IN USHORT Count)
164 {
165  VDD_DBG("0x%08x (WORDSTR[%u]) <-- Port 0x%04x", Data, Count, Port);
166  while (Count--) *Data++ = 0;
167 }
168 
169 VOID
170 WINAPI
172  IN PUSHORT Data,
173  IN USHORT Count)
174 {
175  VDD_DBG("0x%08x (WORDSTR[%u]) --> Port 0x%04x", Data, Count, Port);
176 }
177 
178 
180 {
181  {PortInB, NULL , NULL , NULL , PortOutB, NULL , NULL , NULL },
185 };
186 
187 
188 /* VDD MEMORY HOOKS TESTING ***************************************************/
189 
190 /*
191  * Everything should be page-rounded.
192  */
193 
194 #ifndef PAGE_SIZE
195 #define PAGE_SIZE 0x1000
196 #endif
197 
198 #ifndef PAGE_ROUND_DOWN
199 #define PAGE_ROUND_DOWN(x) \
200  ( ((ULONG_PTR)(x)) & (~(PAGE_SIZE-1)) )
201 #endif
202 
203 #ifndef PAGE_ROUND_UP
204 #define PAGE_ROUND_UP(x) \
205  ( (((ULONG_PTR)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1)) )
206 #endif
207 
208 #define MEM_SEG_START 0x0000
209 #define MEM_SIZE PAGE_SIZE
210 
214 
215 VOID
216 WINAPI
217 MemoryHandler(IN PVOID FaultAddress,
218  IN ULONG RWMode)
219 {
221 
222  VDD_DBG("MemoryHandler(0x%08x, %s)", FaultAddress, (RWMode == 1) ? "Write" : "Read");
223  // VDDTerminateVDM();
224 
226  if (!Success) VDD_DBG("Unable to allocate memory");
227 }
228 
229 PVOID
231  IN ULONG StartOffset,
234 {
236  PVOID PhysMemStart = NULL;
237  USHORT Segment = StartSegment;
238  ULONG Offset = PAGE_ROUND_DOWN(StartOffset);
239 
240  *HookedSegment = 0x0000;
241  *HookedOffset = 0x0000;
242 
243  while (Segment <= 0xF000)
244  {
245  // PhysMemStart = GetVDMPointer(GetVDMAddress(Segment, Offset), MEM_SIZE, (getMSW() & MSW_PE));
246  PhysMemStart = VdmMapFlat(Segment, Offset, getMODE());
247 
248  /* Try to hook this memory area... */
250  if (!Success)
251  {
252  /* ... it didn't work. Free PhysMemStart, increase segment/offset and try again. */
253  DPRINT1("%04lX:%08lX hooking failed, continue...\n", Segment, Offset);
254 
255  VdmUnmapFlat(Segment, Offset, PhysMemStart, getMODE());
256  // FreeVDMPointer(GetVDMAddress(Segment, Offset), MEM_SIZE, PhysMemStart, (getMSW() & MSW_PE));
257  PhysMemStart = NULL;
258 
259  Offset += MEM_SIZE;
260  if (Offset + MEM_SIZE > 0xFFFF)
261  {
262  Segment += 0x1000;
263  Offset = 0x0000;
264  }
265  }
266  else
267  {
268  /* ... it worked. We'll free PhysMemStart later on. */
269  DPRINT1("%04lX:%08lX hooking succeeded!\n", Segment, Offset);
270  break;
271  }
272  }
273 
274  if (PhysMemStart)
275  {
276  VDD_DBG("We hooked at %04lX:%08lX (0x%p)", Segment, Offset, PhysMemStart);
278  *HookedOffset = Offset;
279  }
280  else
281  {
282  VDD_DBG("Hooking attempt failed!");
283  }
284 
285  return PhysMemStart;
286 }
287 
288 
289 /* VDD USER HOOKS TESTING *****************************************************/
290 
291 VOID
292 WINAPI
294 {
295  VDD_DBG("Create1Handler(0x%04x)", DosPDB);
296 }
297 
298 VOID
299 WINAPI
301 {
302  VDD_DBG("Create2Handler(0x%04x)", DosPDB);
303 }
304 
305 VOID
306 WINAPI
308 {
309  VDD_DBG("Terminate1Handler(0x%04x)", DosPDB);
310 }
311 
312 VOID
313 WINAPI
315 {
316  VDD_DBG("Terminate2Handler(0x%04x)", DosPDB);
317 }
318 
319 VOID
320 WINAPI
322 {
323  VDD_DBG("Block1Handler");
324 }
325 
326 VOID
327 WINAPI
329 {
330  VDD_DBG("Block2Handler");
331 }
332 
333 VOID
334 WINAPI
336 {
337  VDD_DBG("Resume1Handler");
338 }
339 
340 VOID
341 WINAPI
343 {
344  VDD_DBG("Resume2Handler");
345 }
346 
347 
348 /* VDD INITIALIZATION AND REGISTRATION ****************************************/
349 
350 VOID
351 WINAPI
353 {
354  VDD_DBG("TestVDDRegister");
355 
356  /* Clear the Carry Flag: success */
357  setCF(0);
358 }
359 
360 VOID
361 WINAPI
363 {
364  VDD_DBG("TestVDDUnRegister");
365 
366  /* Clear the Carry Flag: success */
367  setCF(0);
368 }
369 
370 VOID
371 WINAPI
373 {
374  VDD_DBG("TestVDDDispatch");
375 
376  /* Clear the Carry Flag: success */
377  setCF(0);
378 }
379 
380 BOOLEAN
382 {
384 
385  if (Register)
386  {
387  /* Hook some IO ports */
388  VDD_DBG("VDDInstallIOHook");
390  if (!Success)
391  {
392  VDD_DBG("Unable to hook IO ports, terminate...");
393  VDDTerminateVDM();
394  }
395 
396  /* Add a memory handler */
397  VDD_DBG("FindHookableMemory");
400  if (HookedAddress == NULL)
401  {
402  VDD_DBG("Unable to install memory handler, terminate...");
403  VDDTerminateVDM();
404  }
405 
406  /* Add some user hooks -- Test order of initialization and calling */
407  VDD_DBG("VDDInstallUserHook (1)");
413  if (!Success)
414  {
415  VDD_DBG("Unable to install user hooks (1)...");
416  }
417 
418  VDD_DBG("VDDInstallUserHook (2)");
424  if (!Success)
425  {
426  VDD_DBG("Unable to install user hooks (2)...");
427  }
428 
429  /* We have finished! */
430  VDD_DBG("Initialization finished!");
431  }
432  else
433  {
434  /* Remove the user hooks */
435  VDD_DBG("VDDDeInstallUserHook (1)");
437  if (!Success) VDD_DBG("Unable to uninstall user hooks (1)");
438 
439  // TODO: See which hooks are still existing there...
440 
441  VDD_DBG("VDDDeInstallUserHook (2)");
443  if (!Success) VDD_DBG("Unable to uninstall user hooks (2)");
444 
445  VDD_DBG("VDDDeInstallUserHook (3)");
447  if (!Success) VDD_DBG("EXPECTED ERROR: Unable to uninstall user hooks (3)");
448  else VDD_DBG("UNEXPECTED ERROR: Uninstalling user hooks (3) succeeded?!");
449 
450  /* Uninstall the memory handler */
452  if (!Success) VDD_DBG("Unable to free memory");
453 
454  VDD_DBG("VDDDeInstallMemoryHook");
456  if (!Success) VDD_DBG("Memory handler uninstall failed");
457 
458  VDD_DBG("VdmUnmapFlat");
460  // FreeVDMPointer(GetVDMAddress(HookedSegment, HookedOffset), MEM_SIZE, HookedAddress, (getMSW() & MSW_PE));
461  if (!Success) VDD_DBG("VdmUnmapFlat failed!");
462 
463  /* Deregister the hooked IO ports */
464  VDD_DBG("VDDDeInstallIOHook");
466 
467  VDD_DBG("Cleanup finished!");
468  Success = TRUE;
469  }
470 
471  return Success;
472 }
473 
474 BOOL
475 WINAPI // VDDInitialize
476 DllMain(IN HINSTANCE hInstanceDll,
477  IN DWORD dwReason,
478  IN LPVOID lpReserved)
479 {
481 
482  UNREFERENCED_PARAMETER(lpReserved);
483 
484  switch (dwReason)
485  {
486  case DLL_PROCESS_ATTACH:
487  {
488  VDD_DBG("DLL_PROCESS_ATTACH");
489 
490  /* Save our global VDD handle */
491  hVdd = hInstanceDll;
492 
493  /* Register VDD */
495  if (!Success) VDD_DBG("Failed to register the VDD...");
496 
497  break;
498  }
499 
500  case DLL_PROCESS_DETACH:
501  {
502  VDD_DBG("DLL_PROCESS_DETACH");
503 
504  /* Unregister VDD */
506  if (!Success) VDD_DBG("Failed to unregister the VDD...");
507 
508  break;
509  }
510 
511  case DLL_THREAD_ATTACH:
512  case DLL_THREAD_DETACH:
513  default:
514  break;
515  }
516 
517  return TRUE;
518 }
519 
520 /* EOF */
PVOID FindHookableMemory(IN USHORT StartSegment, IN ULONG StartOffset, OUT PUSHORT HookedSegment, OUT PULONG HookedOffset)
Definition: testvdd.c:230
CPPORT Port[4]
Definition: headless.c:34
#define MEM_SIZE
Definition: testvdd.c:209
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
VOID WINAPI PortOutsW(IN USHORT Port, IN PUSHORT Data, IN USHORT Count)
Definition: testvdd.c:171
#define NUM_PORTS
Definition: testvdd.c:95
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
BOOL WINAPI DllMain(IN HINSTANCE hInstanceDll, IN DWORD dwReason, IN LPVOID lpReserved)
Definition: testvdd.c:476
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define DLL_THREAD_ATTACH
Definition: compat.h:121
VOID WINAPI Resume1Handler(VOID)
Definition: testvdd.c:335
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
VOID WINAPI Create2Handler(USHORT DosPDB)
Definition: testvdd.c:300
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
VOID WINAPI PortOutB(IN USHORT Port, IN UCHAR Data)
Definition: testvdd.c:116
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
VOID WINAPI TestVDDDispatch(VOID)
Definition: testvdd.c:372
VOID WINAPI TestVDDRegister(VOID)
Definition: testvdd.c:352
char * LPSTR
Definition: xmlstorage.h:182
#define DLL_THREAD_DETACH
Definition: compat.h:122
VOID WINAPI Resume2Handler(VOID)
Definition: testvdd.c:342
int WINAPI MessageBoxA(_In_opt_ HWND, _In_opt_ LPCSTR, _In_opt_ LPCSTR, _In_ UINT)
VOID WINAPI PortInsW(IN USHORT Port, OUT PUSHORT Data, IN USHORT Count)
Definition: testvdd.c:161
DWORD dwReason
Definition: misc.cpp:154
ULONG HookedOffset
Definition: testvdd.c:212
#define va_end(ap)
Definition: acmsvcex.h:90
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
BOOL WINAPI VDDDeInstallMemoryHook(_In_ HANDLE hVdd, _In_ PVOID pStart, _In_ DWORD dwCount)
VOID WINAPI Create1Handler(USHORT DosPDB)
Definition: testvdd.c:293
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
VOID WINAPI PortInB(IN USHORT Port, OUT PUCHAR Data)
Definition: testvdd.c:107
#define MEM_SEG_START
Definition: testvdd.c:208
VDD_IO_PORTRANGE PortDefs[NUM_PORTS]
Definition: testvdd.c:97
char * va_list
Definition: acmsvcex.h:78
VOID WINAPI Block2Handler(VOID)
Definition: testvdd.c:328
Definition: bufpool.h:45
BOOL WINAPI VdmUnmapFlat(_In_ USHORT Segment, _In_ ULONG Offset, _In_ PVOID Buffer, _In_ VDM_MODE Mode)
VOID WINAPI PortOutsB(IN USHORT Port, IN PUCHAR Data, IN USHORT Count)
Definition: testvdd.c:152
const char * LPCSTR
Definition: xmlstorage.h:183
_Inout_ PVOID Segment
Definition: exfuncs.h:893
BOOL WINAPI VDDAllocMem(_In_ HANDLE hVdd, _In_ PVOID Address, _In_ ULONG Size)
#define DLL_PROCESS_DETACH
Definition: compat.h:119
VOID WINAPI Terminate1Handler(USHORT DosPDB)
Definition: testvdd.c:307
PVOID HookedAddress
Definition: testvdd.c:213
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
VOID WINAPI PortInW(IN USHORT Port, OUT PUSHORT Data)
Definition: testvdd.c:124
static VOID VddDbgMsg(LPCSTR Format,...)
Definition: testvdd.c:35
#define WINAPI
Definition: msvc.h:8
#define getMODE()
Definition: nt_vdd.h:228
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WINAPI VDDTerminateVDM(VOID)
Definition: emulator.c:677
USHORT HookedSegment
Definition: testvdd.c:211
VOID WINAPI Block1Handler(VOID)
Definition: testvdd.c:321
PVOID WINAPI VdmMapFlat(_In_ USHORT Segment, _In_ ULONG Offset, _In_ VDM_MODE Mode)
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOL WINAPI VDDInstallIOHook(_In_ HANDLE hVdd, _In_ WORD cPortRange, _In_ PVDD_IO_PORTRANGE pPortRange, _In_ PVDD_IO_HANDLERS IoHandlers)
#define VDD_DBG
Definition: testvdd.c:81
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:871
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)
BOOL WINAPI VDDInstallMemoryHook(_In_ HANDLE hVdd, _In_ PVOID pStart, _In_ DWORD dwCount, _In_ PVDD_MEMORY_HANDLER MemoryHandler)
BOOL WINAPI VDDDeInstallUserHook(_In_ HANDLE hVdd)
VOID WINAPI PortInsB(IN USHORT Port, OUT PUCHAR Data, IN USHORT Count)
Definition: testvdd.c:142
_Check_return_ _CRTIMP int __cdecl _vscprintf(_In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
#define PAGE_ROUND_DOWN(x)
Definition: testvdd.c:199
unsigned short USHORT
Definition: pedump.c:61
BOOLEAN RegisterVDD(BOOLEAN Register)
Definition: testvdd.c:381
unsigned int * PULONG
Definition: retypes.h:1
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define MB_OK
Definition: winuser.h:784
BOOL WINAPI VDDFreeMem(_In_ HANDLE hVdd, _In_ PVOID Address, _In_ ULONG Size)
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define _vsnprintf
Definition: xmlstorage.h:202
#define DPRINT1
Definition: precomp.h:8
VDD_IO_HANDLERS PortHandlers[NUM_PORTS]
Definition: testvdd.c:179
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
VOID WINAPI PortOutW(IN USHORT Port, IN USHORT Data)
Definition: testvdd.c:133
VOID WINAPI VDDDeInstallIOHook(_In_ HANDLE hVdd, _In_ WORD cPortRange, _In_ PVDD_IO_PORTRANGE pPortRange)
VOID WINAPI Terminate2Handler(USHORT DosPDB)
Definition: testvdd.c:314
VOID WINAPI MemoryHandler(IN PVOID FaultAddress, IN ULONG RWMode)
Definition: testvdd.c:217
VOID WINAPI TestVDDUnRegister(VOID)
Definition: testvdd.c:362
#define HeapFree(x, y, z)
Definition: compat.h:394
unsigned short * PUSHORT
Definition: retypes.h:2
HANDLE hVdd
Definition: testvdd.c:87