00040 :
00041
00042 This function call
out from kernel mode to a user mode function.
00043
00044 Arguments:
00045
00046 ApiNumber - Supplies
the API number.
00047
00048 InputBuffer - Supplies a pointer to a structure that
is copied
00049 to
the user stack.
00050
00051 InputLength - Supplies
the length of
the input structure.
00052
00053 Outputbuffer - Supplies a pointer to a variable that receives
00054
the address of
the output buffer.
00055
00056 Outputlength - Supplies a pointer to a variable that receives
00057
the length of
the output buffer.
00058
00059 Return Value:
00060
00061 If
the callout cannot be executed, then an error status
is
00062 returned. Otherwise,
the status returned by
the callback function
00063
is returned.
00064
00065 --*/
00066
00067 {
00068 PUCALLOUT_FRAME CalloutFrame;
00069 ULONGLONG OldStack;
00070 ULONGLONG NewStack;
00071 ULONGLONG OldStIFS;
00072 PKTRAP_FRAME TrapFrame;
00073
NTSTATUS Status;
00074 ULONG Length;
00075
SHORT BsFrameSize;
00076
USHORT TearPointOffset;
00077
00078
ASSERT(KeGetPreviousMode() == UserMode);
00079
00080
00081
00082
00083
00084
00085 TrapFrame =
KeGetCurrentThread()->TrapFrame;
00086 OldStack = TrapFrame->IntSp;
00087 OldStIFS = TrapFrame->StIFS;
00088
00089
try {
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 Length = (InputLength + 16 - 1 +
sizeof(UCALLOUT_FRAME) + STACK_SCRATCH_AREA) & ~(16 - 1);
00100 NewStack = OldStack - Length;
00101 CalloutFrame = (PUCALLOUT_FRAME)(NewStack + STACK_SCRATCH_AREA);
00102
ProbeForWrite((PVOID)NewStack, Length,
sizeof(QUAD));
00103 RtlCopyMemory(CalloutFrame + 1, InputBuffer, InputLength);
00104
00105
00106
00107
00108
00109 CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
00110 CalloutFrame->Length = InputLength;
00111 CalloutFrame->ApiNumber = ApiNumber;
00112 CalloutFrame->IntSp = OldStack;
00113 CalloutFrame->RsPFS = TrapFrame->StIFS;
00114 CalloutFrame->BrRp = TrapFrame->BrRp;
00115
00116
if (
PsGetCurrentProcess()->DebugPort !=
NULL) {
00117 KiFlushRse();
00118 BsFrameSize = (
SHORT)(TrapFrame->RsBSP - TrapFrame->RsBSPSTORE);
00119
if (BsFrameSize) {
00120
00121 ULONGLONG TopBound, BottomBound;
00122 ULONGLONG UserRnats1, UserRnats2;
00123 ULONGLONG Mask;
00124 ULONGLONG CurrentRNAT = 0;
00125
SHORT RNatSaveIndex;
00126
00127
00128
00129
00130
00131
00132 TearPointOffset = (
USHORT) TrapFrame->RsBSPSTORE & 0x1F8;
00133 RtlCopyMemory((PVOID)(TrapFrame->RsBSPSTORE),
00134 (PVOID)(PCR->InitialBStore + TearPointOffset),
00135 BsFrameSize);
00136
00137 TopBound = TrapFrame->RsBSP | RNAT_ALIGNMENT;
00138 BottomBound = TrapFrame->RsBSPSTORE | RNAT_ALIGNMENT;
00139
00140 RNatSaveIndex = TearPointOffset >> 3;
00141 Mask = (((1ULL << (NAT_BITS_PER_RNAT_REG - RNatSaveIndex)) - 1) << RNatSaveIndex);
00142 UserRnats1 = TrapFrame->RsRNAT & ((1ULL << RNatSaveIndex) - 1);
00143
00144
if (TopBound > BottomBound) {
00145
00146
00147
00148
00149
00150
00151
00152
00153 UserRnats2 = *(PULONGLONG)BottomBound & Mask;
00154 *(PULONGLONG)BottomBound = UserRnats1 | UserRnats2;
00155 TrapFrame->RsRNAT = CurrentRNAT;
00156
00157 }
else {
00158
00159
00160
00161
00162
00163
00164
00165 UserRnats2 = CurrentRNAT & Mask;
00166 TrapFrame->RsRNAT = UserRnats1 | UserRnats2;
00167
00168 }
00169
00170 TrapFrame->RsBSPSTORE = TrapFrame->RsBSP;
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179
00180 } except (EXCEPTION_EXECUTE_HANDLER) {
00181
return GetExceptionCode();
00182 }
00183
00184
00185
00186
00187
00188 TrapFrame->StIFS = 0xC000000000000000i64;
00189 TrapFrame->IntSp = NewStack;
00190
Status =
KiCallUserMode(OutputBuffer, OutputLength);
00191
00192
00193
00194
00195
00196
00197
if (((PTEB)
KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {
00198
00199
00200
00201
00202
00203
KeGdiFlushUserBatch();
00204 }
00205
00206 TrapFrame->IntSp = OldStack;
00207 TrapFrame->StIFS = OldStIFS;
00208
return Status;
00209
00210 }