Examining the Initial ATL DLL Project Files

 < Free Open Study > 



If you examine the ClassView tab for your new ATL DLL project, you will see a number of familiar-looking functions located under the Globals folder:

click to expand
Figure 6-8: Your initial ATL DLL project.

After the initial compile (which automatically runs MIDL), you will have the complete set of files representing your component housing. The following table lists your new files, grouped by related functionality.

Note 

Of course, the names of many of these files will depend on the name given to your ATL project.

AppWizard Generated Files

Meaning in Life

stdafx.h
stdafx.cpp

Precompiled header files. Includes the core ATL files into your current project.

ATLShapesServer.cpp

Implements the DLL export functions for this server enlisting help from the ATL class, CComModule. Also defines a DllMain() implementation to initialize and terminate the CComModule instance and declares the server's OBJECT_MAP.

ATLShapesServer.def

Exports your DLL functions.

ATLShapesServer.idl

Your project's IDL file, doing nothing more at this point than declaring an empty library statement.

ATLShapesServer.h ATLShapesServer_i.c ATLShapesServer_p.c
dlldata.c
ATLShapesServer.tlb

MIDL-generated files to hold your C/C++ interface bindings, GUID definitions, proxy/stub code (including DLL exports), and the binary type library. Dlldata.c and ATLShapesServer_p.c are generated after you insert an ATL coclass and rerun MIDL.

ATLShapesServerps.mk ATLShapesServerps.def

ATL generated makefile and DEF file to build your stub/proxy DLL using the nmake.exe utility (and thus removing the need to create a separate DLL project to build the stub/proxy DLL).

resource.h
ATLShapesServer.rc

Minimal resource files for this project.

The MIDL-generated files (ATLShapesServer.h, ATLShapesServer_i.c, ATLShapes- Server_p.c, ATLShapesServer.tlb, and dlldata.c) should be no surprise to you at this point, so we will not comment on them further. The following is a more detailed look at the remaining AppWizard generated files.

Initial Project Resources

ATL projects do contain some minimal resources, as defined by your resource.h and ATLShapesServer.rc files. If you expand the subfolders from the ResourceView tab (Figure 6-9) you will see support for a project-wide string table as well as a version information resource.


Figure 6-9: Default ATL resources.

Note 

Much like MFC's CString class, ATL's CComBSTR provides a LoadString() method which reads a string resource from the project's String Table.

To insert additional resources into your ATL projects, go under the Insert | Resource menu selection and select the required resource from the resulting dialog box. Just like an MFC project, each additional resource type results in a new subdirectory.

Precompiled Header Files

Much like an MFC project, ATL provides you with stdafx.h and stdafx.cpp files, working as your project's precompiled headers. Here is a peek inside stdafx.h:

// stdafx.h file #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #define _ATL_APARTMENT_THREADED #include <atlbase.h> extern CComModule _Module;      #include <atlcom.h>

The _ATL_APARTMENT_THREADED symbol marks the default threading model for this server (more on threading in Chapter 7). Note the extern reference to _Module. This object is an instance of ATL's CComModule class that is the backbone for your component housing implementation. This object must be named _Module, as a number of ATL header files (such as <atlcom.h>) reference it by name.

Note 

By way of a friendly reminder, be aware that each and every *.cpp file in your ATL projects (including those you create by hand) must include stdafx.h as the very first line, or else you will get the dreaded: "fatal error C1010: unexpected end of file while looking for precompiled header directive" compiler error.

The Skeleton IDL File

The generated IDL file contains just enough code to force MIDL to generate an empty type library for the server. Notice that you have already been provided with a LIBID for the type library, which you are free to change if need be:

// The initial IDL file for ATL COM AppWizard projects. import "oaidl.idl"; import "ocidl.idl"; [      uuid(4A01DCF1-066C-11D3-B8E5-0020781238D4),      version(1.0),      helpstring("ATLShapesServer 1.0 Type Library") ] library ATLSHAPESSERVERLib {      importlib("stdole32.tlb");      importlib("stdole2.tlb"); }; 

The various ATL wizards maintain this file for you in many respects. When you use the ATL Object Wizard to insert coclasses into the component home, the IDL file is automatically updated. However, you will need to edit this file by hand when you wish to define new COM interfaces and/or modify the wizard-generated IDL code.

