[3655] | 1 | /** $Id: VBoxSF.cpp 93071 2021-12-24 00:12:04Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VBoxSF - OS/2 Shared Folders, the FS and FSD level IFS EPs
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
| 7 | * Copyright (c) 2007 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 |
|
---|
[57358] | 32 | /*********************************************************************************************************************************
|
---|
| 33 | * Header Files *
|
---|
| 34 | *********************************************************************************************************************************/
|
---|
[3655] | 35 | #define LOG_GROUP LOG_GROUP_DEFAULT
|
---|
| 36 | #include "VBoxSFInternal.h"
|
---|
| 37 |
|
---|
| 38 | #include <VBox/log.h>
|
---|
| 39 | #include <iprt/assert.h>
|
---|
[75337] | 40 | #include <iprt/ctype.h>
|
---|
[76448] | 41 | #include <iprt/err.h>
|
---|
[75337] | 42 | #include <iprt/mem.h>
|
---|
[76143] | 43 | #include <iprt/path.h>
|
---|
[3655] | 44 |
|
---|
[75337] | 45 | #include <iprt/asm.h>
|
---|
| 46 | #include <iprt/asm-amd64-x86.h>
|
---|
[3655] | 47 |
|
---|
| 48 |
|
---|
[75337] | 49 | /*********************************************************************************************************************************
|
---|
| 50 | * Defined Constants And Macros *
|
---|
| 51 | *********************************************************************************************************************************/
|
---|
| 52 | /** Max folder name length, including terminator.
|
---|
| 53 | * Easier to deal with stack buffers if we put a reasonable limit on the. */
|
---|
| 54 | #define VBOXSFOS2_MAX_FOLDER_NAME 64
|
---|
| 55 |
|
---|
| 56 |
|
---|
| 57 | /*********************************************************************************************************************************
|
---|
| 58 | * Global Variables *
|
---|
| 59 | *********************************************************************************************************************************/
|
---|
[76693] | 60 | /** VMMDEV_HVF_XXX (set during init). */
|
---|
| 61 | uint32_t g_fHostFeatures = 0;
|
---|
[75337] | 62 | /** The shared mutex protecting folders list, drives and the connection. */
|
---|
| 63 | MutexLock_t g_MtxFolders;
|
---|
| 64 | /** The shared folder service client structure. */
|
---|
| 65 | VBGLSFCLIENT g_SfClient;
|
---|
| 66 | /** Set if g_SfClient is valid, clear if not. */
|
---|
| 67 | bool g_fIsConnectedToService = false;
|
---|
| 68 | /** List of active folder (PVBOXSFFOLDER). */
|
---|
| 69 | RTLISTANCHOR g_FolderHead;
|
---|
| 70 | /** This is incremented everytime g_FolderHead is modified. */
|
---|
| 71 | uint32_t volatile g_uFolderRevision;
|
---|
| 72 | /** Folders mapped on drive letters. Pointers include a reference. */
|
---|
| 73 | PVBOXSFFOLDER g_apDriveFolders[26];
|
---|
| 74 |
|
---|
| 75 |
|
---|
| 76 |
|
---|
| 77 | /**
|
---|
| 78 | * Generic IPRT -> OS/2 status code converter.
|
---|
| 79 | *
|
---|
| 80 | * @returns OS/2 status code.
|
---|
| 81 | * @param vrc IPRT/VBox status code.
|
---|
| 82 | * @param rcDefault The OS/2 status code to return when there
|
---|
| 83 | * is no translation.
|
---|
| 84 | */
|
---|
| 85 | APIRET vboxSfOs2ConvertStatusToOs2(int vrc, APIRET rcDefault)
|
---|
| 86 | {
|
---|
| 87 | switch (vrc)
|
---|
| 88 | {
|
---|
| 89 | default: return rcDefault;
|
---|
| 90 |
|
---|
| 91 | case VERR_FILE_NOT_FOUND: return ERROR_FILE_NOT_FOUND;
|
---|
| 92 | case VERR_PATH_NOT_FOUND: return ERROR_PATH_NOT_FOUND;
|
---|
| 93 | case VERR_SHARING_VIOLATION: return ERROR_SHARING_VIOLATION;
|
---|
| 94 | case VERR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
|
---|
| 95 | case VERR_ALREADY_EXISTS: return ERROR_ACCESS_DENIED;
|
---|
| 96 | case VERR_WRITE_PROTECT: return ERROR_WRITE_PROTECT;
|
---|
| 97 | case VERR_IS_A_DIRECTORY: return ERROR_DIRECTORY;
|
---|
[76143] | 98 | case VERR_DISK_FULL: return ERROR_DISK_FULL;
|
---|
[75337] | 99 | case VINF_SUCCESS: return NO_ERROR;
|
---|
| 100 | }
|
---|
| 101 | }
|
---|
| 102 |
|
---|
| 103 |
|
---|
| 104 | /**
|
---|
| 105 | * Gets the delta for the local timezone, in minutes.
|
---|
| 106 | *
|
---|
| 107 | * We need to do this once for each API call rather than over and over again for
|
---|
| 108 | * each date/time conversion, so as not to create an update race.
|
---|
| 109 | *
|
---|
| 110 | * @returns Delta in minutes. Current thinking is that positive means timezone
|
---|
| 111 | * is west of UTC, while negative is east of it.
|
---|
| 112 | */
|
---|
| 113 | int16_t vboxSfOs2GetLocalTimeDelta(void)
|
---|
| 114 | {
|
---|
| 115 | GINFOSEG volatile *pGis = (GINFOSEG volatile *)&KernSISData;
|
---|
| 116 | if (pGis)
|
---|
| 117 | {
|
---|
| 118 | uint16_t cDelta = pGis->timezone;
|
---|
| 119 | if (cDelta != 0 && cDelta != 0xffff)
|
---|
| 120 | return (int16_t)cDelta;
|
---|
| 121 | }
|
---|
| 122 | return 0;
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 |
|
---|
| 126 | /**
|
---|
| 127 | * Helper for converting from IPRT timespec format to OS/2 DATE/TIME.
|
---|
| 128 | *
|
---|
| 129 | * @param pDosDate The output DOS date.
|
---|
| 130 | * @param pDosTime The output DOS time.
|
---|
| 131 | * @param SrcTimeSpec The IPRT input timestamp.
|
---|
| 132 | * @param cMinLocalTimeDelta The timezone delta in minutes.
|
---|
| 133 | */
|
---|
| 134 | void vboxSfOs2DateTimeFromTimeSpec(FDATE *pDosDate, FTIME *pDosTime, RTTIMESPEC SrcTimeSpec, int16_t cMinLocalTimeDelta)
|
---|
| 135 | {
|
---|
| 136 | if (cMinLocalTimeDelta != 0)
|
---|
[75558] | 137 | RTTimeSpecAddSeconds(&SrcTimeSpec, -cMinLocalTimeDelta * 60);
|
---|
[75337] | 138 |
|
---|
| 139 | RTTIME Time;
|
---|
| 140 | if ( RTTimeSpecGetNano(&SrcTimeSpec) >= RTTIME_OFFSET_DOS_TIME
|
---|
| 141 | && RTTimeExplode(&Time, &SrcTimeSpec))
|
---|
| 142 | {
|
---|
| 143 | pDosDate->year = Time.i32Year - 1980;
|
---|
| 144 | pDosDate->month = Time.u8Month;
|
---|
| 145 | pDosDate->day = Time.u8MonthDay;
|
---|
| 146 | pDosTime->hours = Time.u8Hour;
|
---|
| 147 | pDosTime->minutes = Time.u8Minute;
|
---|
| 148 | pDosTime->twosecs = Time.u8Second / 2;
|
---|
| 149 | }
|
---|
| 150 | else
|
---|
| 151 | {
|
---|
| 152 | pDosDate->year = 0;
|
---|
| 153 | pDosDate->month = 1;
|
---|
| 154 | pDosDate->day = 1;
|
---|
| 155 | pDosTime->hours = 0;
|
---|
| 156 | pDosTime->minutes = 0;
|
---|
| 157 | pDosTime->twosecs = 0;
|
---|
| 158 | }
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 |
|
---|
| 162 | /**
|
---|
| 163 | * Helper for converting from OS/2 DATE/TIME to IPRT timespec format.
|
---|
| 164 | *
|
---|
| 165 | * @returns pDstTimeSpec on success, NULL if invalid input.
|
---|
| 166 | * @param DosDate The input DOS date.
|
---|
| 167 | * @param DosTime The input DOS time.
|
---|
| 168 | * @param cMinLocalTimeDelta The timezone delta in minutes.
|
---|
| 169 | * @param pDstTimeSpec The IPRT output timestamp.
|
---|
| 170 | */
|
---|
| 171 | PRTTIMESPEC vboxSfOs2DateTimeToTimeSpec(FDATE DosDate, FTIME DosTime, int16_t cMinLocalTimeDelta, PRTTIMESPEC pDstTimeSpec)
|
---|
| 172 | {
|
---|
| 173 | RTTIME Time;
|
---|
| 174 | Time.i32Year = DosDate.year + 1980;
|
---|
| 175 | Time.u8Month = DosDate.month;
|
---|
| 176 | Time.u8WeekDay = UINT8_MAX;
|
---|
| 177 | Time.u16YearDay = 0;
|
---|
| 178 | Time.u8MonthDay = DosDate.day;
|
---|
| 179 | Time.u8Hour = DosTime.hours;
|
---|
| 180 | Time.u8Minute = DosTime.minutes;
|
---|
| 181 | Time.u8Second = DosTime.twosecs * 2;
|
---|
| 182 | Time.u32Nanosecond = 0;
|
---|
| 183 | Time.fFlags = RTTIME_FLAGS_TYPE_LOCAL;
|
---|
[77642] | 184 | Time.offUTC = -cMinLocalTimeDelta;
|
---|
[75337] | 185 | if (RTTimeLocalNormalize(&Time))
|
---|
| 186 | return RTTimeImplode(pDstTimeSpec, &Time);
|
---|
| 187 | return NULL;
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 |
|
---|
| 191 | /*********************************************************************************************************************************
|
---|
| 192 | * Shared Folder String Buffer Management *
|
---|
| 193 | *********************************************************************************************************************************/
|
---|
| 194 |
|
---|
| 195 | /**
|
---|
[76108] | 196 | * Allocates a SHFLSTRING buffer (UTF-16).
|
---|
[75337] | 197 | *
|
---|
| 198 | * @returns Pointer to a SHFLSTRING buffer, NULL if out of memory.
|
---|
[76108] | 199 | * @param cwcLength The desired string buffer length in UTF-16 units
|
---|
| 200 | * (excluding terminator).
|
---|
[75337] | 201 | */
|
---|
[76108] | 202 | PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength)
|
---|
[75337] | 203 | {
|
---|
[76108] | 204 | AssertReturn(cwcLength <= 0x1000, NULL);
|
---|
| 205 | uint16_t cb = (uint16_t)cwcLength + 1;
|
---|
| 206 | cb *= sizeof(RTUTF16);
|
---|
[75337] | 207 |
|
---|
[76108] | 208 | PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cb);
|
---|
[75337] | 209 | if (pStr)
|
---|
| 210 | {
|
---|
[76108] | 211 | pStr->u16Size = cb;
|
---|
| 212 | pStr->u16Length = 0;
|
---|
| 213 | pStr->String.utf16[0] = '\0';
|
---|
[75337] | 214 | return pStr;
|
---|
| 215 | }
|
---|
| 216 | return NULL;
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 |
|
---|
| 220 | /**
|
---|
[76108] | 221 | * Duplicates a shared folders string buffer (UTF-16).
|
---|
[75337] | 222 | *
|
---|
| 223 | * @returns Pointer to a SHFLSTRING buffer containing the copy.
|
---|
| 224 | * NULL if out of memory or the string is too long.
|
---|
[76108] | 225 | * @param pSrc The string to clone.
|
---|
[75337] | 226 | */
|
---|
[76108] | 227 | PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc)
|
---|
[75337] | 228 | {
|
---|
[76108] | 229 | PSHFLSTRING pDst = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Length + sizeof(RTUTF16));
|
---|
| 230 | if (pDst)
|
---|
[75337] | 231 | {
|
---|
[76108] | 232 | pDst->u16Size = pSrc->u16Length + (uint16_t)sizeof(RTUTF16);
|
---|
| 233 | pDst->u16Length = pSrc->u16Length;
|
---|
| 234 | memcpy(&pDst->String, &pSrc->String, pSrc->u16Length);
|
---|
| 235 | pDst->String.utf16[pSrc->u16Length / sizeof(RTUTF16)] = '\0';
|
---|
| 236 | return pDst;
|
---|
[75337] | 237 | }
|
---|
| 238 | return NULL;
|
---|
| 239 | }
|
---|
| 240 |
|
---|
| 241 |
|
---|
| 242 | /**
|
---|
| 243 | * Frees a SHLFSTRING buffer.
|
---|
| 244 | *
|
---|
| 245 | * @param pStr The buffer to free.
|
---|
| 246 | */
|
---|
| 247 | void vboxSfOs2StrFree(PSHFLSTRING pStr)
|
---|
| 248 | {
|
---|
| 249 | if (pStr)
|
---|
| 250 | VbglR0PhysHeapFree(pStr);
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 |
|
---|
| 254 |
|
---|
| 255 | /*********************************************************************************************************************************
|
---|
| 256 | * Folders, Paths and Service Connection. *
|
---|
| 257 | *********************************************************************************************************************************/
|
---|
| 258 |
|
---|
| 259 | /**
|
---|
| 260 | * Ensures that we're connected to the host service.
|
---|
| 261 | *
|
---|
| 262 | * @returns VBox status code.
|
---|
| 263 | * @remarks Caller owns g_MtxFolder exclusively!
|
---|
| 264 | */
|
---|
| 265 | static int vboxSfOs2EnsureConnected(void)
|
---|
| 266 | {
|
---|
| 267 | if (g_fIsConnectedToService)
|
---|
| 268 | return VINF_SUCCESS;
|
---|
| 269 |
|
---|
| 270 | int rc = VbglR0SfConnect(&g_SfClient);
|
---|
| 271 | if (RT_SUCCESS(rc))
|
---|
[76108] | 272 | g_fIsConnectedToService = true;
|
---|
[75337] | 273 | else
|
---|
| 274 | LogRel(("VbglR0SfConnect failed: %Rrc\n", rc));
|
---|
| 275 | return rc;
|
---|
| 276 | }
|
---|
| 277 |
|
---|
| 278 |
|
---|
| 279 | /**
|
---|
| 280 | * Destroys a folder when the reference count has reached zero.
|
---|
| 281 | *
|
---|
| 282 | * @param pFolder The folder to destroy.
|
---|
| 283 | */
|
---|
| 284 | static void vboxSfOs2DestroyFolder(PVBOXSFFOLDER pFolder)
|
---|
| 285 | {
|
---|
| 286 | /* Note! We won't get there while the folder is on the list. */
|
---|
| 287 | LogRel(("vboxSfOs2ReleaseFolder: Destroying %p [%s]\n", pFolder, pFolder->szName));
|
---|
[76716] | 288 | VbglR0SfHostReqUnmapFolderSimple(pFolder->idHostRoot);
|
---|
[75337] | 289 | RT_ZERO(pFolder);
|
---|
| 290 | RTMemFree(pFolder);
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 |
|
---|
| 294 | /**
|
---|
| 295 | * Releases a reference to a folder.
|
---|
| 296 | *
|
---|
| 297 | * @param pFolder The folder to release.
|
---|
| 298 | */
|
---|
| 299 | void vboxSfOs2ReleaseFolder(PVBOXSFFOLDER pFolder)
|
---|
| 300 | {
|
---|
| 301 | if (pFolder)
|
---|
| 302 | {
|
---|
| 303 | uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
|
---|
| 304 | AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
|
---|
| 305 | if (!cRefs)
|
---|
| 306 | vboxSfOs2DestroyFolder(pFolder);
|
---|
| 307 | }
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 |
|
---|
| 311 | /**
|
---|
| 312 | * Retain a reference to a folder.
|
---|
| 313 | *
|
---|
| 314 | * @param pFolder The folder to release.
|
---|
| 315 | */
|
---|
| 316 | void vboxSfOs2RetainFolder(PVBOXSFFOLDER pFolder)
|
---|
| 317 | {
|
---|
| 318 | uint32_t cRefs = ASMAtomicIncU32(&pFolder->cRefs);
|
---|
| 319 | AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 |
|
---|
| 323 | /**
|
---|
| 324 | * Locates and retains a folder structure.
|
---|
| 325 | *
|
---|
| 326 | * @returns Folder matching the name, NULL of not found.
|
---|
| 327 | * @remarks Caller owns g_MtxFolder.
|
---|
| 328 | */
|
---|
| 329 | static PVBOXSFFOLDER vboxSfOs2FindAndRetainFolder(const char *pachName, size_t cchName)
|
---|
| 330 | {
|
---|
| 331 | PVBOXSFFOLDER pCur;
|
---|
| 332 | RTListForEach(&g_FolderHead, pCur, VBOXSFFOLDER, ListEntry)
|
---|
| 333 | {
|
---|
| 334 | if ( pCur->cchName == cchName
|
---|
| 335 | && RTStrNICmpAscii(pCur->szName, pachName, cchName) == 0)
|
---|
| 336 | {
|
---|
| 337 | uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
|
---|
| 338 | AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
|
---|
| 339 | return pCur;
|
---|
| 340 | }
|
---|
| 341 | }
|
---|
| 342 | return NULL;
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 |
|
---|
| 346 | /**
|
---|
| 347 | * Maps a folder, linking it into the list of folders.
|
---|
| 348 | *
|
---|
| 349 | * One reference is retained for the caller, which must pass it on or release
|
---|
| 350 | * it. The list also have a reference to it.
|
---|
| 351 | *
|
---|
| 352 | * @returns VBox status code.
|
---|
[76108] | 353 | * @param pName The name of the folder to map - ASCII (not UTF-16!).
|
---|
| 354 | * Must be large enough to hold UTF-16 expansion of the
|
---|
| 355 | * string, will do so upon return.
|
---|
[75405] | 356 | * @param pszTag Folder tag (for the VBoxService automounter). Optional.
|
---|
[75337] | 357 | * @param ppFolder Where to return the folder structure on success.
|
---|
| 358 | *
|
---|
| 359 | * @remarks Caller owns g_MtxFolder exclusively!
|
---|
| 360 | */
|
---|
[75405] | 361 | static int vboxSfOs2MapFolder(PSHFLSTRING pName, const char *pszTag, PVBOXSFFOLDER *ppFolder)
|
---|
[75337] | 362 | {
|
---|
| 363 | int rc;
|
---|
[75405] | 364 | size_t const cbTag = pszTag ? strlen(pszTag) + 1 : NULL;
|
---|
| 365 | PVBOXSFFOLDER pNew = (PVBOXSFFOLDER)RTMemAlloc(RT_UOFFSETOF_DYN(VBOXSFFOLDER, szName[pName->u16Length + 1 + cbTag]));
|
---|
[75337] | 366 | if (pNew != NULL)
|
---|
| 367 | {
|
---|
| 368 | pNew->u32Magic = VBOXSFFOLDER_MAGIC;
|
---|
| 369 | pNew->cRefs = 2; /* (List reference + the returned reference.) */
|
---|
| 370 | pNew->cOpenFiles = 0;
|
---|
[75471] | 371 | pNew->cOpenSearches = 0;
|
---|
[75337] | 372 | pNew->cDrives = 0;
|
---|
[76715] | 373 | pNew->idHostRoot = SHFL_ROOT_NIL;
|
---|
[75337] | 374 | pNew->hVpb = 0;
|
---|
[75405] | 375 | pNew->cbNameAndTag = pName->u16Length + (uint16_t)cbTag;
|
---|
[75337] | 376 | pNew->cchName = (uint8_t)pName->u16Length;
|
---|
[75405] | 377 | pNew->cchName = (uint8_t)pName->u16Length;
|
---|
[75337] | 378 | memcpy(pNew->szName, pName->String.utf8, pName->u16Length);
|
---|
| 379 | pNew->szName[pName->u16Length] = '\0';
|
---|
[75405] | 380 | if (cbTag)
|
---|
| 381 | memcpy(&pNew->szName[pName->u16Length + 1], pszTag, cbTag);
|
---|
[75337] | 382 |
|
---|
[76108] | 383 | /* Expand the folder name to UTF-16. */
|
---|
| 384 | uint8_t off = pNew->cchName;
|
---|
| 385 | uint8_t volatile const *pbSrc = &pName->String.utf8[0];
|
---|
| 386 | RTUTF16 volatile *pwcDst = &pName->String.utf16[0];
|
---|
| 387 | do
|
---|
| 388 | pwcDst[off] = pbSrc[off];
|
---|
| 389 | while (off-- > 0);
|
---|
| 390 | pName->u16Length *= sizeof(RTUTF16);
|
---|
| 391 | Assert(pName->u16Length + sizeof(RTUTF16) <= pName->u16Size);
|
---|
| 392 |
|
---|
| 393 | /* Try do the mapping.*/
|
---|
[76143] | 394 | VBOXSFMAPFOLDERWITHBUFREQ *pReq = (VBOXSFMAPFOLDERWITHBUFREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
|
---|
| 395 | if (pReq)
|
---|
[75337] | 396 | {
|
---|
[76716] | 397 | rc = VbglR0SfHostReqMapFolderWithBuf(pReq, pName, RTPATH_DELIMITER, false /*fCaseSensitive*/);
|
---|
[76143] | 398 | if (RT_SUCCESS(rc))
|
---|
| 399 | {
|
---|
[76715] | 400 | pNew->idHostRoot = pReq->Parms.id32Root.u.value32;
|
---|
[75337] | 401 |
|
---|
[76143] | 402 | RTListAppend(&g_FolderHead, &pNew->ListEntry);
|
---|
| 403 | ASMAtomicIncU32(&g_uFolderRevision);
|
---|
| 404 | LogRel(("vboxSfOs2MapFolder: %p - %s\n", pNew, pNew->szName));
|
---|
| 405 |
|
---|
| 406 | *ppFolder = pNew;
|
---|
| 407 | pNew = NULL;
|
---|
| 408 | }
|
---|
| 409 | else
|
---|
[76716] | 410 | LogRel(("vboxSfOs2MapFolder: VbglR0SfHostReqMapFolderWithBuf(,%s,) -> %Rrc\n", pNew->szName, rc));
|
---|
[76143] | 411 | VbglR0PhysHeapFree(pReq);
|
---|
[75337] | 412 | }
|
---|
| 413 | else
|
---|
[76143] | 414 | LogRel(("vboxSfOs2MapFolder: Out of physical heap :-(\n"));
|
---|
| 415 | RTMemFree(pNew);
|
---|
[75337] | 416 | }
|
---|
| 417 | else
|
---|
| 418 | {
|
---|
| 419 | LogRel(("vboxSfOs2MapFolder: Out of memory :-(\n"));
|
---|
| 420 | rc = VERR_NO_MEMORY;
|
---|
| 421 | }
|
---|
| 422 | return rc;
|
---|
| 423 | }
|
---|
| 424 |
|
---|
| 425 |
|
---|
| 426 | /**
|
---|
| 427 | * Worker for vboxSfOs2UncPrefixLength.
|
---|
| 428 | */
|
---|
| 429 | DECLINLINE(size_t) vboxSfOs2CountLeadingSlashes(const char *pszPath)
|
---|
| 430 | {
|
---|
| 431 | size_t cchSlashes = 0;
|
---|
| 432 | char ch;
|
---|
| 433 | while ((ch = *pszPath) == '\\' || ch == '/')
|
---|
| 434 | cchSlashes++, pszPath++;
|
---|
| 435 | return cchSlashes;
|
---|
| 436 | }
|
---|
| 437 |
|
---|
| 438 |
|
---|
| 439 | /**
|
---|
| 440 | * Checks for a VBox UNC prefix (server + slashes) and determins its length when
|
---|
| 441 | * found.
|
---|
| 442 | *
|
---|
| 443 | * @returns Length of VBoxSF UNC prefix, 0 if not VBoxSF UNC prefix.
|
---|
| 444 | * @param pszPath The possible UNC path.
|
---|
| 445 | */
|
---|
| 446 | DECLINLINE(size_t) vboxSfOs2UncPrefixLength(const char *pszPath)
|
---|
| 447 | {
|
---|
| 448 | char ch;
|
---|
| 449 | if ( ((ch = pszPath[0]) == '\\' || ch == '/')
|
---|
| 450 | && ((ch = pszPath[1]) == '\\' || ch == '/')
|
---|
| 451 | && ((ch = pszPath[2]) == 'V' || ch == 'v')
|
---|
| 452 | && ((ch = pszPath[3]) == 'B' || ch == 'b')
|
---|
| 453 | && ((ch = pszPath[4]) == 'O' || ch == 'o')
|
---|
| 454 | && ((ch = pszPath[5]) == 'X' || ch == 'x')
|
---|
| 455 | && ((ch = pszPath[6]) == 'S' || ch == 's')
|
---|
| 456 | )
|
---|
| 457 | {
|
---|
| 458 | /* \\VBoxSf\ */
|
---|
| 459 | if ( ((ch = pszPath[7]) == 'F' || ch == 'f')
|
---|
| 460 | && ((ch = pszPath[8]) == '\\' || ch == '/') )
|
---|
| 461 | return vboxSfOs2CountLeadingSlashes(&pszPath[9]) + 9;
|
---|
| 462 |
|
---|
| 463 | /* \\VBoxSvr\ */
|
---|
| 464 | if ( ((ch = pszPath[7]) == 'V' || ch == 'v')
|
---|
| 465 | && ((ch = pszPath[8]) == 'R' || ch == 'r')
|
---|
| 466 | && ((ch = pszPath[9]) == '\\' || ch == '/') )
|
---|
| 467 | return vboxSfOs2CountLeadingSlashes(&pszPath[10]) + 10;
|
---|
| 468 |
|
---|
| 469 | /* \\VBoxSrv\ */
|
---|
| 470 | if ( ((ch = pszPath[7]) == 'R' || ch == 'r')
|
---|
| 471 | && ((ch = pszPath[8]) == 'V' || ch == 'v')
|
---|
| 472 | && ((ch = pszPath[9]) == '\\' || ch == '/') )
|
---|
| 473 | return vboxSfOs2CountLeadingSlashes(&pszPath[10]) + 10;
|
---|
| 474 | }
|
---|
| 475 |
|
---|
| 476 | return 0;
|
---|
| 477 | }
|
---|
| 478 |
|
---|
| 479 |
|
---|
| 480 | /**
|
---|
[76108] | 481 | * Converts a path to UTF-16 and puts it in a VBGL friendly buffer.
|
---|
[75337] | 482 | *
|
---|
| 483 | * @returns OS/2 status code
|
---|
| 484 | * @param pszFolderPath The path to convert.
|
---|
| 485 | * @param ppStr Where to return the pointer to the buffer. Free
|
---|
| 486 | * using vboxSfOs2FreePath.
|
---|
| 487 | */
|
---|
| 488 | APIRET vboxSfOs2ConvertPath(const char *pszFolderPath, PSHFLSTRING *ppStr)
|
---|
| 489 | {
|
---|
[76108] | 490 | /*
|
---|
| 491 | * Skip unnecessary leading slashes.
|
---|
| 492 | */
|
---|
[75337] | 493 | char ch = *pszFolderPath;
|
---|
| 494 | if (ch == '\\' || ch == '/')
|
---|
| 495 | while ((ch = pszFolderPath[1]) == '\\' || ch == '/')
|
---|
| 496 | pszFolderPath++;
|
---|
| 497 |
|
---|
[76108] | 498 | /*
|
---|
| 499 | * Since the KEE unicode conversion routines does not seem to know of
|
---|
| 500 | * surrogate pairs, we will get a very good output size estimate by
|
---|
| 501 | * using strlen() on the input.
|
---|
| 502 | */
|
---|
[75337] | 503 | size_t cchSrc = strlen(pszFolderPath);
|
---|
[76108] | 504 | PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc + 4 /*fudge*/);
|
---|
[75337] | 505 | if (pDst)
|
---|
| 506 | {
|
---|
[77640] | 507 | APIRET rc = SafeKernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
|
---|
[76108] | 508 | if (rc == NO_ERROR)
|
---|
| 509 | {
|
---|
| 510 | pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
|
---|
[76146] | 511 | Assert(pDst->u16Length < pDst->u16Size);
|
---|
| 512 | pDst->u16Size = pDst->u16Length + (uint16_t)sizeof(RTUTF16); /* (limit how much is copied to the host) */
|
---|
[76108] | 513 | *ppStr = pDst;
|
---|
| 514 | return NO_ERROR;
|
---|
| 515 | }
|
---|
| 516 | VbglR0PhysHeapFree(pDst);
|
---|
| 517 |
|
---|
| 518 | /*
|
---|
[76146] | 519 | * This shouldn't happen, but just in case we try again with twice
|
---|
| 520 | * the buffer size.
|
---|
[76108] | 521 | */
|
---|
| 522 | if (rc == 0x20412 /*ULS_BUFFERFULL*/)
|
---|
| 523 | {
|
---|
| 524 | pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2);
|
---|
| 525 | if (pDst)
|
---|
| 526 | {
|
---|
[77640] | 527 | rc = SafeKernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
|
---|
[76108] | 528 | if (rc == NO_ERROR)
|
---|
| 529 | {
|
---|
| 530 | pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
|
---|
[76146] | 531 | Assert(pDst->u16Length < pDst->u16Size);
|
---|
| 532 | pDst->u16Size = pDst->u16Length + (uint16_t)sizeof(RTUTF16);
|
---|
[76108] | 533 | *ppStr = pDst;
|
---|
| 534 | return NO_ERROR;
|
---|
| 535 | }
|
---|
| 536 | VbglR0PhysHeapFree(pDst);
|
---|
[77640] | 537 | LogRel(("vboxSfOs2ConvertPath: SafeKernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
|
---|
[76108] | 538 | }
|
---|
| 539 | }
|
---|
| 540 | else
|
---|
[77640] | 541 | LogRel(("vboxSfOs2ConvertPath: SafeKernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
|
---|
[75337] | 542 | }
|
---|
[76108] | 543 |
|
---|
| 544 | LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x\n", cchSrc));
|
---|
[75337] | 545 | *ppStr = NULL;
|
---|
| 546 | return ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 |
|
---|
| 550 | /**
|
---|
[76108] | 551 | * Converts a path to UTF-16 and puts it in a VBGL friendly buffer within a
|
---|
| 552 | * larger buffer.
|
---|
| 553 | *
|
---|
| 554 | * @returns OS/2 status code
|
---|
| 555 | * @param pszFolderPath The path to convert.
|
---|
| 556 | * @param offStrInBuf The offset of the SHLFSTRING in the return buffer.
|
---|
| 557 | * This first part of the buffer is zeroed.
|
---|
| 558 | * @param ppvBuf Where to return the pointer to the buffer. Free
|
---|
| 559 | * using vboxSfOs2FreePath.
|
---|
| 560 | */
|
---|
| 561 | APIRET vboxSfOs2ConvertPathEx(const char *pszFolderPath, uint32_t offStrInBuf, void **ppvBuf)
|
---|
| 562 | {
|
---|
| 563 | /*
|
---|
| 564 | * Skip unnecessary leading slashes.
|
---|
| 565 | */
|
---|
| 566 | char ch = *pszFolderPath;
|
---|
| 567 | if (ch == '\\' || ch == '/')
|
---|
| 568 | while ((ch = pszFolderPath[1]) == '\\' || ch == '/')
|
---|
| 569 | pszFolderPath++;
|
---|
| 570 |
|
---|
| 571 | /*
|
---|
| 572 | * Since the KEE unicode conversion routines does not seem to know of
|
---|
| 573 | * surrogate pairs, we will get a very good output size estimate by
|
---|
| 574 | * using strlen() on the input.
|
---|
| 575 | */
|
---|
| 576 | size_t cchSrc = strlen(pszFolderPath);
|
---|
| 577 | void *pvBuf = VbglR0PhysHeapAlloc(offStrInBuf + SHFLSTRING_HEADER_SIZE + (cchSrc + 4) * sizeof(RTUTF16));
|
---|
| 578 | if (pvBuf)
|
---|
| 579 | {
|
---|
| 580 | RT_BZERO(pvBuf, offStrInBuf);
|
---|
[76146] | 581 | PSHFLSTRING pDst = (PSHFLSTRING)((uint8_t *)pvBuf + offStrInBuf);
|
---|
[76108] | 582 |
|
---|
[77640] | 583 | APIRET rc = SafeKernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
|
---|
[76108] | 584 | if (rc == NO_ERROR)
|
---|
| 585 | {
|
---|
| 586 | pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
|
---|
[76146] | 587 | Assert(pDst->u16Length < (cchSrc + 4) * sizeof(RTUTF16));
|
---|
| 588 | pDst->u16Size = pDst->u16Length + (uint16_t)sizeof(RTUTF16); /* (limit how much is copied to the host) */
|
---|
[76108] | 589 | *ppvBuf = pvBuf;
|
---|
| 590 | return NO_ERROR;
|
---|
| 591 | }
|
---|
| 592 | VbglR0PhysHeapFree(pvBuf);
|
---|
| 593 |
|
---|
| 594 | /*
|
---|
[76146] | 595 | * This shouldn't happen, but just in case we try again with twice
|
---|
| 596 | * the buffer size.
|
---|
[76108] | 597 | */
|
---|
| 598 | if (rc == 0x20412 /*ULS_BUFFERFULL*/)
|
---|
| 599 | {
|
---|
[76146] | 600 | pvBuf = VbglR0PhysHeapAlloc(offStrInBuf + SHFLSTRING_HEADER_SIZE + (cchSrc + 16) * sizeof(RTUTF16) * 2);
|
---|
| 601 | if (pvBuf)
|
---|
[76108] | 602 | {
|
---|
[76146] | 603 | RT_BZERO(pvBuf, offStrInBuf);
|
---|
| 604 | pDst = (PSHFLSTRING)((uint8_t *)pvBuf + offStrInBuf);
|
---|
| 605 |
|
---|
[77640] | 606 | rc = SafeKernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
|
---|
[76108] | 607 | if (rc == NO_ERROR)
|
---|
| 608 | {
|
---|
| 609 | pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
|
---|
[76146] | 610 | Assert(pDst->u16Length < (cchSrc + 16) * 2 * sizeof(RTUTF16));
|
---|
| 611 | pDst->u16Size = pDst->u16Length + (uint16_t)sizeof(RTUTF16);
|
---|
| 612 | *ppvBuf = pvBuf;
|
---|
[76108] | 613 | return NO_ERROR;
|
---|
| 614 | }
|
---|
| 615 | VbglR0PhysHeapFree(pDst);
|
---|
[77640] | 616 | LogRel(("vboxSfOs2ConvertPath: SafeKernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
|
---|
[76108] | 617 | }
|
---|
| 618 | }
|
---|
| 619 | else
|
---|
[77640] | 620 | LogRel(("vboxSfOs2ConvertPath: SafeKernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
|
---|
[76108] | 621 | }
|
---|
| 622 |
|
---|
| 623 | LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x offStrInBuf=%#x\n", cchSrc, offStrInBuf));
|
---|
| 624 | *ppvBuf = NULL;
|
---|
| 625 | return ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 626 | }
|
---|
| 627 |
|
---|
| 628 |
|
---|
| 629 | /**
|
---|
[75337] | 630 | * Counterpart to vboxSfOs2ResolvePath.
|
---|
| 631 | *
|
---|
| 632 | * @param pStrPath The path to free.
|
---|
| 633 | * @param pFolder The folder to release.
|
---|
| 634 | */
|
---|
| 635 | void vboxSfOs2ReleasePathAndFolder(PSHFLSTRING pStrPath, PVBOXSFFOLDER pFolder)
|
---|
| 636 | {
|
---|
| 637 | if (pStrPath)
|
---|
| 638 | VbglR0PhysHeapFree(pStrPath);
|
---|
| 639 | if (pFolder)
|
---|
| 640 | {
|
---|
| 641 | uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
|
---|
| 642 | Assert(cRefs < _64K);
|
---|
| 643 | if (!cRefs)
|
---|
| 644 | vboxSfOs2DestroyFolder(pFolder);
|
---|
| 645 | }
|
---|
| 646 | }
|
---|
| 647 |
|
---|
| 648 |
|
---|
| 649 | /**
|
---|
| 650 | * Worker for vboxSfOs2ResolvePath() for dynamically mapping folders for UNC
|
---|
| 651 | * paths.
|
---|
| 652 | *
|
---|
| 653 | * @returns OS/2 status code.
|
---|
| 654 | * @param pachFolderName The folder to map. Not necessarily zero terminated
|
---|
| 655 | * at the end of the folder name!
|
---|
| 656 | * @param cchFolderName The length of the folder name.
|
---|
| 657 | * @param uRevBefore The previous folder list revision.
|
---|
| 658 | * @param ppFolder Where to return the pointer to the retained folder.
|
---|
| 659 | */
|
---|
| 660 | DECL_NO_INLINE(static, int) vboxSfOs2AttachUncAndRetain(const char *pachFolderName, size_t cchFolderName,
|
---|
| 661 | uint32_t uRevBefore, PVBOXSFFOLDER *ppFolder)
|
---|
| 662 | {
|
---|
| 663 | KernRequestExclusiveMutex(&g_MtxFolders);
|
---|
| 664 |
|
---|
| 665 | /*
|
---|
| 666 | * Check if someone raced us to it.
|
---|
| 667 | */
|
---|
| 668 | if (uRevBefore != g_uFolderRevision)
|
---|
| 669 | {
|
---|
| 670 | PVBOXSFFOLDER pFolder = vboxSfOs2FindAndRetainFolder(pachFolderName, cchFolderName);
|
---|
| 671 | if (pFolder)
|
---|
| 672 | {
|
---|
| 673 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 674 | *ppFolder = pFolder;
|
---|
| 675 | return NO_ERROR;
|
---|
| 676 | }
|
---|
| 677 | }
|
---|
| 678 |
|
---|
| 679 | int rc = vboxSfOs2EnsureConnected();
|
---|
| 680 | if (RT_SUCCESS(rc))
|
---|
| 681 | {
|
---|
| 682 | /*
|
---|
| 683 | * Copy the name into the buffer format that Vbgl desires.
|
---|
| 684 | */
|
---|
[76108] | 685 | PSHFLSTRING pStrName = vboxSfOs2StrAlloc(cchFolderName);
|
---|
[75337] | 686 | if (pStrName)
|
---|
| 687 | {
|
---|
[76108] | 688 | memcpy(pStrName->String.ach, pachFolderName, cchFolderName);
|
---|
| 689 | pStrName->String.ach[cchFolderName] = '\0';
|
---|
| 690 | pStrName->u16Length = (uint16_t)cchFolderName;
|
---|
| 691 |
|
---|
[75337] | 692 | /*
|
---|
| 693 | * Do the attaching.
|
---|
| 694 | */
|
---|
[75405] | 695 | rc = vboxSfOs2MapFolder(pStrName, NULL, ppFolder);
|
---|
[75337] | 696 | vboxSfOs2StrFree(pStrName);
|
---|
| 697 | if (RT_SUCCESS(rc))
|
---|
| 698 | {
|
---|
| 699 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 700 | LogRel(("vboxSfOs2AttachUncAndRetain: Successfully attached '%s' (as UNC).\n", (*ppFolder)->szName));
|
---|
| 701 | return NO_ERROR;
|
---|
| 702 | }
|
---|
| 703 |
|
---|
| 704 | if (rc == VERR_NO_MEMORY)
|
---|
| 705 | rc = ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 706 | else
|
---|
| 707 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 708 | }
|
---|
| 709 | else
|
---|
| 710 | rc = ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 711 | }
|
---|
| 712 | else
|
---|
| 713 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 714 |
|
---|
| 715 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 716 | return rc;
|
---|
| 717 | }
|
---|
| 718 |
|
---|
| 719 |
|
---|
| 720 | /**
|
---|
| 721 | * Resolves the given path to a folder structure and folder relative string.
|
---|
| 722 | *
|
---|
| 723 | * @returns OS/2 status code.
|
---|
| 724 | * @param pszPath The path to resolve.
|
---|
| 725 | * @param pCdFsd The IFS dependent CWD structure if present.
|
---|
| 726 | * @param offCurDirEnd The offset into @a pszPath of the CWD. -1 if not
|
---|
| 727 | * CWD relative path.
|
---|
| 728 | * @param ppFolder Where to return the referenced pointer to the folder
|
---|
| 729 | * structure. Call vboxSfOs2ReleaseFolder() when done.
|
---|
| 730 | * @param ppStrFolderPath Where to return a buffer holding the folder relative
|
---|
| 731 | * path component. Free using vboxSfOs2FreePath().
|
---|
| 732 | */
|
---|
| 733 | APIRET vboxSfOs2ResolvePath(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd,
|
---|
| 734 | PVBOXSFFOLDER *ppFolder, PSHFLSTRING *ppStrFolderPath)
|
---|
| 735 | {
|
---|
| 736 | APIRET rc;
|
---|
| 737 |
|
---|
| 738 | /*
|
---|
| 739 | * UNC path? Reject the prefix to be on the safe side.
|
---|
| 740 | */
|
---|
| 741 | char ch = pszPath[0];
|
---|
| 742 | if (ch == '\\' || ch == '/')
|
---|
| 743 | {
|
---|
| 744 | size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath);
|
---|
| 745 | if (cchPrefix > 0)
|
---|
| 746 | {
|
---|
| 747 | /* Find the length of the folder name (share). */
|
---|
| 748 | const char *pszFolderName = &pszPath[cchPrefix];
|
---|
| 749 | size_t cchFolderName = 0;
|
---|
| 750 | while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/')
|
---|
| 751 | {
|
---|
| 752 | if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':')
|
---|
| 753 | cchFolderName++;
|
---|
| 754 | else
|
---|
| 755 | {
|
---|
| 756 | LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n",
|
---|
| 757 | cchPrefix + cchFolderName, strlen(pszPath), pszPath));
|
---|
| 758 | return ERROR_INVALID_NAME;
|
---|
| 759 | }
|
---|
| 760 | }
|
---|
| 761 | if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME)
|
---|
| 762 | {
|
---|
| 763 | LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n",
|
---|
| 764 | cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath));
|
---|
| 765 | return ERROR_FILENAME_EXCED_RANGE;
|
---|
| 766 | }
|
---|
| 767 |
|
---|
| 768 | /*
|
---|
| 769 | * Look for the share.
|
---|
| 770 | */
|
---|
| 771 | KernRequestSharedMutex(&g_MtxFolders);
|
---|
| 772 | PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName);
|
---|
| 773 | if (pFolder)
|
---|
| 774 | {
|
---|
| 775 | vboxSfOs2RetainFolder(pFolder);
|
---|
| 776 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 777 | }
|
---|
| 778 | else
|
---|
| 779 | {
|
---|
| 780 | uint32_t const uRevBefore = g_uFolderRevision;
|
---|
| 781 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 782 | rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder);
|
---|
| 783 | if (rc == NO_ERROR)
|
---|
| 784 | pFolder = *ppFolder;
|
---|
| 785 | else
|
---|
| 786 | return rc;
|
---|
| 787 | }
|
---|
| 788 |
|
---|
| 789 | /*
|
---|
| 790 | * Convert the path and put it in a Vbgl compatible buffer..
|
---|
| 791 | */
|
---|
| 792 | rc = vboxSfOs2ConvertPath(&pszFolderName[cchFolderName], ppStrFolderPath);
|
---|
| 793 | if (rc == NO_ERROR)
|
---|
| 794 | return rc;
|
---|
| 795 |
|
---|
| 796 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
| 797 | *ppFolder = NULL;
|
---|
| 798 | return rc;
|
---|
| 799 | }
|
---|
| 800 |
|
---|
| 801 | LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
|
---|
| 802 | return ERROR_PATH_NOT_FOUND;
|
---|
| 803 | }
|
---|
| 804 |
|
---|
| 805 | /*
|
---|
| 806 | * Drive letter?
|
---|
| 807 | */
|
---|
| 808 | ch &= ~0x20; /* upper case */
|
---|
| 809 | if ( ch >= 'A'
|
---|
| 810 | && ch <= 'Z'
|
---|
| 811 | && pszPath[1] == ':')
|
---|
| 812 | {
|
---|
| 813 | unsigned iDrive = ch - 'A';
|
---|
| 814 | ch = pszPath[2];
|
---|
| 815 | if (ch == '\\' || ch == '/')
|
---|
| 816 | {
|
---|
| 817 | KernRequestSharedMutex(&g_MtxFolders);
|
---|
| 818 | PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive];
|
---|
| 819 | if (pFolder)
|
---|
| 820 | {
|
---|
| 821 | vboxSfOs2RetainFolder(pFolder);
|
---|
| 822 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 823 |
|
---|
| 824 | /*
|
---|
| 825 | * Convert the path and put it in a Vbgl compatible buffer..
|
---|
| 826 | */
|
---|
| 827 | rc = vboxSfOs2ConvertPath(&pszPath[3], ppStrFolderPath);
|
---|
| 828 | if (rc == NO_ERROR)
|
---|
| 829 | return rc;
|
---|
| 830 |
|
---|
| 831 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
| 832 | *ppFolder = NULL;
|
---|
| 833 | return rc;
|
---|
| 834 | }
|
---|
| 835 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 836 | LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath));
|
---|
| 837 | return ERROR_PATH_NOT_FOUND;
|
---|
| 838 | }
|
---|
| 839 | LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath));
|
---|
| 840 | return ERROR_PATH_NOT_FOUND;
|
---|
| 841 | }
|
---|
| 842 | LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
|
---|
| 843 | RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd);
|
---|
| 844 | return ERROR_PATH_NOT_FOUND;
|
---|
| 845 | }
|
---|
| 846 |
|
---|
| 847 |
|
---|
[76108] | 848 | /**
|
---|
| 849 | * Resolves the given path to a folder structure and folder relative string,
|
---|
| 850 | * the latter placed within a larger request buffer.
|
---|
| 851 | *
|
---|
| 852 | * @returns OS/2 status code.
|
---|
| 853 | * @param pszPath The path to resolve.
|
---|
| 854 | * @param pCdFsd The IFS dependent CWD structure if present.
|
---|
| 855 | * @param offCurDirEnd The offset into @a pszPath of the CWD. -1 if not
|
---|
| 856 | * CWD relative path.
|
---|
| 857 | * @param offStrInBuf The offset of the SHLFSTRING in the return buffer.
|
---|
| 858 | * This first part of the buffer is zeroed.
|
---|
| 859 | * @param ppFolder Where to return the referenced pointer to the folder
|
---|
| 860 | * structure. Call vboxSfOs2ReleaseFolder() when done.
|
---|
| 861 | * @param ppvBuf Where to return the Pointer to the buffer. Free
|
---|
| 862 | * using VbglR0PhysHeapFree.
|
---|
| 863 | */
|
---|
| 864 | APIRET vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf,
|
---|
| 865 | PVBOXSFFOLDER *ppFolder, void **ppvBuf)
|
---|
| 866 | {
|
---|
| 867 | APIRET rc;
|
---|
| 868 |
|
---|
| 869 | /*
|
---|
| 870 | * UNC path? Reject the prefix to be on the safe side.
|
---|
| 871 | */
|
---|
| 872 | char ch = pszPath[0];
|
---|
| 873 | if (ch == '\\' || ch == '/')
|
---|
| 874 | {
|
---|
| 875 | size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath);
|
---|
| 876 | if (cchPrefix > 0)
|
---|
| 877 | {
|
---|
| 878 | /* Find the length of the folder name (share). */
|
---|
| 879 | const char *pszFolderName = &pszPath[cchPrefix];
|
---|
| 880 | size_t cchFolderName = 0;
|
---|
| 881 | while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/')
|
---|
| 882 | {
|
---|
| 883 | if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':')
|
---|
| 884 | cchFolderName++;
|
---|
| 885 | else
|
---|
| 886 | {
|
---|
| 887 | LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n",
|
---|
| 888 | cchPrefix + cchFolderName, strlen(pszPath), pszPath));
|
---|
| 889 | return ERROR_INVALID_NAME;
|
---|
| 890 | }
|
---|
| 891 | }
|
---|
| 892 | if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME)
|
---|
| 893 | {
|
---|
| 894 | LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n",
|
---|
| 895 | cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath));
|
---|
| 896 | return ERROR_FILENAME_EXCED_RANGE;
|
---|
| 897 | }
|
---|
| 898 |
|
---|
| 899 | /*
|
---|
| 900 | * Look for the share.
|
---|
| 901 | */
|
---|
| 902 | KernRequestSharedMutex(&g_MtxFolders);
|
---|
| 903 | PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName);
|
---|
| 904 | if (pFolder)
|
---|
| 905 | {
|
---|
| 906 | vboxSfOs2RetainFolder(pFolder);
|
---|
| 907 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 908 | }
|
---|
| 909 | else
|
---|
| 910 | {
|
---|
| 911 | uint32_t const uRevBefore = g_uFolderRevision;
|
---|
| 912 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 913 | rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder);
|
---|
| 914 | if (rc == NO_ERROR)
|
---|
| 915 | pFolder = *ppFolder;
|
---|
| 916 | else
|
---|
| 917 | return rc;
|
---|
| 918 | }
|
---|
| 919 |
|
---|
| 920 | /*
|
---|
| 921 | * Convert the path and put it in a Vbgl compatible buffer..
|
---|
| 922 | */
|
---|
| 923 | rc = vboxSfOs2ConvertPathEx(&pszFolderName[cchFolderName], offStrInBuf, ppvBuf);
|
---|
| 924 | if (rc == NO_ERROR)
|
---|
| 925 | return rc;
|
---|
| 926 |
|
---|
| 927 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
| 928 | *ppFolder = NULL;
|
---|
| 929 | return rc;
|
---|
| 930 | }
|
---|
| 931 |
|
---|
| 932 | LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
|
---|
| 933 | return ERROR_PATH_NOT_FOUND;
|
---|
| 934 | }
|
---|
| 935 |
|
---|
| 936 | /*
|
---|
| 937 | * Drive letter?
|
---|
| 938 | */
|
---|
| 939 | ch &= ~0x20; /* upper case */
|
---|
| 940 | if ( ch >= 'A'
|
---|
| 941 | && ch <= 'Z'
|
---|
| 942 | && pszPath[1] == ':')
|
---|
| 943 | {
|
---|
| 944 | unsigned iDrive = ch - 'A';
|
---|
| 945 | ch = pszPath[2];
|
---|
| 946 | if (ch == '\\' || ch == '/')
|
---|
| 947 | {
|
---|
| 948 | KernRequestSharedMutex(&g_MtxFolders);
|
---|
| 949 | PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive];
|
---|
| 950 | if (pFolder)
|
---|
| 951 | {
|
---|
| 952 | vboxSfOs2RetainFolder(pFolder);
|
---|
| 953 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 954 |
|
---|
| 955 | /*
|
---|
| 956 | * Convert the path and put it in a Vbgl compatible buffer..
|
---|
| 957 | */
|
---|
| 958 | rc = vboxSfOs2ConvertPathEx(&pszPath[3], offStrInBuf, ppvBuf);
|
---|
| 959 | if (rc == NO_ERROR)
|
---|
| 960 | return rc;
|
---|
| 961 |
|
---|
| 962 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
| 963 | *ppFolder = NULL;
|
---|
| 964 | return rc;
|
---|
| 965 | }
|
---|
| 966 | KernReleaseSharedMutex(&g_MtxFolders);
|
---|
| 967 | LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath));
|
---|
| 968 | return ERROR_PATH_NOT_FOUND;
|
---|
| 969 | }
|
---|
| 970 | LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath));
|
---|
| 971 | return ERROR_PATH_NOT_FOUND;
|
---|
| 972 | }
|
---|
| 973 | LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
|
---|
| 974 | RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd);
|
---|
| 975 | return ERROR_PATH_NOT_FOUND;
|
---|
| 976 | }
|
---|
| 977 |
|
---|
| 978 |
|
---|
[3655] | 979 | DECLASM(void)
|
---|
| 980 | FS32_EXIT(ULONG uid, ULONG pid, ULONG pdb)
|
---|
| 981 | {
|
---|
[75337] | 982 | LogFlow(("FS32_EXIT: uid=%u pid=%u pdb=%#x\n", uid, pid, pdb));
|
---|
[68612] | 983 | NOREF(uid); NOREF(pid); NOREF(pdb);
|
---|
[3655] | 984 | }
|
---|
| 985 |
|
---|
| 986 |
|
---|
[75337] | 987 | DECLASM(APIRET)
|
---|
| 988 | FS32_SHUTDOWN(ULONG uType, ULONG uReserved)
|
---|
[3655] | 989 | {
|
---|
[75337] | 990 | LogFlow(("FS32_SHUTDOWN: type=%u uReserved=%u\n", uType, uReserved));
|
---|
| 991 | NOREF(uType); NOREF(uReserved);
|
---|
[3655] | 992 | return NO_ERROR;
|
---|
| 993 | }
|
---|
| 994 |
|
---|
| 995 |
|
---|
[75337] | 996 | /**
|
---|
| 997 | * FS32_ATTACH worker: FS_ATTACH
|
---|
| 998 | */
|
---|
| 999 | static APIRET vboxSfOs2Attach(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam,
|
---|
| 1000 | PSHFLSTRING *ppCleanup)
|
---|
[3655] | 1001 | {
|
---|
[75337] | 1002 | /*
|
---|
| 1003 | * Check out the parameters, copying the pszParam into a suitable string buffer.
|
---|
| 1004 | */
|
---|
| 1005 | if (pszDev == NULL || !*pszDev || !RT_C_IS_ALPHA(pszDev[0]) || pszDev[1] != ':' || pszDev[2] != '\0')
|
---|
| 1006 | {
|
---|
| 1007 | LogRel(("vboxSfOs2Attach: Invalid pszDev value:%p:{%s}\n", pszDev, pszDev));
|
---|
| 1008 | return ERROR_INVALID_PARAMETER;
|
---|
| 1009 | }
|
---|
| 1010 | unsigned const iDrive = (pszDev[0] & ~0x20) - 'A';
|
---|
| 1011 |
|
---|
| 1012 | if (pszParam == NULL || pcbParam == NULL)
|
---|
| 1013 | {
|
---|
| 1014 | LogRel(("vboxSfOs2Attach: NULL parameter buffer or buffer length\n"));
|
---|
| 1015 | return ERROR_INVALID_PARAMETER;
|
---|
| 1016 | }
|
---|
| 1017 |
|
---|
| 1018 | PSHFLSTRING pStrName = *ppCleanup = vboxSfOs2StrAlloc(VBOXSFOS2_MAX_FOLDER_NAME - 1);
|
---|
| 1019 | pStrName->u16Length = *pcbParam;
|
---|
| 1020 | if (pStrName->u16Length < 1 || pStrName->u16Length > VBOXSFOS2_MAX_FOLDER_NAME)
|
---|
| 1021 | {
|
---|
| 1022 | LogRel(("vboxSfOs2Attach: Parameter buffer length is out of bounds: %u (min: 1, max " RT_XSTR(VBOXSFOS2_MAX_FOLDER_NAME) ")\n",
|
---|
| 1023 | pStrName->u16Length));
|
---|
| 1024 | return ERROR_INVALID_PARAMETER;
|
---|
| 1025 | }
|
---|
| 1026 |
|
---|
| 1027 | int rc = KernCopyIn(pStrName->String.utf8, pszParam, pStrName->u16Length);
|
---|
| 1028 | if (rc != NO_ERROR)
|
---|
| 1029 | return rc;
|
---|
| 1030 |
|
---|
| 1031 | pStrName->u16Length -= 1;
|
---|
| 1032 | if (pStrName->String.utf8[pStrName->u16Length] != '\0')
|
---|
| 1033 | {
|
---|
| 1034 | LogRel(("vboxSfOs2Attach: Parameter not null terminated\n"));
|
---|
| 1035 | return ERROR_INVALID_PARAMETER;
|
---|
| 1036 | }
|
---|
| 1037 |
|
---|
[75405] | 1038 | /* Make sure it's only ascii and contains not weird stuff.
|
---|
| 1039 | Note! There could be a 2nd tag string, so identify that one. */
|
---|
| 1040 | const char *pszTag = NULL;
|
---|
| 1041 | unsigned off = pStrName->u16Length;
|
---|
[75337] | 1042 | while (off-- > 0)
|
---|
| 1043 | {
|
---|
| 1044 | char const ch = pStrName->String.utf8[off];
|
---|
| 1045 | if (ch < 0x20 || ch >= 0x7f || ch == ':' || ch == '\\' || ch == '/')
|
---|
| 1046 | {
|
---|
[75405] | 1047 | if (ch == '\0' && !pszTag && off + 1 < pStrName->u16Length && off > 0)
|
---|
| 1048 | {
|
---|
| 1049 | pszTag = &pStrName->String.ach[off + 1];
|
---|
| 1050 | pStrName->u16Length = (uint16_t)off;
|
---|
| 1051 | }
|
---|
| 1052 | else
|
---|
| 1053 | {
|
---|
| 1054 | LogRel(("vboxSfOs2Attach: Malformed folder name: %.*Rhxs (off %#x)\n", pStrName->u16Length, pStrName->String.utf8, off));
|
---|
| 1055 | return ERROR_INVALID_PARAMETER;
|
---|
| 1056 | }
|
---|
[75337] | 1057 | }
|
---|
| 1058 | }
|
---|
| 1059 |
|
---|
[75405] | 1060 | /* Is there a tag following the name? */
|
---|
| 1061 |
|
---|
[75337] | 1062 | if (!pVpFsd)
|
---|
| 1063 | {
|
---|
| 1064 | LogRel(("vboxSfOs2Attach: pVpFsd is NULL\n"));
|
---|
| 1065 | return ERROR_INVALID_PARAMETER;
|
---|
| 1066 | }
|
---|
| 1067 |
|
---|
| 1068 | /*
|
---|
| 1069 | * Look for the folder to see if we're already using it. Map it if needed.
|
---|
| 1070 | */
|
---|
| 1071 | KernRequestExclusiveMutex(&g_MtxFolders);
|
---|
| 1072 | if (g_apDriveFolders[iDrive] == NULL)
|
---|
| 1073 | {
|
---|
| 1074 |
|
---|
| 1075 | PVBOXSFFOLDER pFolder = vboxSfOs2FindAndRetainFolder(pStrName->String.ach, pStrName->u16Length);
|
---|
| 1076 | if (!pFolder)
|
---|
| 1077 | {
|
---|
| 1078 | rc = vboxSfOs2EnsureConnected();
|
---|
| 1079 | if (RT_SUCCESS(rc))
|
---|
[75405] | 1080 | rc = vboxSfOs2MapFolder(pStrName, pszTag, &pFolder);
|
---|
[75337] | 1081 | }
|
---|
| 1082 | if (pFolder && RT_SUCCESS(rc))
|
---|
| 1083 | {
|
---|
| 1084 | pFolder->cDrives += 1;
|
---|
| 1085 | g_apDriveFolders[iDrive] = pFolder;
|
---|
| 1086 |
|
---|
| 1087 | pVpFsd->u32Magic = VBOXSFVP_MAGIC;
|
---|
| 1088 | pVpFsd->pFolder = pFolder;
|
---|
| 1089 |
|
---|
| 1090 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 1091 |
|
---|
| 1092 | LogRel(("vboxSfOs2Attach: Successfully attached '%s' to '%s'.\n", pFolder->szName, pszDev));
|
---|
| 1093 | return NO_ERROR;
|
---|
| 1094 | }
|
---|
| 1095 |
|
---|
| 1096 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 1097 | return ERROR_FILE_NOT_FOUND;
|
---|
| 1098 | }
|
---|
| 1099 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 1100 |
|
---|
| 1101 | LogRel(("vboxSfOs2Attach: Already got a folder on '%s'!\n", pszDev));
|
---|
| 1102 | RT_NOREF(pCdFsd);
|
---|
| 1103 | return ERROR_BUSY_DRIVE;
|
---|
| 1104 | }
|
---|
| 1105 |
|
---|
| 1106 |
|
---|
| 1107 | /**
|
---|
| 1108 | * FS32_ATTACH worker: FS_DETACH
|
---|
| 1109 | */
|
---|
| 1110 | static APIRET vboxSfOs2Detach(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam)
|
---|
| 1111 | {
|
---|
| 1112 | /*
|
---|
| 1113 | * Validate the volume data and assocated folder.
|
---|
| 1114 | */
|
---|
| 1115 | AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
|
---|
| 1116 | AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1117 | PVBOXSFFOLDER pFolder = pVpFsd->pFolder;
|
---|
| 1118 | AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
|
---|
| 1119 | AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1120 |
|
---|
| 1121 | uint8_t idxDrive = UINT8_MAX;
|
---|
| 1122 | if ( pszDev
|
---|
| 1123 | && RT_C_IS_ALPHA(*pszDev))
|
---|
| 1124 | idxDrive = (*pszDev & ~0x20) - 'A';
|
---|
| 1125 |
|
---|
| 1126 | /*
|
---|
| 1127 | * Can we detach it?
|
---|
| 1128 | */
|
---|
| 1129 | APIRET rc;
|
---|
| 1130 | KernRequestExclusiveMutex(&g_MtxFolders);
|
---|
| 1131 | if ( pFolder->cOpenFiles == 0
|
---|
| 1132 | && pFolder->cOpenSearches == 0)
|
---|
| 1133 | {
|
---|
| 1134 | /*
|
---|
| 1135 | * Check that we've got the right folder/drive combo.
|
---|
| 1136 | */
|
---|
| 1137 | if ( idxDrive < RT_ELEMENTS(g_apDriveFolders)
|
---|
| 1138 | && g_apDriveFolders[idxDrive] == pFolder)
|
---|
| 1139 | {
|
---|
| 1140 | g_apDriveFolders[idxDrive] = NULL;
|
---|
| 1141 | uint8_t cDrives = --pFolder->cDrives;
|
---|
| 1142 | AssertMsg(cDrives < 30, ("%#x\n", cDrives));
|
---|
| 1143 |
|
---|
| 1144 | uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
|
---|
| 1145 | AssertMsg(cRefs < _32K, ("%#x\n", cRefs));
|
---|
| 1146 | if (cRefs)
|
---|
| 1147 | {
|
---|
[75461] | 1148 | /* If there are now zero drives, unlink it from the list and release
|
---|
[75337] | 1149 | the list reference. This should almost always drop end up with us
|
---|
| 1150 | destroying the folder.*/
|
---|
| 1151 | if (cDrives == 0)
|
---|
| 1152 | {
|
---|
| 1153 | RTListNodeRemove(&pFolder->ListEntry);
|
---|
| 1154 | cRefs = ASMAtomicDecU32(&pFolder->cRefs);
|
---|
| 1155 | AssertMsg(cRefs < _32K, ("%#x\n", cRefs));
|
---|
| 1156 | if (!cRefs)
|
---|
| 1157 | vboxSfOs2DestroyFolder(pFolder);
|
---|
| 1158 | }
|
---|
| 1159 | }
|
---|
| 1160 | else
|
---|
| 1161 | {
|
---|
| 1162 | LogRel(("vboxSfOs2Detach: cRefs=0?!?\n"));
|
---|
| 1163 | vboxSfOs2DestroyFolder(pFolder);
|
---|
| 1164 | }
|
---|
[75461] | 1165 | rc = NO_ERROR;
|
---|
[75337] | 1166 | }
|
---|
| 1167 | else
|
---|
| 1168 | {
|
---|
| 1169 | LogRel(("vboxSfOs2Detach: g_apDriveFolders[%#x]=%p pFolder=%p\n",
|
---|
| 1170 | idxDrive, idxDrive < RT_ELEMENTS(g_apDriveFolders) ? g_apDriveFolders[idxDrive] : NULL, pFolder));
|
---|
| 1171 | rc = ERROR_NOT_SUPPORTED;
|
---|
| 1172 | }
|
---|
| 1173 | }
|
---|
| 1174 | else
|
---|
| 1175 | rc = ERROR_BUSY_DRIVE;
|
---|
| 1176 | KernReleaseExclusiveMutex(&g_MtxFolders);
|
---|
| 1177 |
|
---|
| 1178 | RT_NOREF(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
|
---|
| 1179 | return rc;
|
---|
| 1180 | }
|
---|
| 1181 |
|
---|
| 1182 |
|
---|
| 1183 | /**
|
---|
| 1184 | * FS32_ATTACH worker: FSA_ATTACH_INFO
|
---|
| 1185 | */
|
---|
| 1186 | static APIRET vboxSfOs2QueryAttachInfo(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pbData, PUSHORT pcbParam)
|
---|
| 1187 | {
|
---|
| 1188 | /*
|
---|
| 1189 | * Userland calls the kernel with a FSQBUFFER buffer, the kernel
|
---|
| 1190 | * fills in the first part of us and hands us &FSQBUFFER::cbFSAData
|
---|
| 1191 | * to do the rest. We could return the share name here, for instance.
|
---|
| 1192 | */
|
---|
| 1193 | APIRET rc;
|
---|
| 1194 | USHORT cbParam = *pcbParam;
|
---|
| 1195 | if ( pszDev == NULL
|
---|
| 1196 | || (pszDev[0] != '\\' && pszDev[0] != '/'))
|
---|
| 1197 | {
|
---|
| 1198 | /* Validate the volume data and assocated folder. */
|
---|
| 1199 | AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
|
---|
| 1200 | AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1201 | PVBOXSFFOLDER pFolder = pVpFsd->pFolder;
|
---|
| 1202 | AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
|
---|
| 1203 | AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1204 |
|
---|
| 1205 | /* Try copy out the data. */
|
---|
[75405] | 1206 | if (cbParam >= sizeof(USHORT) + pFolder->cbNameAndTag)
|
---|
[75337] | 1207 | {
|
---|
[75405] | 1208 | *pcbParam = (uint16_t)sizeof(USHORT) + pFolder->cbNameAndTag;
|
---|
[75337] | 1209 | cbParam = pFolder->cchName + 1;
|
---|
| 1210 | rc = KernCopyOut(pbData, &cbParam, sizeof(cbParam));
|
---|
[75471] | 1211 | if (rc == NO_ERROR)
|
---|
[75405] | 1212 | rc = KernCopyOut(pbData + sizeof(USHORT), pFolder->szName, pFolder->cbNameAndTag);
|
---|
[75337] | 1213 | }
|
---|
| 1214 | else
|
---|
| 1215 | rc = ERROR_BUFFER_OVERFLOW;
|
---|
| 1216 | }
|
---|
| 1217 | else
|
---|
| 1218 | {
|
---|
| 1219 | /* Looks like a device query, so return zero bytes. */
|
---|
| 1220 | if (cbParam >= sizeof(USHORT))
|
---|
| 1221 | {
|
---|
| 1222 | *pcbParam = sizeof(USHORT);
|
---|
| 1223 | cbParam = 0;
|
---|
| 1224 | rc = KernCopyOut(pbData, &cbParam, sizeof(cbParam));
|
---|
| 1225 | }
|
---|
| 1226 | else
|
---|
| 1227 | rc = ERROR_BUFFER_OVERFLOW;
|
---|
| 1228 | }
|
---|
| 1229 |
|
---|
| 1230 | RT_NOREF(pCdFsd);
|
---|
| 1231 | return rc;
|
---|
| 1232 | }
|
---|
| 1233 |
|
---|
| 1234 |
|
---|
| 1235 | DECLASM(APIRET)
|
---|
| 1236 | FS32_ATTACH(ULONG fFlags, PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam)
|
---|
| 1237 | {
|
---|
| 1238 | LogFlow(("FS32_ATTACH: fFlags=%#x pszDev=%p:{%s} pVpFsd=%p pCdFsd=%p pszParam=%p pcbParam=%p\n",
|
---|
| 1239 | fFlags, pszDev, pszDev, pVpFsd, pCdFsd, pszParam, pcbParam));
|
---|
| 1240 | APIRET rc;
|
---|
| 1241 | if (pVpFsd)
|
---|
| 1242 | {
|
---|
| 1243 | PSHFLSTRING pCleanup = NULL;
|
---|
| 1244 |
|
---|
| 1245 | if (fFlags == FS_ATTACH)
|
---|
| 1246 | rc = vboxSfOs2Attach(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam, &pCleanup);
|
---|
| 1247 | else if (fFlags == FSA_DETACH)
|
---|
| 1248 | rc = vboxSfOs2Detach(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
|
---|
| 1249 | else if (fFlags == FSA_ATTACH_INFO)
|
---|
| 1250 | rc = vboxSfOs2QueryAttachInfo(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
|
---|
| 1251 | else
|
---|
| 1252 | {
|
---|
| 1253 | LogRel(("FS32_ATTACH: Unsupported fFlags value: %#x\n", fFlags));
|
---|
| 1254 | rc = ERROR_NOT_SUPPORTED;
|
---|
| 1255 | }
|
---|
| 1256 |
|
---|
| 1257 | if (pCleanup)
|
---|
| 1258 | vboxSfOs2StrFree(pCleanup);
|
---|
| 1259 | }
|
---|
| 1260 | else
|
---|
| 1261 | rc = ERROR_NOT_SUPPORTED; /* We don't support device attaching. */
|
---|
| 1262 | LogFlow(("FS32_ATTACH: returns %u\n", rc));
|
---|
| 1263 | return rc;
|
---|
| 1264 | }
|
---|
| 1265 |
|
---|
| 1266 |
|
---|
| 1267 | DECLASM(APIRET)
|
---|
| 1268 | FS32_VERIFYUNCNAME(ULONG uType, PCSZ pszName)
|
---|
| 1269 | {
|
---|
| 1270 | LogFlow(("FS32_VERIFYUNCNAME: uType=%#x pszName=%p:{%s}\n", uType, pszName, pszName));
|
---|
| 1271 | RT_NOREF(uType); /* pass 1 or pass 2 doesn't matter to us, we've only got one 'server'. */
|
---|
| 1272 |
|
---|
[76108] | 1273 | if (vboxSfOs2UncPrefixLength(pszName) > 0)
|
---|
[75337] | 1274 | return NO_ERROR;
|
---|
[3655] | 1275 | return ERROR_NOT_SUPPORTED;
|
---|
| 1276 | }
|
---|
| 1277 |
|
---|
| 1278 |
|
---|
[75337] | 1279 | DECLASM(APIRET)
|
---|
[68612] | 1280 | FS32_FLUSHBUF(USHORT hVPB, ULONG fFlags)
|
---|
[3655] | 1281 | {
|
---|
[68612] | 1282 | NOREF(hVPB); NOREF(fFlags);
|
---|
[3655] | 1283 | return NO_ERROR;
|
---|
| 1284 | }
|
---|
| 1285 |
|
---|
| 1286 |
|
---|
[75337] | 1287 | DECLASM(APIRET)
|
---|
| 1288 | FS32_FSINFO(ULONG fFlags, USHORT hVpb, PBYTE pbData, ULONG cbData, ULONG uLevel)
|
---|
[3655] | 1289 | {
|
---|
[75337] | 1290 | LogFlow(("FS32_FSINFO: fFlags=%#x hVpb=%#x pbData=%p cbData=%#x uLevel=%p\n", fFlags, hVpb, pbData, cbData, uLevel));
|
---|
| 1291 |
|
---|
| 1292 | /*
|
---|
| 1293 | * Resolve hVpb and do parameter validation.
|
---|
| 1294 | */
|
---|
| 1295 | PVPFSI pVpFsi = NULL;
|
---|
| 1296 | PVBOXSFVP pVpFsd = Fsh32GetVolParams(hVpb, &pVpFsi);
|
---|
| 1297 | Log(("FS32_FSINFO: hVpb=%#x -> pVpFsd=%p pVpFsi=%p\n", hVpb, pVpFsd, pVpFsi));
|
---|
| 1298 |
|
---|
| 1299 | AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
|
---|
| 1300 | AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1301 | PVBOXSFFOLDER pFolder = pVpFsd->pFolder; /** @todo need to retain it behind locks. */
|
---|
| 1302 | AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
|
---|
| 1303 | AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
|
---|
| 1304 |
|
---|
| 1305 | APIRET rc;
|
---|
| 1306 |
|
---|
| 1307 | /*
|
---|
| 1308 | * Queries.
|
---|
| 1309 | */
|
---|
| 1310 | if (fFlags == INFO_RETREIVE)
|
---|
| 1311 | {
|
---|
| 1312 | /* Check that buffer/level matches up. */
|
---|
| 1313 | switch (uLevel)
|
---|
| 1314 | {
|
---|
| 1315 | case FSIL_ALLOC:
|
---|
| 1316 | if (cbData >= sizeof(FSALLOCATE))
|
---|
| 1317 | break;
|
---|
| 1318 | LogFlow(("FS32_FSINOF: cbData=%u < sizeof(FSALLOCATE) -> ERROR_BUFFER_OVERFLOW\n", cbData));
|
---|
| 1319 | return ERROR_BUFFER_OVERFLOW;
|
---|
| 1320 |
|
---|
| 1321 | case FSIL_VOLSER:
|
---|
| 1322 | if (cbData >= sizeof(FSINFO))
|
---|
| 1323 | break;
|
---|
| 1324 | LogFlow(("FS32_FSINOF: cbData=%u < sizeof(FSINFO) -> ERROR_BUFFER_OVERFLOW\n", cbData));
|
---|
| 1325 | return ERROR_BUFFER_OVERFLOW;
|
---|
| 1326 |
|
---|
| 1327 | default:
|
---|
| 1328 | LogRel(("FS32_FSINFO: Unsupported info level %u!\n", uLevel));
|
---|
| 1329 | return ERROR_INVALID_LEVEL;
|
---|
| 1330 | }
|
---|
| 1331 |
|
---|
| 1332 | /* Work buffer union to keep it to a single allocation and no stack. */
|
---|
| 1333 | union FsInfoBufs
|
---|
| 1334 | {
|
---|
| 1335 | struct
|
---|
| 1336 | {
|
---|
[76118] | 1337 | VBOXSFCREATEREQ Req;
|
---|
| 1338 | uint8_t PathStringSpace[4 * sizeof(RTUTF16)];
|
---|
[75337] | 1339 | } Open;
|
---|
| 1340 | struct
|
---|
| 1341 | {
|
---|
[76118] | 1342 | VBOXSFVOLINFOREQ Req;
|
---|
[75337] | 1343 | union
|
---|
| 1344 | {
|
---|
| 1345 | FSALLOCATE Alloc;
|
---|
| 1346 | FSINFO FsInfo;
|
---|
| 1347 | };
|
---|
| 1348 | } Info;
|
---|
[76118] | 1349 | VBOXSFCLOSEREQ Close;
|
---|
[75337] | 1350 | } *pu = (union FsInfoBufs *)VbglR0PhysHeapAlloc(sizeof(*pu));
|
---|
| 1351 | if (!pu)
|
---|
| 1352 | return ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 1353 |
|
---|
| 1354 | /*
|
---|
| 1355 | * To get the info we need to open the root of the folder.
|
---|
| 1356 | */
|
---|
[76118] | 1357 | RT_ZERO(pu->Open.Req);
|
---|
| 1358 | pu->Open.Req.CreateParms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACT_OPEN_IF_EXISTS
|
---|
| 1359 | | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
|
---|
| 1360 | pu->Open.Req.StrPath.u16Size = 3 * sizeof(RTUTF16);
|
---|
| 1361 | pu->Open.Req.StrPath.u16Length = 2 * sizeof(RTUTF16);
|
---|
| 1362 | pu->Open.Req.StrPath.String.utf16[0] = '\\';
|
---|
| 1363 | pu->Open.Req.StrPath.String.utf16[1] = '.';
|
---|
| 1364 | pu->Open.Req.StrPath.String.utf16[2] = '\0';
|
---|
[75337] | 1365 |
|
---|
[76716] | 1366 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, &pu->Open.Req);
|
---|
| 1367 | LogFlow(("FS32_FSINFO: VbglR0SfHostReqCreate -> %Rrc Result=%d Handle=%#RX64\n",
|
---|
[76118] | 1368 | vrc, pu->Open.Req.CreateParms.Result, pu->Open.Req.CreateParms.Handle));
|
---|
[75337] | 1369 | if ( RT_SUCCESS(vrc)
|
---|
[76118] | 1370 | && pu->Open.Req.CreateParms.Handle != SHFL_HANDLE_NIL)
|
---|
[75337] | 1371 | {
|
---|
[76143] | 1372 | SHFLHANDLE volatile hHandle = pu->Open.Req.CreateParms.Handle;
|
---|
[75337] | 1373 |
|
---|
[76118] | 1374 | RT_ZERO(pu->Info.Req);
|
---|
[76716] | 1375 | vrc = VbglR0SfHostReqQueryVolInfo(pFolder->idHostRoot, &pu->Info.Req, hHandle);
|
---|
[75337] | 1376 | if (RT_SUCCESS(vrc))
|
---|
| 1377 | {
|
---|
| 1378 | /*
|
---|
| 1379 | * Construct and copy out the requested info.
|
---|
| 1380 | */
|
---|
| 1381 | if (uLevel == FSIL_ALLOC)
|
---|
| 1382 | {
|
---|
| 1383 | pu->Info.Alloc.idFileSystem = 0; /* unknown */
|
---|
[76118] | 1384 | uint32_t const cbSector = RT_MAX(pu->Info.Req.VolInfo.ulBytesPerSector, 1);
|
---|
| 1385 | pu->Info.Alloc.cSectorUnit = pu->Info.Req.VolInfo.ulBytesPerAllocationUnit / cbSector;
|
---|
| 1386 | pu->Info.Alloc.cUnit = (uint32_t)(pu->Info.Req.VolInfo.ullTotalAllocationBytes / cbSector);
|
---|
| 1387 | pu->Info.Alloc.cUnitAvail = (uint32_t)(pu->Info.Req.VolInfo.ullAvailableAllocationBytes / cbSector);
|
---|
| 1388 | pu->Info.Alloc.cbSector = (uint16_t)pu->Info.Req.VolInfo.ulBytesPerSector;
|
---|
[75337] | 1389 | rc = KernCopyOut(pbData, &pu->Info.Alloc, sizeof(pu->Info.Alloc));
|
---|
| 1390 | }
|
---|
| 1391 | else
|
---|
| 1392 | {
|
---|
| 1393 | RT_ZERO(pu->Info.FsInfo);
|
---|
| 1394 | pu->Info.FsInfo.vol.cch = (uint8_t)RT_MIN(pFolder->cchName, sizeof(pu->Info.FsInfo.vol.szVolLabel) - 1);
|
---|
| 1395 | memcpy(pu->Info.FsInfo.vol.szVolLabel, pFolder->szName, pu->Info.FsInfo.vol.cch);
|
---|
[76118] | 1396 | *(uint32_t *)&pu->Info.FsInfo.fdateCreation = pu->Info.Req.VolInfo.ulSerial;
|
---|
[75337] | 1397 | rc = KernCopyOut(pbData, &pu->Info.FsInfo, sizeof(pu->Info.FsInfo));
|
---|
| 1398 | }
|
---|
| 1399 | }
|
---|
| 1400 | else
|
---|
| 1401 | {
|
---|
[76716] | 1402 | LogRel(("FS32_FSINFO: VbglR0SfHostReqQueryVolInfo failed: %Rrc\n", vrc));
|
---|
[75337] | 1403 | rc = ERROR_GEN_FAILURE;
|
---|
| 1404 | }
|
---|
| 1405 |
|
---|
[76716] | 1406 | vrc = VbglR0SfHostReqClose(pFolder->idHostRoot, &pu->Close, hHandle);
|
---|
[75337] | 1407 | AssertRC(vrc);
|
---|
| 1408 | }
|
---|
| 1409 | else
|
---|
| 1410 | rc = ERROR_GEN_FAILURE;
|
---|
| 1411 |
|
---|
| 1412 | VbglR0PhysHeapFree(pu);
|
---|
| 1413 | }
|
---|
| 1414 | /*
|
---|
| 1415 | * We don't allow setting anything.
|
---|
| 1416 | */
|
---|
| 1417 | else if (fFlags == INFO_SET)
|
---|
| 1418 | {
|
---|
| 1419 | LogRel(("FS32_FSINFO: Attempting to set volume info (uLevel=%u, cbData=%#x) -> ERROR_ACCESS_DENIED\n", uLevel, cbData));
|
---|
| 1420 | rc = ERROR_ACCESS_DENIED;
|
---|
| 1421 | }
|
---|
| 1422 | else
|
---|
| 1423 | {
|
---|
| 1424 | LogRel(("FS32_FSINFO: Unknown flags: %#x\n", fFlags));
|
---|
| 1425 | rc = ERROR_SYS_INTERNAL;
|
---|
| 1426 | }
|
---|
| 1427 |
|
---|
| 1428 | LogFlow(("FS32_FSINFO: returns %#x\n", rc));
|
---|
| 1429 | return rc;
|
---|
[3655] | 1430 | }
|
---|
| 1431 |
|
---|
| 1432 |
|
---|
[75337] | 1433 | DECLASM(APIRET)
|
---|
| 1434 | FS32_FSCTL(union argdat *pArgData, ULONG iArgType, ULONG uFunction,
|
---|
[68612] | 1435 | PVOID pvParm, USHORT cbParm, PUSHORT pcbParmIO,
|
---|
| 1436 | PVOID pvData, USHORT cbData, PUSHORT pcbDataIO)
|
---|
[3655] | 1437 | {
|
---|
[75337] | 1438 | LogFlow(("FS32_FSCTL: pArgData=%p iArgType=%#x uFunction=%#x pvParam=%p cbParam=%#x pcbParmIO=%p pvData=%p cbData=%#x pcbDataIO=%p\n",
|
---|
| 1439 | pArgData, iArgType, uFunction, pvParm, cbParm, pcbParmIO, pvData, cbData, pcbDataIO));
|
---|
| 1440 | NOREF(pArgData); NOREF(iArgType); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
|
---|
[68612] | 1441 | NOREF(pvData); NOREF(cbData); NOREF(pcbDataIO);
|
---|
[3655] | 1442 | return ERROR_NOT_SUPPORTED;
|
---|
| 1443 | }
|
---|
| 1444 |
|
---|
| 1445 |
|
---|
[75337] | 1446 | DECLASM(APIRET)
|
---|
[3655] | 1447 | FS32_PROCESSNAME(PSZ pszName)
|
---|
| 1448 | {
|
---|
[75337] | 1449 | LogFlow(("FS32_PROCESSNAME: '%s'\n", pszName));
|
---|
[68612] | 1450 | NOREF(pszName);
|
---|
[3655] | 1451 | return NO_ERROR;
|
---|
| 1452 | }
|
---|
| 1453 |
|
---|
| 1454 |
|
---|
[75337] | 1455 | DECLASM(APIRET)
|
---|
| 1456 | FS32_CHDIR(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd)
|
---|
[3655] | 1457 | {
|
---|
[75337] | 1458 | LogFlow(("FS32_CHDIR: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszDir=%p:{%s} offCurDirEnd=%d\n",
|
---|
| 1459 | fFlags, pCdFsi, pCdFsi ? pCdFsi->cdi_hVPB : 0xffff, pCdFsi ? pCdFsi->cdi_curdir : "", pCdFsd, pszDir, pszDir, offCurDirEnd));
|
---|
| 1460 |
|
---|
| 1461 | /*
|
---|
| 1462 | * We do not keep any information about open directory, just verify
|
---|
| 1463 | * them before they are CD'ed into and when asked to revalidate them.
|
---|
| 1464 | * If there were any path walking benefits, we could consider opening the
|
---|
| 1465 | * directory and keeping it open, but there isn't, so we don't do that.
|
---|
| 1466 | */
|
---|
| 1467 | APIRET rc = NO_ERROR;
|
---|
| 1468 | if ( fFlags == CD_EXPLICIT
|
---|
| 1469 | || fFlags == CD_VERIFY)
|
---|
| 1470 | {
|
---|
| 1471 | if (fFlags == CD_VERIFY)
|
---|
| 1472 | pszDir = pCdFsi->cdi_curdir;
|
---|
| 1473 |
|
---|
[76121] | 1474 | PVBOXSFFOLDER pFolder;
|
---|
| 1475 | VBOXSFCREATEREQ *pReq;
|
---|
| 1476 | rc = vboxSfOs2ResolvePathEx(pszDir, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
|
---|
| 1477 | &pFolder, (void **)&pReq);
|
---|
[75337] | 1478 | if (rc == NO_ERROR)
|
---|
| 1479 | {
|
---|
[76121] | 1480 | pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP;
|
---|
| 1481 |
|
---|
[76716] | 1482 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 1483 | LogFlow(("FS32_CHDIR: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
|
---|
[76121] | 1484 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1485 | if (RT_SUCCESS(vrc))
|
---|
[75337] | 1486 | {
|
---|
[76121] | 1487 | switch (pReq->CreateParms.Result)
|
---|
[75337] | 1488 | {
|
---|
[76121] | 1489 | case SHFL_FILE_EXISTS:
|
---|
| 1490 | if (RTFS_IS_DIRECTORY(pReq->CreateParms.Info.Attr.fMode))
|
---|
| 1491 | rc = NO_ERROR;
|
---|
| 1492 | else
|
---|
| 1493 | rc = ERROR_ACCESS_DENIED;
|
---|
| 1494 | break;
|
---|
[75337] | 1495 |
|
---|
[76121] | 1496 | case SHFL_PATH_NOT_FOUND:
|
---|
| 1497 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 1498 | break;
|
---|
[75337] | 1499 |
|
---|
[76121] | 1500 | default:
|
---|
| 1501 | case SHFL_FILE_NOT_FOUND:
|
---|
| 1502 | rc = ERROR_FILE_NOT_FOUND;
|
---|
| 1503 | break;
|
---|
[75337] | 1504 | }
|
---|
| 1505 | }
|
---|
| 1506 | else
|
---|
[76121] | 1507 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
|
---|
[75337] | 1508 | }
|
---|
[76121] | 1509 |
|
---|
| 1510 | VbglR0PhysHeapFree(pReq);
|
---|
| 1511 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 1512 | }
|
---|
| 1513 | else if (fFlags == CD_FREE)
|
---|
| 1514 | {
|
---|
| 1515 | /* nothing to do here. */
|
---|
| 1516 | }
|
---|
| 1517 | else
|
---|
| 1518 | {
|
---|
| 1519 | LogRel(("FS32_CHDIR: Unexpected fFlags value: %#x\n", fFlags));
|
---|
| 1520 | rc = ERROR_NOT_SUPPORTED;
|
---|
| 1521 | }
|
---|
| 1522 |
|
---|
| 1523 | LogFlow(("FS32_CHDIR: returns %u\n", rc));
|
---|
| 1524 | return rc;
|
---|
[3655] | 1525 | }
|
---|
| 1526 |
|
---|
| 1527 |
|
---|
[75337] | 1528 | DECLASM(APIRET)
|
---|
| 1529 | FS32_MKDIR(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd, PEAOP pEaOp, ULONG fFlags)
|
---|
[3655] | 1530 | {
|
---|
[75337] | 1531 | LogFlow(("FS32_MKDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} pEAOp=%p fFlags=%#x\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd, pEaOp, fFlags));
|
---|
[76108] | 1532 | RT_NOREF(fFlags);
|
---|
[75337] | 1533 |
|
---|
| 1534 | /*
|
---|
| 1535 | * We don't do EAs.
|
---|
| 1536 | */
|
---|
| 1537 | APIRET rc;
|
---|
| 1538 | if (pEaOp == NULL)
|
---|
[79112] | 1539 | rc = NO_ERROR;
|
---|
| 1540 | else
|
---|
| 1541 | rc = vboxSfOs2CheckEaOpForCreation(pEaOp);
|
---|
| 1542 | if (rc == NO_ERROR)
|
---|
[75337] | 1543 | {
|
---|
| 1544 | /*
|
---|
| 1545 | * Resolve the path.
|
---|
| 1546 | */
|
---|
[76121] | 1547 | PVBOXSFFOLDER pFolder;
|
---|
| 1548 | VBOXSFCREATEREQ *pReq;
|
---|
| 1549 | rc = vboxSfOs2ResolvePathEx(pszDir, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
|
---|
| 1550 | &pFolder, (void **)&pReq);
|
---|
[75337] | 1551 | if (rc == NO_ERROR)
|
---|
| 1552 | {
|
---|
| 1553 | /*
|
---|
| 1554 | * The silly interface for creating directories amounts an open call that
|
---|
| 1555 | * fails if it exists and we get a file handle back that needs closing. Sigh.
|
---|
| 1556 | */
|
---|
[76121] | 1557 | pReq->CreateParms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW | SHFL_CF_ACT_FAIL_IF_EXISTS
|
---|
| 1558 | | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_DENYNONE;
|
---|
| 1559 |
|
---|
[76716] | 1560 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 1561 | LogFlow(("FS32_MKDIR: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
|
---|
[76121] | 1562 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1563 | if (RT_SUCCESS(vrc))
|
---|
[75337] | 1564 | {
|
---|
[76121] | 1565 | switch (pReq->CreateParms.Result)
|
---|
[75337] | 1566 | {
|
---|
[76121] | 1567 | case SHFL_FILE_CREATED:
|
---|
| 1568 | if (pReq->CreateParms.Handle != SHFL_HANDLE_NIL)
|
---|
| 1569 | {
|
---|
| 1570 | AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
|
---|
[76716] | 1571 | vrc = VbglR0SfHostReqClose(pFolder->idHostRoot, (VBOXSFCLOSEREQ *)pReq, pReq->CreateParms.Handle);
|
---|
[76121] | 1572 | AssertRC(vrc);
|
---|
| 1573 | }
|
---|
| 1574 | rc = NO_ERROR;
|
---|
| 1575 | break;
|
---|
[75337] | 1576 |
|
---|
[76121] | 1577 | case SHFL_FILE_EXISTS:
|
---|
| 1578 | rc = ERROR_ACCESS_DENIED;
|
---|
| 1579 | break;
|
---|
[75337] | 1580 |
|
---|
[76121] | 1581 | case SHFL_PATH_NOT_FOUND:
|
---|
| 1582 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 1583 | break;
|
---|
[75337] | 1584 |
|
---|
[76121] | 1585 | default:
|
---|
| 1586 | case SHFL_FILE_NOT_FOUND:
|
---|
| 1587 | rc = ERROR_FILE_NOT_FOUND;
|
---|
| 1588 | break;
|
---|
[75337] | 1589 | }
|
---|
| 1590 | }
|
---|
[76121] | 1591 | else if (vrc == VERR_ALREADY_EXISTS)
|
---|
| 1592 | rc = ERROR_ACCESS_DENIED;
|
---|
[75337] | 1593 | else
|
---|
[76121] | 1594 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
|
---|
| 1595 |
|
---|
| 1596 | VbglR0PhysHeapFree(pReq);
|
---|
| 1597 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 1598 | }
|
---|
| 1599 | }
|
---|
| 1600 | else
|
---|
[79112] | 1601 | Log(("FS32_MKDIR: EA trouble %p: %u%s\n", pEaOp, rc, rc == ERROR_EAS_NOT_SUPPORTED ? " (ERROR_EAS_NOT_SUPPORTED)" : ""));
|
---|
[75337] | 1602 |
|
---|
| 1603 | RT_NOREF_PV(pCdFsi);
|
---|
[77661] | 1604 | LogFlow(("FS32_MMDIR: returns %u\n", rc));
|
---|
[75337] | 1605 | return rc;
|
---|
[3655] | 1606 | }
|
---|
| 1607 |
|
---|
| 1608 |
|
---|
[75337] | 1609 | DECLASM(APIRET)
|
---|
| 1610 | FS32_RMDIR(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd)
|
---|
[3655] | 1611 | {
|
---|
[75337] | 1612 | LogFlow(("FS32_RMDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} offCurDirEnd=%d\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd));
|
---|
| 1613 |
|
---|
| 1614 | /*
|
---|
| 1615 | * Resolve the path.
|
---|
| 1616 | */
|
---|
| 1617 | PVBOXSFFOLDER pFolder;
|
---|
[76143] | 1618 | VBOXSFREMOVEREQ *pReq;
|
---|
| 1619 | APIRET rc = vboxSfOs2ResolvePathEx(pszDir, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath),
|
---|
| 1620 | &pFolder, (void **)&pReq);
|
---|
[75337] | 1621 | if (rc == NO_ERROR)
|
---|
| 1622 | {
|
---|
[76716] | 1623 | int vrc = VbglR0SfHostReqRemove(pFolder->idHostRoot, pReq, SHFL_REMOVE_DIR);
|
---|
[77661] | 1624 | LogFlow(("FS32_RMDIR: VbglR0SfHostReqRemove -> %Rrc\n", vrc));
|
---|
[75337] | 1625 | if (RT_SUCCESS(vrc))
|
---|
| 1626 | rc = NO_ERROR;
|
---|
| 1627 | else
|
---|
| 1628 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
|
---|
| 1629 |
|
---|
[76143] | 1630 | VbglR0PhysHeapFree(pReq);
|
---|
| 1631 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 1632 | }
|
---|
| 1633 |
|
---|
| 1634 | RT_NOREF_PV(pCdFsi);
|
---|
| 1635 | LogFlow(("FS32_RMDIR: returns %u\n", rc));
|
---|
| 1636 | return rc;
|
---|
[3655] | 1637 | }
|
---|
| 1638 |
|
---|
| 1639 |
|
---|
[75337] | 1640 | DECLASM(APIRET)
|
---|
| 1641 | FS32_COPY(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszSrc, LONG offSrcCurDirEnd,
|
---|
| 1642 | PCSZ pszDst, LONG offDstCurDirEnd, ULONG uNameType)
|
---|
[3655] | 1643 | {
|
---|
[75337] | 1644 | LogFlow(("FS32_COPY: fFlags=%#x pCdFsi=%p pCdFsd=%p pszSrc=%p:{%s} offSrcCurDirEnd=%d pszDst=%p:{%s} offDstCurDirEnd=%d uNameType=%#x\n",
|
---|
| 1645 | fFlags, pCdFsi, pCdFsd, pszSrc, pszSrc, offSrcCurDirEnd, pszDst, pszDst, offDstCurDirEnd, uNameType));
|
---|
| 1646 | NOREF(fFlags); NOREF(pCdFsi); NOREF(pCdFsd); NOREF(pszSrc); NOREF(offSrcCurDirEnd);
|
---|
| 1647 | NOREF(pszDst); NOREF(offDstCurDirEnd); NOREF(uNameType);
|
---|
| 1648 |
|
---|
| 1649 | /* Let DOSCALL1.DLL do the work for us till we get a host side function for doing this. */
|
---|
| 1650 | return ERROR_CANNOT_COPY;
|
---|
[3655] | 1651 | }
|
---|
| 1652 |
|
---|
| 1653 |
|
---|
[75337] | 1654 | DECLASM(APIRET)
|
---|
| 1655 | FS32_MOVE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszSrc, LONG offSrcCurDirEnd, PCSZ pszDst, LONG offDstCurDirEnd, ULONG uNameType)
|
---|
[3655] | 1656 | {
|
---|
[75337] | 1657 | LogFlow(("FS32_MOVE: pCdFsi=%p pCdFsd=%p pszSrc=%p:{%s} offSrcCurDirEnd=%d pszDst=%p:{%s} offDstcurDirEnd=%d uNameType=%#x\n",
|
---|
| 1658 | pCdFsi, pCdFsd, pszSrc, pszSrc, offSrcCurDirEnd, pszDst, pszDst, offDstCurDirEnd, uNameType));
|
---|
| 1659 |
|
---|
| 1660 | /*
|
---|
| 1661 | * Resolve the source and destination paths and check that they
|
---|
| 1662 | * refer to the same folder.
|
---|
| 1663 | */
|
---|
| 1664 | PVBOXSFFOLDER pSrcFolder;
|
---|
| 1665 | PSHFLSTRING pSrcFolderPath;
|
---|
| 1666 | APIRET rc = vboxSfOs2ResolvePath(pszSrc, pCdFsd, offSrcCurDirEnd, &pSrcFolder, &pSrcFolderPath);
|
---|
| 1667 | if (rc == NO_ERROR)
|
---|
| 1668 | {
|
---|
[76143] | 1669 | PVBOXSFFOLDER pDstFolder;
|
---|
| 1670 | VBOXSFRENAMEWITHSRCBUFREQ *pReq;
|
---|
| 1671 | rc = vboxSfOs2ResolvePathEx(pszDst, pCdFsd, offDstCurDirEnd, RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, StrDstPath),
|
---|
| 1672 | &pDstFolder, (void **)&pReq);
|
---|
[75337] | 1673 | if (rc == NO_ERROR)
|
---|
| 1674 | {
|
---|
| 1675 | if (pSrcFolder == pDstFolder)
|
---|
| 1676 | {
|
---|
| 1677 | /*
|
---|
| 1678 | * Do the renaming.
|
---|
| 1679 | * Note! Requires 6.0.0beta2+ or 5.2.24+ host for renaming files.
|
---|
| 1680 | */
|
---|
[76716] | 1681 | int vrc = VbglR0SfHostReqRenameWithSrcBuf(pSrcFolder->idHostRoot, pReq, pSrcFolderPath,
|
---|
| 1682 | SHFL_RENAME_FILE | SHFL_RENAME_DIR);
|
---|
[75337] | 1683 | if (RT_SUCCESS(vrc))
|
---|
| 1684 | rc = NO_ERROR;
|
---|
| 1685 | else
|
---|
| 1686 | {
|
---|
[76716] | 1687 | Log(("FS32_MOVE: VbglR0SfHostReqRenameWithSrcBuf failed: %Rrc\n", rc));
|
---|
[75337] | 1688 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
|
---|
| 1689 | }
|
---|
| 1690 | }
|
---|
| 1691 | else
|
---|
| 1692 | {
|
---|
[76143] | 1693 | Log(("FS32_MOVE: source folder '%s' != destiation folder '%s'\n", pszSrc, pszDst));
|
---|
[75337] | 1694 | rc = ERROR_NOT_SAME_DEVICE;
|
---|
| 1695 | }
|
---|
[76143] | 1696 | VbglR0PhysHeapFree(pReq);
|
---|
| 1697 | vboxSfOs2ReleaseFolder(pDstFolder);
|
---|
[75337] | 1698 | }
|
---|
| 1699 | vboxSfOs2ReleasePathAndFolder(pSrcFolderPath, pSrcFolder);
|
---|
| 1700 | }
|
---|
| 1701 |
|
---|
| 1702 | RT_NOREF_PV(pCdFsi); RT_NOREF_PV(uNameType);
|
---|
| 1703 | return rc;
|
---|
[3655] | 1704 | }
|
---|
| 1705 |
|
---|
| 1706 |
|
---|
[75337] | 1707 | DECLASM(APIRET)
|
---|
| 1708 | FS32_DELETE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszFile, LONG offCurDirEnd)
|
---|
[3655] | 1709 | {
|
---|
[75337] | 1710 | LogFlow(("FS32_DELETE: pCdFsi=%p pCdFsd=%p pszFile=%p:{%s} offCurDirEnd=%d\n", pCdFsi, pCdFsd, pszFile, pszFile, offCurDirEnd));
|
---|
| 1711 |
|
---|
| 1712 | /*
|
---|
| 1713 | * Resolve the path.
|
---|
| 1714 | */
|
---|
[76143] | 1715 | PVBOXSFFOLDER pFolder;
|
---|
| 1716 | VBOXSFREMOVEREQ *pReq;
|
---|
| 1717 | APIRET rc = vboxSfOs2ResolvePathEx(pszFile, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath),
|
---|
| 1718 | &pFolder, (void **)&pReq);
|
---|
[75337] | 1719 | if (rc == NO_ERROR)
|
---|
| 1720 | {
|
---|
[76716] | 1721 | int vrc = VbglR0SfHostReqRemove(pFolder->idHostRoot, pReq, SHFL_REMOVE_FILE);
|
---|
[77661] | 1722 | LogFlow(("FS32_DELETE: VbglR0SfHostReqRemove -> %Rrc\n", vrc));
|
---|
[75337] | 1723 | if (RT_SUCCESS(vrc))
|
---|
| 1724 | rc = NO_ERROR;
|
---|
[76126] | 1725 | else
|
---|
[75337] | 1726 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
|
---|
| 1727 |
|
---|
[76143] | 1728 | VbglR0PhysHeapFree(pReq);
|
---|
| 1729 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 1730 | }
|
---|
| 1731 |
|
---|
| 1732 | RT_NOREF_PV(pCdFsi);
|
---|
| 1733 | LogFlow(("FS32_DELETE: returns %u\n", rc));
|
---|
| 1734 | return rc;
|
---|
[3655] | 1735 | }
|
---|
| 1736 |
|
---|
| 1737 |
|
---|
[75337] | 1738 |
|
---|
| 1739 | /**
|
---|
| 1740 | * Worker for FS32_PATHINFO that handles file stat setting.
|
---|
| 1741 | *
|
---|
| 1742 | * @returns OS/2 status code
|
---|
[76143] | 1743 | * @param pFolder The folder.
|
---|
| 1744 | * @param hHostFile The host file handle.
|
---|
| 1745 | * @param fAttribs The attributes to set.
|
---|
| 1746 | * @param pTimestamps Pointer to the timestamps. NULL if none should be
|
---|
| 1747 | * modified.
|
---|
| 1748 | * @param pObjInfoBuf Buffer to use when setting the attributes (host
|
---|
| 1749 | * will return current info upon successful
|
---|
| 1750 | * return). This must life on the phys heap.
|
---|
| 1751 | * @param offObjInfoInAlloc Offset of pObjInfoBuf in the phys heap
|
---|
| 1752 | * allocation where it lives.
|
---|
[75337] | 1753 | */
|
---|
| 1754 | APIRET vboxSfOs2SetInfoCommonWorker(PVBOXSFFOLDER pFolder, SHFLHANDLE hHostFile, ULONG fAttribs,
|
---|
[76143] | 1755 | PFILESTATUS pTimestamps, PSHFLFSOBJINFO pObjInfoBuf, uint32_t offObjInfoInAlloc)
|
---|
[3655] | 1756 | {
|
---|
[75337] | 1757 | /*
|
---|
| 1758 | * Validate the data a little and convert it to host speak.
|
---|
| 1759 | * When the date part is zero, the timestamp should not be updated.
|
---|
| 1760 | */
|
---|
| 1761 | RT_ZERO(*pObjInfoBuf);
|
---|
| 1762 | uint16_t cDelta = vboxSfOs2GetLocalTimeDelta();
|
---|
| 1763 |
|
---|
| 1764 | /** @todo should we validate attributes? */
|
---|
| 1765 | pObjInfoBuf->Attr.fMode = (fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
|
---|
[77661] | 1766 | if (pObjInfoBuf->Attr.fMode == 0)
|
---|
| 1767 | pObjInfoBuf->Attr.fMode |= RTFS_DOS_NT_NORMAL;
|
---|
[75337] | 1768 |
|
---|
| 1769 | if (pTimestamps)
|
---|
| 1770 | {
|
---|
| 1771 | if ( *(uint16_t *)&pTimestamps->fdateCreation != 0
|
---|
| 1772 | && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateCreation, pTimestamps->ftimeCreation, cDelta, &pObjInfoBuf->BirthTime))
|
---|
| 1773 | {
|
---|
| 1774 | LogRel(("vboxSfOs2SetInfoCommonWorker: Bad creation timestamp: %u-%u-%u %u:%u:%u\n",
|
---|
| 1775 | pTimestamps->fdateCreation.year + 1980, pTimestamps->fdateCreation.month, pTimestamps->fdateCreation.day,
|
---|
| 1776 | pTimestamps->ftimeCreation.hours, pTimestamps->ftimeCreation.minutes, pTimestamps->ftimeCreation.twosecs * 2));
|
---|
| 1777 | return ERROR_INVALID_PARAMETER;
|
---|
| 1778 | }
|
---|
| 1779 | if ( *(uint16_t *)&pTimestamps->fdateLastAccess != 0
|
---|
| 1780 | && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateLastAccess, pTimestamps->ftimeLastAccess, cDelta, &pObjInfoBuf->AccessTime))
|
---|
| 1781 | {
|
---|
| 1782 | LogRel(("vboxSfOs2SetInfoCommonWorker: Bad last access timestamp: %u-%u-%u %u:%u:%u\n",
|
---|
| 1783 | pTimestamps->fdateLastAccess.year + 1980, pTimestamps->fdateLastAccess.month, pTimestamps->fdateLastAccess.day,
|
---|
| 1784 | pTimestamps->ftimeLastAccess.hours, pTimestamps->ftimeLastAccess.minutes, pTimestamps->ftimeLastAccess.twosecs * 2));
|
---|
| 1785 | return ERROR_INVALID_PARAMETER;
|
---|
| 1786 | }
|
---|
| 1787 | if ( *(uint16_t *)&pTimestamps->fdateLastWrite != 0
|
---|
| 1788 | && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateLastWrite, pTimestamps->ftimeLastWrite, cDelta, &pObjInfoBuf->ModificationTime))
|
---|
| 1789 | {
|
---|
| 1790 | LogRel(("vboxSfOs2SetInfoCommonWorker: Bad last access timestamp: %u-%u-%u %u:%u:%u\n",
|
---|
| 1791 | pTimestamps->fdateLastWrite.year + 1980, pTimestamps->fdateLastWrite.month, pTimestamps->fdateLastWrite.day,
|
---|
| 1792 | pTimestamps->ftimeLastWrite.hours, pTimestamps->ftimeLastWrite.minutes, pTimestamps->ftimeLastWrite.twosecs * 2));
|
---|
| 1793 | return ERROR_INVALID_PARAMETER;
|
---|
| 1794 | }
|
---|
| 1795 | }
|
---|
| 1796 |
|
---|
| 1797 | /*
|
---|
| 1798 | * Call the host to do the updating.
|
---|
| 1799 | */
|
---|
[76143] | 1800 | VBOXSFOBJINFOWITHBUFREQ *pReq = (VBOXSFOBJINFOWITHBUFREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
|
---|
| 1801 | if (pReq)
|
---|
| 1802 | {
|
---|
[76716] | 1803 | int vrc = VbglR0SfHostReqSetObjInfoWithBuf(pFolder->idHostRoot, pReq, hHostFile, pObjInfoBuf, offObjInfoInAlloc);
|
---|
| 1804 | LogFlow(("vboxSfOs2SetFileInfo: VbglR0SfHostReqSetObjInfoWithBuf -> %Rrc\n", vrc));
|
---|
[75337] | 1805 |
|
---|
[76143] | 1806 | VbglR0PhysHeapFree(pReq);
|
---|
| 1807 | if (RT_SUCCESS(vrc))
|
---|
| 1808 | return NO_ERROR;
|
---|
| 1809 | return vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
|
---|
| 1810 | }
|
---|
| 1811 | return ERROR_NOT_ENOUGH_MEMORY;
|
---|
[3655] | 1812 | }
|
---|
| 1813 |
|
---|
| 1814 |
|
---|
[75337] | 1815 | /**
|
---|
| 1816 | * Worker for FS32_FILEATTRIBUTE and FS32_PATHINFO that handles setting stuff.
|
---|
| 1817 | *
|
---|
| 1818 | * @returns OS/2 status code.
|
---|
| 1819 | * @param pFolder The folder.
|
---|
[76126] | 1820 | * @param pReq Open/create request buffer with path.
|
---|
[75337] | 1821 | * @param fAttribs New file attributes.
|
---|
| 1822 | * @param pTimestamps New timestamps. May be NULL.
|
---|
| 1823 | */
|
---|
[76126] | 1824 | static APIRET vboxSfOs2SetPathInfoWorker(PVBOXSFFOLDER pFolder, VBOXSFCREATEREQ *pReq, ULONG fAttribs, PFILESTATUS pTimestamps)
|
---|
[75337] | 1825 |
|
---|
[3655] | 1826 | {
|
---|
[75337] | 1827 | /*
|
---|
| 1828 | * In order to do anything we need to open the object.
|
---|
| 1829 | */
|
---|
| 1830 | APIRET rc;
|
---|
[76126] | 1831 | pReq->CreateParms.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW
|
---|
| 1832 | | SHFL_CF_ACCESS_ATTR_READWRITE | SHFL_CF_ACCESS_DENYNONE | SHFL_CF_ACCESS_NONE;
|
---|
| 1833 |
|
---|
[76716] | 1834 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 1835 | LogFlow(("vboxSfOs2SetPathInfoWorker: VbglR0SfHostReqCreate -> %Rrc Result=%d Handle=%#RX64 fMode=%#x\n",
|
---|
[76126] | 1836 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Handle, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1837 | if ( vrc == VERR_IS_A_DIRECTORY
|
---|
| 1838 | || ( RT_SUCCESS(vrc)
|
---|
| 1839 | && pReq->CreateParms.Handle == SHFL_HANDLE_NIL
|
---|
| 1840 | && RTFS_IS_DIRECTORY(pReq->CreateParms.Info.Attr.fMode)))
|
---|
[75337] | 1841 | {
|
---|
[76126] | 1842 | RT_ZERO(pReq->CreateParms);
|
---|
| 1843 | pReq->CreateParms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW
|
---|
| 1844 | | SHFL_CF_ACCESS_ATTR_READWRITE | SHFL_CF_ACCESS_DENYNONE | SHFL_CF_ACCESS_NONE;
|
---|
[76716] | 1845 | vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 1846 | LogFlow(("vboxSfOs2SetPathInfoWorker: VbglR0SfHostReqCreate#2 -> %Rrc Result=%d Handle=%#RX64 fMode=%#x\n",
|
---|
[76126] | 1847 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Handle, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1848 | }
|
---|
| 1849 | if (RT_SUCCESS(vrc))
|
---|
| 1850 | {
|
---|
| 1851 | switch (pReq->CreateParms.Result)
|
---|
[75337] | 1852 | {
|
---|
[76126] | 1853 | case SHFL_FILE_EXISTS:
|
---|
| 1854 | if (pReq->CreateParms.Handle != SHFL_HANDLE_NIL)
|
---|
| 1855 | {
|
---|
| 1856 | /*
|
---|
| 1857 | * Join up with FS32_FILEINFO to do the actual setting.
|
---|
| 1858 | */
|
---|
| 1859 | rc = vboxSfOs2SetInfoCommonWorker(pFolder, pReq->CreateParms.Handle, fAttribs, pTimestamps,
|
---|
[76143] | 1860 | &pReq->CreateParms.Info, RT_UOFFSETOF(VBOXSFCREATEREQ, CreateParms.Info));
|
---|
[75337] | 1861 |
|
---|
[76143] | 1862 | AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
|
---|
[76716] | 1863 | vrc = VbglR0SfHostReqClose(pFolder->idHostRoot, (VBOXSFCLOSEREQ *)pReq, pReq->CreateParms.Handle);
|
---|
[76126] | 1864 | AssertRC(vrc);
|
---|
| 1865 | }
|
---|
| 1866 | else
|
---|
| 1867 | {
|
---|
| 1868 | LogRel(("vboxSfOs2SetPathInfoWorker: No handle! fMode=%#x\n", pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1869 | rc = ERROR_SYS_INTERNAL;
|
---|
| 1870 | }
|
---|
| 1871 | break;
|
---|
[75337] | 1872 |
|
---|
[76126] | 1873 | case SHFL_PATH_NOT_FOUND:
|
---|
| 1874 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 1875 | break;
|
---|
| 1876 |
|
---|
| 1877 | default:
|
---|
| 1878 | case SHFL_FILE_NOT_FOUND:
|
---|
| 1879 | rc = ERROR_FILE_NOT_FOUND;
|
---|
| 1880 | break;
|
---|
[75337] | 1881 | }
|
---|
| 1882 | }
|
---|
| 1883 | else
|
---|
[76126] | 1884 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
|
---|
[75337] | 1885 | return rc;
|
---|
| 1886 | }
|
---|
| 1887 |
|
---|
| 1888 |
|
---|
| 1889 | DECLASM(APIRET)
|
---|
| 1890 | FS32_FILEATTRIBUTE(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszName, LONG offCurDirEnd, PUSHORT pfAttr)
|
---|
| 1891 | {
|
---|
[77661] | 1892 | LogFlow(("FS32_FILEATTRIBUTE: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pfAttr=%p={%#x}\n",
|
---|
| 1893 | fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszName, pszName, offCurDirEnd, pfAttr, *pfAttr));
|
---|
[76108] | 1894 | RT_NOREF(pCdFsi, offCurDirEnd);
|
---|
[75337] | 1895 |
|
---|
| 1896 | APIRET rc;
|
---|
| 1897 | if ( fFlags == FA_RETRIEVE
|
---|
| 1898 | || fFlags == FA_SET)
|
---|
| 1899 | {
|
---|
[76126] | 1900 | /* Both setting and querying needs to make a create request. */
|
---|
| 1901 | PVBOXSFFOLDER pFolder;
|
---|
| 1902 | VBOXSFCREATEREQ *pReq;
|
---|
| 1903 | rc = vboxSfOs2ResolvePathEx(pszName, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
|
---|
| 1904 | &pFolder, (void **)&pReq);
|
---|
[75337] | 1905 | if (rc == NO_ERROR)
|
---|
| 1906 | {
|
---|
| 1907 | if (fFlags == FA_RETRIEVE)
|
---|
| 1908 | {
|
---|
| 1909 | /*
|
---|
| 1910 | * Query it.
|
---|
| 1911 | */
|
---|
[76126] | 1912 | pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP;
|
---|
| 1913 |
|
---|
[76716] | 1914 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 1915 | LogFlow(("FS32_FILEATTRIBUTE: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
|
---|
[76126] | 1916 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 1917 | if (RT_SUCCESS(vrc))
|
---|
[75337] | 1918 | {
|
---|
[76126] | 1919 | switch (pReq->CreateParms.Result)
|
---|
[75337] | 1920 | {
|
---|
[76126] | 1921 | case SHFL_FILE_EXISTS:
|
---|
| 1922 | *pfAttr = (uint16_t)((pReq->CreateParms.Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
|
---|
| 1923 | rc = NO_ERROR;
|
---|
| 1924 | break;
|
---|
[75337] | 1925 |
|
---|
[76126] | 1926 | case SHFL_PATH_NOT_FOUND:
|
---|
| 1927 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 1928 | break;
|
---|
[75337] | 1929 |
|
---|
[76126] | 1930 | default:
|
---|
| 1931 | case SHFL_FILE_NOT_FOUND:
|
---|
| 1932 | rc = ERROR_FILE_NOT_FOUND;
|
---|
| 1933 | break;
|
---|
[75337] | 1934 | }
|
---|
| 1935 | }
|
---|
| 1936 | else
|
---|
[76126] | 1937 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
|
---|
[75337] | 1938 | }
|
---|
| 1939 | else
|
---|
| 1940 | {
|
---|
| 1941 | /*
|
---|
| 1942 | * Set the info. Join paths with FS32_PATHINFO.
|
---|
| 1943 | */
|
---|
[76126] | 1944 | rc = vboxSfOs2SetPathInfoWorker(pFolder, pReq, *pfAttr, NULL);
|
---|
[75337] | 1945 | }
|
---|
[76126] | 1946 | VbglR0PhysHeapFree(pReq);
|
---|
| 1947 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 1948 | }
|
---|
| 1949 | }
|
---|
| 1950 | else
|
---|
| 1951 | {
|
---|
| 1952 | LogRel(("FS32_FILEATTRIBUTE: Unknwon flag value: %#x\n", fFlags));
|
---|
| 1953 | rc = ERROR_NOT_SUPPORTED;
|
---|
| 1954 | }
|
---|
| 1955 | LogFlow(("FS32_FILEATTRIBUTE: returns %u\n", rc));
|
---|
| 1956 | return rc;
|
---|
| 1957 | }
|
---|
| 1958 |
|
---|
| 1959 |
|
---|
| 1960 | /**
|
---|
| 1961 | * Creates an empty full EA list given a GEALIST and info level.
|
---|
| 1962 | *
|
---|
| 1963 | * @returns OS/2 status code.
|
---|
| 1964 | * @param pEaOp Kernel copy of the EA request with flattened pointers.
|
---|
| 1965 | * @param uLevel The info level being queried.
|
---|
[93071] | 1966 | * @param cbFullEasLeft The size of the full EA buffer, ~(ULONG)0 if it
|
---|
| 1967 | * should be read in from pEaOp->fpFEAList->cbList.
|
---|
[75337] | 1968 | * @param pcbWritten Where to return the length of the resulting list. Optional.
|
---|
| 1969 | * @param poffError User buffer address of EAOP.oError for reporting GEALIST issues.
|
---|
| 1970 | */
|
---|
[93071] | 1971 | APIRET vboxSfOs2MakeEmptyEaListEx(PEAOP pEaOp, ULONG uLevel, ULONG cbFullEasLeft, uint32_t *pcbWritten, ULONG *poffError)
|
---|
[75337] | 1972 | {
|
---|
| 1973 | ULONG cbDstList;
|
---|
| 1974 | APIRET rc;
|
---|
| 1975 |
|
---|
| 1976 | /*
|
---|
| 1977 | * Levels 8 and 5 are simple.
|
---|
| 1978 | */
|
---|
| 1979 | if ( pEaOp->fpGEAList == NULL
|
---|
| 1980 | || uLevel == FI_LVL_EAS_FULL_8
|
---|
| 1981 | || uLevel == FI_LVL_EAS_FULL_5)
|
---|
| 1982 | {
|
---|
| 1983 | Log2(("vboxSfOs2MakeEmptyEaList: #1\n"));
|
---|
| 1984 | cbDstList = RT_UOFFSET_AFTER(FEALIST, cbList);
|
---|
| 1985 | rc = NO_ERROR;
|
---|
| 1986 | }
|
---|
| 1987 | /*
|
---|
| 1988 | * For levels 3 and 4 we have to do work when a request list is present.
|
---|
| 1989 | */
|
---|
| 1990 | else
|
---|
| 1991 | {
|
---|
| 1992 | ULONG cbGetEasLeft = 0;
|
---|
| 1993 | rc = KernCopyIn(&cbGetEasLeft, &pEaOp->fpGEAList->cbList, sizeof(pEaOp->fpGEAList->cbList));
|
---|
[93071] | 1994 | if (rc == NO_ERROR && cbFullEasLeft == ~(ULONG)0)
|
---|
[75337] | 1995 | rc = KernCopyIn(&cbFullEasLeft, &pEaOp->fpFEAList->cbList, sizeof(cbFullEasLeft));
|
---|
| 1996 | if ( rc == NO_ERROR
|
---|
| 1997 | && cbGetEasLeft >= sizeof(pEaOp->fpGEAList->cbList)
|
---|
| 1998 | && cbFullEasLeft >= sizeof(pEaOp->fpFEAList->cbList))
|
---|
| 1999 | {
|
---|
| 2000 | cbGetEasLeft -= sizeof(pEaOp->fpGEAList->cbList);
|
---|
| 2001 | cbFullEasLeft -= sizeof(pEaOp->fpFEAList->cbList);
|
---|
| 2002 |
|
---|
| 2003 | char *pszNameBuf = (char *)RTMemAlloc(256 + 1);
|
---|
| 2004 | if (!pszNameBuf)
|
---|
| 2005 | return ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 2006 | /* Start of no-return zone. */
|
---|
| 2007 |
|
---|
| 2008 | uint8_t const *pbSrc = (uint8_t const *)&pEaOp->fpGEAList->list[0]; /* user buffer! */
|
---|
| 2009 | uint8_t *pbDst = (uint8_t *)&pEaOp->fpFEAList->list[0]; /* user buffer! */
|
---|
| 2010 | Log2(("vboxSfOs2MakeEmptyEaList: %p LB %#x -> %p LB %#x...\n", pbSrc, cbGetEasLeft, pbDst, cbFullEasLeft));
|
---|
| 2011 | while (cbGetEasLeft > 0)
|
---|
| 2012 | {
|
---|
| 2013 | /*
|
---|
| 2014 | * pbSrc: GEA: BYTE cbName; char szName[];
|
---|
| 2015 | */
|
---|
[93071] | 2016 | /* Get name length (we call it cchName instead of cbName since
|
---|
| 2017 | it does not include the zero terminator). */
|
---|
| 2018 | uint8_t cchName = 0;
|
---|
| 2019 | rc = KernCopyIn(&cchName, pbSrc, sizeof(cchName));
|
---|
| 2020 | Log3(("vboxSfOs2MakeEmptyEaList: cchName=%#x rc=%u\n", cchName, rc));
|
---|
[75337] | 2021 | if (rc != NO_ERROR)
|
---|
| 2022 | break;
|
---|
| 2023 | pbSrc++;
|
---|
| 2024 | cbGetEasLeft--;
|
---|
[93071] | 2025 | if (cchName + 1U > cbGetEasLeft)
|
---|
[75337] | 2026 | {
|
---|
| 2027 | cbDstList = pbSrc - 1 - (uint8_t *)pEaOp->fpGEAList;
|
---|
| 2028 | rc = KernCopyOut(poffError, &cbDstList, sizeof(pEaOp->oError));
|
---|
| 2029 | if (rc == NO_ERROR)
|
---|
| 2030 | rc = ERROR_EA_LIST_INCONSISTENT;
|
---|
| 2031 | Log(("vboxSfOs2MakeEmptyEaList: ERROR_EA_LIST_INCONSISTENT\n"));
|
---|
| 2032 | break;
|
---|
| 2033 | }
|
---|
| 2034 |
|
---|
| 2035 | /* Copy in name. */
|
---|
[93071] | 2036 | rc = KernCopyIn(pszNameBuf, pbSrc, cchName + 1);
|
---|
[75337] | 2037 | if (rc != NO_ERROR)
|
---|
| 2038 | break;
|
---|
[93071] | 2039 | Log3(("vboxSfOs2MakeEmptyEaList: szName: %.*Rhxs\n", cchName + 1, pszNameBuf));
|
---|
| 2040 | if ((char *)memchr(pszNameBuf, '\0', cchName + 1) != &pszNameBuf[cchName])
|
---|
[75337] | 2041 | {
|
---|
| 2042 | cbDstList = pbSrc - 1 - (uint8_t *)pEaOp->fpGEAList;
|
---|
| 2043 | rc = KernCopyOut(poffError, &cbDstList, sizeof(pEaOp->oError));
|
---|
| 2044 | if (rc == NO_ERROR)
|
---|
| 2045 | rc = ERROR_INVALID_EA_NAME;
|
---|
| 2046 | Log(("vboxSfOs2MakeEmptyEaList: ERROR_INVALID_EA_NAME\n"));
|
---|
| 2047 | break;
|
---|
| 2048 | }
|
---|
| 2049 |
|
---|
| 2050 | /* Skip input. */
|
---|
[93071] | 2051 | cbGetEasLeft -= cchName + 1;
|
---|
| 2052 | pbSrc += cchName + 1;
|
---|
[75337] | 2053 |
|
---|
| 2054 | /*
|
---|
| 2055 | * Construct and emit output.
|
---|
| 2056 | * Note! We should technically skip duplicates here, but who cares...
|
---|
| 2057 | */
|
---|
[93071] | 2058 | if (cchName > 0)
|
---|
[75337] | 2059 | {
|
---|
| 2060 | FEA Result;
|
---|
[93071] | 2061 | if (sizeof(Result) + cchName + 1 <= cbFullEasLeft)
|
---|
| 2062 | cbFullEasLeft -= sizeof(Result) + cchName + 1;
|
---|
| 2063 | else
|
---|
[75337] | 2064 | {
|
---|
[93071] | 2065 | Log(("vboxSfOs2MakeEmptyEaList: ERROR_BUFFER_OVERFLOW (%#x vs %#x)\n", sizeof(Result) + cchName + 1, cbFullEasLeft));
|
---|
[75337] | 2066 | rc = ERROR_BUFFER_OVERFLOW;
|
---|
| 2067 | break;
|
---|
| 2068 | }
|
---|
| 2069 |
|
---|
| 2070 | Result.fEA = 0;
|
---|
[93071] | 2071 | Result.cbName = cchName;
|
---|
[75337] | 2072 | Result.cbValue = 0;
|
---|
| 2073 | rc = KernCopyOut(pbDst, &Result, sizeof(Result));
|
---|
| 2074 | if (rc != NO_ERROR)
|
---|
| 2075 | break;
|
---|
| 2076 | pbDst += sizeof(Result);
|
---|
| 2077 |
|
---|
[93071] | 2078 | rc = KernCopyOut(pbDst, pszNameBuf, cchName + 1);
|
---|
[75337] | 2079 | if (rc != NO_ERROR)
|
---|
| 2080 | break;
|
---|
[93071] | 2081 | pbDst += cchName + 1;
|
---|
[75337] | 2082 | }
|
---|
| 2083 | } /* (while more GEAs) */
|
---|
| 2084 |
|
---|
| 2085 | /* End of no-return zone. */
|
---|
| 2086 | RTMemFree(pszNameBuf);
|
---|
| 2087 |
|
---|
| 2088 | cbDstList = (uintptr_t)pbDst - (uintptr_t)pEaOp->fpFEAList;
|
---|
| 2089 | }
|
---|
| 2090 | else
|
---|
| 2091 | {
|
---|
| 2092 | if (rc == NO_ERROR)
|
---|
| 2093 | rc = ERROR_BUFFER_OVERFLOW;
|
---|
| 2094 | cbDstList = 0; /* oh, shut up. */
|
---|
| 2095 | }
|
---|
| 2096 |
|
---|
| 2097 | }
|
---|
| 2098 |
|
---|
| 2099 | /* Set the list length. */
|
---|
| 2100 | if (rc == NO_ERROR)
|
---|
| 2101 | rc = KernCopyOut(&pEaOp->fpFEAList->cbList, &cbDstList, sizeof(pEaOp->fpFEAList->cbList));
|
---|
| 2102 |
|
---|
| 2103 | if (pcbWritten)
|
---|
| 2104 | *pcbWritten = cbDstList;
|
---|
| 2105 |
|
---|
| 2106 | Log(("vboxSfOs2MakeEmptyEaList: return %u (cbDstList=%#x)\n", rc, cbDstList));
|
---|
| 2107 | return rc;
|
---|
| 2108 | }
|
---|
| 2109 |
|
---|
| 2110 |
|
---|
| 2111 |
|
---|
| 2112 | /**
|
---|
| 2113 | * Creates an empty full EA list given a GEALIST and info level.
|
---|
| 2114 | *
|
---|
| 2115 | * @returns OS/2 status code.
|
---|
| 2116 | * @param pEaOp The EA request. User buffer.
|
---|
| 2117 | * @param uLevel The info level being queried.
|
---|
| 2118 | */
|
---|
| 2119 | DECL_NO_INLINE(RT_NOTHING, APIRET)
|
---|
| 2120 | vboxSfOs2MakeEmptyEaList(PEAOP pEaOp, ULONG uLevel)
|
---|
| 2121 | {
|
---|
| 2122 | /*
|
---|
| 2123 | * Copy the user request into memory, do pointer conversion, and
|
---|
| 2124 | * join extended function version.
|
---|
| 2125 | */
|
---|
| 2126 | EAOP EaOp = { NULL, NULL, 0 };
|
---|
| 2127 | APIRET rc = KernCopyIn(&EaOp, pEaOp, sizeof(EaOp));
|
---|
| 2128 | if (rc == NO_ERROR)
|
---|
| 2129 | {
|
---|
| 2130 | Log2(("vboxSfOs2MakeEmptyEaList: #0: %p %p %#x\n", EaOp.fpGEAList, EaOp.fpFEAList, EaOp.oError));
|
---|
| 2131 | EaOp.fpFEAList = (PFEALIST)KernSelToFlat((uintptr_t)EaOp.fpFEAList);
|
---|
[79110] | 2132 | if ( uLevel != FI_LVL_EAS_FULL
|
---|
| 2133 | && uLevel != FI_LVL_EAS_FULL_5
|
---|
| 2134 | && uLevel != FI_LVL_EAS_FULL_8)
|
---|
| 2135 | EaOp.fpGEAList = (PGEALIST)KernSelToFlat((uintptr_t)EaOp.fpGEAList);
|
---|
| 2136 | else
|
---|
| 2137 | EaOp.fpGEAList = NULL;
|
---|
[75337] | 2138 | Log2(("vboxSfOs2MakeEmptyEaList: #0b: %p %p\n", EaOp.fpGEAList, EaOp.fpFEAList));
|
---|
| 2139 |
|
---|
[93071] | 2140 | rc = vboxSfOs2MakeEmptyEaListEx(&EaOp, uLevel, ~(ULONG)0, NULL, &pEaOp->oError);
|
---|
[75337] | 2141 | }
|
---|
| 2142 | return rc;
|
---|
| 2143 | }
|
---|
| 2144 |
|
---|
| 2145 |
|
---|
| 2146 | /**
|
---|
| 2147 | * Corrects the case of the given path.
|
---|
| 2148 | *
|
---|
| 2149 | * @returns OS/2 status code
|
---|
| 2150 | * @param pFolder The folder.
|
---|
[76126] | 2151 | * @param pReq Open/create request buffer with folder path.
|
---|
[75337] | 2152 | * @param pszPath The original path for figuring the drive letter or
|
---|
| 2153 | * UNC part of the path.
|
---|
| 2154 | * @param pbData Where to return the data (user address).
|
---|
| 2155 | * @param cbData The maximum amount of data we can return.
|
---|
| 2156 | */
|
---|
[77661] | 2157 | static APIRET vboxSfOs2QueryCorrectCase(PVBOXSFFOLDER pFolder, VBOXSFCREATEREQ *pReq, const char *pszPath,
|
---|
| 2158 | PBYTE pbData, ULONG cbData)
|
---|
[75337] | 2159 | {
|
---|
[77661] | 2160 | RT_NOREF(pFolder, pReq);
|
---|
| 2161 | APIRET rc;
|
---|
| 2162 | size_t cchPath = RTStrNLen(pszPath, CCHMAXPATH + 1);
|
---|
| 2163 | if (cchPath <= CCHMAXPATH)
|
---|
| 2164 | {
|
---|
| 2165 | if (cbData > cchPath)
|
---|
| 2166 | {
|
---|
| 2167 | /** @todo implement this properly on the host side! */
|
---|
| 2168 | rc = KernCopyOut(pbData, pszPath, cbData + 1);
|
---|
| 2169 | LogFlow(("vboxSfOs2QueryCorrectCase: returns %u\n", rc));
|
---|
| 2170 | }
|
---|
| 2171 | else
|
---|
| 2172 | {
|
---|
| 2173 | LogFlow(("vboxSfOs2QueryCorrectCase: returns %u (ERROR_INSUFFICIENT_BUFFER) - cchPath=%#x cbData=%#x\n",
|
---|
| 2174 | ERROR_INSUFFICIENT_BUFFER, cchPath, cbData));
|
---|
| 2175 | rc = ERROR_INSUFFICIENT_BUFFER;
|
---|
| 2176 | }
|
---|
| 2177 | }
|
---|
| 2178 | else
|
---|
| 2179 | {
|
---|
| 2180 | LogFlow(("vboxSfOs2QueryCorrectCase: returns %u (ERROR_FILENAME_EXCED_RANGE)\n", ERROR_FILENAME_EXCED_RANGE));
|
---|
| 2181 | rc = ERROR_FILENAME_EXCED_RANGE;
|
---|
| 2182 | }
|
---|
| 2183 | return rc;
|
---|
[3655] | 2184 | }
|
---|
| 2185 |
|
---|
| 2186 |
|
---|
[75337] | 2187 | /**
|
---|
| 2188 | * Copy out file status info.
|
---|
| 2189 | *
|
---|
| 2190 | * @returns OS/2 status code.
|
---|
| 2191 | * @param pbDst User address to put the status info at.
|
---|
| 2192 | * @param cbDst The size of the structure to produce.
|
---|
| 2193 | * @param uLevel The info level of the structure to produce.
|
---|
| 2194 | * @param pSrc The shared folder FS object info source structure.
|
---|
| 2195 | * @note Careful with stack, thus no-inlining.
|
---|
| 2196 | */
|
---|
| 2197 | DECL_NO_INLINE(RT_NOTHING, APIRET)
|
---|
| 2198 | vboxSfOs2FileStatusFromObjInfo(PBYTE pbDst, ULONG cbDst, ULONG uLevel, SHFLFSOBJINFO const *pSrc)
|
---|
[3655] | 2199 | {
|
---|
[75337] | 2200 | union
|
---|
| 2201 | {
|
---|
| 2202 | FILESTATUS Fst;
|
---|
| 2203 | FILESTATUS2 Fst2;
|
---|
| 2204 | FILESTATUS3L Fst3L;
|
---|
| 2205 | FILESTATUS4L Fst4L;
|
---|
| 2206 | } uTmp;
|
---|
| 2207 |
|
---|
| 2208 | int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
|
---|
| 2209 | vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateCreation, &uTmp.Fst.ftimeCreation, pSrc->BirthTime, cMinLocalTimeDelta);
|
---|
| 2210 | vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateLastAccess, &uTmp.Fst.ftimeLastAccess, pSrc->AccessTime, cMinLocalTimeDelta);
|
---|
| 2211 | vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateLastWrite, &uTmp.Fst.ftimeLastWrite, pSrc->ModificationTime, cMinLocalTimeDelta);
|
---|
| 2212 | if (uLevel < FI_LVL_STANDARD_64)
|
---|
| 2213 | {
|
---|
| 2214 | uTmp.Fst.cbFile = (uint32_t)RT_MIN(pSrc->cbObject, UINT32_MAX);
|
---|
| 2215 | uTmp.Fst.cbFileAlloc = (uint32_t)RT_MIN(pSrc->cbAllocated, UINT32_MAX);
|
---|
| 2216 | uTmp.Fst.attrFile = (uint16_t)((pSrc->Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
|
---|
| 2217 | if (uLevel == FI_LVL_STANDARD_EASIZE)
|
---|
| 2218 | uTmp.Fst2.cbList = 0;
|
---|
| 2219 | }
|
---|
| 2220 | else
|
---|
| 2221 | {
|
---|
| 2222 | uTmp.Fst3L.cbFile = pSrc->cbObject;
|
---|
| 2223 | uTmp.Fst3L.cbFileAlloc = pSrc->cbAllocated;
|
---|
| 2224 | uTmp.Fst3L.attrFile = (pSrc->Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT;
|
---|
| 2225 | uTmp.Fst4L.cbList = 0;
|
---|
| 2226 | }
|
---|
| 2227 |
|
---|
| 2228 | return KernCopyOut(pbDst, &uTmp, cbDst);
|
---|
| 2229 | }
|
---|
| 2230 |
|
---|
| 2231 |
|
---|
| 2232 |
|
---|
| 2233 | /**
|
---|
| 2234 | * Worker for FS32_PATHINFO that handles file stat queries.
|
---|
| 2235 | *
|
---|
| 2236 | * @returns OS/2 status code
|
---|
| 2237 | * @param pFolder The folder.
|
---|
[76126] | 2238 | * @param pReq Open/create request buffer with folder path.
|
---|
[75337] | 2239 | * @param uLevel The information level.
|
---|
| 2240 | * @param pbData Where to return the data (user address).
|
---|
| 2241 | * @param cbData The amount of data to produce.
|
---|
| 2242 | */
|
---|
[76126] | 2243 | static APIRET vboxSfOs2QueryPathInfo(PVBOXSFFOLDER pFolder, VBOXSFCREATEREQ *pReq, ULONG uLevel, PBYTE pbData, ULONG cbData)
|
---|
[75337] | 2244 | {
|
---|
| 2245 | APIRET rc;
|
---|
[76126] | 2246 | pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP;
|
---|
| 2247 |
|
---|
[76716] | 2248 | int vrc = VbglR0SfHostReqCreate(pFolder->idHostRoot, pReq);
|
---|
| 2249 | LogFlow(("FS32_PATHINFO: VbglR0SfHostReqCreate -> %Rrc Result=%d fMode=%#x\n",
|
---|
[76126] | 2250 | vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
|
---|
| 2251 | if (RT_SUCCESS(vrc))
|
---|
[75337] | 2252 | {
|
---|
[76126] | 2253 | switch (pReq->CreateParms.Result)
|
---|
[75337] | 2254 | {
|
---|
[76126] | 2255 | case SHFL_FILE_EXISTS:
|
---|
| 2256 | switch (uLevel)
|
---|
| 2257 | {
|
---|
| 2258 | /*
|
---|
| 2259 | * Produce the desired file stat data.
|
---|
| 2260 | */
|
---|
| 2261 | case FI_LVL_STANDARD:
|
---|
| 2262 | case FI_LVL_STANDARD_EASIZE:
|
---|
| 2263 | case FI_LVL_STANDARD_64:
|
---|
| 2264 | case FI_LVL_STANDARD_EASIZE_64:
|
---|
| 2265 | rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, &pReq->CreateParms.Info);
|
---|
| 2266 | break;
|
---|
[75337] | 2267 |
|
---|
[76126] | 2268 | /*
|
---|
| 2269 | * We don't do EAs and we "just" need to return no-EAs.
|
---|
| 2270 | * However, that's not as easy as you might think.
|
---|
| 2271 | */
|
---|
| 2272 | case FI_LVL_EAS_FROM_LIST:
|
---|
| 2273 | case FI_LVL_EAS_FULL:
|
---|
| 2274 | case FI_LVL_EAS_FULL_5:
|
---|
| 2275 | case FI_LVL_EAS_FULL_8:
|
---|
| 2276 | rc = vboxSfOs2MakeEmptyEaList((PEAOP)pbData, uLevel);
|
---|
| 2277 | break;
|
---|
[75337] | 2278 |
|
---|
[76126] | 2279 | default:
|
---|
| 2280 | AssertFailed();
|
---|
| 2281 | rc = ERROR_GEN_FAILURE;
|
---|
| 2282 | break;
|
---|
| 2283 | }
|
---|
| 2284 | break;
|
---|
[75337] | 2285 |
|
---|
[76126] | 2286 | case SHFL_PATH_NOT_FOUND:
|
---|
| 2287 | rc = ERROR_PATH_NOT_FOUND;
|
---|
| 2288 | break;
|
---|
[75337] | 2289 |
|
---|
[76126] | 2290 | default:
|
---|
| 2291 | case SHFL_FILE_NOT_FOUND:
|
---|
| 2292 | rc = ERROR_FILE_NOT_FOUND;
|
---|
| 2293 | break;
|
---|
[75337] | 2294 | }
|
---|
| 2295 | }
|
---|
| 2296 | else
|
---|
[76126] | 2297 | rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
|
---|
[75337] | 2298 | return rc;
|
---|
| 2299 | }
|
---|
| 2300 |
|
---|
| 2301 |
|
---|
| 2302 | DECLASM(APIRET)
|
---|
| 2303 | FS32_PATHINFO(USHORT fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszPath, LONG offCurDirEnd,
|
---|
| 2304 | ULONG uLevel, PBYTE pbData, ULONG cbData)
|
---|
| 2305 | {
|
---|
| 2306 | LogFlow(("FS32_PATHINFO: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszPath=%p:{%s} offCurDirEnd=%d uLevel=%u pbData=%p cbData=%#x\n",
|
---|
| 2307 | fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszPath, pszPath, offCurDirEnd, uLevel, pbData, cbData));
|
---|
| 2308 |
|
---|
| 2309 | /*
|
---|
| 2310 | * Check the level.
|
---|
| 2311 | *
|
---|
| 2312 | * Note! You would think this is FIL_STANDARD, FIL_QUERYEASIZE,
|
---|
| 2313 | * FIL_QUERYEASFROMLISTL and such. However, there are several levels
|
---|
| 2314 | * (4/14, 6/16, 7/17, 8/18) that are not defined in os2.h and then
|
---|
| 2315 | * there and FIL_QUERYFULLNAME that is used very between the kernel
|
---|
| 2316 | * and the FSD so the kernel can implement DosEnumAttributes.
|
---|
| 2317 | *
|
---|
| 2318 | * Note! DOSCALL1.DLL has code for converting FILESTATUS to FILESTATUS3
|
---|
| 2319 | * and FILESTATUS2 to FILESTATUS4 as needed. We don't need to do this.
|
---|
| 2320 | * It also has weird code for doubling the FILESTATUS2.cbList value
|
---|
| 2321 | * for no apparent reason.
|
---|
| 2322 | */
|
---|
| 2323 | ULONG cbMinData;
|
---|
| 2324 | switch (uLevel)
|
---|
| 2325 | {
|
---|
| 2326 | case FI_LVL_STANDARD:
|
---|
| 2327 | cbMinData = sizeof(FILESTATUS);
|
---|
| 2328 | AssertCompileSize(FILESTATUS, 0x16);
|
---|
| 2329 | break;
|
---|
| 2330 | case FI_LVL_STANDARD_64:
|
---|
| 2331 | cbMinData = sizeof(FILESTATUS3L);
|
---|
| 2332 | AssertCompileSize(FILESTATUS3L, 0x20); /* cbFile and cbFileAlloc are misaligned. */
|
---|
| 2333 | break;
|
---|
| 2334 | case FI_LVL_STANDARD_EASIZE:
|
---|
| 2335 | cbMinData = sizeof(FILESTATUS2);
|
---|
| 2336 | AssertCompileSize(FILESTATUS2, 0x1a);
|
---|
| 2337 | break;
|
---|
| 2338 | case FI_LVL_STANDARD_EASIZE_64:
|
---|
| 2339 | cbMinData = sizeof(FILESTATUS4L);
|
---|
| 2340 | AssertCompileSize(FILESTATUS4L, 0x24); /* cbFile and cbFileAlloc are misaligned. */
|
---|
| 2341 | break;
|
---|
| 2342 | case FI_LVL_EAS_FROM_LIST:
|
---|
| 2343 | case FI_LVL_EAS_FULL:
|
---|
| 2344 | case FI_LVL_EAS_FULL_5:
|
---|
| 2345 | case FI_LVL_EAS_FULL_8:
|
---|
| 2346 | cbMinData = sizeof(EAOP);
|
---|
| 2347 | break;
|
---|
| 2348 | case FI_LVL_VERIFY_PATH:
|
---|
| 2349 | case FI_LVL_CASE_CORRECT_PATH:
|
---|
| 2350 | cbMinData = 1;
|
---|
| 2351 | break;
|
---|
| 2352 | default:
|
---|
| 2353 | LogRel(("FS32_PATHINFO: Unsupported info level %u!\n", uLevel));
|
---|
| 2354 | return ERROR_INVALID_LEVEL;
|
---|
| 2355 | }
|
---|
| 2356 | if (cbData < cbMinData || pbData == NULL)
|
---|
| 2357 | {
|
---|
| 2358 | Log(("FS32_PATHINFO: ERROR_BUFFER_OVERFLOW (cbMinData=%#x, cbData=%#x, pszPath=%s)\n", cbMinData, cbData, pszPath));
|
---|
| 2359 | return ERROR_BUFFER_OVERFLOW;
|
---|
| 2360 | }
|
---|
| 2361 |
|
---|
| 2362 | /*
|
---|
| 2363 | * Resolve the path to a folder and folder path.
|
---|
| 2364 | */
|
---|
[76126] | 2365 | PVBOXSFFOLDER pFolder;
|
---|
| 2366 | VBOXSFCREATEREQ *pReq;
|
---|
| 2367 | int rc = vboxSfOs2ResolvePathEx(pszPath, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
|
---|
| 2368 | &pFolder, (void **)&pReq);
|
---|
[75337] | 2369 | if (rc == NO_ERROR)
|
---|
| 2370 | {
|
---|
| 2371 | /*
|
---|
| 2372 | * Query information.
|
---|
| 2373 | */
|
---|
| 2374 | if (fFlags == PI_RETRIEVE)
|
---|
| 2375 | {
|
---|
| 2376 | if ( uLevel != FI_LVL_VERIFY_PATH
|
---|
| 2377 | && uLevel != FI_LVL_CASE_CORRECT_PATH)
|
---|
[76126] | 2378 | rc = vboxSfOs2QueryPathInfo(pFolder, pReq, uLevel, pbData, cbMinData);
|
---|
[75337] | 2379 | else if (uLevel == FI_LVL_VERIFY_PATH)
|
---|
| 2380 | rc = NO_ERROR; /* vboxSfOs2ResolvePath should've taken care of this already */
|
---|
| 2381 | else
|
---|
[76126] | 2382 | rc = vboxSfOs2QueryCorrectCase(pFolder, pReq, pszPath, pbData, cbData);
|
---|
[75337] | 2383 | }
|
---|
| 2384 | /*
|
---|
| 2385 | * Update information.
|
---|
| 2386 | */
|
---|
| 2387 | else if ( fFlags == PI_SET
|
---|
| 2388 | || fFlags == (PI_SET | PI_WRITE_THRU))
|
---|
| 2389 | {
|
---|
| 2390 | if ( uLevel == FI_LVL_STANDARD
|
---|
| 2391 | || uLevel == FI_LVL_STANDARD_64)
|
---|
| 2392 | {
|
---|
| 2393 | /* Read in the data and join paths with FS32_FILEATTRIBUTE: */
|
---|
| 2394 | PFILESTATUS pDataCopy = (PFILESTATUS)VbglR0PhysHeapAlloc(cbMinData);
|
---|
| 2395 | if (pDataCopy)
|
---|
| 2396 | {
|
---|
| 2397 | rc = KernCopyIn(pDataCopy, pbData, cbMinData);
|
---|
| 2398 | if (rc == NO_ERROR)
|
---|
[76126] | 2399 | rc = vboxSfOs2SetPathInfoWorker(pFolder, pReq,
|
---|
[75337] | 2400 | uLevel == FI_LVL_STANDARD
|
---|
| 2401 | ? (ULONG)pDataCopy->attrFile
|
---|
| 2402 | : ((PFILESTATUS3L)pDataCopy)->attrFile,
|
---|
| 2403 | (PFILESTATUS)pDataCopy);
|
---|
| 2404 | VbglR0PhysHeapFree(pDataCopy);
|
---|
| 2405 | }
|
---|
| 2406 | else
|
---|
| 2407 | rc = ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 2408 | }
|
---|
| 2409 | else if (uLevel == FI_LVL_STANDARD_EASIZE)
|
---|
| 2410 | rc = ERROR_EAS_NOT_SUPPORTED;
|
---|
| 2411 | else
|
---|
| 2412 | rc = ERROR_INVALID_LEVEL;
|
---|
| 2413 | }
|
---|
| 2414 | else
|
---|
| 2415 | {
|
---|
| 2416 | LogRel(("FS32_PATHINFO: Unknown flags value: %#x (path: %s)\n", fFlags, pszPath));
|
---|
| 2417 | rc = ERROR_INVALID_PARAMETER;
|
---|
| 2418 | }
|
---|
[76126] | 2419 | VbglR0PhysHeapFree(pReq);
|
---|
| 2420 | vboxSfOs2ReleaseFolder(pFolder);
|
---|
[75337] | 2421 | }
|
---|
| 2422 | RT_NOREF_PV(pCdFsi);
|
---|
| 2423 | return rc;
|
---|
| 2424 | }
|
---|
| 2425 |
|
---|
| 2426 |
|
---|
| 2427 | DECLASM(APIRET)
|
---|
| 2428 | FS32_MOUNT(USHORT fFlags, PVPFSI pvpfsi, PVBOXSFVP pVpFsd, USHORT hVPB, PCSZ pszBoot)
|
---|
| 2429 | {
|
---|
| 2430 | NOREF(fFlags); NOREF(pvpfsi); NOREF(pVpFsd); NOREF(hVPB); NOREF(pszBoot);
|
---|
[3655] | 2431 | return ERROR_NOT_SUPPORTED;
|
---|
| 2432 | }
|
---|
| 2433 |
|
---|