VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.c@ 76563

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