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 ULONG Length;
00068 ULONG NewStack;
00069 ULONG OldStack;
00070
NTSTATUS Status;
00071 PULONG UserStack;
00072 PVOID
ValueBuffer;
00073 ULONG ValueLength;
00074 PEXCEPTION_REGISTRATION_RECORD ExceptionList;
00075 PTEB Teb;
00076
00077
ASSERT(KeGetPreviousMode() == UserMode);
00078
00079
00080
00081
00082
00083
00084 UserStack =
KiGetUserModeStackAddress();
00085 OldStack = *UserStack;
00086
try {
00087
00088
00089
00090
00091
00092
00093 Length = (InputLength +
sizeof(
CHAR) - 1) & ~(
sizeof(
CHAR) - 1);
00094 NewStack = OldStack - Length;
00095
ProbeForWrite((PCHAR)(NewStack - 16), Length + 16,
sizeof(CHAR));
00096 RtlCopyMemory((PVOID)NewStack, InputBuffer, Length);
00097
00098
00099
00100
00101
00102 *(PULONG)(NewStack - 4) = (ULONG)InputLength;
00103 *(PULONG)(NewStack - 8) = (ULONG)NewStack;
00104 *(PULONG)(NewStack - 12) = ApiNumber;
00105 *(PULONG)(NewStack - 16) = 0;
00106 NewStack -= 16;
00107
00108
00109
00110
00111
00112
00113 Teb = (PTEB)
KeGetCurrentThread()->Teb;
00114 ExceptionList = Teb->NtTib.ExceptionList;
00115
00116
00117
00118
00119
00120 *UserStack = NewStack;
00121
Status =
KiCallUserMode(OutputBuffer, OutputLength);
00122
00123
00124
00125
00126
00127 Teb->NtTib.ExceptionList = ExceptionList;
00128
00129
00130
00131
00132
00133
00134
00135 } except (EXCEPTION_EXECUTE_HANDLER) {
00136
return GetExceptionCode();
00137 }
00138
00139
00140
00141
00142
00143
00144
if (Teb->GdiBatchCount > 0) {
00145
00146
00147
00148
00149
00150 *UserStack -= 256;
00151
KeGdiFlushUserBatch();
00152 }
00153
00154 *UserStack = OldStack;
00155
return Status;
00156 }