/** * Advances the buffer pointer. * * @param pThis The directory instance data. */ static int rtDirNtAdvanceBuffer(PRTDIR pThis) { int rc; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pThis->enmInfoClass == FileMaximumInformation) { pThis->uCurData.pObjDir++; pThis->fDataUnread = pThis->uCurData.pObjDir->Name.Length != 0; return VINF_SUCCESS; } #endif pThis->fDataUnread = false; uint32_t const offNext = pThis->uCurData.pBoth->NextEntryOffset; if (offNext == 0) return VINF_SUCCESS; #ifdef RTDIR_NT_STRICT /* Make sure the next-record offset is beyond the current record. */ size_t cbRec; if (pThis->enmInfoClass == FileIdBothDirectoryInformation) cbRec = RT_UOFFSETOF(FILE_ID_BOTH_DIR_INFORMATION, FileName); else cbRec = RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName); cbRec += pThis->uCurData.pBoth->FileNameLength; AssertReturn(offNext >= cbRec, VERR_IO_GEN_FAILURE); #endif pThis->uCurData.u += offNext; rc = rtDirNtCheckRecord(pThis); pThis->fDataUnread = RT_SUCCESS(rc); return rc; }
/** * Checks the validity of the current record. * * @returns IPRT status code * @param pThis The directory instance data. */ static int rtDirNtCheckRecord(PRTDIRINTERNAL pThis) { #if defined(RTDIR_NT_STRICT) || defined(RT_ARCH_X86) # ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pThis->enmInfoClass != FileMaximumInformation) # endif { uintptr_t uEndAddr; if (pThis->enmInfoClass == FileIdBothDirectoryInformation) uEndAddr = (uintptr_t)&pThis->uCurData.pBothId->FileName[0]; else uEndAddr = (uintptr_t)&pThis->uCurData.pBoth->FileName[0]; # ifdef RT_ARCH_X86 /* Workaround for NT 3.1 bug where FAT returns a too short buffer length. Including all NT 3.x versions in case it bug was fixed till NT 4. */ uintptr_t const uEndBuffer = (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer]; if ( uEndAddr < uEndBuffer && uEndAddr + pThis->uCurData.pBoth->FileNameLength <= uEndBuffer) { /* likely */ } else if ( ( g_enmWinVer == kRTWinOSType_NT310 || g_enmWinVer == kRTWinOSType_NT350 // not sure when it was fixed... || g_enmWinVer == kRTWinOSType_NT351) && pThis->enmInfoClass == FileBothDirectoryInformation) { size_t cbLeft = (uintptr_t)&pThis->pabBuffer[pThis->cbBufferAlloc] - (uintptr_t)pThis->uCurData.pBoth; if ( cbLeft >= RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName) && pThis->uCurData.pBoth->FileNameLength > 0 && cbLeft >= RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName) + pThis->uCurData.pBoth->FileNameLength) { pThis->cbBuffer = ((uintptr_t)&pThis->uCurData.pBoth->FileName[0] + pThis->uCurData.pBoth->FileNameLength) - (uintptr_t)&pThis->pabBuffer[0]; } } # endif # ifdef RTDIR_NT_STRICT AssertReturn(uEndAddr < (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE); AssertReturn(pThis->uCurData.pBoth->FileNameLength < _64K, VERR_FILENAME_TOO_LONG); AssertReturn((pThis->uCurData.pBoth->FileNameLength & 1) == 0, VERR_IO_GEN_FAILURE); uEndAddr += pThis->uCurData.pBoth->FileNameLength; AssertReturn(uEndAddr <= (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE); AssertReturn((unsigned)pThis->uCurData.pBoth->ShortNameLength <= sizeof(pThis->uCurData.pBoth->ShortName), VERR_IO_GEN_FAILURE); # endif } #else RT_NOREF_PV(pThis); #endif return VINF_SUCCESS; }
/** * Finds an option. * * @returns On success, a pointer to the first byte in the option data (no none * then it'll be the byte following the 0 size field) and *pcbOpt set * to the option length. * On failure, NULL is returned and *pcbOpt unchanged. * * @param uOption The option to search for. * @param pDhcpMsg The DHCP message. * that this is adjusted if the option length is larger * than the message buffer. */ int ConfigurationManager::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt) { Assert(uOption != RTNET_DHCP_OPT_PAD); /* * Validate the DHCP bits and figure the max size of the options in the vendor field. */ if (cbDhcpMsg <= RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts)) return VERR_INVALID_PARAMETER; if (pDhcpMsg->bp_vend.Dhcp.dhcp_cookie != RT_H2N_U32_C(RTNET_DHCP_COOKIE)) return VERR_INVALID_PARAMETER; size_t cbLeft = cbDhcpMsg - RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts); if (cbLeft > RTNET_DHCP_OPT_SIZE) cbLeft = RTNET_DHCP_OPT_SIZE; /* * Search the vendor field. */ bool fExtended = false; uint8_t const *pb = &pDhcpMsg->bp_vend.Dhcp.dhcp_opts[0]; while (pb && cbLeft > 0) { uint8_t uCur = *pb; if (uCur == RTNET_DHCP_OPT_PAD) { cbLeft--; pb++; } else if (cbLeft <= 1) break; else { size_t cbCur = pb[1]; if (cbCur > cbLeft - 2) cbCur = cbLeft - 2; if (uCur == uOption) { opt.u8OptId = uCur; memcpy(opt.au8RawOpt, pb+2, cbCur); opt.cbRawOpt = cbCur; return VINF_SUCCESS; } pb += cbCur + 2; cbLeft -= cbCur - 2; } } /** @todo search extended dhcp option field(s) when present */ return VERR_NOT_FOUND; }
static int listDir(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root, SHFLHANDLE handle, uint32_t fFlags, uint32_t cb, const char *pcszPath, void *pvBuf, uint32_t cbBuf, uint32_t resumePoint, uint32_t *pcFiles) { VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LIST]; struct TESTSHFLSTRING Path; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; aParms[0].setUInt32(root); aParms[1].setUInt64(handle); aParms[2].setUInt32(fFlags); aParms[3].setUInt32(cb); if (pcszPath) { fillTestShflString(&Path, pcszPath); aParms[4].setPointer(&Path, RT_UOFFSETOF(SHFLSTRING, String) + Path.string.u16Size); } else aParms[4].setPointer(NULL, 0); aParms[5].setPointer(pvBuf, cbBuf); aParms[6].setUInt32(resumePoint); aParms[7].setUInt32(0); psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_LIST, RT_ELEMENTS(aParms), aParms); if (pcFiles) *pcFiles = aParms[7].u.uint32; return callHandle.rc; }
static int createFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root, const char *pcszFilename, uint32_t fCreateFlags, SHFLHANDLE *pHandle, SHFLCREATERESULT *pResult) { VBOXHGCMSVCPARM aParms[SHFL_CPARMS_CREATE]; struct TESTSHFLSTRING Path; SHFLCREATEPARMS CreateParms; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; fillTestShflString(&Path, pcszFilename); RT_ZERO(CreateParms); CreateParms.CreateFlags = fCreateFlags; aParms[0].setUInt32(Root); aParms[1].setPointer(&Path, RT_UOFFSETOF(SHFLSTRING, String) + Path.string.u16Size); aParms[2].setPointer(&CreateParms, sizeof(CreateParms)); psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_CREATE, RT_ELEMENTS(aParms), aParms); if (RT_FAILURE(callHandle.rc)) return callHandle.rc; if (pHandle) *pHandle = CreateParms.Handle; if (pResult) *pResult = CreateParms.Result; return VINF_SUCCESS; }
RTDECL(int) RTPathParse(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags) { /* * Input validation. */ AssertReturn(cbParsed >= RT_UOFFSETOF(RTPATHPARSED, aComps), VERR_INVALID_PARAMETER); AssertPtrReturn(pParsed, VERR_INVALID_POINTER); AssertPtrReturn(pszPath, VERR_INVALID_POINTER); AssertReturn(*pszPath, VERR_PATH_ZERO_LENGTH); AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), VERR_INVALID_FLAGS); /* * Invoke the worker for the selected path style. */ switch (fFlags & RTPATH_STR_F_STYLE_MASK) { #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) case RTPATH_STR_F_STYLE_HOST: #endif case RTPATH_STR_F_STYLE_DOS: return rtPathParseStyleDos(pszPath, pParsed, cbParsed, fFlags); #if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) case RTPATH_STR_F_STYLE_HOST: #endif case RTPATH_STR_F_STYLE_UNIX: return rtPathParseStyleUnix(pszPath, pParsed, cbParsed, fFlags); default: AssertFailedReturn(VERR_INVALID_FLAGS); /* impossible */ } }
RTDECL(int) RTAsn1ContentAllocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator) { AssertReturn(pAllocator != NULL, VERR_WRONG_ORDER); AssertReturn(cb > 0 && cb < _1G, VERR_INVALID_PARAMETER); AssertPtr(pAsn1Core); AssertReturn(!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT), VERR_INVALID_STATE); /* Initialize the temporary allocation tracker. */ RTASN1ALLOCATION Allocation; Allocation.cbAllocated = 0; Allocation.cReallocs = 0; Allocation.uReserved0 = 0; Allocation.pAllocator = pAllocator; /* Make the allocation. */ uint32_t cbAlloc = RT_UOFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb; PRTASN1MEMCONTENT pHdr; int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdr, cbAlloc); if (RT_SUCCESS(rc)) { Assert(Allocation.cbAllocated >= cbAlloc); pHdr->Allocation = Allocation; pAsn1Core->cb = (uint32_t)cb; pAsn1Core->uData.pv = &pHdr->au64Content[0]; pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; } return rc; }
static void fillTestShflString(struct TESTSHFLSTRING *pDest, const char *pcszSource) { AssertRelease( strlen(pcszSource) * 2 + 2 < sizeof(*pDest) - RT_UOFFSETOF(SHFLSTRING, String)); pDest->string.u16Length = (uint16_t)(strlen(pcszSource) * sizeof(RTUTF16)); pDest->string.u16Size = pDest->string.u16Length + sizeof(RTUTF16); for (unsigned i = 0; i <= pDest->string.u16Length; ++i) pDest->string.String.ucs2[i] = (uint16_t)pcszSource[i]; }
static SHFLROOT initWithWritableMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable, VBOXHGCMSVCHELPERS *psvcHelpers, const char *pcszFolderName, const char *pcszMapping) { VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING, SHFL_CPARMS_MAP_FOLDER)]; struct TESTSHFLSTRING FolderName; struct TESTSHFLSTRING Mapping; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; int rc; initTable(psvcTable, psvcHelpers); AssertReleaseRC(VBoxHGCMSvcLoad(psvcTable)); AssertRelease( psvcTable->pvService = RTTestGuardedAllocTail(hTest, psvcTable->cbClient)); RT_BZERO(psvcTable->pvService, psvcTable->cbClient); fillTestShflString(&FolderName, pcszFolderName); fillTestShflString(&Mapping, pcszMapping); aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String) + FolderName.string.u16Size); aParms[1].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[2].setUInt32(1); rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING, SHFL_CPARMS_ADD_MAPPING, aParms); AssertReleaseRC(rc); aParms[0].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[1].setUInt32(0); /* root */ aParms[2].setUInt32('/'); /* delimiter */ aParms[3].setUInt32(1); /* case sensitive */ psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_MAP_FOLDER, SHFL_CPARMS_MAP_FOLDER, aParms); AssertReleaseRC(callHandle.rc); return aParms[1].u.uint32; }
/** @todo Mappings should be automatically removed by unloading the service, * but unloading is currently a no-op! */ static void unmapAndRemoveMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root, const char *pcszFolderName) { VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_UNMAP_FOLDER, SHFL_CPARMS_REMOVE_MAPPING)]; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; struct TESTSHFLSTRING FolderName; int rc; aParms[0].setUInt32(root); psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_UNMAP_FOLDER, SHFL_CPARMS_UNMAP_FOLDER, aParms); AssertReleaseRC(callHandle.rc); fillTestShflString(&FolderName, pcszFolderName); aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String) + FolderName.string.u16Size); rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_REMOVE_MAPPING, SHFL_CPARMS_REMOVE_MAPPING, aParms); AssertReleaseRC(rc); }
RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) { int rc; /* * Validate input. */ AssertPtrReturn(pDir, VERR_INVALID_POINTER); AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER); AssertReturn(enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST, VERR_INVALID_PARAMETER); AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRYEX, szName[2]), ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])), VERR_INVALID_PARAMETER); } /* * Fetch data? */ if (!pDir->fDataUnread) { rc = rtDirNtFetchMore(pDir); if (RT_FAILURE(rc)) return rc; } /* * Convert the filename to UTF-8. */ rc = rtDirNtConvertCurName(pDir); if (RT_FAILURE(rc)) return rc; /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ PFILE_BOTH_DIR_INFORMATION pBoth = pDir->uCurData.pBoth; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName)); #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pDir->enmInfoClass != FileMaximumInformation) #endif { uint8_t cbShort = pBoth->ShortNameLength; if (cbShort > 0) { AssertStmt(cbShort < sizeof(pDirEntry->wszShortName), cbShort = sizeof(pDirEntry->wszShortName) - 2); memcpy(pDirEntry->wszShortName, pBoth->ShortName, cbShort); pDirEntry->cwcShortName = cbShort / 2; } else pDirEntry->cwcShortName = 0; pDirEntry->Info.cbObject = pBoth->EndOfFile.QuadPart; pDirEntry->Info.cbAllocated = pBoth->AllocationSize.QuadPart; Assert(sizeof(uint64_t) == sizeof(pBoth->CreationTime)); RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, pBoth->CreationTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, pBoth->LastAccessTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, pBoth->LastWriteTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, pBoth->ChangeTime.QuadPart); pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pBoth->FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszName, cchName); } #ifdef IPRT_WITH_NT_PATH_PASSTHRU else { pDirEntry->cwcShortName = 0; pDirEntry->Info.cbObject = 0; pDirEntry->Info.cbAllocated = 0; RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, 0); if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("Directory"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("SymbolicLink"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777; else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("Device"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666; else pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666; } #endif /* * Requested attributes (we cannot provide anything actually). */ switch (enmAdditionalAttribs) { case RTFSOBJATTRADD_EASIZE: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pDir->enmInfoClass == FileMaximumInformation) pDirEntry->Info.Attr.u.EASize.cb = 0; else #endif pDirEntry->Info.Attr.u.EASize.cb = pBoth->EaSize; break; case RTFSOBJATTRADD_UNIX: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX; pDirEntry->Info.Attr.u.Unix.uid = ~0U; pDirEntry->Info.Attr.u.Unix.gid = ~0U; pDirEntry->Info.Attr.u.Unix.cHardlinks = 1; pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.fFlags = 0; pDirEntry->Info.Attr.u.Unix.GenerationId = 0; pDirEntry->Info.Attr.u.Unix.Device = 0; break; case RTFSOBJATTRADD_NOTHING: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; break; case RTFSOBJATTRADD_UNIX_OWNER: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U; pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */ break; case RTFSOBJATTRADD_UNIX_GROUP: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U; pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0'; break; default: AssertMsgFailed(("Impossible!\n")); return VERR_INTERNAL_ERROR; } /* * Follow links if requested. */ if ( (fFlags & RTPATH_F_FOLLOW_LINK) && RTFS_IS_SYMLINK(fFlags)) { /** @todo Symlinks: Find[First|Next]FileW will return info about the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ } /* * Finally advance the buffer. */ return rtDirNtAdvanceBuffer(pDir); }
RTDECL(int) RTPathSplit(const char *pszPath, PRTPATHSPLIT pSplit, size_t cbSplit, uint32_t fFlags) { /* * Input validation. */ AssertReturn(cbSplit >= RT_UOFFSETOF(RTPATHSPLIT, apszComps), VERR_INVALID_PARAMETER); AssertPtrReturn(pSplit, VERR_INVALID_POINTER); AssertPtrReturn(pszPath, VERR_INVALID_POINTER); AssertReturn(*pszPath, VERR_PATH_ZERO_LENGTH); AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), VERR_INVALID_FLAGS); /* * Use RTPathParse to do the parsing. * - This makes the ASSUMPTION that the output of this function is greater * or equal to that of RTPathParsed. * - We're aliasing the buffer here, so use volatile to avoid issues due to * compiler optimizations. */ RTPATHPARSED volatile *pParsedVolatile = (RTPATHPARSED volatile *)pSplit; RTPATHSPLIT volatile *pSplitVolatile = (RTPATHSPLIT volatile *)pSplit; AssertCompile(sizeof(*pParsedVolatile) <= sizeof(*pSplitVolatile)); AssertCompile(sizeof(pParsedVolatile->aComps[0]) <= sizeof(pSplitVolatile->apszComps[0])); int rc = RTPathParse(pszPath, (PRTPATHPARSED)pParsedVolatile, cbSplit, fFlags); if (RT_FAILURE(rc) && rc != VERR_BUFFER_OVERFLOW) return rc; /* * Calculate the required buffer space. */ uint16_t const cComps = pParsedVolatile->cComps; uint16_t const fProps = pParsedVolatile->fProps; uint16_t const cchPath = pParsedVolatile->cchPath; uint16_t const offSuffix = pParsedVolatile->offSuffix; uint32_t cbNeeded = RT_OFFSETOF(RTPATHSPLIT, apszComps[cComps]) + cchPath + RTPATH_PROP_FIRST_NEEDS_NO_SLASH(fProps) /* zero terminator for root spec. */ - RT_BOOL(fProps & RTPATH_PROP_DIR_SLASH) /* counted by cchPath, not included in the comp str. */ + 1; /* zero terminator. */ if (cbNeeded > cbSplit) { pSplitVolatile->cbNeeded = cbNeeded; return VERR_BUFFER_OVERFLOW; } Assert(RT_SUCCESS(rc)); /* * Convert the array and copy the strings, both backwards. */ char *psz = (char *)pSplit + cbNeeded; uint32_t idxComp = cComps - 1; /* the final component first (because of suffix handling). */ uint16_t offComp = pParsedVolatile->aComps[idxComp].off; uint16_t cchComp = pParsedVolatile->aComps[idxComp].cch; *--psz = '\0'; psz -= cchComp; memcpy(psz, &pszPath[offComp], cchComp); pSplitVolatile->apszComps[idxComp] = psz; char *pszSuffix; if (offSuffix >= offComp + cchComp) pszSuffix = &psz[cchComp]; else pszSuffix = &psz[offSuffix - offComp]; /* the remainder */ while (idxComp-- > 0) { offComp = pParsedVolatile->aComps[idxComp].off; cchComp = pParsedVolatile->aComps[idxComp].cch; *--psz = '\0'; psz -= cchComp; memcpy(psz, &pszPath[offComp], cchComp); pSplitVolatile->apszComps[idxComp] = psz; } /* * Store / reshuffle the non-array bits. This MUST be done after finishing * the array processing because there may be members in RTPATHSPLIT * overlapping the array of RTPATHPARSED. */ AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cComps, RTPATHSPLIT, cComps); Assert(pSplitVolatile->cComps == cComps); AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, fProps, RTPATHSPLIT, fProps); Assert(pSplitVolatile->fProps == fProps); AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cchPath, RTPATHSPLIT, cchPath); Assert(pSplitVolatile->cchPath == cchPath); pSplitVolatile->u16Reserved = 0; pSplitVolatile->cbNeeded = cbNeeded; pSplitVolatile->pszSuffix = pszSuffix; return rc; }
/** * Entry point. */ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) { /* * Init runtime. */ RTR3InitExe(argc, &argv, 0); /* * Create empty VM structure and call MMR3Init(). */ PVM pVM; RTR0PTR pvR0; SUPPAGE aPages[RT_ALIGN_Z(sizeof(*pVM) + NUM_CPUS * sizeof(VMCPU), PAGE_SIZE) >> PAGE_SHIFT]; int rc = SUPR3Init(NULL); if (RT_SUCCESS(rc)) rc = SUPR3LowAlloc(RT_ELEMENTS(aPages), (void **)&pVM, &pvR0, &aPages[0]); if (RT_FAILURE(rc)) { RTPrintf("Fatal error: SUP Failure! rc=%Rrc\n", rc); return 1; } memset(pVM, 0, sizeof(*pVM)); /* wtf? */ pVM->paVMPagesR3 = aPages; pVM->pVMR0 = pvR0; static UVM s_UVM; PUVM pUVM = &s_UVM; pUVM->pVM = pVM; pVM->pUVM = pUVM; pVM->cCpus = NUM_CPUS; pVM->cbSelf = RT_UOFFSETOF(VM, aCpus[pVM->cCpus]); rc = STAMR3InitUVM(pUVM); if (RT_FAILURE(rc)) { RTPrintf("FAILURE: STAMR3Init failed. rc=%Rrc\n", rc); return 1; } rc = MMR3InitUVM(pUVM); if (RT_FAILURE(rc)) { RTPrintf("FAILURE: STAMR3Init failed. rc=%Rrc\n", rc); return 1; } rc = CFGMR3Init(pVM, NULL, NULL); if (RT_FAILURE(rc)) { RTPrintf("FAILURE: CFGMR3Init failed. rc=%Rrc\n", rc); return 1; } rc = MMR3Init(pVM); if (RT_FAILURE(rc)) { RTPrintf("Fatal error: MMR3Init failed! rc=%Rrc\n", rc); return 1; } /* * Try allocate. */ static struct { size_t cb; unsigned uAlignment; void *pvAlloc; unsigned iFreeOrder; } aOps[] = { { 16, 0, NULL, 0 }, { 16, 4, NULL, 1 }, { 16, 8, NULL, 2 }, { 16, 16, NULL, 5 }, { 16, 32, NULL, 4 }, { 32, 0, NULL, 3 }, { 31, 0, NULL, 6 }, { 1024, 0, NULL, 8 }, { 1024, 32, NULL, 10 }, { 1024, 32, NULL, 12 }, { PAGE_SIZE, PAGE_SIZE, NULL, 13 }, { 1024, 32, NULL, 9 }, { PAGE_SIZE, 32, NULL, 11 }, { PAGE_SIZE, PAGE_SIZE, NULL, 14 }, { 16, 0, NULL, 15 }, { 9, 0, NULL, 7 }, { 16, 0, NULL, 7 }, { 36, 0, NULL, 7 }, { 16, 0, NULL, 7 }, { 12344, 0, NULL, 7 }, { 50, 0, NULL, 7 }, { 16, 0, NULL, 7 }, }; unsigned i; #ifdef DEBUG MMHyperHeapDump(pVM); #endif size_t cbBefore = MMHyperHeapGetFreeSize(pVM); static char szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* allocate */ for (i = 0; i < RT_ELEMENTS(aOps); i++) { rc = MMHyperAlloc(pVM, aOps[i].cb, aOps[i].uAlignment, MM_TAG_VM, &aOps[i].pvAlloc); if (RT_FAILURE(rc)) { RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %d i=%d\n", aOps[i].cb, aOps[i].uAlignment, rc, i); return 1; } memset(aOps[i].pvAlloc, szFill[i], aOps[i].cb); if (RT_ALIGN_P(aOps[i].pvAlloc, (aOps[i].uAlignment ? aOps[i].uAlignment : 8)) != aOps[i].pvAlloc) { RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %p, invalid alignment!\n", aOps[i].cb, aOps[i].uAlignment, aOps[i].pvAlloc); return 1; } } /* free and allocate the same node again. */ for (i = 0; i < RT_ELEMENTS(aOps); i++) { if ( !aOps[i].pvAlloc || aOps[i].uAlignment == PAGE_SIZE) continue; //size_t cbBeforeSub = MMHyperHeapGetFreeSize(pVM); rc = MMHyperFree(pVM, aOps[i].pvAlloc); if (RT_FAILURE(rc)) { RTPrintf("Failure: MMHyperFree(, %p,) -> %d i=%d\n", aOps[i].pvAlloc, rc, i); return 1; } //RTPrintf("debug: i=%d cbBeforeSub=%d now=%d\n", i, cbBeforeSub, MMHyperHeapGetFreeSize(pVM)); void *pv; rc = MMHyperAlloc(pVM, aOps[i].cb, aOps[i].uAlignment, MM_TAG_VM_REQ, &pv); if (RT_FAILURE(rc)) { RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %d i=%d\n", aOps[i].cb, aOps[i].uAlignment, rc, i); return 1; } if (pv != aOps[i].pvAlloc) { RTPrintf("Failure: Free+Alloc returned different address. new=%p old=%p i=%d (doesn't work with delayed free)\n", pv, aOps[i].pvAlloc, i); //return 1; } aOps[i].pvAlloc = pv; #if 0 /* won't work :/ */ size_t cbAfterSub = MMHyperHeapGetFreeSize(pVM); if (cbBeforeSub != cbAfterSub) { RTPrintf("Failure: cbBeforeSub=%d cbAfterSub=%d. i=%d\n", cbBeforeSub, cbAfterSub, i); return 1; } #endif } /* free it in a specific order. */ int cFreed = 0; for (i = 0; i < RT_ELEMENTS(aOps); i++) { unsigned j; for (j = 0; j < RT_ELEMENTS(aOps); j++) { if ( aOps[j].iFreeOrder != i || !aOps[j].pvAlloc) continue; RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, MMHyperHeapGetFreeSize(pVM), aOps[j].cb, aOps[j].pvAlloc); if (aOps[j].uAlignment == PAGE_SIZE) cbBefore -= aOps[j].cb; else { rc = MMHyperFree(pVM, aOps[j].pvAlloc); if (RT_FAILURE(rc)) { RTPrintf("Failure: MMHyperFree(, %p,) -> %d j=%d i=%d\n", aOps[j].pvAlloc, rc, i, j); return 1; } } aOps[j].pvAlloc = NULL; cFreed++; } } Assert(cFreed == RT_ELEMENTS(aOps)); RTPrintf("i=done free=%d\n", MMHyperHeapGetFreeSize(pVM)); /* check that we're back at the right amount of free memory. */ size_t cbAfter = MMHyperHeapGetFreeSize(pVM); if (cbBefore != cbAfter) { RTPrintf("Warning: Either we've split out an alignment chunk at the start, or we've got\n" " an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter); #ifdef DEBUG MMHyperHeapDump(pVM); #endif } RTPrintf("tstMMHyperHeap: Success\n"); #ifdef LOG_ENABLED RTLogFlush(NULL); #endif return 0; }
RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) { /** @todo Symlinks: Find[First|Next]FileW will return info about the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ /* * Validate input. */ if (!pDir || pDir->u32Magic != RTDIR_MAGIC) { AssertMsgFailed(("Invalid pDir=%p\n", pDir)); return VERR_INVALID_PARAMETER; } if (!pDirEntry) { AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); return VERR_INVALID_PARAMETER; } if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING || enmAdditionalAttribs > RTFSOBJATTRADD_LAST) { AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs)); return VERR_INVALID_PARAMETER; } AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2])) { AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2]))); return VERR_INVALID_PARAMETER; } } /* * Fetch data? */ if (!pDir->fDataUnread) { RTStrFree(pDir->pszName); pDir->pszName = NULL; BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); if (!fRc) { int iErr = GetLastError(); if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) return VERR_NO_MORE_FILES; return RTErrConvertFromWin32(iErr); } } /* * Convert the filename to UTF-8. */ if (!pDir->pszName) { int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); if (RT_FAILURE(rc)) { pDir->pszName = NULL; return rc; } pDir->cchName = strlen(pDir->pszName); } /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ pDir->fDataUnread = false; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); if (pDir->Data.cAlternateFileName[0]) { /* copy and calc length */ PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName; PRTUTF16 pwszDst = pDirEntry->wszShortName; uint32_t off = 0; while (off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U && pwszSrc[off]) { pwszDst[off] = pwszSrc[off]; off++; } pDirEntry->cwcShortName = (uint16_t)off; /* zero the rest */ do pwszDst[off++] = '\0'; while (off < RT_ELEMENTS(pDirEntry->wszShortName)); } else { memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName)); pDirEntry->cwcShortName = 0; } pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32) | (uint64_t)pDir->Data.nFileSizeLow; pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject; Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime)); RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime); pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime; pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszName, cchName); /* * Requested attributes (we cannot provide anything actually). */ switch (enmAdditionalAttribs) { case RTFSOBJATTRADD_EASIZE: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; pDirEntry->Info.Attr.u.EASize.cb = 0; break; case RTFSOBJATTRADD_UNIX: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX; pDirEntry->Info.Attr.u.Unix.uid = ~0U; pDirEntry->Info.Attr.u.Unix.gid = ~0U; pDirEntry->Info.Attr.u.Unix.cHardlinks = 1; pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.fFlags = 0; pDirEntry->Info.Attr.u.Unix.GenerationId = 0; pDirEntry->Info.Attr.u.Unix.Device = 0; break; case RTFSOBJATTRADD_NOTHING: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; break; case RTFSOBJATTRADD_UNIX_OWNER: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U; pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */ break; case RTFSOBJATTRADD_UNIX_GROUP: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U; pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0'; break; default: AssertMsgFailed(("Impossible!\n")); return VERR_INTERNAL_ERROR; } return VINF_SUCCESS; }
RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry) { /* * Validate input. */ if (!pDir || pDir->u32Magic != RTDIR_MAGIC) { AssertMsgFailed(("Invalid pDir=%p\n", pDir)); return VERR_INVALID_PARAMETER; } if (!pDirEntry) { AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); return VERR_INVALID_PARAMETER; } size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2])) { AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2]))); return VERR_INVALID_PARAMETER; } } /* * Fetch data? */ if (!pDir->fDataUnread) { RTStrFree(pDir->pszName); pDir->pszName = NULL; BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); if (!fRc) { int iErr = GetLastError(); if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) return VERR_NO_MORE_FILES; return RTErrConvertFromWin32(iErr); } } /* * Convert the filename to UTF-8. */ if (!pDir->pszName) { int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); if (RT_FAILURE(rc)) { pDir->pszName = NULL; return rc; } pDir->cchName = strlen(pDir->pszName); } /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ pDir->fDataUnread = false; pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */ pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); return VINF_SUCCESS; }
RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry) { /* * Validate and digest input. */ if (!rtDirValidHandle(pDir)) return VERR_INVALID_PARAMETER; AssertMsgReturn(VALID_PTR(pDirEntry), ("%p\n", pDirEntry), VERR_INVALID_POINTER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { AssertMsgReturn(VALID_PTR(pcbDirEntry), ("%p\n", pcbDirEntry), VERR_INVALID_POINTER); cbDirEntry = *pcbDirEntry; AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]), ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])), VERR_INVALID_PARAMETER); } /* * Fetch more data if necessary and/or convert the name. */ int rc = rtDirReadMore(pDir); if (RT_SUCCESS(rc)) { /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired <= cbDirEntry) { /* * Setup the returned data. */ pDirEntry->INodeId = pDir->Data.d_ino; /* may need #ifdefing later */ #ifdef HAVE_DIRENT_D_TYPE pDirEntry->enmType = rtDirType(pDir->Data.d_type); #else pDirEntry->enmType = RTDIRENTRYTYPE_UNKNOWN; #endif pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); /* free cached data */ pDir->fDataUnread = false; rtPathFreeIprt(pDir->pszName, pDir->Data.d_name); pDir->pszName = NULL; } else rc = VERR_BUFFER_OVERFLOW; } LogFlow(("RTDirRead(%p:{%s}, %p:{%s}, %p:{%u}): returns %Rrc\n", pDir, pDir->pszPath, pDirEntry, RT_SUCCESS(rc) ? pDirEntry->szName : "<failed>", pcbDirEntry, pcbDirEntry ? *pcbDirEntry : 0, rc)); return rc; }
/** Internal worker for VBoxNetUDPUnicast and VBoxNetUDPBroadcast. */ static int vboxnetudpSend(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf, RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort, RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort, void const *pvData, size_t cbData) { INTNETSEG aSegs[4]; /* the Ethernet header */ RTNETETHERHDR EtherHdr; EtherHdr.DstMac = *pDstMacAddr; EtherHdr.SrcMac = *pSrcMacAddr; EtherHdr.EtherType = RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4); aSegs[0].pv = &EtherHdr; aSegs[0].cb = sizeof(EtherHdr); aSegs[0].Phys = NIL_RTHCPHYS; /* the IP header */ RTNETIPV4 IpHdr; unsigned cbIdHdr = RT_UOFFSETOF(RTNETIPV4, ip_options); IpHdr.ip_v = 4; IpHdr.ip_hl = cbIdHdr >> 2; IpHdr.ip_tos = 0; IpHdr.ip_len = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP) + cbIdHdr)); IpHdr.ip_id = (uint16_t)RTRandU32(); IpHdr.ip_off = 0; IpHdr.ip_ttl = 255; IpHdr.ip_p = RTNETIPV4_PROT_UDP; IpHdr.ip_sum = 0; IpHdr.ip_src = SrcIPv4Addr; IpHdr.ip_dst = DstIPv4Addr; IpHdr.ip_sum = RTNetIPv4HdrChecksum(&IpHdr); aSegs[1].pv = &IpHdr; aSegs[1].cb = cbIdHdr; aSegs[1].Phys = NIL_RTHCPHYS; /* the UDP bit */ RTNETUDP UdpHdr; UdpHdr.uh_sport = RT_H2BE_U16(uSrcPort); UdpHdr.uh_dport = RT_H2BE_U16(uDstPort); UdpHdr.uh_ulen = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP))); #if 0 UdpHdr.uh_sum = 0; /* pretend checksumming is disabled */ #else UdpHdr.uh_sum = RTNetIPv4UDPChecksum(&IpHdr, &UdpHdr, pvData); #endif aSegs[2].pv = &UdpHdr; aSegs[2].cb = sizeof(UdpHdr); aSegs[2].Phys = NIL_RTHCPHYS; /* the payload */ aSegs[3].pv = (void *)pvData; aSegs[3].cb = (uint32_t)cbData; aSegs[3].Phys = NIL_RTHCPHYS; /* send it */ return VBoxNetIntIfSend(pSession, hIf, pBuf, RT_ELEMENTS(aSegs), &aSegs[0], true /* fFlush */); }
RTDECL(int) RTAsn1ContentReallocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator) { /* Validate input. */ AssertPtr(pAsn1Core); AssertReturn(cb < _1G, VERR_INVALID_PARAMETER); if (cb > 0) { /* * Case 1 - Initial allocation. */ uint32_t cbNeeded = RT_UOFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb; if (!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT)) return RTAsn1ContentAllocZ(pAsn1Core, cb, pAllocator); /* Locate the header. */ PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content); /* * Case 2 - Reallocation using the same allocator. */ if ( pHdr->Allocation.pAllocator == pAllocator || !pAllocator) { pHdr->Allocation.cReallocs++; /* Modify the allocation if necessary. */ if (pHdr->Allocation.cbAllocated < cbNeeded) { RTASN1ALLOCATION Allocation = pHdr->Allocation; int rc = Allocation.pAllocator->pfnRealloc(Allocation.pAllocator, &Allocation, pHdr, (void **)&pHdr, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); pAsn1Core->uData.pv = &pHdr->au64Content[0]; pHdr->Allocation = Allocation; } /* Clear any additional memory we're letting the user use and update the content size. */ if (pAsn1Core->cb < cb) RT_BZERO((uint8_t *)&pAsn1Core->uData.pu8[pAsn1Core->cb], cb - pAsn1Core->cb); pAsn1Core->cb = (uint32_t)cb; } /* * Case 3 - Reallocation using a different allocator. */ else { /* Initialize the temporary allocation tracker. */ RTASN1ALLOCATION Allocation; Allocation.cbAllocated = 0; Allocation.cReallocs = pHdr->Allocation.cReallocs + 1; Allocation.uReserved0 = 0; Allocation.pAllocator = pAllocator; /* Make the allocation. */ PRTASN1MEMCONTENT pHdrNew; int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdrNew, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); /* Duplicate the old content and zero any new memory we might've added. */ if (pAsn1Core->cb >= cb) memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], cb); else { memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], pAsn1Core->cb); RT_BZERO((uint8_t *)&pHdrNew->au64Content[0] + pAsn1Core->cb, cb - pAsn1Core->cb); } /* Update the core. */ pHdrNew->Allocation = Allocation; pAsn1Core->uData.pv = &pHdrNew->au64Content[0]; pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; /* free cleared it. */ pAsn1Core->cb = (uint32_t)cb; /* Free the old content. */ Allocation = pHdr->Allocation; Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr); Assert(Allocation.cbAllocated == 0); } } /* * Case 4 - It's a request to free the memory. */ else RTAsn1ContentFree(pAsn1Core); return VINF_SUCCESS; }
/** * \#PF Virtual Handler callback for Guest write access to the Guest's own current TSS. * * @returns VBox status code (appropriate for trap handling and GC return). * @param pVM VM Handle. * @param uErrorCode CPU Error code. * @param pRegFrame Trap register frame. * @param pvFault The fault address (cr2). * @param pvRange The base address of the handled virtual range. * @param offRange The offset of the access into this range. * (If it's a EIP range this is the EIP, if not it's pvFault.) */ VMMRCDECL(int) selmRCGuestTSSWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange) { PVMCPU pVCpu = VMMGetCpu0(pVM); LogFlow(("selmRCGuestTSSWriteHandler errcode=%x fault=%RGv offRange=%08x\n", (uint32_t)uErrorCode, pvFault, offRange)); /* * Try emulate the access. */ uint32_t cb; int rc = EMInterpretInstruction(pVM, pVCpu, pRegFrame, (RTGCPTR)(RTRCUINTPTR)pvFault, &cb); if (RT_SUCCESS(rc) && cb) { rc = VINF_SUCCESS; /* * If it's on the same page as the esp0 and ss0 fields or actually one of them, * then check if any of these has changed. */ PCVBOXTSS pGuestTss = (PVBOXTSS)(uintptr_t)pVM->selm.s.GCPtrGuestTss; if ( PAGE_ADDRESS(&pGuestTss->esp0) == PAGE_ADDRESS(&pGuestTss->padding_ss0) && PAGE_ADDRESS(&pGuestTss->esp0) == PAGE_ADDRESS((uint8_t *)pGuestTss + offRange) && ( pGuestTss->esp0 != pVM->selm.s.Tss.esp1 || pGuestTss->ss0 != (pVM->selm.s.Tss.ss1 & ~1)) /* undo raw-r0 */ ) { Log(("selmRCGuestTSSWriteHandler: R0 stack: %RTsel:%RGv -> %RTsel:%RGv\n", (RTSEL)(pVM->selm.s.Tss.ss1 & ~1), (RTGCPTR)pVM->selm.s.Tss.esp1, (RTSEL)pGuestTss->ss0, (RTGCPTR)pGuestTss->esp0)); pVM->selm.s.Tss.esp1 = pGuestTss->esp0; pVM->selm.s.Tss.ss1 = pGuestTss->ss0 | 1; STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestTSSHandledChanged); } /* Handle misaligned TSS in a safe manner (just in case). */ else if ( offRange >= RT_UOFFSETOF(VBOXTSS, esp0) && offRange < RT_UOFFSETOF(VBOXTSS, padding_ss0)) { struct { uint32_t esp0; uint16_t ss0; uint16_t padding_ss0; } s; AssertCompileSize(s, 8); rc = selmRCReadTssBits(pVM, &s, &pGuestTss->esp0, sizeof(s)); if ( rc == VINF_SUCCESS && ( s.esp0 != pVM->selm.s.Tss.esp1 || s.ss0 != (pVM->selm.s.Tss.ss1 & ~1)) /* undo raw-r0 */ ) { Log(("selmRCGuestTSSWriteHandler: R0 stack: %RTsel:%RGv -> %RTsel:%RGv [x-page]\n", (RTSEL)(pVM->selm.s.Tss.ss1 & ~1), (RTGCPTR)pVM->selm.s.Tss.esp1, (RTSEL)s.ss0, (RTGCPTR)s.esp0)); pVM->selm.s.Tss.esp1 = s.esp0; pVM->selm.s.Tss.ss1 = s.ss0 | 1; STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestTSSHandledChanged); } } /* * If VME is enabled we need to check if the interrupt redirection bitmap * needs updating. */ if ( offRange >= RT_UOFFSETOF(VBOXTSS, offIoBitmap) && (CPUMGetGuestCR4(pVCpu) & X86_CR4_VME)) { if (offRange - RT_UOFFSETOF(VBOXTSS, offIoBitmap) < sizeof(pGuestTss->offIoBitmap)) { uint16_t offIoBitmap = pGuestTss->offIoBitmap; if (offIoBitmap != pVM->selm.s.offGuestIoBitmap) { Log(("TSS offIoBitmap changed: old=%#x new=%#x -> resync in ring-3\n", pVM->selm.s.offGuestIoBitmap, offIoBitmap)); VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3); } else Log(("TSS offIoBitmap: old=%#x new=%#x [unchanged]\n", pVM->selm.s.offGuestIoBitmap, offIoBitmap)); } else { /** @todo not sure how the partial case is handled; probably not allowed */ uint32_t offIntRedirBitmap = pVM->selm.s.offGuestIoBitmap - sizeof(pVM->selm.s.Tss.IntRedirBitmap); if ( offIntRedirBitmap <= offRange && offIntRedirBitmap + sizeof(pVM->selm.s.Tss.IntRedirBitmap) >= offRange + cb && offIntRedirBitmap + sizeof(pVM->selm.s.Tss.IntRedirBitmap) <= pVM->selm.s.cbGuestTss) { Log(("TSS IntRedirBitmap Changed: offIoBitmap=%x offIntRedirBitmap=%x cbTSS=%x offRange=%x cb=%x\n", pVM->selm.s.offGuestIoBitmap, offIntRedirBitmap, pVM->selm.s.cbGuestTss, offRange, cb)); /** @todo only update the changed part. */ for (uint32_t i = 0; i < sizeof(pVM->selm.s.Tss.IntRedirBitmap) / 8; i++) { rc = selmRCReadTssBits(pVM, &pVM->selm.s.Tss.IntRedirBitmap[i * 8], (uint8_t *)pGuestTss + offIntRedirBitmap + i * 8, 8); if (rc != VINF_SUCCESS) break; } STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestTSSRedir); } } } /* Return to ring-3 for a full resync if any of the above fails... (?) */ if (rc != VINF_SUCCESS) { VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3); if (RT_SUCCESS(rc)) rc = VINF_SUCCESS; } STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestTSSHandled); } else { Assert(RT_FAILURE(rc)); VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestTSSUnhandled); if (rc == VERR_EM_INTERPRETER) rc = VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT; } return rc; }
RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry) { int rc; /* * Validate input. */ AssertPtrReturn(pDir, VERR_INVALID_POINTER); AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]), ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])), VERR_INVALID_PARAMETER); } /* * Fetch data? */ if (!pDir->fDataUnread) { rc = rtDirNtFetchMore(pDir); if (RT_FAILURE(rc)) return rc; } /* * Convert the filename to UTF-8. */ rc = rtDirNtConvertCurName(pDir); if (RT_FAILURE(rc)) return rc; /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); pDirEntry->INodeId = pDir->enmInfoClass == FileIdBothDirectoryInformation ? pDir->uCurData.pBothId->FileId.QuadPart : 0; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pDir->enmInfoClass != FileMaximumInformation) #endif { switch ( pDir->uCurData.pBoth->FileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY)) { default: AssertFailed(); case 0: pDirEntry->enmType = RTDIRENTRYTYPE_FILE; break; case FILE_ATTRIBUTE_DIRECTORY: pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; break; case FILE_ATTRIBUTE_REPARSE_POINT: case FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY: pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; break; } } #ifdef IPRT_WITH_NT_PATH_PASSTHRU else { pDirEntry->enmType = RTDIRENTRYTYPE_UNKNOWN; if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("Directory"))) pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("SymbolicLink"))) pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; } #endif return rtDirNtAdvanceBuffer(pDir); }