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