VirtualBox

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

Last change on this file since 55628 was 51997, checked in by vboxsync, 10 years ago

include,Main,Additions: SHFLSTRING cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 53.1 KB
Line 
1/* $Id: vbsf.c 51997 2014-07-11 21:04:44Z 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 vboxDisconnect (&pDeviceExtension->hgcmClient);
85 }
86
87 vboxUninit();
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 VBSFCLIENT 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 = vboxInit();
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 = vboxConnect(&hgcmClient);
434 if (RT_FAILURE(vboxRC))
435 {
436 Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n",
437 vboxRC));
438 vboxUninit();
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 vboxDisconnect(&hgcmClient);
558 vboxUninit();
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 switch (LowIoContext->ParamsFor.IoCtl.IoControlCode)
637 {
638 case IOCTL_MRX_VBOX_ADDCONN:
639 {
640 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
641 Status = vbsfCreateConnection(RxContext, &RxContext->PostRequest);
642 break;
643 }
644
645 case IOCTL_MRX_VBOX_DELCONN:
646 {
647 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
648 Status = vbsfDeleteConnection(RxContext, &RxContext->PostRequest);
649 break;
650 }
651
652 case IOCTL_MRX_VBOX_GETLIST:
653 {
654 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
655 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
656
657 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
658
659 if (!pDeviceExtension)
660 {
661 RxContext->InformationToReturn = 0;
662 break;
663 }
664
665 if (cbOut >= _MRX_MAX_DRIVE_LETTERS && pu8Out)
666 {
667 BOOLEAN fLocked = FALSE;
668
669 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n"));
670
671 fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
672
673 RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
674
675 if (fLocked)
676 {
677 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
678 }
679
680 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
681 }
682 else
683 {
684 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: cbOut is too small %d bytes\n",
685 cbOut));
686 RxContext->InformationToReturn = 0;
687 }
688
689 Status = STATUS_SUCCESS;
690 break;
691 }
692
693 /*
694 * Returns the root IDs of shared folder mappings.
695 */
696 case IOCTL_MRX_VBOX_GETGLOBALLIST:
697 {
698 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
699 uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
700
701 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
702
703 RxContext->InformationToReturn = 0;
704
705 if (!pDeviceExtension)
706 break;
707
708 if (cbOut >= _MRX_MAX_DRIVE_LETTERS && pu8Out)
709 {
710 SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
711 uint32_t cMappings = RT_ELEMENTS(mappings);
712
713 int vboxRC = vboxCallQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings);
714
715 if (vboxRC == VINF_SUCCESS)
716 {
717 uint32_t i;
718
719 RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS);
720
721 for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
722 {
723 pu8Out[i] = mappings[i].root;
724 pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */
725 }
726
727 RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
728 }
729 else
730 {
731 Status = VBoxErrorToNTStatus(vboxRC);
732 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n",
733 Status));
734 }
735 }
736
737 Status = STATUS_SUCCESS;
738 break;
739 }
740
741 /*
742 * Translates a local connection name (e.g. drive "S:") to the
743 * corresponding remote name (e.g. \\vboxsrv\share).
744 */
745 case IOCTL_MRX_VBOX_GETCONN:
746 {
747 ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
748 PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
749
750 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
751 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
752
753 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, RemoteName = 0x%p, Len = %d\n",
754 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, pwcRemoteName, cbRemoteName));
755
756 if (!pDeviceExtension)
757 {
758 Status = STATUS_INVALID_PARAMETER;
759 break;
760 }
761
762 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n"));
763
764 if (cbConnectName > sizeof(WCHAR) && pwcConnectName)
765 {
766 ULONG cbLocalConnectionName;
767
768 uint32_t idx = *pwcConnectName - L'A';
769
770 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index = %d\n", idx));
771
772 if (idx >= RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName))
773 {
774 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
775 Status = STATUS_INVALID_PARAMETER;
776 break;
777 }
778
779 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
780
781 if (!pDeviceExtension->wszLocalConnectionName[idx])
782 {
783 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
784 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
785 Status = STATUS_BAD_NETWORK_NAME;
786 break;
787 }
788
789 cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length;
790
791 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n",
792 cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
793
794 if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName))
795 {
796 RtlZeroMemory(pwcRemoteName, cbRemoteName);
797 RtlCopyMemory(pwcRemoteName, pDeviceExtension->wszLocalConnectionName[idx]->Buffer, cbLocalConnectionName);
798
799 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n",
800 cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName));
801
802 RxContext->InformationToReturn = cbLocalConnectionName;
803 }
804 else
805 {
806 Status = STATUS_BUFFER_TOO_SMALL;
807 RxContext->InformationToReturn = cbLocalConnectionName;
808 }
809
810 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
811 }
812 else
813 {
814 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: bad connect name!n"));
815 Status = STATUS_BAD_NETWORK_NAME;
816 }
817
818 break;
819 }
820
821 case IOCTL_MRX_VBOX_GETGLOBALCONN:
822 {
823 ULONG ReturnedSize = 0;
824
825 uint8_t *pConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
826 ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
827 PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
828
829 int vboxRC;
830 PSHFLSTRING pString;
831
832 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d, RemoteName = 0x%x, Len = %d\n",
833 *pConnectId, pwcRemoteName, cbRemoteName));
834
835 /* Allocate empty string where the host can store cbRemoteName bytes. */
836 Status = vbsfShflStringFromUnicodeAlloc(&pString, NULL, (uint16_t)cbRemoteName);
837 if (Status != STATUS_SUCCESS)
838 break;
839
840 vboxRC = vboxCallQueryMapName(&pDeviceExtension->hgcmClient,
841 (*pConnectId) & ~0x80 /** @todo fix properly */,
842 pString, ShflStringSizeOfBuffer(pString));
843 if ( vboxRC == VINF_SUCCESS
844 && pString->u16Length < cbRemoteName)
845 {
846 ReturnedSize = pString->u16Length;
847 RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length);
848 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n",
849 ReturnedSize / sizeof(WCHAR), pwcRemoteName, ReturnedSize));
850 Status = STATUS_SUCCESS;
851 }
852 else
853 Status = STATUS_BAD_NETWORK_NAME;
854
855 vbsfFreeNonPagedMem(pString);
856
857 RxContext->InformationToReturn = ReturnedSize;
858 break;
859 }
860
861 case IOCTL_MRX_VBOX_START:
862 {
863 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n",
864 capFobx));
865
866 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n",
867 IoGetCurrentProcess(), RxGetRDBSSProcess()));
868
869 switch (VBoxMRxState)
870 {
871 case MRX_VBOX_STARTABLE:
872
873 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n"));
874
875 if (capFobx)
876 {
877 Status = STATUS_INVALID_DEVICE_REQUEST;
878 break;;
879 }
880
881 InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
882
883 case MRX_VBOX_START_IN_PROGRESS:
884 Status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
885
886 Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n",
887 Status, RxContext->PostRequest));
888
889 if (Status == STATUS_REDIRECTOR_STARTED)
890 {
891 Status = STATUS_SUCCESS;
892 break;
893 }
894
895 if ( Status == STATUS_PENDING
896 && RxContext->PostRequest == TRUE)
897 {
898 /* Will be restarted in RDBSS process. */
899 Status = STATUS_MORE_PROCESSING_REQUIRED;
900 break;
901 }
902
903 /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
904 if (Status == STATUS_SUCCESS)
905 {
906 SECURITY_DESCRIPTOR SecurityDescriptor;
907 OBJECT_ATTRIBUTES InitializedAttributes;
908 HANDLE hDevice;
909 IO_STATUS_BLOCK IoStatusBlock;
910 UNICODE_STRING UserModeDeviceName;
911
912 RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
913
914 /* Create empty security descriptor */
915 RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
916 Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
917 if (Status != STATUS_SUCCESS)
918 {
919 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n",
920 Status));
921 return Status;
922 }
923
924 RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
925 InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
926
927 /* Open our symbolic link device name */
928 Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
929 if (Status != STATUS_SUCCESS)
930 {
931 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n",
932 DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
933 return Status;
934 }
935
936 /* Override the discretionary access control list (DACL) settings */
937 Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
938 if (Status != STATUS_SUCCESS)
939 {
940 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n",
941 Status));
942 return Status;
943 }
944
945 Status = ZwClose(hDevice);
946 if (Status != STATUS_SUCCESS)
947 {
948 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n",
949 Status));
950 return Status;
951 }
952 }
953 break;
954
955 case MRX_VBOX_STARTED:
956 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
957 Status = STATUS_SUCCESS;
958 break;
959
960 default:
961 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n",
962 VBoxMRxState));
963 Status = STATUS_INVALID_PARAMETER;
964 break;
965 }
966
967 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n",
968 Status));
969 break;
970 }
971
972 case IOCTL_MRX_VBOX_STOP:
973 {
974 MRX_VBOX_STATE CurrentState;
975
976 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n",
977 capFobx));
978
979 if (capFobx)
980 {
981 Status = STATUS_INVALID_DEVICE_REQUEST;
982 break;
983 }
984
985 if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
986 {
987 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n",
988 RxContext->RxDeviceObject->NumberOfActiveFcbs));
989 Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
990 break;
991 }
992
993 CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
994
995 Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
996 Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n",
997 Status));
998
999 if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
1000 Status = STATUS_MORE_PROCESSING_REQUIRED;
1001 break;
1002 }
1003
1004 default:
1005 Status = STATUS_INVALID_DEVICE_REQUEST;
1006 break;
1007 }
1008 break;
1009 }
1010
1011 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1012 {
1013 Status = STATUS_INVALID_DEVICE_REQUEST;
1014 break;
1015 }
1016
1017 default:
1018 Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n",
1019 RxContext->MajorFunction));
1020 Status = STATUS_INVALID_DEVICE_REQUEST;
1021 break;
1022 }
1023
1024 Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n",
1025 Status, RxContext->InformationToReturn));
1026
1027 return Status;
1028}
1029
1030static NTSTATUS vbsfVerifyConnectionName(PUNICODE_STRING ConnectionName)
1031{
1032 /* Check that the connection name is valid:
1033 * "\Device\VBoxMiniRdr\;X:\vboxsvr\sf"
1034 */
1035 NTSTATUS Status = STATUS_BAD_NETWORK_NAME;
1036
1037 ULONG i;
1038 PWCHAR pwc;
1039 PWCHAR pwc1;
1040
1041 static PWCHAR spwszPrefix = L"\\Device\\VBoxMiniRdr\\;";
1042
1043 /* Unicode chars in the string. */
1044 ULONG cConnectionName = ConnectionName->Length / sizeof(WCHAR);
1045 ULONG cRemainingName;
1046
1047 /* Check that the name starts with correct prefix. */
1048 pwc1 = &spwszPrefix[0];
1049 pwc = ConnectionName->Buffer;
1050 for (i = 0; i < cConnectionName; i++, pwc1++, pwc++)
1051 {
1052 if (*pwc1 == 0 || *pwc == 0 || *pwc1 != *pwc)
1053 break;
1054 }
1055
1056 cRemainingName = cConnectionName - i;
1057
1058 Log(("VBOXSF: vbsfVerifyConnectionName: prefix %d remaining %d [%.*ls]\n",
1059 *pwc1 == 0, cRemainingName, cRemainingName, &ConnectionName->Buffer[i]));
1060
1061 if (*pwc1 == 0)
1062 {
1063 /* pwc should point to a drive letter followed by ':\' that is at least 3 chars more. */
1064 if (cRemainingName >= 3)
1065 {
1066 if ( pwc[0] >= L'A' && pwc[0] <= L'Z'
1067 && pwc[1] == L':')
1068 {
1069 pwc += 2;
1070 cRemainingName -= 2;
1071
1072 /* @todo should also check that the drive letter corresponds to the name. */
1073 if (vboxIsPrefixOK(pwc, cRemainingName * sizeof (WCHAR)))
1074 Status = STATUS_SUCCESS;
1075 }
1076 }
1077 }
1078
1079 return Status;
1080}
1081
1082static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName)
1083{
1084 NTSTATUS Status;
1085 IO_STATUS_BLOCK IoStatusBlock;
1086 OBJECT_ATTRIBUTES ObjectAttributes;
1087
1088 HANDLE Handle = INVALID_HANDLE_VALUE;
1089
1090 Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n",
1091 ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer));
1092
1093 Status = vbsfVerifyConnectionName(ConnectionName);
1094
1095 if (NT_SUCCESS(Status))
1096 {
1097 /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */
1098 InitializeObjectAttributes(&ObjectAttributes,
1099 ConnectionName,
1100 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1101 NULL,
1102 NULL);
1103
1104 Status = ZwCreateFile(&Handle,
1105 SYNCHRONIZE,
1106 &ObjectAttributes,
1107 &IoStatusBlock,
1108 NULL,
1109 FILE_ATTRIBUTE_NORMAL,
1110 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1111 FILE_OPEN_IF,
1112 FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
1113 NULL,
1114 0);
1115 }
1116
1117 if ( Status != STATUS_SUCCESS
1118 || Handle == INVALID_HANDLE_VALUE)
1119 {
1120 Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n",
1121 Status));
1122 Handle = INVALID_HANDLE_VALUE;
1123 }
1124
1125 return Handle;
1126}
1127
1128NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1129{
1130 NTSTATUS Status = STATUS_SUCCESS;
1131
1132 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1133
1134 PLOWIO_CONTEXT LowIoContext;
1135 ULONG cbConnectName;
1136 PWCHAR pwcConnectName;
1137
1138 HANDLE Handle;
1139 UNICODE_STRING FileName;
1140
1141 Log(("VBOXSF: vbsfCreateConnection\n"));
1142
1143 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1144 {
1145 Log(("VBOXSF: vbsfCreateConnection: post to file system process\n"));
1146 *PostToFsp = TRUE;
1147 return STATUS_PENDING;
1148 }
1149
1150 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1151
1152 LowIoContext = &RxContext->LowIoContext;
1153 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1154 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1155
1156 if (!pDeviceExtension)
1157 return STATUS_INVALID_PARAMETER;
1158
1159 if (cbConnectName == 0 || !pwcConnectName)
1160 {
1161 Log(("VBOXSF: vbsfCreateConnection: Connection name / length is invalid!\n"));
1162 return STATUS_INVALID_PARAMETER;
1163 }
1164
1165 Log(("VBOXSF: vbsfCreateConnection: Name = %.*ls, Len = %d\n",
1166 cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName));
1167
1168 FileName.Buffer = pwcConnectName;
1169 FileName.Length = (USHORT)cbConnectName;
1170 FileName.MaximumLength = (USHORT)cbConnectName;
1171
1172 Handle = vbsfOpenConnectionHandle(&FileName);
1173
1174 if (Handle != INVALID_HANDLE_VALUE)
1175 {
1176 PWCHAR pwc;
1177 ULONG i;
1178
1179 ZwClose(Handle);
1180
1181 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1182 pwc = pwcConnectName;
1183 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1184 {
1185 if (*pwc == L':')
1186 break;
1187 pwc++;
1188 }
1189
1190 if (i >= sizeof(WCHAR) && i < cbConnectName)
1191 {
1192 pwc--; /* Go back to the drive letter, "X" for example. */
1193
1194 if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */
1195 {
1196 uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */
1197
1198 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1199 {
1200 Log(("VBOXSF: vbsfCreateConnection: Index 0x%x is invalid!\n",
1201 idx));
1202 Status = STATUS_BAD_NETWORK_NAME;
1203 }
1204 else
1205 {
1206 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1207
1208 if (pDeviceExtension->wszLocalConnectionName[idx] != NULL)
1209 {
1210 Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d is NOT empty!\n",
1211 idx));
1212 }
1213
1214 pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName);
1215
1216 if (!pDeviceExtension->wszLocalConnectionName[idx])
1217 {
1218 Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n",
1219 idx));
1220 Status = STATUS_INSUFFICIENT_RESOURCES;
1221 }
1222 else
1223 {
1224 PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
1225
1226 pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
1227 pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR));
1228 pRemoteName->MaximumLength = pRemoteName->Length;
1229 RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length);
1230
1231 Log(("VBOXSF: vbsfCreateConnection: RemoteName %.*ls, Len = %d\n",
1232 pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
1233
1234 pDeviceExtension->cLocalConnections[idx] = TRUE;
1235 }
1236
1237 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1238 }
1239 }
1240 }
1241 else
1242 {
1243 Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
1244 Status = STATUS_BAD_NETWORK_NAME;
1245 }
1246 }
1247 else
1248 {
1249 Log(("VBOXSF: vbsfCreateConnection: connection was not found\n"));
1250 Status = STATUS_BAD_NETWORK_NAME;
1251 }
1252
1253 return Status;
1254}
1255
1256NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
1257{
1258 NTSTATUS Status;
1259 UNICODE_STRING FileName;
1260 HANDLE Handle;
1261 PLOWIO_CONTEXT LowIoContext;
1262 PWCHAR pwcConnectName;
1263 ULONG cbConnectName;
1264 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
1265
1266 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
1267 {
1268 Log(("VBOXSF: vbsfDeleteConnection: post to file system process\n"));
1269 *PostToFsp = TRUE;
1270 return STATUS_PENDING;
1271 }
1272
1273 LowIoContext = &RxContext->LowIoContext;
1274 pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1275 cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1276
1277 pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1278
1279 Log(("VBOXSF: vbsfDeleteConnection: pwcConnectName = %.*ls\n",
1280 cbConnectName / sizeof(WCHAR), pwcConnectName));
1281
1282 FileName.Buffer = pwcConnectName;
1283 FileName.Length = (USHORT)cbConnectName;
1284 FileName.MaximumLength = (USHORT)cbConnectName;
1285
1286 Handle = vbsfOpenConnectionHandle(&FileName);
1287
1288 if (Handle != INVALID_HANDLE_VALUE)
1289 {
1290 PFILE_OBJECT pFileObject;
1291 Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
1292
1293 Log(("VBOXSF: vbsfDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n",
1294 Status));
1295
1296 if (NT_SUCCESS(Status))
1297 {
1298 PFOBX Fobx = (PFOBX)pFileObject->FsContext2;
1299 Log(("VBOXSF: vbsfDeleteConnection: Fobx %p\n", Fobx));
1300
1301 if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
1302 {
1303 PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
1304
1305 Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
1306 }
1307 else
1308 {
1309 Log(("VBOXSF: vbsfDeleteConnection: wrong FsContext2\n"));
1310 Status = STATUS_INVALID_DEVICE_REQUEST;
1311 }
1312
1313 ObDereferenceObject(pFileObject);
1314 }
1315
1316 ZwClose(Handle);
1317 }
1318
1319 if (NT_SUCCESS(Status))
1320 {
1321 PWCHAR pwc;
1322 ULONG i;
1323
1324 /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
1325 pwc = pwcConnectName;
1326 for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
1327 {
1328 if (*pwc == L':')
1329 {
1330 break;
1331 }
1332 pwc++;
1333 }
1334
1335 if (i >= sizeof(WCHAR) && i < cbConnectName)
1336 {
1337 pwc--;
1338
1339 if (*pwc >= L'A' && *pwc <= L'Z')
1340 {
1341 uint32_t idx = *pwc - L'A';
1342
1343 if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
1344 {
1345 Log(("VBOXSF: vbsfDeleteConnection: Index 0x%x is invalid!\n",
1346 idx));
1347 Status = STATUS_BAD_NETWORK_NAME;
1348 }
1349 else
1350 {
1351 ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
1352
1353 pDeviceExtension->cLocalConnections[idx] = FALSE;
1354
1355 /* Free saved name */
1356 if (pDeviceExtension->wszLocalConnectionName[idx])
1357 {
1358 vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
1359 pDeviceExtension->wszLocalConnectionName[idx] = NULL;
1360 }
1361
1362 ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
1363
1364 Log(("VBOXSF: vbsfDeleteConnection: deleted index 0x%x\n",
1365 idx));
1366 }
1367 }
1368 }
1369 else
1370 {
1371 Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
1372 Status = STATUS_BAD_NETWORK_NAME;
1373 }
1374 }
1375
1376 Log(("VBOXSF: vbsfDeleteConnection: Status 0x%08X\n", Status));
1377 return Status;
1378}
1379
1380NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext)
1381{
1382 Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n",
1383 RxContext->Info.LengthRemaining));
1384 return STATUS_SUCCESS;
1385}
1386
1387NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext)
1388{
1389 Log(("VBOXSF: MRxSetEaInfo\n"));
1390 return STATUS_NOT_IMPLEMENTED;
1391}
1392
1393NTSTATUS VBoxMRxFsCtl (IN OUT PRX_CONTEXT RxContext)
1394{
1395 Log(("VBOXSF: MRxFsCtl\n"));
1396 return STATUS_INVALID_DEVICE_REQUEST;
1397}
1398
1399NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext)
1400{
1401 Log(("VBOXSF: MRxNotifyChangeDirectory\n"));
1402 return STATUS_NOT_IMPLEMENTED;
1403}
1404
1405NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext)
1406{
1407 Log(("VBOXSF: MRxQuerySdInfo\n"));
1408 return STATUS_NOT_IMPLEMENTED;
1409}
1410
1411NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext)
1412{
1413 Log(("VBOXSF: MRxSetSdInfo\n"));
1414 return STATUS_NOT_IMPLEMENTED;
1415}
1416
1417/*
1418 * WML stubs which are referenced by rdbsslib.
1419 */
1420NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp)
1421{
1422 return STATUS_WMI_GUID_NOT_FOUND;
1423}
1424
1425ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...)
1426{
1427 return STATUS_SUCCESS;
1428}
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