/* $Id: vbsf.c 42154 2012-07-13 23:00:53Z vboxsync $ */ /** @file * VirtualBox Windows Guest Shared Folders. * * File System Driver initialization and generic routines */ /* * Copyright (C) 2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #include "vbsf.h" /* * The current state of the driver. */ typedef enum _MRX_VBOX_STATE_ { MRX_VBOX_STARTABLE, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTED } MRX_VBOX_STATE, *PMRX_VBOX_STATE; static MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE; /* * The VBoxSF dispatch table. */ static struct _MINIRDR_DISPATCH VBoxMRxDispatch; /* * The VBoxSF device object. */ PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject; static NTSTATUS VBoxMRxFsdDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); UCHAR MajorFunctionCode = IrpSp->MajorFunction; ULONG MinorFunctionCode = IrpSp->MinorFunction; Log(("VBOXSF: MRxFsdDispatch: major %d, minor %d: %s\n", MajorFunctionCode, MinorFunctionCode, MajorFunctionString(MajorFunctionCode, MinorFunctionCode))); if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); Log(("VBOXSF: MRxFsdDispatch: Invalid device request detected %p %p\n", DeviceObject, (PDEVICE_OBJECT)VBoxMRxDeviceObject)); return STATUS_INVALID_DEVICE_REQUEST; } Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp); Log(("VBOXSF: MRxFsdDispatch: Returned 0x%X\n", Status)); return Status; } static void VBoxMRxUnload(IN PDRIVER_OBJECT DriverObject) { NTSTATUS Status; UNICODE_STRING UserModeDeviceName; Log(("VBOXSF: MRxUnload\n")); if (VBoxMRxDeviceObject) { PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension; pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT)); vboxDisconnect (&pDeviceExtension->hgcmClient); } vboxUninit(); if (VBoxMRxDeviceObject) { PRX_CONTEXT RxContext; RxContext = RxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP); if (RxContext != NULL) { Status = RxStopMinirdr(RxContext, &RxContext->PostRequest); if (Status == STATUS_SUCCESS) { MRX_VBOX_STATE State; State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED); if (State != MRX_VBOX_STARTABLE) { Status = STATUS_REDIRECTOR_STARTED; } } RxDereferenceAndDeleteRxContext(RxContext); } else { Status = STATUS_INSUFFICIENT_RESOURCES; } RxUnregisterMinirdr(VBoxMRxDeviceObject); } RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U); Status = IoDeleteSymbolicLink(&UserModeDeviceName); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: MRxUnload: IoDeleteSymbolicLink Status 0x%08X\n", Status)); } RxUnload(DriverObject); Log(("VBOXSF: MRxUnload: VBoxSF.sys driver object %p unloaded\n", DriverObject)); } static void vbsfInitMRxDispatch(void) { Log(("VBOXSF: vbsfInitMRxDispatch: Called.\n")); ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH)); VBoxMRxDispatch.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION); VBoxMRxDispatch.MRxSrvCallSize = 0; VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION); VBoxMRxDispatch.MRxVNetRootSize = 0; VBoxMRxDispatch.MRxFcbSize = 0; VBoxMRxDispatch.MRxSrvOpenSize = 0; VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX); VBoxMRxDispatch.MRxStart = VBoxMRxStart; VBoxMRxDispatch.MRxStop = VBoxMRxStop; VBoxMRxDispatch.MRxCreate = VBoxMRxCreate; VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen; VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen; VBoxMRxDispatch.MRxFlush = VBoxMRxFlush; VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate; VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx; VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen; VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb; VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx; VBoxMRxDispatch.MRxForceClosed = VBoxMRxForceClosed; VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory; VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInfo; VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInfo; VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInfoAtCleanup; VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInfo; VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInfo; VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySdInfo; VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSdInfo; VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInfo; VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl; VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory; VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub; VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub; VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest; VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot; VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot; VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot; VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState; VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName; VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall; VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify; VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall; VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile; Log(("VBOXSF: vbsfInitMRxDispatch: Success.\n")); return; } static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength) { BOOL PrefixOK; /* The FilePathName here looks like: \vboxsrv\... */ if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */ { PrefixOK = (FilePathName[0] == L'\\'); PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v'); PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b'); PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o'); PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x'); PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's'); /* Both vboxsvr & vboxsrv are now accepted */ if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v')) { PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v'); PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r'); } else { PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r'); PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v'); } if (PathNameLength > 8 * sizeof (WCHAR)) { /* There is something after '\vboxsrv'. */ PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0); } } else { PrefixOK = FALSE; } return PrefixOK; } static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS Status = STATUS_SUCCESS; QUERY_PATH_REQUEST *pReq = NULL; QUERY_PATH_REQUEST_EX *pReqEx = NULL; QUERY_PATH_RESPONSE *pResp = NULL; BOOL PrefixOK = FALSE; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); /* Make a local copy, it will be needed after the Irp completion. */ ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode; PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT)); Log(("VBOXSF: MRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n", pDevObj, pDevObj->DeviceExtension, IoControlCode)); switch (IoControlCode) { case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */ case IOCTL_REDIR_QUERY_PATH: /* XP and earlier */ { /* This IOCTL is intercepted for 2 reasons: * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them * will be routed to the VBox provider automatically without any prefix resolution * since the prefix is already in the prefix cache. * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit, * because RDBSS will not be involved then. */ const WCHAR *FilePathName = NULL; ULONG PathNameLength = 0; if (pIrp->RequestorMode != KernelMode) { /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying * that RequestorMode member of the IRP structure is KernelMode. */ Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n", pStack->Parameters.DeviceIoControl.InputBufferLength)); /* Continue to RDBSS. */ break; } if (IoControlCode == IOCTL_REDIR_QUERY_PATH) { Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess())); if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST)) { Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n", pStack->Parameters.DeviceIoControl.InputBufferLength)); /* Continue to RDBSS. */ break; } pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer; Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReq->PathNameLength)); Log(("VBOXSF: MRxDeviceControl: SecurityContext = %p.\n", pReq->SecurityContext)); Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName)); FilePathName = pReq->FilePathName; PathNameLength = pReq->PathNameLength; } else { Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: Called.\n")); if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX)) { Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n", pStack->Parameters.DeviceIoControl.InputBufferLength)); /* Continue to RDBSS. */ break; } pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer; Log(("VBOXSF: MRxDeviceControl: pSecurityContext = %p.\n", pReqEx->pSecurityContext)); Log(("VBOXSF: MRxDeviceControl: EaLength = %d.\n", pReqEx->EaLength)); Log(("VBOXSF: MRxDeviceControl: pEaBuffer = %p.\n", pReqEx->pEaBuffer)); Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReqEx->PathName.Length)); Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer)); FilePathName = pReqEx->PathName.Buffer; PathNameLength = pReqEx->PathName.Length; } pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer; PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength); Log(("VBOXSF: MRxDeviceControl PrefixOK %d\n", PrefixOK)); if (!PrefixOK) { /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN. * No need to involve RDBSS. */ Status = STATUS_BAD_NETWORK_NAME; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); Log(("VBOXSF: MRxDeviceControl: returned STATUS_BAD_NETWORK_NAME\n")); return Status; } Log(("VBOXSF: MRxDeviceControl pResp %p verifying the path.\n", pResp)); if (pResp) { /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path. * Here it is assigned to the length of \vboxsrv prefix. */ pResp->LengthAccepted = 8 * sizeof (WCHAR); Status = STATUS_SUCCESS; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); Log(("VBOXSF: MRxDeviceControl: claiming the path.\n")); return Status; } /* No pResp pointer, should not happen. Just a precaution. */ Status = STATUS_INVALID_PARAMETER; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); Log(("VBOXSF: MRxDeviceControl: returned STATUS_INVALID_PARAMETER\n")); return Status; } default: break; } /* Pass the IOCTL to RDBSS. */ if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl) { Log(("VBOXSF: MRxDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl)); Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp); Log(("VBOXSF: MRxDeviceControl RDBSS status 0x%08X\n", Status)); } else { /* No RDBSS, should not happen. Just a precaution. */ Status = STATUS_NOT_IMPLEMENTED; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); Log(("VBOXSF: MRxDeviceControl: returned STATUS_NOT_IMPLEMENTED\n")); } return Status; } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS Status; UNICODE_STRING VBoxMRxName; UNICODE_STRING UserModeDeviceName; PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension; ULONG i; int vboxRC; VBSFCLIENT hgcmClient; Log(("VBOXSF: DriverEntry: Driver object %p\n", DriverObject)); if (DriverObject == NULL) { Log(("VBOXSF: DriverEntry: driver object is NULL.\n")); return STATUS_UNSUCCESSFUL; } /* Initialize VBox subsystem. */ vboxRC = vboxInit(); if (RT_FAILURE(vboxRC)) { Log(("VBOXSF: DriverEntry: ERROR while initializing VBox subsystem (%Rrc)!\n", vboxRC)); return STATUS_UNSUCCESSFUL; } /* Connect the HGCM client */ RT_ZERO(hgcmClient); vboxRC = vboxConnect(&hgcmClient); if (RT_FAILURE(vboxRC)) { Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n", vboxRC)); vboxUninit(); return STATUS_UNSUCCESSFUL; } /* Init the driver object. */ DriverObject->DriverUnload = VBoxMRxUnload; for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch; } /* Forward to RDBSS. */ Status = RxDriverEntry(DriverObject, RegistryPath); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: DriverEntry: RxDriverEntry failed: 0x%08X\n", Status)); goto failure; } __try { Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: calling VBoxMRxDeviceObject %p\n", VBoxMRxDeviceObject)); RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U); /* Don use RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else * UNC mappings don't work (including Windows explorer browsing). */ Status = RxRegisterMinirdr(&VBoxMRxDeviceObject, DriverObject, &VBoxMRxDispatch, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS, &VBoxMRxName, sizeof(MRX_VBOX_DEVICE_EXTENSION), FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE); Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: returned 0x%08X VBoxMRxDeviceObject %p\n", Status, VBoxMRxDeviceObject)); if (Status!=STATUS_SUCCESS) { Log(("VBOXSF: DriverEntry: RxRegisterMinirdr failed: 0x%08X\n", Status )); try_return(Status); } /* Init the device extension. * NOTE: the device extension actually points to fields * in the RDBSS_DEVICE_OBJECT. Our space is past the end * of this struct!! */ pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT)); pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject; for (i = 0; i < RT_ELEMENTS(pDeviceExtension->cLocalConnections); i++) { pDeviceExtension->cLocalConnections[i] = FALSE; } /* Mutex for synchronizining our connection list */ ExInitializeFastMutex(&pDeviceExtension->mtxLocalCon); /* The device object has been created. Need to setup a symbolic * link so that the device may be accessed from a Win32 user mode * application. */ RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U); Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink\n")); Status = IoCreateSymbolicLink(&UserModeDeviceName, &VBoxMRxName); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: DriverEntry: IoCreateSymbolicLink: 0x%08X\n", Status)); try_return(Status); } Log(("VBOXSF: DriverEntry: Symbolic link created.\n")); /* * Build the dispatch tables for the minirdr */ vbsfInitMRxDispatch(); try_exit: ; } __finally { ; } if (Status != STATUS_SUCCESS) { Log(("VBOXSF: DriverEntry: VBoxSF.sys failed to start with Status = 0x%08X\n", Status)); goto failure; } pDeviceExtension->hgcmClient = hgcmClient; /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution * by other redirectors. These additional name resolutions cause long delays. */ Log(("VBOXSF: DriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n", VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension)); pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl; /* @todo start the redirector here RxStartMiniRdr. */ Log(("VBOXSF: DriverEntry: Init successful!\n")); return STATUS_SUCCESS; failure: Log(("VBOXSF: DriverEntry: Failure! Status = 0x%08X\n", Status)); vboxDisconnect(&hgcmClient); vboxUninit(); if (VBoxMRxDeviceObject) { RxUnregisterMinirdr(VBoxMRxDeviceObject); VBoxMRxDeviceObject = NULL; } return Status; } NTSTATUS VBoxMRxStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject) { NTSTATUS Status; MRX_VBOX_STATE CurrentState; Log(("VBOXSF: MRxStart\n")); CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS); if (CurrentState == MRX_VBOX_START_IN_PROGRESS) { Log(("VBOXSF: MRxStart: Start in progress -> started\n")); Status = STATUS_SUCCESS; } else if (VBoxMRxState == MRX_VBOX_STARTED) { Log(("VBOXSF: MRxStart: Already started\n")); Status = STATUS_REDIRECTOR_STARTED; } else { Log(("VBOXSF: MRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState)); Status = STATUS_UNSUCCESSFUL; } return Status; } NTSTATUS VBoxMRxStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject) { Log(("VBOXSF: MRxStop\n")); return STATUS_SUCCESS; } NTSTATUS VBoxMRxIoCtl(IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxIoCtl: IoControlCode = 0x%08X\n", RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode)); return STATUS_INVALID_DEVICE_REQUEST; } NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor); NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext) { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFobx; PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext); PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; Log(("VBOXSF: MRxDevFcbXXXControlFile: MajorFunction = 0x%02X\n", RxContext->MajorFunction)); switch (RxContext->MajorFunction) { case IRP_MJ_FILE_SYSTEM_CONTROL: { Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: 0x%08X\n", LowIoContext->ParamsFor.FsCtl.MinorFunction)); Status = STATUS_INVALID_DEVICE_REQUEST; break; } case IRP_MJ_DEVICE_CONTROL: { switch (LowIoContext->ParamsFor.IoCtl.IoControlCode) { case IOCTL_MRX_VBOX_ADDCONN: { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n")); Status = vbsfCreateConnection(RxContext, &RxContext->PostRequest); } break; case IOCTL_MRX_VBOX_DELCONN: { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n")); Status = vbsfDeleteConnection(RxContext, &RxContext->PostRequest); } break; case IOCTL_MRX_VBOX_GETLIST: { ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n")); if (NULL == pDeviceExtension) { RxContext->InformationToReturn = 0; break; } if ((cbOut >= _MRX_MAX_DRIVE_LETTERS) && (NULL != pu8Out)) { BOOLEAN fLocked = FALSE; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n")); fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon); RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS); if (fLocked) { ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); } RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS; } else { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: cbOut is too small %d bytes\n", cbOut)); RxContext->InformationToReturn = 0; } Status = STATUS_SUCCESS; break; } /* * Returns the root IDs of shared folder mappings. */ case IOCTL_MRX_VBOX_GETGLOBALLIST: { ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n")); RxContext->InformationToReturn = 0; if (NULL == pDeviceExtension) { break; } if ((cbOut >= _MRX_MAX_DRIVE_LETTERS) && (NULL != pu8Out)) { SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS]; uint32_t cMappings = RT_ELEMENTS(mappings); int vboxRC = vboxCallQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings); if (vboxRC == VINF_SUCCESS) { uint32_t i; RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS); for (i = 0; i < RT_MIN(cMappings, cbOut); i++) { pu8Out[i] = mappings[i].root; pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */ } RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS; } else { Status = VBoxErrorToNTStatus(vboxRC); Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n", Status)); } } Status = STATUS_SUCCESS; break; } /* * Translates a local connection name (e.g. drive "S:") to the * corresponding remote name (e.g. \\vboxsrv\share). */ case IOCTL_MRX_VBOX_GETCONN: { ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength; PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer; ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, RemoteName = 0x%p, Len = %d\n", cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, pwcRemoteName, cbRemoteName)); if (NULL == pDeviceExtension) { Status = STATUS_INVALID_PARAMETER; break; } Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n")); if ((cbConnectName > sizeof(WCHAR)) && (NULL != pwcConnectName)) { ULONG cbLocalConnectionName; uint32_t idx = *pwcConnectName - L'A'; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index = %d\n", idx)); if (idx >= RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName)) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n")); Status = STATUS_INVALID_PARAMETER; break; } ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon); if (NULL == pDeviceExtension->wszLocalConnectionName[idx]) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n")); ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); Status = STATUS_BAD_NETWORK_NAME; break; } cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n", cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer)); if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName)) { RtlZeroMemory(pwcRemoteName, cbRemoteName); RtlCopyMemory(pwcRemoteName, pDeviceExtension->wszLocalConnectionName[idx]->Buffer, cbLocalConnectionName); Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n", cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName)); RxContext->InformationToReturn = cbLocalConnectionName; } else { Status = STATUS_BUFFER_TOO_SMALL; RxContext->InformationToReturn = cbLocalConnectionName; } ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); } else { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: bad connect name!n")); Status = STATUS_BAD_NETWORK_NAME; } break; } case IOCTL_MRX_VBOX_GETGLOBALCONN: { ULONG ReturnedSize = 0; uint8_t *pConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer; ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer; int vboxRC; PSHFLSTRING pString; uint32_t cbString; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d, RemoteName = 0x%x, Len = %d\n", *pConnectId, pwcRemoteName, cbRemoteName)); cbString = sizeof(SHFLSTRING) + cbRemoteName; pString = (PSHFLSTRING)vbsfAllocNonPagedMem(cbString); if (!pString) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } memset(pString, 0, cbString); ShflStringInitBuffer(pString, cbRemoteName); vboxRC = vboxCallQueryMapName(&pDeviceExtension->hgcmClient, (*pConnectId) & ~0x80 /** @todo fix properly */, pString, cbString); if ( vboxRC == VINF_SUCCESS && pString->u16Length < cbRemoteName) { ReturnedSize = pString->u16Length; RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length); Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n", ReturnedSize / sizeof(WCHAR), pwcRemoteName, ReturnedSize)); Status = STATUS_SUCCESS; } else { Status = STATUS_BAD_NETWORK_NAME; } vbsfFreeNonPagedMem(pString); RxContext->InformationToReturn = ReturnedSize; } break; case IOCTL_MRX_VBOX_START: { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n", capFobx)); Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n", IoGetCurrentProcess(), RxGetRDBSSProcess())); switch (VBoxMRxState) { case MRX_VBOX_STARTABLE: Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n")); if (capFobx) { Status = STATUS_INVALID_DEVICE_REQUEST; break;; } InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE); case MRX_VBOX_START_IN_PROGRESS: Status = RxStartMinirdr(RxContext, &RxContext->PostRequest); Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n", Status, RxContext->PostRequest)); if (Status == STATUS_REDIRECTOR_STARTED) { Status = STATUS_SUCCESS; break; } if ( Status == STATUS_PENDING && RxContext->PostRequest == TRUE) { /* Will be restarted in RDBSS process. */ Status = STATUS_MORE_PROCESSING_REQUIRED; break; } /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */ if (Status == STATUS_SUCCESS) { SECURITY_DESCRIPTOR SecurityDescriptor; OBJECT_ATTRIBUTES InitializedAttributes; HANDLE hDevice; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING UserModeDeviceName; RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U); /* Create empty security descriptor */ RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor)); Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n", Status)); return Status; } RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes)); InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0); /* Open our symbolic link device name */ Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n", DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status)); return Status; } /* Override the discretionary access control list (DACL) settings */ Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n", Status)); return Status; } Status = ZwClose(hDevice); if (Status != STATUS_SUCCESS) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n", Status)); return Status; } } break; case MRX_VBOX_STARTED: Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n")); Status = STATUS_SUCCESS; break; default: Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n", VBoxMRxState)); Status = STATUS_INVALID_PARAMETER; break; } Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n", Status)); break; } case IOCTL_MRX_VBOX_STOP: { MRX_VBOX_STATE CurrentState; Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n", capFobx)); if (capFobx) { Status = STATUS_INVALID_DEVICE_REQUEST; break; } if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) { Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n", RxContext->RxDeviceObject->NumberOfActiveFcbs)); Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES; break; } CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED); Status = RxStopMinirdr(RxContext, &RxContext->PostRequest); Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n", Status)); if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE) { Status = STATUS_MORE_PROCESSING_REQUIRED; } } break; default: Status = STATUS_INVALID_DEVICE_REQUEST; break; } break; } case IRP_MJ_INTERNAL_DEVICE_CONTROL: { Status = STATUS_INVALID_DEVICE_REQUEST; break; } default: Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n", RxContext->MajorFunction)); Status = STATUS_INVALID_DEVICE_REQUEST; break; } Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n", Status, RxContext->InformationToReturn)); return Status; } static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle = INVALID_HANDLE_VALUE; Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n", ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer)); /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */ InitializeObjectAttributes(&ObjectAttributes, ConnectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateFile(&Handle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if ( Status != STATUS_SUCCESS || Handle == INVALID_HANDLE_VALUE) { Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n", Status)); Handle = INVALID_HANDLE_VALUE; } return Handle; } NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) { NTSTATUS Status = STATUS_SUCCESS; PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension; PLOWIO_CONTEXT LowIoContext; ULONG cbConnectName; PWCHAR pwcConnectName; HANDLE Handle; UNICODE_STRING FileName; Log(("VBOXSF: vbsfCreateConnection\n")); if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT)) { Log(("VBOXSF: vbsfCreateConnection: post to file system process\n")); *PostToFsp = TRUE; return STATUS_PENDING; } pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext); LowIoContext = &RxContext->LowIoContext; cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength; pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer; if (pDeviceExtension == NULL) { return STATUS_INVALID_PARAMETER; } if (cbConnectName == 0 || pwcConnectName == NULL) { Log(("VBOXSF: vbsfCreateConnection: Connection name / length is invalid!\n")); return STATUS_INVALID_PARAMETER; } Log(("VBOXSF: vbsfCreateConnection: Name = %.*ls, Len = %d\n", cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName)); FileName.Buffer = pwcConnectName; FileName.Length = (USHORT)cbConnectName; FileName.MaximumLength = (USHORT)cbConnectName; Handle = vbsfOpenConnectionHandle(&FileName); if (Handle != INVALID_HANDLE_VALUE) { PWCHAR pwc; ULONG i; ZwClose(Handle); /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */ pwc = pwcConnectName; for (i = 0; i < cbConnectName; i += sizeof(WCHAR)) { if (*pwc == L':') { break; } pwc++; } if (i >= sizeof(WCHAR) && i < cbConnectName) { pwc--; /* Go back to the drive letter, "X" for example. */ if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */ { uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */ if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections)) { Log(("VBOXSF: vbsfCreateConnection: Index 0x%x is invalid!\n", idx)); Status = STATUS_BAD_NETWORK_NAME; } else { ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon); if (pDeviceExtension->wszLocalConnectionName[idx] != NULL) { Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d is NOT empty!\n", idx)); } pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName); if (pDeviceExtension->wszLocalConnectionName[idx] == NULL) { Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n", idx)); Status = STATUS_INSUFFICIENT_RESOURCES; } else { PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx]; pRemoteName->Buffer = (PWSTR)(pRemoteName + 1); pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR)); pRemoteName->MaximumLength = pRemoteName->Length; RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length); Log(("VBOXSF: vbsfCreateConnection: RemoteName %.*ls, Len = %d\n", pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length)); pDeviceExtension->cLocalConnections[idx] = TRUE; } ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); } } } else { Log(("VBOXSF: vbsfCreateConnection: bad format\n")); Status = STATUS_BAD_NETWORK_NAME; } } else { Log(("VBOXSF: vbsfCreateConnection: connection was not found\n")); Status = STATUS_BAD_NETWORK_NAME; } return Status; } NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) { NTSTATUS Status; UNICODE_STRING FileName; HANDLE Handle; PLOWIO_CONTEXT LowIoContext; PWCHAR pwcConnectName; ULONG cbConnectName; PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension; if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT)) { Log(("VBOXSF: vbsfDeleteConnection: post to file system process\n")); *PostToFsp = TRUE; return STATUS_PENDING; } LowIoContext = &RxContext->LowIoContext; pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer; cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength; pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext); Log(("VBOXSF: vbsfDeleteConnection: pwcConnectName = %.*ls\n", cbConnectName / sizeof(WCHAR), pwcConnectName)); FileName.Buffer = pwcConnectName; FileName.Length = (USHORT)cbConnectName; FileName.MaximumLength = (USHORT)cbConnectName; Handle = vbsfOpenConnectionHandle(&FileName); if (Handle != INVALID_HANDLE_VALUE) { PFILE_OBJECT pFileObject; Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL); Log(("VBOXSF: vbsfDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n", Status)); if (NT_SUCCESS(Status)) { PFOBX Fobx = (PFOBX)pFileObject->FsContext2; if (NodeType(Fobx) == RDBSS_NTC_V_NETROOT) { PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx; Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE); } else { Log(("VBOXSF: vbsfDeleteConnection: wrong FsContext2\n")); Status = STATUS_INVALID_DEVICE_REQUEST; } ObDereferenceObject(pFileObject); } ZwClose(Handle); } if (NT_SUCCESS(Status)) { PWCHAR pwc; ULONG i; /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */ pwc = pwcConnectName; for (i = 0; i < cbConnectName; i += sizeof(WCHAR)) { if (*pwc == L':') { break; } pwc++; } if (i >= sizeof(WCHAR) && i < cbConnectName) { pwc--; if (*pwc >= L'A' && *pwc <= L'Z') { uint32_t idx = *pwc - L'A'; if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections)) { Log(("VBOXSF: vbsfDeleteConnection: Index 0x%x is invalid!\n", idx)); Status = STATUS_BAD_NETWORK_NAME; } else { ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon); pDeviceExtension->cLocalConnections[idx] = FALSE; /* Free saved name */ if (pDeviceExtension->wszLocalConnectionName[idx]) { vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]); pDeviceExtension->wszLocalConnectionName[idx] = NULL; } ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); } } } else { Log(("VBOXSF: vbsfCreateConnection: bad format\n")); Status = STATUS_BAD_NETWORK_NAME; } } return Status; } NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n", RxContext->Info.LengthRemaining)); return STATUS_SUCCESS; } NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxSetEaInfo\n")); return STATUS_NOT_IMPLEMENTED; } NTSTATUS VBoxMRxFsCtl (IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxFsCtl\n")); return STATUS_INVALID_DEVICE_REQUEST; } NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxNotifyChangeDirectory\n")); return STATUS_NOT_IMPLEMENTED; } NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext) { Log(("VBOXSF: MRxQuerySdInfo\n")); return STATUS_NOT_IMPLEMENTED; } NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext) { Log(("VBOXSF: MRxSetSdInfo\n")); return STATUS_NOT_IMPLEMENTED; } /* * WML stubs which are referenced by rdbsslib. */ NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp) { return STATUS_WMI_GUID_NOT_FOUND; } ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...) { return STATUS_SUCCESS; }