|
|
|
date: Tue, 27 Dec 2005 16:32:08 +0100,
group: microsoft.public.platformsdk.com_ole
back
Manual instanciation from DLL+CLSID acting weird (WinCE)
Hello,
I'm trying to code my own CoCreateInstance replacement function in to be
able to instanciate an in-process object that is not yet installed in the
registry, simply from its DLL path and filename, and its ClassID.
Most of the objects I'm using at this time are programmed using ATL as
simple objects, using Single threading and dual interface.
In short, the application should be able to load an object from a dll
located in its folder, without registering anything on the device.
The problem I'm facing is really strange, some objects like Microsoft
VBScript and JScript engines can be instanciated without being installed,
and are working correctly, but my own controls programmed using ATL are
working only if their DLL is _also_ in the \Windows\ folder.
If each dll isn't both in the expected folder (included in szLibFullName
below) and in \Windows\, they seems to instanciate correctly (I get an
IDispatch to them fine), but fails when calling a function through that
dispatch interface with a 80070716 error (The specified resource could not
be found in the file).
VBScript on the other hand works fine when located only in the expected
folder and not registered on the device, I can run scripts and call into
dispatch methods fine.
Storing a copy of the dll in another folder searched by LoadLibrary doesn't
help, it really works only when copied in \Windows\, and storing it only in
the \Windows\ folder ends up in CoLoadLibrary failing, as expected.
Both the app and controls are coded using eVC 4.0 for CE 4.2, ARMv4 and
ARMv4I.
I wrote the following code, not clean yet, but hoping it would be a good
starting point:
#define DLLGETCLASSOBJECT TEXT("DllGetClassObject")
typedef HRESULT (STDMETHODCALLTYPE *PFN_DllGetClassObject) (REFCLSID rclsid,
REFIID riid, LPVOID * ppv);
HRESULT NoRegCreateInstanceFromProgID (LPCOLESTR lpszProgID, LPUNKNOWN
pUnkOuter, REFIID riid, LPVOID* ppv)
{
// some code ending up with szLibFullName being the full path and filename
of the dll containing the COM object, and clsid being the ClassID of the
object I need.
HMODULE hModule = CoLoadLibrary (szLibFullName, TRUE);
if (hModule == NULL)
return E_FAIL;
PFN_DllGetClassObject fnDllGetClassObject;
fnDllGetClassObject = (PFN_DllGetClassObject)GetProcAddress (hModule,
DLLGETCLASSOBJECT);
if (fnDllGetClassObject == NULL)
{
CoFreeLibrary (hModule);
return E_FAIL;
}
IClassFactory *pCF;
hr = fnDllGetClassObject (clsid, IID_IClassFactory, (void **)&pCF);
if (FAILED(hr))
{
CoFreeLibrary (hModule);
return hr;
}
pCF->LockServer(TRUE);
hr = pCF->CreateInstance (NULL, riid, ppv);
if (FAILED(hr))
{
pCF->LockServer(FALSE);
pCF->Release();
CoFreeLibrary (hModule);
return hr;
}
pCF->LockServer(FALSE);
pCF->Release();
return hr;
}
Any suggestion would be welcome, as I'm really out of ideas, it seems to me
the COM library is trying to load something from DLLs at later time and
fails to remember its original path somehow... but I don't see why it would
expect every dll to be in \Windows\, and the fact that the VBScript object
works without any problem is even more confusing...
Thanks for reading,
--
Philippe Majerus
http://www.phm.lu
date: Tue, 27 Dec 2005 16:32:08 +0100
author: Philippe Majerus Use: http://www.phm.lu/?action=email
Re: Manual instanciation from DLL+CLSID acting weird (WinCE)
"Philippe Majerus" <Use: http://www.phm.lu/?action=email> wrote in
message news:OcJG1qvCGHA.916@TK2MSFTNGP10.phx.gbl
> In short, the application should be able to load an object from a dll
> located in its folder, without registering anything on the device.
> The problem I'm facing is really strange, some objects like Microsoft
> VBScript and JScript engines can be instanciated without being
> installed, and are working correctly, but my own controls programmed
> using ATL are working only if their DLL is _also_ in the \Windows\
> folder.
My guess is, you are using IDispatchImpl to implement a dual interface.
IDispatchImpl needs a type library to translate Invoke into calls on
your methods. Normally, the type library is registered and is being
loaded with LoadRegTypeLib. But not in your case.
For your DLLs to work correctly, make sure the type library is bound to
the DLL as a resource (the wizard sets the project up this way by
default, so most likely you already have it), and put 0xFFFF as both
major and minor version template parameters to IDispatchImpl. These are
special values that instruct IDispatchImpl to use GetModuleFileName
followed by LoadTypeLib instead, removing the requirement that the TLB
be registered.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
date: Tue, 27 Dec 2005 12:01:13 -0500
author: Igor Tandetnik
Re: Manual instanciation from DLL+CLSID acting weird (WinCE)
Hi Igor,
> My guess is, you are using IDispatchImpl to implement a dual interface.
Correct.
> IDispatchImpl needs a type library to translate Invoke into calls on your
> methods. Normally, the type library is registered and is being loaded with
> LoadRegTypeLib. But not in your case.
Ah, that's the piece of information I overlooked. I expected the
IDispatchImpl to load the typelib from the module.
Do you know the reason behind their choice of going through the registry in
the default implementation ?
> (...) and put 0xFFFF as both major and minor version template
> parameters to IDispatchImpl. These are special values (...)
Ah, so it seems someone at Microsoft realized being able to load it from the
module instead would be usefull.
Unfortunately that didn't fix the problem, but from some searches I
performed on that magic value, it seems the features have been added in
ATL7, working with eVC4, WinCE is always lagging a bit behind.
I'll try to write a complete test object without ATL at all to check if the
other part of the code is working as expected, then I'll have to find out
how to provide my own implementation of IDispatch in ATL (I'm used to do it
when not using ATL at all, but am not sure about the interdependencies in
ATL and if replacing it is easy).
Thanks for the great information, I've been reading lots of your post when
searching for COM information in newsgroups archives, you definitely helped
me a lot now, but also several times before without even knowing it :-)
--
Philippe Majerus
http://www.phm.lu
date: Wed, 4 Jan 2006 13:55:37 +0100
author: Philippe Majerus Use: http://www.phm.lu/?action=email
Re: Manual instanciation from DLL+CLSID acting weird (WinCE)
"Philippe Majerus" <Use: http://www.phm.lu/?action=email> wrote in
message news:e0Wjq4SEGHA.3820@TK2MSFTNGP12.phx.gbl
>> (...) and put 0xFFFF as both major and minor version template
>> parameters to IDispatchImpl. These are special values (...)
>
> Ah, so it seems someone at Microsoft realized being able to load it
> from the module instead would be usefull.
> Unfortunately that didn't fix the problem, but from some searches I
> performed on that magic value, it seems the features have been added
> in ATL7, working with eVC4, WinCE is always lagging a bit behind.
ATL3 shipped with VC6 doesn't have this feature, either. In this case,
you can implement a custom CComTypeInfoHolder. See
http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_frm/thread/08952df15cef547a/596044931c0e3df4
You specify your CComTypeInfoHolder replacement as the last (normally
omitted) parameter to IDispatchImpl.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
date: Wed, 4 Jan 2006 08:38:45 -0500
author: Igor Tandetnik
|
|