mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
9.1 KiB
453 lines
9.1 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
apc.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the APC helper functions for the WinSock 2.0
|
|
helper library. This particular implementation is specific to NT 3.51.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 20-Jun-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
VOID
|
|
WINAPI
|
|
WahpIntermediateApc(
|
|
LPVOID Context,
|
|
LPVOID SystemArgument1,
|
|
LPVOID SystemArgument2
|
|
);
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
WahOpenApcHelper(
|
|
OUT LPHANDLE HelperHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens the WinSock 2.0 APC helper device.
|
|
|
|
Arguments:
|
|
|
|
HelperHandle - Points to a HANDLE that will receive an open handle
|
|
to the APC helper device.
|
|
|
|
Return Value:
|
|
|
|
DWORD - NO_ERROR if successful, a Win32 error code if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING helperName;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
|
|
if( HelperHandle == NULL ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Open the helper device.
|
|
//
|
|
|
|
RtlInitUnicodeString( &helperName, L"\\Device\\Afd\\Helper" );
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes, // ObjectAttributes
|
|
&helperName, // ObjectName
|
|
OBJ_CASE_INSENSITIVE, // Attributes
|
|
NULL, // RootDirectory
|
|
NULL // SecurityDescriptor
|
|
);
|
|
|
|
status = NtCreateFile(
|
|
HelperHandle, // FileHandle
|
|
GENERIC_READ | // DesiredAccess
|
|
GENERIC_WRITE |
|
|
SYNCHRONIZE,
|
|
&objectAttributes, // ObjectAttributes
|
|
&ioStatusBlock, // IoStatusBlock
|
|
NULL, // AllocationSize
|
|
0, // FileAttributes
|
|
FILE_SHARE_READ | // ShareAccess
|
|
FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF, // CreateDisposition
|
|
FILE_SYNCHRONOUS_IO_NONALERT, // CreateOptions
|
|
NULL, // EaBuffer
|
|
0 // EaLength
|
|
);
|
|
|
|
if( NT_SUCCESS(status) ) {
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
return RtlNtStatusToDosError( status );
|
|
|
|
} // WahOpenApcHelper
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
WahCloseApcHelper(
|
|
IN HANDLE HelperHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function closes the WinSock 2.0 APC helper device.
|
|
|
|
Arguments:
|
|
|
|
HelperHandle - The handle to close.
|
|
|
|
Return Value:
|
|
|
|
DWORD - NO_ERROR if successful, a Win32 error code if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
|
|
if( HelperHandle == NULL ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Close the handle.
|
|
//
|
|
|
|
status = NtClose( HelperHandle );
|
|
|
|
if( NT_SUCCESS(status) ) {
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
return RtlNtStatusToDosError( status );
|
|
|
|
} // WahCloseApcHelper
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
WahOpenCurrentThread(
|
|
IN HANDLE HelperHandle,
|
|
OUT LPWSATHREADID ThreadId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens a handle to the current thread.
|
|
|
|
Arguments:
|
|
|
|
HelperHandle - An open handle to the APC helper device.
|
|
|
|
ThreadId - Points to a WSATHREADID structure that will receive
|
|
an open handle to the current thread and an (optional) OS-
|
|
dependent thread identifier.
|
|
|
|
Return Value:
|
|
|
|
DWORD - NO_ERROR if successful, a Win32 error code if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
|
|
if( ( HelperHandle == NULL ) ||
|
|
( ThreadId == NULL ) ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Duplicate the current thread pseudo handle.
|
|
//
|
|
|
|
status = NtDuplicateObject(
|
|
NtCurrentProcess(), // SourceProcessHandle
|
|
NtCurrentThread(), // SourceHandle
|
|
NtCurrentProcess(), // TargetProcessHandle
|
|
&ThreadId->ThreadHandle, // TargetHandle
|
|
0, // DesiredAccess
|
|
0, // HandleAttributes
|
|
DUPLICATE_SAME_ACCESS // Options
|
|
);
|
|
|
|
if( NT_SUCCESS(status) ) {
|
|
|
|
//
|
|
// The NT implementation of the APC helper does not really
|
|
// need the OS-dependent thread identifier, but we'll store
|
|
// the current thread ID in the structure just for completeness.
|
|
//
|
|
|
|
ThreadId->Reserved = (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
return RtlNtStatusToDosError( status );
|
|
|
|
} // WahOpenCurrentThread
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
WahCloseThread(
|
|
IN HANDLE HelperHandle,
|
|
IN LPWSATHREADID ThreadId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine closes an open thread handle.
|
|
|
|
Arguments:
|
|
|
|
HelperHandle - An open handle to the APC helper device.
|
|
|
|
ThreadId - Points to a WSATHREADID structure initialized by a
|
|
previous call to WahOpenCurrentThread().
|
|
|
|
Return Value:
|
|
|
|
DWORD - NO_ERROR if successful, a Win32 error code if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( HelperHandle );
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
|
|
if( ( ThreadId == NULL ) ||
|
|
( ThreadId->ThreadHandle == NULL ) ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Close the handle.
|
|
//
|
|
|
|
status = NtClose( ThreadId->ThreadHandle );
|
|
|
|
if( NT_SUCCESS(status) ) {
|
|
|
|
//
|
|
// Clear the fields in case the client tries something stupid.
|
|
//
|
|
|
|
ThreadId->ThreadHandle = NULL;
|
|
ThreadId->Reserved = 0;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
return RtlNtStatusToDosError( status );
|
|
|
|
} // WahCloseThread
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
WahQueueUserApc(
|
|
IN HANDLE HelperHandle,
|
|
IN LPWSATHREADID ThreadId,
|
|
IN LPWSAUSERAPC ApcRoutine,
|
|
IN DWORD ApcContext OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queues a user-mode APC for the specified thread.
|
|
|
|
Arguments:
|
|
|
|
HelperHandle - An open handle to the APC helper device.
|
|
|
|
ThreadId - Points to a WSATHREADID structure initialized by a
|
|
previous call to WahOpenCurrentThread().
|
|
|
|
ApcRoutine - Points to the APC code to execute when the specified
|
|
thread enters an alertable wait.
|
|
|
|
ApcContext - An uninterpreted context value to pass to the APC routine.
|
|
|
|
Return Value:
|
|
|
|
DWORD - NO_ERROR if successful, a Win32 error code if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
AFD_QUEUE_APC_INFO apcInfo;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
|
|
if( ( HelperHandle == NULL ) ||
|
|
( ThreadId == NULL ) ||
|
|
( ThreadId->ThreadHandle == NULL ) ||
|
|
( ApcRoutine == NULL ) ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Ask the helper to queue the APC. We'll actually schedule
|
|
// WahpIntermediateApc as the "real" APC, which will unpack
|
|
// the parameters and call the routine specified by ApcRoutine.
|
|
//
|
|
|
|
apcInfo.Thread = ThreadId->ThreadHandle;
|
|
apcInfo.ApcRoutine = WahpIntermediateApc;
|
|
apcInfo.ApcContext = (PVOID)ApcContext;
|
|
apcInfo.SystemArgument1 = ApcRoutine;
|
|
apcInfo.SystemArgument2 = NULL;
|
|
|
|
status = NtDeviceIoControlFile(
|
|
HelperHandle, // FileHandle
|
|
NULL, // Event
|
|
NULL, // ApcRoutine
|
|
NULL, // ApcContext
|
|
&ioStatusBlock, // IoStatusBlock
|
|
IOCTL_AFD_QUEUE_APC, // IoControlCode
|
|
&apcInfo, // InputBuffer
|
|
sizeof(apcInfo), // InputBufferLength
|
|
NULL, // OutputBuffer
|
|
0 // OutputBufferLength
|
|
);
|
|
|
|
if( NT_SUCCESS(status) ) {
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
return RtlNtStatusToDosError( status );
|
|
|
|
} // WahQueueUserApc
|
|
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
VOID
|
|
WINAPI
|
|
WahpIntermediateApc(
|
|
LPVOID Context,
|
|
LPVOID SystemArgument1,
|
|
LPVOID SystemArgument2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the "real" APC as scheduled by the NT kernel. It packages
|
|
the parameters into the "portable" (with Win95) form, then calls the
|
|
user-specified APC function.
|
|
|
|
Arguments:
|
|
|
|
Context - The APC context. This is just the ApcContext as passed
|
|
into WahQueueUserApc.
|
|
|
|
SystemArgument1 - This points to the "portable" APC function (this
|
|
is the ApcRoutine as passed into WahQueueUserApc).
|
|
|
|
SystemArgument2 - Unused.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER( SystemArgument2 );
|
|
|
|
//
|
|
// Just call through to the user's APC function.
|
|
//
|
|
|
|
((LPWSAUSERAPC)SystemArgument1)( (DWORD)Context );
|
|
|
|
} // WahpIntermediateApc
|
|
|