00067 :
00068
00069 This function invokes specified ROM BIOS code by executing
00070
"INT BiosCommand." Before executing
the BIOS code,
this function
00071 will setup VDM context, change stack pointer ...etc. If
for some
reason
00072
the operation fails, a status code will be returned. Otherwise,
this
00073 function always returns success reguardless of
the result of
the BIOS
00074 call.
00075
00076 N.B. This implementation relies on
the fact that
the direct
00077 I/O access operations between apps are serialized by win user.
00078
00079 Arguments:
00080
00081 BiosCommand - specifies which ROM BIOS function to invoke.
00082
00083 BiosArguments - specifies a pointer to
the context which will be used
00084 to invoke ROM BIOS.
00085
00086 Return Value:
00087
00088
NTSTATUS code to specify
the failure.
00089
00090 --*/
00091
00092 {
00093
00094
NTSTATUS Status = STATUS_SUCCESS;
00095
PVDM_TIB VdmTib;
00096 PUCHAR BaseAddress = (PUCHAR)
V86_CODE_ADDRESS;
00097 PTEB UserInt10Teb = (PTEB)
INT_10_TEB;
00098 PKTSS Tss;
00099
PKPROCESS Process;
00100
PKTHREAD Thread;
00101
USHORT OldIopmOffset, OldIoMapBase;
00102 PVDM_PROCESS_OBJECTS VdmObjects;
00103 ULONG ContextLength;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
if (!
BiosInitialized) {
00117 RtlZeroMemory(UserInt10Teb,
sizeof(TEB));
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
try {
00132
00133
00134
00135
00136
00137
00138
00139 *BaseAddress++ =
INT_OPCODE;
00140 *BaseAddress++ = (UCHAR)BiosCommand;
00141 *(PULONG)BaseAddress =
V86_BOP_OPCODE;
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 UserInt10Teb->Vdm = (PVOID)
VDM_TIB_ADDRESS;
00158 VdmTib = (
PVDM_TIB)
VDM_TIB_ADDRESS;
00159 RtlZeroMemory(VdmTib,
sizeof(
VDM_TIB));
00160 VdmTib->
Size =
sizeof(
VDM_TIB);
00161 *pNtVDMState = 0;
00162
00163
00164
00165
00166
00167
00168 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
00169 RtlMoveMemory(&(VdmTib->
VdmContext), BiosArguments, ContextLength);
00170 VdmTib->
VdmContext.SegCs = (ULONG)BaseAddress >> 4;
00171 VdmTib->
VdmContext.SegSs = (ULONG)BaseAddress >> 4;
00172 VdmTib->
VdmContext.Eip = 0;
00173 VdmTib->
VdmContext.Esp = 2 *
PAGE_SIZE -
sizeof(ULONG);
00174 VdmTib->
VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
00175 VdmTib->
VdmContext.ContextFlags =
CONTEXT_FULL;
00176
00177 } except (EXCEPTION_EXECUTE_HANDLER) {
00178
00179
Status = GetExceptionCode();
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
try {
00190
00191
00192
00193
00194
00195
ASSERT(
PsGetCurrentProcess()->VdmObjects == NULL);
00196 VdmObjects =
ExAllocatePoolWithTag(
00197 NonPagedPool,
00198
sizeof(VDM_PROCESS_OBJECTS),
00199 ' eK'
00200 );
00201
00202
00203
00204
00205
00206
00207
if (VdmObjects ==
NULL) {
00208
Status = STATUS_NO_MEMORY;
00209 }
else {
00210
00211
00212
00213
00214
00215
00216
00217 RtlZeroMemory( VdmObjects,
sizeof(VDM_PROCESS_OBJECTS));
00218
00219 VdmObjects->VdmTib = VdmTib;
00220
00221
PsGetCurrentProcess()->VdmObjects = VdmObjects;
00222 }
00223 } except (EXCEPTION_EXECUTE_HANDLER) {
00224
00225
Status = GetExceptionCode();
00226 }
00227
00228
if (
Status == STATUS_SUCCESS) {
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 Thread =
KeGetCurrentThread();
00251
KeSetSystemAffinityThread(1);
00252 Tss =
KeGetPcr()->TSS;
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
ASSERT(
KeGetPcr()->GDT[KGDT_TSS / 8].LimitLow >= (0x2000 + IOPM_OFFSET - 1));
00264 RtlMoveMemory (Ki386IopmSaveArea,
00265 (PVOID)&Tss->IoMaps[0].IoMap,
00266 PAGE_SIZE * 2
00267 );
00268 RtlZeroMemory ((PVOID)&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);
00269
00270 Process = Thread->
ApcState.
Process;
00271 OldIopmOffset = Process->IopmOffset;
00272 OldIoMapBase = Tss->IoMapBase;
00273 Process->IopmOffset = (
USHORT)(
IOPM_OFFSET);
00274 Tss->IoMapBase = (
USHORT)(
IOPM_OFFSET);
00275
00276
00277
00278
00279
00280
00281
Ki386SetupAndExitToV86Code(UserInt10Teb);
00282
00283
00284
00285
00286
00287
00288
00289 RtlMoveMemory ((PVOID)&Tss->IoMaps[0].IoMap,
00290 Ki386IopmSaveArea,
00291 PAGE_SIZE * 2
00292 );
00293
00294 Process->IopmOffset = OldIopmOffset;
00295 Tss->IoMapBase = OldIoMapBase;
00296
00297
00298
00299
00300
00301
KeRevertToUserAffinityThread();
00302
00303
00304
00305
00306
00307
00308
00309 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
00310 RtlMoveMemory(BiosArguments, &(VdmTib->
VdmContext), ContextLength);
00311 BiosArguments->ContextFlags =
CONTEXT_FULL;
00312
00313
00314
00315
00316
ExFreePool(
PsGetCurrentProcess()->VdmObjects);
00317
PsGetCurrentProcess()->VdmObjects =
NULL;
00318
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
return(
Status);
00333 }
}