devfcb.c revision 78a072e1b56619e3230735ae073668311232ec94
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
Abstract:
This module implements the mechanism for deleting an established connection
--*/
#include "precomp.h"
#pragma hdrstop
#include "rdbss_vbox.h"
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_DEVFCB)
//#define FIXED_CONNECT_NAME L"\\;0:\\vboxsvr\\share"
#define FIXED_CONNECT_NAME L"\\;0:"
#ifdef ALLOC_PRAGMA
#endif
ZwSetSecurityObject (IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor);
/*++
Routine Description:
This routine handles all the device FCB related FSCTL's in the mini rdr
Arguments:
RxContext - Describes the Fsctl and Context.
Return Value:
a valid NTSTATUS code.
Notes:
--*/
{
ULONG ControlCode = 0;
switch (MajorFunctionCode)
{
{
{
case IRP_MN_USER_FS_REQUEST:
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: ControlCode = %x\n", ControlCode));
break;
default: //minor function != IRP_MN_USER_FS_REQUEST
break;
}
break;
}
case IRP_MJ_DEVICE_CONTROL:
{
switch (ControlCode)
{
case IOCTL_MRX_VBOX_ADDCONN:
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
break;
case IOCTL_MRX_VBOX_DELCONN:
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
break;
case IOCTL_MRX_VBOX_GETLIST:
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections ...\n"));
if (NULL == pDeviceExtension)
break;
if (GotMutex)
}
else
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Nothing to copy, cbOut is too small (%d bytes)\n", cbOut));
RxContext->InformationToReturn = 0;
}
break;
}
/*
* Returns the root IDs of shared folder mappings.
*/
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
if (NULL == pDeviceExtension)
break;
RxContext->InformationToReturn = 0;
{
int vboxRC;
if (vboxRC == VINF_SUCCESS)
{
uint32_t i;
{
}
}
else
{
}
}
break;
}
/*
* Translates a local connection name (e.g. drive "S:") to the
* corresponding remote name (e.g. \\vboxsrv\share).
*/
case IOCTL_MRX_VBOX_GETCONN:
{
Log(
("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, RemoteName = 0x%x, Len = %d\n", ulConnectNameLen / sizeof(WCHAR), pwcConnectName, ulConnectNameLen, pulRemoteName, ulRemoteNameLen));
if (NULL == pDeviceExtension)
{
break;
}
/* Insert the local connection name. */
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections ...\n"));
{
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
break;
}
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
break;
}
Log(
("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n", ulLocalConnectionNameLen / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
{
RtlCopyMemory (pulRemoteName, pDeviceExtension->wszLocalConnectionName[idx]->Buffer, ulLocalConnectionNameLen);
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Size = %d\n", ulLocalConnectionNameLen / sizeof(WCHAR), pulRemoteName, ulLocalConnectionNameLen));
}
else
{
}
}
else
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: No connection name found!\n"));
}
break;
}
{
ULONG ReturnedSize = 0;
int vboxRC;
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d, RemoteName = 0x%x, Len = %d\n", *pConnectId, RemoteName, RemoteNameLen));
if (!pString)
{
break;
}
ShflStringInitBuffer(pString, RemoteNameLen); /** @todo r=andy This function does not have an effect ...? */
vboxRC = vboxCallQueryMapName(&pDeviceExtension->hgcmClient, (*pConnectId) & ~0x80 /** @todo fix properly */, pString, cbString);
if (vboxRC == VINF_SUCCESS)
{
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Size = %d\n", ReturnedSize / sizeof(WCHAR), RemoteName, ReturnedSize));
}
}
else
if (ReturnedSize)
{
}
else
{
}
break;
}
case IOCTL_MRX_VBOX_START:
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Called.\n"));
switch (VBoxMRxState)
{
case MRX_VBOX_STARTABLE:
/* The correct sequence of start events issued by the workstation
service would have avoided this. We can recover from this
by actually invoking RxStartMiniRdr. */
if (capFobx)
{
break;;
}
/* Set global VBoxMRxState variable to MRX_VBOX_STARTABLE and fall through to the next case. */
/* Lack of break is intentional. */
if (Status == STATUS_REDIRECTOR_STARTED)
/* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
if (Status == STATUS_SUCCESS)
{
/* Create empty security descriptor */
if (Status != STATUS_SUCCESS)
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%x!\n", Status));
return Status;
}
/* Open our symbolic link device name */
if (Status != STATUS_SUCCESS)
{
Log(
("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%x!\n", DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
return Status;
}
/* Override the discretionary access control list (DACL) settings */
if (Status != STATUS_SUCCESS)
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%x!\n", Status));
return Status;
}
if (Status != STATUS_SUCCESS)
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%x\n", Status));
return Status;
}
}
break;
case MRX_VBOX_STARTED:
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
break;
default:
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n", VBoxMRxState));
break;
}
break;
}
case IOCTL_MRX_VBOX_STOP:
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Called.\n"));
if (capFobx)
{
break;
}
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n", RxContext->RxDeviceObject->NumberOfActiveFcbs));
break;
}
CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
break;
}
default:
break;
}
break;
}
{
break;
}
default:
AssertMsgFailed(("VBOXSF: VBoxMRxDevFcbXXXControlFile: Unimplemented major function!"));
break;
}
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: Status = %08lx, Info = %08lx\n", Status, RxContext->InformationToReturn));
return Status;
}
{
#ifndef VBOX
#endif
// Connection name should get checked to be certain our device is in the path
Log(("VBOXSF: GetConnectionHandle: Called.\n"));
Status = ZwCreateFile(&Handle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, // Allocation size
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT, NULL, // Ptr to EA Buffer
0); // Length of EA buffer
{
Log(("VBOXSF: GetConnectionHandle: ZwCreateFile returned success\n"));
}
else
{
Log(("VBOXSF: GetConnectionHandle: ZwCreateFile returned invalid handle!\n"));
}
return Handle;
}
{
if (NULL == pDeviceExtension)
return STATUS_INVALID_PARAMETER;
{
Log(("VBOXSF: DoCreateConnection: Connection name / length is invalid!\n"));
return STATUS_INVALID_PARAMETER;
}
// The sample code passes in only the filename in the Ioctl data buffer.
// An actual implementation could pass in stuff like EAs, security
// credentials, etc
Log(("VBOXSF: DoCreateConnection: Name = %.*ls, Length = %d\n", ConnectNameLen / sizeof(WCHAR), ConnectName, ConnectNameLen));
if (INVALID_HANDLE_VALUE != Handle)
{
ULONG i;
Log(("VBOXSF: DoCreateConnection: GetConnectionHandle returned success!\n"));
/* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
;
if (i >= sizeof(WCHAR) && i < ConnectNameLen)
{
pwcLC--; /* Go back to the drive letter, "X" for example. */
{
{
Log(("VBOXSF: VBoxMRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
return STATUS_BAD_NETWORK_NAME;
}
/*pDeviceExtension->LocalConnectionName[idx] = (PUNICODE_STRING)ExAllocatePool(PagedPool, sizeof(UNICODE_STRING) + ConnectNameLen /* more than enough );*/
pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + ConnectNameLen);
Log(("VBOXSF: DoCreateConnection: RemoteName %.*ls, Len = %d\n", pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
}
}
}
else
{
Log(("VBOXSF: DoCreateConnection: GetConnectionHandle returned failure!\n"));
}
return (Status);
}
/*++
Routine Description:
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
Return Value:
RXSTATUS
--*/
{
PAGED_CODE();
Log(("VBOXSF: VBoxMRxCreateConnection: Called.\n"));
if (!Wait)
{
//just post right now!
return STATUS_PENDING;
}
return Status;
}
{
Log(("VBOXSF: DoDeleteConnection: Called.\n"));
if (INVALID_HANDLE_VALUE != Handle)
{
Log(("VBOXSF: DoDeleteConnection: GetConnectionHandle returned success\n"));
if (NT_SUCCESS(Status))
{
// Got the FileObject. Now get an Fobx
{
Log(("Calling RxFinalizeConnection\n"));
}
else
{
}
}
}
return Status;
}
/*++
Routine Description:
This routine deletes a single vnetroot.
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
Return Value:
RXSTATUS
--*/
{
PAGED_CODE();
Log(("VBOXSF: VBoxMRxDeleteConnection: ConnectName = %.*ls\n", ConnectNameLen / sizeof(WCHAR), ConnectName));
if (!Wait)
{
//just post right now!
return (STATUS_PENDING);
}
if (NT_SUCCESS(Status))
{
ULONG i;
;
if (i >= sizeof(WCHAR) && i < ConnectNameLen)
{
pwcLC--;
{
/* Free saved name */
/*Assert(pDeviceExtension->LocalConnectionName[idx]);
ExFreePool(pDeviceExtension->LocalConnectionName[idx]);
pDeviceExtension->LocalConnectionName[idx] = NULL;*/
{
}
}
}
}
return Status;
}