VirtualBox

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

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

SharedFolders,os2/VBoxSF: Added SHFL_FN_SET_FILE_SIZE for setting the file size without needing to passing an mostly unused buffer (SHFLOBJINFO). Deprecated most of VbglR0SfXxxx and continued hacking on replacements using OS/2 as testbed. bugref:9172

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