Вы находитесь на странице: 1из 6

Concerning Proxy/Stub DLLs [modified] Saturday, March 18, 2006 10:36 AM by Lim Bio Liong 1.

A Proxy/Stub DLL is always required under one of the following situations : 1.1 Your COM object resides in an EXE Server. Further note the following : 1.1.1 This is where the use of marshalling is most natural. 1.1.2 In order for your client (a separate EXE application) to use your COM object, marshalling is required. 1.2 Your COM object resides in a DLL Server. Further note the following : 1.2.1 A COM object will always be used by a thread in a client application. 1.2.2 A client thread which uses COM will always reside in an apartment. 1.2.3 A COM object will also always reside in an apartment. 1.2.3 If the apartment of a client thread which uses a COM object is not the same the apartment of the COM object, marshalling will be required. To put things simply, where a COM object is accessed across threads (be it threads of a single process or threads across processes), marshalling may be involved.

2. Even when you are using OLE-automation-compatible types, marshalling will be involved. 2.1 In this case, the standard COM marshaller is used. However, note carefully : 2.1.1 That this is provided that your interface has been assigned the [dual] or the [oleautomation] attribute. 2.1.2 If not, your interface cannot be marshaled using the standard COM marshaler. 2.2 The standard COM marshaler is oleaut32.dll (the standard Proxy/Stub DLL for Ole Automation). 2.2 In this case, you do not have to build any Proxy/Stub DLL in order for your clients to use your interface.

3. If your interface uses non-OLE-automation-compatible types as parameters, or that it uses OLE-automation-compatible parameter types but that it is not marked with the [dual] or [oleautomation] attributes, you would definitely need a Proxy/Stub DLL.

3.1 Note that your Proxy/Stub DLL is meant to be used for interfaces and not implementations. 3.2 For example, if you have an interface IAnInterface, say. And you have two implementations of IAnInterface in two separate DLLs, the two implementations will use the same Proxy/Stub DLL. 3.3 Every interface that is ever defined in a Windows OS will have an entry in the registry (under the HKEY_CLASSES_ROOT\Interface Key). They are registered under their GUIDs. 3.4 You will notice that many of the interface entries have a "ProxyStubClsid32" subkey. 3.5 This subkey contains a GUID which identifies the Proxy/Stub DLL associated with this Interface.

4. If you use the MIDL compiler, the source codes for building a Proxy/Stub DLL for your interface can be generated for you. 4.1 The followig files, generated by the MIDL compiler, are the raw materials for your Proxy/Stub : - *_i.c - *_p.c - dlldata.c where * denotes the name of your COM project. The *_i.c file contains the actual definitions of the IIDs and CLSIDs defined in your COM project IDL file. The *_p.c file contains proxy/stub data specific to the interfaces defined in your IDL file. The dlldata.c file contains macros and code that help to generate basic COM DLL requirements (e.g. DllCanUnloadNow(), DllGetClassObject(), etc).

4.2 Start Visual C++ and create a basic Win32 DLL (non-MFC and non-ATL) project.

4.3 Add the *_i.c, *_p.c and dlldata.c files into this project.

4.4 Create your own .DEF file which should contain the following definitions : LIBRARY <YOUR MODULE NAME>

EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE GetProxyDllInfo

4.5 You will need to supply the following pre-processor definitions to your project : - REGISTER_PROXY_DLL - either _WIN32_WINNT=0x400 - or _WIN32_WINNT=0x500 (if any interfaces has async_uuid attribute) The REGISTER_PROXY_DLL definition will ensure that two of the basic COM DLL required exported functions DllRegisterServer() and DllUnregisterServer() are generated within dlldata.c. The "_WIN32_WINNT=0x400" or "_WIN32_WINNT=0x500" is required otherwise you will face several compilation errors. If any interface has been attributed with "async_uuid" then you will also need to use the correct-versioned "rpcproxy.h" file. If you are not using the correct-versioned one, the compiler will complain of this. The latest MS SDK include directory usually will contain the latest version of "rpcproxy.h". To use this, set $(MSSDK)\include in your "Additional include directories" path (under project settings).

4.6 Your project will also need to link to rpcrt4.lib.

4.7 After building a successful Proxy/Stub DLL project, you must remember to register this DLL. <div class="ForumMod">modified on Thursday, January 29, 2009 12:31 AM</div>
///////////////////////

COM proxy stub dll and why do you need it

