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 ULONG OldStack;
00070
NTSTATUS Status;
00071 PKTRAP_FRAME TrapFrame;
00072 PULONG UserStack;
00073 PVOID
ValueBuffer;
00074 ULONG ValueLength;
00075
00076
ASSERT(KeGetPreviousMode() == UserMode);
00077
00078
00079
00080
00081
00082
00083 TrapFrame =
KeGetCurrentThread()->TrapFrame;
00084 OldStack = (ULONG)TrapFrame->XIntSp;
00085
try {
00086
00087
00088
00089
00090
00091
00092 Length = (InputLength +
00093
sizeof(QUAD) - 1 +
sizeof(UCALLOUT_FRAME)) & ~(
sizeof(QUAD) - 1);
00094
00095 CalloutFrame = (PUCALLOUT_FRAME)(OldStack - Length);
00096
ProbeForWrite(CalloutFrame, Length,
sizeof(QUAD));
00097 RtlMoveMemory(CalloutFrame + 1, InputBuffer, InputLength);
00098
00099
00100
00101
00102
00103 CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
00104 CalloutFrame->Length = InputLength;
00105 CalloutFrame->ApiNumber = ApiNumber;
00106 CalloutFrame->Pad = 0;
00107 CalloutFrame->Sp = TrapFrame->XIntSp;
00108 CalloutFrame->Ra = TrapFrame->XIntRa;
00109
00110
00111
00112
00113
00114
00115
00116 } except (EXCEPTION_EXECUTE_HANDLER) {
00117
return GetExceptionCode();
00118 }
00119
00120
00121
00122
00123
00124 TrapFrame->XIntSp = (LONG)CalloutFrame;
00125
Status =
KiCallUserMode(OutputBuffer, OutputLength);
00126 TrapFrame->XIntSp = (LONG)OldStack;
00127
00128
00129
00130
00131
00132
if (((PTEB)
KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {
00133
KeGdiFlushUserBatch();
00134 }
00135
00136
return Status;
00137 }