VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c@ 40269

Last change on this file since 40269 was 40269, checked in by vboxsync, 13 years ago

VBOXSF: updated windows guest shared folders driver.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1/** @file
2 *
3 * VirtualBox Windows Guest Shared Folders
4 *
5 * File System Driver file routines
6 */
7
8/*
9 * Copyright (C) 2012 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include "vbsf.h"
21#include <iprt/fs.h>
22
23static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext)
24{
25 NTSTATUS Status = STATUS_SUCCESS;
26
27 RxCaptureFcb;
28 RxCaptureFobx;
29
30 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
31 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
32 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
33
34 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
35
36 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
37 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
38 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
39
40 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
41
42 int vboxRC;
43
44 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
45 LONGLONG FileSize;
46
47 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
48
49 Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
50 AsyncIo, capFcb->Header.FileSize.QuadPart));
51 Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
52 pbUserBuffer, BufferMdl));
53 Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
54 ByteCount, ByteOffset, FileSize));
55
56 /* @todo check if this is necessary. */
57#if (NTDDI_VERSION >= NTDDI_VISTA) /* Correct spelling for Vista 6001 SDK. */
58 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHING_ENABLED))
59#else
60 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHEING_ENABLED))
61#endif
62 {
63 if (ByteOffset >= FileSize)
64 {
65 Log(("VBOXSF: vbsfReadInternal: EOF\n"));
66 return STATUS_END_OF_FILE;
67 }
68
69 if (ByteCount > FileSize - ByteOffset)
70 {
71 ByteCount = (ULONG)(FileSize - ByteOffset);
72 }
73 }
74
75 /* @todo read 0 bytes == always success? */
76 if ( BufferMdl == NULL
77 || ByteCount == 0)
78 {
79 AssertFailed();
80 return STATUS_INVALID_PARAMETER;
81 }
82
83 /* @todo Split large reads. */
84 vboxRC = vboxCallRead(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
85 ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
86
87 Status = VBoxErrorToNTStatus(vboxRC);
88
89 if (Status != STATUS_SUCCESS)
90 {
91 /* Nothing read. */
92 ByteCount = 0;
93 }
94
95 RxContext->InformationToReturn = ByteCount;
96
97 Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
98 Status, ByteCount));
99
100 return Status;
101}
102
103
104static VOID vbsfReadWorker(VOID *pv)
105{
106 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
107
108 Log(("VBOXSF: vbsfReadWorker: calling the worker\n"));
109
110 RxContext->IoStatusBlock.Status = vbsfReadInternal(RxContext);
111
112 Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n",
113 RxContext->IoStatusBlock.Status));
114
115 RxLowIoCompletion(RxContext);
116}
117
118
119NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext)
120{
121 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
122 vbsfReadWorker,
123 RxContext);
124
125 Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n",
126 Status));
127
128 if (Status == STATUS_SUCCESS)
129 {
130 Status = STATUS_PENDING;
131 }
132
133 return Status;
134}
135
136static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext)
137{
138 NTSTATUS Status = STATUS_SUCCESS;
139
140 RxCaptureFcb;
141 RxCaptureFobx;
142
143 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
144 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
145 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
146
147 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
148
149 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
150 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
151 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
152
153 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
154
155 int vboxRC;
156
157 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
158 LONGLONG FileSize;
159
160 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
161
162 Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
163 AsyncIo, capFcb->Header.FileSize.QuadPart));
164 Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
165 pbUserBuffer, BufferMdl));
166 Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
167 ByteCount, ByteOffset, FileSize));
168
169 /* @todo allow to write 0 bytes. */
170 if ( BufferMdl == NULL
171 || ByteCount == 0)
172 {
173 AssertFailed();
174 return STATUS_INVALID_PARAMETER;
175 }
176
177 /* @todo Split large writes. */
178 vboxRC = vboxCallWrite(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
179 ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
180
181 Status = VBoxErrorToNTStatus(vboxRC);
182
183 if (Status != STATUS_SUCCESS)
184 {
185 /* Nothing written. */
186 ByteCount = 0;
187 }
188
189 RxContext->InformationToReturn = ByteCount;
190
191 Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
192 Status, ByteCount));
193
194 return Status;
195}
196
197static VOID vbsfWriteWorker(VOID *pv)
198{
199 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
200
201 Log(("VBOXSF: vbsfWriteWorker: calling the worker\n"));
202
203 RxContext->IoStatusBlock.Status = vbsfWriteInternal(RxContext);
204
205 Log(("VBOXSF: vbsfWriteWorker: Status 0x%08X\n",
206 RxContext->IoStatusBlock.Status));
207
208 RxLowIoCompletion(RxContext);
209}
210
211
212NTSTATUS VBoxMRxWrite(IN PRX_CONTEXT RxContext)
213{
214 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
215 vbsfWriteWorker,
216 RxContext);
217
218 Log(("VBOXSF: MRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n",
219 Status));
220
221 if (Status == STATUS_SUCCESS)
222 {
223 Status = STATUS_PENDING;
224 }
225
226 return Status;
227}
228
229
230NTSTATUS VBoxMRxLocks(IN PRX_CONTEXT RxContext)
231{
232 NTSTATUS Status = STATUS_SUCCESS;
233
234 RxCaptureFcb;
235 RxCaptureFobx;
236
237 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
238 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
239 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
240
241 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
242 uint32_t fu32Lock = 0;
243 int vboxRC;
244
245 Log(("VBOXSF: MRxLocks: Operation %d\n",
246 LowIoContext->Operation));
247
248 switch (LowIoContext->Operation)
249 {
250 default:
251 AssertMsgFailed(("VBOXSF: MRxLocks: Unsupported lock/unlock type %d detected!\n",
252 LowIoContext->Operation));
253 return STATUS_NOT_IMPLEMENTED;
254
255 case LOWIO_OP_UNLOCK_MULTIPLE:
256 /* @todo Remove multiple locks listed in LowIoContext.ParamsFor.Locks.LockList. */
257 Log(("VBOXSF: MRxLocks: Unsupported LOWIO_OP_UNLOCK_MULTIPLE!\n",
258 LowIoContext->Operation));
259 return STATUS_NOT_IMPLEMENTED;
260
261 case LOWIO_OP_SHAREDLOCK:
262 fu32Lock = SHFL_LOCK_SHARED | SHFL_LOCK_PARTIAL;
263 break;
264
265 case LOWIO_OP_EXCLUSIVELOCK:
266 fu32Lock = SHFL_LOCK_EXCLUSIVE | SHFL_LOCK_PARTIAL;
267 break;
268
269 case LOWIO_OP_UNLOCK:
270 fu32Lock = SHFL_LOCK_CANCEL | SHFL_LOCK_PARTIAL;
271 break;
272 }
273
274 if (LowIoContext->ParamsFor.Locks.Flags & LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)
275 {
276 fu32Lock |= SHFL_LOCK_NOWAIT;
277 }
278 else
279 {
280 fu32Lock |= SHFL_LOCK_WAIT;
281 }
282
283 vboxRC = vboxCallLock(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
284 LowIoContext->ParamsFor.Locks.ByteOffset, LowIoContext->ParamsFor.Locks.Length, fu32Lock);
285
286 Status = VBoxErrorToNTStatus(vboxRC);
287
288 Log(("VBOXSF: MRxLocks: Returned 0x%08X\n",
289 Status));
290 return Status;
291}
292
293NTSTATUS VBoxMRxCompleteBufferingStateChangeRequest(IN OUT PRX_CONTEXT RxContext,
294 IN OUT PMRX_SRV_OPEN SrvOpen,
295 IN PVOID pContext)
296{
297 Log(("VBOXSF: MRxCompleteBufferingStateChangeRequest: not implemented\n"));
298 return STATUS_NOT_IMPLEMENTED;
299}
300
301NTSTATUS VBoxMRxFlush (IN PRX_CONTEXT RxContext)
302{
303 NTSTATUS Status = STATUS_SUCCESS;
304
305 RxCaptureFcb;
306 RxCaptureFobx;
307
308 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
309 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
310 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
311
312 int vboxRC;
313
314 Log(("VBOXSF: MRxFlush\n"));
315
316 /* Do the actual flushing of file buffers */
317 vboxRC = vboxCallFlush(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
318
319 Status = VBoxErrorToNTStatus(vboxRC);
320
321 Log(("VBOXSF: MRxFlush: Returned 0x%08X\n",
322 Status));
323 return Status;
324}
325
326NTSTATUS vbsfSetEndOfFile(IN OUT struct _RX_CONTEXT * RxContext,
327 IN OUT PLARGE_INTEGER pNewFileSize,
328 OUT PLARGE_INTEGER pNewAllocationSize)
329{
330 NTSTATUS Status = STATUS_SUCCESS;
331
332 RxCaptureFcb;
333 RxCaptureFobx;
334
335 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
336 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
337 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
338
339 PSHFLFSOBJINFO pObjInfo;
340 uint32_t cbBuffer;
341 int vboxRC;
342
343 Log(("VBOXSF: vbsfSetEndOfFile: New size = %RX64 (%p), pNewAllocationSize = %p\n",
344 pNewFileSize->QuadPart, pNewFileSize, pNewAllocationSize));
345
346 Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
347
348 cbBuffer = sizeof(SHFLFSOBJINFO);
349 pObjInfo = (SHFLFSOBJINFO *)vbsfAllocNonPagedMem(cbBuffer);
350 if (pObjInfo == NULL)
351 {
352 AssertFailed();
353 return STATUS_INSUFFICIENT_RESOURCES;
354 }
355
356 RtlZeroMemory(pObjInfo, cbBuffer);
357 pObjInfo->cbObject = pNewFileSize->QuadPart;
358
359 vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
360 SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)pObjInfo);
361
362 Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo returned %Rrc\n",
363 vboxRC));
364
365 Status = VBoxErrorToNTStatus(vboxRC);
366 if (Status == STATUS_SUCCESS)
367 {
368 Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo new allocation size = %RX64\n",
369 pObjInfo->cbAllocated));
370
371 /* Return new allocation size */
372 pNewAllocationSize->QuadPart = pObjInfo->cbAllocated;
373 }
374
375 if (pObjInfo)
376 {
377 vbsfFreeNonPagedMem(pObjInfo);
378 }
379
380 Log(("VBOXSF: vbsfSetEndOfFile: Returned 0x%08X\n",
381 Status));
382 return Status;
383}
384
385NTSTATUS VBoxMRxExtendStub(IN OUT struct _RX_CONTEXT * RxContext,
386 IN OUT PLARGE_INTEGER pNewFileSize,
387 OUT PLARGE_INTEGER pNewAllocationSize)
388{
389 /* Note: On Windows hosts vbsfSetEndOfFile returns ACCESS_DENIED if the file has been
390 * opened in APPEND mode. Writes to a file will extend it anyway, therefore it is
391 * better to not call the host at all and tell the caller that the file was extended.
392 */
393 Log(("VBOXSF: MRxExtendStub: new size = %RX64\n",
394 pNewFileSize->QuadPart));
395
396 pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
397
398 return STATUS_SUCCESS;
399}
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