VirtualBox

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

Last change on this file since 58361 was 58361, checked in by vboxsync, 9 years ago

Additions/WINNT/SharedFolders: IOCTL processing cleanup, logging.

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