|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
internal.c
Abstract:
User-mode interface to SR.SYS.
Author:
Keith Moore (keithmo) 15-Dec-1998 (ul.sys) Paul McDaniel (paulmcd) 07-Mar-2000
Revision History:
--*/
#include "precomp.h"
//
// Private macros.
//
#define EA_BUFFER_LENGTH \
( sizeof(FILE_FULL_EA_INFORMATION) + \ SR_OPEN_PACKET_NAME_LENGTH + \ sizeof(SR_OPEN_PACKET) )
//
// Private prototypes.
//
NTSTATUS SrpAcquireCachedEvent( OUT PHANDLE pEvent );
VOID SrpReleaseCachedEvent( IN HANDLE Event );
//
// Public functions.
//
/***************************************************************************++
Routine Description:
Synchronous wrapper around NtDeviceIoControlFile().
Arguments:
FileHandle - Supplies a handle to the file on which the service is being performed.
IoControlCode - Subfunction code to determine exactly what operation is being performed.
pInputBuffer - Optionally supplies an input buffer to be passed to the device driver. Whether or not the buffer is actually optional is dependent on the IoControlCode.
InputBufferLength - Length of the pInputBuffer in bytes.
pOutputBuffer - Optionally supplies an output buffer to receive information from the device driver. Whether or not the buffer is actually optional is dependent on the IoControlCode.
OutputBufferLength - Length of the pOutputBuffer in bytes.
pBytesTransferred - Optionally receives the number of bytes transferred.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS SrpSynchronousDeviceControl( IN HANDLE FileHandle, IN ULONG IoControlCode, IN PVOID pInputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PULONG pBytesTransferred OPTIONAL ) { NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; HANDLE event; LARGE_INTEGER timeout;
//
// Try to snag an event object.
//
status = SrpAcquireCachedEvent( &event );
if (NT_SUCCESS(status)) { //
// Make the call.
//
status = NtDeviceIoControlFile( FileHandle, // FileHandle
event, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
IoControlCode, // IoControlCode
pInputBuffer, // InputBuffer
InputBufferLength, // InputBufferLength
pOutputBuffer, // OutputBuffer
OutputBufferLength // OutputBufferLength
);
if (status == STATUS_PENDING) { //
// Wait for it to complete.
//
timeout.LowPart = 0xFFFFFFFF; timeout.HighPart = 0x7FFFFFFF;
status = NtWaitForSingleObject( event, FALSE, &timeout ); ASSERT( status == STATUS_SUCCESS );
status = ioStatusBlock.Status; }
//
// If the call didn't fail and the caller wants the number
// of bytes transferred, grab the value from the I/O status
// block & return it.
//
if (!NT_ERROR(status) && pBytesTransferred != NULL) { *pBytesTransferred = (ULONG)ioStatusBlock.Information; }
//
// Release the cached event object we acquired above.
//
SrpReleaseCachedEvent( event ); }
return status;
} // SrpSynchronousDeviceControl
/***************************************************************************++
Routine Description:
Overlapped wrapper around NtDeviceIoControlFile().
Arguments:
FileHandle - Supplies a handle to the file on which the service is being performed.
pOverlapped - Supplies an OVERLAPPED structure.
IoControlCode - Subfunction code to determine exactly what operation is being performed.
pInputBuffer - Optionally supplies an input buffer to be passed to the device driver. Whether or not the buffer is actually optional is dependent on the IoControlCode.
InputBufferLength - Length of the pInputBuffer in bytes.
pOutputBuffer - Optionally supplies an output buffer to receive information from the device driver. Whether or not the buffer is actually optional is dependent on the IoControlCode.
OutputBufferLength - Length of the pOutputBuffer in bytes.
pBytesTransferred - Optionally receives the number of bytes transferred.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS SrpOverlappedDeviceControl( IN HANDLE FileHandle, IN OUT LPOVERLAPPED pOverlapped, IN ULONG IoControlCode, IN PVOID pInputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PULONG pBytesTransferred OPTIONAL ) { NTSTATUS status;
//
// Overlapped I/O gets a little more interesting. We'll strive to be
// compatible with NT's KERNEL32 implementation. See DeviceIoControl()
// in \\rastaman\ntwin\src\base\client\filehops.c for the gory details.
//
OVERLAPPED_TO_IO_STATUS(pOverlapped)->Status = STATUS_PENDING;
status = NtDeviceIoControlFile( FileHandle, // FileHandle
pOverlapped->hEvent, // Event
NULL, // ApcRoutine
(ULONG_PTR)pOverlapped->hEvent & 1 // ApcContext
? NULL : pOverlapped, OVERLAPPED_TO_IO_STATUS(pOverlapped), // IoStatusBlock
IoControlCode, // IoControlCode
pInputBuffer, // InputBuffer
InputBufferLength, // InputBufferLength
pOutputBuffer, // OutputBuffer
OutputBufferLength // OutputBufferLength
);
//
// If the call didn't fail or pend and the caller wants the number of
// bytes transferred, grab the value from the I/O status block &
// return it.
//
if (!NT_ERROR(status) && status != STATUS_PENDING && pBytesTransferred != NULL) { *pBytesTransferred = (ULONG)OVERLAPPED_TO_IO_STATUS(pOverlapped)->Information; }
return status;
} // SrpOverlappedDeviceControl
/***************************************************************************++
Routine Description:
Initializes the event object cache.
Return Value:
ULONG - Completion status.
--***************************************************************************/ ULONG SrpInitializeEventCache( VOID ) { //
// CODEWORK: MAKE THIS CACHED!
//
return NO_ERROR;
} // SrpInitializeEventCache
/***************************************************************************++
Routine Description:
Terminates the event object cache.
Return Value:
ULONG - Completion status.
--***************************************************************************/ ULONG SrpTerminateEventCache( VOID ) { //
// CODEWORK: MAKE THIS CACHED!
//
return NO_ERROR;
} // SrpTerminateEventCache
/***************************************************************************++
Routine Description:
This routine attempts to start UL.SYS.
Return Value:
BOOLEAN - TRUE if successful, FALSE otherwise.
--***************************************************************************/ BOOLEAN SrpTryToStartDriver( VOID ) { BOOLEAN result; SC_HANDLE scHandle; SC_HANDLE svcHandle;
result = FALSE; // until proven otherwise...
//
// Open the service controller.
//
scHandle = OpenSCManagerW( NULL, // lpMachineName
NULL, // lpDatabaseName
SC_MANAGER_ALL_ACCESS // dwDesiredAccess
);
if (scHandle != NULL) { //
// Try to open the UL service.
//
svcHandle = OpenServiceW( scHandle, // hSCManager
SR_SERVICE_NAME, // lpServiceName
SERVICE_ALL_ACCESS // dwDesiredAccess
);
if (svcHandle != NULL) { //
// Try to start it.
//
if (StartService( svcHandle, 0, NULL)) { result = TRUE; }
CloseServiceHandle( svcHandle ); }
CloseServiceHandle( scHandle ); }
return result;
} // SrpTryToStartDriver
//
// Private functions.
//
/***************************************************************************++
Routine Description:
Helper routine for opening a UL.SYS handle.
Arguments:
pHandle - Receives a handle if successful.
DesiredAccess - Supplies the types of access requested to the file.
AppPool - Supplies TRUE to open/create an application pool, FALSE to open a control channel.
pAppPoolName - Optionally supplies the name of the application pool to create/open.
Options - Supplies zero or more UL_OPTION_* flags.
CreateDisposition - Supplies the creation disposition for the new object.
pSecurityAttributes - Optionally supplies security attributes for the newly created application pool. Ignored if opening a control channel.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS SrpOpenDriverHelper( OUT PHANDLE pHandle, IN ACCESS_MASK DesiredAccess, IN ULONG Options, IN ULONG CreateDisposition, IN PSECURITY_ATTRIBUTES pSecurityAttributes OPTIONAL ) { NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING deviceName; IO_STATUS_BLOCK ioStatusBlock; ULONG shareAccess; ULONG createOptions; PFILE_FULL_EA_INFORMATION pEaBuffer; PSR_OPEN_PACKET pOpenPacket; WCHAR deviceNameBuffer[MAX_PATH]; UCHAR rawEaBuffer[EA_BUFFER_LENGTH];
//
// Validate the parameters.
//
if ((pHandle == NULL) || (Options & ~SR_OPTION_VALID)) { return STATUS_INVALID_PARAMETER; }
//
// Build the open packet.
//
pEaBuffer = (PFILE_FULL_EA_INFORMATION)rawEaBuffer;
pEaBuffer->NextEntryOffset = 0; pEaBuffer->Flags = 0; pEaBuffer->EaNameLength = SR_OPEN_PACKET_NAME_LENGTH; pEaBuffer->EaValueLength = sizeof(*pOpenPacket);
RtlCopyMemory( pEaBuffer->EaName, SR_OPEN_PACKET_NAME, SR_OPEN_PACKET_NAME_LENGTH + 1 );
pOpenPacket = (PSR_OPEN_PACKET)( pEaBuffer->EaName + pEaBuffer->EaNameLength + 1 );
pOpenPacket->MajorVersion = SR_INTERFACE_VERSION_MAJOR; pOpenPacket->MinorVersion = SR_INTERFACE_VERSION_MINOR;
//
// Build the device name.
//
//
// It's a control channel, so just use the appropriate device name.
//
wcscpy( deviceNameBuffer, SR_CONTROL_DEVICE_NAME );
//
// Determine the share access and create options based on the
// Flags parameter.
//
shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createOptions = 0;
if ((Options & SR_OPTION_OVERLAPPED) == 0) { createOptions |= FILE_SYNCHRONOUS_IO_NONALERT; }
//
// Build the object attributes.
//
RtlInitUnicodeString( &deviceName, deviceNameBuffer );
InitializeObjectAttributes( &objectAttributes, // ObjectAttributes
&deviceName, // ObjectName
OBJ_CASE_INSENSITIVE, // Attributes
NULL, // RootDirectory
NULL // SecurityDescriptor
);
if (pSecurityAttributes != NULL) { objectAttributes.SecurityDescriptor = pSecurityAttributes->lpSecurityDescriptor;
if (pSecurityAttributes->bInheritHandle) { objectAttributes.Attributes |= OBJ_INHERIT; } }
//
// Open the SR device.
//
status = NtCreateFile( pHandle, // FileHandle
DesiredAccess, // DesiredAccess
&objectAttributes, // ObjectAttributes
&ioStatusBlock, // IoStatusBlock
NULL, // AllocationSize
0, // FileAttributes
shareAccess, // ShareAccess
CreateDisposition, // CreateDisposition
createOptions, // CreateOptions
pEaBuffer, // EaBuffer
EA_BUFFER_LENGTH // EaLength
);
if (!NT_SUCCESS(status)) { *pHandle = NULL; }
return status;
} // SrpOpenDriverHelper
/***************************************************************************++
Routine Description:
Acquires a short-term event from the global event cache. This event object may only be used for pseudo-synchronous I/O.
Arguments:
pEvent - Receives the event handle.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS SrpAcquireCachedEvent( OUT PHANDLE pEvent ) { NTSTATUS status;
//
// CODEWORK: MAKE THIS CACHED!
//
status = NtCreateEvent( pEvent, // EventHandle
EVENT_ALL_ACCESS, // DesiredAccess
NULL, // ObjectAttributes
SynchronizationEvent, // EventType
FALSE // InitialState
);
return status;
} // SrpAcquireCachedEvent
/***************************************************************************++
Routine Description:
Releases a cached event acquired via SrpAcquireCachedEvent().
Arguments:
Event - Supplies the event to release.
--***************************************************************************/ VOID SrpReleaseCachedEvent( IN HANDLE Event ) { NTSTATUS status;
//
// CODEWORK: MAKE THIS CACHED!
//
status = NtClose( Event ); ASSERT( NT_SUCCESS(status) );
} // SrpReleaseCachedEvent
|