VirtualBox

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

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

winnt/vboxsf: DriverEntry cleaning up... bugref:9172

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

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