VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/net.c@ 76553

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.2 KB
Line 
1/* $Id: net.c 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - File System Driver network redirector subsystem 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#include "vbsf.h"
19
20NTSTATUS VBoxMRxUpdateNetRootState(IN OUT PMRX_NET_ROOT pNetRoot)
21{
22 RT_NOREF(pNetRoot);
23 Log(("VBOXSF: MRxUpdateNetRootState\n"));
24 return STATUS_NOT_IMPLEMENTED;
25}
26
27static void vbsfUpdateNetRoot(PMRX_NET_ROOT pNetRoot)
28{
29 Log(("VBOXSF: vbsfUpdateNetRoot: NetRoot = 0x%x Type = 0x%x\n",
30 pNetRoot, pNetRoot->Type));
31
32 switch (pNetRoot->Type)
33 {
34 case NET_ROOT_DISK:
35 pNetRoot->DeviceType = RxDeviceType(DISK);
36 break;
37 case NET_ROOT_PIPE:
38 pNetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
39 break;
40 case NET_ROOT_COMM:
41 pNetRoot->DeviceType = RxDeviceType(SERIAL_PORT);
42 break;
43 case NET_ROOT_PRINT:
44 pNetRoot->DeviceType = RxDeviceType(PRINTER);
45 break;
46 case NET_ROOT_MAILSLOT:
47 pNetRoot->DeviceType = RxDeviceType(MAILSLOT);
48 break;
49 case NET_ROOT_WILD:
50 /* We get this type when for example Windows Media player opens an MP3 file.
51 * This NetRoot has the same remote path (\\vboxsrv\dir) as other NetRoots,
52 * which were created earlier and which were NET_ROOT_DISK.
53 *
54 * In the beginning of the function (UpdateNetRoot) the DDK sample sets
55 * pNetRoot->Type of newly created NetRoots using a value previously
56 * pstored in a NetRootExtension. One NetRootExtensions is used for a single
57 * remote path and reused by a few NetRoots, if they point to the same path.
58 *
59 * To simplify things we just set the type to DISK here (we do not support
60 * anything else anyway), and update the DeviceType correspondingly.
61 */
62 pNetRoot->Type = NET_ROOT_DISK;
63 pNetRoot->DeviceType = RxDeviceType(DISK);
64 break;
65 default:
66 AssertMsgFailed(("VBOXSF: vbsfUpdateNetRoot: Invalid net root type! Type = 0x%x\n",
67 pNetRoot->Type));
68 break;
69 }
70
71 Log(("VBOXSF: vbsfUpdateNetRoot: leaving pNetRoot->DeviceType = 0x%x\n",
72 pNetRoot->DeviceType));
73}
74
75NTSTATUS VBoxMRxCreateVNetRoot(IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
76{
77 NTSTATUS Status;
78
79 PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
80
81 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(pCreateNetRootContext->RxContext);
82 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot);
83
84 PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
85 PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
86
87 BOOLEAN fInitializeNetRoot = FALSE;
88
89 Log(("VBOXSF: MRxCreateVNetRoot: pNetRoot = %p, pNetRootExtension = %p, name = [%.*ls]\n",
90 pNetRoot, pNetRootExtension, pNetRoot->pNetRootName->Length / sizeof(WCHAR), pNetRoot->pNetRootName->Buffer));
91
92 /* IMPORTANT:
93 *
94 * This function must always call 'pCreateNetRootContext->Callback(pCreateNetRootContext)' before
95 * returning and then return STATUS_PENDING. Otherwise Win64 will hang.
96 */
97
98 if (pNetRoot->Type == NET_ROOT_PIPE)
99 {
100 /* VBoxSF claims everything which starts with '\vboxsrv'.
101 *
102 * So sometimes the system tries to open \vboxsrv\ipc$ pipe for DFS
103 * and fails the application call if an unexpected code is returned.
104 *
105 * According to MSDN: The Windows client returns STATUS_MORE_PROCESSING_REQUIRED to the calling
106 * application to indicate that the path does not correspond to a DFS Namespace.
107 */
108 pVNetRoot->Context = NULL;
109
110 if (pNetRoot->pNetRootName->Length >= 13 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv\ipc$' unicode string. */
111 {
112 const WCHAR *Suffix = &pNetRoot->pNetRootName->Buffer[8]; /* Number of chars in '\vboxsrv' */
113
114 if ( Suffix[0] == L'\\'
115 && (Suffix[1] == L'I' || Suffix[1] == L'i')
116 && (Suffix[2] == L'P' || Suffix[2] == L'p')
117 && (Suffix[3] == L'C' || Suffix[3] == L'c')
118 && Suffix[4] == L'$'
119 )
120 {
121 if ( pNetRoot->pNetRootName->Length == 13 * sizeof (WCHAR)
122 || (Suffix[5] == L'\\' || Suffix[5] == 0)
123 )
124 {
125 /* It is '\vboxsrv\IPC$[\*]'. */
126 Log(("VBOXSF: MRxCreateVNetRoot: IPC$\n"));
127 Status = STATUS_MORE_PROCESSING_REQUIRED;
128 goto l_Exit;
129 }
130 }
131 }
132
133 /* Fail all other pipe open requests. */
134 Log(("VBOXSF: MRxCreateVNetRoot: Pipe open not supported!\n"));
135 Status = STATUS_NOT_SUPPORTED;
136 goto l_Exit;
137 }
138 else if (pNetRoot->Type == NET_ROOT_MAILSLOT)
139 {
140 Log(("VBOXSF: MRxCreateVNetRoot: Mailslot open not supported!\n"));
141 pVNetRoot->Context = NULL;
142 Status = STATUS_NOT_SUPPORTED;
143 goto l_Exit;
144 }
145
146 if (!pNetRoot->Context)
147 {
148 /* MRxNetRootSize is not zero in VBoxSF, so it is expected
149 * that the Context, which is NetRootExtension, is already allocated.
150 */
151 Log(("VBOXSF: MRxCreateVNetRoot: NULL netroot context\n"));
152 pVNetRoot->Context = NULL;
153 Status = STATUS_NOT_SUPPORTED;
154 goto l_Exit;
155 }
156
157 /* Detect an already initialized NetRoot.
158 * pNetRootExtension is actually the pNetRoot->Context and it is not NULL.
159 */
160 fInitializeNetRoot = (pNetRootExtension->phgcmClient == NULL);
161
162 Status = STATUS_SUCCESS;
163
164 if (fInitializeNetRoot)
165 {
166 PWCHAR pRootName;
167 ULONG RootNameLength;
168 int vboxRC;
169 PSHFLSTRING ParsedPath = 0;
170
171 Log(("VBOXSF: MRxCreateVNetRoot: initialize NET_ROOT\n"));
172
173 pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
174
175 RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
176 if (RootNameLength < sizeof(WCHAR))
177 {
178 /* Refuse a netroot path with an empty shared folder name */
179 Log(("VBOXSF: MRxCreateVNetRoot: Empty shared folder name!\n"));
180 pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
181
182 Status = STATUS_BAD_NETWORK_NAME;
183 goto l_Exit;
184 }
185
186 RootNameLength -= sizeof(WCHAR); /* Remove leading backslash. */
187 pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
188 pRootName++; /* Remove leading backslash. */
189
190 /* Strip the trailing \0. Sometimes there is one, sometimes not... */
191 if ( RootNameLength >= sizeof(WCHAR)
192 && pRootName[RootNameLength / sizeof(WCHAR) - 1] == 0)
193 RootNameLength -= sizeof(WCHAR);
194
195 if (!pNetRootExtension->phgcmClient)
196 {
197 Log(("VBOXSF: MRxCreateVNetRoot: Initialize netroot length = %d, name = %.*ls\n",
198 RootNameLength, RootNameLength / sizeof(WCHAR), pRootName));
199
200 Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, pRootName, (uint16_t)RootNameLength);
201 if (Status != STATUS_SUCCESS)
202 {
203 goto l_Exit;
204 }
205
206 vboxRC = VbglR0SfMapFolder(&pDeviceExtension->hgcmClient, ParsedPath, &pNetRootExtension->map);
207 vbsfFreeNonPagedMem(ParsedPath);
208 if (vboxRC != VINF_SUCCESS)
209 {
210 Log(("VBOXSF: MRxCreateVNetRoot: VbglR0SfMapFolder failed with %d\n", vboxRC));
211 Status = STATUS_BAD_NETWORK_NAME;
212 }
213 else
214 {
215 Status = STATUS_SUCCESS;
216 pNetRootExtension->phgcmClient = &pDeviceExtension->hgcmClient;
217 }
218 }
219 }
220 else
221 Log(("VBOXSF: MRxCreateVNetRoot: Creating V_NET_ROOT on existing NET_ROOT!\n"));
222
223 vbsfUpdateNetRoot(pNetRoot);
224
225l_Exit:
226 if (Status != STATUS_PENDING)
227 {
228 Log(("VBOXSF: MRxCreateVNetRoot: Returning 0x%08X\n", Status));
229 pCreateNetRootContext->VirtualNetRootStatus = Status;
230 if (fInitializeNetRoot)
231 pCreateNetRootContext->NetRootStatus = Status;
232 else
233 pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
234
235 /* Inform RDBSS. */
236 pCreateNetRootContext->Callback(pCreateNetRootContext);
237
238 /* RDBSS expects this. */
239 Status = STATUS_PENDING;
240 }
241
242 Log(("VBOXSF: MRxCreateVNetRoot: Returned STATUS_PENDING\n"));
243 return Status;
244}
245
246NTSTATUS VBoxMRxFinalizeVNetRoot(IN PMRX_V_NET_ROOT pVNetRoot, IN PBOOLEAN ForceDisconnect)
247{
248 RT_NOREF(pVNetRoot, ForceDisconnect);
249 Log(("VBOXSF: MRxFinalizeVNetRoot: V_NET_ROOT %p, NET_ROOT %p\n", pVNetRoot, pVNetRoot->pNetRoot));
250
251 return STATUS_SUCCESS;
252}
253
254NTSTATUS VBoxMRxFinalizeNetRoot(IN PMRX_NET_ROOT pNetRoot, IN PBOOLEAN ForceDisconnect)
255{
256 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(pNetRoot);
257 RT_NOREF(pNetRoot, ForceDisconnect);
258
259 Log(("VBOXSF: MRxFinalizeNetRoot: NET_ROOT %p\n", pNetRoot));
260
261 if (pNetRootExtension->phgcmClient)
262 {
263 int vboxRC = VbglR0SfUnmapFolder(pNetRootExtension->phgcmClient, &pNetRootExtension->map);
264 if (vboxRC != VINF_SUCCESS)
265 Log(("VBOXSF: MRxFinalizeVNetRoot: VbglR0SfUnmapFolder failed with %d\n",
266 vboxRC));
267 pNetRootExtension->phgcmClient = NULL;
268 }
269
270 return STATUS_SUCCESS;
271}
272
273VOID VBoxMRxExtractNetRootName(IN PUNICODE_STRING FilePathName,
274 IN PMRX_SRV_CALL SrvCall,
275 OUT PUNICODE_STRING NetRootName,
276 OUT PUNICODE_STRING RestOfName OPTIONAL)
277{
278 int cChars = FilePathName->Length/sizeof(WCHAR);
279 int iNetRoot;
280 int i;
281
282 /* Split "\vboxsvr\share\path" to
283 * NetRootName = "\share"
284 * RestOfName = "\path"
285 *
286 * Note that SrvCall->pSrvCallName contains "\vboxsrv".
287 */
288
289 Log(("VBOXSF: MRxExtractNetRootName: [%.*ls], RestOfName %p\n",
290 FilePathName->Length/sizeof(WCHAR), FilePathName->Buffer, RestOfName));
291
292 /* Assume that the server prefix is OK.
293 * iNetRoot points to the first char after server name, the delimiter.
294 */
295 iNetRoot = SrvCall->pSrvCallName->Length/sizeof(WCHAR);
296
297 /* Find the NetRoot length: end of FilePathName or the next delimiter. */
298 i = iNetRoot;
299 while (i < cChars)
300 {
301 if ( FilePathName->Buffer[i] == L'\\'
302 && i > iNetRoot)
303 {
304 break;
305 }
306 i++;
307 }
308
309 Log(("VBOXSF: MRxExtractNetRootName: cChars %d, iNetRoot %d, iRest %d\n",
310 cChars, iNetRoot, i));
311
312 NetRootName->Buffer = &FilePathName->Buffer[iNetRoot];
313 NetRootName->Length = (USHORT)((i - iNetRoot) * sizeof(WCHAR));
314 NetRootName->MaximumLength = NetRootName->Length;
315
316 Log(("VBOXSF: MRxExtractNetRootName: Srv = %.*ls, Root = %.*ls\n",
317 SrvCall->pSrvCallName->Length / sizeof(WCHAR), SrvCall->pSrvCallName->Buffer,
318 NetRootName->Length / sizeof(WCHAR), NetRootName->Buffer));
319
320 if (RestOfName)
321 {
322 RestOfName->Buffer = &FilePathName->Buffer[i];
323 RestOfName->Length = (USHORT)((cChars - i) * sizeof(WCHAR));
324 RestOfName->MaximumLength = RestOfName->Length;
325
326 Log(("VBOXSF: MRxExtractNetRootName: Rest = %.*ls\n",
327 RestOfName->Length / sizeof(WCHAR), RestOfName->Buffer));
328 }
329}
330
331static VOID vbsfExecuteCreateSrvCall(PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
332{
333 NTSTATUS Status;
334 PWCHAR pSrvName = 0;
335 BOOLEAN Verifier;
336
337 PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = pCallbackContext;
338 PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(SCCBC->SrvCalldownStructure);
339 PMRX_SRV_CALL pSrvCall = SrvCalldownStructure->SrvCall;
340
341 /* Validate the server name with the test name of 'vboxsvr'. */
342 Log(("VBOXSF: vbsfExecuteCreateSrvCall: Connection Name %.*ls Length: %d, pSrvCall = %p\n",
343 pSrvCall->pSrvCallName->Length / sizeof(WCHAR), pSrvCall->pSrvCallName->Buffer, pSrvCall->pSrvCallName->Length, pSrvCall));
344
345 if (pSrvCall->pPrincipalName && pSrvCall->pPrincipalName->Length)
346 {
347 Log(("VBOXSF: vbsfExecuteCreateSrvCall: Principal name = %.*ls\n",
348 pSrvCall->pPrincipalName->Length / sizeof(WCHAR), pSrvCall->pPrincipalName->Buffer));
349 }
350
351 if (pSrvCall->pDomainName && pSrvCall->pDomainName->Length)
352 {
353 Log(("VBOXSF: vbsfExecuteCreateSrvCall: Domain name = %.*ls\n",
354 pSrvCall->pDomainName->Length / sizeof(WCHAR), pSrvCall->pDomainName->Buffer));
355 }
356
357 if (pSrvCall->pSrvCallName->Length >= 14)
358 {
359 pSrvName = pSrvCall->pSrvCallName->Buffer;
360
361 Verifier = (pSrvName[0] == L'\\');
362 Verifier &= (pSrvName[1] == L'V') || (pSrvName[1] == L'v');
363 Verifier &= (pSrvName[2] == L'B') || (pSrvName[2] == L'b');
364 Verifier &= (pSrvName[3] == L'O') || (pSrvName[3] == L'o');
365 Verifier &= (pSrvName[4] == L'X') || (pSrvName[4] == L'x');
366 Verifier &= (pSrvName[5] == L'S') || (pSrvName[5] == L's');
367 /* Both vboxsvr & vboxsrv are now accepted */
368 if ((pSrvName[6] == L'V') || (pSrvName[6] == L'v'))
369 {
370 Verifier &= (pSrvName[6] == L'V') || (pSrvName[6] == L'v');
371 Verifier &= (pSrvName[7] == L'R') || (pSrvName[7] == L'r');
372 }
373 else
374 {
375 Verifier &= (pSrvName[6] == L'R') || (pSrvName[6] == L'r');
376 Verifier &= (pSrvName[7] == L'V') || (pSrvName[7] == L'v');
377 }
378 Verifier &= (pSrvName[8] == L'\\') || (pSrvName[8] == 0);
379 }
380 else
381 Verifier = FALSE;
382
383 if (Verifier)
384 {
385 Log(("VBOXSF: vbsfExecuteCreateSrvCall: Verifier succeeded!\n"));
386 Status = STATUS_SUCCESS;
387 }
388 else
389 {
390 Log(("VBOXSF: vbsfExecuteCreateSrvCall: Verifier failed!\n"));
391 Status = STATUS_BAD_NETWORK_PATH;
392 }
393
394 SCCBC->Status = Status;
395 SrvCalldownStructure->CallBack(SCCBC);
396}
397
398NTSTATUS VBoxMRxCreateSrvCall(PMRX_SRV_CALL pSrvCall, PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
399{
400 PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(pCallbackContext->SrvCalldownStructure);
401 RT_NOREF(pSrvCall);
402
403 Log(("VBOXSF: MRxCreateSrvCall: %p.\n", pSrvCall));
404
405 if (IoGetCurrentProcess() == RxGetRDBSSProcess())
406 {
407 Log(("VBOXSF: MRxCreateSrvCall: Called in context of RDBSS process\n"));
408
409 vbsfExecuteCreateSrvCall(pCallbackContext);
410 }
411 else
412 {
413 NTSTATUS Status;
414
415 Log(("VBOXSF: MRxCreateSrvCall: Dispatching to worker thread\n"));
416
417 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
418 (PWORKER_THREAD_ROUTINE)vbsfExecuteCreateSrvCall,
419 pCallbackContext);
420
421 if (Status == STATUS_SUCCESS)
422 Log(("VBOXSF: MRxCreateSrvCall: queued\n"));
423 else
424 {
425 pCallbackContext->Status = Status;
426 SrvCalldownStructure->CallBack(pCallbackContext);
427 }
428 }
429
430 /* RDBSS expect this. */
431 return STATUS_PENDING;
432}
433
434NTSTATUS VBoxMRxFinalizeSrvCall(PMRX_SRV_CALL pSrvCall, BOOLEAN Force)
435{
436 RT_NOREF(Force);
437 Log(("VBOXSF: MRxFinalizeSrvCall %p, ctx = %p.\n", pSrvCall, pSrvCall->Context));
438
439 pSrvCall->Context = NULL;
440
441 return STATUS_SUCCESS;
442}
443
444NTSTATUS VBoxMRxSrvCallWinnerNotify(IN PMRX_SRV_CALL pSrvCall, IN BOOLEAN ThisMinirdrIsTheWinner, IN OUT PVOID pSrvCallContext)
445{
446 RT_NOREF(ThisMinirdrIsTheWinner, pSrvCallContext);
447 Log(("VBOXSF: MRxSrvCallWinnerNotify: pSrvCall %p, pSrvCall->Ctx %p, winner %d, context %p\n",
448 pSrvCall, pSrvCall->Context, ThisMinirdrIsTheWinner, pSrvCallContext));
449
450 /* Set it to not NULL. */
451 pSrvCall->Context = pSrvCall;
452
453 return STATUS_SUCCESS;
454}
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