VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp@ 78562

Last change on this file since 78562 was 78562, checked in by vboxsync, 6 years ago

winnt/vboxsf: Must initialize IPRT. Duh! bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 70.9 KB
Line 
1/* $Id: vbsf.cpp 78562 2019-05-17 11:36:45Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - File System Driver initialization and generic routines
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "vbsf.h"
23#include <iprt/initterm.h>
24
25
26/*********************************************************************************************************************************
27* Structures and Typedefs *
28*********************************************************************************************************************************/
29/**
30 * The current state of the driver.
31 */
32typedef enum _MRX_VBOX_STATE_
33{
34 MRX_VBOX_STARTABLE,
35 MRX_VBOX_START_IN_PROGRESS,
36 MRX_VBOX_STARTED
37} MRX_VBOX_STATE, *PMRX_VBOX_STATE;
38
39
40/*********************************************************************************************************************************
41* Global Variables *
42*********************************************************************************************************************************/
43static MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE;
44
45/**
46 * The VBoxSF dispatch table.
47 */
48static struct _MINIRDR_DISPATCH VBoxMRxDispatch;
49
50/**
51 * The VBoxSF device object.
52 */
53PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
54
55/** The shared folder service client structure. */
56VBGLSFCLIENT g_SfClient;
57/** VMMDEV_HVF_XXX (set during init). */
58uint32_t g_fHostFeatures = 0;
59/** Last valid shared folders function number. */
60uint32_t g_uSfLastFunction = SHFL_FN_SET_FILE_SIZE;
61/** Shared folders features (SHFL_FEATURE_XXX). */
62uint64_t g_fSfFeatures = 0;
63
64
65/*********************************************************************************************************************************
66* Exported Functions *
67*********************************************************************************************************************************/
68RT_C_DECLS_BEGIN
69NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
70RT_C_DECLS_END
71
72
73static NTSTATUS VBoxMRxFsdDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
74{
75 NTSTATUS Status;
76#ifdef LOG_ENABLED
77 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
78 Log(("VBOXSF: MRxFsdDispatch: major %d, minor %d: %s\n",
79 IrpSp->MajorFunction, IrpSp->MinorFunction, vbsfNtMajorFunctionName(IrpSp->MajorFunction, IrpSp->MinorFunction)));
80#endif
81
82 if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject)
83 {
84 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
85 Irp->IoStatus.Information = 0;
86 IoCompleteRequest(Irp, IO_NO_INCREMENT);
87
88 Log(("VBOXSF: MRxFsdDispatch: Invalid device request detected %p %p\n",
89 DeviceObject, (PDEVICE_OBJECT)VBoxMRxDeviceObject));
90
91 return STATUS_INVALID_DEVICE_REQUEST;
92 }
93
94 Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp);
95 Log(("VBOXSF: MRxFsdDispatch: Returned 0x%X\n", Status));
96 return Status;
97}
98
99static void VBoxMRxUnload(IN PDRIVER_OBJECT DriverObject)
100{
101 NTSTATUS Status;
102 UNICODE_STRING UserModeDeviceName;
103
104 Log(("VBOXSF: MRxUnload\n"));
105
106 if (VBoxMRxDeviceObject)
107 {
108 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
109 pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
110 }
111
112 if (VBoxMRxDeviceObject)
113 {
114 PRX_CONTEXT RxContext;
115 RxContext = RxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP);
116
117 if (RxContext != NULL)
118 {
119 Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
120
121 if (Status == STATUS_SUCCESS)
122 {
123 MRX_VBOX_STATE State;
124
125 State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
126
127 if (State != MRX_VBOX_STARTABLE)
128 Status = STATUS_REDIRECTOR_STARTED;
129 }
130
131 RxDereferenceAndDeleteRxContext(RxContext);
132 }
133 else
134 Status = STATUS_INSUFFICIENT_RESOURCES;
135
136 RxUnregisterMinirdr(VBoxMRxDeviceObject);
137 }
138
139 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
140 Status = IoDeleteSymbolicLink(&UserModeDeviceName);
141 if (Status != STATUS_SUCCESS)
142 Log(("VBOXSF: MRxUnload: IoDeleteSymbolicLink Status 0x%08X\n", Status));
143
144 RxUnload(DriverObject);
145
146 VbglR0SfDisconnect(&g_SfClient);
147 VbglR0SfTerm();
148
149 Log(("VBOXSF: MRxUnload: VBoxSF.sys driver object %p almost unloaded, just RTR0Term left...\n", DriverObject));
150 RTR0Term(); /* No logging after this. */
151}
152
153static void vbsfInitMRxDispatch(void)
154{
155 Log(("VBOXSF: vbsfInitMRxDispatch: Called.\n"));
156
157 ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
158
159 VBoxMRxDispatch.MRxFlags = RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FCB_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION;
160
161 VBoxMRxDispatch.MRxSrvCallSize = 0;
162 VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION);
163 VBoxMRxDispatch.MRxVNetRootSize = 0;
164 VBoxMRxDispatch.MRxFcbSize = sizeof(VBSFNTFCBEXT);
165 VBoxMRxDispatch.MRxSrvOpenSize = 0;
166 VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX);
167
168 VBoxMRxDispatch.MRxStart = VBoxMRxStart;
169 VBoxMRxDispatch.MRxStop = VBoxMRxStop;
170
171 VBoxMRxDispatch.MRxCreate = VBoxMRxCreate;
172 VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen;
173 VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen;
174 VBoxMRxDispatch.MRxFlush = VBoxMRxFlush;
175 VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate;
176 VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx;
177 VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen;
178 VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb;
179 VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx;
180 VBoxMRxDispatch.MRxForceClosed = VBoxMRxForceClosed;
181
182 VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory;
183 VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInfo;
184 VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInfo;
185 VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInfoAtCleanup;
186 VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInfo;
187 VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInfo;
188 VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySdInfo;
189 VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSdInfo;
190 VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInfo;
191
192 VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState;
193
194 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead;
195 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite;
196 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks;
197 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks;
198 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks;
199 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks;
200 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl;
201 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl;
202 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory;
203
204 VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub;
205 VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub;
206 VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest;
207
208 VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot;
209 VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot;
210 VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot;
211 VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState;
212 VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName;
213
214 VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall;
215 VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify;
216 VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall;
217
218 VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile;
219
220 Log(("VBOXSF: vbsfInitMRxDispatch: Success.\n"));
221 return;
222}
223
224static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength)
225{
226 BOOL PrefixOK;
227
228 /* The FilePathName here looks like: \vboxsrv\... */
229 if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */
230 {
231 PrefixOK = (FilePathName[0] == L'\\');
232 PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v');
233 PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b');
234 PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o');
235 PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x');
236 PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's');
237 /* Both vboxsvr & vboxsrv are now accepted */
238 if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v'))
239 {
240 PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v');
241 PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r');
242 }
243 else
244 {
245 PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r');
246 PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v');
247 }
248 if (PathNameLength > 8 * sizeof (WCHAR))
249 {
250 /* There is something after '\vboxsrv'. */
251 PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0);
252 }
253 }
254 else
255 PrefixOK = FALSE;
256
257 return PrefixOK;
258}
259
260static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
261{
262 NTSTATUS Status = STATUS_SUCCESS;
263
264 QUERY_PATH_REQUEST *pReq = NULL;
265 QUERY_PATH_REQUEST_EX *pReqEx = NULL;
266 QUERY_PATH_RESPONSE *pResp = NULL;
267
268 BOOL PrefixOK = FALSE;
269
270 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
271
272 /* Make a local copy, it will be needed after the Irp completion. */
273 ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
274
275 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
276
277 Log(("VBOXSF: MRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n",
278 pDevObj, pDevObj->DeviceExtension, IoControlCode));
279
280 switch (IoControlCode)
281 {
282 case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */
283 case IOCTL_REDIR_QUERY_PATH: /* XP and earlier */
284 {
285 /* This IOCTL is intercepted for 2 reasons:
286 * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them
287 * will be routed to the VBox provider automatically without any prefix resolution
288 * since the prefix is already in the prefix cache.
289 * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit,
290 * because RDBSS will not be involved then.
291 */
292
293 const WCHAR *FilePathName = NULL;
294 ULONG PathNameLength = 0;
295
296 if (pIrp->RequestorMode != KernelMode)
297 {
298 /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying
299 * that RequestorMode member of the IRP structure is KernelMode.
300 */
301 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n",
302 pStack->Parameters.DeviceIoControl.InputBufferLength));
303 /* Continue to RDBSS. */
304 break;
305 }
306
307 if (IoControlCode == IOCTL_REDIR_QUERY_PATH)
308 {
309 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess()));
310
311 if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST))
312 {
313 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n",
314 pStack->Parameters.DeviceIoControl.InputBufferLength));
315 /* Continue to RDBSS. */
316 break;
317 }
318
319 pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
320
321 Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReq->PathNameLength));
322 Log(("VBOXSF: MRxDeviceControl: SecurityContext = %p.\n", pReq->SecurityContext));
323 Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName));
324
325 FilePathName = pReq->FilePathName;
326 PathNameLength = pReq->PathNameLength;
327 }
328 else
329 {
330 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: Called.\n"));
331
332 if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX))
333 {
334 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n",
335 pStack->Parameters.DeviceIoControl.InputBufferLength));
336 /* Continue to RDBSS. */
337 break;
338 }
339
340 pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
341
342 Log(("VBOXSF: MRxDeviceControl: pSecurityContext = %p.\n", pReqEx->pSecurityContext));
343 Log(("VBOXSF: MRxDeviceControl: EaLength = %d.\n", pReqEx->EaLength));
344 Log(("VBOXSF: MRxDeviceControl: pEaBuffer = %p.\n", pReqEx->pEaBuffer));
345 Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReqEx->PathName.Length));
346 Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer));
347
348 FilePathName = pReqEx->PathName.Buffer;
349 PathNameLength = pReqEx->PathName.Length;
350 }
351
352 pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer;
353
354 PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength);
355 Log(("VBOXSF: MRxDeviceControl PrefixOK %d\n", PrefixOK));
356
357 if (!PrefixOK)
358 {
359 /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN.
360 * No need to involve RDBSS.
361 */
362 Status = STATUS_BAD_NETWORK_NAME;
363
364 pIrp->IoStatus.Status = Status;
365 pIrp->IoStatus.Information = 0;
366
367 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
368
369 Log(("VBOXSF: MRxDeviceControl: returned STATUS_BAD_NETWORK_NAME\n"));
370 return Status;
371 }
372
373 Log(("VBOXSF: MRxDeviceControl pResp %p verifying the path.\n", pResp));
374 if (pResp)
375 {
376 /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path.
377 * Here it is assigned to the length of \vboxsrv prefix.
378 */
379 pResp->LengthAccepted = 8 * sizeof (WCHAR);
380
381 Status = STATUS_SUCCESS;
382
383 pIrp->IoStatus.Status = Status;
384 pIrp->IoStatus.Information = 0;
385
386 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
387
388 Log(("VBOXSF: MRxDeviceControl: claiming the path.\n"));
389 return Status;
390 }
391
392 /* No pResp pointer, should not happen. Just a precaution. */
393 Status = STATUS_INVALID_PARAMETER;
394
395 pIrp->IoStatus.Status = Status;
396 pIrp->IoStatus.Information = 0;
397
398 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
399
400 Log(("VBOXSF: MRxDeviceControl: returned STATUS_INVALID_PARAMETER\n"));
401 return Status;
402 }
403
404 default:
405 break;
406 }
407
408 /* Pass the IOCTL to RDBSS. */
409 if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl)
410 {
411 Log(("VBOXSF: MRxDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl));
412 Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp);
413 Log(("VBOXSF: MRxDeviceControl RDBSS status 0x%08X\n", Status));
414 }
415 else
416 {
417 /* No RDBSS, should not happen. Just a precaution. */
418 Status = STATUS_NOT_IMPLEMENTED;
419
420 pIrp->IoStatus.Status = Status;
421 pIrp->IoStatus.Information = 0;
422
423 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
424
425 Log(("VBOXSF: MRxDeviceControl: returned STATUS_NOT_IMPLEMENTED\n"));
426 }
427
428 return Status;
429}
430
431/**
432 * Intercepts IRP_MJ_CREATE to workaround a RDBSS quirk.
433 *
434 * Our RDBSS library will return STATUS_OBJECT_NAME_INVALID when FILE_NON_DIRECTORY_FILE
435 * is set and the path ends with a slash. NTFS and FAT will fail with
436 * STATUS_OBJECT_NAME_NOT_FOUND if the final component does not exist or isn't a directory,
437 * STATUS_OBJECT_PATH_NOT_FOUND if some path component doesn't exist or isn't a directory,
438 * or STATUS_ACCESS_DENIED if the final component is a directory.
439 *
440 * So, our HACK is to drop the trailing slash and set an unused flag in the ShareAccess
441 * parameter to tell vbsfProcessCreate about it.
442 *
443 */
444static NTSTATUS VBoxHookMjCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
445{
446 PMRX_VBOX_DEVICE_EXTENSION pDevExt = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
447 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
448 PFILE_OBJECT pFileObj = pStack->FileObject;
449 NTSTATUS rcNt;
450
451 Log(("VBOXSF: VBoxHookMjCreate: pDevObj %p, pDevExt %p, pFileObj %p, options %#x, attr %#x, share %#x, ealength %#x, secctx %p, IrpFlags %#x\n",
452 pDevObj, pDevObj->DeviceExtension, pFileObj, pStack->Parameters.Create.Options, pStack->Parameters.Create.FileAttributes,
453 pStack->Parameters.Create.ShareAccess, pStack->Parameters.Create.EaLength, pStack->Parameters.Create.SecurityContext, pIrp->Flags));
454 if (pFileObj)
455 Log(("VBOXSF: VBoxHookMjCreate: FileName=%.*ls\n", pFileObj->FileName.Length / sizeof(WCHAR), pFileObj->FileName.Buffer));
456
457 /*
458 * Check if we need to apply the hack. If we do, we grab a reference to
459 * the file object to be absolutely sure it's around for the cleanup work.
460 */
461 AssertMsg(!(pStack->Parameters.Create.ShareAccess & VBOX_MJ_CREATE_SLASH_HACK), ("%#x\n", pStack->Parameters.Create.ShareAccess));
462 if ( (pStack->Parameters.Create.Options & (FILE_NON_DIRECTORY_FILE | FILE_DIRECTORY_FILE)) == FILE_NON_DIRECTORY_FILE
463 && pFileObj
464 && pFileObj->FileName.Length > 18
465 && pFileObj->FileName.Buffer
466 && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 1] == '\\'
467 && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 2] != '\\')
468 {
469 NTSTATUS rcNtRef = ObReferenceObjectByPointer(pFileObj, (ACCESS_MASK)0, *IoFileObjectType, KernelMode);
470 pFileObj->FileName.Length -= 2;
471 pStack->Parameters.Create.ShareAccess |= VBOX_MJ_CREATE_SLASH_HACK; /* secret flag for vbsfProcessCreate */
472
473 rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
474
475 if (rcNt != STATUS_PENDING)
476 pStack->Parameters.Create.ShareAccess &= ~VBOX_MJ_CREATE_SLASH_HACK;
477 if (NT_SUCCESS(rcNtRef))
478 {
479 pFileObj->FileName.Length += 2;
480 ObDereferenceObject(pFileObj);
481 }
482
483 Log(("VBOXSF: VBoxHookMjCreate: returns %#x (hacked; rcNtRef=%#x)\n", rcNt, rcNtRef));
484 }
485 /*
486 * No hack needed.
487 */
488 else
489 {
490 rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
491 Log(("VBOXSF: VBoxHookMjCreate: returns %#x\n", rcNt));
492 }
493 return rcNt;
494}
495
496/**
497 * Intercepts IRP_MJ_SET_INFORMATION to workaround a RDBSS quirk in the
498 * FileEndOfFileInformation handling.
499 *
500 * We will add 4096 to the FileEndOfFileInformation function value and pick it
501 * up in VBoxMRxSetFileInfo after RxCommonSetInformation has done the necessary
502 * locking. If we find that the desired file size matches the cached one, just
503 * issue the call directly, otherwise subtract 4096 and call the
504 * RxSetEndOfFileInfo worker.
505 */
506static NTSTATUS VBoxHookMjSetInformation(PDEVICE_OBJECT pDevObj, PIRP pIrp)
507{
508 PMRX_VBOX_DEVICE_EXTENSION pDevExt = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
509 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
510 PFILE_OBJECT pFileObj = pStack->FileObject;
511 NTSTATUS rcNt;
512
513 Log(("VBOXSF: VBoxHookMjSetInformation: pDevObj %p, pDevExt %p, pFileObj %p, FileInformationClass %d, Length %#x\n",
514 pDevObj, pDevObj->DeviceExtension, pFileObj, pStack->Parameters.SetFile.FileInformationClass, pStack->Parameters.SetFile.Length));
515 if (pFileObj)
516 Log2(("VBOXSF: VBoxHookMjSetInformation: FileName=%.*ls\n", pFileObj->FileName.Length / sizeof(WCHAR), pFileObj->FileName.Buffer));
517
518 /*
519 * Setting EOF info?
520 */
521 if (pStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation)
522 {
523#if 0 /* This only works for more recent versions of the RDBSS library, not for the one we're using (WDK 7600.16385.1). */
524 pStack->Parameters.SetFile.FileInformationClass = (FILE_INFORMATION_CLASS)(FileEndOfFileInformation + 4096);
525 rcNt = pDevExt->pfnRDBSSSetInformation(pDevObj, pIrp);
526 Log(("VBOXSF: VBoxHookMjSetInformation: returns %#x (hacked)\n", rcNt));
527 return rcNt;
528#else
529 /*
530 * For the older WDK, we have to detect the same-size situation up front and hack
531 * it here instead of in VBoxMRxSetFileInfo. This means we need to lock the FCB
532 * before modifying the Fcb.Header.FileSize value and ASSUME the locking is
533 * reentrant and nothing else happens during RDBSS dispatching wrt that...
534 */
535 PMRX_FCB pFcb = (PMRX_FCB)pFileObj->FsContext;
536 if ( (NODE_TYPE_CODE)pFcb->Header.NodeTypeCode == RDBSS_NTC_STORAGE_TYPE_FILE
537 && pIrp->AssociatedIrp.SystemBuffer != NULL
538 && pStack->Parameters.SetFile.Length >= sizeof(FILE_END_OF_FILE_INFORMATION))
539 {
540 LONGLONG cbFileNew = -42;
541 __try
542 {
543 cbFileNew = ((PFILE_END_OF_FILE_INFORMATION)pIrp->AssociatedIrp.SystemBuffer)->EndOfFile.QuadPart;
544 }
545 __except(EXCEPTION_EXECUTE_HANDLER)
546 {
547 cbFileNew = -42;
548 }
549 if ( cbFileNew >= 0
550 && pFcb->Header.FileSize.QuadPart == cbFileNew
551 && !(pFcb->FcbState & FCB_STATE_PAGING_FILE))
552 {
553 /* Now exclusivly lock the FCB like RxCommonSetInformation would do
554 to reduce chances of races and of anyone else grabbing the value
555 while it's incorrect on purpose. */
556 NTSTATUS rcNtLock = RxAcquireExclusiveFcb(NULL, (PFCB)pFcb);
557 if (NT_SUCCESS(rcNtLock))
558 {
559 if (pFcb->Header.FileSize.QuadPart == cbFileNew)
560 {
561 int64_t const cbHackedSize = cbFileNew ? cbFileNew - 1 : 1;
562 pFcb->Header.FileSize.QuadPart = cbHackedSize;
563 rcNt = pDevExt->pfnRDBSSSetInformation(pDevObj, pIrp);
564 if ( !NT_SUCCESS(rcNt)
565 && pFcb->Header.FileSize.QuadPart == cbHackedSize)
566 pFcb->Header.FileSize.QuadPart = cbFileNew;
567# ifdef VBOX_STRICT
568 else
569 {
570 PMRX_FOBX pFobx = (PMRX_FOBX)pFileObj->FsContext2;
571 PMRX_VBOX_FOBX pVBoxFobX = VBoxMRxGetFileObjectExtension(pFobx);
572 Assert( pFcb->Header.FileSize.QuadPart != cbHackedSize
573 || (pVBoxFobX && pVBoxFobX->Info.cbObject == cbHackedSize));
574 }
575# endif
576 RxReleaseFcb(NULL, pFcb);
577 Log(("VBOXSF: VBoxHookMjSetInformation: returns %#x (hacked, cbFileNew=%#RX64)\n", rcNt, cbFileNew));
578 return rcNt;
579 }
580 RxReleaseFcb(NULL, pFcb);
581 }
582 }
583 }
584#endif
585 }
586
587 /*
588 * No hack needed.
589 */
590 rcNt = pDevExt->pfnRDBSSSetInformation(pDevObj, pIrp);
591 Log(("VBOXSF: VBoxHookMjSetInformation: returns %#x\n", rcNt));
592 return rcNt;
593}
594
595NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
596 IN PUNICODE_STRING RegistryPath)
597{
598 NTSTATUS Status;
599 UNICODE_STRING VBoxMRxName;
600 UNICODE_STRING UserModeDeviceName;
601 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = NULL;
602 ULONG i;
603 int vrc;
604
605 Log(("VBOXSF: DriverEntry: Driver object %p\n", DriverObject));
606
607 if (!DriverObject)
608 {
609 Log(("VBOXSF: DriverEntry: driver object is NULL.\n"));
610 return STATUS_UNSUCCESSFUL;
611 }
612
613 /*
614 * Initialize IPRT.
615 */
616 vrc = RTR0Init(0);
617 if (RT_FAILURE(vrc))
618 {
619 Log(("VBOXSF: DriverEntry: RTR0Init failed! %Rrc!\n", vrc));
620 return STATUS_UNSUCCESSFUL;
621 }
622
623 /* Initialize VBox subsystem. */
624 vrc = VbglR0SfInit();
625 if (RT_FAILURE(vrc))
626 {
627 Log(("VBOXSF: DriverEntry: ERROR while initializing VBox subsystem (%Rrc)!\n", vrc));
628 RTR0Term();
629 return STATUS_UNSUCCESSFUL;
630 }
631
632 /* Connect the HGCM client */
633 vrc = VbglR0SfConnect(&g_SfClient);
634 if (RT_FAILURE(vrc))
635 {
636 Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n",
637 vrc));
638 VbglR0SfTerm();
639 RTR0Term();
640 return STATUS_UNSUCCESSFUL;
641 }
642
643 vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
644 if (RT_FAILURE(vrc))
645 {
646 LogRel(("vboxsf: VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
647 g_fHostFeatures = 0;
648 }
649 VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
650 LogRel(("VBoxSF: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
651 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
652
653 /* Init the driver object. */
654 DriverObject->DriverUnload = VBoxMRxUnload;
655 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
656 {
657 DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch;
658 }
659
660 /* Forward to RDBSS. */
661 Status = RxDriverEntry(DriverObject, RegistryPath);
662 if (Status != STATUS_SUCCESS)
663 {
664 Log(("VBOXSF: DriverEntry: RxDriverEntry failed: 0x%08X\n", Status));
665 goto failure;
666 }
667
668 __try
669 {
670 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: calling VBoxMRxDeviceObject %p\n",
671 VBoxMRxDeviceObject));
672
673 RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U);
674
675 /* Don use RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else
676 * UNC mappings don't work (including Windows explorer browsing).
677 */
678 Status = RxRegisterMinirdr(&VBoxMRxDeviceObject,
679 DriverObject,
680 &VBoxMRxDispatch,
681 RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS,
682 &VBoxMRxName,
683 sizeof(MRX_VBOX_DEVICE_EXTENSION),
684 FILE_DEVICE_NETWORK_FILE_SYSTEM,
685 FILE_REMOTE_DEVICE);
686
687 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: returned 0x%08X VBoxMRxDeviceObject %p\n",
688 Status, VBoxMRxDeviceObject));
689
690 if (Status!=STATUS_SUCCESS)
691 {
692 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr failed: 0x%08X\n", Status ));
693 try_return((void)Status);
694 }
695
696 /* Init the device extension.
697 * NOTE: the device extension actually points to fields
698 * in the RDBSS_DEVICE_OBJECT. Our space is past the end
699 * of this struct!!
700 */
701 pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
702
703 pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject;
704
705 for (i = 0; i < RT_ELEMENTS(pDeviceExtension->cLocalConnections); i++)
706 {
707 pDeviceExtension->cLocalConnections[i] = FALSE;
708 }
709
710 /* Mutex for synchronizining our connection list */
711 ExInitializeFastMutex(&pDeviceExtension->mtxLocalCon);
712
713 /* The device object has been created. Need to setup a symbolic
714 * link so that the device may be accessed from a Win32 user mode
715 * application.
716 */
717
718 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
719 Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink\n"));
720 Status = IoCreateSymbolicLink(&UserModeDeviceName, &VBoxMRxName);
721 if (Status != STATUS_SUCCESS)
722 {
723 Log(("VBOXSF: DriverEntry: IoCreateSymbolicLink: 0x%08X\n",
724 Status));
725 try_return((void)Status);
726 }
727 Log(("VBOXSF: DriverEntry: Symbolic link created.\n"));
728
729 /*
730 * Build the dispatch tables for the minirdr
731 */
732 vbsfInitMRxDispatch();
733
734 try_exit:
735 ;
736 }
737 __finally
738 {
739 ;
740 }
741
742 if (Status != STATUS_SUCCESS)
743 {
744 Log(("VBOXSF: DriverEntry: VBoxSF.sys failed to start with Status = 0x%08X\n",
745 Status));
746 goto failure;
747 }
748
749 AssertPtr(pDeviceExtension);
750
751 /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution
752 * by other redirectors. These additional name resolutions cause long delays.
753 */
754 Log(("VBOXSF: DriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n",
755 VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension));
756 pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
757 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl;
758
759 /* Intercept IRP_MJ_CREATE to fix incorrect (wrt NTFS, FAT, ++) return
760 * codes for NtOpenFile("r:\\asdf\\", FILE_NON_DIRECTORY_FILE).
761 */
762 pDeviceExtension->pfnRDBSSCreate = DriverObject->MajorFunction[IRP_MJ_CREATE];
763 DriverObject->MajorFunction[IRP_MJ_CREATE] = VBoxHookMjCreate;
764
765 /* Intercept IRP_MJ_SET_INFORMATION to ensure we call the host for all
766 * FileEndOfFileInformation requestes, even if the new size matches the
767 * old one. We don't know if someone else might have modified the file
768 * size cached in the FCB since the last time we update it.
769 */
770 pDeviceExtension->pfnRDBSSSetInformation = DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION];
771 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VBoxHookMjSetInformation;
772
773
774 /** @todo start the redirector here RxStartMiniRdr. */
775
776 Log(("VBOXSF: DriverEntry: Init successful!\n"));
777 return STATUS_SUCCESS;
778
779failure:
780
781 Log(("VBOXSF: DriverEntry: Failure! Status = 0x%08X\n", Status));
782
783 VbglR0SfDisconnect(&g_SfClient);
784 VbglR0SfTerm();
785 RTR0Term();
786
787 if (VBoxMRxDeviceObject)
788 {
789 RxUnregisterMinirdr(VBoxMRxDeviceObject);
790 VBoxMRxDeviceObject = NULL;
791 }
792
793 return Status;
794}
795
796NTSTATUS VBoxMRxStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
797{
798 NTSTATUS Status;
799 MRX_VBOX_STATE CurrentState;
800 RT_NOREF(RxContext, RxDeviceObject);
801
802 Log(("VBOXSF: MRxStart\n"));
803
804 CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS);
805
806 if (CurrentState == MRX_VBOX_START_IN_PROGRESS)
807 {
808 Log(("VBOXSF: MRxStart: Start in progress -> started\n"));
809 Status = STATUS_SUCCESS;
810 }
811 else if (VBoxMRxState == MRX_VBOX_STARTED)
812 {
813 Log(("VBOXSF: MRxStart: Already started\n"));
814 Status = STATUS_REDIRECTOR_STARTED;
815 }
816 else
817 {
818 Log(("VBOXSF: MRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState));
819 Status = STATUS_UNSUCCESSFUL;
820 }
821
822 return Status;
823}
824
825NTSTATUS VBoxMRxStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
826{
827 RT_NOREF(RxContext, RxDeviceObject);
828 Log(("VBOXSF: MRxStop\n"));
829 return STATUS_SUCCESS;
830}
831
832NTSTATUS VBoxMRxIoCtl(IN OUT PRX_CONTEXT RxContext)
833{
834 RT_NOREF(RxContext);
835 Log(("VBOXSF: MRxIoCtl: IoControlCode = 0x%08X\n", RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode));
836 return STATUS_INVALID_DEVICE_REQUEST;
837}
838
839NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject(IN HANDLE Handle,
840 IN SECURITY_INFORMATION SecurityInformation,
841 IN PSECURITY_DESCRIPTOR SecurityDescriptor);
842
843NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext)
844{
845 NTSTATUS Status = STATUS_SUCCESS;
846 RxCaptureFobx;
847 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
848 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
849
850 Log(("VBOXSF: MRxDevFcbXXXControlFile: MajorFunction = 0x%02X\n",
851 RxContext->MajorFunction));
852
853 switch (RxContext->MajorFunction)
854 {
855 case IRP_MJ_FILE_SYSTEM_CONTROL:
856 {
857 Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: 0x%08X\n",
858 LowIoContext->ParamsFor.FsCtl.MinorFunction));
859 Status = STATUS_INVALID_DEVICE_REQUEST;
860 break;
861 }
862
863 case IRP_MJ_DEVICE_CONTROL:
864 {
865 Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MJ_DEVICE_CONTROL: InputBuffer %p/%d, OutputBuffer %p/%d\n",
866 LowIoContext->ParamsFor.IoCtl.pInputBuffer,
867 LowIoContext->ParamsFor.IoCtl.InputBufferLength,
868 LowIoContext->ParamsFor.IoCtl.pOutputBuffer,
869 LowIoContext->ParamsFor.IoCtl.OutputBufferLength));
870
871 switch (LowIoContext->ParamsFor.IoCtl.IoControlCode)
872 {
873 case IOCTL_MRX_VBOX_ADDCONN:
874 {
875 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
876 Status = vbsfNtCreateConnection(RxContext, &RxContext->PostRequest);
877 break;
878 }
879
880 case IOCTL_MRX_VBOX_DELCONN:
881 {
882 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
883 Status = vbsfNtDeleteConnection(RxContext, &RxContext->PostRequest);
884 break;
885 }
886
887 case IOCTL_MRX_VBOX_GETLIST:
888 {
889 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
890 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
891
892 BOOLEAN fLocked = FALSE;
893
894 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
895
896 RxContext->InformationToReturn = 0;
897
898 if ( !pDeviceExtension
899 || cbOut < _MRX_MAX_DRIVE_LETTERS)
900 {
901 Status = STATUS_INVALID_PARAMETER;
902 break;
903 }
904
905 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n"));
906
907 fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
908
909 __try
910 {
911 RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
912 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
913 }
914 __except(EXCEPTION_EXECUTE_HANDLER)
915 {
916 Status = STATUS_INVALID_PARAMETER;
917 }
918
919 if (fLocked)
920 {
921 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
922 fLocked = FALSE;
923 }
924
925 break;
926 }
927
928 /*
929 * Returns the root IDs of shared folder mappings.
930 */
931 case IOCTL_MRX_VBOX_GETGLOBALLIST:
932 {
933 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
934 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
935
936 int vrc;
937 SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
938 uint32_t cMappings = RT_ELEMENTS(mappings);
939
940 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
941
942 RxContext->InformationToReturn = 0;
943
944 if ( !pDeviceExtension
945 || cbOut < _MRX_MAX_DRIVE_LETTERS)
946 {
947 Status = STATUS_INVALID_PARAMETER;
948 break;
949 }
950
951 vrc = VbglR0SfQueryMappings(&g_SfClient, mappings, &cMappings);
952 if (vrc == VINF_SUCCESS)
953 {
954 __try
955 {
956 uint32_t i;
957
958 RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS);
959
960 for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
961 {
962 pu8Out[i] = mappings[i].root;
963 pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */
964 }
965
966 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
967 }
968 __except(EXCEPTION_EXECUTE_HANDLER)
969 {
970 Status = STATUS_INVALID_PARAMETER;
971 }
972 }
973 else
974 {
975 Status = vbsfNtVBoxStatusToNt(vrc);
976 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n",
977 Status));
978 }
979
980 break;
981 }
982
983 /*
984 * Translates a local connection name (e.g. drive "S:") to the
985 * corresponding remote name (e.g. \\vboxsrv\share).
986 */
987 case IOCTL_MRX_VBOX_GETCONN:
988 {
989 ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
990 PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
991 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
992 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
993
994 BOOLEAN fMutexAcquired = FALSE;
995
996 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN\n"));
997
998 RxContext->InformationToReturn = 0;
999
1000 if ( !pDeviceExtension
1001 || cbConnectName < sizeof(WCHAR))
1002 {
1003 Status = STATUS_INVALID_PARAMETER;
1004 break;
1005 }
1006
1007 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n"));
1008
1009 __try
1010 {
1011 uint32_t idx = *pwcConnectName - L'A';
1012
1013 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, Index = %d\n",
1014 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, idx));
1015
1016 if (idx < RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName))
1017 {
1018 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1019 fMutexAcquired = TRUE;
1020
1021 if (pDeviceExtension->wszLocalConnectionName[idx])
1022 {
1023 ULONG cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length;
1024
1025 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n",
1026 cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
1027
1028 if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName))
1029 {
1030 RtlZeroMemory(pwcRemoteName, cbRemoteName);
1031 RtlCopyMemory(pwcRemoteName,
1032 pDeviceExtension->wszLocalConnectionName[idx]->Buffer,
1033 cbLocalConnectionName);
1034
1035 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n",
1036 cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName));
1037 }
1038 else
1039 {
1040 Status = STATUS_BUFFER_TOO_SMALL;
1041 }
1042
1043 RxContext->InformationToReturn = cbLocalConnectionName;
1044 }
1045 else
1046 {
1047 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
1048 Status = STATUS_BAD_NETWORK_NAME;
1049 }
1050 }
1051 else
1052 {
1053 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
1054 Status = STATUS_INVALID_PARAMETER;
1055 }
1056 }
1057 __except(EXCEPTION_EXECUTE_HANDLER)
1058 {
1059 Status = STATUS_INVALID_PARAMETER;
1060 }
1061
1062 if (fMutexAcquired)
1063 {
1064 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1065 fMutexAcquired = FALSE;
1066 }
1067
1068 break;
1069 }
1070
1071 case IOCTL_MRX_VBOX_GETGLOBALCONN:
1072 {
1073 ULONG cbConnectId = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1074 uint8_t *pu8ConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1075 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
1076 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
1077
1078 int vrc;
1079 PSHFLSTRING pString;
1080
1081 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN\n"));
1082
1083 RxContext->InformationToReturn = 0;
1084
1085 if ( !pDeviceExtension
1086 || cbConnectId < sizeof(uint8_t))
1087 {
1088 Status = STATUS_INVALID_PARAMETER;
1089 break;
1090 }
1091
1092 /* Allocate empty string where the host can store cbRemoteName bytes. */
1093 Status = vbsfNtShflStringFromUnicodeAlloc(&pString, NULL, (uint16_t)cbRemoteName);
1094 if (Status != STATUS_SUCCESS)
1095 break;
1096
1097 __try
1098 {
1099 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d\n",
1100 *pu8ConnectId));
1101
1102 vrc = VbglR0SfQueryMapName(&g_SfClient,
1103 *pu8ConnectId & ~0x80 /** @todo fix properly */,
1104 pString, ShflStringSizeOfBuffer(pString));
1105 if ( vrc == VINF_SUCCESS
1106 && pString->u16Length < cbRemoteName)
1107 {
1108 RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length);
1109 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n",
1110 pString->u16Length / sizeof(WCHAR), pwcRemoteName, pString->u16Length));
1111 RxContext->InformationToReturn = pString->u16Length;
1112 }
1113 else
1114 {
1115 Status = STATUS_BAD_NETWORK_NAME;
1116 }
1117 }
1118 __except(EXCEPTION_EXECUTE_HANDLER)
1119 {
1120 Status = STATUS_INVALID_PARAMETER;
1121 }
1122
1123 vbsfNtFreeNonPagedMem(pString);
1124
1125 break;
1126 }
1127
1128 case IOCTL_MRX_VBOX_START:
1129 {
1130 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n",
1131 capFobx));
1132
1133 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n",
1134 IoGetCurrentProcess(), RxGetRDBSSProcess()));
1135
1136 switch (VBoxMRxState)
1137 {
1138 case MRX_VBOX_STARTABLE:
1139
1140 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n"));
1141
1142 if (capFobx)
1143 {
1144 Status = STATUS_INVALID_DEVICE_REQUEST;
1145 break;;
1146 }
1147
1148 InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
1149
1150 case MRX_VBOX_START_IN_PROGRESS:
1151 Status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
1152
1153 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n",
1154 Status, RxContext->PostRequest));
1155
1156 if (Status == STATUS_REDIRECTOR_STARTED)
1157 {
1158 Status = STATUS_SUCCESS;
1159 break;
1160 }
1161
1162 if ( Status == STATUS_PENDING
1163 && RxContext->PostRequest == TRUE)
1164 {
1165 /* Will be restarted in RDBSS process. */
1166 Status = STATUS_MORE_PROCESSING_REQUIRED;
1167 break;
1168 }
1169
1170 /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
1171 if (Status == STATUS_SUCCESS)
1172 {
1173 SECURITY_DESCRIPTOR SecurityDescriptor;
1174 OBJECT_ATTRIBUTES InitializedAttributes;
1175 HANDLE hDevice;
1176 IO_STATUS_BLOCK IoStatusBlock;
1177 UNICODE_STRING UserModeDeviceName;
1178
1179 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
1180
1181 /* Create empty security descriptor */
1182 RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
1183 Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1184 if (Status != STATUS_SUCCESS)
1185 {
1186 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n",
1187 Status));
1188 return Status;
1189 }
1190
1191 RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
1192 InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
1193
1194 /* Open our symbolic link device name */
1195 Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
1196 if (Status != STATUS_SUCCESS)
1197 {
1198 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n",
1199 DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
1200 return Status;
1201 }
1202
1203 /* Override the discretionary access control list (DACL) settings */
1204 Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
1205 if (Status != STATUS_SUCCESS)
1206 {
1207 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n",
1208 Status));
1209 return Status;
1210 }
1211
1212 Status = ZwClose(hDevice);
1213 if (Status != STATUS_SUCCESS)
1214 {
1215 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n",
1216 Status));
1217 return Status;
1218 }
1219 }
1220 break;
1221
1222 case MRX_VBOX_STARTED:
1223 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
1224 Status = STATUS_SUCCESS;
1225 break;
1226
1227 default:
1228 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n",
1229 VBoxMRxState));
1230 Status = STATUS_INVALID_PARAMETER;
1231 break;
1232 }
1233
1234 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n",
1235 Status));
1236 break;
1237 }
1238
1239 case IOCTL_MRX_VBOX_STOP:
1240 {
1241 MRX_VBOX_STATE CurrentState;
1242
1243 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n",
1244 capFobx));
1245
1246 if (capFobx)
1247 {
1248 Status = STATUS_INVALID_DEVICE_REQUEST;
1249 break;
1250 }
1251
1252 if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
1253 {
1254 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n",
1255 RxContext->RxDeviceObject->NumberOfActiveFcbs));
1256 Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
1257 break;
1258 }
1259
1260 CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
1261
1262 Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
1263 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n",
1264 Status));
1265
1266 if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
1267 Status = STATUS_MORE_PROCESSING_REQUIRED;
1268 break;
1269 }
1270
1271 default:
1272 Status = STATUS_INVALID_DEVICE_REQUEST;
1273 break;
1274 }
1275 break;
1276 }
1277
1278 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1279 {
1280 Status = STATUS_INVALID_DEVICE_REQUEST;
1281 break;
1282 }
1283
1284 default:
1285 Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n",
1286 RxContext->MajorFunction));
1287 Status = STATUS_INVALID_DEVICE_REQUEST;
1288 break;
1289 }
1290
1291 Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n",
1292 Status, RxContext->InformationToReturn));
1293
1294 return Status;
1295}
1296
1297static NTSTATUS vbsfVerifyConnectionName(PUNICODE_STRING ConnectionName)
1298{
1299 /* Check that the connection name is valid:
1300 * "\Device\VBoxMiniRdr\;X:\vboxsvr\sf"
1301 */
1302 NTSTATUS Status = STATUS_BAD_NETWORK_NAME;
1303
1304 ULONG i;
1305 PWCHAR pwc;
1306 PWCHAR pwc1;
1307
1308 static PWCHAR spwszPrefix = L"\\Device\\VBoxMiniRdr\\;";
1309
1310 /* Unicode chars in the string. */
1311 ULONG cConnectionName = ConnectionName->Length / sizeof(WCHAR);
1312 ULONG cRemainingName;
1313
1314 /* Check that the name starts with correct prefix. */
1315 pwc1 = &spwszPrefix[0];
1316 pwc = ConnectionName->Buffer;
1317 for (i = 0; i < cConnectionName; i++, pwc1++, pwc++)
1318 {
1319 if (*pwc1 == 0 || *pwc == 0 || *pwc1 != *pwc)
1320 break;
1321 }
1322
1323 cRemainingName = cConnectionName - i;
1324
1325 Log(("VBOXSF: vbsfVerifyConnectionName: prefix %d remaining %d [%.*ls]\n",
1326 *pwc1 == 0, cRemainingName, cRemainingName, &ConnectionName->Buffer[i]));
1327
1328 if (*pwc1 == 0)
1329 {
1330 /* pwc should point to a drive letter followed by ':\' that is at least 3 chars more. */
1331 if (cRemainingName >= 3)
1332 {
1333 if ( pwc[0] >= L'A' && pwc[0] <= L'Z'
1334 && pwc[1] == L':')
1335 {
1336 pwc += 2;
1337 cRemainingName -= 2;
1338
1339 /** @todo should also check that the drive letter corresponds to the name. */
1340 if (vboxIsPrefixOK(pwc, cRemainingName * sizeof (WCHAR)))
1341 Status = STATUS_SUCCESS;
1342 }
1343 }
1344 }
1345
1346 return Status;
1347}
1348
1349static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName, NTSTATUS *prcNt)
1350{
1351 NTSTATUS Status;
1352 IO_STATUS_BLOCK IoStatusBlock;
1353 OBJECT_ATTRIBUTES ObjectAttributes;
1354
1355 HANDLE Handle = INVALID_HANDLE_VALUE;
1356
1357 Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n",
1358 ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer));
1359
1360 Status = vbsfVerifyConnectionName(ConnectionName);
1361
1362 if (NT_SUCCESS(Status))
1363 {
1364 /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */
1365 InitializeObjectAttributes(&ObjectAttributes,
1366 ConnectionName,
1367 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1368 NULL,
1369 NULL);
1370
1371 Status = ZwCreateFile(&Handle,
1372 SYNCHRONIZE,
1373 &ObjectAttributes,
1374 &IoStatusBlock,
1375 NULL,
1376 FILE_ATTRIBUTE_NORMAL,
1377 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1378 FILE_OPEN_IF,
1379 FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
1380 NULL,
1381 0);
1382 }
1383
1384 if ( Status != STATUS_SUCCESS
1385 || Handle == INVALID_HANDLE_VALUE)
1386 {
1387 Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n", Status));
1388 if (prcNt)
1389 *prcNt = !NT_SUCCESS(Status) ? Status : STATUS_UNSUCCESSFUL;
1390 Handle = INVALID_HANDLE_VALUE;
1391 }
1392
1393 return Handle;
1394}
1395
1396NTSTATUS vbsfNtCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1397{
1398 NTSTATUS Status = STATUS_SUCCESS;
1399
1400 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1401
1402 PLOWIO_CONTEXT LowIoContext;
1403 ULONG cbConnectName;
1404 PWCHAR pwcConnectName;
1405
1406 HANDLE Handle;
1407 UNICODE_STRING FileName;
1408
1409 BOOLEAN fMutexAcquired = FALSE;
1410
1411 Log(("VBOXSF: vbsfNtCreateConnection\n"));
1412
1413 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1414 {
1415 Log(("VBOXSF: vbsfNtCreateConnection: post to file system process\n"));
1416 *PostToFsp = TRUE;
1417 return STATUS_PENDING;
1418 }
1419
1420 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1421 if (!pDeviceExtension)
1422 return STATUS_INVALID_PARAMETER;
1423
1424 LowIoContext = &RxContext->LowIoContext;
1425 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1426 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1427
1428 if (cbConnectName == 0 || !pwcConnectName)
1429 {
1430 Log(("VBOXSF: vbsfNtCreateConnection: Connection name / length is invalid!\n"));
1431 return STATUS_INVALID_PARAMETER;
1432 }
1433
1434 __try
1435 {
1436 Log(("VBOXSF: vbsfNtCreateConnection: Name = %.*ls, Len = %d\n",
1437 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName));
1438
1439 FileName.Buffer = pwcConnectName;
1440 FileName.Length = (USHORT)cbConnectName;
1441 FileName.MaximumLength = (USHORT)cbConnectName;
1442
1443 Handle = vbsfOpenConnectionHandle(&FileName, NULL);
1444
1445 if (Handle != INVALID_HANDLE_VALUE)
1446 {
1447 PWCHAR pwc;
1448 ULONG i;
1449
1450 ZwClose(Handle);
1451
1452 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1453 pwc = pwcConnectName;
1454 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1455 {
1456 if (*pwc == L':')
1457 break;
1458 pwc++;
1459 }
1460
1461 if (i >= sizeof(WCHAR) && i < cbConnectName)
1462 {
1463 pwc--; /* Go back to the drive letter, "X" for example. */
1464
1465 if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */
1466 {
1467 uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */
1468
1469 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1470 {
1471 Log(("VBOXSF: vbsfNtCreateConnection: Index 0x%x is invalid!\n",
1472 idx));
1473 Status = STATUS_BAD_NETWORK_NAME;
1474 }
1475 else
1476 {
1477 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1478 fMutexAcquired = TRUE;
1479
1480 if (pDeviceExtension->wszLocalConnectionName[idx] != NULL)
1481 {
1482 Log(("VBOXSF: vbsfNtCreateConnection: LocalConnectionName at index %d is NOT empty!\n",
1483 idx));
1484 }
1485
1486 pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfNtAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName);
1487
1488 if (!pDeviceExtension->wszLocalConnectionName[idx])
1489 {
1490 Log(("VBOXSF: vbsfNtCreateConnection: LocalConnectionName at index %d NOT allocated!\n",
1491 idx));
1492 Status = STATUS_INSUFFICIENT_RESOURCES;
1493 }
1494 else
1495 {
1496 PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
1497
1498 pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
1499 pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR));
1500 pRemoteName->MaximumLength = pRemoteName->Length;
1501 RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length);
1502
1503 Log(("VBOXSF: vbsfNtCreateConnection: RemoteName %.*ls, Len = %d\n",
1504 pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
1505
1506 pDeviceExtension->cLocalConnections[idx] = TRUE;
1507 }
1508
1509 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1510 fMutexAcquired = FALSE;
1511 }
1512 }
1513 }
1514 else
1515 {
1516 Log(("VBOXSF: vbsfNtCreateConnection: bad format\n"));
1517 Status = STATUS_BAD_NETWORK_NAME;
1518 }
1519 }
1520 else
1521 {
1522 Log(("VBOXSF: vbsfNtCreateConnection: connection was not found\n"));
1523 Status = STATUS_BAD_NETWORK_NAME;
1524 }
1525 }
1526 __except(EXCEPTION_EXECUTE_HANDLER)
1527 {
1528 Status = STATUS_INVALID_PARAMETER;
1529 }
1530
1531 if (fMutexAcquired)
1532 {
1533 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1534 fMutexAcquired = FALSE;
1535 }
1536
1537 return Status;
1538}
1539
1540NTSTATUS vbsfNtDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1541{
1542 NTSTATUS Status;
1543 UNICODE_STRING FileName;
1544 HANDLE Handle;
1545 PLOWIO_CONTEXT LowIoContext;
1546 PWCHAR pwcConnectName;
1547 ULONG cbConnectName;
1548 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1549
1550 BOOLEAN fMutexAcquired = FALSE;
1551
1552 Log(("VBOXSF: vbsfNtDeleteConnection\n"));
1553
1554 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1555 {
1556 Log(("VBOXSF: vbsfNtDeleteConnection: post to file system process\n"));
1557 *PostToFsp = TRUE;
1558 return STATUS_PENDING;
1559 }
1560
1561 LowIoContext = &RxContext->LowIoContext;
1562 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1563 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1564
1565 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1566 if (!pDeviceExtension)
1567 return STATUS_INVALID_PARAMETER;
1568
1569 __try
1570 {
1571 Log(("VBOXSF: vbsfNtDeleteConnection: pwcConnectName = %.*ls\n",
1572 cbConnectName / sizeof(WCHAR), pwcConnectName));
1573
1574 FileName.Buffer = pwcConnectName;
1575 FileName.Length = (USHORT)cbConnectName;
1576 FileName.MaximumLength = (USHORT)cbConnectName;
1577
1578 Handle = vbsfOpenConnectionHandle(&FileName, &Status);
1579 if (Handle != INVALID_HANDLE_VALUE)
1580 {
1581 PFILE_OBJECT pFileObject;
1582 Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
1583
1584 Log(("VBOXSF: vbsfNtDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n",
1585 Status));
1586
1587 if (NT_SUCCESS(Status))
1588 {
1589 PFOBX Fobx = (PFOBX)pFileObject->FsContext2;
1590 Log(("VBOXSF: vbsfNtDeleteConnection: Fobx %p\n", Fobx));
1591
1592 if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
1593 {
1594 PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
1595
1596#ifdef __cplusplus /* C version points at NET_ROOT, C++ points at MRX_NET_ROOT. Weird. */
1597 Status = RxFinalizeConnection((PNET_ROOT)VNetRoot->pNetRoot, VNetRoot, TRUE);
1598#else
1599 Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
1600#endif
1601 }
1602 else
1603 {
1604 Log(("VBOXSF: vbsfNtDeleteConnection: wrong FsContext2\n"));
1605 Status = STATUS_INVALID_DEVICE_REQUEST;
1606 }
1607
1608 ObDereferenceObject(pFileObject);
1609 }
1610
1611 ZwClose(Handle);
1612
1613 if (NT_SUCCESS(Status))
1614 {
1615 PWCHAR pwc;
1616 ULONG i;
1617
1618 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1619 pwc = pwcConnectName;
1620 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1621 {
1622 if (*pwc == L':')
1623 {
1624 break;
1625 }
1626 pwc++;
1627 }
1628
1629 if (i >= sizeof(WCHAR) && i < cbConnectName)
1630 {
1631 pwc--;
1632
1633 if (*pwc >= L'A' && *pwc <= L'Z')
1634 {
1635 uint32_t idx = *pwc - L'A';
1636
1637 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1638 {
1639 Log(("VBOXSF: vbsfNtDeleteConnection: Index 0x%x is invalid!\n",
1640 idx));
1641 Status = STATUS_BAD_NETWORK_NAME;
1642 }
1643 else
1644 {
1645 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1646 fMutexAcquired = TRUE;
1647
1648 pDeviceExtension->cLocalConnections[idx] = FALSE;
1649
1650 /* Free saved name */
1651 if (pDeviceExtension->wszLocalConnectionName[idx])
1652 {
1653 vbsfNtFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
1654 pDeviceExtension->wszLocalConnectionName[idx] = NULL;
1655 }
1656
1657 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1658 fMutexAcquired = FALSE;
1659
1660 Log(("VBOXSF: vbsfNtDeleteConnection: deleted index 0x%x\n",
1661 idx));
1662 }
1663 }
1664 }
1665 else
1666 {
1667 Log(("VBOXSF: vbsfNtCreateConnection: bad format\n"));
1668 Status = STATUS_BAD_NETWORK_NAME;
1669 }
1670 }
1671 }
1672 }
1673 __except(EXCEPTION_EXECUTE_HANDLER)
1674 {
1675 Status = STATUS_INVALID_PARAMETER;
1676 }
1677
1678 if (fMutexAcquired)
1679 {
1680 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1681 fMutexAcquired = FALSE;
1682 }
1683
1684 Log(("VBOXSF: vbsfNtDeleteConnection: Status 0x%08X\n", Status));
1685 return Status;
1686}
1687
1688NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext)
1689{
1690 RT_NOREF(RxContext);
1691 Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n", RxContext->Info.LengthRemaining));
1692 return STATUS_SUCCESS;
1693}
1694
1695NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext)
1696{
1697 RT_NOREF(RxContext);
1698 Log(("VBOXSF: MRxSetEaInfo\n"));
1699 return STATUS_NOT_IMPLEMENTED;
1700}
1701
1702NTSTATUS VBoxMRxFsCtl(IN OUT PRX_CONTEXT RxContext)
1703{
1704 RT_NOREF(RxContext);
1705 Log(("VBOXSF: MRxFsCtl\n"));
1706 return STATUS_INVALID_DEVICE_REQUEST;
1707}
1708
1709NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext)
1710{
1711 RT_NOREF(RxContext);
1712 Log(("VBOXSF: MRxNotifyChangeDirectory\n"));
1713 return STATUS_NOT_IMPLEMENTED;
1714}
1715
1716static NTSTATUS vbsfQuerySdInfo(PVOID pvBuffer, ULONG cbBuffer, SECURITY_INFORMATION SecurityInformation, ULONG *pcbOut)
1717{
1718 /* What a public SMB share would return. */
1719 static SID_IDENTIFIER_AUTHORITY sIA = SECURITY_NT_AUTHORITY;
1720 #define SUB_AUTHORITY_COUNT 2
1721 static const ULONG saSubAuthorityOwner[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_USER_RID_GUEST };
1722 static const ULONG saSubAuthorityGroup[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_GROUP_RID_GUESTS };
1723
1724 SECURITY_DESCRIPTOR_RELATIVE *pSD = (SECURITY_DESCRIPTOR_RELATIVE *)pvBuffer;
1725 ULONG cbSD = 0; /* Size of returned security descriptor. */
1726 ULONG cbAdd; /* How many bytes to add to the buffer for each component of the security descriptor. */
1727
1728 cbAdd = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1729 if (cbSD + cbAdd <= cbBuffer)
1730 {
1731 pSD->Revision = SECURITY_DESCRIPTOR_REVISION1;
1732 pSD->Sbz1 = 0;
1733 pSD->Control = SE_SELF_RELATIVE;
1734 pSD->Owner = 0;
1735 pSD->Group = 0;
1736 pSD->Sacl = 0;
1737 pSD->Dacl = 0;
1738 }
1739 cbSD += cbAdd;
1740
1741 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1742 {
1743 cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
1744 if (cbSD + cbAdd <= cbBuffer)
1745 {
1746 SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
1747 pSID->Revision = 1;
1748 pSID->SubAuthorityCount = SUB_AUTHORITY_COUNT;
1749 pSID->IdentifierAuthority = sIA;
1750 memcpy(pSID->SubAuthority, saSubAuthorityOwner, SUB_AUTHORITY_COUNT * sizeof(ULONG));
1751
1752 pSD->Owner = cbSD;
1753 }
1754 cbSD += cbAdd;
1755 }
1756
1757 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1758 {
1759 cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
1760 if (cbSD + cbAdd <= cbBuffer)
1761 {
1762 SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
1763 pSID->Revision = 1;
1764 pSID->SubAuthorityCount = SUB_AUTHORITY_COUNT;
1765 pSID->IdentifierAuthority = sIA;
1766 memcpy(pSID->SubAuthority, saSubAuthorityGroup, SUB_AUTHORITY_COUNT * sizeof(ULONG));
1767
1768 pSD->Group = cbSD;
1769 }
1770 cbSD += cbAdd;
1771 }
1772
1773 #undef SUB_AUTHORITY_COUNT
1774
1775 *pcbOut = cbSD;
1776 return STATUS_SUCCESS;
1777}
1778
1779NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext)
1780{
1781 NTSTATUS Status;
1782
1783 PVOID pvBuffer = RxContext->Info.Buffer;
1784 ULONG cbBuffer = RxContext->Info.LengthRemaining;
1785 SECURITY_INFORMATION SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
1786
1787 ULONG cbSD = 0;
1788
1789 Log(("VBOXSF: MRxQuerySdInfo: Buffer %p, Length %d, SecurityInformation 0x%x\n",
1790 pvBuffer, cbBuffer, SecurityInformation));
1791
1792 Status = vbsfQuerySdInfo(pvBuffer, cbBuffer, SecurityInformation, &cbSD);
1793 if (NT_SUCCESS(Status))
1794 {
1795 RxContext->InformationToReturn = cbSD;
1796 if (RxContext->InformationToReturn > cbBuffer)
1797 {
1798 Status = STATUS_BUFFER_OVERFLOW;
1799 }
1800 }
1801
1802 Log(("VBOXSF: MRxQuerySdInfo: Status 0x%08X, InformationToReturn %d\n",
1803 Status, RxContext->InformationToReturn));
1804 return Status;
1805}
1806
1807NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext)
1808{
1809 RT_NOREF(RxContext);
1810 Log(("VBOXSF: MRxSetSdInfo\n"));
1811 return STATUS_NOT_IMPLEMENTED;
1812}
1813
1814/*
1815 * WML stubs which are referenced by rdbsslib.
1816 */
1817extern "C" NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp)
1818{
1819 RT_NOREF(pWmiLibInfo, pDevObj, pIrp);
1820 return STATUS_WMI_GUID_NOT_FOUND;
1821}
1822
1823extern "C" ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...)
1824{
1825 RT_NOREF(ulType, pTraceUuid, ullLogger);
1826 return STATUS_SUCCESS;
1827}
1828
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette