ReactOS 0.4.16-dev-109-gf4cb10f
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 {
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
105VOID
106WINAPI
109{
110 *Data = 0;
111 VDD_DBG("0x%08x (BYTE 0x%02x) <-- Port 0x%04x", Data, *Data, Port);
112}
113
114VOID
115WINAPI
117 IN UCHAR Data)
118{
119 VDD_DBG("(BYTE 0x%02x) --> Port 0x%04x", Data, Port);
120}
121
122VOID
123WINAPI
126{
127 *Data = 0;
128 VDD_DBG("0x%08x (WORD 0x%04x) <-- Port 0x%04x", Data, *Data, Port);
129}
130
131VOID
132WINAPI
134 IN USHORT Data)
135{
136 VDD_DBG("(WORD 0x%04x) --> Port 0x%04x", Data, Port);
137}
138
139
140VOID
141WINAPI
145{
146 VDD_DBG("0x%08x (BYTESTR[%u]) <-- Port 0x%04x", Data, Count, Port);
147 while (Count--) *Data++ = 0;
148}
149
150VOID
151WINAPI
153 IN PUCHAR Data,
155{
156 VDD_DBG("0x%08x (BYTESTR[%u]) --> Port 0x%04x", Data, Count, Port);
157}
158
159VOID
160WINAPI
164{
165 VDD_DBG("0x%08x (WORDSTR[%u]) <-- Port 0x%04x", Data, Count, Port);
166 while (Count--) *Data++ = 0;
167}
168
169VOID
170WINAPI
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
215VOID
216WINAPI
217MemoryHandler(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
229PVOID
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);
279 }
280 else
281 {
282 VDD_DBG("Hooking attempt failed!");
283 }
284
285 return PhysMemStart;
286}
287
288
289/* VDD USER HOOKS TESTING *****************************************************/
290
291VOID
292WINAPI
294{
295 VDD_DBG("Create1Handler(0x%04x)", DosPDB);
296}
297
298VOID
299WINAPI
301{
302 VDD_DBG("Create2Handler(0x%04x)", DosPDB);
303}
304
305VOID
306WINAPI
308{
309 VDD_DBG("Terminate1Handler(0x%04x)", DosPDB);
310}
311
312VOID
313WINAPI
315{
316 VDD_DBG("Terminate2Handler(0x%04x)", DosPDB);
317}
318
319VOID
320WINAPI
322{
323 VDD_DBG("Block1Handler");
324}
325
326VOID
327WINAPI
329{
330 VDD_DBG("Block2Handler");
331}
332
333VOID
334WINAPI
336{
337 VDD_DBG("Resume1Handler");
338}
339
340VOID
341WINAPI
343{
344 VDD_DBG("Resume2Handler");
345}
346
347
348/* VDD INITIALIZATION AND REGISTRATION ****************************************/
349
350VOID
351WINAPI
353{
354 VDD_DBG("TestVDDRegister");
355
356 /* Clear the Carry Flag: success */
357 setCF(0);
358}
359
360VOID
361WINAPI
363{
364 VDD_DBG("TestVDDUnRegister");
365
366 /* Clear the Carry Flag: success */
367 setCF(0);
368}
369
370VOID
371WINAPI
373{
374 VDD_DBG("TestVDDDispatch");
375
376 /* Clear the Carry Flag: success */
377 setCF(0);
378}
379
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...");
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...");
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
474BOOL
475WINAPI // VDDInitialize
476DllMain(IN HINSTANCE hInstanceDll,
478 IN LPVOID lpReserved)
479{
481
482 UNREFERENCED_PARAMETER(lpReserved);
483
484 switch (dwReason)
485 {
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
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
513 default:
514 break;
515 }
516
517 return TRUE;
518}
519
520/* EOF */
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define DPRINT1
Definition: precomp.h:8
DWORD dwReason
Definition: misc.cpp:141
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define GetProcessHeap()
Definition: compat.h:736
#define DLL_THREAD_DETACH
Definition: compat.h:133
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define DLL_THREAD_ATTACH
Definition: compat.h:132
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
CPPORT Port[4]
Definition: headless.c:35
_Check_return_ _CRTIMP int __cdecl _vscprintf(_In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
int Count
Definition: noreturn.cpp:7
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)
VOID WINAPI VDDTerminateVDM(VOID)
Definition: emulator.c:677
#define getMODE()
Definition: nt_vdd.h:228
BOOL WINAPI VDDInstallIOHook(_In_ HANDLE hVdd, _In_ WORD cPortRange, _In_ PVDD_IO_PORTRANGE pPortRange, _In_ PVDD_IO_HANDLERS IoHandlers)
BOOL WINAPI VDDDeInstallUserHook(_In_ HANDLE hVdd)
PVOID WINAPI VdmMapFlat(_In_ USHORT Segment, _In_ ULONG Offset, _In_ VDM_MODE Mode)
BOOL WINAPI VDDInstallMemoryHook(_In_ HANDLE hVdd, _In_ PVOID pStart, _In_ DWORD dwCount, _In_ PVDD_MEMORY_HANDLER MemoryHandler)
BOOL WINAPI VDDFreeMem(_In_ HANDLE hVdd, _In_ PVOID Address, _In_ ULONG Size)
VOID WINAPI VDDDeInstallIOHook(_In_ HANDLE hVdd, _In_ WORD cPortRange, _In_ PVDD_IO_PORTRANGE pPortRange)
BOOL WINAPI VDDDeInstallMemoryHook(_In_ HANDLE hVdd, _In_ PVOID pStart, _In_ DWORD dwCount)
BOOL WINAPI VdmUnmapFlat(_In_ USHORT Segment, _In_ ULONG Offset, _In_ PVOID Buffer, _In_ VDM_MODE Mode)
BOOL WINAPI VDDAllocMem(_In_ HANDLE hVdd, _In_ PVOID Address, _In_ ULONG Size)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned short USHORT
Definition: pedump.c:61
VOID WINAPI PortOutsB(IN USHORT Port, IN PUCHAR Data, IN USHORT Count)
Definition: testvdd.c:152
PVOID HookedAddress
Definition: testvdd.c:213
VOID WINAPI PortInB(IN USHORT Port, OUT PUCHAR Data)
Definition: testvdd.c:107
VOID WINAPI Block2Handler(VOID)
Definition: testvdd.c:328
VOID WINAPI PortOutW(IN USHORT Port, IN USHORT Data)
Definition: testvdd.c:133
#define VDD_DBG
Definition: testvdd.c:81
#define MEM_SIZE
Definition: testvdd.c:209
VOID WINAPI Terminate2Handler(USHORT DosPDB)
Definition: testvdd.c:314
VDD_IO_PORTRANGE PortDefs[NUM_PORTS]
Definition: testvdd.c:97
#define MEM_SEG_START
Definition: testvdd.c:208
VOID WINAPI MemoryHandler(IN PVOID FaultAddress, IN ULONG RWMode)
Definition: testvdd.c:217
VOID WINAPI Create1Handler(USHORT DosPDB)
Definition: testvdd.c:293
HANDLE hVdd
Definition: testvdd.c:87
VOID WINAPI Resume2Handler(VOID)
Definition: testvdd.c:342
VOID WINAPI PortOutB(IN USHORT Port, IN UCHAR Data)
Definition: testvdd.c:116
VOID WINAPI Resume1Handler(VOID)
Definition: testvdd.c:335
BOOLEAN RegisterVDD(BOOLEAN Register)
Definition: testvdd.c:381
ULONG HookedOffset
Definition: testvdd.c:212
VOID WINAPI Terminate1Handler(USHORT DosPDB)
Definition: testvdd.c:307
VOID WINAPI PortInsW(IN USHORT Port, OUT PUSHORT Data, IN USHORT Count)
Definition: testvdd.c:161
PVOID FindHookableMemory(IN USHORT StartSegment, IN ULONG StartOffset, OUT PUSHORT HookedSegment, OUT PULONG HookedOffset)
Definition: testvdd.c:230
static VOID VddDbgMsg(LPCSTR Format,...)
Definition: testvdd.c:35
VOID WINAPI Block1Handler(VOID)
Definition: testvdd.c:321
BOOL WINAPI DllMain(IN HINSTANCE hInstanceDll, IN DWORD dwReason, IN LPVOID lpReserved)
Definition: testvdd.c:476
VOID WINAPI PortInsB(IN USHORT Port, OUT PUCHAR Data, IN USHORT Count)
Definition: testvdd.c:142
VOID WINAPI TestVDDRegister(VOID)
Definition: testvdd.c:352
VDD_IO_HANDLERS PortHandlers[NUM_PORTS]
Definition: testvdd.c:179
VOID WINAPI TestVDDUnRegister(VOID)
Definition: testvdd.c:362
VOID WINAPI TestVDDDispatch(VOID)
Definition: testvdd.c:372
VOID WINAPI PortInW(IN USHORT Port, OUT PUSHORT Data)
Definition: testvdd.c:124
VOID WINAPI Create2Handler(USHORT DosPDB)
Definition: testvdd.c:300
#define NUM_PORTS
Definition: testvdd.c:95
VOID WINAPI PortOutsW(IN USHORT Port, IN PUSHORT Data, IN USHORT Count)
Definition: testvdd.c:171
#define PAGE_ROUND_DOWN(x)
Definition: testvdd.c:199
USHORT HookedSegment
Definition: testvdd.c:211
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
#define WINAPI
Definition: msvc.h:6
int WINAPI MessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
#define MB_OK
Definition: winuser.h:793
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define _vsnprintf
Definition: xmlstorage.h:202
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175