ms_com2

Upload: shrihn

Post on 14-Apr-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/30/2019 MS_COM2

    1/10

    Chapter 2: Creating a Client of a COM ObjectIn this chapter, you will learn about creating a client of a COM object in C++. Throughout this course, youwill see that COM's fundamental programming model does not change by referring back to this client.

    ObjectivesAfter completing this chapter, you will be able to:

    Explain how COM uses strings.

    Write code to initialize and uninitialize COM services.

    Explain CLSIDs, ProgIDs, their use in the registry, and how COM system services and clientapplications use them.

    Write code that creates and uses a simple COM object.

  • 7/30/2019 MS_COM2

    2/10

    14 Chapter 2: Creating a Client of a COM Object

    Notes

    How COM Uses StringsCOM serves component software developers in every country. To serve languages in different countries,COM uses Unicode characters internally, both on Windows NTand Windows 95.

    A Unicode character is a 16-bit character capable of encoding all known characters. All of the COM APIsthat take strings expect Unicode characters. Strings returned from many of the standard interfaces are

    also Unicode.

    Conversion MacrosTypically, you see Unicode characters used in functions such as CLSIDFromProgID. The prototype forthe CLSIDFromProgID function is:

    HRESULT CLSIDFromProgID(LPCOLESTR lpszProgID, LPCLSID pclsid);

    The data type LPCOLESTR is created by a series of typedef statements in the wtypes.h file:

    typedef wchar_t WCHAR;

    typedef WCHAR OLECHAR;

    typedef const OLECHAR * LPCOLESTR;

    The wchar_t is a 16-bit wide data type, which is what comprises a Unicode character. You use theOLESTR macro to convert a string literal to an LPCOLESTR data type, as seen in the following examplecode:

    CLSIDFromProgID(OLESTR("Simple.Object"),...);

    When you convert a char array, you use a string conversion macro, such as A2COLE. For moreinformation about string conversion macros, see the online Help in Microsoft Developer Studio.

    Conversion FunctionsThere are also many functions for converting strings that are available in the Win32API and the C run-time library. The Win32 API functions are MultiByteToWideChar and WideCharToMultiByte . C run-timefunctions include mbstowcs and wcstombs. For more information about the Win32 API and C run-time

    functions, see the online Help in Microsoft Developer Studio.

    The BSTR Data TypeUse the BSTR (Basic string) data type whenever you pass a string between a COM object server and aCOM client. The BSTR is a null-terminated, length-prefixed, double-byte string, which is the native stringtype of Visual Basic. This COM requirement makes it possible to mix the programming language of clientsand servers.

    Two wrapper classes provided by Microsoft Visual C++support the BSTR data type. These classes areCComBSTR and_bstr_t.

  • 7/30/2019 MS_COM2

    3/10

    Chapter 2: Creating a Client of a COM Object 15

    Notes

    The CComBSTR class, which is part of the Active Template Library (ATL), has a full set of methods forperforming string-manipulation operations. The_bstr_t class is a COM support class that also provides afull set of methods for performing string-manipulation operations. In an MFC-based application, it is easierto display objects of the_bstr_t class. To use the _bstr_t class, you include the comdef.h file in yourproject's stdafx.h file.

    You can easily create an instance of the_bstr_t class from char arrays, as shown in the followingexample code:

    char *szArgument = "Mastering";

    _bstr_t bst1(szArgument), bst2;

    bst2 = szArgument;

    To use the CComBSTR wrapper class in a client application, you include the atlbase.h file in theapplication's stdafx.h file. Unlike class_bstr_t, the class CComBSTR does not have a conversion functionthat provides a char pointer.

    Steps for Creating a ClientIn this section, you will learn about the steps for creating a client of a COM object. These steps are alwaysthe same. They are: initializing the COM libraries, activating an object, getting interface pointers,

    manipulating objects through interfaces, and then releasing the interface pointers.

    This section includes the following topics:

    Initializing the COM Libraries

    Getting the CLSID of an Object

    Creating an Instance of an Object

    Using a COM Object

    Uninitializing the COM Libraries

    Initializing the COM LibrariesWhen you create a client of a COM object, you first initialize the COM libraries by calling the CoInitialize

    function. You must initialize the COM libraries before you can call their functions. The return value of theCoInitialize function is an HRESULT. This indicates whether the operation succeeded.

    You should pass the return value of a COM function, such as CoInitialize, to the SUCCEEDED or FAILEDmacro.

    In the following example code, the COM libraries are initialized, and then the initialization is verified withthe FAILED macro:

    {

    HRESULT hr;

    hr = CoInitialize(NULL);

    if (FAILED(hr))

    return FALSE;

    ...

    }

  • 7/30/2019 MS_COM2

    4/10

    16 Chapter 2: Creating a Client of a COM Object

    Notes

    For more information about the SUCCEEDED and FAILED macros, see the online Help in MicrosoftDeveloper Studio.

    As an alternative to using the SUCCEEDED or FAILED macros, you can compare the return value of aCOM function against predefined return values. For more information about the return values of anHRESULT, see the online Help in Microsoft Developer Studio.

    In the following example code, the COM libraries are initialized and the return value is compared to the

    S_OK constant to verify that the initialization was successful:

    {

    HRESULT hr;

    hr = CoInitialize(NULL);

    if (S_OK != hr)

    return FALSE;

    ...

    }

    Getting the CLSID of an ObjectAfter initializing the COM libraries, the next step for creating a client is to determine the name of the class

    you want to instantiate.

    CLSIDsTo avoid errors when using any COM object, each class must have a unique name.

    In the Microsoft Windows operating systems, a class name is a 128-bit number known as a CLSID (classidentifier), which is a type of GUID (globally unique identifier).

    CLSIDs are stored in the registry under HKEY_CLASSES_ROOT\CLSID.

    For information about GUIDs, see Identifying Interfaces in Chapter 3: Creating a COM Object.

    ProgIDs

    The CLSID of an object is often mapped to a more readable name, known as a ProgID. ProgIDs are notguaranteed to be unique across computers. The unique class name is the CLSID.

    ProgIDs are usually written in the form library.type.version, although this is by convention only. If youleave off the version number, it is called a version-independent ProgID.

    ProgIDs are stored in the registry under HKEY_CLASSES_ROOT. Under the ProgID key there is usually asubkey named CLSID, which contains the CLSID's value. Under the CLSID subkey, there is usually aProgID subkey, which contains the ProgID's value. This mutual reference enables the two functionsCLSIDFromProgID and ProgIDFromCLSID.

    To see a demonstration of how to locate CLSIDs and ProgIDs in the registry, click this icon.

    (CD-ROM plays the demonstration, "Locating CLSIDs and ProgIDs in the Registry.")

  • 7/30/2019 MS_COM2

    5/10

    Chapter 2: Creating a Client of a COM Object 17

    Notes

    Retrieving the CLSID ProgrammaticallyThe following example code uses the CLSIDFromProgID function to retrieve the CLSID of an objectknowing only its ProgID, and then verifies that the function call was successful:

    {

    ...

    CLSID clsid;

    hr = CLSIDFromProgID(

    OLESTR("Simple.Object"),

    &clsid);

    if (FAILED(hr))

    return FALSE;

    ...

    }

    Creating an Instance of an ObjectTo create an instance of a COM object, use the CoCreateInstance function. You cannot use a language-specific function, such as the C++ new keyword, because it violates the language-independence goal of

    COM. COM will not provide a pointer to the object that is being instantiated; you can provide pointers onlyto interfaces.

    The CoCreateInstance FunctionThe CoCreateInstance function is the functional equivalent of the C++ new keyword. As arguments to theCoCreateInstance function, you supply the CLSID as the first parameter to specify which COM object youwant to create.

    To create an instance of a COM object, use the following function.

    CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext,

    REFIID riid, LPVOID * ppv);

    If you want to create the object as part of a larger object, you use the second parameter. The third

    parameter of the CoCreateInstance function specifies the context in which you want the objectinstantiated (in-process, local server, or remote server). The fourth parameter is the interface ID of theinterface pointer that you want to retrieve. The last parameter is an indirect pointer to the requestedinterface.

    The return value of the CoCreateInstance function is an HRESULT that indicates whether the functionsucceeded. Although by convention the server will zero out the interface pointer if the creation fails, youshould not rely on this convention to test for failure.

  • 7/30/2019 MS_COM2

    6/10

    18 Chapter 2: Creating a Client of a COM Object

    Notes

    Using the CoCreateInstance FunctionThe following example code shows how to create an instance of a COM object by using theCoCreateInstance function:

    {

    ...

    IStream * pStream;

    hr = CoCreateInstance(

    clsid,

    NULL,

    CLSCTX_LOCAL_SERVER,

    IID_IStream,

    (LPVOID *) &pStream);

    ...

    }

    Using a COM ObjectAfter you use the CoCreateInstance function, you will have a pointer to an interface. Use this pointer as

    you would use a pointer to a C++ class.When you have finished with an instance of a COM object, you need to indicate that you no longer needthe instance. You cannot use a language-specific function, such as the C++ delete keyword. Instead, callthe Release function to indicate that the interface pointer is no longer needed.

    The following example code shows how to use an instance of a COM object after ensuring that youcreated it successfully, and how to call the Release function to indicate that the instance of the COMobject is no longer needed:

    {

    ...

    if (SUCCEEDED(hr))

    { // Use the interface pointer

    pStream->Read(...);

    pStream->Release();

    }

    ...

    }

  • 7/30/2019 MS_COM2

    7/10

    Chapter 2: Creating a Client of a COM Object 19

    Notes

    Uninitializing the COM LibrariesAfter releasing the instance of a COM object, you should indicate that the initialized COM libraries are nolonger needed.

    To release the COM libraries, use the CoUninitialize function.

    The following example code shows how to use the CoUninitialize function to release the COM libraries:{

    ...

    CoUninitialize();

    ...

    }

    To see a demonstration of how to create a client of a COM object, click this icon.

    (CD-ROM plays the demonstration, "Creating a Client of a COM Object.")

  • 7/30/2019 MS_COM2

    8/10

    20 Chapter 2: Creating a Client of a COM Object

    Notes

    Self-Check Questions1. How would you reorder the following steps to correctly create a client of a COM object?

    a. Get the CLSID of the COM object.

    b. Release the instance of the COM object.

    c. Use the instance of the COM object.d. Initialize the COM libraries.

    e. Create an instance of the COM object.

    A. a, d, e, c, b

    B. d, a, e, c, b

    C. d, e, c, a, b

    D. a, e, c, b, d

    2. Which one of the following functions initializes the COM libraries?

    A. Initialize

    B. ComInitialize

    C. CoInitialize

    D. CreateInstance

    3. Where in the registry would you find a listing of all the registered ProgIDs?

    A. HKEY_CLASSES_ROOT\CLSID

    B. HKEY_CLASSES_ROOT

    C. HKEY_CLASSES_ROOT\PROGID

    D. HKEY_CLASSES

    4. How does a client application create an instance of a COM object?

    A. By using the new C++ keyword.

    B. By creating the object on the stack like any other variable.

    C. By calling the CoCreateInstance function.

    D. By creating an HRESULT structure and passing it to the CoInitializefunction.

  • 7/30/2019 MS_COM2

    9/10

    Chapter 2: Creating a Client of a COM Object 21

    Notes

    5. Which one of the following is accurate about strings and COM?

    A. To achieve true language independence, you can continue to usewhatever the best string type is for the language you're using.

    B. All COM functions take BSTRs as arguments.

    C. Clients and servers use ANSI strings between them, and COMfunctions, such as CLSIDFromProgID, use BSTRs.

    D. COM uses Unicode character strings exclusively.

  • 7/30/2019 MS_COM2

    10/10

    This page intentionally left blank