414 lines
11 KiB
C
414 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
DevCtrl.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the File System Device Control routines for Rx
|
|||
|
called by the dispatch driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Balan Sethu Raman [19-July-95] -- Hook it up to the mini rdr call down.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#include "ntddmup.h"
|
|||
|
|
|||
|
//
|
|||
|
// The local debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_DEVCTRL)
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxLowIoIoCtlShellCompletion( RXCOMMON_SIGNATURE );
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, RxCommonDeviceControl)
|
|||
|
#pragma alloc_text(PAGE, RxLowIoIoCtlShellCompletion)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxCommonDeviceControl ( RXCOMMON_SIGNATURE )
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for doing Device control operations called
|
|||
|
by both the fsd and fsp threads
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Supplies the Irp to process
|
|||
|
|
|||
|
InFsp - Indicates if this is the fsp thread or someother thread
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - The return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
RxCaptureRequestPacket;
|
|||
|
//RxCaptureFcb;
|
|||
|
//RxCaptureFobx;
|
|||
|
RxCaptureParamBlock;
|
|||
|
//RxCaptureFileObject;
|
|||
|
|
|||
|
//NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
|
|||
|
|
|||
|
BOOLEAN SubmitLowIoRequest = TRUE;
|
|||
|
ULONG IoControlCode = capPARAMS->Parameters.DeviceIoControl.IoControlCode;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxCommonDeviceControl\n", 0));
|
|||
|
RxDbgTrace( 0, Dbg, ("Irp = %08lx\n", capReqPacket));
|
|||
|
RxDbgTrace( 0, Dbg, ("MinorFunction = %08lx\n", capPARAMS->MinorFunction));
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
if (IoControlCode == IOCTL_REDIR_QUERY_PATH) {
|
|||
|
Status = (STATUS_INVALID_DEVICE_REQUEST);
|
|||
|
SubmitLowIoRequest = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (SubmitLowIoRequest) {
|
|||
|
RxInitializeLowIoContext(&RxContext->LowIoContext,LOWIO_OP_IOCTL);
|
|||
|
Status = RxLowIoSubmit(RxContext,RxLowIoIoCtlShellCompletion);
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxCommonDeviceControl -> %08lx\n", Status));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxLowIoIoCtlShellCompletion( RXCOMMON_SIGNATURE )
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the completion routine for IoCtl requests passed down to the mini rdr
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Supplies the Irp being processed
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - The return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RxCaptureRequestPacket;
|
|||
|
//RxCaptureFcb;
|
|||
|
//RxCaptureFobx;
|
|||
|
//RxCaptureParamBlock;
|
|||
|
//RxCaptureFileObject;
|
|||
|
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
//NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
|
|||
|
PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
|
|||
|
//ULONG FsControlCode = capPARAMS->Parameters.FileSystemControl.FsControlCode;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Status = RxContext->StoredStatus;
|
|||
|
RxDbgTrace(+1, Dbg, ("RxLowIoIoCtlShellCompletion entry Status = %08lx\n", Status));
|
|||
|
|
|||
|
switch (Status) { //maybe success vs warning vs error
|
|||
|
case STATUS_SUCCESS:
|
|||
|
case STATUS_BUFFER_OVERFLOW:
|
|||
|
//capReqPacket->IoStatus.Information = pLowIoContext->ParamsFor.IoCtl.OutputBufferLength;
|
|||
|
capReqPacket->IoStatus.Information = RxContext->InformationToReturn;
|
|||
|
break;
|
|||
|
//case STATUS(CONNECTION_INVALID:
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
capReqPacket->IoStatus.Status = Status;
|
|||
|
RxDbgTrace(-1, Dbg, ("RxLowIoIoCtlShellCompletion exit Status = %08lx\n", Status));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
|
|||
|
THIS CODE IS NOT USED CURRENTLY....IT'S BEING SAVED HERE TO MAP OVER TO HAVING RDBSS LOAD/UNLOAD EACH MINIRDR UNDER IOCTL
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxLoadMiniRdrs(
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
);
|
|||
|
VOID
|
|||
|
RxUnloadMiniRdrs(
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
NTSYSAPI
|
|||
|
NTSTATUS
|
|||
|
NTAPI
|
|||
|
ZwLoadDriver(
|
|||
|
IN PUNICODE_STRING DriverServiceName
|
|||
|
);
|
|||
|
NTSYSAPI
|
|||
|
NTSTATUS
|
|||
|
NTAPI
|
|||
|
ZwUnloadDriver(
|
|||
|
IN PUNICODE_STRING DriverServiceName
|
|||
|
);
|
|||
|
PWCHAR RxMiniRdrInfo = NULL;
|
|||
|
ULONG RxMiniRdrsLoaded = 0;
|
|||
|
|
|||
|
//CODE.IMPROVEMENT this should be allocated dynamically
|
|||
|
#define MAXIMUM_NUMBER_OF_MINIRDRS 16
|
|||
|
UNICODE_STRING RxLoadedDrivers[MAXIMUM_NUMBER_OF_MINIRDRS];
|
|||
|
PWCHAR RxLoadedDriversNameBuffer = NULL;
|
|||
|
ULONG RxNextDriverLoaded = 0;
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxFabricateRegistryStringZZ(
|
|||
|
IN OUT PUNICODE_STRING RegistryNameString,
|
|||
|
IN PUNICODE_STRING DriverName,
|
|||
|
IN OUT PVOID Buffer,
|
|||
|
IN ULONG BufferLength
|
|||
|
)
|
|||
|
{
|
|||
|
UNICODE_STRING RegistryServicePrefix;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
RegistryNameString->Buffer = (PWCHAR)Buffer;
|
|||
|
RegistryNameString->MaximumLength = (USHORT)BufferLength;
|
|||
|
|
|||
|
RtlInitUnicodeString(&RegistryServicePrefix, SERVICE_REGISTRY_KEY);
|
|||
|
|
|||
|
RtlCopyUnicodeString(RegistryNameString,&RegistryServicePrefix);
|
|||
|
|
|||
|
Status = RtlAppendUnicodeStringToString(RegistryNameString,DriverName);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RxLoadMiniRdrs(
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine does an enumeration from the registry to load the minirdrs. It saves what it finds so it
|
|||
|
can unload them later. It also initializes the structures that are used to scan over minirdrs.......
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS if at least one minirdr was loaded
|
|||
|
STATUS_INSUFFICIENT_RESOURCES if the buffer to save the names could not be allocated
|
|||
|
STATUS_UNSUCCESSFUL if no minirdrs were loaded
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Storage[256];
|
|||
|
WCHAR ServiceNameRegistryStringBuffer[256]; //bugbug allocate this!
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
PCHAR NextNameBufferPosition;
|
|||
|
HANDLE RdbssHandle = INVALID_HANDLE_VALUE;
|
|||
|
HANDLE MiniRdrsHandle = INVALID_HANDLE_VALUE;
|
|||
|
NTSTATUS Status;
|
|||
|
KEY_FULL_INFORMATION KeyInformation;
|
|||
|
PKEY_VALUE_BASIC_INFORMATION ValueInformation;
|
|||
|
ULONG DummyLength,Index;
|
|||
|
//ULONG BytesRead;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
//PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
|||
|
|
|||
|
DbgPrint("here we go\n");
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
RegistryPath, // name
|
|||
|
OBJ_CASE_INSENSITIVE, // attributes
|
|||
|
NULL, // root
|
|||
|
NULL // security descriptor
|
|||
|
);
|
|||
|
|
|||
|
Status = ZwOpenKey (&RdbssHandle, KEY_READ, &ObjectAttributes);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DbgPrint("FirstOpenFailed: %08lx %wZ\n",Status,RegistryPath);
|
|||
|
RxLogFailure (
|
|||
|
RxFileSystemDeviceObject,
|
|||
|
NULL,
|
|||
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|||
|
Status);
|
|||
|
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
RtlInitUnicodeString(&UnicodeString, L"MiniRdrs");
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&UnicodeString,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
RdbssHandle,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
Status = ZwOpenKey (&MiniRdrsHandle, KEY_READ, &ObjectAttributes);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DbgPrint("2ndOpenFailed: %08lx %wZ\n",Status,&UnicodeString);
|
|||
|
RxLogFailure (
|
|||
|
RxFileSystemDeviceObject,
|
|||
|
NULL,
|
|||
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|||
|
Status);
|
|||
|
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
Status = ZwQueryKey (MiniRdrsHandle, KeyFullInformation, &KeyInformation,sizeof(KeyInformation),&DummyLength);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DbgPrint("QueryFailed: %08lx %wZ\n",Status,&UnicodeString);
|
|||
|
RxLogFailure (
|
|||
|
RxFileSystemDeviceObject,
|
|||
|
NULL,
|
|||
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|||
|
Status);
|
|||
|
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
DbgPrint("HandleInfo %08lx %08lx %08lx\n",
|
|||
|
KeyInformation.Values,
|
|||
|
KeyInformation.MaxValueNameLen,
|
|||
|
KeyInformation.MaxValueDataLen);
|
|||
|
|
|||
|
RxLoadedDriversNameBuffer = RxAllocatePoolWithTag(PagedPool,
|
|||
|
KeyInformation.Values*KeyInformation.MaxValueNameLen,
|
|||
|
'xMxR');
|
|||
|
if (RxLoadedDriversNameBuffer==NULL) {
|
|||
|
DbgPrint("NameBufferAllocFailed: %08lx %wZ\n",Status,&UnicodeString);
|
|||
|
RxLogFailure (
|
|||
|
RxFileSystemDeviceObject,
|
|||
|
NULL,
|
|||
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|||
|
Status);
|
|||
|
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
NextNameBufferPosition = (PCHAR)RxLoadedDriversNameBuffer;
|
|||
|
ValueInformation = (PKEY_VALUE_BASIC_INFORMATION)(&Storage[0]); //this restricts the name length..we'll just skip long ones
|
|||
|
for (Index=0;Index<KeyInformation.Values;Index++) {
|
|||
|
UNICODE_STRING DriverName,RegistryNameString;
|
|||
|
NTSTATUS LoadStatus;
|
|||
|
ULONG ThisDriver;
|
|||
|
|
|||
|
LoadStatus = ZwEnumerateValueKey(MiniRdrsHandle,
|
|||
|
Index,
|
|||
|
KeyValueBasicInformation,
|
|||
|
ValueInformation,
|
|||
|
sizeof(Storage),
|
|||
|
&DummyLength);
|
|||
|
if (!NT_SUCCESS(LoadStatus)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
DriverName.Length = DriverName.MaximumLength = (USHORT)(ValueInformation->NameLength);
|
|||
|
DriverName.Buffer = &(ValueInformation->Name[0]);
|
|||
|
|
|||
|
LoadStatus = RxFabricateRegistryStringZZ(&RegistryNameString,
|
|||
|
&DriverName,
|
|||
|
&ServiceNameRegistryStringBuffer[0],
|
|||
|
sizeof(ServiceNameRegistryStringBuffer));
|
|||
|
if (!NT_SUCCESS(LoadStatus)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
DbgPrint(">>LOADING %wZ:%wZ\n",&DriverName,&RegistryNameString);
|
|||
|
LoadStatus = ZwLoadDriver(&RegistryNameString);
|
|||
|
if (!NT_SUCCESS(LoadStatus)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
ThisDriver = RxNextDriverLoaded;
|
|||
|
RxNextDriverLoaded++;
|
|||
|
RxLoadedDrivers[ThisDriver].Buffer = (PWCHAR)NextNameBufferPosition;
|
|||
|
RxLoadedDrivers[ThisDriver].Length = DriverName.MaximumLength;
|
|||
|
RxLoadedDrivers[ThisDriver].MaximumLength = DriverName.MaximumLength;
|
|||
|
RtlCopyMemory(NextNameBufferPosition,DriverName.Buffer,DriverName.MaximumLength);
|
|||
|
NextNameBufferPosition+=DriverName.MaximumLength;
|
|||
|
DbgPrint(">>SAVEDNAME %wZ:%wZ\n",&DriverName,&RxLoadedDrivers[ThisDriver]);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
FINALLY:
|
|||
|
if (MiniRdrsHandle!=INVALID_HANDLE_VALUE) ZwClose(MiniRdrsHandle);
|
|||
|
if (MiniRdrsHandle!=INVALID_HANDLE_VALUE) ZwClose(RdbssHandle);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
RxUnloadMiniRdrs();
|
|||
|
}
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
RxUnloadMiniRdrs(
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ThisDriver;
|
|||
|
WCHAR ServiceNameRegistryStringBuffer[256]; //bugbug allocate this!
|
|||
|
|
|||
|
PAGED_CODE(); //not actually in use
|
|||
|
|
|||
|
DbgPrint("here we ungo, drivertounload=%08lx\n",RxNextDriverLoaded);
|
|||
|
|
|||
|
for (ThisDriver=0;ThisDriver<RxNextDriverLoaded;ThisDriver++) {
|
|||
|
NTSTATUS LoadStatus;
|
|||
|
UNICODE_STRING RegistryNameString;
|
|||
|
DbgPrint(">>Unloading %wZ\n",&RxLoadedDrivers[ThisDriver]);
|
|||
|
LoadStatus = RxFabricateRegistryStringZZ(&RegistryNameString,
|
|||
|
&RxLoadedDrivers[ThisDriver],
|
|||
|
&ServiceNameRegistryStringBuffer[0],
|
|||
|
sizeof(ServiceNameRegistryStringBuffer));
|
|||
|
LoadStatus = ZwUnloadDriver(&RegistryNameString);
|
|||
|
DbgPrint(">>Unloaded %wZ, status =%08lx\n",&RxLoadedDrivers[ThisDriver],LoadStatus);
|
|||
|
//no status check.....can't do anything anyway!
|
|||
|
}
|
|||
|
|
|||
|
if (RxLoadedDriversNameBuffer!=NULL) RxFreePool(RxLoadedDriversNameBuffer);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#endif
|
|||
|
|