EldarM1

28 Feb 2006 9:07 PM

Lets start from the end, after all ordering of posts on a blog make it natural. Please, notice that this post is rather for people starting writing COM, veterans would find it pretty evident. On another hand, remembering all the small details may be bothersome, so I decided to push it to the blog as a reminder. Suppose you implemented your COM object, everything look fine while you test it in DLL or in the same exe file, and now you are trying to host it in EXE or use a threading model different from apartment. The behavior becomes a little puzzling. To start from, your test driver returns 0x80040155 (REGDB_E_IIDNOTREG). What happens? You investigate more, and notice that your class factory CreateInstance method is called all right, it goes through creation, it calls QueryInterface, which also works just, fine, and it returns S_OK, but thats not what you test driver that called CreateInstance gets! Apparently, COM runtime got in the middle, tried something, failed, and returned failure instead of S_OK. Why? You investigate more and notice that Query Interface on your object created by CreateInstance is called several times with some strange IIDs:
{00000003-0000-0000-C000-000000000046} {0000001B-0000-0000-C000-000000000046} {00000018-0000-0000-C000-000000000046} {00000019-0000-0000-C000-000000000046} {4C1E39E1-E3E3-4296-AA86-EC938D896E92}

You check a few of them up and find out that these are marshalling interfaces. But, you wonder, should the default marshaler handle it, if you did not implement them? Yes, it will. But it needs the description of your interfaces. So, either description of interfaces of the proxy stubs should be available. There are two ways to do that: type library (which has a few restrictions) or proxy stub DLL. I will talk about type libraries some other time, for now lets see what traps expect you when creating a proxy stub. First, what do you need for you proxy stub? Surprisingly little just your IDL file. If you do it in Visual Studio, create and empty Win32 DLL project; name it, say, myproxy; drop the IDL file into the folder; and add it to the project as a source file, lets say, its called my.idl. Compile it. You get four more files: my_h.h, my_i.c, my_p.c and dlldata.c. Add all of them except .h file to your project. Now, try to build the project Oops Fatal error C1189: #error : You need a Windows 2000 or later to run this stub because it uses these features: /robust command line switch.

Of course, you can go to project properties, MIDL compiler and uncheck Validate Parameters, but generally /robust flag is a very good thing, so unless you plan to run the object on anything before Windows 2000, you better just set the compiler flag saying that. Go to project properties, C/C++, Preprocessor, Preprocessor Definitions and add ;_WIN32_WINNT=0x0500 in the end of the line. Try to build again Now you should get a bunch of linker errors. Why that? Thats because you are missing COM runtime library in your project. Go to project properties again, Linker, Input, Additional Dependencies, and add rpcrt4.lib to the line (it should be empty anyway, but if there is anything there, just add rpcrt4.lib to the list). Try to build again. Now, it should succeed. Are you done? Not quite. Yes, myproxy.dll is successfully built. But it needs to be registered. This may be done from a command line with regsvr32:
Regsvr32 myproxy.dll

Oops, again:
MyProxy.dll was loaded, but the DllRegisterServer entry point was not found. This file can not be registered.

What happened now? You forgot a .def file that tell to export DLL entry points. You can create it in notepad. Call it myproxy.def, open it in notepad, and type in:
; MyProxy.def LIBRARY MyProxy.dll EXPORTS DllGetClassObject PRIVATE DllCanUnloadNow PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE

Now, you need VS to pick it up. Go to project properties once more, Linker, Input, Module definition file, and enter the file name there. Also, add one more C++ preprocessor directive, if its not there yet: ;REGISTER_PROXY_DLL Rebuild it. Register it now it will succeed. You are done with the proxy dll. Dont forget that, in the process, your IDL was moved to a separate project within the solution, your header file (my_h.h) has moved to another folder, and you still need the header and IID definitions (my_i.c) for your main projects. Otherwise the thing should start to work. Notice, that generally, you would register it with the keys in the installation module. Regsvr32 is just a development time workaround. So, again, a short reminder of what you need to do: 1. Create empty DLL project 2. Set preprocessor definition WIN32_WINNT=0x0500 and REGISTER_PROXY_DLL

3. 4. 5. 6.

Add linker additional dependency rpcrt4.lib Create a def file for your project and set it as the linker module definition file Compile IDL and files, generated out of IDL, into a DLL Register proxy DLL with regsvr32

Вам также может понравиться