RTDECL(int) RTEnvQueryUtf16Block(RTENV hEnv, PRTUTF16 *ppwszzBlock) { RTENV hClone = NIL_RTENV; PRTENVINTERNAL pIntEnv; int rc; /* * Validate / simplify input. */ if (hEnv == RTENV_DEFAULT) { rc = RTEnvClone(&hClone, RTENV_DEFAULT); if (RT_FAILURE(rc)) return rc; pIntEnv = hClone; } else { pIntEnv = hEnv; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); rc = VINF_SUCCESS; } RTENV_LOCK(pIntEnv); /* * Sort it first. */ RTSortApvShell((void **)pIntEnv->papszEnv, pIntEnv->cVars, rtEnvSortCompare, pIntEnv); /* * Calculate the size. */ size_t cwc; size_t cwcTotal = 2; for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) { rc = RTStrCalcUtf16LenEx(pIntEnv->papszEnv[iVar], RTSTR_MAX, &cwc); AssertRCBreak(rc); cwcTotal += cwc + 1; } PRTUTF16 pwszzBlock = NULL; if (RT_SUCCESS(rc)) { /* * Perform the conversion. */ PRTUTF16 pwszz = pwszzBlock = (PRTUTF16)RTMemAlloc(cwcTotal * sizeof(RTUTF16)); if (pwszz) { size_t cwcLeft = cwcTotal; for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) { rc = RTStrToUtf16Ex(pIntEnv->papszEnv[iVar], RTSTR_MAX, &pwszz, cwcTotal - (pwszz - pwszzBlock), &cwc); AssertRCBreak(rc); pwszz += cwc + 1; cwcLeft -= cwc + 1; AssertBreakStmt(cwcLeft >= 2, rc = VERR_INTERNAL_ERROR_3); } AssertStmt(cwcLeft == 2 || RT_FAILURE(rc), rc = VERR_INTERNAL_ERROR_2); if (RT_SUCCESS(rc)) { pwszz[0] = '\0'; pwszz[1] = '\0'; } else { RTMemFree(pwszzBlock); pwszzBlock = NULL; } } else rc = VERR_NO_MEMORY; } RTENV_UNLOCK(pIntEnv); if (hClone != NIL_RTENV) RTEnvDestroy(hClone); if (RT_SUCCESS(rc)) *ppwszzBlock = pwszzBlock; return rc; }
RTDECL(int) RTAsn1ObjId_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pThis, const char *pszErrorTag) { int rc = RTAsn1CursorReadHdr(pCursor, &pThis->Asn1Core, pszErrorTag); if (RT_SUCCESS(rc)) { rc = RTAsn1CursorMatchTagClassFlags(pCursor, &pThis->Asn1Core, ASN1_TAG_OID, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE, fFlags, pszErrorTag, "OID"); if (RT_SUCCESS(rc)) { /* * Validate and count things first. */ uint8_t cComponents = 0; /* gcc maybe-crap */ uint8_t cchObjId = 0; /* ditto */ rc = rtAsn1ObjId_PreParse(pCursor->pbCur, pThis->Asn1Core.cb, pCursor, pszErrorTag, &cComponents, &cchObjId); if (RT_SUCCESS(rc)) { /* * Allocate memory for the components array, either out of the * string buffer or off the heap. */ pThis->cComponents = cComponents; RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); #if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */ if (cComponents * sizeof(uint32_t) <= sizeof(pThis->szObjId) - cchObjId - 1) pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)]; else #endif rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents, cComponents * sizeof(pThis->pauComponents[0])); if (RT_SUCCESS(rc)) { uint32_t *pauComponents = (uint32_t *)pThis->pauComponents; /* * Deal with the two first components first since they are * encoded in a weird way to save a byte. */ uint8_t const *pbContent = pCursor->pbCur; uint32_t cbContent = pThis->Asn1Core.cb; uint32_t uValue; rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRC(rc); if (RT_SUCCESS(rc)) { pbContent += rc; cbContent -= rc; if (uValue < 80) { pauComponents[0] = uValue / 40; pauComponents[1] = uValue % 40; } else { pauComponents[0] = 2; pauComponents[1] = uValue - 2*40; } char *pszObjId = &pThis->szObjId[0]; *pszObjId++ = g_achDigits[pauComponents[0]]; size_t cbObjIdLeft = cchObjId + 1 - 1; rc = rtAsn1ObjId_InternalFormatComponent(pauComponents[1], &pszObjId, &cbObjIdLeft); AssertRC(rc); if (RT_SUCCESS(rc)) { /* * The other components are encoded in less complicated manner. */ for (uint32_t i = 2; i < cComponents; i++) { rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRCBreak(rc); pbContent += rc; cbContent -= rc; pauComponents[i] = uValue; rc = rtAsn1ObjId_InternalFormatComponent(uValue, &pszObjId, &cbObjIdLeft); AssertRCBreak(rc); } if (RT_SUCCESS(rc)) { Assert(cbObjIdLeft == 1); *pszObjId = '\0'; RTAsn1CursorSkip(pCursor, pThis->Asn1Core.cb); pThis->Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT; pThis->Asn1Core.pOps = &g_RTAsn1ObjId_Vtable; return VINF_SUCCESS; } } } } } } } RT_ZERO(*pThis); return rc; }
int readSavedDisplayScreenshot(const Utf8Str &strStateFilePath, uint32_t u32Type, uint8_t **ppu8Data, uint32_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height) { LogFlowFunc(("u32Type = %d [%s]\n", u32Type, strStateFilePath.c_str())); /* @todo cache read data */ if (strStateFilePath.isEmpty()) { /* No saved state data. */ return VERR_NOT_SUPPORTED; } uint8_t *pu8Data = NULL; uint32_t cbData = 0; uint32_t u32Width = 0; uint32_t u32Height = 0; PSSMHANDLE pSSM; int vrc = SSMR3Open(strStateFilePath.c_str(), 0 /*fFlags*/, &pSSM); if (RT_SUCCESS(vrc)) { uint32_t uVersion; vrc = SSMR3Seek(pSSM, "DisplayScreenshot", 1100 /*iInstance*/, &uVersion); if (RT_SUCCESS(vrc)) { if (uVersion == sSSMDisplayScreenshotVer) { uint32_t cBlocks; vrc = SSMR3GetU32(pSSM, &cBlocks); AssertRCReturn(vrc, vrc); for (uint32_t i = 0; i < cBlocks; i++) { uint32_t cbBlock; vrc = SSMR3GetU32(pSSM, &cbBlock); AssertRCBreak(vrc); uint32_t typeOfBlock; vrc = SSMR3GetU32(pSSM, &typeOfBlock); AssertRCBreak(vrc); LogFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock)); if (typeOfBlock == u32Type) { if (cbBlock > 2 * sizeof(uint32_t)) { cbData = cbBlock - 2 * sizeof(uint32_t); pu8Data = (uint8_t *)RTMemAlloc(cbData); if (pu8Data == NULL) { vrc = VERR_NO_MEMORY; break; } vrc = SSMR3GetU32(pSSM, &u32Width); AssertRCBreak(vrc); vrc = SSMR3GetU32(pSSM, &u32Height); AssertRCBreak(vrc); vrc = SSMR3GetMem(pSSM, pu8Data, cbData); AssertRCBreak(vrc); } else { /* No saved state data. */ vrc = VERR_NOT_SUPPORTED; } break; } else { /* displaySSMSaveScreenshot did not write any data, if * cbBlock was == 2 * sizeof (uint32_t). */ if (cbBlock > 2 * sizeof (uint32_t)) { vrc = SSMR3Skip(pSSM, cbBlock); AssertRCBreak(vrc); } } } } else { vrc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; } } SSMR3Close(pSSM); } if (RT_SUCCESS(vrc)) { if (u32Type == 0 && cbData % 4 != 0) { /* Bitmap is 32bpp, so data is invalid. */ vrc = VERR_SSM_UNEXPECTED_DATA; } } if (RT_SUCCESS(vrc)) { *ppu8Data = pu8Data; *pcbData = cbData; *pu32Width = u32Width; *pu32Height = u32Height; LogFlowFunc(("cbData %d, u32Width %d, u32Height %d\n", cbData, u32Width, u32Height)); } LogFlowFunc(("vrc %Rrc\n", vrc)); return vrc; }