VirtualBox

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

Last change on this file since 55781 was 55401, checked in by vboxsync, 10 years ago

added a couple of missing Id headers

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