NT4/private/ntos/ke/mips/callback.c
2020-09-30 17:12:29 +02:00

238 lines
5.2 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
callback.c
Abstract:
This module implements user mode call back services.
Author:
David N. Cutler (davec) 29-Oct-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
NTSTATUS
KeUserModeCallback (
IN ULONG ApiNumber,
IN PVOID InputBuffer,
IN ULONG InputLength,
OUT PVOID *OutputBuffer,
IN PULONG OutputLength
)
/*++
Routine Description:
This function call out from kernel mode to a user mode function.
Arguments:
ApiNumber - Supplies the API number.
InputBuffer - Supplies a pointer to a structure that is copied
to the user stack.
InputLength - Supplies the length of the input structure.
Outputbuffer - Supplies a pointer to a variable that receives
the address of the output buffer.
Outputlength - Supplies a pointer to a variable that receives
the length of the output buffer.
Return Value:
If the callout cannot be executed, then an error status is
returned. Otherwise, the status returned by the callback function
is returned.
--*/
{
PUCALLOUT_FRAME CalloutFrame;
ULONG Length;
ULONG OldStack;
NTSTATUS Status;
PKTRAP_FRAME TrapFrame;
PULONG UserStack;
PVOID ValueBuffer;
ULONG ValueLength;
ASSERT(KeGetPreviousMode() == UserMode);
//
// Get the user mode stack pointer and attempt to copy input buffer
// to the user stack.
//
TrapFrame = KeGetCurrentThread()->TrapFrame;
OldStack = (ULONG)TrapFrame->XIntSp;
try {
//
// Compute new user mode stack address, probe for writability,
// and copy the input buffer to the user stack.
//
Length = (InputLength +
sizeof(QUAD) - 1 + sizeof(UCALLOUT_FRAME)) & ~(sizeof(QUAD) - 1);
CalloutFrame = (PUCALLOUT_FRAME)(OldStack - Length);
ProbeForWrite(CalloutFrame, Length, sizeof(QUAD));
RtlMoveMemory(CalloutFrame + 1, InputBuffer, InputLength);
//
// Allocate stack frame fill in callout arguments.
//
CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
CalloutFrame->Length = InputLength;
CalloutFrame->ApiNumber = ApiNumber;
CalloutFrame->Pad = 0;
CalloutFrame->Sp = TrapFrame->XIntSp;
CalloutFrame->Ra = TrapFrame->XIntRa;
//
// If an exception occurs during the probe of the user stack, then
// always handle the exception and return the exception code as the
// status value.
//
} except (EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
//
// Call user mode.
//
TrapFrame->XIntSp = (LONG)CalloutFrame;
Status = KiCallUserMode(OutputBuffer, OutputLength);
TrapFrame->XIntSp = (LONG)OldStack;
//
// If the GDI TEB batch contains any entries, it must be flushed.
//
if (((PTEB)KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {
KeGdiFlushUserBatch();
}
return Status;
}
NTSTATUS
NtW32Call (
IN ULONG ApiNumber,
IN PVOID InputBuffer,
IN ULONG InputLength,
OUT PVOID *OutputBuffer,
OUT PULONG OutputLength
)
/*++
Routine Description:
This function calls a W32 function.
N.B. ************** This is a temporary service *****************
Arguments:
ApiNumber - Supplies the API number.
InputBuffer - Supplies a pointer to a structure that is copied to
the user stack.
InputLength - Supplies the length of the input structure.
Outputbuffer - Supplies a pointer to a variable that recevies the
output buffer address.
Outputlength - Supplies a pointer to a variable that recevies the
output buffer length.
Return Value:
TBS.
--*/
{
PVOID ValueBuffer;
ULONG ValueLength;
NTSTATUS Status;
ASSERT(KeGetPreviousMode() == UserMode);
//
// If the current thread is not a GUI thread, then fail the service
// since the thread does not have a large stack.
//
if (KeGetCurrentThread()->Win32Thread == (PVOID)&KeServiceDescriptorTable[0]) {
return STATUS_NOT_IMPLEMENTED;
}
//
// Probe the output buffer address and length for writeability.
//
try {
ProbeForWriteUlong((PULONG)OutputBuffer);
ProbeForWriteUlong(OutputLength);
//
// If an exception occurs during the probe of the output buffer or
// length, then always handle the exception and return the exception
// code as the status value.
//
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
//
// Call out to user mode specifying the input buffer and API number.
//
Status = KeUserModeCallback(ApiNumber,
InputBuffer,
InputLength,
&ValueBuffer,
&ValueLength);
//
// If the callout is successful, then the output buffer address and
// length.
//
if (NT_SUCCESS(Status)) {
try {
*OutputBuffer = ValueBuffer;
*OutputLength = ValueLength;
} except(EXCEPTION_EXECUTE_HANDLER) {
}
}
return Status;
}