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 }