00038 :
00039
00040 This function call
out from kernel mode to a user mode function.
00041
00042 Arguments:
00043
00044 ApiNumber - Supplies
the API number.
00045
00046 InputBuffer - Supplies a pointer to a structure that
is copied
00047 to
the user stack.
00048
00049 InputLength - Supplies
the length of
the input structure.
00050
00051 Outputbuffer - Supplies a pointer to a variable that receives
00052
the address of
the output buffer.
00053
00054 Outputlength - Supplies a pointer to a variable that receives
00055
the length of
the output buffer.
00056
00057 Return Value:
00058
00059 If
the callout cannot be executed, then an error status
is
00060 returned. Otherwise,
the status returned by
the callback function
00061
is returned.
00062
00063 --*/
00064
00065 {
00066
00067 PUCALLOUT_FRAME CalloutFrame;
00068 ULONG Length;
00069 ULONGLONG OldStack;
00070
NTSTATUS Status;
00071 PKTRAP_FRAME TrapFrame;
00072 PVOID
ValueBuffer;
00073 ULONG ValueLength;
00074
00075
ASSERT(KeGetPreviousMode() == UserMode);
00076
00077
00078
00079
00080
00081
00082 TrapFrame =
KeGetCurrentThread()->TrapFrame;
00083 OldStack = TrapFrame->IntSp;
00084
try {
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 Length = (InputLength +
00095 16 - 1 +
sizeof(UCALLOUT_FRAME)) & ~(16 - 1);
00096
00097 CalloutFrame = (PUCALLOUT_FRAME)(OldStack - Length);
00098
ProbeForWrite(CalloutFrame, Length,
sizeof(QUAD));
00099 RtlCopyMemory(CalloutFrame + 1, InputBuffer, InputLength);
00100
00101
00102
00103
00104
00105 CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
00106 CalloutFrame->Length = InputLength;
00107 CalloutFrame->ApiNumber = ApiNumber;
00108 CalloutFrame->Sp = OldStack;
00109 CalloutFrame->Ra = TrapFrame->IntRa;
00110
00111
00112
00113
00114
00115
00116
00117 } except (EXCEPTION_EXECUTE_HANDLER) {
00118
return GetExceptionCode();
00119 }
00120
00121
00122
00123
00124
00125 TrapFrame->IntSp = (ULONGLONG)(LONG_PTR)CalloutFrame;
00126
Status =
KiCallUserMode(OutputBuffer, OutputLength);
00127
00128
00129
00130
00131
00132
00133
if (((PTEB)
KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {
00134 TrapFrame->IntSp -= 256;
00135
KeGdiFlushUserBatch();
00136 }
00137
00138 TrapFrame->IntSp = OldStack;
00139
return Status;
00140 }