2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/samples/testvdd/testvdd.c
5 * PURPOSE: Testing VDD for NTVDM
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
20 /* DEBUGGING HELPERS **********************************************************/
22 // Enable this define to use DPRINT1 instead of MessageBox
27 #define VDD_DBG(...) \
29 DPRINT1(__VA_ARGS__); \
36 VddDbgMsg(LPCSTR Format
, ...)
38 #ifndef WIN2K_COMPLIANT
39 CHAR StaticBuffer
[256];
40 LPSTR Buffer
= StaticBuffer
; // Use the static buffer by default.
42 CHAR Buffer
[2048]; // Large enough. If not, increase it by hand.
47 va_start(Parameters
, Format
);
49 #ifndef WIN2K_COMPLIANT
51 * Retrieve the message length and if it is too long, allocate
52 * an auxiliary buffer; otherwise use the static buffer.
54 MsgLen
= _vscprintf(Format
, Parameters
) + 1; // NULL-terminated
55 if (MsgLen
> ARRAYSIZE(StaticBuffer
))
57 Buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MsgLen
* sizeof(WCHAR
));
60 /* Allocation failed, use the static buffer and display a suitable error message */
61 Buffer
= StaticBuffer
;
62 Format
= "DisplayMessage()\nOriginal message is too long and allocating an auxiliary buffer failed.";
63 MsgLen
= strlen(Format
);
67 MsgLen
= ARRAYSIZE(Buffer
);
70 /* Display the message */
71 _vsnprintf(Buffer
, MsgLen
, Format
, Parameters
);
72 MessageBoxA(NULL
, Buffer
, "Test VDD", MB_OK
);
74 #ifndef WIN2K_COMPLIANT
75 /* Free the buffer if needed */
76 if (Buffer
!= StaticBuffer
) HeapFree(GetProcessHeap(), 0, Buffer
);
82 #define VDD_DBG VddDbgMsg
86 /* GLOBALS ********************************************************************/
91 /* VDD I/O PORTS TESTING ******************************************************/
94 * Port hooks (serial ports) -- Each port range is for testing different port handlers.
98 VDD_IO_PORTRANGE PortDefs
[NUM_PORTS
] =
108 PortInB(IN USHORT Port
,
112 VDD_DBG("0x%08x (BYTE 0x%02x) <-- Port 0x%04x", Data
, *Data
, Port
);
117 PortOutB(IN USHORT Port
,
120 VDD_DBG("(BYTE 0x%02x) --> Port 0x%04x", Data
, Port
);
125 PortInW(IN USHORT Port
,
129 VDD_DBG("0x%08x (WORD 0x%04x) <-- Port 0x%04x", Data
, *Data
, Port
);
134 PortOutW(IN USHORT Port
,
137 VDD_DBG("(WORD 0x%04x) --> Port 0x%04x", Data
, Port
);
143 PortInsB(IN USHORT Port
,
147 VDD_DBG("0x%08x (BYTESTR[%u]) <-- Port 0x%04x", Data
, Count
, Port
);
148 while (Count
--) *Data
++ = 0;
153 PortOutsB(IN USHORT Port
,
157 VDD_DBG("0x%08x (BYTESTR[%u]) --> Port 0x%04x", Data
, Count
, Port
);
162 PortInsW(IN USHORT Port
,
166 VDD_DBG("0x%08x (WORDSTR[%u]) <-- Port 0x%04x", Data
, Count
, Port
);
167 while (Count
--) *Data
++ = 0;
172 PortOutsW(IN USHORT Port
,
176 VDD_DBG("0x%08x (WORDSTR[%u]) --> Port 0x%04x", Data
, Count
, Port
);
180 VDD_IO_HANDLERS PortHandlers
[NUM_PORTS
] =
182 {PortInB
, NULL
, NULL
, NULL
, PortOutB
, NULL
, NULL
, NULL
},
183 {PortInB
, PortInW
, NULL
, NULL
, PortOutB
, PortOutW
, NULL
, NULL
},
184 {PortInB
, NULL
, PortInsB
, NULL
, PortOutB
, NULL
, PortOutsB
, NULL
},
185 {PortInB
, NULL
, NULL
, PortInsW
, PortOutB
, NULL
, NULL
, PortOutsW
},
189 /* VDD MEMORY HOOKS TESTING ***************************************************/
192 * Everything should be page-rounded.
196 #define PAGE_SIZE 0x1000
199 #ifndef PAGE_ROUND_DOWN
200 #define PAGE_ROUND_DOWN(x) \
201 ( ((ULONG_PTR)(x)) & (~(PAGE_SIZE-1)) )
204 #ifndef PAGE_ROUND_UP
205 #define PAGE_ROUND_UP(x) \
206 ( (((ULONG_PTR)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1)) )
209 #define MEM_SEG_START 0x0000
210 #define MEM_SIZE PAGE_SIZE
212 USHORT HookedSegment
= 0x0000;
213 ULONG HookedOffset
= 0x0000;
214 PVOID HookedAddress
= NULL
;
218 MemoryHandler(IN PVOID FaultAddress
,
221 BOOLEAN Success
= FALSE
;
223 VDD_DBG("MemoryHandler(0x%08x, %s)", FaultAddress
, (RWMode
== 1) ? "Write" : "Read");
224 // VDDTerminateVDM();
226 Success
= VDDAllocMem(hVdd
, HookedAddress
, MEM_SIZE
);
227 if (!Success
) VDD_DBG("Unable to allocate memory");
231 FindHookableMemory(IN USHORT StartSegment
,
232 IN ULONG StartOffset
,
233 OUT PUSHORT HookedSegment
,
234 OUT PULONG HookedOffset
)
237 PVOID PhysMemStart
= NULL
;
238 USHORT Segment
= StartSegment
;
239 ULONG Offset
= PAGE_ROUND_DOWN(StartOffset
);
241 *HookedSegment
= 0x0000;
242 *HookedOffset
= 0x0000;
244 while (Segment
<= 0xF000)
246 // PhysMemStart = GetVDMPointer(GetVDMAddress(Segment, Offset), MEM_SIZE, (getMSW() & MSW_PE));
247 PhysMemStart
= VdmMapFlat(Segment
, Offset
, getMODE());
249 /* Try to hook this memory area... */
250 Success
= VDDInstallMemoryHook(hVdd
, PhysMemStart
, MEM_SIZE
, MemoryHandler
);
253 /* ... it didn't work. Free PhysMemStart, increase segment/offset and try again. */
254 DPRINT1("%04lX:%08lX hooking failed, continue...\n", Segment
, Offset
);
256 VdmUnmapFlat(Segment
, Offset
, PhysMemStart
, getMODE());
257 // FreeVDMPointer(GetVDMAddress(Segment, Offset), MEM_SIZE, PhysMemStart, (getMSW() & MSW_PE));
261 if (Offset
+ MEM_SIZE
> 0xFFFF)
269 /* ... it worked. We'll free PhysMemStart later on. */
270 DPRINT1("%04lX:%08lX hooking succeeded!\n", Segment
, Offset
);
277 VDD_DBG("We hooked at %04lX:%08lX (0x%p)", Segment
, Offset
, PhysMemStart
);
278 *HookedSegment
= Segment
;
279 *HookedOffset
= Offset
;
283 VDD_DBG("Hooking attempt failed!");
290 /* VDD USER HOOKS TESTING *****************************************************/
294 Create1Handler(USHORT DosPDB
)
296 VDD_DBG("Create1Handler(0x%04x)", DosPDB
);
301 Create2Handler(USHORT DosPDB
)
303 VDD_DBG("Create2Handler(0x%04x)", DosPDB
);
308 Terminate1Handler(USHORT DosPDB
)
310 VDD_DBG("Terminate1Handler(0x%04x)", DosPDB
);
315 Terminate2Handler(USHORT DosPDB
)
317 VDD_DBG("Terminate2Handler(0x%04x)", DosPDB
);
324 VDD_DBG("Block1Handler");
331 VDD_DBG("Block2Handler");
338 VDD_DBG("Resume1Handler");
345 VDD_DBG("Resume2Handler");
349 /* VDD INITIALIZATION AND REGISTRATION ****************************************/
353 TestVDDRegister(VOID
)
355 VDD_DBG("TestVDDRegister");
357 /* Clear the Carry Flag: success */
363 TestVDDUnRegister(VOID
)
365 VDD_DBG("TestVDDUnRegister");
367 /* Clear the Carry Flag: success */
373 TestVDDDispatch(VOID
)
375 VDD_DBG("TestVDDDispatch");
377 /* Clear the Carry Flag: success */
382 RegisterVDD(BOOLEAN Register
)
384 BOOLEAN Success
= FALSE
;
388 /* Hook some IO ports */
389 VDD_DBG("VDDInstallIOHook");
390 Success
= VDDInstallIOHook(hVdd
, NUM_PORTS
, PortDefs
, PortHandlers
);
393 VDD_DBG("Unable to hook IO ports, terminate...");
397 /* Add a memory handler */
398 VDD_DBG("FindHookableMemory");
399 HookedAddress
= FindHookableMemory(MEM_SEG_START
, 0x0000,
400 &HookedSegment
, &HookedOffset
);
401 if (HookedAddress
== NULL
)
403 VDD_DBG("Unable to install memory handler, terminate...");
407 /* Add some user hooks -- Test order of initialization and calling */
408 VDD_DBG("VDDInstallUserHook (1)");
409 Success
= VDDInstallUserHook(hVdd
,
416 VDD_DBG("Unable to install user hooks (1)...");
419 VDD_DBG("VDDInstallUserHook (2)");
420 Success
= VDDInstallUserHook(hVdd
,
427 VDD_DBG("Unable to install user hooks (2)...");
430 /* We have finished! */
431 VDD_DBG("Initialization finished!");
435 /* Remove the user hooks */
436 VDD_DBG("VDDDeInstallUserHook (1)");
437 Success
= VDDDeInstallUserHook(hVdd
);
438 if (!Success
) VDD_DBG("Unable to uninstall user hooks (1)");
440 // TODO: See which hooks are still existing there...
442 VDD_DBG("VDDDeInstallUserHook (2)");
443 Success
= VDDDeInstallUserHook(hVdd
);
444 if (!Success
) VDD_DBG("Unable to uninstall user hooks (2)");
446 VDD_DBG("VDDDeInstallUserHook (3)");
447 Success
= VDDDeInstallUserHook(hVdd
);
448 if (!Success
) VDD_DBG("EXPECTED ERROR: Unable to uninstall user hooks (3)");
449 else VDD_DBG("UNEXPECTED ERROR: Uninstalling user hooks (3) succeeded?!");
451 /* Uninstall the memory handler */
452 Success
= VDDFreeMem(hVdd
, HookedAddress
, MEM_SIZE
);
453 if (!Success
) VDD_DBG("Unable to free memory");
455 VDD_DBG("VDDDeInstallMemoryHook");
456 Success
= VDDDeInstallMemoryHook(hVdd
, HookedAddress
, MEM_SIZE
);
457 if (!Success
) VDD_DBG("Memory handler uninstall failed");
459 VDD_DBG("VdmUnmapFlat");
460 Success
= VdmUnmapFlat(HookedSegment
, HookedOffset
, HookedAddress
, getMODE());
461 // FreeVDMPointer(GetVDMAddress(HookedSegment, HookedOffset), MEM_SIZE, HookedAddress, (getMSW() & MSW_PE));
462 if (!Success
) VDD_DBG("VdmUnmapFlat failed!");
464 /* Deregister the hooked IO ports */
465 VDD_DBG("VDDDeInstallIOHook");
466 VDDDeInstallIOHook(hVdd
, NUM_PORTS
, PortDefs
);
468 VDD_DBG("Cleanup finished!");
476 WINAPI
// VDDInitialize
477 DllMain(IN HINSTANCE hInstanceDll
,
479 IN LPVOID lpReserved
)
483 UNREFERENCED_PARAMETER(lpReserved
);
487 case DLL_PROCESS_ATTACH
:
489 VDD_DBG("DLL_PROCESS_ATTACH");
491 /* Save our global VDD handle */
495 Success
= RegisterVDD(TRUE
);
496 if (!Success
) VDD_DBG("Failed to register the VDD...");
501 case DLL_PROCESS_DETACH
:
503 VDD_DBG("DLL_PROCESS_DETACH");
506 Success
= RegisterVDD(FALSE
);
507 if (!Success
) VDD_DBG("Failed to unregister the VDD...");
512 case DLL_THREAD_ATTACH
:
513 case DLL_THREAD_DETACH
: