VirtualBox

Ticket #9753: netroot.c

File netroot.c, 13.9 KB (added by Alex Bobryshev, 13 years ago)
Line 
1/*++
2
3 Copyright (c) 1989 - 1999 Microsoft Corporation
4
5 Module Name:
6
7 netroot.c
8
9 Abstract:
10
11 This module implements the routines for creating the net root.
12
13 --*/
14
15#include "precomp.h"
16#pragma hdrstop
17
18//
19// Forward declarations ...
20//
21
22NTSTATUS VBoxMRxUpdateNetRootState (IN OUT PMRX_NET_ROOT pNetRoot)
23/*++
24
25 Routine Description:
26
27 This routine updates the mini redirector state associated with a net root.
28
29 Arguments:
30
31 pNetRoot - the net root instance.
32
33 Return Value:
34
35 NTSTATUS - The return status for the operation
36
37 Notes:
38
39 By differentiating the mini redirector state from the net root condition it is possible
40 to permit a variety of reconnect strategies. It is conceivable that the RDBSS considers
41 a net root to be good while the underlying mini redirector might mark it as invalid
42 and reconnect on the fly.
43
44 --*/
45{
46 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
47
48 Log(("VBOXSF: VBoxMRxUpdateNetRootState: Called.\n"));
49 return (Status);
50}
51
52NTSTATUS VBoxMRxInitializeNetRootEntry (IN PMRX_NET_ROOT pNetRoot)
53/*++
54
55 Routine Description:
56
57 This routine initializes a new net root.
58 It also validates rootnames. Eg: attempts to create a
59 file in a root that has not been created will fail.
60
61 Arguments:
62
63 pNetRoot - the net root
64
65 Return Value:
66
67 NTSTATUS - The return status for the operation
68
69 Notes:
70
71 --*/
72{
73 NTSTATUS Status = STATUS_SUCCESS;
74 PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
75 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = (PMRX_VBOX_NETROOT_EXTENSION)pNetRoot->Context;
76
77 Log(("VBOXSF: VBoxMRxInitializeNetRootEntry: Called.\n"));
78 return Status;
79}
80
81NTSTATUS VBoxUpdateNetRoot (PMRX_NET_ROOT pNetRoot)
82/*++
83
84 Routine Description:
85
86 This routine initializes the wrapper data structure corresponding to a
87 given net root entry.
88
89 Arguments:
90
91 pNetRootEntry - the server entry
92
93 Return Value:
94
95 STATUS_SUCCESS if successful
96
97 --*/
98{
99 PAGED_CODE();
100
101 Log(("VBOXSF: VBoxUpdateNetRoot: NetRoot = 0x%x Type = 0x%x\n", pNetRoot, pNetRoot->Type));
102
103 switch (pNetRoot->Type)
104 {
105 case NET_ROOT_DISK:
106 pNetRoot->DeviceType = RxDeviceType(DISK);
107 break;
108
109 case NET_ROOT_PIPE:
110 pNetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
111 break;
112 case NET_ROOT_COMM:
113 pNetRoot->DeviceType = RxDeviceType(SERIAL_PORT);
114 break;
115 case NET_ROOT_PRINT:
116 pNetRoot->DeviceType = RxDeviceType(PRINTER);
117 break;
118 case NET_ROOT_MAILSLOT:
119 pNetRoot->DeviceType = RxDeviceType(MAILSLOT);
120 break;
121 case NET_ROOT_WILD:
122 /* We get this type when for example Windows Media player opens an MP3 file.
123 * This NetRoot has the same remote path (\\vboxsrv\dir) as other NetRoots,
124 * which were created earlier and which were NET_ROOT_DISK.
125 *
126 * In the beginning of the function (UpdateNetRoot) the DDK sample sets
127 * pNetRoot->Type of newly created NetRoots using a value previously
128 * pstored in a NetRootExtension. One NetRootExtensions is used for a single
129 * remote path and reused by a few NetRoots, if they point to the same path.
130 *
131 * To simplify things we just set the type to DISK here (we do not support
132 * anything else anyway), and update the DeviceType correspondingly.
133 */
134 pNetRoot->Type = NET_ROOT_DISK;
135 pNetRoot->DeviceType = RxDeviceType(DISK);
136 break;
137 default:
138 AssertMsgFailed(("VBOXSF: VBoxUpdateNetRoot: Invalid net root type! Type = 0x%x\n", pNetRoot->Type));
139 break;
140 }
141
142 Log(("VBOXSF: VBoxUpdateNetRoot: leaving pNetRoot->DeviceType = 0x%x\n", pNetRoot->DeviceType));
143 return STATUS_SUCCESS;
144}
145
146NTSTATUS VBoxMRxCreateVNetRoot (IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
147/*++
148
149 Routine Description:
150
151 This routine patches the RDBSS created net root instance with the information required
152 by the mini redirector.
153
154 Arguments:
155
156 pVNetRoot - the virtual net root instance.
157
158 pCreateNetRootContext - the net root context for calling back
159
160 Return Value:
161
162 NTSTATUS - The return status for the operation
163
164 Notes:
165
166 --*/
167{
168 NTSTATUS Status;
169 PRX_CONTEXT pRxContext = pCreateNetRootContext->RxContext;
170 PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
171 VBoxMRxGetDeviceExtension(pRxContext, pDeviceExtension);
172 VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot, pNetRootExtension);
173
174 PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
175 PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
176
177 BOOLEAN fTreeConnectOpen = TRUE; // RxContext->Create.ThisIsATreeConnectOpen;
178 BOOLEAN fInitializeNetRoot = FALSE; //// !! Fix
179
180 Log(("VBOXSF: VBoxMRxCreateVNetRoot: pNetRoot = %p, fTreeConnectOpen = %d\n", pNetRoot, pRxContext->Create.ThisIsATreeConnectOpen));
181
182 /* IMPORTANT:
183 *
184 * This function must always call 'pCreateNetRootContext->Callback(pCreateNetRootContext)' before
185 * returning and then return STATUS_PENDING. Otherwise Win64 will hang.
186 */
187
188 if (pNetRoot->Type == NET_ROOT_PIPE)
189 {
190 pNetRoot->Type = NET_ROOT_WILD;
191 }
192
193
194 if (pNetRoot->Type == NET_ROOT_MAILSLOT)
195 {
196
197 /* DDK sample returns this status code. And our driver does get such NetRoots. */
198 Log(("VBOXSF: VBoxMRxCreateVNetRoot: Mailslot or Pipe open (%d) not supported!\n", pNetRoot->Type));
199
200 pVNetRoot->Context = NULL;
201
202 Status = STATUS_NOT_SUPPORTED;
203 goto l_Exit;
204 }
205
206
207 // The V_NET_ROOT is associated with a NET_ROOT. The two cases of interest are as
208 // follows
209 // 1) the V_NET_ROOT and the associated NET_ROOT are being newly created.
210 // 2) a new V_NET_ROOT associated with an existing NET_ROOT is being created.
211 //
212 // These two cases can be distinguished by checking if the context associated with
213 // NET_ROOT is NULL. Since the construction of NET_ROOT's/V_NET_ROOT's are serialized
214 // by the wrapper this is a safe check.
215 // ( The wrapper cannot have more then one thread trying to initialize the same
216 // NET_ROOT).
217 //
218 // The above is not really true in our case. Since we have asked the wrapper,
219 // to manage our netroot extension, the netroot context will always be non-NULL.
220 // We will distinguish the cases by checking our root state in the context...
221 //
222
223 if (pNetRoot->Context == NULL)
224 {
225 fInitializeNetRoot = TRUE;
226 }
227 else
228 {
229 VBoxMRxGetNetRootExtension(pNetRoot,pNetRootExtension);
230 /* Detect an already initialized NetRoot.
231 * pNetRootExtension is actually the pNetRoot->Context and it is not null.
232 */
233 fInitializeNetRoot = pNetRootExtension->phgcmClient == NULL;
234 }
235
236 Assert((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) && (NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));
237
238 Status = STATUS_SUCCESS;
239
240 // update the net root state to be good.
241
242 if (fInitializeNetRoot)
243 {
244 PWCHAR pRootName;
245 ULONG RootNameLength;
246 int vboxRC;
247 PSHFLSTRING ParsedPath = 0;
248 ULONG ParsedPathSize;
249
250 pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
251
252 // validate the fixed netroot name
253
254 RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
255 if (!RootNameLength)
256 {
257 /* Refuse a netroot path with an empty shared folder name */
258 Log(("VBOXSF: VBoxMRxCreateVNetRoot: Invalid shared folder name! (length=0)\n"));
259 pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
260
261 Status = STATUS_BAD_NETWORK_NAME;
262 goto l_Exit;
263 }
264
265 RootNameLength -= 2; /* remove leading backslash */
266
267 pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
268 pRootName++; /* remove leading backslash */
269
270 if (pNetRootExtension->phgcmClient == NULL)
271 {
272 Log(("VBOXSF: VBoxMRxCreateVNetRoot: Initialize netroot length = %d, name = %.*ls\n", RootNameLength, RootNameLength / sizeof(WCHAR), pRootName));
273
274 /* Calculate length required for parsed path.
275 */
276 ParsedPathSize = sizeof(*ParsedPath) + RootNameLength + sizeof(WCHAR);
277
278 ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
279 if (!ParsedPath)
280 {
281 Status = STATUS_INSUFFICIENT_RESOURCES;
282 goto l_Exit;
283 }
284 memset(ParsedPath, 0, ParsedPathSize);
285
286 ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));
287
288 ParsedPath->u16Size = (uint16_t)RootNameLength + sizeof(WCHAR);
289 ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
290 RtlCopyMemory(ParsedPath->String.ucs2, pRootName, ParsedPath->u16Length);
291
292 vboxRC = vboxCallMapFolder(&pDeviceExtension->hgcmClient, ParsedPath, &pNetRootExtension->map);
293 vbsfFreeNonPagedMem(ParsedPath);
294 if (vboxRC != VINF_SUCCESS)
295 {
296 Log(("VBOXSF: VBoxMRxCreateVNetRoot: vboxCallMapFolder failed with %d\n", vboxRC));
297 Status = STATUS_BAD_NETWORK_NAME;
298 }
299 else
300 {
301 Status = STATUS_SUCCESS;
302 pNetRootExtension->phgcmClient = &pDeviceExtension->hgcmClient;
303 }
304 }
305 }
306 else Log(("VBOXSF: VBoxMRxCreateVNetRoot: Creating V_NET_ROOT on existing NET_ROOT!\n"));
307
308 if ((Status == STATUS_SUCCESS) && fInitializeNetRoot)
309 {
310 //
311 // A new NET_ROOT and associated V_NET_ROOT are being created !
312 //
313 Status = VBoxMRxInitializeNetRootEntry(pNetRoot);
314 Log(("VBOXSF: VBoxMRxCreateVNetRoot: NulMRXInitializeNetRootEntry called, Status = 0x%lx\n", Status));
315 }
316
317 VBoxUpdateNetRoot(pNetRoot);
318
319l_Exit:
320 if (Status != STATUS_PENDING)
321 {
322 Log(("VBOXSF: VBoxMRxCreateVNetRoot: Returning 0x%lx\n", Status));
323 pCreateNetRootContext->VirtualNetRootStatus = Status;
324 if (fInitializeNetRoot)
325 pCreateNetRootContext->NetRootStatus = Status;
326 else pCreateNetRootContext->NetRootStatus = Status;
327
328 // Callback the RDBSS for resumption.
329 pCreateNetRootContext->Callback(pCreateNetRootContext);
330
331 // Map the error code to STATUS_PENDING since this triggers
332 // the synchronization mechanism in the RDBSS.
333 Status = STATUS_PENDING;
334 }
335
336 Log(("VBOXSF: VBoxMRxCreateVNetRoot: Returned STATUS_PENDING\n"));
337 return Status;
338}
339
340NTSTATUS VBoxMRxFinalizeVNetRoot (IN PMRX_V_NET_ROOT pVNetRoot, IN PBOOLEAN ForceDisconnect)
341/*++
342
343 Routine Description:
344
345
346 Arguments:
347
348 pVNetRoot - the virtual net root
349
350 ForceDisconnect - disconnect is forced
351
352 Return Value:
353
354 NTSTATUS - The return status for the operation
355
356 --*/
357{
358 NTSTATUS Status = STATUS_SUCCESS;
359 PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
360 VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot, pNetRootExtension);
361 int vboxRC;
362
363 Log(("VBOXSF: VBoxMRxFinalizeVNetRoot: Address = 0x%lx\n", pVNetRoot));
364
365 if (pNetRootExtension->phgcmClient)
366 {
367 vboxRC = vboxCallUnmapFolder(pNetRootExtension->phgcmClient, &pNetRootExtension->map);
368 if (vboxRC != VINF_SUCCESS)
369 {
370 Log(("VBOXSF: VBoxMRxFinalizeVNetRoot: vboxCallMapFolder failed with %d\n", vboxRC));
371 }
372 pNetRootExtension->phgcmClient = NULL;
373 }
374
375 //
376 // This is called when all outstanding handles on this
377 // root have been cleaned up ! We can now zap the netroot
378 // extension...
379 //
380
381 return Status;
382}
383
384NTSTATUS VBoxMRxFinalizeNetRoot (IN PMRX_NET_ROOT pNetRoot, IN PBOOLEAN ForceDisconnect)
385/*++
386
387 Routine Description:
388
389
390 Arguments:
391
392 pVirtualNetRoot - the virtual net root
393
394 ForceDisconnect - disconnect is forced
395
396 Return Value:
397
398 NTSTATUS - The return status for the operation
399
400 --*/
401{
402 NTSTATUS Status = STATUS_SUCCESS;
403
404 Log(("VBOXSF: VBoxMRxFinalizeNetRoot: Called.\n"));
405 //
406 // This is called when all outstanding handles on this
407 // root have been cleaned up ! We can now zap the netroot
408 // extension...
409 //
410 return (Status);
411}
412
413VOID VBoxMRxExtractNetRootName (IN PUNICODE_STRING FilePathName, IN PMRX_SRV_CALL SrvCall, OUT PUNICODE_STRING NetRootName, OUT PUNICODE_STRING RestOfName OPTIONAL
414 )
415/*++
416
417 Routine Description:
418
419 This routine parses the input name into srv, netroot, and the
420 rest.
421
422 Arguments:
423
424
425 --*/
426{
427 UNICODE_STRING xRestOfName;
428
429 ULONG length = FilePathName->Length;
430 PWCH w = FilePathName->Buffer;
431 PWCH wlimit = (PWCH)(((PCHAR)w) + length);
432 PWCH wlow;
433
434 Log(("VBOXSF: VBoxMRxExtractNetRootName: Called.\n"));
435
436 w += (SrvCall->pSrvCallName->Length / sizeof(WCHAR));
437 NetRootName->Buffer = wlow = w;
438 for (;;)
439 {
440 if (w >= wlimit)
441 break;
442 if ((*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow))
443 {
444 break;
445 }
446 w++;
447 }
448
449 NetRootName->Length = NetRootName->MaximumLength = (USHORT)((PCHAR)w - (PCHAR)wlow);
450
451 //w = FilePathName->Buffer;
452 //NetRootName->Buffer = w++;
453
454 if (!RestOfName)
455 RestOfName = &xRestOfName;
456 RestOfName->Buffer = w;
457 RestOfName->Length = (USHORT)RestOfName->MaximumLength = (USHORT)((PCHAR)wlimit - (PCHAR)w);
458
459 Log(("VBOXSF: VBoxMRxExtractNetRootName: FilePath = %.*ls\n", FilePathName->Length / sizeof(WCHAR), FilePathName->Buffer));
460 Log(("VBOXSF: VBoxMRxExtractNetRootName: Srv = %.*ls, Root = %.*ls, Rest = %.*ls\n", SrvCall->pSrvCallName->Length / sizeof(WCHAR), SrvCall->pSrvCallName->Buffer, NetRootName->Length
461 / sizeof(WCHAR), NetRootName->Buffer, RestOfName->Length / sizeof(WCHAR), RestOfName->Buffer));
462
463 return;
464}
465

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