Я разработал Out-Of-Proc-COM-сервер на C ++ с Visual Studio 2010, чтобы избежать 64-битных и 32-битных проблем в расширениях Shellextensions (http://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/).
Я описал интерфейсы как здесь (http://msdn.microsoft.com/en-us/library/ms686605%28v=VS.85%29.aspx) в IDL-файле:
</p>
<pre><code>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 filebstr = ::SysAllocString(A2OLE(file));
BSTR pathBstr = ::SysAllocString(A2OLE(pathChar));
BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
В клиенте BSTR генерируются правильно, но когда вызывается COM-метод (он его находит!), И я отлаживаю в dllhost.exe параметры недопустимы, так как выбрана неправильная кодировка. Я пытался для всего проекта установить «Юникод», но ничего не изменилось.
Я забыл какие-либо настройки или мне нужно попробовать другие типы данных для сортировки?
Заранее спасибо за помощь.
EDIT:
Реализация клиента:
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;
}
Метод сервера объявлен следующим образом:
HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{...
//TODO
}
В методах сервера и клиента отладчик распознает BSTR-строки как wchar_t * -arrays. Но содержимое, например, для строки «file» в методе сервера выглядит примерно так: 0x02546e80 «㤈 榧».
Кодировка для всех проектов (клиент / сервер) установлена на Multibyte-Encoding (Visual Studio).
EDIT2:
Сервер объявлен следующим образом:
class IShellServerx86 : public IUnknown {
public:
virtual HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar) = 0;
};
Реализация интерфейса:
//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;
};
... и класс-фабрика
Класс CShellServerx86ClassFactory: public IClassFactory {
общественности:
CShellServerx86ClassFactory ();
~ CShellServerx86ClassFactory ();
//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);
защищен:
ULONG m_uRefCount;
};
GetClass-метод из DLL:
STDAPI DllGetClassObject ( REFCLSID rclsid, REFIID riid, void** ppv ) {
if (!::InlineIsEqualGUID(rclsid, __uuidof(CShellServerx86)) ) {
return CLASS_E_CLASSNOTAVAILABLE;
}
*ppv = NULL;
CShellServerx86ClassFactory* pShellServerFac;
pShellServerFac = new CShellServerx86ClassFactory;
if (pShellServerFac == NULL) {
return E_OUTOFMEMORY;
}
pShellServerFac->AddRef();
HRESULT hr = pShellServerFac->QueryInterface(riid, ppv);
pShellServerFac->Release();
return hr;
}