/*++ 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;IndexNameLength); 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>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