VirtualBox

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

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

os2/VBoxSF,Vbgl: Promoted the fast host request wrappers to generic status. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 62.0 KB
Line 
1/** $Id: VBoxSFFile.cpp 76716 2019-01-08 23:36:02Z vboxsync $ */
2/** @file
3 * VBoxSF - OS/2 Shared Folders, the file level IFS EPs.
4 */
5
6/*
7 * Copyright (c) 2007-2018 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#define LOG_GROUP LOG_GROUP_DEFAULT
36#include "VBoxSFInternal.h"
37
38#include <VBox/log.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/err.h>
42#include <iprt/mem.h>
43
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48/** A preallocated buffer. */
49typedef struct
50{
51 RTCCPHYS PhysAddr;
52 void *pvBuf;
53 bool volatile fBusy;
54} VBOXSFOS2BUF;
55
56
57/*********************************************************************************************************************************
58* Global Variables *
59*********************************************************************************************************************************/
60/** Buffer spinlock. */
61static SpinLock_t g_BufferLock;
62/** 64KB buffers. */
63static VBOXSFOS2BUF g_aBigBuffers[4];
64
65
66
67/**
68 * Initialize file buffers.
69 */
70void vboxSfOs2InitFileBuffers(void)
71{
72 KernAllocSpinLock(&g_BufferLock);
73
74 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
75 {
76 g_aBigBuffers[i].pvBuf = RTMemContAlloc(&g_aBigBuffers[i].PhysAddr, _64K);
77 g_aBigBuffers[i].fBusy = g_aBigBuffers[i].pvBuf == NULL;
78 }
79}
80
81
82/**
83 * Allocates a big buffer.
84 * @returns Pointer to buffer on success, NULL on failure.
85 * @param pPhysAddr The physical address of the buffer.
86 */
87DECLINLINE(void *) vboxSfOs2AllocBigBuffer(RTGCPHYS *pPhysAddr)
88{
89 KernAcquireSpinLock(&g_BufferLock);
90 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
91 if (!g_aBigBuffers[i].fBusy)
92 {
93 g_aBigBuffers[i].fBusy = true;
94 KernReleaseSpinLock(&g_BufferLock);
95
96 *pPhysAddr = g_aBigBuffers[i].PhysAddr;
97 return g_aBigBuffers[i].pvBuf;
98 }
99 KernReleaseSpinLock(&g_BufferLock);
100 *pPhysAddr = NIL_RTGCPHYS;
101 return NULL;
102}
103
104
105/**
106 * Frees a big buffer.
107 * @param pvBuf The address of the buffer to be freed.
108 */
109DECLINLINE(void) vboxSfOs2FreeBigBuffer(void *pvBuf)
110{
111 Assert(pvBuf);
112 KernAcquireSpinLock(&g_BufferLock);
113 for (uint32_t i = 0; i < RT_ELEMENTS(g_aBigBuffers); i++)
114 if (g_aBigBuffers[i].pvBuf == pvBuf)
115 {
116 Assert(g_aBigBuffers[i].fBusy);
117 g_aBigBuffers[i].fBusy = false;
118 KernReleaseSpinLock(&g_BufferLock);
119 return;
120 }
121 KernReleaseSpinLock(&g_BufferLock);
122 AssertFailed();
123}
124
125
126
127DECLASM(APIRET)
128FS32_OPENCREATE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszName, LONG offCurDirEnd,
129 PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fOpenMode, USHORT fOpenFlags,
130 PUSHORT puAction, ULONG fAttribs, BYTE const *pbEaBuf, PUSHORT pfGenFlag)
131{
132 LogFlow(("FS32_OPENCREATE: pCdFsi=%p pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pSfFsi=%p pSfFsd=%p fOpenMode=%#x fOpenFlags=%#x puAction=%p fAttribs=%#x pbEaBuf=%p pfGenFlag=%p\n",
133 pCdFsi, pCdFsd, pszName, pszName, offCurDirEnd, pSfFsi, pSfFsd, fOpenMode, fOpenFlags, puAction, fAttribs, pbEaBuf, pfGenFlag));
134 RT_NOREF(pfGenFlag, pCdFsi);
135
136 /*
137 * Validate and convert parameters.
138 */
139 /* No EAs. */
140 if (!pbEaBuf)
141 { /* likely */ }
142 else
143 {
144 LogRel(("FS32_OPENCREATE: Returns ERROR_EAS_NOT_SUPPORTED [%p];\n", pbEaBuf));
145 return ERROR_EAS_NOT_SUPPORTED;
146 }
147
148 /* No direct access. */
149 if (!(fOpenMode & OPEN_FLAGS_DASD))
150 { /* likely */ }
151 else
152 {
153 LogRel(("FS32_OPENCREATE: Returns ERROR_ACCESS_DENIED [DASD];\n"));
154 return ERROR_ACCESS_DENIED;
155 }
156
157 /*
158 * Allocate request buffer and resovle the path to folder and folder relative path.
159 */
160 PVBOXSFFOLDER pFolder;
161 VBOXSFCREATEREQ *pReq;
162 APIRET rc = vboxSfOs2ResolvePathEx(pszName, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
163 &pFolder, (void **)&pReq);
164 LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
165 if (rc == NO_ERROR)
166 { /* likely */ }
167 else
168 return rc;
169
170 /*
171 * Continue validating and converting parameters.
172 */
173 /* access: */
174 if (fOpenMode & OPEN_ACCESS_READWRITE)
175 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
176 else if (fOpenMode & OPEN_ACCESS_WRITEONLY)
177 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_WRITE | SHFL_CF_ACCESS_ATTR_WRITE;
178 else
179 pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
180
181 /* Sharing: */
182 switch (fOpenMode & (OPEN_SHARE_DENYNONE | OPEN_SHARE_DENYREADWRITE | OPEN_SHARE_DENYREAD | OPEN_SHARE_DENYWRITE))
183 {
184 case OPEN_SHARE_DENYNONE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
185 case OPEN_SHARE_DENYWRITE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
186 case OPEN_SHARE_DENYREAD: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
187 case OPEN_SHARE_DENYREADWRITE: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
188 case 0: pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
189 default:
190 LogRel(("FS32_OPENCREATE: Invalid file sharing mode: %#x\n", fOpenMode));
191 VbglR0PhysHeapFree(pReq);
192 return VERR_INVALID_PARAMETER;
193
194 }
195
196 /* How to open the file: */
197 switch (fOpenFlags & 0x13)
198 {
199 case OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x00 */
200 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
201 break;
202 case OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x10 */
203 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
204 break;
205 case OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x01 */
206 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
207 break;
208 case OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x11 */
209 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
210 break;
211 case OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW: /* 0x02 */
212 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
213 break;
214 case OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
215 pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
216 break;
217 default:
218 LogRel(("FS32_OPENCREATE: Invalid file open flags: %#x\n", fOpenFlags));
219 VbglR0PhysHeapFree(pReq);
220 return VERR_INVALID_PARAMETER;
221 }
222
223 /* Misc: cache, etc? There seems to be no API for that. */
224
225 /* Attributes: */
226 pReq->CreateParms.Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
227
228 /* Initial size: */
229 if (pSfFsi->sfi_sizel > 0)
230 pReq->CreateParms.Info.cbObject = pSfFsi->sfi_sizel;
231
232 /*
233 * Try open the file.
234 */
235 int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
236 LogFlow(("FS32_OPENCREATE: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
237 vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
238 if (RT_SUCCESS(vrc))
239 {
240 switch (pReq->CreateParms.Result)
241 {
242 case SHFL_FILE_EXISTS:
243 if (pReq->CreateParms.Handle == SHFL_HANDLE_NIL)
244 {
245 rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
246 break;
247 }
248 RT_FALL_THRU();
249 case SHFL_FILE_CREATED:
250 case SHFL_FILE_REPLACED:
251 if ( pReq->CreateParms.Info.cbObject < _2G
252 || (fOpenMode & OPEN_FLAGS_LARGEFILE))
253 {
254 pSfFsd->u32Magic = VBOXSFSYFI_MAGIC;
255 pSfFsd->pSelf = pSfFsd;
256 pSfFsd->hHostFile = pReq->CreateParms.Handle;
257 pSfFsd->pFolder = pFolder;
258
259 uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
260 Assert(cOpenFiles < _32K);
261 pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
262
263 pSfFsi->sfi_sizel = pReq->CreateParms.Info.cbObject;
264 pSfFsi->sfi_type = STYPE_FILE;
265 pSfFsi->sfi_DOSattr = (uint8_t)((pReq->CreateParms.Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
266 int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
267 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->CreateParms.Info.BirthTime, cMinLocalTimeDelta);
268 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->CreateParms.Info.AccessTime, cMinLocalTimeDelta);
269 vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->CreateParms.Info.ModificationTime, cMinLocalTimeDelta);
270 if (pReq->CreateParms.Result == SHFL_FILE_CREATED)
271 pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
272
273 *puAction = pReq->CreateParms.Result == SHFL_FILE_CREATED ? FILE_CREATED
274 : pReq->CreateParms.Result == SHFL_FILE_EXISTS ? FILE_EXISTED
275 : FILE_TRUNCATED;
276
277 Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
278 rc = NO_ERROR;
279 }
280 else
281 {
282 LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pReq->CreateParms.Info.cbObject, pszName));
283 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
284 VbglR0SfHostReqClose(pFolder->idHostRoot, (VBOXSFCLOSEREQ *)pReq, pReq->CreateParms.Handle);
285 rc = ERROR_ACCESS_DENIED;
286 }
287 break;
288
289 case SHFL_PATH_NOT_FOUND:
290 rc = ERROR_PATH_NOT_FOUND;
291 break;
292
293 default:
294 case SHFL_FILE_NOT_FOUND:
295 rc = ERROR_OPEN_FAILED;
296 break;
297 }
298 }
299 else if (vrc == VERR_ALREADY_EXISTS)
300 rc = ERROR_ACCESS_DENIED;
301 else if (vrc == VERR_FILE_NOT_FOUND)
302 rc = ERROR_OPEN_FAILED;
303 else
304 rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
305 VbglR0PhysHeapFree(pReq);
306 vboxSfOs2ReleaseFolder(pFolder);
307 LogFlow(("FS32_OPENCREATE: returns %u\n", rc));
308 return rc;
309}
310
311
312DECLASM(APIRET)
313FS32_CLOSE(ULONG uType, ULONG fIoFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
314{
315 LogFlow(("FS32_CLOSE: uType=%#x fIoFlags=%#x pSfFsi=%p pSfFsd=%p:{%#x}\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 = VbglR0SfHostReqCloseSimple(pFolder->idHostRoot, 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 = VbglR0SfHostReqFlushSimple(pFolder->idHostRoot, pSfFsd->hHostFile);
377 if (RT_FAILURE(vrc))
378 {
379 LogRel(("FS32_COMMIT: VbglR0SfHostReqFlushSimple 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 = VbglR0SfHostReqQueryObjInfo(pFolder->idHostRoot, 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->idHostRoot;
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 = VbglR0SfHostReqQueryObjInfo(pFolder->idHostRoot, 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: VbglR0SfHostReqQueryObjInfo 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 = VbglR0SfHostReqSetFileSizeSimple(pFolder->idHostRoot, 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 = VbglR0SfHostReqReadEmbedded(pFolder->idHostRoot, 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: VbglR0SfHostReqReadEmbedded(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 structure.
1194 * So, we do one allocation large enough for both code paths below.
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 APIRET rc;
1225 int vrc = VbglR0SfHostReqReadContig(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offRead, cbToRead, pvBuf, GCPhys);
1226 if (RT_SUCCESS(vrc))
1227 {
1228 cbActual = pReq->Parms.cb32Read.u.value32;
1229 AssertStmt(cbActual <= cbToRead, cbActual = cbToRead);
1230 rc = KernCopyOut(pvData, pvBuf, cbActual);
1231 if (rc == NO_ERROR)
1232 {
1233 *pcb = vboxSfOs2ReadFinalize(pSfFsi, offRead, cbActual);
1234 LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [bounced]\n", cbActual, pSfFsi->sfi_positionl));
1235 }
1236 }
1237 else
1238 {
1239 Log(("FS32_READ: VbglR0SfHostReqReadEmbedded(off=%#RU64,cb=%#x) -> %Rrc [bounced]\n", offRead, cbToRead, vrc));
1240 rc = ERROR_BAD_NET_RESP;
1241 }
1242
1243 if (cbToRead <= _16K)
1244 VbglR0PhysHeapFree(pvBuf);
1245 else
1246 vboxSfOs2FreeBigBuffer(pvBuf);
1247 VbglR0PhysHeapFree(pReq);
1248 return rc;
1249 }
1250 }
1251
1252 /*
1253 * We couldn't use a bounce buffer for it, so lock the buffer pages.
1254 */
1255 KernVMLock_t Lock;
1256 ULONG cPagesRet;
1257 AssertCompile(sizeof(KernPageList_t) == sizeof(pReq->PgLst.aPages[0]));
1258 APIRET rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, (void *)pvData, cbToRead, &Lock,
1259 (KernPageList_t *)&pReq->PgLst.aPages[0], &cPagesRet);
1260 if (rc == NO_ERROR)
1261 {
1262 pReq->PgLst.offFirstPage = (uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK;
1263 cPages = (cbToRead + ((uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
1264 vboxSfOs2ConvertPageList((KernPageList_t volatile *)&pReq->PgLst.aPages[0], &pReq->PgLst.aPages[0], cPagesRet, cPages);
1265
1266 APIRET rc;
1267 int vrc = VbglR0SfHostReqReadPgLst(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offRead, cbToRead, cPages);
1268 if (RT_SUCCESS(vrc))
1269 {
1270 cbActual = pReq->Parms.cb32Read.u.value32;
1271 AssertStmt(cbActual <= cbToRead, cbActual = cbToRead);
1272 *pcb = vboxSfOs2ReadFinalize(pSfFsi, offRead, cbActual);
1273 LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [locked]\n", cbActual, pSfFsi->sfi_positionl));
1274 }
1275 else
1276 {
1277 Log(("FS32_READ: VbglR0SfHostReqReadEmbedded(off=%#RU64,cb=%#x) -> %Rrc [locked]\n", offRead, cbToRead, vrc));
1278 rc = ERROR_BAD_NET_RESP;
1279 }
1280
1281 KernVMUnlock(&Lock);
1282 }
1283 else
1284 Log(("FS32_READ: KernVMLock(,%p,%#x,) failed -> %u\n", pvData, cbToRead, rc));
1285 VbglR0PhysHeapFree(pReq);
1286 RT_NOREF_PV(fIoFlags);
1287 return rc;
1288}
1289
1290
1291/**
1292 * Helper for FS32_WRITE.
1293 */
1294DECLINLINE(uint32_t) vboxSfOs2WriteFinalize(PSFFSI pSfFsi, uint64_t offWrite, uint32_t cbActual)
1295{
1296 pSfFsi->sfi_positionl = offWrite + cbActual;
1297 if ((uint64_t)pSfFsi->sfi_sizel < offWrite + cbActual)
1298 pSfFsi->sfi_sizel = offWrite + cbActual;
1299 pSfFsi->sfi_tstamp |= ST_SWRITE | ST_PWRITE;
1300 return cbActual;
1301}
1302
1303
1304extern "C" APIRET APIENTRY
1305FS32_WRITE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, void const *pvData, PULONG pcb, ULONG fIoFlags)
1306{
1307 /*
1308 * Validate and extract input.
1309 */
1310 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1311 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1312 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1313 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1314 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1315 Assert(pFolder->cOpenFiles > 0);
1316 RT_NOREF(pFolder);
1317
1318 uint64_t offWrite = pSfFsi->sfi_positionl;
1319 uint32_t cbToWrite = *pcb;
1320 uint32_t cbActual = cbToWrite;
1321
1322 /*
1323 * We'll try embedded buffers for writes a smaller than ~2KB if we get
1324 * a heap block that's entirely within one page so the host can lock it
1325 * and avoid bouncing it off the heap on completion.
1326 */
1327 if (cbToWrite <= _2K)
1328 {
1329 size_t cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + cbToWrite;
1330 VBOXSFWRITEEMBEDDEDREQ *pReq = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
1331 if ( pReq != NULL
1332 && ( PAGE_SIZE - (PAGE_OFFSET_MASK & (uintptr_t)pReq) >= cbReq
1333 || cbToWrite == 0))
1334 {
1335 APIRET rc = KernCopyIn(&pReq->abData[0], pvData, cbToWrite);
1336 if (rc == NO_ERROR)
1337 {
1338 int vrc = VbglR0SfHostReqWriteEmbedded(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offWrite, cbToWrite);
1339 if (RT_SUCCESS(vrc))
1340 {
1341 cbActual = pReq->Parms.cb32Write.u.value32;
1342 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1343 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1344 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [embedded]\n", cbActual, pSfFsi->sfi_positionl));
1345 }
1346 else
1347 {
1348 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [embedded]\n", offWrite, cbToWrite, vrc));
1349 rc = ERROR_BAD_NET_RESP;
1350 }
1351 }
1352 VbglR0PhysHeapFree(pReq);
1353 return rc;
1354 }
1355 if (pReq)
1356 VbglR0PhysHeapFree(pReq);
1357 }
1358
1359 /*
1360 * Whatever we do now we're going to use a page list request structure.
1361 * So, we do one allocation large enough for both code paths below.
1362 */
1363 uint32_t cPages = ((cbToWrite + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
1364 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cPages]));
1365 if (pReq)
1366 { /* likely */ }
1367 else
1368 {
1369 LogRel(("FS32_WRITE: Out of memory for page list request (%u pages)\n", cPages));
1370 return ERROR_NOT_ENOUGH_MEMORY;
1371 }
1372
1373 /*
1374 * If the request is less than 16KB or smaller, we try bounce it off the
1375 * physical heap (slab size is 64KB). For requests up to 64KB we try use
1376 * one of a handful of preallocated big buffers rather than the phys heap.
1377 */
1378 if (cbToWrite <= _64K)
1379 {
1380 RTGCPHYS GCPhys;
1381 void *pvBuf = NULL;
1382 if (cbToWrite <= _16K)
1383 {
1384 pvBuf = VbglR0PhysHeapAlloc(cbToWrite);
1385 GCPhys = pvBuf ? VbglR0PhysHeapGetPhysAddr(pvBuf) : NIL_RTGCPHYS;
1386 }
1387 else
1388 pvBuf = vboxSfOs2AllocBigBuffer(&GCPhys);
1389 if (pvBuf)
1390 {
1391 APIRET rc = KernCopyIn(pvBuf, pvData, cbToWrite);
1392 if (rc == NO_ERROR)
1393 {
1394 APIRET rc;
1395 int vrc = VbglR0SfHostReqWriteContig(pFolder->idHostRoot, pReq, pSfFsd->hHostFile,
1396 offWrite, cbToWrite, pvBuf, GCPhys);
1397 if (RT_SUCCESS(vrc))
1398 {
1399 cbActual = pReq->Parms.cb32Write.u.value32;
1400 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1401 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1402 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [bounced]\n", cbActual, pSfFsi->sfi_positionl));
1403 }
1404 else
1405 {
1406 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [bounced]\n", offWrite, cbToWrite, vrc));
1407 rc = ERROR_BAD_NET_RESP;
1408 }
1409 }
1410
1411 if (cbToWrite <= _16K)
1412 VbglR0PhysHeapFree(pvBuf);
1413 else
1414 vboxSfOs2FreeBigBuffer(pvBuf);
1415 VbglR0PhysHeapFree(pReq);
1416 return rc;
1417 }
1418 }
1419
1420 /*
1421 * We couldn't use a bounce buffer for it, so lock the buffer pages.
1422 */
1423 KernVMLock_t Lock;
1424 ULONG cPagesRet;
1425 AssertCompile(sizeof(KernPageList_t) == sizeof(pReq->PgLst.aPages[0]));
1426 APIRET rc = KernVMLock(VMDHL_LONG, (void *)pvData, cbToWrite, &Lock, (KernPageList_t *)&pReq->PgLst.aPages[0], &cPagesRet);
1427 if (rc == NO_ERROR)
1428 {
1429 pReq->PgLst.offFirstPage = (uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK;
1430 cPages = (cbToWrite + ((uint16_t)(uintptr_t)pvData & (uint16_t)PAGE_OFFSET_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
1431 vboxSfOs2ConvertPageList((KernPageList_t volatile *)&pReq->PgLst.aPages[0], &pReq->PgLst.aPages[0], cPagesRet, cPages);
1432
1433 APIRET rc;
1434 int vrc = VbglR0SfHostReqWritePgLst(pFolder->idHostRoot, pReq, pSfFsd->hHostFile, offWrite, cbToWrite, cPages);
1435 if (RT_SUCCESS(vrc))
1436 {
1437 cbActual = pReq->Parms.cb32Write.u.value32;
1438 AssertStmt(cbActual <= cbToWrite, cbActual = cbToWrite);
1439 *pcb = vboxSfOs2WriteFinalize(pSfFsi, offWrite, cbActual);
1440 LogFlow(("FS32_WRITE: returns; cbActual=%#x sfi_positionl=%RI64 [locked]\n", cbActual, pSfFsi->sfi_positionl));
1441 }
1442 else
1443 {
1444 Log(("FS32_WRITE: VbglR0SfHostReqWriteEmbedded(off=%#RU64,cb=%#x) -> %Rrc [locked]\n", offWrite, cbToWrite, vrc));
1445 rc = ERROR_BAD_NET_RESP;
1446 }
1447
1448 KernVMUnlock(&Lock);
1449 }
1450 else
1451 Log(("FS32_WRITE: KernVMLock(,%p,%#x,) failed -> %u\n", pvData, cbToWrite, rc));
1452 VbglR0PhysHeapFree(pReq);
1453 RT_NOREF_PV(fIoFlags);
1454 return rc;
1455}
1456
1457
1458extern "C" APIRET APIENTRY
1459FS32_READFILEATCACHE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fIoFlags, LONGLONG off, ULONG pcb, KernCacheList_t **ppCacheList)
1460{
1461 /*
1462 * Validate input.
1463 */
1464 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1465 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1466 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1467 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1468 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1469 Assert(pFolder->cOpenFiles > 0);
1470 RT_NOREF(pFolder);
1471
1472 /* I think this is used for sendfile(). */
1473
1474 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fIoFlags); NOREF(off); NOREF(pcb); NOREF(ppCacheList);
1475 return ERROR_NOT_SUPPORTED;
1476}
1477
1478
1479extern "C" APIRET APIENTRY
1480FS32_RETURNFILECACHE(KernCacheList_t *pCacheList)
1481{
1482 NOREF(pCacheList);
1483 return ERROR_NOT_SUPPORTED;
1484}
1485
1486
1487/* oddments */
1488
1489DECLASM(APIRET)
1490FS32_CANCELLOCKREQUESTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pLockRange)
1491{
1492 /*
1493 * Validate input.
1494 */
1495 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1496 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1497 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1498 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1499 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1500 Assert(pFolder->cOpenFiles > 0);
1501 RT_NOREF(pFolder);
1502
1503 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
1504 return ERROR_NOT_SUPPORTED;
1505}
1506
1507
1508DECLASM(APIRET)
1509FS32_CANCELLOCKREQUEST(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pLockRange)
1510{
1511 /*
1512 * Validate input.
1513 */
1514 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1515 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1516 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1517 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1518 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1519 Assert(pFolder->cOpenFiles > 0);
1520 RT_NOREF(pFolder);
1521
1522 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
1523 return ERROR_NOT_SUPPORTED;
1524}
1525
1526
1527DECLASM(APIRET)
1528FS32_FILELOCKSL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pUnLockRange,
1529 struct filelockl *pLockRange, ULONG cMsTimeout, ULONG fFlags)
1530{
1531 /*
1532 * Validate input.
1533 */
1534 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1535 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1536 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1537 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1538 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1539 Assert(pFolder->cOpenFiles > 0);
1540 RT_NOREF(pFolder);
1541
1542 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
1543 return ERROR_NOT_SUPPORTED;
1544}
1545
1546
1547DECLASM(APIRET)
1548FS32_FILELOCKS(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pUnLockRange,
1549 struct filelock *pLockRange, ULONG cMsTimeout, ULONG fFlags)
1550{
1551 /*
1552 * Validate input.
1553 */
1554 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1555 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1556 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1557 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1558 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1559 Assert(pFolder->cOpenFiles > 0);
1560 RT_NOREF(pFolder);
1561
1562 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
1563 return ERROR_NOT_SUPPORTED;
1564}
1565
1566
1567DECLASM(APIRET)
1568FS32_IOCTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uCategory, USHORT uFunction,
1569 PVOID pvParm, USHORT cbParm, PUSHORT pcbParmIO,
1570 PVOID pvData, USHORT cbData, PUSHORT pcbDataIO)
1571{
1572 /*
1573 * Validate input.
1574 */
1575 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1576 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1577 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1578 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1579 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1580 Assert(pFolder->cOpenFiles > 0);
1581 RT_NOREF(pFolder);
1582
1583 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uCategory); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
1584 NOREF(pvData); NOREF(cbData); NOREF(pcbDataIO);
1585 return ERROR_NOT_SUPPORTED;
1586}
1587
1588
1589DECLASM(APIRET)
1590FS32_FILEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, PBYTE pbCmdList, USHORT cbCmdList,
1591 PUSHORT poffError, USHORT fIoFlag)
1592{
1593 /*
1594 * Validate input.
1595 */
1596 AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
1597 AssertReturn(pSfFsd->pSelf == pSfFsd, ERROR_SYS_INTERNAL);
1598 PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
1599 AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
1600 Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
1601 Assert(pFolder->cOpenFiles > 0);
1602 RT_NOREF(pFolder);
1603
1604 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pbCmdList); NOREF(cbCmdList); NOREF(poffError); NOREF(fIoFlag);
1605 return ERROR_NOT_SUPPORTED;
1606}
1607
1608
1609DECLASM(APIRET)
1610FS32_NMPIPE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uOpType, union npoper *pOpRec,
1611 PBYTE pbData, PCSZ pszName)
1612{
1613 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uOpType); NOREF(pOpRec); NOREF(pbData); NOREF(pszName);
1614 return ERROR_NOT_SUPPORTED;
1615}
1616
1617
1618DECLASM(APIRET)
1619FS32_OPENPAGEFILE(PULONG pfFlags, PULONG pcMaxReq, PCSZ pszName, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd,
1620 USHORT fOpenMode, USHORT fOpenFlags, USHORT fAttr, ULONG uReserved)
1621{
1622 NOREF(pfFlags); NOREF(pcMaxReq); NOREF(pszName); NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fOpenMode); NOREF(fOpenFlags);
1623 NOREF(fAttr); NOREF(uReserved);
1624 return ERROR_NOT_SUPPORTED;
1625}
1626
1627
1628DECLASM(APIRET)
1629FS32_SETSWAP(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
1630{
1631 NOREF(pSfFsi); NOREF(pSfFsd);
1632 return ERROR_NOT_SUPPORTED;
1633}
1634
1635
1636DECLASM(APIRET)
1637FS32_ALLOCATEPAGESPACE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG cb, USHORT cbWantContig)
1638{
1639 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(cb); NOREF(cbWantContig);
1640 return ERROR_NOT_SUPPORTED;
1641}
1642
1643
1644DECLASM(APIRET)
1645FS32_DOPAGEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct PageCmdHeader *pList)
1646{
1647 NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pList);
1648 return ERROR_NOT_SUPPORTED;
1649}
1650
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