我正在尝试找出一些COM编组功能。最终,我想将深度嵌套的变量数组持久化到文件中,但是我首先尝试使用一个简单的字符串。我意识到这些API是用于远程过程调用的,但是我希望这种序列化也适合文件持久化。
我使用Excel VBA进行了大量工作,发现这种序列化API确实令人大开眼界。
下面的代码将BSTR序列化到缓冲区,缓冲区被复制,这将替代保存到文件或从文件中加载。
当前问题是BSTR_UserUnmarshal引发异常Unhandled exception at 0x7631C762 (KernelBase.dll) in RPCMarshalling.exe: 0x00000057: The parameter is incorrect. occurred
我可能语法错误,因为我正在处理示例代码片段。目的是通过RPC序列化API调用将字符串从srctest转换为desttest。
// RPCMarshalling.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "pch.h"
#include <iostream>
//https://searchcode.com/file/140723732/dlls/oleaut32/tmarshal.c#l-818
typedef struct _marshal_state {
LPBYTE base;
int size;
int curoff;
} marshal_state;
int main()
{
::CoInitialize(0);
CComBSTR srctest("Hello");
marshal_state srcbuf;
memset(&srcbuf, 0, sizeof(srcbuf));
ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
ULONG size = ::BSTR_UserSize(&flags, 0, &srctest);
DWORD newsize = max(size, 256);
(&srcbuf)->base = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize);
if (!(&srcbuf)->base)
return E_OUTOFMEMORY;
::BSTR_UserMarshal(&flags, (&srcbuf)->base + (&srcbuf)->curoff, &srctest);
(&srcbuf)->curoff = size;
std::cout << "Hello World!\n" << size << "\n";
marshal_state destbuf;
memset(&destbuf, 0, sizeof(destbuf));
(&destbuf)->base = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize);
if (!(&destbuf)->base)
return E_OUTOFMEMORY;
/* pretend we are loading from file saved by src buffer */
RtlCopyMemory((&destbuf)->base, (&srcbuf)->base, newsize);
CComBSTR desttest("");
BSTR deststring;
try
{
unsigned char *buffer;
buffer = ::BSTR_UserUnmarshal(&flags, (&destbuf)->base, &deststring);
}
catch (int e)
{
std::cout << "Error:" << e << "\n" << size << "\n";
}
::CoUninitialize();
}
答案 0 :(得分:0)
使用西蒙·穆里尔(Simon Mourier)关于StgSerializePropVariant的建议,实现序列化Variant(按照OP的问题文本)工作的目标的另一种方法
int main()
{
::CoInitialize(0);
CComVariant srctest("Hello");
SERIALIZEDPROPERTYVALUE* serialized;
ULONG cb;
::StgSerializePropVariant((PROPVARIANT*)&srctest, &serialized, &cb);
CComVariant pvDest;
::StgDeserializePropVariant(serialized, cb, (PROPVARIANT*)&pvDest);
CoTaskMemFree(serialized);
CComBSTR strDest(pvDest.bstrVal);
std::cout << "This got serialized:\n" << LPCSTR(_bstr_t(strDest, true)) << "\n";
::CoUninitialize();
}
答案 1 :(得分:0)
实际上,如果目标是序列化,那么为什么不序列化到IStream
int main()
{
::CoInitialize(0);
CComVariant srctest("Hello");
CComPtr<IStream> pStream;
HRESULT hr;
hr = CreateStreamOnHGlobal(NULL, TRUE,(LPSTREAM *) &pStream.p);
if (hr != S_OK) return hr;
hr = srctest.WriteToStream(pStream, VT_BSTR);
if (hr != S_OK) return hr;
{
// stream needs resetting to the start before we
// attempt to read it
LARGE_INTEGER dlibMove;
dlibMove.HighPart = 0;
dlibMove.LowPart = 0;
DWORD dwOrigin;
dwOrigin = 0;
ULARGE_INTEGER libNewPosition;
hr = pStream->Seek(dlibMove, dwOrigin, &libNewPosition);
if (hr != S_OK) return hr;
}
CComVariant pvDest;
hr = pvDest.ReadFromStream(pStream, VT_BSTR);
if (hr != S_OK) return hr;
CComBSTR strDest(pvDest.bstrVal);
std::cout << "This got serialized:\n" << LPCSTR(_bstr_t(strDest, true)) << "\n";
//std::cout << "This got serialized:\n" << strDest.m_str << "\n";
::CoUninitialize();
}