Out-Of-Proc-COM-Server:BSTR未正确编组

时间:2011-08-08 14:15:59

标签: c++ visual-studio-2010 com ole

我使用Visual Studio 2010在C ++中开发了一个Out-Of-Proc-COM-Server,以避免Shellextensions(http://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/)中的64位与32位问题。

我在IDL文件中描述了这里的接口(http://msdn.microsoft.com/en-us/library/ms686605%28v=VS.85%29.aspx):

import "unknwn.idl";
[
 object,
 uuid("xx"),
 helpstring("IShellServerx86-Interface")
]
interface IShellServerx86 : IUnknown 
{
   HRESULT ShowFileInfo([in]BSTR file, [out]BSTR* htmlFile, [in]BSTR pathChar);
};

import "unknwn.idl"; [ object, uuid("xx"), helpstring("IShellServerx86-Interface") ] interface IShellServerx86 : IUnknown { HRESULT ShowFileInfo([in]BSTR file, [out]BSTR* htmlFile, [in]BSTR pathChar); };

此文件生成一个Proxy / Stub-DLL,我也注册使用标准Marshaller方法。 如果我现在打电话

创建了服务器,我可以调用方法

IShellServerx86* pShellServer = NULL;
CoCreateInstance(__uuidof(CShellServerx86), NULL, CLSCTX_LOCAL_SERVER,
                 __uuidof(IShellServerx86), (void**)&pShellServer);

并使用创建的参数(客户端):

HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar)

在客户端中BSTR是正确生成的,但是当调用COM方法时(他找到它!)并且我调试到dllhost.exe,参数无效,就像选择了错误的编码一样。我尝试整个项目设置“Unicode”,但没有任何变化。

我是否忘记了任何设置,还是应该尝试其他数据类型进行编组?

提前感谢您的帮助。

编辑:

客户的实施是:

BSTR filebstr = ::SysAllocString(A2OLE(file));
BSTR pathBstr = ::SysAllocString(A2OLE(pathChar));
BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));

服务器方法声明如下:

int CShellWrapperx64Module::ShowFileInfo(IN const char* file, 
                                                    OUT VARIANT &htmlFile,
                                                    IN const char* pathChar)
{...
    ::CoInitialize(NULL);
    IShellServerx86* pShellServer = NULL
    hr = ::CoCreateInstance(__uuidof(CShellServerx86), NULL, 
                           CLSCTX_LOCAL_SERVER, __uuidof(IShellServerx86),
                           (void**)&pShellServer);
    BSTR filebstr = ::SysAllocString(A2OLE(file));
    BSTR pathBstr = ::SysAllocString(A2OLE(pathChar));
    BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
    //Call method of Server
    hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);
    ::CoUninitialize();
    VariantInit(&htmlFile);
    htmlFile.vt = VT_BSTR;
    htmlFile.bstrVal = htmlFileBstr;
}

在服务器和客户端方法中,调试器将BSTR字符串识别为wchar_t * -arrays。但是,例如服务器方法中字符串“file”的内容类似于:0x02546e80“㤈榧”。

编码适用于设置为Multibyte-Encoding(Visual Studio)的所有项目(客户端/服务器)。

EDIT2:

服务器声明为follwed:

HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{...
 //TODO
}

接口的实现:

class IShellServerx86 : public IUnknown {
  public:

  virtual HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar) = 0;

};

......和班级工厂     class CShellServerx86ClassFactory:public IClassFactory {     上市:       CShellServerx86ClassFactory();       〜CShellServerx86ClassFactory();

//CoClass from Interface (Implementation)
class CShellServerx86 : public IShellServerx86 {
 public:
  CShellServerx86();
  virtual ~CShellServerx86();
  //inherited from IUnknown
  ULONG STDMETHODCALLTYPE AddRef(void);
  ULONG STDMETHODCALLTYPE Release(void);
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);

  HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar);

 protected:
  ULONG m_uRefCount;
};

保护:      ULONG m_uRefCount;    };

DLL中的GetClass-Method:

 //inherited methods from IUnknown
 ULONG STDMETHODCALLTYPE AddRef(void);
 ULONG STDMETHODCALLTYPE Release(void);
 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);

 //inherited methods from IClassFactory
 HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, 
                                          REFIID riid, void** ppv);
 HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);

}

1 个答案:

答案 0 :(得分:1)

首先,您必须检查A2OLE在您的案例中产生的内容以及这是SysAllocString()的合适输入。

然后你必须实现//TODO - 正确构建out参数值的被调用者责任。你必须做这样的事情:

HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{
    if( htmlFile == 0 ) {
       return E_POINTER;
    }
    // do useful stuff, generate the string for the htmlFile, then
    *htmlFile = SysAllocString( TheStringForHtmlFileParameter );
    return S_OK;
}

此外,您在调用方中泄露BSTR

BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);

将丢失作为第二个参数传递的BSTR,因为被调用者将创建一个新的BSTR。而只是将其初始化为空指针:

BSTR htmlFileBstr = 0;
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);

此外,您仍然会泄漏所有BSTR,因为完成后您没有拨打SysFreeString()。在您拥有的每个SysFreeString()上调用BSTR,或者更好地使用ATL::CComBSTR_bstr_t等包装类。