00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "psp.h"
00022
00023
00024
#if DBG
00025
#define ASSERTEQUAL(value1, value2, string) \
00026
if ((ULONG)value1 != (ULONG)value2) { \
00027
DbgPrint string ; \
00028
}
00029
00030
#define ASSERTEQUALBREAK(value1, value2, string)\
00031
if ((ULONG)value1 != (ULONG)value2) { \
00032
DbgPrint string ; \
00033
DbgBreakPoint(); \
00034
}
00035
#else
00036
00037 #define ASSERTEQUAL(value1, value2, string)
00038 #define ASSERTEQUALBREAK(value1, value2, string)
00039
00040
#endif
00041
00042
00043
00044
00045
00046
00047
NTSTATUS
00048
Psp386InstallIoHandler(
00049 IN
PEPROCESS Process,
00050 IN
PEMULATOR_ACCESS_ENTRY EmulatorAccessEntry,
00051 IN ULONG PortNumber,
00052 IN ULONG Context
00053 );
00054
00055
NTSTATUS
00056
Psp386RemoveIoHandler(
00057 IN
PEPROCESS Process,
00058 IN
PEMULATOR_ACCESS_ENTRY EmulatorAccessEntry,
00059 IN ULONG PortNumber
00060 );
00061
00062
NTSTATUS
00063
Psp386InsertVdmIoHandlerBlock(
00064 IN
PEPROCESS Process,
00065 IN PVDM_IO_HANDLER VdmIoHandler
00066 );
00067
00068 PVDM_IO_HANDLER
00069
Psp386GetVdmIoHandler(
00070 IN
PEPROCESS Process,
00071 IN ULONG PortNumber
00072 );
00073
00074
NTSTATUS
00075
Psp386CreateVdmIoListHead(
00076 IN
PEPROCESS Process
00077 );
00078
00079
00080
#ifdef ALLOC_PRAGMA
00081
#pragma alloc_text(INIT,PspVdmInitialize)
00082
#pragma alloc_text(PAGE,PspSetProcessIoHandlers)
00083
#pragma alloc_text(PAGE,Ps386GetVdmIoHandler)
00084
#pragma alloc_text(PAGE,Psp386RemoveIoHandler)
00085
#pragma alloc_text(PAGE,Psp386InstallIoHandler)
00086
#pragma alloc_text(PAGE,Psp386CreateVdmIoListHead)
00087
#pragma alloc_text(PAGE,Psp386InsertVdmIoHandlerBlock)
00088
#pragma alloc_text(PAGE,Psp386GetVdmIoHandler)
00089
#endif
00090
00091
00092
00093
00094
00095 ERESOURCE VdmIoListCreationResource;
00096
00097
00098
00099
00100
NTSTATUS
00101 PspSetProcessIoHandlers(
00102 IN
PEPROCESS Process,
00103 IN PVOID IoHandlerInformation,
00104 IN ULONG IoHandlerLength
00105 )
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 {
00129 PPROCESS_IO_PORT_HANDLER_INFORMATION IoHandlerInfo;
00130
NTSTATUS Status;
00131
PEMULATOR_ACCESS_ENTRY EmulatorAccess;
00132 ULONG EmulatorEntryNumber, NumberPorts;
00133 ULONG PortSize;
00134
PAGED_CODE();
00135
00136
00137
00138
00139
if (KeGetPreviousMode() !=
KernelMode) {
00140
return STATUS_INVALID_PARAMETER;
00141 }
00142
00143
00144
00145
if (IoHandlerLength < (ULONG)
sizeof( PROCESS_IO_PORT_HANDLER_INFORMATION)) {
00146
return STATUS_INFO_LENGTH_MISMATCH;
00147 }
00148 IoHandlerInfo = IoHandlerInformation;
00149
00150
00151
00152
00153
00154
00155
for (EmulatorEntryNumber = 0, EmulatorAccess =
00156 IoHandlerInfo->EmulatorAccessEntries;
00157 EmulatorEntryNumber < IoHandlerInfo->NumEntries;
00158 EmulatorEntryNumber++, EmulatorAccess++) {
00159
00160
switch (EmulatorAccess->AccessType) {
00161
case Uchar:
00162 PortSize = 1;
00163
break;
00164
case Ushort:
00165 PortSize = 2;
00166
break;
00167
case Ulong:
00168 PortSize = 4;
00169 }
00170
00171
for (NumberPorts = 0;
00172 NumberPorts < EmulatorAccess->NumConsecutivePorts;
00173 NumberPorts++) {
00174
if (IoHandlerInfo->Install) {
00175
Status =
Psp386InstallIoHandler(
00176 Process,
00177 EmulatorAccess,
00178 EmulatorAccess->BasePort + NumberPorts * PortSize,
00179 IoHandlerInfo->Context
00180 );
00181
if (
NT_SUCCESS(
Status)) {
00182 }
00183 }
else {
00184
Status =
Psp386RemoveIoHandler(
00185 Process,
00186 EmulatorAccess,
00187 EmulatorAccess->BasePort + NumberPorts * PortSize
00188 );
00189 }
00190
if (!
NT_SUCCESS(
Status)) {
00191
goto exitloop;
00192 }
00193 }
00194 }
00195
Status = STATUS_SUCCESS;
00196 exitloop:
00197
return Status;
00198
00199 }
00200
00201
00202
VOID
00203 PspDeleteVdmObjects(
00204 IN
PEPROCESS Process
00205 )
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 {
00221
00222 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00223 PVDM_IO_HANDLER p1, p2;
00224 PVDM_IO_LISTHEAD p3;
00225 PLIST_ENTRY Next;
00226 PDELAYINTIRQ pDelayIntIrq;
00227 KIRQL OldIrql;
00228
00229
if (pVdmObjects ==
NULL) {
00230
return;
00231 }
00232
00233
00234
00235
00236 p1 =
NULL;
00237 p3 = pVdmObjects->VdmIoListHead;
00238
00239
if (p3) {
00240 p2 = p3->VdmIoHandlerList;
00241
00242
while (p2) {
00243 p1 = p2;
00244 p2 = p1->Next;
00245
ExFreePool( p1 );
00246 }
00247
00248
ExDeleteResource(&p3->VdmIoResource);
00249
00250
ExFreePool( p3 );
00251 pVdmObjects->VdmIoListHead =
NULL;
00252 }
00253
00254
if (pVdmObjects->pIcaUserData) {
00255
ExFreePool(pVdmObjects->pIcaUserData);
00256 }
00257
00258
00259
00260
00261
KeAcquireSpinLock(&pVdmObjects->DelayIntSpinLock, &OldIrql);
00262
00263 Next = pVdmObjects->DelayIntListHead.Flink;
00264
while (Next != &pVdmObjects->DelayIntListHead) {
00265 pDelayIntIrq = CONTAINING_RECORD(Next, DELAYINTIRQ, DelayIntListEntry);
00266 Next = Next->Flink;
00267 RemoveEntryList(&pDelayIntIrq->DelayIntListEntry);
00268
ExFreePool(pDelayIntIrq);
00269 }
00270
00271
KeReleaseSpinLock(&pVdmObjects->DelayIntSpinLock, OldIrql);
00272
00273
ExFreePool(Process->VdmObjects);
00274 Process->VdmObjects =
NULL;
00275 }
00276
00277
00278
00279
NTSTATUS
00280 Psp386RemoveIoHandler(
00281 IN
PEPROCESS Process,
00282 IN
PEMULATOR_ACCESS_ENTRY EmulatorAccessEntry,
00283 IN ULONG PortNumber
00284 )
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 {
00303 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00304 PVDM_IO_HANDLER VdmIoHandler;
00305 KIRQL OldIrql;
00306
PAGED_CODE();
00307
00308
00309
00310
00311
00312
if (!pVdmObjects) {
00313
#if DBG
00314
DbgPrint(
"Psp386RemoveIoHandler: uninitialized VdmObjects\n");
00315
#endif
00316
return STATUS_UNSUCCESSFUL;
00317 }
00318
00319
00320
00321
00322
00323
00324
if (!pVdmObjects->VdmIoListHead) {
00325
#if DBG
00326
DbgPrint(
"Psp386RemoveIoHandler : attempt to remove non-existent hdlr\n");
00327
#endif
00328
return STATUS_SUCCESS;
00329 }
00330
00331
00332
00333
00334
KeRaiseIrql(
APC_LEVEL, &OldIrql);
00335
ExAcquireResourceExclusive(&pVdmObjects->VdmIoListHead->VdmIoResource,
TRUE);
00336
00337 VdmIoHandler =
Psp386GetVdmIoHandler(
00338 Process,
00339 PortNumber & ~0x3
00340 );
00341
00342
if (!VdmIoHandler) {
00343
#if DBG
00344
DbgPrint(
"Psp386RemoveIoHandler : attempt to remove non-existent hdlr\n");
00345
#endif
00346
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00347
KeLowerIrql(OldIrql);
00348
return STATUS_SUCCESS;
00349 }
00350
00351
ASSERTEQUALBREAK(
00352 VdmIoHandler->PortNumber,
00353 PortNumber & ~0x3,
00354 (
"Psp386RemoveIoHandler : Bad pointer returned from GetVdmIoHandler\n")
00355 );
00356
00357
if (EmulatorAccessEntry->AccessMode &
EMULATOR_READ_ACCESS) {
00358
switch (EmulatorAccessEntry->AccessType) {
00359
case Uchar:
00360
if (EmulatorAccessEntry->StringSupport) {
00361
ASSERTEQUAL(
00362 EmulatorAccessEntry->Routine,
00363 VdmIoHandler->IoFunctions[0].UcharStringIo[PortNumber % 4],
00364 (
"Psp386RemoveIoHandler : UcharString fns don't match\n")
00365 );
00366 VdmIoHandler->IoFunctions[0].UcharStringIo[PortNumber % 4] =
NULL;
00367 }
else {
00368
ASSERTEQUAL(
00369 EmulatorAccessEntry->Routine,
00370 VdmIoHandler->IoFunctions[0].UcharIo[PortNumber % 4],
00371 (
"Psp386RemoveIoHandler : Uchar fns don't match\n")
00372 );
00373 VdmIoHandler->IoFunctions[0].UcharIo[PortNumber % 4] =
NULL;
00374 }
00375
break;
00376
case Ushort:
00377
if (EmulatorAccessEntry->StringSupport) {
00378
ASSERTEQUAL(
00379 EmulatorAccessEntry->Routine,
00380 VdmIoHandler->IoFunctions[0].UshortStringIo[(PortNumber & 2) >> 1],
00381 (
"Psp386RemoveIoHandler : UshortString fns don't match\n")
00382 );
00383 VdmIoHandler->IoFunctions[0].UshortStringIo[(PortNumber & 2) >> 1] =
NULL;
00384 }
else {
00385
ASSERTEQUAL(
00386 EmulatorAccessEntry->Routine,
00387 VdmIoHandler->IoFunctions[0].UshortIo[(PortNumber & 2) >> 1],
00388 (
"Psp386RemoveIoHandler : Ushort fns don't match\n")
00389 );
00390 VdmIoHandler->IoFunctions[0].UshortIo[(PortNumber & 2) >> 1] =
NULL;
00391 }
00392
break;
00393
case Ulong:
00394
if (EmulatorAccessEntry->StringSupport) {
00395
ASSERTEQUAL(
00396 EmulatorAccessEntry->Routine,
00397 VdmIoHandler->IoFunctions[0].UlongStringIo,
00398 (
"Psp386RemoveIoHandler : UlongString fns don't match\n")
00399 );
00400 VdmIoHandler->IoFunctions[0].UlongStringIo =
NULL;
00401 }
else {
00402
ASSERTEQUAL(
00403 EmulatorAccessEntry->Routine,
00404 VdmIoHandler->IoFunctions[0].UlongIo,
00405 (
"Psp386RemoveIoHandler : Ulong fns don't match\n")
00406 );
00407 VdmIoHandler->IoFunctions[0].UlongIo =
NULL;
00408 }
00409
break;
00410 }
00411 }
00412
00413
if (EmulatorAccessEntry->AccessMode &
EMULATOR_WRITE_ACCESS) {
00414
switch (EmulatorAccessEntry->AccessType) {
00415
case Uchar:
00416
if (EmulatorAccessEntry->StringSupport) {
00417
ASSERTEQUAL(
00418 EmulatorAccessEntry->Routine,
00419 VdmIoHandler->IoFunctions[1].UcharStringIo[PortNumber % 4],
00420 (
"Psp386RemoveIoHandler : UcharString fns don't match\n")
00421 );
00422 VdmIoHandler->IoFunctions[1].UcharStringIo[PortNumber % 4] =
NULL;
00423 }
else {
00424
ASSERTEQUAL(
00425 EmulatorAccessEntry->Routine,
00426 VdmIoHandler->IoFunctions[1].UcharIo[PortNumber % 4],
00427 (
"Psp386RemoveIoHandler : Uchar fns don't match\n")
00428 );
00429 VdmIoHandler->IoFunctions[1].UcharIo[PortNumber % 4] =
NULL;
00430 }
00431
break;
00432
case Ushort:
00433
if (EmulatorAccessEntry->StringSupport) {
00434
ASSERTEQUAL(
00435 EmulatorAccessEntry->Routine,
00436 VdmIoHandler->IoFunctions[1].UshortStringIo[(PortNumber & 2) >> 1],
00437 (
"Psp386RemoveIoHandler : UshortString fns don't match\n")
00438 );
00439 VdmIoHandler->IoFunctions[1].UshortStringIo[(PortNumber & 2) >> 1] =
NULL;
00440 }
else {
00441
ASSERTEQUAL(
00442 EmulatorAccessEntry->Routine,
00443 VdmIoHandler->IoFunctions[1].UshortIo[(PortNumber & 2) >> 1],
00444 (
"Psp386RemoveIoHandler : Ushort fns don't match\n")
00445 );
00446 VdmIoHandler->IoFunctions[1].UshortIo[(PortNumber & 2) >> 1] =
NULL;
00447 }
00448
break;
00449
case Ulong:
00450
if (EmulatorAccessEntry->StringSupport) {
00451
ASSERTEQUAL(
00452 EmulatorAccessEntry->Routine,
00453 VdmIoHandler->IoFunctions[1].UlongStringIo,
00454 (
"Psp386RemoveIoHandler : UlongString fns don't match\n")
00455 );
00456 VdmIoHandler->IoFunctions[1].UlongStringIo =
NULL;
00457 }
else {
00458
ASSERTEQUAL(
00459 EmulatorAccessEntry->Routine,
00460 VdmIoHandler->IoFunctions[1].UlongIo,
00461 (
"Psp386RemoveIoHandler : Ulong fns don't match\n")
00462 );
00463 VdmIoHandler->IoFunctions[1].UlongIo =
NULL;
00464 }
00465
break;
00466 }
00467 }
00468
00469
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00470
KeLowerIrql(OldIrql);
00471
00472
return STATUS_SUCCESS;
00473
00474 }
00475
00476
NTSTATUS
00477 Psp386InstallIoHandler(
00478 IN
PEPROCESS Process,
00479 IN
PEMULATOR_ACCESS_ENTRY EmulatorAccessEntry,
00480 IN ULONG PortNumber,
00481 IN ULONG Context
00482 )
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 {
00501 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00502 PVDM_IO_HANDLER VdmIoHandler;
00503
NTSTATUS Status;
00504 KIRQL OldIrql;
00505
PAGED_CODE();
00506
00507
00508
00509
00510
00511
00512
if (!pVdmObjects) {
00513
#if DBG
00514
DbgPrint(
"Psp386InstallIoHandler: uninitialized VdmObjects\n");
00515
#endif
00516
return STATUS_UNSUCCESSFUL;
00517 }
00518
00519
00520
Status = STATUS_SUCCESS;
00521
00522
00523
00524
00525
00526
if (!pVdmObjects->VdmIoListHead) {
00527
Status =
Psp386CreateVdmIoListHead(
00528 Process
00529 );
00530
00531
if (!
NT_SUCCESS(
Status)) {
00532
return Status;
00533 }
00534 }
00535
00536
00537
00538
00539
KeRaiseIrql(
APC_LEVEL, &OldIrql);
00540
ExAcquireResourceExclusive(&pVdmObjects->VdmIoListHead->VdmIoResource,
TRUE);
00541
00542
00543
00544
00545
00546 pVdmObjects->VdmIoListHead->Context = Context;
00547
00548 VdmIoHandler =
Psp386GetVdmIoHandler(
00549 Process,
00550 PortNumber & ~0x3
00551 );
00552
00553
00554
00555
00556
if (!VdmIoHandler) {
00557
try {
00558
00559 VdmIoHandler =
ExAllocatePoolWithQuota(
00560
PagedPool,
00561
sizeof(VDM_IO_HANDLER)
00562 );
00563
00564 } except(
EXCEPTION_EXECUTE_HANDLER) {
00565
Status = GetExceptionCode();
00566
if (VdmIoHandler) {
00567
ExFreePool(VdmIoHandler);
00568 }
00569 }
00570
00571
if (!
NT_SUCCESS(
Status)) {
00572
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00573
KeLowerIrql(OldIrql);
00574
return Status;
00575 }
00576
00577 RtlZeroMemory(VdmIoHandler,
sizeof(VDM_IO_HANDLER));
00578 VdmIoHandler->PortNumber = PortNumber & ~0x3;
00579
00580
Status =
Psp386InsertVdmIoHandlerBlock(
00581 Process,
00582 VdmIoHandler
00583 );
00584
00585
if (!
NT_SUCCESS(
Status)) {
00586
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00587
KeLowerIrql(OldIrql);
00588
return Status;
00589 }
00590 }
00591
00592
ASSERTEQUALBREAK(
00593 VdmIoHandler->PortNumber,
00594 PortNumber & ~0x3,
00595 (
"Psp386InstallIoHandler : Bad pointer returned from GetVdmIoHandler\n")
00596 );
00597
00598
if (EmulatorAccessEntry->AccessMode &
EMULATOR_READ_ACCESS) {
00599
switch (EmulatorAccessEntry->AccessType) {
00600
case Uchar:
00601
if (EmulatorAccessEntry->StringSupport) {
00602
ASSERTEQUALBREAK(
00603
NULL,
00604 VdmIoHandler->IoFunctions[0].UcharStringIo[PortNumber % 4],
00605 (
"Psp386InstallIoHandler : UcharString fns don't match\n")
00606 );
00607 VdmIoHandler->IoFunctions[0].UcharStringIo[PortNumber % 4] =
00608 (
PDRIVER_IO_PORT_UCHAR_STRING)EmulatorAccessEntry->Routine;
00609 }
else {
00610
ASSERTEQUALBREAK(
00611
NULL,
00612 VdmIoHandler->IoFunctions[0].UcharIo[PortNumber % 4],
00613 (
"Psp386InstallIoHandler : Uchar fns don't match\n")
00614 );
00615 VdmIoHandler->IoFunctions[0].UcharIo[PortNumber % 4] =
00616 (
PDRIVER_IO_PORT_UCHAR)EmulatorAccessEntry->Routine;
00617 }
00618
break;
00619
case Ushort:
00620
if (EmulatorAccessEntry->StringSupport) {
00621
ASSERTEQUALBREAK(
00622
NULL,
00623 VdmIoHandler->IoFunctions[0].UshortStringIo[(PortNumber & 2) >> 1],
00624 (
"Psp386InstallIoHandler : UshortString fns don't match\n")
00625 );
00626 VdmIoHandler->IoFunctions[0].UshortStringIo[(PortNumber & 2) >> 1] =
00627 (
PDRIVER_IO_PORT_USHORT_STRING)EmulatorAccessEntry->Routine;
00628 }
else {
00629
ASSERTEQUALBREAK(
00630
NULL,
00631 VdmIoHandler->IoFunctions[0].UshortIo[(PortNumber & 2) >> 1],
00632 (
"Psp386InstallIoHandler : Ushort fns don't match\n")
00633 );
00634 VdmIoHandler->IoFunctions[0].UshortIo[(PortNumber & 2) >> 1] =
00635 (
PDRIVER_IO_PORT_USHORT)EmulatorAccessEntry->Routine;
00636 }
00637
break;
00638
case Ulong:
00639
if (EmulatorAccessEntry->StringSupport) {
00640
ASSERTEQUALBREAK(
00641
NULL,
00642 VdmIoHandler->IoFunctions[0].UlongStringIo,
00643 (
"Psp386InstallIoHandler : UlongString fns don't match\n")
00644 );
00645 VdmIoHandler->IoFunctions[0].UlongStringIo =
00646 (
PDRIVER_IO_PORT_ULONG_STRING)EmulatorAccessEntry->Routine;
00647 }
else {
00648
ASSERTEQUALBREAK(
00649
NULL,
00650 VdmIoHandler->IoFunctions[0].UlongIo,
00651 (
"Psp386InstallIoHandler : Ulong fns don't match\n")
00652 );
00653 VdmIoHandler->IoFunctions[0].UlongIo =
00654 (
PDRIVER_IO_PORT_ULONG)EmulatorAccessEntry->Routine;
00655 }
00656
break;
00657 }
00658 }
00659
00660
if (EmulatorAccessEntry->AccessMode &
EMULATOR_WRITE_ACCESS) {
00661
switch (EmulatorAccessEntry->AccessType) {
00662
case Uchar:
00663
if (EmulatorAccessEntry->StringSupport) {
00664
ASSERTEQUALBREAK(
00665
NULL,
00666 VdmIoHandler->IoFunctions[1].UcharStringIo[PortNumber % 4],
00667 (
"Psp386InstallIoHandler : UcharString fns don't match\n")
00668 );
00669 VdmIoHandler->IoFunctions[1].UcharStringIo[PortNumber % 4] =
00670 (
PDRIVER_IO_PORT_UCHAR_STRING)EmulatorAccessEntry->Routine;
00671 }
else {
00672
ASSERTEQUALBREAK(
00673
NULL,
00674 VdmIoHandler->IoFunctions[1].UcharIo[PortNumber % 4],
00675 (
"Psp386InstallIoHandler : Uchar fns don't match\n")
00676 );
00677 VdmIoHandler->IoFunctions[1].UcharIo[PortNumber % 4] =
00678 (
PDRIVER_IO_PORT_UCHAR)EmulatorAccessEntry->Routine;
00679 }
00680
break;
00681
case Ushort:
00682
if (EmulatorAccessEntry->StringSupport) {
00683
ASSERTEQUALBREAK(
00684
NULL,
00685 VdmIoHandler->IoFunctions[1].UshortStringIo[(PortNumber & 2) >> 1],
00686 (
"Psp386InstallIoHandler : UshortString fns don't match\n")
00687 );
00688 VdmIoHandler->IoFunctions[1].UshortStringIo[(PortNumber & 2) >> 1] =
00689 (
PDRIVER_IO_PORT_USHORT_STRING)EmulatorAccessEntry->Routine;
00690 }
else {
00691
ASSERTEQUALBREAK(
00692
NULL,
00693 VdmIoHandler->IoFunctions[1].UshortIo[(PortNumber & 2) >> 1],
00694 (
"Psp386InstallIoHandler : Ushort fns don't match\n")
00695 );
00696 VdmIoHandler->IoFunctions[1].UshortIo[(PortNumber & 2) >> 1] =
00697 (
PDRIVER_IO_PORT_USHORT)EmulatorAccessEntry->Routine;
00698 }
00699
break;
00700
case Ulong:
00701
if (EmulatorAccessEntry->StringSupport) {
00702
ASSERTEQUALBREAK(
00703
NULL,
00704 VdmIoHandler->IoFunctions[1].UlongStringIo,
00705 (
"Psp386InstallIoHandler : UlongString fns don't match\n")
00706 );
00707 VdmIoHandler->IoFunctions[1].UlongStringIo =
00708 (
PDRIVER_IO_PORT_ULONG_STRING)EmulatorAccessEntry->Routine;
00709 }
else {
00710
ASSERTEQUALBREAK(
00711
NULL,
00712 VdmIoHandler->IoFunctions[1].UlongIo,
00713 (
"Psp386InstallIoHandler : Ulong fns don't match\n")
00714 );
00715 VdmIoHandler->IoFunctions[1].UlongIo =
00716 (
PDRIVER_IO_PORT_ULONG)EmulatorAccessEntry->Routine;
00717 }
00718 }
00719 }
00720
00721
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00722
KeLowerIrql(OldIrql);
00723
return STATUS_SUCCESS;
00724
00725 }
00726
00727
00728
00729
NTSTATUS
00730 Psp386CreateVdmIoListHead(
00731 IN
PEPROCESS Process
00732 )
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 {
00751 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00752
NTSTATUS Status;
00753 PVDM_IO_LISTHEAD HandlerListHead;
00754 KIRQL OldIrql;
00755
PAGED_CODE();
00756
00757
Status = STATUS_SUCCESS;
00758
00759
00760
if (pVdmObjects->VdmIoListHead ==
NULL) {
00761
KeRaiseIrql(
APC_LEVEL, &OldIrql);
00762
ExAcquireResourceExclusive(&
VdmIoListCreationResource,
TRUE);
00763
00764
00765
if (pVdmObjects->VdmIoListHead ==
NULL) {
00766
00767
try {
00768
00769
00770
00771 HandlerListHead =
ExAllocatePoolWithQuota(
00772
NonPagedPool,
00773
sizeof(VDM_IO_LISTHEAD)
00774 );
00775
00776 } except(
EXCEPTION_EXECUTE_HANDLER) {
00777
Status = GetExceptionCode();
00778
if (HandlerListHead) {
00779
ExFreePool(HandlerListHead);
00780 }
00781 }
00782
00783
if ((!
NT_SUCCESS(
Status) || !HandlerListHead)) {
00784
ExReleaseResource(&
VdmIoListCreationResource);
00785
KeLowerIrql(OldIrql);
00786
00787
return (
Status == STATUS_SUCCESS ?
00788 STATUS_INSUFFICIENT_RESOURCES :
00789
Status);
00790
00791 }
00792
00793
ExInitializeResource(&HandlerListHead->VdmIoResource);
00794
00795 HandlerListHead->VdmIoHandlerList =
NULL;
00796
00797
00798
00799
00800
00801
00802 pVdmObjects->VdmIoListHead = HandlerListHead;
00803
00804
ExReleaseResource(&
VdmIoListCreationResource);
00805
KeLowerIrql(OldIrql);
00806
00807
00808 }
00809 }
00810
return STATUS_SUCCESS;
00811 }
00812
00813
NTSTATUS
00814 Psp386InsertVdmIoHandlerBlock(
00815 IN
PEPROCESS Process,
00816 IN PVDM_IO_HANDLER VdmIoHandler
00817 )
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833 {
00834 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00835 PVDM_IO_HANDLER
HandlerList, p;
00836 PVDM_IO_LISTHEAD HandlerListHead;
00837
PAGED_CODE();
00838
00839
00840 HandlerListHead = pVdmObjects->VdmIoListHead;
00841
HandlerList = HandlerListHead->VdmIoHandlerList;
00842 p =
NULL;
00843
while ((
HandlerList !=
NULL) &&
00844 (
HandlerList->PortNumber < VdmIoHandler->PortNumber)) {
00845
#if DBG
00846
if (
HandlerList->PortNumber == VdmIoHandler->PortNumber) {
00847
DbgPrint(
"Ps386InsertVdmIoHandlerBlock : handler list corrupt\n");
00848 }
00849
#endif
00850
p =
HandlerList;
00851
HandlerList =
HandlerList->Next;
00852 }
00853
00854
if (p ==
NULL) {
00855 VdmIoHandler->Next = HandlerListHead->VdmIoHandlerList;
00856 HandlerListHead->VdmIoHandlerList = VdmIoHandler;
00857 }
else if (
HandlerList ==
NULL) {
00858 p->Next = VdmIoHandler;
00859 VdmIoHandler->Next =
NULL;
00860 }
else {
00861 VdmIoHandler->Next =
HandlerList;
00862 p->Next = VdmIoHandler;
00863 }
00864
00865
return STATUS_SUCCESS;
00866 }
00867
00868 BOOLEAN
00869 Ps386GetVdmIoHandler(
00870 IN
PEPROCESS Process,
00871 IN ULONG PortNumber,
00872 OUT PVDM_IO_HANDLER VdmIoHandler,
00873 OUT PULONG Context
00874 )
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 {
00895 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00896 PVDM_IO_HANDLER p;
00897 BOOLEAN Success;
00898 KIRQL OldIrql;
00899
PAGED_CODE();
00900
00901
ASSERT (pVdmObjects !=
NULL);
00902
00903
if (PortNumber % 4) {
00904
#if DBG
00905
DbgPrint(
00906
"Ps386GetVdmIoHandler : Invalid Port Number %lx\n",
00907 PortNumber
00908 );
00909
#endif
00910
return FALSE;
00911 }
00912
00913
if (!pVdmObjects->VdmIoListHead) {
00914
return FALSE;
00915 }
00916
00917
00918
KeRaiseIrql(
APC_LEVEL, &OldIrql);
00919
ExAcquireResourceExclusive(&pVdmObjects->VdmIoListHead->VdmIoResource,
TRUE);
00920
00921 p =
Psp386GetVdmIoHandler(
00922 Process,
00923 PortNumber
00924 );
00925
00926
if (p) {
00927 *VdmIoHandler = *p;
00928 *Context = pVdmObjects->VdmIoListHead->Context;
00929 Success =
TRUE;
00930 }
else {
00931 Success =
FALSE;
00932 }
00933
ExReleaseResource(&pVdmObjects->VdmIoListHead->VdmIoResource);
00934
KeLowerIrql(OldIrql);
00935
00936
return Success;
00937 }
00938
00939
00940 PVDM_IO_HANDLER
00941 Psp386GetVdmIoHandler(
00942 IN
PEPROCESS Process,
00943 IN ULONG PortNumber
00944 )
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 {
00963 PVDM_PROCESS_OBJECTS pVdmObjects = Process->VdmObjects;
00964 PVDM_IO_HANDLER p;
00965
PAGED_CODE();
00966
00967
if (PortNumber % 4) {
00968
#if DBG
00969
DbgPrint(
00970
"Ps386GetVdmIoHandler : Invalid Port Number %lx\n",
00971 PortNumber
00972 );
00973
#endif
00974
return NULL;
00975 }
00976
00977 p = pVdmObjects->VdmIoListHead->VdmIoHandlerList;
00978
while ((p) && (p->PortNumber != PortNumber)) {
00979 p = p->Next;
00980 }
00981
00982
return p;
00983
00984 }
00985
00986
NTSTATUS
00987 PspVdmInitialize(
00988 )
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 {
01005
return ExInitializeResource(&
VdmIoListCreationResource);
01006 }
01007