VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c@ 63079

Last change on this file since 63079 was 63079, checked in by vboxsync, 8 years ago

vbsfDeleteConnection: Status was used uninitialized if vbsfOpenConnectionHandle failed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.5 KB
Line 
1/* $Id: vbsf.c 63079 2016-08-06 13:45:43Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders.
4 *
5 * File System Driver initialization and generic routines
6 */
7
8/*
9 * Copyright (C) 2012-2016 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include "vbsf.h"
21
22/*
23 * The current state of the driver.
24 */
25typedef enum _MRX_VBOX_STATE_
26{
27 MRX_VBOX_STARTABLE,
28 MRX_VBOX_START_IN_PROGRESS,
29 MRX_VBOX_STARTED
30} MRX_VBOX_STATE, *PMRX_VBOX_STATE;
31
32static MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE;
33
34/*
35 * The VBoxSF dispatch table.
36 */
37static struct _MINIRDR_DISPATCH VBoxMRxDispatch;
38
39/*
40 * The VBoxSF device object.
41 */
42PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
43
44static NTSTATUS VBoxMRxFsdDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
45{
46 NTSTATUS Status = STATUS_SUCCESS;
47 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
48
49 Log(("VBOXSF: MRxFsdDispatch: major %d, minor %d: %s\n",
50 IrpSp->MajorFunction, IrpSp->MinorFunction, MajorFunctionString(IrpSp->MajorFunction, IrpSp->MinorFunction)));
51
52 if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject)
53 {
54 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
55 Irp->IoStatus.Information = 0;
56 IoCompleteRequest(Irp, IO_NO_INCREMENT);
57
58 Log(("VBOXSF: MRxFsdDispatch: Invalid device request detected %p %p\n",
59 DeviceObject, (PDEVICE_OBJECT)VBoxMRxDeviceObject));
60
61 return STATUS_INVALID_DEVICE_REQUEST;
62 }
63
64 Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp);
65
66 Log(("VBOXSF: MRxFsdDispatch: Returned 0x%X\n",
67 Status));
68 return Status;
69}
70
71static void VBoxMRxUnload(IN PDRIVER_OBJECT DriverObject)
72{
73 NTSTATUS Status;
74 UNICODE_STRING UserModeDeviceName;
75
76 Log(("VBOXSF: MRxUnload\n"));
77
78 if (VBoxMRxDeviceObject)
79 {
80 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
81 pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
82 VbglR0SfDisconnect(&pDeviceExtension->hgcmClient);
83 }
84
85 VbglR0SfTerm();
86
87 if (VBoxMRxDeviceObject)
88 {
89 PRX_CONTEXT RxContext;
90 RxContext = RxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP);
91
92 if (RxContext != NULL)
93 {
94 Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
95
96 if (Status == STATUS_SUCCESS)
97 {
98 MRX_VBOX_STATE State;
99
100 State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
101
102 if (State != MRX_VBOX_STARTABLE)
103 Status = STATUS_REDIRECTOR_STARTED;
104 }
105
106 RxDereferenceAndDeleteRxContext(RxContext);
107 }
108 else
109 Status = STATUS_INSUFFICIENT_RESOURCES;
110
111 RxUnregisterMinirdr(VBoxMRxDeviceObject);
112 }
113
114 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
115 Status = IoDeleteSymbolicLink(&UserModeDeviceName);
116 if (Status != STATUS_SUCCESS)
117 Log(("VBOXSF: MRxUnload: IoDeleteSymbolicLink Status 0x%08X\n", Status));
118
119 RxUnload(DriverObject);
120
121 Log(("VBOXSF: MRxUnload: VBoxSF.sys driver object %p unloaded\n", DriverObject));
122}
123
124static void vbsfInitMRxDispatch(void)
125{
126 Log(("VBOXSF: vbsfInitMRxDispatch: Called.\n"));
127
128 ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
129
130 VBoxMRxDispatch.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION);
131
132 VBoxMRxDispatch.MRxSrvCallSize = 0;
133 VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION);
134 VBoxMRxDispatch.MRxVNetRootSize = 0;
135 VBoxMRxDispatch.MRxFcbSize = 0;
136 VBoxMRxDispatch.MRxSrvOpenSize = 0;
137 VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX);
138
139 VBoxMRxDispatch.MRxStart = VBoxMRxStart;
140 VBoxMRxDispatch.MRxStop = VBoxMRxStop;
141
142 VBoxMRxDispatch.MRxCreate = VBoxMRxCreate;
143 VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen;
144 VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen;
145 VBoxMRxDispatch.MRxFlush = VBoxMRxFlush;
146 VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate;
147 VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx;
148 VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen;
149 VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb;
150 VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx;
151 VBoxMRxDispatch.MRxForceClosed = VBoxMRxForceClosed;
152
153 VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory;
154 VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInfo;
155 VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInfo;
156 VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInfoAtCleanup;
157 VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInfo;
158 VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInfo;
159 VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySdInfo;
160 VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSdInfo;
161 VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInfo;
162
163 VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState;
164
165 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead;
166 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite;
167 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks;
168 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks;
169 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks;
170 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks;
171 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl;
172 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl;
173 VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory;
174
175 VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub;
176 VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub;
177 VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest;
178
179 VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot;
180 VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot;
181 VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot;
182 VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState;
183 VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName;
184
185 VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall;
186 VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify;
187 VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall;
188
189 VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile;
190
191 Log(("VBOXSF: vbsfInitMRxDispatch: Success.\n"));
192 return;
193}
194
195static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength)
196{
197 BOOL PrefixOK;
198
199 /* The FilePathName here looks like: \vboxsrv\... */
200 if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */
201 {
202 PrefixOK = (FilePathName[0] == L'\\');
203 PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v');
204 PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b');
205 PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o');
206 PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x');
207 PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's');
208 /* Both vboxsvr & vboxsrv are now accepted */
209 if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v'))
210 {
211 PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v');
212 PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r');
213 }
214 else
215 {
216 PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r');
217 PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v');
218 }
219 if (PathNameLength > 8 * sizeof (WCHAR))
220 {
221 /* There is something after '\vboxsrv'. */
222 PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0);
223 }
224 }
225 else
226 PrefixOK = FALSE;
227
228 return PrefixOK;
229}
230
231static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
232{
233 NTSTATUS Status = STATUS_SUCCESS;
234
235 QUERY_PATH_REQUEST *pReq = NULL;
236 QUERY_PATH_REQUEST_EX *pReqEx = NULL;
237 QUERY_PATH_RESPONSE *pResp = NULL;
238
239 BOOL PrefixOK = FALSE;
240
241 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
242
243 /* Make a local copy, it will be needed after the Irp completion. */
244 ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
245
246 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
247
248 Log(("VBOXSF: MRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n",
249 pDevObj, pDevObj->DeviceExtension, IoControlCode));
250
251 switch (IoControlCode)
252 {
253 case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */
254 case IOCTL_REDIR_QUERY_PATH: /* XP and earlier */
255 {
256 /* This IOCTL is intercepted for 2 reasons:
257 * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them
258 * will be routed to the VBox provider automatically without any prefix resolution
259 * since the prefix is already in the prefix cache.
260 * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit,
261 * because RDBSS will not be involved then.
262 */
263
264 const WCHAR *FilePathName = NULL;
265 ULONG PathNameLength = 0;
266
267 if (pIrp->RequestorMode != KernelMode)
268 {
269 /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying
270 * that RequestorMode member of the IRP structure is KernelMode.
271 */
272 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n",
273 pStack->Parameters.DeviceIoControl.InputBufferLength));
274 /* Continue to RDBSS. */
275 break;
276 }
277
278 if (IoControlCode == IOCTL_REDIR_QUERY_PATH)
279 {
280 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess()));
281
282 if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST))
283 {
284 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n",
285 pStack->Parameters.DeviceIoControl.InputBufferLength));
286 /* Continue to RDBSS. */
287 break;
288 }
289
290 pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
291
292 Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReq->PathNameLength));
293 Log(("VBOXSF: MRxDeviceControl: SecurityContext = %p.\n", pReq->SecurityContext));
294 Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName));
295
296 FilePathName = pReq->FilePathName;
297 PathNameLength = pReq->PathNameLength;
298 }
299 else
300 {
301 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: Called.\n"));
302
303 if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX))
304 {
305 Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n",
306 pStack->Parameters.DeviceIoControl.InputBufferLength));
307 /* Continue to RDBSS. */
308 break;
309 }
310
311 pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
312
313 Log(("VBOXSF: MRxDeviceControl: pSecurityContext = %p.\n", pReqEx->pSecurityContext));
314 Log(("VBOXSF: MRxDeviceControl: EaLength = %d.\n", pReqEx->EaLength));
315 Log(("VBOXSF: MRxDeviceControl: pEaBuffer = %p.\n", pReqEx->pEaBuffer));
316 Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReqEx->PathName.Length));
317 Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer));
318
319 FilePathName = pReqEx->PathName.Buffer;
320 PathNameLength = pReqEx->PathName.Length;
321 }
322
323 pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer;
324
325 PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength);
326 Log(("VBOXSF: MRxDeviceControl PrefixOK %d\n", PrefixOK));
327
328 if (!PrefixOK)
329 {
330 /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN.
331 * No need to involve RDBSS.
332 */
333 Status = STATUS_BAD_NETWORK_NAME;
334
335 pIrp->IoStatus.Status = Status;
336 pIrp->IoStatus.Information = 0;
337
338 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
339
340 Log(("VBOXSF: MRxDeviceControl: returned STATUS_BAD_NETWORK_NAME\n"));
341 return Status;
342 }
343
344 Log(("VBOXSF: MRxDeviceControl pResp %p verifying the path.\n", pResp));
345 if (pResp)
346 {
347 /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path.
348 * Here it is assigned to the length of \vboxsrv prefix.
349 */
350 pResp->LengthAccepted = 8 * sizeof (WCHAR);
351
352 Status = STATUS_SUCCESS;
353
354 pIrp->IoStatus.Status = Status;
355 pIrp->IoStatus.Information = 0;
356
357 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
358
359 Log(("VBOXSF: MRxDeviceControl: claiming the path.\n"));
360 return Status;
361 }
362
363 /* No pResp pointer, should not happen. Just a precaution. */
364 Status = STATUS_INVALID_PARAMETER;
365
366 pIrp->IoStatus.Status = Status;
367 pIrp->IoStatus.Information = 0;
368
369 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
370
371 Log(("VBOXSF: MRxDeviceControl: returned STATUS_INVALID_PARAMETER\n"));
372 return Status;
373 }
374
375 default:
376 break;
377 }
378
379 /* Pass the IOCTL to RDBSS. */
380 if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl)
381 {
382 Log(("VBOXSF: MRxDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl));
383 Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp);
384 Log(("VBOXSF: MRxDeviceControl RDBSS status 0x%08X\n", Status));
385 }
386 else
387 {
388 /* No RDBSS, should not happen. Just a precaution. */
389 Status = STATUS_NOT_IMPLEMENTED;
390
391 pIrp->IoStatus.Status = Status;
392 pIrp->IoStatus.Information = 0;
393
394 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
395
396 Log(("VBOXSF: MRxDeviceControl: returned STATUS_NOT_IMPLEMENTED\n"));
397 }
398
399 return Status;
400}
401
402NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
403 IN PUNICODE_STRING RegistryPath)
404{
405 NTSTATUS Status;
406 UNICODE_STRING VBoxMRxName;
407 UNICODE_STRING UserModeDeviceName;
408 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = NULL;
409 ULONG i;
410 int vboxRC;
411 VBGLSFCLIENT hgcmClient;
412
413 Log(("VBOXSF: DriverEntry: Driver object %p\n", DriverObject));
414
415 if (!DriverObject)
416 {
417 Log(("VBOXSF: DriverEntry: driver object is NULL.\n"));
418 return STATUS_UNSUCCESSFUL;
419 }
420
421 /* Initialize VBox subsystem. */
422 vboxRC = VbglR0SfInit();
423 if (RT_FAILURE(vboxRC))
424 {
425 Log(("VBOXSF: DriverEntry: ERROR while initializing VBox subsystem (%Rrc)!\n", vboxRC));
426 return STATUS_UNSUCCESSFUL;
427 }
428
429 /* Connect the HGCM client */
430 RT_ZERO(hgcmClient);
431 vboxRC = VbglR0SfConnect(&hgcmClient);
432 if (RT_FAILURE(vboxRC))
433 {
434 Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n",
435 vboxRC));
436 VbglR0SfTerm();
437 return STATUS_UNSUCCESSFUL;
438 }
439
440 /* Init the driver object. */
441 DriverObject->DriverUnload = VBoxMRxUnload;
442 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
443 {
444 DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch;
445 }
446
447 /* Forward to RDBSS. */
448 Status = RxDriverEntry(DriverObject, RegistryPath);
449 if (Status != STATUS_SUCCESS)
450 {
451 Log(("VBOXSF: DriverEntry: RxDriverEntry failed: 0x%08X\n", Status));
452 goto failure;
453 }
454
455 __try
456 {
457 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: calling VBoxMRxDeviceObject %p\n",
458 VBoxMRxDeviceObject));
459
460 RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U);
461
462 /* Don use RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else
463 * UNC mappings don't work (including Windows explorer browsing).
464 */
465 Status = RxRegisterMinirdr(&VBoxMRxDeviceObject,
466 DriverObject,
467 &VBoxMRxDispatch,
468 RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS,
469 &VBoxMRxName,
470 sizeof(MRX_VBOX_DEVICE_EXTENSION),
471 FILE_DEVICE_NETWORK_FILE_SYSTEM,
472 FILE_REMOTE_DEVICE);
473
474 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: returned 0x%08X VBoxMRxDeviceObject %p\n",
475 Status, VBoxMRxDeviceObject));
476
477 if (Status!=STATUS_SUCCESS)
478 {
479 Log(("VBOXSF: DriverEntry: RxRegisterMinirdr failed: 0x%08X\n", Status ));
480 try_return((void)Status);
481 }
482
483 /* Init the device extension.
484 * NOTE: the device extension actually points to fields
485 * in the RDBSS_DEVICE_OBJECT. Our space is past the end
486 * of this struct!!
487 */
488 pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
489
490 pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject;
491
492 for (i = 0; i < RT_ELEMENTS(pDeviceExtension->cLocalConnections); i++)
493 {
494 pDeviceExtension->cLocalConnections[i] = FALSE;
495 }
496
497 /* Mutex for synchronizining our connection list */
498 ExInitializeFastMutex(&pDeviceExtension->mtxLocalCon);
499
500 /* The device object has been created. Need to setup a symbolic
501 * link so that the device may be accessed from a Win32 user mode
502 * application.
503 */
504
505 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
506 Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink\n"));
507 Status = IoCreateSymbolicLink(&UserModeDeviceName, &VBoxMRxName);
508 if (Status != STATUS_SUCCESS)
509 {
510 Log(("VBOXSF: DriverEntry: IoCreateSymbolicLink: 0x%08X\n",
511 Status));
512 try_return((void)Status);
513 }
514 Log(("VBOXSF: DriverEntry: Symbolic link created.\n"));
515
516 /*
517 * Build the dispatch tables for the minirdr
518 */
519 vbsfInitMRxDispatch();
520
521 try_exit:
522 ;
523 }
524 __finally
525 {
526 ;
527 }
528
529 if (Status != STATUS_SUCCESS)
530 {
531 Log(("VBOXSF: DriverEntry: VBoxSF.sys failed to start with Status = 0x%08X\n",
532 Status));
533 goto failure;
534 }
535
536 AssertPtr(pDeviceExtension);
537 pDeviceExtension->hgcmClient = hgcmClient;
538
539 /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution
540 * by other redirectors. These additional name resolutions cause long delays.
541 */
542 Log(("VBOXSF: DriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n",
543 VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension));
544 pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
545 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl;
546
547 /* @todo start the redirector here RxStartMiniRdr. */
548
549 Log(("VBOXSF: DriverEntry: Init successful!\n"));
550 return STATUS_SUCCESS;
551
552failure:
553
554 Log(("VBOXSF: DriverEntry: Failure! Status = 0x%08X\n", Status));
555
556 VbglR0SfDisconnect(&hgcmClient);
557 VbglR0SfTerm();
558
559 if (VBoxMRxDeviceObject)
560 {
561 RxUnregisterMinirdr(VBoxMRxDeviceObject);
562 VBoxMRxDeviceObject = NULL;
563 }
564
565 return Status;
566}
567
568NTSTATUS VBoxMRxStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
569{
570 NTSTATUS Status;
571 MRX_VBOX_STATE CurrentState;
572 RT_NOREF(RxContext, RxDeviceObject);
573
574 Log(("VBOXSF: MRxStart\n"));
575
576 CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS);
577
578 if (CurrentState == MRX_VBOX_START_IN_PROGRESS)
579 {
580 Log(("VBOXSF: MRxStart: Start in progress -> started\n"));
581 Status = STATUS_SUCCESS;
582 }
583 else if (VBoxMRxState == MRX_VBOX_STARTED)
584 {
585 Log(("VBOXSF: MRxStart: Already started\n"));
586 Status = STATUS_REDIRECTOR_STARTED;
587 }
588 else
589 {
590 Log(("VBOXSF: MRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState));
591 Status = STATUS_UNSUCCESSFUL;
592 }
593
594 return Status;
595}
596
597NTSTATUS VBoxMRxStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
598{
599 RT_NOREF(RxContext, RxDeviceObject);
600 Log(("VBOXSF: MRxStop\n"));
601 return STATUS_SUCCESS;
602}
603
604NTSTATUS VBoxMRxIoCtl(IN OUT PRX_CONTEXT RxContext)
605{
606 Log(("VBOXSF: MRxIoCtl: IoControlCode = 0x%08X\n",
607 RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode));
608 return STATUS_INVALID_DEVICE_REQUEST;
609}
610
611NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject(IN HANDLE Handle,
612 IN SECURITY_INFORMATION SecurityInformation,
613 IN PSECURITY_DESCRIPTOR SecurityDescriptor);
614
615NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext)
616{
617 NTSTATUS Status = STATUS_SUCCESS;
618 RxCaptureFobx;
619 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
620 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
621
622 Log(("VBOXSF: MRxDevFcbXXXControlFile: MajorFunction = 0x%02X\n",
623 RxContext->MajorFunction));
624
625 switch (RxContext->MajorFunction)
626 {
627 case IRP_MJ_FILE_SYSTEM_CONTROL:
628 {
629 Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: 0x%08X\n",
630 LowIoContext->ParamsFor.FsCtl.MinorFunction));
631 Status = STATUS_INVALID_DEVICE_REQUEST;
632 break;
633 }
634
635 case IRP_MJ_DEVICE_CONTROL:
636 {
637 Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MJ_DEVICE_CONTROL: InputBuffer %p/%d, OutputBuffer %p/%d\n",
638 LowIoContext->ParamsFor.IoCtl.pInputBuffer,
639 LowIoContext->ParamsFor.IoCtl.InputBufferLength,
640 LowIoContext->ParamsFor.IoCtl.pOutputBuffer,
641 LowIoContext->ParamsFor.IoCtl.OutputBufferLength));
642
643 switch (LowIoContext->ParamsFor.IoCtl.IoControlCode)
644 {
645 case IOCTL_MRX_VBOX_ADDCONN:
646 {
647 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
648 Status = vbsfCreateConnection(RxContext, &RxContext->PostRequest);
649 break;
650 }
651
652 case IOCTL_MRX_VBOX_DELCONN:
653 {
654 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
655 Status = vbsfDeleteConnection(RxContext, &RxContext->PostRequest);
656 break;
657 }
658
659 case IOCTL_MRX_VBOX_GETLIST:
660 {
661 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
662 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
663
664 BOOLEAN fLocked = FALSE;
665
666 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
667
668 RxContext->InformationToReturn = 0;
669
670 if ( !pDeviceExtension
671 || cbOut < _MRX_MAX_DRIVE_LETTERS)
672 {
673 Status = STATUS_INVALID_PARAMETER;
674 break;
675 }
676
677 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n"));
678
679 fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
680
681 __try
682 {
683 RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
684 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
685 }
686 __except(EXCEPTION_EXECUTE_HANDLER)
687 {
688 Status = STATUS_INVALID_PARAMETER;
689 }
690
691 if (fLocked)
692 {
693 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
694 fLocked = FALSE;
695 }
696
697 break;
698 }
699
700 /*
701 * Returns the root IDs of shared folder mappings.
702 */
703 case IOCTL_MRX_VBOX_GETGLOBALLIST:
704 {
705 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
706 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
707
708 int vboxRC;
709 SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
710 uint32_t cMappings = RT_ELEMENTS(mappings);
711
712 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
713
714 RxContext->InformationToReturn = 0;
715
716 if ( !pDeviceExtension
717 || cbOut < _MRX_MAX_DRIVE_LETTERS)
718 {
719 Status = STATUS_INVALID_PARAMETER;
720 break;
721 }
722
723 vboxRC = VbglR0SfQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings);
724 if (vboxRC == VINF_SUCCESS)
725 {
726 __try
727 {
728 uint32_t i;
729
730 RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS);
731
732 for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
733 {
734 pu8Out[i] = mappings[i].root;
735 pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */
736 }
737
738 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
739 }
740 __except(EXCEPTION_EXECUTE_HANDLER)
741 {
742 Status = STATUS_INVALID_PARAMETER;
743 }
744 }
745 else
746 {
747 Status = VBoxErrorToNTStatus(vboxRC);
748 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n",
749 Status));
750 }
751
752 break;
753 }
754
755 /*
756 * Translates a local connection name (e.g. drive "S:") to the
757 * corresponding remote name (e.g. \\vboxsrv\share).
758 */
759 case IOCTL_MRX_VBOX_GETCONN:
760 {
761 ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
762 PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
763 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
764 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
765
766 BOOLEAN fMutexAcquired = FALSE;
767
768 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN\n"));
769
770 RxContext->InformationToReturn = 0;
771
772 if ( !pDeviceExtension
773 || cbConnectName < sizeof(WCHAR))
774 {
775 Status = STATUS_INVALID_PARAMETER;
776 break;
777 }
778
779 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n"));
780
781 __try
782 {
783 uint32_t idx = *pwcConnectName - L'A';
784
785 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, Index = %d\n",
786 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, idx));
787
788 if (idx < RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName))
789 {
790 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
791 fMutexAcquired = TRUE;
792
793 if (pDeviceExtension->wszLocalConnectionName[idx])
794 {
795 ULONG cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length;
796
797 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n",
798 cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
799
800 if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName))
801 {
802 RtlZeroMemory(pwcRemoteName, cbRemoteName);
803 RtlCopyMemory(pwcRemoteName,
804 pDeviceExtension->wszLocalConnectionName[idx]->Buffer,
805 cbLocalConnectionName);
806
807 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n",
808 cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName));
809 }
810 else
811 {
812 Status = STATUS_BUFFER_TOO_SMALL;
813 }
814
815 RxContext->InformationToReturn = cbLocalConnectionName;
816 }
817 else
818 {
819 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
820 Status = STATUS_BAD_NETWORK_NAME;
821 }
822 }
823 else
824 {
825 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
826 Status = STATUS_INVALID_PARAMETER;
827 }
828 }
829 __except(EXCEPTION_EXECUTE_HANDLER)
830 {
831 Status = STATUS_INVALID_PARAMETER;
832 }
833
834 if (fMutexAcquired)
835 {
836 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
837 fMutexAcquired = FALSE;
838 }
839
840 break;
841 }
842
843 case IOCTL_MRX_VBOX_GETGLOBALCONN:
844 {
845 ULONG cbConnectId = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
846 uint8_t *pu8ConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
847 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
848 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
849
850 int vboxRC;
851 PSHFLSTRING pString;
852
853 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN\n"));
854
855 RxContext->InformationToReturn = 0;
856
857 if ( !pDeviceExtension
858 || cbConnectId < sizeof(uint8_t))
859 {
860 Status = STATUS_INVALID_PARAMETER;
861 break;
862 }
863
864 /* Allocate empty string where the host can store cbRemoteName bytes. */
865 Status = vbsfShflStringFromUnicodeAlloc(&pString, NULL, (uint16_t)cbRemoteName);
866 if (Status != STATUS_SUCCESS)
867 break;
868
869 __try
870 {
871 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d\n",
872 *pu8ConnectId));
873
874 vboxRC = VbglR0SfQueryMapName(&pDeviceExtension->hgcmClient,
875 (*pu8ConnectId) & ~0x80 /** @todo fix properly */,
876 pString, ShflStringSizeOfBuffer(pString));
877 if ( vboxRC == VINF_SUCCESS
878 && pString->u16Length < cbRemoteName)
879 {
880 RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length);
881 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n",
882 pString->u16Length / sizeof(WCHAR), pwcRemoteName, pString->u16Length));
883 RxContext->InformationToReturn = pString->u16Length;
884 }
885 else
886 {
887 Status = STATUS_BAD_NETWORK_NAME;
888 }
889 }
890 __except(EXCEPTION_EXECUTE_HANDLER)
891 {
892 Status = STATUS_INVALID_PARAMETER;
893 }
894
895 vbsfFreeNonPagedMem(pString);
896
897 break;
898 }
899
900 case IOCTL_MRX_VBOX_START:
901 {
902 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n",
903 capFobx));
904
905 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n",
906 IoGetCurrentProcess(), RxGetRDBSSProcess()));
907
908 switch (VBoxMRxState)
909 {
910 case MRX_VBOX_STARTABLE:
911
912 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n"));
913
914 if (capFobx)
915 {
916 Status = STATUS_INVALID_DEVICE_REQUEST;
917 break;;
918 }
919
920 InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
921
922 case MRX_VBOX_START_IN_PROGRESS:
923 Status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
924
925 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n",
926 Status, RxContext->PostRequest));
927
928 if (Status == STATUS_REDIRECTOR_STARTED)
929 {
930 Status = STATUS_SUCCESS;
931 break;
932 }
933
934 if ( Status == STATUS_PENDING
935 && RxContext->PostRequest == TRUE)
936 {
937 /* Will be restarted in RDBSS process. */
938 Status = STATUS_MORE_PROCESSING_REQUIRED;
939 break;
940 }
941
942 /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
943 if (Status == STATUS_SUCCESS)
944 {
945 SECURITY_DESCRIPTOR SecurityDescriptor;
946 OBJECT_ATTRIBUTES InitializedAttributes;
947 HANDLE hDevice;
948 IO_STATUS_BLOCK IoStatusBlock;
949 UNICODE_STRING UserModeDeviceName;
950
951 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
952
953 /* Create empty security descriptor */
954 RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
955 Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
956 if (Status != STATUS_SUCCESS)
957 {
958 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n",
959 Status));
960 return Status;
961 }
962
963 RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
964 InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
965
966 /* Open our symbolic link device name */
967 Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
968 if (Status != STATUS_SUCCESS)
969 {
970 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n",
971 DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
972 return Status;
973 }
974
975 /* Override the discretionary access control list (DACL) settings */
976 Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
977 if (Status != STATUS_SUCCESS)
978 {
979 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n",
980 Status));
981 return Status;
982 }
983
984 Status = ZwClose(hDevice);
985 if (Status != STATUS_SUCCESS)
986 {
987 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n",
988 Status));
989 return Status;
990 }
991 }
992 break;
993
994 case MRX_VBOX_STARTED:
995 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
996 Status = STATUS_SUCCESS;
997 break;
998
999 default:
1000 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n",
1001 VBoxMRxState));
1002 Status = STATUS_INVALID_PARAMETER;
1003 break;
1004 }
1005
1006 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n",
1007 Status));
1008 break;
1009 }
1010
1011 case IOCTL_MRX_VBOX_STOP:
1012 {
1013 MRX_VBOX_STATE CurrentState;
1014
1015 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n",
1016 capFobx));
1017
1018 if (capFobx)
1019 {
1020 Status = STATUS_INVALID_DEVICE_REQUEST;
1021 break;
1022 }
1023
1024 if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
1025 {
1026 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n",
1027 RxContext->RxDeviceObject->NumberOfActiveFcbs));
1028 Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
1029 break;
1030 }
1031
1032 CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
1033
1034 Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
1035 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n",
1036 Status));
1037
1038 if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
1039 Status = STATUS_MORE_PROCESSING_REQUIRED;
1040 break;
1041 }
1042
1043 default:
1044 Status = STATUS_INVALID_DEVICE_REQUEST;
1045 break;
1046 }
1047 break;
1048 }
1049
1050 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1051 {
1052 Status = STATUS_INVALID_DEVICE_REQUEST;
1053 break;
1054 }
1055
1056 default:
1057 Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n",
1058 RxContext->MajorFunction));
1059 Status = STATUS_INVALID_DEVICE_REQUEST;
1060 break;
1061 }
1062
1063 Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n",
1064 Status, RxContext->InformationToReturn));
1065
1066 return Status;
1067}
1068
1069static NTSTATUS vbsfVerifyConnectionName(PUNICODE_STRING ConnectionName)
1070{
1071 /* Check that the connection name is valid:
1072 * "\Device\VBoxMiniRdr\;X:\vboxsvr\sf"
1073 */
1074 NTSTATUS Status = STATUS_BAD_NETWORK_NAME;
1075
1076 ULONG i;
1077 PWCHAR pwc;
1078 PWCHAR pwc1;
1079
1080 static PWCHAR spwszPrefix = L"\\Device\\VBoxMiniRdr\\;";
1081
1082 /* Unicode chars in the string. */
1083 ULONG cConnectionName = ConnectionName->Length / sizeof(WCHAR);
1084 ULONG cRemainingName;
1085
1086 /* Check that the name starts with correct prefix. */
1087 pwc1 = &spwszPrefix[0];
1088 pwc = ConnectionName->Buffer;
1089 for (i = 0; i < cConnectionName; i++, pwc1++, pwc++)
1090 {
1091 if (*pwc1 == 0 || *pwc == 0 || *pwc1 != *pwc)
1092 break;
1093 }
1094
1095 cRemainingName = cConnectionName - i;
1096
1097 Log(("VBOXSF: vbsfVerifyConnectionName: prefix %d remaining %d [%.*ls]\n",
1098 *pwc1 == 0, cRemainingName, cRemainingName, &ConnectionName->Buffer[i]));
1099
1100 if (*pwc1 == 0)
1101 {
1102 /* pwc should point to a drive letter followed by ':\' that is at least 3 chars more. */
1103 if (cRemainingName >= 3)
1104 {
1105 if ( pwc[0] >= L'A' && pwc[0] <= L'Z'
1106 && pwc[1] == L':')
1107 {
1108 pwc += 2;
1109 cRemainingName -= 2;
1110
1111 /* @todo should also check that the drive letter corresponds to the name. */
1112 if (vboxIsPrefixOK(pwc, cRemainingName * sizeof (WCHAR)))
1113 Status = STATUS_SUCCESS;
1114 }
1115 }
1116 }
1117
1118 return Status;
1119}
1120
1121static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName, NTSTATUS *prcNt)
1122{
1123 NTSTATUS Status;
1124 IO_STATUS_BLOCK IoStatusBlock;
1125 OBJECT_ATTRIBUTES ObjectAttributes;
1126
1127 HANDLE Handle = INVALID_HANDLE_VALUE;
1128
1129 Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n",
1130 ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer));
1131
1132 Status = vbsfVerifyConnectionName(ConnectionName);
1133
1134 if (NT_SUCCESS(Status))
1135 {
1136 /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */
1137 InitializeObjectAttributes(&ObjectAttributes,
1138 ConnectionName,
1139 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1140 NULL,
1141 NULL);
1142
1143 Status = ZwCreateFile(&Handle,
1144 SYNCHRONIZE,
1145 &ObjectAttributes,
1146 &IoStatusBlock,
1147 NULL,
1148 FILE_ATTRIBUTE_NORMAL,
1149 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1150 FILE_OPEN_IF,
1151 FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
1152 NULL,
1153 0);
1154 }
1155
1156 if ( Status != STATUS_SUCCESS
1157 || Handle == INVALID_HANDLE_VALUE)
1158 {
1159 Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n", Status));
1160 if (prcNt)
1161 *prcNt = !NT_SUCCESS(Status) ? Status : STATUS_UNSUCCESSFUL;
1162 Handle = INVALID_HANDLE_VALUE;
1163 }
1164
1165 return Handle;
1166}
1167
1168NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1169{
1170 NTSTATUS Status = STATUS_SUCCESS;
1171
1172 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1173
1174 PLOWIO_CONTEXT LowIoContext;
1175 ULONG cbConnectName;
1176 PWCHAR pwcConnectName;
1177
1178 HANDLE Handle;
1179 UNICODE_STRING FileName;
1180
1181 BOOLEAN fMutexAcquired = FALSE;
1182
1183 Log(("VBOXSF: vbsfCreateConnection\n"));
1184
1185 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1186 {
1187 Log(("VBOXSF: vbsfCreateConnection: post to file system process\n"));
1188 *PostToFsp = TRUE;
1189 return STATUS_PENDING;
1190 }
1191
1192 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1193 if (!pDeviceExtension)
1194 return STATUS_INVALID_PARAMETER;
1195
1196 LowIoContext = &RxContext->LowIoContext;
1197 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1198 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1199
1200 if (cbConnectName == 0 || !pwcConnectName)
1201 {
1202 Log(("VBOXSF: vbsfCreateConnection: Connection name / length is invalid!\n"));
1203 return STATUS_INVALID_PARAMETER;
1204 }
1205
1206 __try
1207 {
1208 Log(("VBOXSF: vbsfCreateConnection: Name = %.*ls, Len = %d\n",
1209 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName));
1210
1211 FileName.Buffer = pwcConnectName;
1212 FileName.Length = (USHORT)cbConnectName;
1213 FileName.MaximumLength = (USHORT)cbConnectName;
1214
1215 Handle = vbsfOpenConnectionHandle(&FileName, NULL);
1216
1217 if (Handle != INVALID_HANDLE_VALUE)
1218 {
1219 PWCHAR pwc;
1220 ULONG i;
1221
1222 ZwClose(Handle);
1223
1224 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1225 pwc = pwcConnectName;
1226 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1227 {
1228 if (*pwc == L':')
1229 break;
1230 pwc++;
1231 }
1232
1233 if (i >= sizeof(WCHAR) && i < cbConnectName)
1234 {
1235 pwc--; /* Go back to the drive letter, "X" for example. */
1236
1237 if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */
1238 {
1239 uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */
1240
1241 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1242 {
1243 Log(("VBOXSF: vbsfCreateConnection: Index 0x%x is invalid!\n",
1244 idx));
1245 Status = STATUS_BAD_NETWORK_NAME;
1246 }
1247 else
1248 {
1249 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1250 fMutexAcquired = TRUE;
1251
1252 if (pDeviceExtension->wszLocalConnectionName[idx] != NULL)
1253 {
1254 Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d is NOT empty!\n",
1255 idx));
1256 }
1257
1258 pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName);
1259
1260 if (!pDeviceExtension->wszLocalConnectionName[idx])
1261 {
1262 Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n",
1263 idx));
1264 Status = STATUS_INSUFFICIENT_RESOURCES;
1265 }
1266 else
1267 {
1268 PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
1269
1270 pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
1271 pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR));
1272 pRemoteName->MaximumLength = pRemoteName->Length;
1273 RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length);
1274
1275 Log(("VBOXSF: vbsfCreateConnection: RemoteName %.*ls, Len = %d\n",
1276 pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
1277
1278 pDeviceExtension->cLocalConnections[idx] = TRUE;
1279 }
1280
1281 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1282 fMutexAcquired = FALSE;
1283 }
1284 }
1285 }
1286 else
1287 {
1288 Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
1289 Status = STATUS_BAD_NETWORK_NAME;
1290 }
1291 }
1292 else
1293 {
1294 Log(("VBOXSF: vbsfCreateConnection: connection was not found\n"));
1295 Status = STATUS_BAD_NETWORK_NAME;
1296 }
1297 }
1298 __except(EXCEPTION_EXECUTE_HANDLER)
1299 {
1300 Status = STATUS_INVALID_PARAMETER;
1301 }
1302
1303 if (fMutexAcquired)
1304 {
1305 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1306 fMutexAcquired = FALSE;
1307 }
1308
1309 return Status;
1310}
1311
1312NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1313{
1314 NTSTATUS Status;
1315 UNICODE_STRING FileName;
1316 HANDLE Handle;
1317 PLOWIO_CONTEXT LowIoContext;
1318 PWCHAR pwcConnectName;
1319 ULONG cbConnectName;
1320 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1321
1322 BOOLEAN fMutexAcquired = FALSE;
1323
1324 Log(("VBOXSF: vbsfDeleteConnection\n"));
1325
1326 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1327 {
1328 Log(("VBOXSF: vbsfDeleteConnection: post to file system process\n"));
1329 *PostToFsp = TRUE;
1330 return STATUS_PENDING;
1331 }
1332
1333 LowIoContext = &RxContext->LowIoContext;
1334 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1335 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1336
1337 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1338 if (!pDeviceExtension)
1339 return STATUS_INVALID_PARAMETER;
1340
1341 __try
1342 {
1343 Log(("VBOXSF: vbsfDeleteConnection: pwcConnectName = %.*ls\n",
1344 cbConnectName / sizeof(WCHAR), pwcConnectName));
1345
1346 FileName.Buffer = pwcConnectName;
1347 FileName.Length = (USHORT)cbConnectName;
1348 FileName.MaximumLength = (USHORT)cbConnectName;
1349
1350 Handle = vbsfOpenConnectionHandle(&FileName, &Status);
1351 if (Handle != INVALID_HANDLE_VALUE)
1352 {
1353 PFILE_OBJECT pFileObject;
1354 Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
1355
1356 Log(("VBOXSF: vbsfDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n",
1357 Status));
1358
1359 if (NT_SUCCESS(Status))
1360 {
1361 PFOBX Fobx = (PFOBX)pFileObject->FsContext2;
1362 Log(("VBOXSF: vbsfDeleteConnection: Fobx %p\n", Fobx));
1363
1364 if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
1365 {
1366 PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
1367
1368 Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
1369 }
1370 else
1371 {
1372 Log(("VBOXSF: vbsfDeleteConnection: wrong FsContext2\n"));
1373 Status = STATUS_INVALID_DEVICE_REQUEST;
1374 }
1375
1376 ObDereferenceObject(pFileObject);
1377 }
1378
1379 ZwClose(Handle);
1380
1381 if (NT_SUCCESS(Status))
1382 {
1383 PWCHAR pwc;
1384 ULONG i;
1385
1386 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1387 pwc = pwcConnectName;
1388 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1389 {
1390 if (*pwc == L':')
1391 {
1392 break;
1393 }
1394 pwc++;
1395 }
1396
1397 if (i >= sizeof(WCHAR) && i < cbConnectName)
1398 {
1399 pwc--;
1400
1401 if (*pwc >= L'A' && *pwc <= L'Z')
1402 {
1403 uint32_t idx = *pwc - L'A';
1404
1405 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1406 {
1407 Log(("VBOXSF: vbsfDeleteConnection: Index 0x%x is invalid!\n",
1408 idx));
1409 Status = STATUS_BAD_NETWORK_NAME;
1410 }
1411 else
1412 {
1413 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1414 fMutexAcquired = TRUE;
1415
1416 pDeviceExtension->cLocalConnections[idx] = FALSE;
1417
1418 /* Free saved name */
1419 if (pDeviceExtension->wszLocalConnectionName[idx])
1420 {
1421 vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
1422 pDeviceExtension->wszLocalConnectionName[idx] = NULL;
1423 }
1424
1425 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1426 fMutexAcquired = FALSE;
1427
1428 Log(("VBOXSF: vbsfDeleteConnection: deleted index 0x%x\n",
1429 idx));
1430 }
1431 }
1432 }
1433 else
1434 {
1435 Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
1436 Status = STATUS_BAD_NETWORK_NAME;
1437 }
1438 }
1439 }
1440 }
1441 __except(EXCEPTION_EXECUTE_HANDLER)
1442 {
1443 Status = STATUS_INVALID_PARAMETER;
1444 }
1445
1446 if (fMutexAcquired)
1447 {
1448 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1449 fMutexAcquired = FALSE;
1450 }
1451
1452 Log(("VBOXSF: vbsfDeleteConnection: Status 0x%08X\n", Status));
1453 return Status;
1454}
1455
1456NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext)
1457{
1458 Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n",
1459 RxContext->Info.LengthRemaining));
1460 return STATUS_SUCCESS;
1461}
1462
1463NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext)
1464{
1465 RT_NOREF(RxContext);
1466 Log(("VBOXSF: MRxSetEaInfo\n"));
1467 return STATUS_NOT_IMPLEMENTED;
1468}
1469
1470NTSTATUS VBoxMRxFsCtl (IN OUT PRX_CONTEXT RxContext)
1471{
1472 RT_NOREF(RxContext);
1473 Log(("VBOXSF: MRxFsCtl\n"));
1474 return STATUS_INVALID_DEVICE_REQUEST;
1475}
1476
1477NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext)
1478{
1479 RT_NOREF(RxContext);
1480 Log(("VBOXSF: MRxNotifyChangeDirectory\n"));
1481 return STATUS_NOT_IMPLEMENTED;
1482}
1483
1484NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext)
1485{
1486 RT_NOREF(RxContext);
1487 Log(("VBOXSF: MRxQuerySdInfo\n"));
1488 return STATUS_NOT_IMPLEMENTED;
1489}
1490
1491NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext)
1492{
1493 RT_NOREF(RxContext);
1494 Log(("VBOXSF: MRxSetSdInfo\n"));
1495 return STATUS_NOT_IMPLEMENTED;
1496}
1497
1498/*
1499 * WML stubs which are referenced by rdbsslib.
1500 */
1501NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp)
1502{
1503 RT_NOREF(pWmiLibInfo, pDevObj, pIrp);
1504 return STATUS_WMI_GUID_NOT_FOUND;
1505}
1506
1507ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...)
1508{
1509 RT_NOREF(ulType, pTraceUuid, ullLogger);
1510 return STATUS_SUCCESS;
1511}
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