VirtualBox

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

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

err.h build fixes. bugref:9344

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

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