VirtualBox

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

Last change on this file since 106506 was 106172, checked in by vboxsync, 4 months ago

Add/Nt/Shfl: Add product version and revision to the early release logging in DriverEntry to help tell what's being loaded. bugref:10766

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