That example loads IExample2.dll
ask IClassFactory pointer using exported function DllGetClassObject()
create object /CreateInstance IExample2 to the pointer pExample2
release IClassFactory
call methods/functions SetString() and GetString()
finally release IExample2
In this way it's easier to develop functions and debug those.
int __cdecl main(void)
{
IClassFactory *pClassFactory;
HMODULE hModule = LoadLibrary(TEXT("iexample2\\IExample2.dll"));
if (!hModule) return 1;
HRESULT (WINAPI*DllGetClassObject)(REFCLSID,REFIID,LPVOID) =
(HRESULT(WINAPI*)(REFCLSID,REFIID,LPVOID))GetProcAddress(hModule, TEXT("DllGetClassObject"));
if (!DllGetClassObject) return 2;
HRESULT hr = DllGetClassObject(&CLSID_IExample2, &IID_IClassFactory, (void**)&pClassFactory);
printf("hr=%X\n", hr);
if (!hr) {
IExample2 *pExample2;
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory, NULL, &IID_IExample2, (void **)&pExample2);
pClassFactory->lpVtbl->Release(pClassFactory);
printf("hr=%X\n", hr);
BSTR bstr1 = SysAllocString(L"test");
pExample2->lpVtbl->SetString(pExample2, bstr1);
BSTR bstr2;
pExample2->lpVtbl->GetString(pExample2, &bstr2);
printf("%ls\n", bstr2);
SysFreeString(bstr2);
pExample2->lpVtbl->Release(pExample2);
}
return 0;
}
Hopefully we see something more in this thread.
Experts could fix code and tell us what other things have to care.
EDIT:
After dll debug next example:#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#pragma comment(lib, "ole32")
#pragma comment(lib, "oleaut32")
#include "IExample2.h"
void ErrorString(HRESULT errno);
int __cdecl main(void)
{
IExample2 *pExample2 = NULL;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(&CLSID_IExample2, NULL, CLSCTX_ALL, &IID_IExample2, (void**)&pExample2);
printf("hr=%X\n", hr);
if (!hr && pExample2) {
printf("hr=%X\n", hr);
BSTR bstr1 = SysAllocString(L"test");
pExample2->lpVtbl->SetString(pExample2, bstr1);
BSTR bstr2;
pExample2->lpVtbl->GetString(pExample2, &bstr2);
printf("%ls\n", bstr2);
SysFreeString(bstr2);
pExample2->lpVtbl->Release(pExample2);
} else ErrorString(hr);
CoUninitialize();
return 0;
}
void ErrorString(HRESULT errno)
{
#define BUFSIZE 1000
static TCHAR szMsgBuf[BUFSIZE];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL, errno
, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
, (LPTSTR) szMsgBuf, BUFSIZE
, NULL);
printf("%Xh %s\n", errno, szMsgBuf);
}
Registration-Free COM manifest
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="IExample2Test.exe" version="1.0.0.0" />
<file name="IExample2.dll">
<comClass progid="IExample2.Test"
clsid="{520F4CFD-61C6-4EED-8004-C26D514D3D19}"
description="IExample2 Control" />
</file>
</assembly>
EDIT: small tool to create manifest lines:#define UNICODE
#define _UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
//int DumpTLib(WCHAR *szFileName)
int __cdecl wmain(int argc, wchar_t **argv)
{
LPTYPELIB pITypeLib;
WCHAR wsGuid[40];
if (!LoadTypeLibEx(argv[1], REGKIND_NONE, &pITypeLib))
{
BSTR bstrLib;
pITypeLib->lpVtbl->GetDocumentation(pITypeLib, -1, &bstrLib, 0, 0, 0);
TLIBATTR *pLibAttr;
pITypeLib->lpVtbl->GetLibAttr(pITypeLib, &pLibAttr);
StringFromGUID2(&pLibAttr->guid, wsGuid, sizeof(wsGuid));
_tprintf(_T("<file name=\"%ls\">\n<typelib tlbid=\"%ls\" />\n"),
argv[1], wsGuid);
pITypeLib->lpVtbl->ReleaseTLibAttr(pITypeLib, pLibAttr);
UINT tiCount = pITypeLib->lpVtbl->GetTypeInfoCount(pITypeLib);
for (UINT i = 0; i < tiCount; i++)
{
TYPEKIND TypeKind;
BSTR bstrName;
LPTYPEINFO pITypeInfo;
pITypeLib->lpVtbl->GetTypeInfoType(pITypeLib, i, &TypeKind);
pITypeLib->lpVtbl->GetDocumentation(pITypeLib, i, &bstrName, 0, 0, 0);
if (!pITypeLib->lpVtbl->GetTypeInfo(pITypeLib, i, &pITypeInfo))
{
TYPEATTR *pTypeAttr;
if (!pITypeInfo->lpVtbl->GetTypeAttr(pITypeInfo, &pTypeAttr))
{
if (TypeKind == TKIND_COCLASS) {
StringFromGUID2(&pTypeAttr->guid, wsGuid, sizeof(wsGuid));
//_tprintf(_T("<comClass clsid=\"%ls\" />\n"), wsGuid);
_tprintf(_T("<comClass clsid=\"%ls\" progid=\"%ls.%ls\"/>\n"),
wsGuid, bstrLib, bstrName);
}
pITypeInfo->lpVtbl->ReleaseTypeAttr(pITypeInfo, pTypeAttr);
}
pITypeInfo->lpVtbl->Release(pITypeInfo);
}
if (bstrName) SysFreeString(bstrName);
}
if (bstrLib) SysFreeString(bstrLib);
_tprintf(_T("</file>\n"));
}
return 0;
}