将VARIANT转换为字节,反之亦然?

我需要能够在系统registry中保存VARIANT (用于COM自动化),然后从那里读取它。

我认为最简单的方法是将其转换为字节数组,然后将其保存(反过来反过来)。问题是我不想开始实现所有数据types的所有可能性VARIANT可能包含(包括对象和数组)。

所以我很好奇,如果有办法做到这一点? (即序列化一个VARIANT。)

在这里找到这个解决方案。 它并没有涵盖所有的角落,但它是迄今为止我所见过的最接近的:

 STDMETHODIMP CVarToByteArrayCvt::CvtVariantToByteArray(VARIANT srcVariant, VARIANT *retval) { CComVariant vSrcData(srcVariant); // any VARIANT type IStream *pStream; HRESULT hRes; STATSTG statstg; LPBYTE buf; ULONG cbRead, ulStreamSize; USHORT i; VariantClear(retval); hRes = CreateStreamOnHGlobal(NULL, TRUE, &pStream); // IStream based on memory handler if(hRes==S_OK) { if((vSrcData.vt & VT_ARRAY)==0) { // not an array hRes = vSrcData.WriteToStream(pStream); // writes VARIANT to a stream (array of bytes) } else { // special array handling hRes = pStream->Write(&srcVariant.vt, sizeof(VARTYPE), NULL); // stores element type hRes = pStream->Write(&srcVariant.parray->rgsabound[0].lLbound, sizeof(LONG), NULL); // stores lower boundary hRes = pStream->Write(&srcVariant.parray->rgsabound[0].cElements, sizeof(ULONG), NULL); // stores number of elements LPVOID ptr; hRes = SafeArrayAccessData(vSrcData.parray, (LPVOID *)&ptr); switch (vSrcData.vt & (~VT_ARRAY)) { case VT_UNKNOWN: case VT_DISPATCH: { LPUNKNOWN *punkValArr = (LPUNKNOWN *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { CComPtr<IPersistStream> spStream; if(punkValArr[i] != NULL) hRes = punkValArr[i]->QueryInterface(IID_IPersistStream, (void**)&spStream); if(spStream != NULL) OleSaveToStream(spStream, pStream); else WriteClassStm(pStream, CLSID_NULL); } } case VT_UI1: case VT_I1: { BYTE *pbyteValArr = (BYTE *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { hRes = pStream->Write((void *)&pbyteValArr[i], sizeof(BYTE), NULL); } } break; case VT_I2: case VT_UI2: case VT_BOOL: { short *pshortValArr = (short *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { hRes = pStream->Write((void *)&pshortValArr[i], sizeof(short), NULL); } } break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: { long *plongValArr = (long *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { hRes = pStream->Write((void *)&plongValArr[i], sizeof(long), NULL); } } break; case VT_R8: case VT_CY: case VT_DATE: { double *pdoubleValArr = (double *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { hRes = pStream->Write((void *)&pdoubleValArr[i], sizeof(double), NULL); } } break; case VT_BSTR: { BSTR *pbstrValArr = (BSTR *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { CComBSTR bstrVal = pbstrValArr[i]; hRes = bstrVal.WriteToStream(pStream); } } break; case VT_VARIANT: { VARIANT *pvariantValArr = (VARIANT *)ptr; for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++) { CComVariant varVal = pvariantValArr[i]; hRes = varVal.WriteToStream(pStream); } } break; } SafeArrayUnaccessData(vSrcData.parray); }; if(hRes==S_OK) { hRes = pStream->Stat(&statstg, STATFLAG_NONAME); if(hRes==S_OK) { ulStreamSize = (ULONG)statstg.cbSize.QuadPart; retval->vt=VT_ARRAY|VT_UI1; retval->parray = SafeArrayCreateVector(VT_UI1, 0, ulStreamSize); if(retval->parray!=NULL) { hRes = SafeArrayAccessData(retval->parray, (LPVOID *)&buf); if(hRes==S_OK) { _LARGE_INTEGER pos; pos.QuadPart = 0; hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL); hRes = pStream->Read(buf, ulStreamSize, &cbRead); SafeArrayUnaccessData(retval->parray); }; }; }; }; pStream->Release(); }; return hRes; } STDMETHODIMP CVarToByteArrayCvt::CvtByteArrayToVariant(VARIANT srcByteArray, VARIANT *retval) { HRESULT hRes = S_OK; LPBYTE buf; IStream *pStream; ULONG cbWritten; CComVariant destVariant; USHORT i; VariantClear(retval); if(srcByteArray.vt==(VT_ARRAY|VT_UI1)) { // is it really a byte array hRes = SafeArrayAccessData(srcByteArray.parray, (LPVOID *)&buf); if(hRes==S_OK) { hRes = CreateStreamOnHGlobal(NULL, TRUE, &pStream); // IStream based on memory handler if(hRes==S_OK) { _LARGE_INTEGER pos; pos.QuadPart = 0; hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL); hRes = pStream->Write(buf, retval->parray->rgsabound[0].cElements, &cbWritten); if(hRes==S_OK) { hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL); VARTYPE vt; hRes = pStream->Read((LPVOID)&vt, sizeof(VARTYPE), NULL); if((vt & VT_ARRAY)==0) { // not an array hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL); hRes = destVariant.ReadFromStream(pStream); if(hRes==S_OK) VariantCopy(retval, &destVariant); } else { // handling an array retval->vt = vt; LONG lBound; ULONG cElems; LPVOID ptr; hRes = pStream->Read((LPVOID)&lBound, sizeof(LONG), NULL); hRes = pStream->Read((LPVOID)&cElems, sizeof(ULONG), NULL); retval->parray = SafeArrayCreateVector(vt & ~VT_ARRAY, lBound, cElems); hRes = SafeArrayAccessData(retval->parray, &ptr); switch (vt & (~VT_ARRAY)) { case VT_UNKNOWN: case VT_DISPATCH: { LPUNKNOWN *punkArr = (LPUNKNOWN *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { punkArr[i] = NULL; OleLoadFromStream(pStream, ((vt & VT_UNKNOWN)!=0) ? IID_IUnknown : IID_IDispatch, (void**)&punkArr[i]); } } case VT_UI1: case VT_I1: { BYTE *pbyteValArr = (BYTE *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { hRes = pStream->Read((void *)&pbyteValArr[i], sizeof(BYTE), NULL); } } break; case VT_I2: case VT_UI2: case VT_BOOL: { short *pshortValArr = (short *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { hRes = pStream->Read((void *)&pshortValArr[i], sizeof(short), NULL); } } break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: { long *plongValArr = (long *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { hRes = pStream->Read((void *)&plongValArr[i], sizeof(long), NULL); } } break; case VT_R8: case VT_CY: case VT_DATE: { double *pdoubleValArr = (double *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { hRes = pStream->Read((void *)&pdoubleValArr[i], sizeof(double), NULL); } } break; case VT_BSTR: { BSTR *pbstrValArr = (BSTR *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { CComBSTR bstrVal; pbstrValArr[i] = NULL; hRes = bstrVal.ReadFromStream(pStream); pbstrValArr[i] = ::SysAllocString((wchar_t *)bstrVal); } } break; case VT_VARIANT: { VARIANT *pvariantValArr = (VARIANT *)ptr; for(i = 0; i < retval->parray->rgsabound[0].cElements; i++) { CComVariant varVal; hRes = varVal.ReadFromStream(pStream); VariantCopy(&pvariantValArr[i], &varVal); } } break; } SafeArrayUnaccessData(retval->parray); }; }; pStream->Release(); }; SafeArrayUnaccessData(srcByteArray.parray); }; }; return hRes; }