VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.cpp@ 78304

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

winnt/vboxsf: Use g_SfClient everywhere to avoid having dangling pointers (MRX_VBOX_NETROOT_EXTENSION::phgcmClient) and copies (MRX_VBOX_DEVICE_EXTENSION::hgcmClient). This also reduces the stack space usage. ASSUMES that the module can only be instantiated once (already an assumption of the g_SfClient variable and related code in VBoxGuestLibSharedFoldersInline.h). Renamed all sources to .cpp (except the w2k hacks). bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1/* $Id: vbsfhlp.cpp 78304 2019-04-26 01:19:49Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - File System Driver system helpers
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 <iprt/nt/nt.h> /* includes ntifs.h and wdm.h */
19#include <iprt/win/ntdddisk.h>
20
21#include "vbsfhlp.h"
22#include <iprt/err.h>
23
24#ifdef DEBUG
25static int s_iAllocRefCount = 0;
26#endif
27
28void vbsfHlpSleep(ULONG ulMillies)
29{
30 KEVENT event;
31 LARGE_INTEGER dueTime;
32
33 KeInitializeEvent(&event, NotificationEvent, FALSE);
34
35 dueTime.QuadPart = -10000 * (int)ulMillies;
36
37 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &dueTime);
38}
39
40/**
41 * Converts VBox (IPRT) file mode to NT file attributes.
42 *
43 * @returns NT file attributes
44 * @param fIprtMode IPRT file mode.
45 *
46 */
47uint32_t VBoxToNTFileAttributes(uint32_t fIprtMode)
48{
49 AssertCompile((RTFS_DOS_READONLY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_READONLY);
50 AssertCompile((RTFS_DOS_HIDDEN >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_HIDDEN);
51 AssertCompile((RTFS_DOS_SYSTEM >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_SYSTEM);
52 AssertCompile((RTFS_DOS_DIRECTORY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_DIRECTORY);
53 AssertCompile((RTFS_DOS_ARCHIVED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_ARCHIVE);
54 /* skipping: RTFS_DOS_NT_DEVICE */
55 AssertCompile((RTFS_DOS_NT_NORMAL >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_NORMAL);
56 AssertCompile((RTFS_DOS_NT_TEMPORARY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_TEMPORARY);
57 AssertCompile((RTFS_DOS_NT_SPARSE_FILE >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_SPARSE_FILE);
58 AssertCompile((RTFS_DOS_NT_REPARSE_POINT >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_REPARSE_POINT);
59 AssertCompile((RTFS_DOS_NT_COMPRESSED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_COMPRESSED);
60 /* skipping: RTFS_DOS_NT_OFFLINE */
61 AssertCompile((RTFS_DOS_NT_NOT_CONTENT_INDEXED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
62 AssertCompile((RTFS_DOS_NT_ENCRYPTED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_ENCRYPTED);
63
64 uint32_t fNtAttribs = (fIprtMode & (RTFS_DOS_MASK_NT & ~(RTFS_DOS_NT_OFFLINE | RTFS_DOS_NT_DEVICE | RTFS_DOS_NT_REPARSE_POINT)))
65 >> RTFS_DOS_SHIFT;
66 return fNtAttribs ? fNtAttribs : FILE_ATTRIBUTE_NORMAL;
67}
68
69/**
70 * Converts NT file attributes to VBox (IPRT) ones.
71 *
72 * @returns IPRT file mode
73 * @param fNtAttribs NT file attributes
74 */
75uint32_t NTToVBoxFileAttributes(uint32_t fNtAttribs)
76{
77 uint32_t fIprtMode = (fNtAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT;
78 fIprtMode &= ~(RTFS_DOS_NT_OFFLINE | RTFS_DOS_NT_DEVICE | RTFS_DOS_NT_REPARSE_POINT);
79 return fIprtMode ? fIprtMode : RTFS_DOS_NT_NORMAL;
80}
81
82NTSTATUS vbsfHlpCreateDriveLetter(WCHAR Letter, UNICODE_STRING *pDeviceName)
83{
84 UNICODE_STRING driveName;
85 RtlInitUnicodeString(&driveName,L"\\??\\_:" );
86
87 /* Replace '_' with actual drive letter */
88 driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
89
90 return IoCreateSymbolicLink(&driveName, pDeviceName);
91}
92
93NTSTATUS vbsfHlpDeleteDriveLetter(WCHAR Letter)
94{
95 UNICODE_STRING driveName;
96 RtlInitUnicodeString(&driveName,L"\\??\\_:" );
97
98 /* Replace '_' with actual drive letter */
99 driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
100
101 return IoDeleteSymbolicLink(&driveName);
102}
103
104/**
105 * Convert VBox error code to NT status code
106 *
107 * @returns NT status code
108 * @param vrc VBox status code.
109 *
110 */
111NTSTATUS VBoxErrorToNTStatus(int vrc)
112{
113 NTSTATUS Status;
114
115 switch (vrc)
116 {
117 case VINF_SUCCESS:
118 Status = STATUS_SUCCESS;
119 break;
120
121 case VERR_ACCESS_DENIED:
122 Status = STATUS_ACCESS_DENIED;
123 break;
124
125 case VERR_NO_MORE_FILES:
126 Status = STATUS_NO_MORE_FILES;
127 break;
128
129 case VERR_PATH_NOT_FOUND:
130 Status = STATUS_OBJECT_PATH_NOT_FOUND;
131 break;
132
133 case VERR_FILE_NOT_FOUND:
134 Status = STATUS_OBJECT_NAME_NOT_FOUND;
135 break;
136
137 case VERR_DIR_NOT_EMPTY:
138 Status = STATUS_DIRECTORY_NOT_EMPTY;
139 break;
140
141 case VERR_SHARING_VIOLATION:
142 Status = STATUS_SHARING_VIOLATION;
143 break;
144
145 case VERR_FILE_LOCK_VIOLATION:
146 Status = STATUS_FILE_LOCK_CONFLICT;
147 break;
148
149 case VERR_FILE_LOCK_FAILED:
150 Status = STATUS_LOCK_NOT_GRANTED;
151 break;
152
153 case VINF_BUFFER_OVERFLOW:
154 Status = STATUS_BUFFER_OVERFLOW;
155 break;
156
157 case VERR_EOF:
158 case VINF_EOF:
159 Status = STATUS_END_OF_FILE;
160 break;
161
162 case VERR_READ_ERROR:
163 case VERR_WRITE_ERROR:
164 case VERR_FILE_IO_ERROR:
165 Status = STATUS_UNEXPECTED_IO_ERROR;
166 break;
167
168 case VERR_WRITE_PROTECT:
169 Status = STATUS_MEDIA_WRITE_PROTECTED;
170 break;
171
172 case VERR_ALREADY_EXISTS:
173 Status = STATUS_OBJECT_NAME_COLLISION;
174 break;
175
176 case VERR_NOT_A_DIRECTORY:
177 Status = STATUS_NOT_A_DIRECTORY;
178 break;
179
180 case VERR_SEEK:
181 Status = STATUS_INVALID_PARAMETER;
182 break;
183
184 case VERR_INVALID_PARAMETER:
185 Status = STATUS_INVALID_PARAMETER;
186 break;
187
188 case VERR_NOT_SUPPORTED:
189 Status = STATUS_NOT_SUPPORTED;
190 break;
191
192 case VERR_INVALID_NAME:
193 Status = STATUS_OBJECT_NAME_INVALID;
194 break;
195
196 default:
197 /** @todo error handling */
198 Status = STATUS_INVALID_PARAMETER;
199 Log(("Unexpected vbox error %Rrc\n",
200 vrc));
201 break;
202 }
203 return Status;
204}
205
206PVOID vbsfAllocNonPagedMem(ULONG ulSize)
207{
208 PVOID pMemory = NULL;
209
210#ifdef DEBUG
211 s_iAllocRefCount = s_iAllocRefCount + 1;
212 Log(("vbsfAllocNonPagedMem: RefCnt after incrementing: %d\n", s_iAllocRefCount));
213#endif
214
215 /* Tag is reversed (a.k.a "SHFL") to display correctly in debuggers, so search for "SHFL" */
216 pMemory = ExAllocatePoolWithTag(NonPagedPool, ulSize, 'LFHS');
217
218 if (NULL != pMemory)
219 {
220 RtlZeroMemory(pMemory, ulSize);
221#ifdef DEBUG
222 Log(("vbsfAllocNonPagedMem: Allocated %d bytes of memory at %p.\n", ulSize, pMemory));
223#endif
224 }
225 else
226 {
227#ifdef DEBUG
228 Log(("vbsfAllocNonPagedMem: ERROR: Could not allocate %d bytes of memory!\n", ulSize));
229#endif
230 }
231
232 return pMemory;
233}
234
235void vbsfFreeNonPagedMem(PVOID lpMem)
236{
237#ifdef DEBUG
238 s_iAllocRefCount = s_iAllocRefCount - 1;
239 Log(("vbsfFreeNonPagedMem: RefCnt after decrementing: %d\n", s_iAllocRefCount));
240#endif
241
242 Assert(lpMem);
243
244 /* MSDN: The ExFreePoolWithTag routine issues a bug check if the specified value for Tag does not match the tag value passed
245 to the routine that originally allocated the memory block. Otherwise, the behavior of this routine is identical to ExFreePool. */
246 ExFreePoolWithTag(lpMem, 'LFHS');
247 lpMem = NULL;
248}
249
250#if 0 //def DEBUG
251/**
252 * Callback for RTLogFormatV which writes to the backdoor.
253 * See PFNLOGOUTPUT() for details.
254 */
255static DECLCALLBACK(size_t) rtLogBackdoorOutput(void *pv, const char *pachChars, size_t cbChars)
256{
257 RTLogWriteUser(pachChars, cbChars);
258 return cbChars;
259}
260
261int RTLogBackdoorPrintf1(const char *pszFormat, ...)
262{
263 va_list args;
264
265 LARGE_INTEGER time;
266
267 KeQueryTickCount(&time);
268
269 RTLogBackdoorPrintf("T=%RX64 ", time.QuadPart);
270 va_start(args, pszFormat);
271 RTLogFormatV(rtLogBackdoorOutput, NULL, pszFormat, args);
272 va_end(args);
273
274 return 0;
275}
276#endif
277
278#if defined(DEBUG) || defined(LOG_ENABLED)
279
280static PCHAR PnPMinorFunctionString(LONG MinorFunction)
281{
282 switch (MinorFunction)
283 {
284 case IRP_MN_START_DEVICE:
285 return "IRP_MJ_PNP - IRP_MN_START_DEVICE";
286 case IRP_MN_QUERY_REMOVE_DEVICE:
287 return "IRP_MJ_PNP - IRP_MN_QUERY_REMOVE_DEVICE";
288 case IRP_MN_REMOVE_DEVICE:
289 return "IRP_MJ_PNP - IRP_MN_REMOVE_DEVICE";
290 case IRP_MN_CANCEL_REMOVE_DEVICE:
291 return "IRP_MJ_PNP - IRP_MN_CANCEL_REMOVE_DEVICE";
292 case IRP_MN_STOP_DEVICE:
293 return "IRP_MJ_PNP - IRP_MN_STOP_DEVICE";
294 case IRP_MN_QUERY_STOP_DEVICE:
295 return "IRP_MJ_PNP - IRP_MN_QUERY_STOP_DEVICE";
296 case IRP_MN_CANCEL_STOP_DEVICE:
297 return "IRP_MJ_PNP - IRP_MN_CANCEL_STOP_DEVICE";
298 case IRP_MN_QUERY_DEVICE_RELATIONS:
299 return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_RELATIONS";
300 case IRP_MN_QUERY_INTERFACE:
301 return "IRP_MJ_PNP - IRP_MN_QUERY_INTERFACE";
302 case IRP_MN_QUERY_CAPABILITIES:
303 return "IRP_MJ_PNP - IRP_MN_QUERY_CAPABILITIES";
304 case IRP_MN_QUERY_RESOURCES:
305 return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCES";
306 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
307 return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
308 case IRP_MN_QUERY_DEVICE_TEXT:
309 return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_TEXT";
310 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
311 return "IRP_MJ_PNP - IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
312 case IRP_MN_READ_CONFIG:
313 return "IRP_MJ_PNP - IRP_MN_READ_CONFIG";
314 case IRP_MN_WRITE_CONFIG:
315 return "IRP_MJ_PNP - IRP_MN_WRITE_CONFIG";
316 case IRP_MN_EJECT:
317 return "IRP_MJ_PNP - IRP_MN_EJECT";
318 case IRP_MN_SET_LOCK:
319 return "IRP_MJ_PNP - IRP_MN_SET_LOCK";
320 case IRP_MN_QUERY_ID:
321 return "IRP_MJ_PNP - IRP_MN_QUERY_ID";
322 case IRP_MN_QUERY_PNP_DEVICE_STATE:
323 return "IRP_MJ_PNP - IRP_MN_QUERY_PNP_DEVICE_STATE";
324 case IRP_MN_QUERY_BUS_INFORMATION:
325 return "IRP_MJ_PNP - IRP_MN_QUERY_BUS_INFORMATION";
326 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
327 return "IRP_MJ_PNP - IRP_MN_DEVICE_USAGE_NOTIFICATION";
328 case IRP_MN_SURPRISE_REMOVAL:
329 return "IRP_MJ_PNP - IRP_MN_SURPRISE_REMOVAL";
330 default:
331 return "IRP_MJ_PNP - unknown_pnp_irp";
332 }
333}
334
335PCHAR MajorFunctionString(UCHAR MajorFunction, LONG MinorFunction)
336{
337 switch (MajorFunction)
338 {
339 case IRP_MJ_CREATE:
340 return "IRP_MJ_CREATE";
341 case IRP_MJ_CREATE_NAMED_PIPE:
342 return "IRP_MJ_CREATE_NAMED_PIPE";
343 case IRP_MJ_CLOSE:
344 return "IRP_MJ_CLOSE";
345 case IRP_MJ_READ:
346 return "IRP_MJ_READ";
347 case IRP_MJ_WRITE:
348 return "IRP_MJ_WRITE";
349 case IRP_MJ_QUERY_INFORMATION:
350 return "IRP_MJ_QUERY_INFORMATION";
351 case IRP_MJ_SET_INFORMATION:
352 return "IRP_MJ_SET_INFORMATION";
353 case IRP_MJ_QUERY_EA:
354 return "IRP_MJ_QUERY_EA";
355 case IRP_MJ_SET_EA:
356 return "IRP_MJ_SET_EA";
357 case IRP_MJ_FLUSH_BUFFERS:
358 return "IRP_MJ_FLUSH_BUFFERS";
359 case IRP_MJ_QUERY_VOLUME_INFORMATION:
360 return "IRP_MJ_QUERY_VOLUME_INFORMATION";
361 case IRP_MJ_SET_VOLUME_INFORMATION:
362 return "IRP_MJ_SET_VOLUME_INFORMATION";
363 case IRP_MJ_DIRECTORY_CONTROL:
364 return "IRP_MJ_DIRECTORY_CONTROL";
365 case IRP_MJ_FILE_SYSTEM_CONTROL:
366 return "IRP_MJ_FILE_SYSTEM_CONTROL";
367 case IRP_MJ_DEVICE_CONTROL:
368 return "IRP_MJ_DEVICE_CONTROL";
369 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
370 return "IRP_MJ_INTERNAL_DEVICE_CONTROL";
371 case IRP_MJ_SHUTDOWN:
372 return "IRP_MJ_SHUTDOWN";
373 case IRP_MJ_LOCK_CONTROL:
374 return "IRP_MJ_LOCK_CONTROL";
375 case IRP_MJ_CLEANUP:
376 return "IRP_MJ_CLEANUP";
377 case IRP_MJ_CREATE_MAILSLOT:
378 return "IRP_MJ_CREATE_MAILSLOT";
379 case IRP_MJ_QUERY_SECURITY:
380 return "IRP_MJ_QUERY_SECURITY";
381 case IRP_MJ_SET_SECURITY:
382 return "IRP_MJ_SET_SECURITY";
383 case IRP_MJ_POWER:
384 return "IRP_MJ_POWER";
385 case IRP_MJ_SYSTEM_CONTROL:
386 return "IRP_MJ_SYSTEM_CONTROL";
387 case IRP_MJ_DEVICE_CHANGE:
388 return "IRP_MJ_DEVICE_CHANGE";
389 case IRP_MJ_QUERY_QUOTA:
390 return "IRP_MJ_QUERY_QUOTA";
391 case IRP_MJ_SET_QUOTA:
392 return "IRP_MJ_SET_QUOTA";
393 case IRP_MJ_PNP:
394 return PnPMinorFunctionString(MinorFunction);
395
396 default:
397 return "unknown_pnp_irp";
398 }
399}
400
401#endif /* DEBUG || LOG_ENABLED */
402
403/** Allocate and initialize a SHFLSTRING from a UNICODE string.
404 *
405 * @param ppShflString Where to store the pointer to the allocated SHFLSTRING structure.
406 * The structure must be deallocated with vbsfFreeNonPagedMem.
407 * @param pwc The UNICODE string. If NULL then SHFL is only allocated.
408 * @param cb Size of the UNICODE string in bytes without the trailing nul.
409 *
410 * @return Status code.
411 */
412NTSTATUS vbsfShflStringFromUnicodeAlloc(PSHFLSTRING *ppShflString, const WCHAR *pwc, uint16_t cb)
413{
414 NTSTATUS Status = STATUS_SUCCESS;
415
416 PSHFLSTRING pShflString;
417 ULONG cbShflString;
418
419 /* Calculate length required for the SHFL structure: header + chars + nul. */
420 cbShflString = SHFLSTRING_HEADER_SIZE + cb + sizeof(WCHAR);
421 pShflString = (PSHFLSTRING)vbsfAllocNonPagedMem(cbShflString);
422 if (pShflString)
423 {
424 if (ShflStringInitBuffer(pShflString, cbShflString))
425 {
426 if (pwc)
427 {
428 RtlCopyMemory(pShflString->String.ucs2, pwc, cb);
429 pShflString->String.ucs2[cb / sizeof(WCHAR)] = 0;
430 pShflString->u16Length = cb; /* without terminating null */
431 AssertMsg(pShflString->u16Length + sizeof(WCHAR) == pShflString->u16Size,
432 ("u16Length %d, u16Size %d\n", pShflString->u16Length, pShflString->u16Size));
433 }
434 else
435 {
436 /** @todo r=bird: vbsfAllocNonPagedMem already zero'ed it... */
437 RtlZeroMemory(pShflString->String.ucs2, cb + sizeof(WCHAR));
438 pShflString->u16Length = 0; /* without terminating null */
439 AssertMsg(pShflString->u16Size >= sizeof(WCHAR),
440 ("u16Size %d\n", pShflString->u16Size));
441 }
442
443 *ppShflString = pShflString;
444 }
445 else
446 {
447 vbsfFreeNonPagedMem(pShflString);
448 Status = STATUS_INSUFFICIENT_RESOURCES;
449 }
450 }
451 else
452 {
453 Status = STATUS_INSUFFICIENT_RESOURCES;
454 }
455
456 return Status;
457}
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