Your Component Housing File: ATLShapesServer.cpp

The major workhorse in the new project is ATLShapesServer.cpp, which implements the DLL exports for the server. ATL has already included a corresponding DEF file into your project, so the detail of exposing the DLL export functions is of no concern to you. Each of your DLL exports is implemented with help from the ATL class CComModule. Many methods of CComModule make use of an ATL object map.

We have much to say about the object map at a later time; however, for now just understand that each coclass contained in your server must be listed in this map, or else it cannot be created or registered by the ATL framework. Many methods of CComModule will iterate over the object map in order to create class factories, as well as ask a coclass to (un)register itself into the system.

Note 

The CComModule class of ATL provides a similar service as the CWinApp class in MFC. Both classes are used to encapsulate the details of the necessary "goo" for DLL and EXE projects.

Located at the top of ATLShapesServer.cpp is the global instance of the CComModule class and its related object map:

// ATLShapesServer.cpp // _Module encapsulates the details of DLL and EXE server housing. CComModule _Module; // The object map maintains a list of all coclasses contained in the server. BEGIN_OBJECT_MAP(ObjectMap) END_OBJECT_MAP()

After the definition of your CComModule object you find the DLL export functions. The CarInProcServer.dll server we created "in the raw," did not require a DllMain() entry point, as we had no server-level initialization or termination related code. As far as COM is concerned, this DLL export is strictly optional.

In ATL, DllMain() is used to initialize and destroy the CComModule object. When a client process is connecting to the server, the dwReason parameter of DllMain() will be set to DLL_PROCESS_ATTACH. On the other hand, if the DLL is being unloaded, the dwReason parameter is set to DLL_PROCESS_DETACH. Based on this value, CComModule is configured by a call to Init() or Term(), respectively:

// Initialize or terminate the CComModule object based on dwReason. BOOL WINAPI DllMain(     HINSTANCE hInstance,                     DWORD dwReason,                     LPVOID /*lpReserved*/) { ...      if (dwReason == DLL_PROCESS_ATTACH)      {           // Prep the internal state of the CComModule object.            _Module.Init(     ObjectMap, hInstance,                          &LIBID_ATLSHAPESSERVERLib);      }      // Clean up the CComModule object.      else if (dwReason == DLL_PROCESS_DETACH)               _Module.Term();      return TRUE; // ok }

The remainder of ATLShapesServer.cpp contains implementation code for the DLL exports. Given what you already know, you should feel comfortable with the signatures of these methods, and understand when they are called. DllCanUnloadNow() is implemented by a single call to CComModule::GetLockCount(), which returns the number of server locks and active objects in the server:

// Returns S_OK if server contains no active objects and no server locks. STDAPI DllCanUnloadNow(void) {      return (_Module.GetLockCount() == 0) ? S_OK : S_FALSE; }

DllGetClassObject() is implemented by calling the GetClassObject() method of CComModule. GetClassObject() consults the server's object map in order to determine which class factory to create for the client:

// Return a class object pointer (IClassFactory) to the client. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {      return _Module.GetClassObject(rclsid, riid, ppv); }

Finally, ATL in-process servers export the DllRegisterServer() and DllUnregisterServer() functions. When a COM server provides registration logic to the outside world, the server is termed self-registering. Our CarInProcServer.dll server did not implement these functions, but instead relied on a REG file to install the correct registry listings. Not so in ATL! The CComModule class provides methods that automatically install or remove the server's type information: RegisterServer() and UnregisterServer().

// Enter all necessary registry entries into the system registry. STDAPI DllRegisterServer(void) {      // Registers coclasses, typelib, and all interfaces (if marked with      // the [oleautomation] attribute) as defined in the type library      return _Module.RegisterServer(TRUE); } // Remove all necessary registry entries from the system registry. STDAPI DllUnregisterServer(void) {      return _Module.UnregisterServer(TRUE); }



 < Free Open Study > 



Developer's Workshop to COM and ATL 3.0
Developers Workshop to COM and ATL 3.0
ISBN: 1556227043
EAN: 2147483647
Year: 2000
Pages: 171

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net