In trying to create an IWIC Factory, the CoCreateInstance function is returning E_INVALIDARG (One or more arguments are invalid). I checked MSDN and I cannot see which of these arguments could be invalid.
IWICImagingFactory* iwicfactory = nullptr;
HRESULT IWFactHRes = CoCreateInstance(CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)iwicfactory
);
Am I missing something?
The final parameter to CoCreateInstance is the
address of pointer variable that receives the interface pointer requested in riid.
Your code currently passes the pointer variable, not the address of it. You have to change
(LPVOID*)iwicfactory
to
(LPVOID*)&iwicfactory
Additional notes:
It is a good idea to use the IID_PPV_ARGS macro, which ensures that IID and interface pointer are in sync as well as removing the need for a cast:
HRESULT IWFactHRes = CoCreateInstance(CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&iwicfactory)
);
COM needs to be initialized on the calling thread before the call to CoCreateInstance. Call either CoInitialize or CoInitializeEx to do so.
Related
How can a Guid be associated with a Runtime Class to be used in the function call winrt::create_instance, so a winrt Runtime Class can be late bound? I don't see how in MIDL 3.0--though Interfaces work with uuid and version. Is this the answer to late binding in WinRT?
I still don't know how to use winrt::create_instance, but I took a really deep look into base.h. I found plenty of guts to late bind to a WinRT component dll using def calls and interop. This is my solution to the problem. It works. Choosing the right way to hold IUnknown was important, and there was some specifics I'm still working out; like why I have to wrap the IUnknown in a winrt::impl::abi_t<> (WinRT/COM conversion?). Using the following code you simply load the dll by file name (with qualified path if not in in the executable directory), and call the class according to it's runtime namespace.classname. It is absolutely not necessary to add the activatableclass to the Packackage.appxmanifest or to reference the winmd. A search shows a lot of people looking for this, but there is a general reluctance to point this out. It's just like COM really, with its own quirks.
UINT32 ret = 0;
void* dllHandle = WINRT_IMPL_LoadLibraryW(L"Project.dll");
if (!dllHandle) { throw; };
void* pProc = WINRT_IMPL_GetProcAddress(dllHandle, "DllGetActivationFactory");
auto DllGetActivationFactory = reinterpret_cast<int32_t(__stdcall*)(void* classId, void** factory)>(pProc);
static const WCHAR* cname = L"namespace.classname";
const UINT32 cnamelen = wcslen(cname);
HSTRING hcname = NULL;
HSTRING_HEADER header;
HRESULT hr = WindowsCreateStringReference(cname, cnamelen, &header, &hcname);
com_ptr< winrt::impl::abi_t<winrt::Windows::Foundation::IActivationFactory> > oCOMActivationFactory{ nullptr };
ret = (*DllGetActivationFactory)(&header, oCOMActivationFactory.put_void());
com_ptr< winrt::impl::abi_t<winrt::Windows::Foundation::IUnknown> > iObj{ nullptr };
ret = oCOMActivationFactory.get()->ActivateInstance(iObj.put_void());
winrt::com_ptr<ProxyServer::ImplementationInterface> iImplementationInterface{ nullptr };
winrt::copy_from_abi(iImplementationInterface, iObj.as<ProxyServer::ImplementationInterface>());
iImplementationInterface.get()->MyFunction();
oCOMActivationFactory.detach();
WindowsDeleteString(hcname);
Docs tell me that SHCreateShellItemArrayFromDataObject might be a simpler way to get a list of files from DataObject than DataObject::GetFiles. I want to use the function in ShellExtInit::Initialize, but cannot figure out how.
I need some kind of IShellItemArray to place the result in, but it is an abstract class so I don't know how to define it. And SHCreateShellItemArrayFromDataObject final argument is supposed to be type void**, which I don't know how to satisfy.
How could I fix the code?
HRESULT MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtObj, HKEY hkeyProgId)
{
[...]
IShellItemArray items; // Class IShellItemArray is abstract
HRESULT hr = SHCreateShellItemArrayFromDataObject(pdtObj, IID_IShellItemArray, &items); // Cannot convert to void**
Interfaces must be accessed by pointers/references only. In this case, you need a pointer variable, and must pass the address of that variable to SHCreateShellItemArrayFromDataObject() (using a type cast) so it can set that pointer to the address of an IShellItemArray-implementing object that the Shell creates for you. For example:
HRESULT MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtObj, HKEY hkeyProgId)
{
...
IShellItemArray *items; // <-- pointer
HRESULT hr = SHCreateShellItemArrayFromDataObject(pdtObj, IID_IShellItemArray, (void**)&items); // <-- type cast
...
}
I'm trying to create a thin wrapper of Windows MMDevice API for Go, and I faced the problem about Windows data types for strings.
According to the documentation of IMMDevice::GetId method, it takes the parameter below:
HRESULT GetId(
[out] LPWSTR *ppstrId
);
And here is my Go code that corresponds to the method above. (github.com/moutend/ywca/immdevice_windows.go:13)
func getId(mmd *IMMDevice, strId *uint16) (err error) {
hr, _, _ := syscall.Syscall(
mmd.VTable().GetId,
2,
uintptr(unsafe.Pointer(mmd)),
uintptr(unsafe.Pointer(strId)),
0)
// ...
}
My understand is that the LPWSTR is the pointer to the array of uint16 values, but it causes invalid pointer error.
What type should I use in this case? Thanks.
It is a pointer to a pointer. The LPWSTR type is a wchar_t* and therefor the parameter in that method is a wchar_t**.
You are not passing in a string buffer for the method to fill. The method will allocate memory with CoTaskMemAlloc and return this memory address back to you after it has been filled. You are responsible for freeing this memory with CoTaskMemAlloc.
The first thing to do is read the documentation for the Windows function.
IMMDevice::GetId
method,
HRESULT GetId(
[out] LPWSTR *ppstrId
);
Parameters
ppstrId [out]
Pointer to a pointer variable into which the method writes the address
of a null-terminated, wide-character string containing the endpoint
device ID. The method allocates the storage for the string. The caller
is responsible for freeing the storage, when it is no longer needed,
by calling the CoTaskMemFree function. If the GetId call fails,
*ppstrId is NULL. For information about CoTaskMemFree, see the Windows SDK documentation.
Return value
If the method succeeds, it returns S_OK. If it fails, possible return
codes include, but are not limited to, the values shown in the
following table.
In particular, "ppstrId [out] Pointer to a pointer variable ..." You have strId *uint16 or *pstrId when I would expect you to have strId **uint16 or *ppstrId.
I have to dynamically load the DLL interface of libxml2 via LoadLibrary and GetProcAddress under Windows. All of the function pointers I've used are properly loaded, except for xmlFree.
xmlFree is not a normal DLL export, but instead a function pointer. GetProcAddress on "xmlFree" will thus return a pointer to a pointer to the xmlFree function.
typedef void (*LibXmlFree) (void* mem);
LibXmlFree xmlFree = GetProcAddress( hModule, "xmlFree" );
This will thus succeed, but calling this function will fail because xmlFree doesn't point to the real function.
How do I create a proper pointer to DLL's xmlFree(void*) export?
To assign the real xmlFree pointer you have to dereference the pointer returned by GetProcAddress.
The first part of the cast specifies the result type, the second part dereferences it with the proper type specification.
xmlFree = (void (__cdecl *)(void *)) *((void (__cdecl **)(void *)) GetProcAddress( hModule, "xmlFree" ));
Same should apply to libxml's other function pointers (malloc, realloc & friends).
There is a funciton to obtain an address xmlFree:
xmlGlobalState xmlMem = {};
xmlMemGet( &xmlMem.xmlFree,
&xmlMem.xmlMalloc,
&xmlMem.xmlRealloc,
&xmlMem.xmlMemStrdup
);
xmlMem.xmlFree( result );
I had similar problem with xmlFree being NULL, while compiling under mingw.
Effectively xmlFree() failed with SIGSEGV.
I'm slightly puzzled by the lack of documentation on the issue, so I may be completely off track here:
When I allocate memory in order to return an object through an unique pointer whose value I have modified, what allocater should I use?
The documentation says that I can provide MIDL_user_allocate() and MIDL_user_free() and the stub will use these -- however that does not make sense in CLSCTX_INPROC_SERVER, as the calling object would need to use (and hence resolve) my allocater.
So, how should I allocate memory here, so that the stub code can properly free the list if the DLL is loaded into SVCHOST, and applications can still use the DLL directly if they so desire.
idl:
HRESULT GetItems([out] DWORD *count, [out, size_is(,count)] ITEM **items);
cpp:
HRESULT STDMETHODCALLTYPE impl::GetBuffer(DWORD *count, ITEM **items)
{
*count = 0;
*items = reinterpret_cast<ITEM *>(/* ??? */);
if(!*items)
return E_OUTOFMEMORY;
*count = 5;
/* fill in items */
return S_OK;
}
From here:
Out-parameters must be allocated by the one called; they are freed by the caller using the standard COM task memory allocator.
where COM task memory allocator is either the set of IMalloc methods or the set of CoTaskMemAlloc()/CoTaskMemRealloc()/CoTaskMemFree() functions that provide the same functionality.
The midl_user-*() functions you mention are used for RPC memory management. You need them in case you deal with RPC interfaces, not COM interfaces.