【发布时间】:2019-10-24 10:07:04
【问题描述】:
我正在尝试找出一些 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();
}
【问题讨论】:
-
虽然我认为它曾经可以工作(很久以前),但它不再起作用了,因为 [type]_UserUnmarshal 的第一个参数实际上是指向 USER_MARSHAL_CB 结构的指针(第一个成员是确实是旗帜)。是的,没有这样记录,但这是真的(尝试使用 VARIANT 而不是 BSTR,它只会崩溃)。此结构由 RPC 代码填充(以及当您构建 RPC 接口时 MIDL 构建的内容)。几乎不可能在 RPC 上下文之外使用。如果你想看看它喜欢什么,只需在方法中构建一个包含 BSTR 的简单 idl。
-
PS:序列化一个BSTR,你不需要,只写长度和字节:-)
-
@Simon:下一步是序列化嵌套的 Variant 数组。这只是第一步。
-
您可以尝试 StgSerializePropVariant docs.microsoft.com/en-us/windows/desktop/api/propvarutil/…(将您的 VARIANT* 转换为 PROPVARIANT*)。我知道它适用于相对复杂的东西。
-
@SimonMourier :我根据您的建议创建了一个答案。
标签: c++ com marshalling