VirtualBox

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

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

SharedFolders,os2/VBoxSF: Continued hacking on replacements for VbglR0SfXxxx using OS/2 as testbed. Some simple read+write optimizations. bugref:9172

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