Using Visual c++ 6.0, I have created an ATL based .EXE server .
(VC6 as I am dealing with legacy code, a .exe server as I need to test operation in an out of process context, currently the .exe server is essentialy a no op)
I have built and registered the corresponding proxy stub DLL.
I have a client app that does
CoCreateInstance of IUnknown which invokes FinalConstruct in server object and succeeds (so server is correctly invoked)
OleRun of returned IUnknown interface succeeds
QueryInterface on IUnknown pointer for my server object fails with error code of 0x8000402 (No such interface supported) for the IMarshall interface
These steps were copied from (comip.h::CreateInstance)
The problem appears to be that the proxystub dll is not being invoked (it doesn't appear in the Modules list in the IDE, nor in loaded modules list in debug window)
The OleCom Object viewer for my class and interface can be seen here https://skydrive.live.com/redir?resid=AE43106917EBD9E1!191&authkey=!AIOWeS5P3o2mlpw
8891..ca4d is the class interface id for my object
A298...420c is the interface ID for my server object (IDispatch based)
TIA for any assistance
It's possible that your issue is that the component that is implementing the IRunnableObject interface isn't registering itself in the Running Object Table. This will mean that the CoCreateInstance itself will succeed, however, when the object it called on, the RPC code will be unable to find it.
This MSDN page indicates:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms694517(v=vs.85).aspx
Notes to Implementers
The object should register in the running object table if it has a
moniker assigned. The object should not hold any strong locks on itself;
instead, it should remain in the unstable, unlocked state. The object
should be locked when the first external connection is made to the object.
I'm a little worried about why you're also using the IMarshall interface. Normally it's not necessary to write custom marshaling code, thus you won't need to use this interface.
As long as you don't reference a custom interface the default marshaller in ole32.dll or oleauto32.dll will be used. That's most likely why you don't see your proxy being loaded.
In the case of most COM interfaces, the proxies and stubs for standard
marshaling are in-process component objects which are loaded from a
systemwide DLL provided by COM in Ole32.dll.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms692621(v=vs.85).aspx
Related
I have a in-proc COM server for which I want to build 32-bit and 64-bit versions. I can do this with no problem. However, I am encountering some issues when both versions are registered.
I am not using ATL. In my DllRegisterServer function, I am using RegisterTypeLibForUser. I am acquiring the ITypeLib instance for the RegisterTypeLibForUser call by calling LoadTypeLibEx with my DLL's path, and I am using the REGKIND_NONE flag. I am creating my type library using .idl and the MIDL compiler. I am embedding the type library in my .dll as a resource. Given the first two bullets below (where everything works as expected), there doesn't seem to be any issues with the way that I'm doing this.
If I register ONLY 32-bit, everything works fine in a 32-bit client, and I get expected failures in a 64-bit client (class not registered).
If I register ONLY 64-bit, everything works fine in a 64-bit client, and I get expected failures in a 32-bit client (class not registered).
If I register 64-bit followed by 32-bit, everything works fine in a 32-bit client, but I get failures in a 64-bit client. If I then unregister the 32-bit server, the 64-bit client continues to fail. If I re-register the 64-bit server (with or without unregistering), the 64-bit client works.
If I register 32-bit followed by 64-bit, everything works fine in a 64-bit client, but I get failures in a 32-bit client. If I then unregister the 64-bit server, the 32-bit client continues to fail. If I re-register the 32-bit server (with or without unregistering), the 32-bit client works.
It appears that when I register both servers, the latter RegisterTypeLibForUser call does something that screws up the registry settings for the previous RegisterTypeLibForUser call.
As for the errors I'm getting:
CoCreateInstance always works as long as the correct server is registered. In a 32-bit client, CoCreateInstance works as long as the 32-bit server is registered (even if the 64-bit server is also registered). Ditto for 64-bit client with 64-bit server.
In any situation where CoCreateInstance works, I can invoke methods on the object. I can marshal my interfaces between apartments (I'm using the global interface table), and I can invoke methods on the marshaled interfaces.
The errors I'm getting are specifically related to ICallFactory in an apartment to which the interfaces have been marshaled. I can query for ICallFactory on the marshaled interface without any problem. But when I call CreateCall with the IID of my asynchronous interface, I receive the error E_NOINTERFACE.
As mentioned in the previous list, I do not receive this error as long as the server that was last registered is the one with the same target platform as the client.
I'm trying to dig through my registry now and figure out exactly what is being changed as the registrations are happening, but due to the registry redirector, this isn't so simple. I will update this post as I uncover the registry information.
Figured it out.
RegisterTypeLib and RegisterTypeLibForUser always write both 32-bit and 64-bit entries when running on a 64-bit OS (even if the process is 32-bit). This is perfectly acceptable in most cases since it's only the interface and type library metadata that gets written. When the interface key is written, RegisterTypeLib/RegisterTypeLibForUser set ProxyStubClsid32 to the generic, default p/s that is appropriate for the type of interface (dual, oleautomation, etc). However, the generic proxy/stubs do not seem to work with ICallFactory on custom async interfaces. I modified my registration routine to always setup my custom proxy/stub information in both the 32-bit and 64-bit registry keys. This makes sure a later registration doesn't trump this information from a previous registration.
[UPDATE]: In the end, I had to write my own registration routine due to several weaknesses in the available APIS:
RegisterTypeLib and RegisterTypeLibForUser do not write the AsynchronousInterface, SynchronousInterface and NumMethods registry entries. This is because there is no information in the compiled type library that explicitly links the synchronous and asynchronous interfaces. My own registration routine matches interfaces by name -- it finds IXxx interfaces with corresponding AsyncIXxx interfaces (by name only, no method comparison) and sets these registry entries as appropriate.
RegisterTypeLib and RegisterTypeLibForUser always write both 32-bit and 64-bit registry keys, including but not limited to ProxyStubClsid32. This means that registering a type library by this means will overwrite any ProxyStubClsid32 for the opposite architecture that was previously written by other means. To resolve this, one could just register both type libraries (32 and 64) first and then register the proxy/stub dlls. However:
The proxy/stub code generated by the MIDL compiler does not seem to provide any way to register the p/s in the per-user registry. If per-user registration is a requirement, the generated registration routine is of no use.
Even if the generated proxy/stub registration routine could be per-user, if the proxy/stub is merged into the com server dll, there is only one registration opportunity -- the single DllRegisterServer in the single dll. If that routine only writes the ProxyStubClsid32 entry on one side of the registry (32- or 64-bit, not both), the subsequent registration of the dll for the other architecture will change the ProxyStubClsid32 for the first architecture.
I haven't tested some of the apis like CoRegisterPSClsid. Since the documentation says nothing about per-user registration, I would imagine it's not supported.
I have an application which uses an out of process COM server to access a COM object created by an in-proc COM server. This means that the out of process COM server has to load the in process COM DLL to create the final object which it would then return.
For example:
// Create an object which resides in the out of process COM server
container.CoCreateInstance("HelperServerProcess");
// Grab a reference to an object which resides in an in process COM server DLL,
// hosted by the out of process COM server
object = container.GenerateResults();
// Release the object instantiated by the out of process server
container = NULL; // or return, or go out of scope, etc
// This call will fail, because the out of process server has shutdown unloading
// the inproc DLL hosting <object>
object.DoStuff();
However, once the container object is released, the final server process reference (in CoReleaseServerProcess ) is released, and the server shuts down. This results in an E_RPC_SERVER_UNAVAILABLE error when trying to use the result object. At the same time the in-proc DLL hosted in this EXE server still has outstanding objects and therefor returns S_FALSE from CanUnloadNow.
I think adding IExternalConnection to the EXE server 's class factory to manually do reference counting on the remote references will not help, because the objects registered by the DLL in-proc server will use the DLLs class factory and try using IExternalConnection on this factory. Also, if the server spawns interactive child objects in its process space it wouldn't trigger IExternalConnection either way.
It also isn't possible to modify the DLL's reference counting to use CoAddRefServerProcess / CoReleaseServerProcess as the DLL doesn't have access to the container's shutdown code in case it triggers the last release, and third party DLLs can't be changed anyhow.
The only method which I can think of which might work is adding a loop after the server refcount hits zero, which calls CoFreeUnusedLibraries, and then somehow enumerates all loaded COM DLLs and waits until none are loaded and ensures the server refcount is still zero. This would leak processes if a loaded DLL does not implement CanUnloadNow correctly, and involves messing around with low level COM implmentation details which I would like to avoid.
Is there any easier way to ensure that the COM objects instantiated by class factories of in-proc servers keep the process alive, or to enumerate the class factories of DLLs loaded into the current process and query them for the number of references?
Update: Another method which may work, but sounds very much like the sort of things you aren't supposed to do: intercepting every spawned thread in the process, registering a CoInitialize hook via CoRegisterInitializeSpy, and adding server process reference for every thread that currently has COM initialized.
The out-of-proc EXE can delegate the DLL object rather than return it directly. Have GetResults() return an object that the EXE implements, and have that implementation use the DLL internally as needed. This way, the EXE will not be released until the caller releases the EXE's object, thus keeping the EXE's own refcount active. The EXE's object can implement the same interface that the DLL object implements. This way, the caller does not know (or care) that delegation is being used.
I have a C# wrapper over C library.
In C lib I have function which takes callback as input.
In C# I have exposed callback like delegate.
Everything works fine in normal mode but when I try to call same function in remoting mode it gives exception like
Could not load file or assembly.
My scenario for remoting is like
1)SharedLib: I have a c# shared lib which has functions which are wrapper over C functions.
All functions are defined in this lib.
2)Server Console Application: Role of server is to get session from Shredlib and open a port so that client ask server for Session
3)Client Console application: Client listen to port opened by server and get session object from server.It defines a functions having same signature as delegate in sharedlib
On session object client calls method from sharedLib which take callback as input.
Client pass address of method having same signature like delegate to method from sharedLib which expects callback as input.
After this I got exception like "Could not load file or assembly."
If I pass null to parameter which take callback as input then everything works fine in remoting mode also.
So can anybody help in using callback in remoting mode.
Three suggestions:
1) Are the different AppDomains running at the same trust level? The second domain may not have permissions to load assemblies if the trust level is lower.
2) The remote application doesn't have all of the dependencies required available to it in the directories it loads assemblies from.
3) Are both applications running under the same version of .NET? If one is .NET 4.5 and one is .NET 3.5 and there's a .NET 4.0 assembly there, then the second process would not be able to run it.
You could try turning on Fusion assembly binding logging to see if there's a more detailed reason why the load fails.
I have a NDIS driver, which gets listed both in connection properties's installed items list and in device manager; the question is, how do I write an extension which will be used for managing driver's properties, and how to install it?
Of course, a plain GUI program may communicate with the driver, set properties, get version numbers and other statistical info etc, that's what DeviceIoControl exists for; but, does this means that no dedicated interface exists to inform the driver about configuration changes?
It would be pleasant if someone can forward this question to eggheadcafe/osr's ntdev lists.
If you want your network driver to have some UI in the LAN Properties dialog, then you need to do these things:
Create a NotifyObject (if you don't have one already)
A NotifyObject is essentially a COM object associated with your driver. To make one,
Make a DLL that can create your new COM class. (If you use ATL's class factory, it's only a couple lines of code. I highly recommend using ATL for implementing COM objects. This is out-of-scope of the LAN Properties GUI, but you should look up DllGetClassObject, a C++ class that inherits from CComObjectRoot and CComCoClass, a call to OBJECT_ENTRY_AUTO, and a BEGIN_COM_MAP if you're new to COM.)
Associate your COM object with the driver by putting ClsId={guid} and ComponentDll=filename into your INF.
Implement INetCfgComponentPropertyUi on your COM object
The key method is MergePropPages. In this method, you allocate propertysheet pages and merge them into the adapter properties. This operation looks something like this pseudocode:
HPROPSHEETPAGE *psharray = CoTaskMemAlloc(NUMBER_OF_PAGES * sizeof(HPROPSHEETPAGE);
for (i = 0; i < NUMBER_OF_PAGES; i++)
psharray[i] = CreatePropertySheetPage(&psp);
The API is meant to be transactional. Make sure to apply any changes in the ApplyProperties method, and (if applicable) undo them in CancelProperties.
You don't need to do anything in QueryPropertyUi or SetContext, although you might want to save the context if you need to get the registry key location.
Test your changes
If all goes well, then your new Notify Object will be loaded up every time there are any network configuration changes. If the GUI is being displayed, then Windows will query your class for the INetCfgComponentPropertyUi interface and call MergePropPages.
I find it helpful to put hardcoded breakpoints in my DLL at key locations, and then attach a kernel debugger so that I can always find the DLL, no matter which process is loading it. (On Windows 7, you'll be loaded in drvinst.exe, which can be hard to find with a usermode debugger.)
I'm developing an Internet Explorer ActiveX plugin using Qt, and trying to make the installer ensure the plugin is not running before continuing. A standard approach to this is to create a named mutex in the application and try to open it in the installer.
This works fine when built as a standalone .exe, but when the plugin DLL is loaded by either idc.exe (to register the server or handle the type library) or IE itself (after adding a test against argv[0] to skip CreateMutex for the idc runs), the CreateMutex call crashes.
Here's how I'm calling it:
CreateMutex((LPSECURITY_ATTRIBUTES)MUTEX_ALL_ACCESS, FALSE, "mutex_name_here");
Is there a reason this should fail when run within the context of an ActiveX server, but work correctly when running standalone? Is there something else I'm missing here?
The first parameter to CreateMutex() is a pointer to a SECURITY_ATTRIBUTES structure (which contains a pointer to a security descriptor); it's not a set of requested access rights bits, which is what you're passing in. I'm not sure why that would work any better in a standalone application.
You probably want to pass in NULL for the first parameters so the mutex gets created with a default security descriptor.
The Desired Access bits would get passed to OpenMutex().