Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
platform
active.directory
adsi
adsi.iis-admin
base
com_ole
complus_mts
component_svcs
database
directx
gdi
graphics_mm
internet.client
internet.server
internet.server.isapi-dev
localization
mapi
messaging
msi
mslayerforunicode
multimedia
networking
networking.ipv6
sdk_install
security
shell
telephony.tapi_2
telephony.tapi_3
telephony.tsp
telephony.wte
tools
ui
ui_shell
win_base_svcs
win16
  
 
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

Re: Manual instanciation from DLL+CLSID acting weird (WinCE)   
> (...) 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.

Woah, thanks a lot, that sure made my changes easy, all my controls now work 
without registration :-D
I just changed the module handle from 0 to _Module.m_hInst, as I believe it 
might try to load the typelib from the host .exe instead of my dll 
otherwise.

Thanks for the great and fast help!

-- 
Philippe Majerus
http://www.phm.lu
date: Wed, 4 Jan 2006 15:54:47 +0100   author:   Philippe Majerus Use: http://www.phm.lu/?action=email

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us