VirtualBox

source: vbox/trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp@ 77661

最後變更 在這個檔案從77661是 77661,由 vboxsync 提交於 6 年 前

os2/vboxsf: Supply RTFS_DOS_NT_NORMAL if fMode is zero, or the host will make no changes (resetting readonly bit not possible). Fake case correction or the icsdebug won't display sources (among other things). Detect reads beyond EOF and skip updating sfi_sizel and timestamps. Both FS32_READ and FS32_WRITE had one or three instances of 'rc' variable shadowing.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 63.0 KB
 
1/** $Id: VBoxSFFile.cpp 77661 2019-03-11 21:14:16Z vboxsync $ */
2/** @file
3 * VBoxSF - OS/2 Shared Folders, the file level IFS EPs.
4 */
5
6/*
7 * Copyright (c) 2007-2018 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#define LOG_GROUP LOG_GROUP_DEFAULT
36#include "VBoxSFInternal.h"
37
38#include <VBox/log.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/err.h>
42#include <iprt/mem.h>
43
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48/** A preallocated buffer. */
49typedef struct
50{
51 RTCCPHYS PhysAddr;
52 void *pvBuf;
53 bool volatile fBusy;
54} VBOXSFOS2BUF;
55
56
57/*********************************************************************************************************************************
58* Global Variables *
59*********************************************************************************************************************************/
60/** Buffer spinlock. */
61static SpinLock_t g_BufferLock;
62/** 64KB buffers. */
63static VBOXSFOS2BUF g_aBigBuffers[4];
64
65
66
67/**
68 * Initialize file buffers.
69 */
70void vboxSfOs2InitFileBuffers(void)
71{
72 KernAllocSpinLock(&g_BufferLock);
73
74 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
75 {
76 g_aBigBuffers[i].pvBuf = RTMemContAlloc(&g_aBigBuffers[i].PhysAddr, _64K);
77 g_aBigBuffers[i].fBusy = g_aBigBuffers[i].pvBuf == NULL;
78 }
79}
80
81
82/**
83 * Allocates a big buffer.
84 * @returns Pointer to buffer on success, NULL on failure.
85 * @param pPhysAddr The physical address of the buffer.
86 */
87DECLINLINE(void *) vboxSfOs2AllocBigBuffer(RTGCPHYS *pPhysAddr)
88{
89 KernAcquireSpinLock(&g_BufferLock);
90 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
91 if (!g_aBigBuffers[i].fBusy)
92 {
93 g_aBigBuffers[i].fBusy = true;
94 KernReleaseSpinLock(&g_BufferLock);
95
96 *pPhysAddr = g_aBigBuffers[i].PhysAddr;
97 return g_aBigBuffers[i].pvBuf;
98 }
99 KernReleaseSpinLock(&g_BufferLock);
100 *pPhysAddr = NIL_RTGCPHYS;
101 return NULL;
102}
103
104
105/**
106 * Frees a big buffer.
107 * @param pvBuf The address of the buffer to be freed.
108 */
109DECLINLINE(void) vboxSfOs2FreeBigBuffer(void *pvBuf)
110{
111 Assert(pvBuf);
112 KernAcquireSpinLock(&g_BufferLock);
113 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
114 if (g_aBigBuffers[i].pvBuf == pvBuf)
115 {
116 Assert(g_aBigBuffers[i].fBusy);
117 g_aBigBuffers[i].fBusy = false;
118 KernReleaseSpinLock(&g_BufferLock);
119 return;
120 }
121 KernReleaseSpinLock(&g_BufferLock);
122 AssertFailed();
123}
124
125
126
127DECLASM(APIRET)
128FS32_OPENCREATE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszName, LONG offCurDirEnd,
129 PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fOpenMode, USHORT fOpenFlags,
130 PUSHORT puAction, ULONG fAttribs, BYTE const *pbEaBuf, PUSHORT pfGenFlag)
131{
132 LogFlow(("FS32_OPENCREATE: pCdFsi=%p pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pSfFsi=%p pSfFsd=%p fOpenMode=%#x fOpenFlags=%#x puAction=%p fAttribs=%#x pbEaBuf=%p pfGenFlag=%p\n",
133 pCdFsi, pCdFsd, pszName, pszName, offCurDirEnd, pSfFsi, pSfFsd, fOpenMode, fOpenFlags, puAction, fAttribs, pbEaBuf, pfGenFlag));
134 RT_NOREF(pfGenFlag, pCdFsi);
135
136 /*
137 * Validate and convert parameters.
138 */
139 /* No EAs. */
140 if (!pbEaBuf)
141 { /* likely */ }
142 else
143 {
144 LogRel(("FS32_OPENCREATE: Returns ERROR_EAS_NOT_SUPPORTED [%p];\n", pbEaBuf));
145 return ERROR_EAS_NOT_SUPPORTED;
146 }
147
148 /* No direct access. */
149 if (!(fOpenMode & OPEN_FLAGS_DASD))
150 { /* likely */ }
151 else
152 {
153 LogRel(("FS32_OPENCREATE: Returns ERROR_ACCESS_DENIED [DASD];\n"));
154 return ERROR_ACCESS_DENIED;
155 }
156
157 /*
158 * Allocate request buffer and resovle the path to folder and folder relative path.
159 */
160 PVBOXSFFOLDER pFolder;
161 VBOXSFCREATEREQ *pReq;
162 APIRET rc = vboxSfOs2ResolvePathEx(pszName, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
163 &pFolder, (void **)&pReq);
164 LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
165 if (rc == NO_ERROR)
166 { /* likely */ }
167 else
168 return rc;
169
170 /*
171 * Continue validating and converting parameters.
172 */
173 /* access: */
174 if (fOpenMode & OPEN_ACCESS_READWRITE)
175 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
176 else if (fOpenMode & OPEN_ACCESS_WRITEONLY)
177 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_WRITE | SHFL_CF_ACCESS_ATTR_WRITE;
178 else
179 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
180
181 /* Sharing: */
182 switch (fOpenMode & (OPEN_SHARE_DENYNONE | OPEN_SHARE_DENYREADWRITE | OPEN_SHARE_DENYREAD | OPEN_SHARE_DENYWRITE))
183 {
184 case OPEN_SHARE_DENYNONE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
185 case OPEN_SHARE_DENYWRITE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
186 case OPEN_SHARE_DENYREAD: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
187 case OPEN_SHARE_DENYREADWRITE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
188 case 0: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
189 default:
190 LogRel(("FS32_OPENCREATE: Invalid file sharing mode: %#x\n", fOpenMode));
191 VbglR0PhysHeapFree(pReq);
192 return VERR_INVALID_PARAMETER;
193
194 }
195
196 /* How to open the file: */
197 switch (fOpenFlags & 0x13)
198 {
199 case OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x00 */
200 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
201 break;
202 case OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x10 */
203 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
204 break;
205 case OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x01 */
206 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
207 break;
208 case OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x11 */
209 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
210 break;
211 case OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x02 */
212 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
213 break;
214 case OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
215 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
216 break;
217 default:
218 LogRel(("FS32_OPENCREATE: Invalid file open flags: %#x\n", fOpenFlags));
219 VbglR0PhysHeapFree(pReq);
220 return VERR_INVALID_PARAMETER;
221 }
222
223 /* Misc: cache, etc? There seems to be no API for that. */
224
225 /* Attributes: */
226 pReq->CreateParms.Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
227
228 /* Initial size: */
229 if (pSfFsi->sfi_sizel > 0)
230 pReq->CreateParms.Info.cbObject = pSfFsi->sfi_sizel;
231
232 /*
233 * Try open the file.
234 */
235 int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
236 LogFlow(("FS32_OPENCREATE: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
237 vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
238 if (RT_SUCCESS(vrc))
239 {
240 switch (pReq->CreateParms.Result)
241 {
242 case SHFL_FILE_EXISTS:
243 if (pReq->CreateParms.Handle == SHFL_HANDLE_NIL)
244 {
245 rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
246 break;
247 }
248 RT_FALL_THRU();
249 case SHFL_FILE_CREATED:
250 case SHFL_FILE_REPLACED:
251 if ( pReq->CreateParms.Info.cbObject < _2G
252 || (fOpenMode & OPEN_FLAGS_LARGEFILE))
253 {
254 pSfFsd->u32Magic = VBOXSFSYFI_MAGIC;
255 pSfFsd->pSelf = pSfFsd;
256 pSfFsd->hHostFile = pReq->CreateParms.Handle;
257 pSfFsd->pFolder = pFolder;
258
259 uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
260 Assert(cOpenFiles < _32K);
261 pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
262
263 pSfFsi->sfi_sizel = pReq->CreateParms.Info.cbObject;
264 pSfFsi->sfi_type = STYPE_FILE;
265 pSfFsi->sfi_DOSattr = (uint8_t)((pReq->CreateParms.Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
266 int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
267 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->CreateParms.Info.BirthTime, cMinLocalTimeDelta);
268 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->CreateParms.Info.AccessTime, cMinLocalTimeDelta);
269 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->CreateParms.Info.ModificationTime, cMinLocalTimeDelta);
270 if (pReq->CreateParms.Result == SHFL_FILE_CREATED)
271 pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
272
273 *puAction = pReq->CreateParms.Result == SHFL_FILE_CREATED ? FILE_CREATED
274 : pReq->CreateParms.Result == SHFL_FILE_EXISTS ? FILE_EXISTED
275 : FILE_TRUNCATED;
276
277 Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
278 rc = NO_ERROR;
279 }
280 else
281 {
282 LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pReq->CreateParms.Info.cbObject, pszName));
283 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
284 VbglR0SfHostReqClose(pFolder->idHostRoot, (VBOXSFCLOSEREQ *)pReq, pReq->CreateParms.Handle);
285 rc = ERROR_ACCESS_DENIED;
286 }
287 break;
288
289 case SHFL_PATH_NOT_FOUND:
290 rc = ERROR_PATH_NOT_FOUND;
291 break;
292
293 default:
294 case SHFL_FILE_NOT_FOUND:
295 rc = ERROR_OPEN_FAILED;
296 break;
297 }
298 }
299 else if (vrc == VERR_ALREADY_EXISTS)
300 rc = ERROR_ACCESS_DENIED;
301 else if (vrc == VERR_FILE_NOT_FOUND)
302 rc = ERROR_OPEN_FAILED;
303 else
304 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
305 VbglR0PhysHeapFree(pReq);
306 vboxSfOs2ReleaseFolder(pFolder);
307 LogFlow(("FS32_OPENCREATE: returns %u\n", rc));
308 return rc;
309}
310
311
312DECLASM(APIRET)
313FS32_CLOSE(ULONG uType, ULONG fIoFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
314{
315 LogFlow(("FS32_CLOSE: uType=%#x fIoFlags=%#x pSfFsi=%p pSfFsd=%p:{%#x, %#llx}\n",
316 uType, fIoFlags, pSfFsi, pSfFsd, pSfFsd->u32Magic, pSfFsd->hHostFile));
317
318 /*
319 * Validate input.
320 */
321 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
322 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
323 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
324 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
325 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
326 Assert(pFolder->cOpenFiles > 0);
327
328 /*
329 * We only care for when the system is done truly with the file
330 * and we can close it.
331 */
332 if (uType != FS_CL_FORSYS)
333 return NO_ERROR;
334
335 /** @todo flush file if fIoFlags says so? */
336 RT_NOREF(fIoFlags);
337
338 int vrc = VbglR0SfHostReqCloseSimple(pFolder->idHostRoot, pSfFsd->hHostFile);
339 AssertRC(vrc);
340
341 pSfFsd->hHostFile = SHFL_HANDLE_NIL;
342 pSfFsd->pSelf = NULL;
343 pSfFsd->u32Magic = ~VBOXSFSYFI_MAGIC;
344 pSfFsd->pFolder = NULL;
345
346 ASMAtomicDecU32(&pFolder->cOpenFiles);
347 vboxSfOs2ReleaseFolder(pFolder);
348
349 RT_NOREF(pSfFsi);
350 LogFlow(("FS32_CLOSE: returns NO_ERROR\n"));
351 return NO_ERROR;
352}
353
354
355DECLASM(APIRET)
356FS32_COMMIT(ULONG uType, ULONG fIoFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
357{
358 LogFlow(("FS32_COMMIT: uType=%#x fIoFlags=%#x pSfFsi=%p pSfFsd=%p:{%#x}\n", uType, fIoFlags, pSfFsi, pSfFsd, pSfFsd->u32Magic));
359
360 /*
361 * Validate input.
362 */
363 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
364 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
365 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
366 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
367 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
368 Assert(pFolder->cOpenFiles > 0);
369 RT_NOREF(pFolder);
370
371 /*
372 * We only need to flush writable files.
373 */
374 if ( (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_WRITEONLY
375 || (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_READWRITE)
376 {
377 int vrc = VbglR0SfHostReqFlushSimple(pFolder->idHostRoot, pSfFsd->hHostFile);
378 if (RT_FAILURE(vrc))
379 {
380 LogRel(("FS32_COMMIT: VbglR0SfHostReqFlushSimple failed: %Rrc\n", vrc));
381 return ERROR_FLUSHBUF_FAILED;
382 }
383 }
384
385 NOREF(uType); NOREF(fIoFlags); NOREF(pSfFsi);
386 LogFlow(("FS32_COMMIT: returns NO_ERROR\n"));
387 return NO_ERROR;
388}
389
390
391extern "C" APIRET APIENTRY
392FS32_CHGFILEPTRL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONGLONG off, ULONG uMethod, ULONG fIoFlags)
393{
394 LogFlow(("FS32_CHGFILEPTRL: pSfFsi=%p pSfFsd=%p off=%RI64 (%#RX64) uMethod=%u fIoFlags=%#x\n",
395 pSfFsi, pSfFsd, off, off, uMethod, fIoFlags));
396
397 /*
398 * Validate input.
399 */
400 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
401 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
402 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
403 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
404 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
405 Assert(pFolder->cOpenFiles > 0);
406
407 /*
408 * Calc absolute offset.
409 */
410 int64_t offNew;
411 switch (uMethod)
412 {
413 case CFP_RELBEGIN:
414 if (off >= 0)
415 {
416 offNew = off;
417 break;
418 }
419 Log(("FS32_CHGFILEPTRL: Negative seek (BEGIN): %RI64\n", off));
420 return ERROR_NEGATIVE_SEEK;
421
422 case CFP_RELCUR:
423 offNew = pSfFsi->sfi_positionl + off;
424 if (offNew >= 0)
425 break;
426 Log(("FS32_CHGFILEPTRL: Negative seek (RELCUR): %RU64 + %RI64\n", pSfFsi->sfi_positionl, off));
427 return ERROR_NEGATIVE_SEEK;
428
429 case CFP_RELEND:
430 {
431 /* Have to consult the host to get the current file size. */
432 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
433 if (pReq)
434 RT_ZERO(*pReq);
435 else
436 return ERROR_NOT_ENOUGH_MEMORY;
437
438 int vrc = VbglR0SfHostReqQueryObjInfo(pFolder->idHostRoot, pReq, pSfFsd->hHostFile);
439 if (RT_SUCCESS(vrc))
440 {
441 if (pSfFsi->sfi_mode & SFMODE_LARGE_FILE)
442 pSfFsi->sfi_sizel = pReq->ObjInfo.cbObject;
443 else
444 pSfFsi->sfi_sizel = RT_MIN(pReq->ObjInfo.cbObject, _2G - 1);
445 }
446 else
447 LogRel(("FS32_CHGFILEPTRL/CFP_RELEND: VbglR0SfFsInfo failed: %Rrc\n", vrc));
448
449 VbglR0PhysHeapFree(pReq);
450
451 offNew = pSfFsi->sfi_sizel + off;
452 if (offNew >= 0)
453 break;
454 Log(("FS32_CHGFILEPTRL: Negative seek (CFP_RELEND): %RI64 + %RI64\n", pSfFsi->sfi_sizel, off));
455 return ERROR_NEGATIVE_SEEK;
456 }
457
458
459 default:
460 LogRel(("FS32_CHGFILEPTRL: Unknown seek method: %#x\n", uMethod));
461 return ERROR_INVALID_FUNCTION;
462 }
463
464 /*
465 * Commit the seek.
466 */
467 pSfFsi->sfi_positionl = offNew;
468 LogFlow(("FS32_CHGFILEPTRL: returns; sfi_positionl=%RI64\n", offNew));
469 RT_NOREF_PV(fIoFlags);
470 return NO_ERROR;
471}
472
473
474/** Forwards the call to FS32_CHGFILEPTRL. */
475DECLASM(APIRET)
476FS32_CHGFILEPTR(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONG off, ULONG uMethod, ULONG fIoFlags)
477{
478 return FS32_CHGFILEPTRL(pSfFsi, pSfFsd, off, uMethod, fIoFlags);
479}
480
481
482/**
483 * Worker for FS32_PATHINFO that handles file stat setting.
484 *
485 * @returns OS/2 status code
486 * @param pFolder The folder.
487 * @param pSfFsi The file system independent file structure. We'll
488 * update the timestamps and size here.
489 * @param pSfFsd Out file data.
490 * @param uLevel The information level.
491 * @param pbData The stat data to set.
492 * @param cbData The uLevel specific input size.
493 */
494static APIRET
495vboxSfOs2SetFileInfo(PVBOXSFFOLDER pFolder, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel, PBYTE pbData, ULONG cbData)
496{
497 APIRET rc;
498
499 /*
500 * Data buffer both for caching user data and for issuing the
501 * change request to the host.
502 */
503 struct SetFileInfoBuf
504 {
505 union
506 {
507 FILESTATUS Lvl1;
508 FILESTATUS3L Lvl1L;
509 };
510 SHFLFSOBJINFO ObjInfo;
511 } *pBuf = (struct SetFileInfoBuf *)VbglR0PhysHeapAlloc(sizeof(*pBuf));
512 if (pBuf)
513 {
514 /* Copy in the data. */
515 rc = KernCopyIn(&pBuf->Lvl1, pbData, cbData);
516 if (rc == NO_ERROR)
517 {
518 /*
519 * Join paths with FS32_PATHINFO and FS32_FILEATTRIBUTE.
520 */
521 rc = vboxSfOs2SetInfoCommonWorker(pFolder, pSfFsd->hHostFile,
522 uLevel == FI_LVL_STANDARD ? pBuf->Lvl1.attrFile : pBuf->Lvl1L.attrFile,
523 &pBuf->Lvl1, &pBuf->ObjInfo, RT_UOFFSETOF(struct SetFileInfoBuf, ObjInfo));
524 if (rc == NO_ERROR)
525 {
526 /*
527 * Update the timestamps in the independent file data with what
528 * the host returned:
529 */
530 pSfFsi->sfi_tstamp |= ST_PCREAT | ST_PWRITE | ST_PREAD;
531 pSfFsi->sfi_tstamp &= ~(ST_SCREAT | ST_SWRITE| ST_SREAD);
532 uint16_t cDelta = vboxSfOs2GetLocalTimeDelta();
533 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pBuf->ObjInfo.BirthTime, cDelta);
534 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pBuf->ObjInfo.AccessTime, cDelta);
535 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pBuf->ObjInfo.ModificationTime, cDelta);
536
537 /* And the size field as we're at it: */
538 pSfFsi->sfi_sizel = pBuf->ObjInfo.cbObject;
539 }
540 else
541 rc = ERROR_INVALID_PARAMETER;
542 }
543
544 VbglR0PhysHeapFree(pBuf);
545 }
546 else
547 rc = ERROR_NOT_ENOUGH_MEMORY;
548 return rc;
549}
550
551
552#if 0
553
554DECLVBGL(int) VbglR0SfFastPhysFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
555 uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer)
556{
557 struct FsInfoReq
558 {
559 VBGLIOCIDCHGCMFASTCALL Hdr;
560 VMMDevHGCMCall Call;
561 VBoxSFParmInformation Parms;
562 HGCMPageListInfo PgLst;
563 RTGCPHYS64 PageTwo;
564 } *pReq;
565 AssertCompileMemberOffset(struct FsInfoReq, Call, 52);
566 AssertCompileMemberOffset(struct FsInfoReq, Parms, 0x60);
567
568 pReq = (struct FsInfoReq *)VbglR0PhysHeapAlloc(sizeof(*pReq));
569 if (!pReq)
570 return VERR_NO_MEMORY;
571
572 VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, pClient->idClient,
573 SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
574#if 0
575 VBGLREQHDR_INIT_EX(&pReq->Hdr.Hdr, sizeof(*pReq), sizeof(*pReq));
576 pReq->Hdr.GCPhysReq = VbglR0PhysHeapGetPhysAddr(pReq) + sizeof(pReq->Hdr);
577 pReq->Hdr.fInterruptible = false;
578
579 pReq->Call.header.header.size = sizeof(*pReq) - sizeof(pReq->Hdr);
580 pReq->Call.header.header.version = VBGLREQHDR_VERSION;
581 pReq->Call.header.header.requestType= VMMDevReq_HGCMCall32;
582 pReq->Call.header.header.rc = VERR_INTERNAL_ERROR;
583 pReq->Call.header.header.reserved1 = 0;
584 pReq->Call.header.header.fRequestor = VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER
585 | VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN;
586 pReq->Call.header.fu32Flags = 0;
587 pReq->Call.header.result = VERR_INTERNAL_ERROR;
588 pReq->Call.u32ClientID = pClient->idClient;
589 pReq->Call.u32Function = SHFL_FN_INFORMATION;
590 pReq->Call.cParms = SHFL_CPARMS_INFORMATION;
591#endif
592 uint32_t const cbBuffer = *pcbBuffer;
593 pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
594 pReq->Parms.id32Root.u.value32 = pMap->root;
595 pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
596 pReq->Parms.u64Handle.u.value64 = hFile;
597 pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
598 pReq->Parms.f32Flags.u.value32 = flags;
599 pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
600 pReq->Parms.cb32.u.value32 = cbBuffer;
601 pReq->Parms.pInfo.type = VMMDevHGCMParmType_PageList;
602 pReq->Parms.pInfo.u.PageList.size = cbBuffer;
603 pReq->Parms.pInfo.u.PageList.offset = RT_UOFFSETOF(struct FsInfoReq, PgLst) - RT_UOFFSETOF(struct FsInfoReq, Call);
604
605 Assert(cbBuffer < _1K);
606 pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
607 pReq->PgLst.cPages = cbBuffer <= (PAGE_SIZE - ((uintptr_t)pBuffer & PAGE_OFFSET_MASK)) ? 1 : 2;
608 pReq->PgLst.offFirstPage = (uint16_t)((uintptr_t)pBuffer & PAGE_OFFSET_MASK);
609 pReq->PgLst.aPages[0] = VbglR0PhysHeapGetPhysAddr(pBuffer) & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
610 if (pReq->PgLst.cPages == 1)
611 pReq->PageTwo = NIL_RTGCPHYS64;
612 else
613 pReq->PageTwo = pReq->PgLst.aPages[0] + PAGE_SIZE;
614
615 int rc = VbglR0HGCMFastCall(pClient->handle, &pReq->Hdr, sizeof(*pReq));
616 if (RT_SUCCESS(rc))
617 {
618 rc = pReq->Call.header.result;
619 *pcbBuffer = pReq->Parms.cb32.u.value32;
620 }
621 VbglR0PhysHeapFree(pReq);
622 return rc;
623}
624
625
626DECLVBGL(int) VbglR0SfPhysFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
627 uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer)
628{
629 uint32_t const cbBuffer = *pcbBuffer;
630
631 struct
632 {
633 VBoxSFInformation Core;
634 HGCMPageListInfo PgLst;
635 RTGCPHYS64 PageTwo;
636 } Req;
637
638 VBGL_HGCM_HDR_INIT_EX(&Req.Core.callInfo, pClient->idClient, SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(Req));
639 Req.Core.callInfo.fInterruptible = false;
640
641 Req.Core.root.type = VMMDevHGCMParmType_32bit;
642 Req.Core.root.u.value32 = pMap->root;
643
644 Req.Core.handle.type = VMMDevHGCMParmType_64bit;
645 Req.Core.handle.u.value64 = hFile;
646 Req.Core.flags.type = VMMDevHGCMParmType_32bit;
647 Req.Core.flags.u.value32 = flags;
648 Req.Core.cb.type = VMMDevHGCMParmType_32bit;
649 Req.Core.cb.u.value32 = cbBuffer;
650 Req.Core.info.type = VMMDevHGCMParmType_PageList;
651 Req.Core.info.u.PageList.size = cbBuffer;
652 Req.Core.info.u.PageList.offset = sizeof(Req.Core);
653
654 Assert(cbBuffer < _1K);
655 Req.PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
656 Req.PgLst.cPages = cbBuffer <= (PAGE_SIZE - ((uintptr_t)pBuffer & PAGE_OFFSET_MASK)) ? 1 : 2;
657 Req.PgLst.offFirstPage = (uint16_t)((uintptr_t)pBuffer & PAGE_OFFSET_MASK);
658 Req.PgLst.aPages[0] = VbglR0PhysHeapGetPhysAddr(pBuffer) & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
659 if (Req.PgLst.cPages == 1)
660 Req.PageTwo = NIL_RTGCPHYS64;
661 else
662 Req.PageTwo = Req.PgLst.aPages[0] + PAGE_SIZE;
663
664 int rc = VbglR0HGCMCallRaw(pClient->handle, &Req.Core.callInfo, sizeof(Req));
665 //Log(("VBOXSF: VbglR0SfFsInfo: VbglR0HGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.Hdr.rc));
666 if (RT_SUCCESS(rc))
667 {
668 rc = Req.Core.callInfo.Hdr.rc;
669 *pcbBuffer = Req.Core.cb.u.value32;
670 }
671 return rc;
672}
673
674#endif
675
676
677/**
678 * Worker for FS32_PATHINFO that handles file stat queries.
679 *
680 * @returns OS/2 status code
681 * @param pFolder The folder.
682 * @param pSfFsi The file system independent file structure. We'll
683 * update the timestamps and size here.
684 * @param pSfFsd Out file data.
685 * @param uLevel The information level.
686 * @param pbData Where to return the data (user address).
687 * @param cbData The amount of data to produce.
688 */
689static APIRET
690vboxSfOs2QueryFileInfo(PVBOXSFFOLDER pFolder, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel, PBYTE pbData, ULONG cbData)
691{
692 /*
693 * Performance notes (@bugref{9172}):
694 *
695 * This function was used for some performance hacking in an attempt at
696 * squeezing more performance out of the HGCM and shared folders code.
697 *
698 * 0. Skip calling the host and returning zeros:
699 * 906 ns / 3653 ticks
700 *
701 * This is comparable to JFS (859 ns) and HPFS (1107 ns) and give an
702 * idea what we're up against compared to a "local" file system.
703 *
704 * Host build of r126639 with strict VBoxGuest.sys and VBoxSF.ifs
705 * circa r126775, just for establishing some actual base line for (2, 3, +):
706 * (a) 39095 ns / 156757 ticks - VbglR0SfFsInfo.
707 * (b) 35074 ns / 140880 ticks - VbglR0SfPhysFsInfo.
708 *
709 * 1. Having shortcircuted the host side processing by faking a success when
710 * VMMDevHGCM.cpp is about to do pThis->pHGCMDrv->pfnCall, then measuring
711 * various guest side changes in the request and request submission path:
712 *
713 * - Saved by page lists vs virtul address for buffers:
714 * 4095 ns / 16253 ticks / %35.
715 *
716 * Suspect this is due to expensive memory locking on the guest side and
717 * the host doing extra virtual address conversion.
718 *
719 * - Saved by no repackaging the HGCM requests:
720 * 450 ns / 1941 ticks / 5.8%.
721 *
722 * - Embedding the SHFLFSOBJINFO into the buffer may save a little as well:
723 * 286 ns / 1086 ticks / 3.9%.
724 *
725 * Raw data:
726 * 11843 ns / 47469 ticks - VbglR0SfFsInfo.
727 * 7748 ns / 31216 ticks - VbglR0SfPhysFsInfo.
728 * 7298 ns / 29275 ticks - VbglR0SfFastPhysFsInfo.
729 * 7012 ns / 28189 ticks - Embedded buffer.
730 *
731 * 2. Interrupt acknowledgement in VBoxGuest goes to ring-3, which is wasteful.
732 * Played around with handling VMMDevReq_AcknowledgeEvents requests in
733 * ring-0, but since it just returns a 32-bit mask of pending events it was
734 * more natural to implement it as a 32-bit IN operation.
735 *
736 * Saves 4217 ns / 17048 ticks / 13%.
737 *
738 * Raw data:
739 * 32027 ns / 128506 ticks - ring-3 VMMDevReq_AcknowledgeEvents.
740 * 27810 ns / 111458 ticks - fast ring-0 ACK.
741 *
742 * 3. Use single release & auto resetting event semaphore in HGCMThread.
743 *
744 * Saves 922 ns / 3406 ticks / 3.4%.
745 *
746 * Raw data:
747 * 27472 ns / 110237 ticks - RTSEMEVENTMULTI
748 * 26550 ns / 106831 ticks - RTSEMEVENT
749 *
750 * Gain since 0a: 12545 ns / 49926 ticks / 32%
751 * Gain since 0b: 8524 ns / 34049 ticks / 24%
752 *
753 * 4. Try handle VINF_EM_HALT from HMR0 in ring-0, avoiding 4 context switches
754 * and a EM reschduling.
755 *
756 * Saves 1216 ns / 4734 ticks / 4.8%.
757 *
758 * Raw data:
759 * 25595 ns / 102768 ticks - no ring-0 HLT.
760 * 24379 ns / 98034 ticks - ring-0 HLT (42 spins)
761 *
762 * Gain since 0a: 14716 ns / 58723 ticks / 38%
763 * Gain since 0b: 10695 ns / 42846 ticks / 30%
764 *
765 */
766#if 0
767 APIRET rc;
768 PSHFLFSOBJINFO pObjInfo = (PSHFLFSOBJINFO)VbglR0PhysHeapAlloc(sizeof(*pObjInfo));
769 if (pObjInfo)
770 {
771 RT_ZERO(*pObjInfo);
772 uint32_t cbObjInfo = sizeof(*pObjInfo);
773
774 int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
775 SHFL_INFO_FILE | SHFL_INFO_GET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
776 if (RT_SUCCESS(vrc))
777 {
778 rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, pObjInfo);
779 if (rc == NO_ERROR)
780 {
781 /* Update the timestamps in the independent file data: */
782 int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
783 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pObjInfo->BirthTime, cMinLocalTimeDelta);
784 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pObjInfo->AccessTime, cMinLocalTimeDelta);
785 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pObjInfo->ModificationTime, cMinLocalTimeDelta);
786
787 /* And the size field as we're at it: */
788 pSfFsi->sfi_sizel = pObjInfo->cbObject;
789 }
790 }
791 else
792 {
793 Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc));
794 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
795 }
796 VbglR0PhysHeapFree(pObjInfo);
797 }
798 else
799 rc = ERROR_NOT_ENOUGH_MEMORY;
800#elif 0
801 APIRET rc;
802 struct MyEmbReq
803 {
804 VBGLIOCIDCHGCMFASTCALL Hdr;
805 VMMDevHGCMCall Call;
806 VBoxSFParmInformation Parms;
807 SHFLFSOBJINFO ObjInfo;
808 } *pReq = (struct MyEmbReq *)VbglR0PhysHeapAlloc(sizeof(*pReq));
809 if (pReq)
810 {
811 RT_ZERO(pReq->ObjInfo);
812
813 VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
814 SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
815 pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
816 pReq->Parms.id32Root.u.value32 = pFolder->idHostRoot;
817 pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
818 pReq->Parms.u64Handle.u.value64 = pSfFsd->hHostFile;
819 pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
820 pReq->Parms.f32Flags.u.value32 = SHFL_INFO_FILE | SHFL_INFO_GET;
821 pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
822 pReq->Parms.cb32.u.value32 = sizeof(pReq->ObjInfo);
823 pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
824 pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->ObjInfo);
825 pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(struct MyEmbReq, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
826 pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
827
828 int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
829 if (RT_SUCCESS(vrc))
830 vrc = pReq->Call.header.result;
831 if (RT_SUCCESS(vrc))
832 {
833 rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, &pReq->ObjInfo);
834 if (rc == NO_ERROR)
835 {
836 /* Update the timestamps in the independent file data: */
837 int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
838 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->ObjInfo.BirthTime, cMinLocalTimeDelta);
839 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->ObjInfo.AccessTime, cMinLocalTimeDelta);
840 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->ObjInfo.ModificationTime, cMinLocalTimeDelta);
841
842 /* And the size field as we're at it: */
843 pSfFsi->sfi_sizel = pReq->ObjInfo.cbObject;
844 }
845 }
846 else
847 {
848 Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc));
849 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
850 }
851
852 VbglR0PhysHeapFree(pReq);
853 }
854 else
855 rc = ERROR_NOT_ENOUGH_MEMORY;
856#else /* clean version of the above. */
857 APIRET rc;
858 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
859 if (pReq)
860 {
861 int vrc = VbglR0SfHostReqQueryObjInfo(pFolder->idHostRoot, pReq, pSfFsd->hHostFile);
862 if (RT_SUCCESS(vrc))
863 {
864 rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, &pReq->ObjInfo);
865 if (rc == NO_ERROR)
866 {
867 /* Update the timestamps in the independent file data: */
868 int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
869 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->ObjInfo.BirthTime, cMinLocalTimeDelta);
870 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->ObjInfo.AccessTime, cMinLocalTimeDelta);
871 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->ObjInfo.ModificationTime, cMinLocalTimeDelta);
872
873 /* And the size field as we're at it: */
874 pSfFsi->sfi_sizel = pReq->ObjInfo.cbObject;
875 }
876 }
877 else
878 {
879 Log(("vboxSfOs2QueryFileInfo: VbglR0SfHostReqQueryObjInfo failed: %Rrc\n", vrc));
880 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
881 }
882
883 VbglR0PhysHeapFree(pReq);
884 }
885 else
886 rc = ERROR_NOT_ENOUGH_MEMORY;
887#endif
888 return rc;
889}
890
891
892DECLASM(APIRET)
893FS32_FILEINFO(ULONG fFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel,
894 PBYTE pbData, ULONG cbData, ULONG fIoFlags)
895{
896 LogFlow(("FS32_FILEINFO: fFlags=%#x pSfFsi=%p pSfFsd=%p uLevel=%p pbData=%p cbData=%#x fIoFlags=%#x\n",
897 fFlags, pSfFsi, pSfFsd, uLevel, pbData, cbData, fIoFlags));
898
899 /*
900 * Validate input.
901 */
902 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
903 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
904 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
905 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
906 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
907 Assert(pFolder->cOpenFiles > 0);
908
909 /*
910 * Check the level.
911 * Note! See notes in FS32_PATHINFO.
912 */
913 ULONG cbMinData;
914 switch (uLevel)
915 {
916 case FI_LVL_STANDARD:
917 cbMinData = sizeof(FILESTATUS);
918 AssertCompileSize(FILESTATUS, 0x16);
919 break;
920 case FI_LVL_STANDARD_64:
921 cbMinData = sizeof(FILESTATUS3L);
922 AssertCompileSize(FILESTATUS3L, 0x20); /* cbFile and cbFileAlloc are misaligned. */
923 break;
924 case FI_LVL_STANDARD_EASIZE:
925 cbMinData = sizeof(FILESTATUS2);
926 AssertCompileSize(FILESTATUS2, 0x1a);
927 break;
928 case FI_LVL_STANDARD_EASIZE_64:
929 cbMinData = sizeof(FILESTATUS4L);
930 AssertCompileSize(FILESTATUS4L, 0x24); /* cbFile and cbFileAlloc are misaligned. */
931 break;
932 case FI_LVL_EAS_FROM_LIST:
933 case FI_LVL_EAS_FULL:
934 case FI_LVL_EAS_FULL_5:
935 case FI_LVL_EAS_FULL_8:
936 cbMinData = sizeof(EAOP);
937 break;
938 default:
939 LogRel(("FS32_PATHINFO: Unsupported info level %u!\n", uLevel));
940 return ERROR_INVALID_LEVEL;
941 }
942 if (cbData < cbMinData || pbData == NULL)
943 {
944 Log(("FS32_FILEINFO: ERROR_BUFFER_OVERFLOW (cbMinData=%#x, cbData=%#x)\n", cbMinData, cbData));
945 return ERROR_BUFFER_OVERFLOW;
946 }
947
948 /*
949 * Query information.
950 */
951 APIRET rc;
952 if (fFlags == FI_RETRIEVE)
953 {
954 switch (uLevel)
955 {
956 case FI_LVL_STANDARD:
957 case FI_LVL_STANDARD_EASIZE:
958 case FI_LVL_STANDARD_64:
959 case FI_LVL_STANDARD_EASIZE_64:
960 rc = vboxSfOs2QueryFileInfo(pFolder, pSfFsi, pSfFsd, uLevel, pbData, cbMinData);
961 break;
962
963 /*
964 * We don't do EAs and we "just" need to return no-EAs.
965 * However, that's not as easy as you might think.
966 */
967 case FI_LVL_EAS_FROM_LIST:
968 case FI_LVL_EAS_FULL:
969 case FI_LVL_EAS_FULL_5:
970 case FI_LVL_EAS_FULL_8:
971 rc = vboxSfOs2MakeEmptyEaList((PEAOP)pbData, uLevel);
972 break;
973
974 default:
975 AssertFailed();
976 rc = ERROR_GEN_FAILURE;
977 break;
978 }
979 }
980 /*
981 * Update information.
982 */
983 else if (fFlags == FI_SET)
984 {
985 switch (uLevel)
986 {
987 case FI_LVL_STANDARD:
988 case FI_LVL_STANDARD_64:
989 rc = vboxSfOs2SetFileInfo(pFolder, pSfFsi, pSfFsd, uLevel, pbData, cbMinData);
990 break;
991
992 case FI_LVL_STANDARD_EASIZE:
993 rc = ERROR_EAS_NOT_SUPPORTED;
994 break;
995
996 case FI_LVL_STANDARD_EASIZE_64:
997 case FI_LVL_EAS_FROM_LIST:
998 case FI_LVL_EAS_FULL:
999 case FI_LVL_EAS_FULL_5:
1000 case FI_LVL_EAS_FULL_8:
1001 rc = ERROR_INVALID_LEVEL;
1002 break;
1003
1004 default:
1005 AssertFailed();
1006 rc = ERROR_GEN_FAILURE;
1007 break;
1008 }
1009 }
1010 else
1011 {
1012 LogRel(("FS32_FILEINFO: Unknown flags value: %#x\n", fFlags));
1013 rc = ERROR_INVALID_PARAMETER;
1014 }
1015 RT_NOREF_PV(fIoFlags);
1016 return rc;
1017}
1018
1019
1020DECLASM(APIRET)
1021FS32_NEWSIZEL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONGLONG cbFile, ULONG fIoFlags)
1022{
1023 LogFlow(("FS32_NEWSIZEL: pSfFsi=%p pSfFsd=%p cbFile=%RI64 (%#RX64) fIoFlags=%#x\n", pSfFsi, pSfFsd, cbFile, cbFile, fIoFlags));
1024
1025 /*
1026 * Validate input.
1027 */
1028 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1029 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1030 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1031 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1032 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1033 Assert(pFolder->cOpenFiles > 0);
1034 if (cbFile < 0)
1035 {
1036 LogRel(("FS32_NEWSIZEL: Negative size: %RI64\n", cbFile));
1037 return ERROR_INVALID_PARAMETER;
1038 }
1039
1040 /*
1041 * This should only be possible on a file that is writable.
1042 */
1043 APIRET rc;
1044 if ( (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_WRITEONLY
1045 || (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_READWRITE)
1046 {
1047 /*
1048 * Call the host.
1049 */
1050 int vrc = VbglR0SfHostReqSetFileSizeSimple(pFolder->idHostRoot, pSfFsd->hHostFile, cbFile);
1051 if (RT_SUCCESS(vrc))
1052 {
1053 pSfFsi->sfi_sizel = cbFile;
1054 rc = NO_ERROR;
1055 }
1056 else
1057 {
1058 LogRel(("FS32_NEWSIZEL: VbglR0SfFsInfo failed: %Rrc\n", vrc));
1059 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
1060 }
1061 }
1062 else
1063 rc = ERROR_ACCESS_DENIED;
1064
1065 RT_NOREF(fIoFlags);
1066 LogFlow(("FS32_NEWSIZEL: returns %u\n", rc));
1067 return rc;
1068}
1069
1070
1071/**
1072 * Convert KernVMLock page list to HGCM page list.
1073 *
1074 * The trouble is that it combine pages.
1075 */
1076static void vboxSfOs2ConvertPageList(KernPageList_t volatile *paSrc, RTGCPHYS64 volatile *paDst, ULONG cSrc, uint32_t cDst)
1077{
1078 LogFlow(("vboxSfOs2ConvertPageList: %d vs %d\n", cSrc, cDst));
1079
1080 /* If the list have identical length, the job is easy. */
1081 if (cSrc == cDst)
1082 for (uint32_t i = 0; i < cSrc; i++)
1083 paDst[i] &= ~(uint32_t)PAGE_OFFSET_MASK;
1084 else
1085 {
1086 Assert(cSrc <= cDst);
1087 Assert(cSrc > 0);
1088
1089 /*
1090 * We have fewer source entries than destiation pages, so something needs
1091 * expanding. The fact that the first and last pages might be partial ones
1092 * makes this more interesting. We have to do it backwards, of course.
1093 */
1094
1095 /* Deal with the partial page stuff first. */
1096 paSrc[0].Size += paSrc[0].Addr & PAGE_OFFSET_MASK;
1097 paSrc[0].Addr &= ~(ULONG)PAGE_OFFSET_MASK;
1098 paSrc[cSrc - 1].Size = RT_ALIGN_32(paSrc[cSrc - 1].Size, PAGE_SIZE);
1099
1100 /* The go do work on the conversion. */
1101 uint32_t iDst = cDst;
1102 uint32_t iSrc = cSrc;
1103 while (iSrc-- > 0)
1104 {
1105 ULONG cbSrc = paSrc[iSrc].Size;
1106 ULONG uAddrSrc = paSrc[iSrc].Addr + cbSrc;
1107 Assert(!(cbSrc & PAGE_OFFSET_MASK));
1108 Assert(!(uAddrSrc & PAGE_OFFSET_MASK));
1109 while (cbSrc > 0)
1110 {
1111 uAddrSrc -= PAGE_SIZE;
1112 Assert(iDst > 0);
1113 paDst[--iDst] = uAddrSrc;
1114 cbSrc -= PAGE_SIZE;
1115 }
1116 }
1117 Assert(iDst == 0);
1118 }
1119}
1120
1121
1122/**
1123 * Helper for FS32_READ.
1124 *
1125 * @note Must not called if reading beyond the end of the file, as we would give
1126 * sfi_sizel an incorrect value then.
1127 */
1128DECLINLINE(uint32_t) vboxSfOs2ReadFinalize(PSFFSI pSfFsi, uint64_t offRead, uint32_t cbActual)
1129{
1130 pSfFsi->sfi_positionl = offRead + cbActual;
1131 if ((uint64_t)pSfFsi->sfi_sizel < offRead + cbActual)
1132 pSfFsi->sfi_sizel = offRead + cbActual;
1133 pSfFsi->sfi_tstamp |= ST_SREAD | ST_PREAD;
1134 return cbActual;
1135}
1136
1137
1138extern "C" APIRET APIENTRY
1139FS32_READ(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, PVOID pvData, PULONG pcb, ULONG fIoFlags)
1140{
1141 LogFlow(("FS32_READ: pSfFsi=%p pSfFsd=%p pvData=%p pcb=%p:{%#x} fIoFlags=%#x\n", pSfFsi, pSfFsd, pvData, pcb, *pcb, fIoFlags));
1142
1143 /*
1144 * Validate and extract input.
1145 */
1146 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1147 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1148 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1149 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1150 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1151 Assert(pFolder->cOpenFiles > 0);
1152 RT_NOREF(pFolder);
1153
1154 uint64_t const offRead = pSfFsi->sfi_positionl;
1155 uint32_t const cbToRead = *pcb;
1156 uint32_t cbActual = cbToRead;
1157
1158 /*
1159 * We'll try embedded buffers for reads a smaller than ~2KB if we get
1160 * a heap block that's entirely within one page so the host can lock it
1161 * and avoid bouncing it off the heap on completion.
1162 */
1163 if (cbToRead <= _2K)
1164 {
1165 size_t cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + cbToRead;
1166 VBOXSFREADEMBEDDEDREQ *pReq = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
1167 if ( pReq != NULL
1168 && ( PAGE_SIZE - (PAGE_OFFSET_MASK & (uintptr_t)pReq) >= cbReq
1169 || cbToRead == 0))
1170 {
1171 APIRET rc;
1172 int vrc = VbglR0SfHostReqReadEmbedded(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offRead, cbToRead);
1173 if (RT_SUCCESS(vrc))
1174 {
1175 cbActual = pReq->Parms.cb32Read.u.value32;
1176 if (cbActual > 0)
1177 {
1178 AssertStmt(cbActual <= cbToRead, cbActual = cbToRead);
1179 rc = KernCopyOut(pvData, &pReq->abData[0], cbActual);
1180 if (rc == NO_ERROR)
1181 {
1182 *pcb = vboxSfOs2ReadFinalize(pSfFsi, offRead, cbActual);
1183 LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [embedded]\n", cbActual, pSfFsi->sfi_positionl));
1184 }
1185 }
1186 else
1187 {
1188 LogFlow(("FS32_READ: returns; cbActual=0 (EOF); sfi_positionl=%RI64 [embedded]\n", pSfFsi->sfi_positionl));
1189 *pcb = 0;
1190 rc = NO_ERROR;
1191 }
1192 }
1193 else
1194 {
1195 Log(("FS32_READ: VbglR0SfHostReqReadEmbedded(off=%#RU64,cb=%#x) -> %Rrc [embedded]\n", offRead, cbToRead, vrc));
1196 rc = ERROR_BAD_NET_RESP;
1197 }
1198 VbglR0PhysHeapFree(pReq);
1199 return rc;
1200 }
1201 if (pReq)
1202 VbglR0PhysHeapFree(pReq);
1203 }
1204
1205 /*
1206 * Whatever we do now we're going to use a page list request structure.
1207 * So, we do one allocation large enough for both code paths below.
1208 */
1209 uint32_t cPages = ((cbToRead + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
1210 VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cPages]));
1211 if (pReq)
1212 { /* likely */ }
1213 else
1214 {
1215 LogRel(("FS32_READ: Out of memory for page list request (%u pages)\n", cPages));
1216 return ERROR_NOT_ENOUGH_MEMORY;
1217 }
1218
1219 /*
1220 * If the request is less than 16KB or smaller, we try bounce it off the
1221 * physical heap (slab size is 64KB). For requests up to 64KB we try use
1222 * one of a handful of preallocated big buffers rather than the phys heap.
1223 */
1224 if (cbToRead <= _64K)
1225 {
1226 RTGCPHYS GCPhys;
1227 void *pvBuf = NULL;
1228 if (cbToRead <= _16K)
1229 {
1230 pvBuf = VbglR0PhysHeapAlloc(cbToRead);
1231 GCPhys = pvBuf ? VbglR0PhysHeapGetPhysAddr(pvBuf) : NIL_RTGCPHYS;
1232 }
1233 else
1234 pvBuf = vboxSfOs2AllocBigBuffer(&GCPhys);
1235 if (pvBuf)
1236 {
1237 APIRET rc;
1238 int vrc = VbglR0SfHostReqReadContig(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offRead, cbToRead, pvBuf, GCPhys);
1239 if (RT_SUCCESS(vrc))
1240 {
1241 cbActual = pReq->Parms.cb32Read.u.value32;
1242 if (cbActual > 0)
1243 {
1244 AssertStmt(cbActual <= cbToRead, cbActual = cbToRead);
1245 rc = KernCopyOut(pvData, pvBuf, cbActual);
1246 if (rc == NO_ERROR)
1247 {
1248 *pcb = vboxSfOs2ReadFinalize(pSfFsi, offRead, cbActual);
1249 LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [bounced]\n", cbActual, pSfFsi->sfi_positionl));
1250 }
1251 }
1252 else
1253 {
1254 LogFlow(("FS32_READ: returns; cbActual=0 (EOF) sfi_positionl=%RI64 [bounced]\n", pSfFsi->sfi_positionl));
1255 *pcb = 0;
1256 rc = NO_ERROR;
1257 }
1258 }
1259 else
1260 {
1261 Log(("FS32_READ: VbglR0SfHostReqReadEmbedded(off=%#RU64,cb=%#x) -> %Rrc [bounced]\n", offRead, cbToRead, vrc));
1262 rc = ERROR_BAD_NET_RESP;
1263 }
1264
1265 if (cbToRead <= _16K)
1266 VbglR0PhysHeapFree(pvBuf);
1267 else
1268 vboxSfOs2FreeBigBuffer(pvBuf);
1269 VbglR0PhysHeapFree(pReq);
1270 return rc;
1271 }
1272 }
1273
1274 /*
1275 * We couldn't use a bounce buffer for it, so lock the buffer pages.
1276 */
1277 KernVMLock_t Lock;
1278 ULONG cPagesRet;
1279 AssertCompile(sizeof(KernPageList_t) == sizeof(pReq->PgLst.aPages[0]));
1280 APIRET rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, (void *)pvData, cbToRead, &Lock,
1281 (KernPageList_t *)&pReq->PgLst.aPages[0], &cPagesRet);
1282 if (rc == NO_ERROR)
1283 {
1284 pReq->PgLst.offFirstPage = (uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK;
1285 cPages = (cbToRead + ((uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
1286 vboxSfOs2ConvertPageList((KernPageList_t volatile *)&pReq->PgLst.aPages[0], &pReq->PgLst.aPages[0], cPagesRet, cPages);
1287
1288 int vrc = VbglR0SfHostReqReadPgLst(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offRead, cbToRead, cPages);
1289 if (RT_SUCCESS(vrc))
1290 {
1291 cbActual = pReq->Parms.cb32Read.u.value32;
1292 if (cbActual > 0)
1293 {
1294 AssertStmt(cbActual <= cbToRead, cbActual = cbToRead);
1295 *pcb = vboxSfOs2ReadFinalize(pSfFsi, offRead, cbActual);
1296 LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [locked]\n", cbActual, pSfFsi->sfi_positionl));
1297 }
1298 else
1299 {
1300 LogFlow(("FS32_READ: returns; cbActual=0 (EOF) sfi_positionl=%RI64 [locked]\n", pSfFsi->sfi_positionl));
1301 *pcb = 0;
1302 rc = NO_ERROR;
1303 }
1304 }
1305 else
1306 {
1307 Log(("FS32_READ: VbglR0SfHostReqReadEmbedded(off=%#RU64,cb=%#x) -> %Rrc [locked]\n", offRead, cbToRead, vrc));
1308 rc = ERROR_BAD_NET_RESP;
1309 }
1310
1311 KernVMUnlock(&Lock);
1312 }
1313 else
1314 Log(("FS32_READ: KernVMLock(,%p,%#x,) failed -> %u\n", pvData, cbToRead, rc));
1315 VbglR0PhysHeapFree(pReq);
1316 RT_NOREF_PV(fIoFlags);
1317 return rc;
1318}
1319
1320
1321/**
1322 * Helper for FS32_WRITE.
1323 */
1324DECLINLINE(uint32_t) vboxSfOs2WriteFinalize(PSFFSI pSfFsi, uint64_t offWrite, uint32_t cbActual)
1325{
1326 pSfFsi->sfi_positionl = offWrite + cbActual;
1327 if ((uint64_t)pSfFsi->sfi_sizel < offWrite + cbActual)
1328 pSfFsi->sfi_sizel = offWrite + cbActual;
1329 pSfFsi->sfi_tstamp |= ST_SWRITE | ST_PWRITE;
1330 return cbActual;
1331}
1332
1333
1334extern "C" APIRET APIENTRY
1335FS32_WRITE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, void const *pvData, PULONG pcb, ULONG fIoFlags)
1336{
1337 /*
1338 * Validate and extract input.
1339 */
1340 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1341 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1342 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1343 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1344 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1345 Assert(pFolder->cOpenFiles > 0);
1346 RT_NOREF(pFolder);
1347
1348 uint64_t offWrite = pSfFsi->sfi_positionl;
1349 uint32_t cbToWrite = *pcb;
1350 uint32_t cbActual = cbToWrite;
1351
1352 /*
1353 * We'll try embedded buffers for writes a smaller than ~2KB if we get
1354 * a heap block that's entirely within one page so the host can lock it
1355 * and avoid bouncing it off the heap on completion.
1356 */
1357 if (cbToWrite <= _2K)
1358 {
1359 size_t cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + cbToWrite;
1360 VBOXSFWRITEEMBEDDEDREQ *pReq = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
1361 if ( pReq != NULL
1362 && ( PAGE_SIZE - (PAGE_OFFSET_MASK & (uintptr_t)pReq) >= cbReq
1363 || cbToWrite == 0))
1364 {
1365 APIRET rc = KernCopyIn(&pReq->abData[0], pvData, cbToWrite);
1366 if (rc == NO_ERROR)
1367 {
1368 int vrc = VbglR0SfHostReqWriteEmbedded(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offWrite, cbToWrite);
1369 if (RT_SUCCESS(vrc))
1370 {
1371 cbActual = pReq->Parms.cb32Write.u.value32;
1372 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1373 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1374 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [embedded]\n", cbActual, pSfFsi->sfi_positionl));
1375 }
1376 else
1377 {
1378 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [embedded]\n", offWrite, cbToWrite, vrc));
1379 rc = ERROR_BAD_NET_RESP;
1380 }
1381 }
1382 VbglR0PhysHeapFree(pReq);
1383 return rc;
1384 }
1385 if (pReq)
1386 VbglR0PhysHeapFree(pReq);
1387 }
1388
1389 /*
1390 * Whatever we do now we're going to use a page list request structure.
1391 * So, we do one allocation large enough for both code paths below.
1392 */
1393 uint32_t cPages = ((cbToWrite + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
1394 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cPages]));
1395 if (pReq)
1396 { /* likely */ }
1397 else
1398 {
1399 LogRel(("FS32_WRITE: Out of memory for page list request (%u pages)\n", cPages));
1400 return ERROR_NOT_ENOUGH_MEMORY;
1401 }
1402
1403 /*
1404 * If the request is less than 16KB or smaller, we try bounce it off the
1405 * physical heap (slab size is 64KB). For requests up to 64KB we try use
1406 * one of a handful of preallocated big buffers rather than the phys heap.
1407 */
1408 if (cbToWrite <= _64K)
1409 {
1410 RTGCPHYS GCPhys;
1411 void *pvBuf = NULL;
1412 if (cbToWrite <= _16K)
1413 {
1414 pvBuf = VbglR0PhysHeapAlloc(cbToWrite);
1415 GCPhys = pvBuf ? VbglR0PhysHeapGetPhysAddr(pvBuf) : NIL_RTGCPHYS;
1416 }
1417 else
1418 pvBuf = vboxSfOs2AllocBigBuffer(&GCPhys);
1419 if (pvBuf)
1420 {
1421 APIRET rc = KernCopyIn(pvBuf, pvData, cbToWrite);
1422 if (rc == NO_ERROR)
1423 {
1424 int vrc = VbglR0SfHostReqWriteContig(pFolder->idHostRoot, pReq, pSfFsd->hHostFile,
1425 offWrite, cbToWrite, pvBuf, GCPhys);
1426 if (RT_SUCCESS(vrc))
1427 {
1428 cbActual = pReq->Parms.cb32Write.u.value32;
1429 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1430 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1431 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [bounced]\n", cbActual, pSfFsi->sfi_positionl));
1432 }
1433 else
1434 {
1435 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [bounced]\n", offWrite, cbToWrite, vrc));
1436 rc = ERROR_BAD_NET_RESP;
1437 }
1438 }
1439
1440 if (cbToWrite <= _16K)
1441 VbglR0PhysHeapFree(pvBuf);
1442 else
1443 vboxSfOs2FreeBigBuffer(pvBuf);
1444 VbglR0PhysHeapFree(pReq);
1445 return rc;
1446 }
1447 }
1448
1449 /*
1450 * We couldn't use a bounce buffer for it, so lock the buffer pages.
1451 */
1452 KernVMLock_t Lock;
1453 ULONG cPagesRet;
1454 AssertCompile(sizeof(KernPageList_t) == sizeof(pReq->PgLst.aPages[0]));
1455 APIRET rc = KernVMLock(VMDHL_LONG, (void *)pvData, cbToWrite, &Lock, (KernPageList_t *)&pReq->PgLst.aPages[0], &cPagesRet);
1456 if (rc == NO_ERROR)
1457 {
1458 pReq->PgLst.offFirstPage = (uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK;
1459 cPages = (cbToWrite + ((uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
1460 vboxSfOs2ConvertPageList((KernPageList_t volatile *)&pReq->PgLst.aPages[0], &pReq->PgLst.aPages[0], cPagesRet, cPages);
1461
1462 int vrc = VbglR0SfHostReqWritePgLst(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offWrite, cbToWrite, cPages);
1463 if (RT_SUCCESS(vrc))
1464 {
1465 cbActual = pReq->Parms.cb32Write.u.value32;
1466 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1467 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1468 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [locked]\n", cbActual, pSfFsi->sfi_positionl));
1469 }
1470 else
1471 {
1472 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [locked]\n", offWrite, cbToWrite, vrc));
1473 rc = ERROR_BAD_NET_RESP;
1474 }
1475
1476 KernVMUnlock(&Lock);
1477 }
1478 else
1479 Log(("FS32_WRITE: KernVMLock(,%p,%#x,) failed -> %u\n", pvData, cbToWrite, rc));
1480 VbglR0PhysHeapFree(pReq);
1481 RT_NOREF_PV(fIoFlags);
1482 return rc;
1483}
1484
1485
1486extern "C" APIRET APIENTRY
1487FS32_READFILEATCACHE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fIoFlags, LONGLONG off, ULONG pcb, KernCacheList_t **ppCacheList)
1488{
1489 /*
1490 * Validate input.
1491 */
1492 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1493 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1494 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1495 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1496 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1497 Assert(pFolder->cOpenFiles > 0);
1498 RT_NOREF(pFolder);
1499
1500 /* I think this is used for sendfile(). */
1501
1502 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fIoFlags); NOREF(off); NOREF(pcb); NOREF(ppCacheList);
1503 return ERROR_NOT_SUPPORTED;
1504}
1505
1506
1507extern "C" APIRET APIENTRY
1508FS32_RETURNFILECACHE(KernCacheList_t *pCacheList)
1509{
1510 NOREF(pCacheList);
1511 return ERROR_NOT_SUPPORTED;
1512}
1513
1514
1515/* oddments */
1516
1517DECLASM(APIRET)
1518FS32_CANCELLOCKREQUESTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pLockRange)
1519{
1520 /*
1521 * Validate input.
1522 */
1523 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1524 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1525 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1526 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1527 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1528 Assert(pFolder->cOpenFiles > 0);
1529 RT_NOREF(pFolder);
1530
1531 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
1532 return ERROR_NOT_SUPPORTED;
1533}
1534
1535
1536DECLASM(APIRET)
1537FS32_CANCELLOCKREQUEST(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pLockRange)
1538{
1539 /*
1540 * Validate input.
1541 */
1542 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1543 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1544 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1545 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1546 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1547 Assert(pFolder->cOpenFiles > 0);
1548 RT_NOREF(pFolder);
1549
1550 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
1551 return ERROR_NOT_SUPPORTED;
1552}
1553
1554
1555DECLASM(APIRET)
1556FS32_FILELOCKSL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pUnLockRange,
1557 struct filelockl *pLockRange, ULONG cMsTimeout, ULONG fFlags)
1558{
1559 /*
1560 * Validate input.
1561 */
1562 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1563 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1564 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1565 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1566 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1567 Assert(pFolder->cOpenFiles > 0);
1568 RT_NOREF(pFolder);
1569
1570 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
1571 return ERROR_NOT_SUPPORTED;
1572}
1573
1574
1575DECLASM(APIRET)
1576FS32_FILELOCKS(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pUnLockRange,
1577 struct filelock *pLockRange, ULONG cMsTimeout, ULONG fFlags)
1578{
1579 /*
1580 * Validate input.
1581 */
1582 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1583 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1584 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1585 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1586 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1587 Assert(pFolder->cOpenFiles > 0);
1588 RT_NOREF(pFolder);
1589
1590 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
1591 return ERROR_NOT_SUPPORTED;
1592}
1593
1594
1595DECLASM(APIRET)
1596FS32_IOCTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uCategory, USHORT uFunction,
1597 PVOID pvParm, USHORT cbParm, PUSHORT pcbParmIO,
1598 PVOID pvData, USHORT cbData, PUSHORT pcbDataIO)
1599{
1600 /*
1601 * Validate input.
1602 */
1603 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1604 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1605 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1606 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1607 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1608 Assert(pFolder->cOpenFiles > 0);
1609 RT_NOREF(pFolder);
1610
1611 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uCategory); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
1612 NOREF(pvData); NOREF(cbData); NOREF(pcbDataIO);
1613 return ERROR_NOT_SUPPORTED;
1614}
1615
1616
1617DECLASM(APIRET)
1618FS32_FILEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, PBYTE pbCmdList, USHORT cbCmdList,
1619 PUSHORT poffError, USHORT fIoFlag)
1620{
1621 /*
1622 * Validate input.
1623 */
1624 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1625 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1626 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1627 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1628 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1629 Assert(pFolder->cOpenFiles > 0);
1630 RT_NOREF(pFolder);
1631
1632 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pbCmdList); NOREF(cbCmdList); NOREF(poffError); NOREF(fIoFlag);
1633 return ERROR_NOT_SUPPORTED;
1634}
1635
1636
1637DECLASM(APIRET)
1638FS32_NMPIPE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uOpType, union npoper *pOpRec,
1639 PBYTE pbData, PCSZ pszName)
1640{
1641 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uOpType); NOREF(pOpRec); NOREF(pbData); NOREF(pszName);
1642 return ERROR_NOT_SUPPORTED;
1643}
1644
1645
1646DECLASM(APIRET)
1647FS32_OPENPAGEFILE(PULONG pfFlags, PULONG pcMaxReq, PCSZ pszName, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd,
1648 USHORT fOpenMode, USHORT fOpenFlags, USHORT fAttr, ULONG uReserved)
1649{
1650 NOREF(pfFlags); NOREF(pcMaxReq); NOREF(pszName); NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fOpenMode); NOREF(fOpenFlags);
1651 NOREF(fAttr); NOREF(uReserved);
1652 return ERROR_NOT_SUPPORTED;
1653}
1654
1655
1656DECLASM(APIRET)
1657FS32_SETSWAP(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
1658{
1659 NOREF(pSfFsi); NOREF(pSfFsd);
1660 return ERROR_NOT_SUPPORTED;
1661}
1662
1663
1664DECLASM(APIRET)
1665FS32_ALLOCATEPAGESPACE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG cb, USHORT cbWantContig)
1666{
1667 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(cb); NOREF(cbWantContig);
1668 return ERROR_NOT_SUPPORTED;
1669}
1670
1671
1672DECLASM(APIRET)
1673FS32_DOPAGEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct PageCmdHeader *pList)
1674{
1675 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pList);
1676 return ERROR_NOT_SUPPORTED;
1677}
1678
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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