{"id":318,"date":"2012-07-28T21:33:07","date_gmt":"2012-07-29T01:33:07","guid":{"rendered":"http:\/\/templesystems.com\/?page_id=318"},"modified":"2012-07-28T21:37:17","modified_gmt":"2012-07-29T01:37:17","slug":"318-2","status":"publish","type":"page","link":"https:\/\/templesystems.com\/?page_id=318","title":{"rendered":"COM Tutorial"},"content":{"rendered":"<p>COM Tutorial<\/p>\n<div class=\"Section1\">\n<p class=\"MsoTitle\" style=\"margin-left: 0cm; text-align: left; mso-outline-level: 1;\" align=\"left\"><a name=\"_Toc516485621\"><\/a><a name=\"_Toc43522767\"><\/a><span style=\"mso-bookmark: _Toc516485621;\"><span style=\"font-size: 18.0pt;\">COM &amp; ATL<\/span><\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><span style=\"mso-bookmark: _Toc516485621;\"><strong style=\"mso-bidi-font-weight: normal;\"><span style=\"mso-ansi-language: FR;\" lang=\"FR\">Silan Liu<\/span><\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><span style=\"mso-bookmark: _Toc516485621;\">\u00a0<\/span><\/p>\n<h1><span style=\"mso-bookmark: _Toc516485621;\"><a name=\"_Toc43522133\"><\/a><a name=\"_Ref43522764\"><\/a><a name=\"_Ref43522765\"><\/a><a name=\"_Ref43522766\"><\/a><a name=\"_Toc43522768\"><\/a><span style=\"mso-bookmark: _Ref43522766;\"><span style=\"mso-bookmark: _Ref43522765;\"><span style=\"mso-bookmark: _Ref43522764;\"><span style=\"mso-bookmark: _Toc43522133;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>COM<\/span><\/span><\/span><\/span><\/span><\/h1>\n<p>Basics<\/p>\n<h1><span style=\"mso-bookmark: _Toc516485621;\"><a name=\"_Toc43522768\"><\/a><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522134\"><\/a><a name=\"_Toc43522769\"><\/a><span style=\"mso-bookmark: _Toc43522134;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522769\"><\/a><span style=\"mso-bookmark: _Toc43522134;\">Service Control Manager (SCM)<\/span><\/h2>\n<p class=\"MsoNormal\">A Windows program called Service Control Manager (SCM) does<\/p>\n<p>most of the job in COM server invoking. It finds the server through System Registry,<\/p>\n<p>runs it, has it create the COM object, sets up local\/remote transparency, and<\/p>\n<p>returns an interface pointer to the client.<\/p>\n<p class=\"MsoNormal\">Then the client can directly invoke methods of the COM<\/p>\n<p>object through the pointer, and there is no middleware involved unless it is a<\/p>\n<p>remote server, in which case only RPC is involved.<\/p>\n<h2><a name=\"_Toc43522135\"><\/a><a name=\"_Toc43522770\"><\/a><span style=\"mso-bookmark: _Toc43522135;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522770\"><\/a><span style=\"mso-bookmark: _Toc43522135;\">Interface IUnknown<\/span><\/h2>\n<p class=\"MsoNormal\">All COM interfaces should inherit interface <strong>IUnknown<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interface <strong><span style=\"color: red;\">IUnknown<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>HRESULT QueryInterface(REFIID iid, void** ppvObject);<\/p>\n<p>ULONG AddRef();<\/p>\n<p>ULONG Release();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\">One COM object may be used by multiple clients. The COM<\/p>\n<p>server maintains a reference count for each interface of the object. When one<\/p>\n<p>client asks to create an instance of the interface with <strong>CoCreateInstance<\/strong><\/p>\n<p>or <strong>CoCreateInstanceEx<\/strong>, the COM server will call that interface\u2019s method <strong>AddRef<\/strong><\/p>\n<p>to increment the reference count.<\/p>\n<p class=\"MsoNormal\">When one client is finished with an interface, it should<\/p>\n<p>call its <strong>Release<\/strong> method to decrement the reference count. When the count<\/p>\n<p>reaches zero, the COM server should destroy the COM object.<\/p>\n<p class=\"MsoNormal\">In Visual Basic, a local COM object is automatically<\/p>\n<p>destroyed when leaving scope. To manually delete an object, say<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522771\"><\/a><span lang=\"EN-AU\">Set objAccount = <strong><span style=\"color: red;\">Nothing<\/span><\/strong><\/span><\/p>\n<h2><a name=\"_Toc43522136\"><\/a><a name=\"_Toc43522772\"><\/a><span style=\"mso-bookmark: _Toc43522136;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522772\"><\/a><span style=\"mso-bookmark: _Toc43522136;\">Global Unique ID (GUID)<\/span><\/h2>\n<p class=\"MsoNormal\">Each coclass and interface has its guid, which is a 128-bit<\/p>\n<p>number. For easy use by the programmer, an easy-remember manifest constant is<\/p>\n<p>defined for each guid. In Visual C++ these constants are defined in a header<\/p>\n<p>file e.g. \u201cBank_i.c\u201d, and some entries look like:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">const IID <strong><span style=\"color: red;\">IID_IGreet<\/span><\/strong><\/span><\/p>\n<p>= {0x7A5E6E81,0x3DF8,0x11D3,{0x90,0x3D,0x00,0x10,0x5A,0xA4,0x5B,0xDC}};<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">const IID <strong><span style=\"color: red;\">LIBID_BANKLib<\/span><\/strong><\/span><\/p>\n<p>= {0x0FFBDAA1,0xFCA7,0x11D2,{0x8F,0xF4,0x00,0x10,0x5A,0xA4,0x5B,0xDC}};<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">const CLSID <strong><span style=\"color: red;\">CLSID_Account<\/span><\/strong><\/span><\/p>\n<p>= {0x0FFBDAAE,0xFCA7,0x11D2,{0x8F,0xF4,0x00,0x10,0x5A,0xA4,0x5B,0xDC}};<\/p>\n<p class=\"MsoNormal\">GUID constants such as IID_IGreet and CLSID_Account are not<\/p>\n<p>globally unique, but it does not matter because they live only in the scope of<\/p>\n<p>one application program. The compiler will read the interface definition file<\/p>\n<p>to convert the constant to the corresponding guid.<\/p>\n<p class=\"MsoNormal\">GUIDs for classes are of type <strong>CLSID<\/strong>, and all<\/p>\n<p>variables start with \u201cCLSID_\u201d followed by the class name, such as<\/p>\n<p>\u201cCLSID_Account\u201d. GUIDs for interfaces are of type <strong>IID<\/strong>,and all start with \u201cIID_\u201d followed by the<\/p>\n<p>interface name such as \u201cIID_IAccount\u201d.<\/p>\n<p class=\"MsoNormal\">To convert between CLSID and unicode array:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CLSID clsid;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">&#8230;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">WCHAR * ostr;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT hr = <strong><span style=\"color: red;\">StringFromCLSID<\/span><\/strong>(clsid,<\/span><\/p>\n<p>&amp;ostr);<\/p>\n<p class=\"MsoNormal\">Program \u201cMicrosoft Visual Studio\\Common\\Tools\\<strong>Guidgen.exe<\/strong>\u201d<\/p>\n<p>is used to generate a guid. Choose the format of the guid and press button<\/p>\n<p>\u201cCopy\u201d. The generated guid will be in the clipboard.<\/p>\n<p class=\"MsoNormal\">You can also add it to the \u201cTools\u201d menu with menu \u201cTools |<\/p>\n<p>Customize | Tools\u201d.<\/p>\n<h2><a name=\"_Toc43522137\"><\/a><a name=\"_Toc43522773\"><\/a><span style=\"mso-bookmark: _Toc43522137;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522773\"><\/a><span style=\"mso-bookmark: _Toc43522137;\">OLE\/COM Object Viewer<\/span><\/h2>\n<p class=\"MsoNormal\">OLE\/COM Object Viewer goes through System Registry and<\/p>\n<p>collects all info about each coclass and their interfaces, and put them under<\/p>\n<p>one entry as their \u201cuser names\u201d, which is the help string in the IDL file. You<\/p>\n<p>can find this entry under \u201cAll Objects\u201d entry.<\/p>\n<p class=\"MsoNormal\">The \u201cuser name\u201d entry stores the info about the coclass<\/p>\n<p>itself. Under it there are entries for all the interfaces of this class. Each<\/p>\n<p>entry stores the info about a specific interface.<\/p>\n<p class=\"MsoNormal\">OLD\/COM Object Viewer can be started both from the \u201cStart\u201d<\/p>\n<p>menu and from Visual C++ menu \u201cTools\u201d.<\/p>\n<h2><a name=\"_Toc43522138\"><\/a><a name=\"_Toc43522774\"><\/a><span style=\"mso-bookmark: _Toc43522138;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522774\"><\/a><span style=\"mso-bookmark: _Toc43522138;\">System Registry<\/span><\/h2>\n<p class=\"MsoNormal\">System Registry contains information about the computer.<\/p>\n<p>Under its \u201c<strong>HKEY_CLASSES_ROOT<\/strong>\u201d entry, all information about a coclass is<\/p>\n<p>stored. Under this entry, all coclasses are listed by their <strong>ProgID<\/strong>s.<\/p>\n<p>Among the countless ProgID entries, there are two other entries: one named <strong>CLSID<\/strong>,<\/p>\n<p>under which all coclasses are listed by their guids; the other named <strong>Interface<\/strong>,<\/p>\n<p>under which all interfaces are listed by their guids.<\/p>\n<p class=\"MsoNormal\"><strong>ProgIDs<\/strong> are not guaranteed to be unique. They are<\/p>\n<p>used by some languages that can not directly refer to guids such as VBScript.<\/p>\n<p>VB can directly refer to guids, and can also optionally use ProgIDs. COM<\/p>\n<p>library provides to functions which can go through the System Registry and<\/p>\n<p>convert a ProgID to a CLSID or vice versa:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CLSID clsid;<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">CLSIDFromProgID<\/span><\/strong><span lang=\"EN-AU\">(L&#8221;Cars.Jeep.1&#8243;, &amp;clsid);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">LPOLESTR progid;<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">ProgIDFromCLSID<\/span><\/strong><span lang=\"EN-AU\">(clsid, &amp;progid);<\/span><\/p>\n<p class=\"MsoNormal\">We also need an entry to store some attributes about the<\/p>\n<p>whole server. For each server we can assign an <strong>AppID<\/strong>, under which we<\/p>\n<p>store all those atttributes such as <strong>AccessPermission<\/strong>, <strong>AuthenticationLevel<\/strong>,<\/p>\n<p><strong>DllSurogate<\/strong>, <strong>LunchPermissions<\/strong>, <strong>RemoteServerName<\/strong>, etc. Then<\/p>\n<p>under each coclass entry under HKCR\\CLSID, we add an AppID entry containing the<\/p>\n<p>AppID of the server.<\/p>\n<p class=\"MsoNormal\">When a coclass in invoked, the SCM reads the CLSID entry<\/p>\n<p>under HKCR\\CLSID. If it finds an AppID entry, it will go further to find the<\/p>\n<p>AppID entry under HKCR\\AppID. There it reads more about the server and knows<\/p>\n<p>how to deal with the server. For example, if SCM finds <strong>RemoteServerName<\/strong><\/p>\n<p>entry there containing the name of another computer, it knows that the server<\/p>\n<p>is located oin another computer and it should contact the SCM of that computer.<\/p>\n<p class=\"MsoNormal\">When you call COM library functions such as <strong>CoCreateInstance<\/strong><\/p>\n<p>passing a guid constant such as &#8220;CLSID_CoCar&#8221; or<\/p>\n<p>&#8220;IID_IRegistration&#8221;, the compiler converts the guid contstant to the<\/p>\n<p>real guid by looking up the guid definition file <strong>*_i.c<\/strong>. At run time the<\/p>\n<p>real guid is sent to the API function.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>DLL<\/h3>\n<p>server&#8217;s entries in System Registry<\/p>\n<p class=\"MsoNormal\">A DLL server should have the following basic entries in the<\/p>\n<p>System Registry:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\<strong><span style=\"color: red;\">&lt;ProgID&gt;<\/span><\/strong>\\CLSID<\/span><\/p>\n<p>= &lt;clsid&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\<strong><span style=\"color: red;\">&lt;clsid&gt;<\/span><\/strong> = &lt;ProgID&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\&lt;clsid&gt;\\<strong><span style=\"color: red;\">InprocServer32<\/span><\/strong> = &lt;server full path&gt;<\/span><\/p>\n<p class=\"MsoNormal\">You do not have to register your type library, for VC can<\/p>\n<p>directly #import from any directory, and VB and J++ can browse to find a *.tlb<\/p>\n<p>file. However, if you want to do it, you should add the following type library<\/p>\n<p>entries:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\&lt;clsid&gt;\\TypeLib<\/span><\/p>\n<p>= &lt;libid&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\TypeLib\\&lt;libid&gt; =<\/span><\/p>\n<p>&lt;type library help string&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\TypeLib\\&lt;libid&gt;\\1.0\\0\\Win32<\/span><\/p>\n<p>= &lt;type library full path&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\TypeLib\\&lt;libid&gt;\\1.0\\FLAGS<\/span><\/p>\n<p>= 0<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\TypeLib\\&lt;libid&gt;\\1.0\\HELPDIR<\/span><\/p>\n<p class=\"MsoNormal\">When client calls <strong>CoCreateInstance<\/strong> with a CLSID and a<\/p>\n<p>IID, the COM run time will:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l16 level1 lfo6; tab-stops: list 42.55pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>go to the <strong>HKCR\\CLSID\\&lt;guid&gt;\\InProcServer32<\/strong><\/p>\n<p>entry to find the location of the DLL server.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l16 level1 lfo6; tab-stops: list 42.55pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>load the DLL into process, call its exported <strong>DllGetClassObject<\/strong><\/p>\n<p>function passing the coclass guid to get an <strong>IClassFactory<\/strong> pointer of the<\/p>\n<p>corresponding class factory;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l16 level1 lfo6; tab-stops: list 42.55pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>call the <strong>IClassFactory<\/strong>&#8216;s <strong>CreateInstance<\/strong><\/p>\n<p>method passing the IID of the interface to get a pointer of the interface.<\/p>\n<p class=\"MsoNormal\">You can see in the above process that the guids of the<\/p>\n<p>interfaces are only used inside the class factory. There is no need to store an<\/p>\n<p>entry for an interface in the System Registry.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>EXE<\/h3>\n<p>server&#8217;s entries in System Registry<\/p>\n<p class=\"MsoNormal\">A EXE server should have similar basic entries as a DLL<\/p>\n<p>server except it is <strong>LocalServer32<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\<strong><span style=\"color: red;\">&lt;ProgID&gt;<\/span><\/strong>\\CLSID<\/span><\/p>\n<p>= &lt;clsid&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\<strong><span style=\"color: red;\">&lt;clsid&gt;<\/span><\/strong> = &lt;ProgID&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\&lt;clsid&gt;\\<strong><span style=\"color: red;\">LocalServer32<\/span><\/strong> = &lt;server full path&gt;<\/span><\/p>\n<p class=\"MsoNormal\">Besides these, it should have the following entries for each<\/p>\n<p>interface:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\Interface\\&lt;iid&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\Interface\\ProxyStubClsid =<\/span><\/p>\n<p>&lt;proxy\/stub dll clsid&gt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\Interface\\ProxyStubClsid32<\/span><\/p>\n<p>= &lt;proxy\/stub dll clsid&gt;<\/p>\n<p class=\"MsoNormal\">If you use universal marshaller <strong>oleaut32.dll<\/strong>, which<\/p>\n<p>reads the registered type library and creates proxy\/stub classes on the fly,<\/p>\n<p>you should put the CLSID of <strong>oleaut32.dll<\/strong> under <strong>ProxyStubClsid32<\/strong>, add<\/p>\n<p>the following interface entry, plus all the type library entries:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\Interface\\TypeLib =<\/span><\/p>\n<p>&lt;type library libid&gt;<\/p>\n<p class=\"MsoNormal\">For each interface you invoke, one proxy\/stub object is<\/p>\n<p>instantiated. Therefore, you must set up a correspondence between an interface<\/p>\n<p>and its proxy\/stub DLL server, so that when client invoke an interface, the SCM<\/p>\n<p>can find the corresponding proxy\/stub DLL and create the corresponding<\/p>\n<p>proxy\/stub object from it.<\/p>\n<p class=\"MsoNormal\">For this purpose, the System Registry stores the guids of<\/p>\n<p>the all interfaces of an EXE server under entry <strong>HKCR\\Interface<\/strong>. Under<\/p>\n<p>each interface guid entry there is a <strong>ProxyStubClsid32<\/strong> entry, which<\/p>\n<p>stores the <strong>CLSID<\/strong> of the custom proxy\/stub DLL server which contains the<\/p>\n<p>proxy\/stub coclass for that interface, or the universal marshaller <strong>oleaut32.dll<\/strong>.<\/p>\n<p class=\"MsoNormal\">Therefore, if you use the type library marshalling, you must<\/p>\n<p>register the type library under <strong>HKCR\\TypeLib<\/strong> entry and each interface<\/p>\n<p>entry.<\/p>\n<p class=\"MsoNormal\">System Registry editor can be started at command line by<\/p>\n<p>typing \u201cregedit\u201d, or from OLE\/COM Object Viewer in Visual C++.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522139\"><\/a><a name=\"_Toc43522775\"><\/a><span style=\"mso-bookmark: _Toc43522139;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522775\"><\/a><span style=\"mso-bookmark: _Toc43522139;\">Unicode Handling<\/span><\/h1>\n<h2><a name=\"_Toc43522140\"><\/a><a name=\"_Toc534441136\"><\/a><a name=\"_Toc43522776\"><\/a><span style=\"mso-bookmark: _Toc534441136;\"><span style=\"mso-bookmark: _Toc43522140;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522776\"><\/a><span style=\"mso-bookmark: _Toc534441136;\"><span style=\"mso-bookmark: _Toc43522140;\">Definitions of Different Type of Strings<\/span><\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>wchar_t<\/h3>\n<p class=\"MsoNormal\">In C++ wchar_t is 16-bit wide character represented by <strong>unsigned<\/strong><\/p>\n<p>short:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef wchar_t WCHAR;\/\/ wc,<\/span><\/p>\n<p>16-bit UNICODE character<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef unsigned short wchar_t;<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>LPOLESTR<\/h3>\n<p class=\"MsoNormal\">In C++ LPOLESTR is a 16-bit unicode string represented by<\/p>\n<p>const <strong>unsigned short *<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef OLECHAR __RPC_FAR * LPOLESTR;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef WCHAR OLECHAR;<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>LPCOLESTR<\/h3>\n<p class=\"MsoNormal\">In C++ LPOLESTR is a constant 16-bit unicode string<\/p>\n<p>represented by <strong>const<\/strong> <strong>unsigned short *<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef const OLECHAR __RPC_FAR *LPCOLESTR;<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>LPSTR<\/h3>\n<p class=\"MsoNormal\">In C++ LPSTR is 8-bit multi-byte\/ANSI string represented by<strong><\/strong><\/p>\n<p>char *<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef CHAR *LPSTR, *PSTR;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef char CHAR;<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>LPCSTR<\/h3>\n<p class=\"MsoNormal\">In C++ LPCSTR is 8-bit multi-byte\/ANSI string represented by<strong><\/strong><\/p>\n<p>const char *:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef CONST CHAR *LPCSTR, *PCSTR;<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>TCHAR<\/h3>\n<p class=\"MsoNormal\">In C++ TCHAR is 8-bit character represented by<strong> char<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef char TCHAR, *PTCHAR;<\/span><\/p>\n<h2><a name=\"_Toc534441137\"><\/a><a name=\"_Toc430074\"><\/a><a name=\"_Toc43522141\"><\/a><a name=\"_Toc43522777\"><\/a><span style=\"mso-bookmark: _Toc43522141;\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522777\"><\/a><span style=\"mso-bookmark: _Toc43522141;\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\">CString &lt;=&gt; Multibyte String<\/span><\/span><\/span><\/h2>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">#define m(x) ::MessageBox(NULL, x,<\/span><\/span><\/span><\/p>\n<p>&#8220;Test&#8221;, MB_OK | MB_TOPMOST)<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p>CString cstr(&#8220;Hello the world&#8221;);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ CString::GetBuffer returns a pointer to<\/span><\/span><\/span><\/p>\n<p>its underlying buffer.<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">LPSTR<\/span><\/span><\/span><\/p>\n<p>lpsz = cstr.GetBuffer(cstr.GetLength());<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ Both lpsz and cstr can access the<\/span><\/span><\/span><\/p>\n<p>underlying buffer.<\/p>\n<p>m(lpsz);<\/p>\n<p>m(cstr);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ You can amend the buffer through cstr.<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">cstr<\/span><\/span><\/span><\/p>\n<p>= &#8220;Hi Frank.&#8221;;<\/p>\n<p>m(lpsz);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ You can also amend the buffer through<\/span><\/span><\/span><\/p>\n<p>lpsz, but you can&#8217;t free it.<\/p>\n<p>lpsz[8] = &#8216;!&#8217;;<\/p>\n<p>m(cstr);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\/\/<\/span><\/span><\/span><\/p>\n<p>free(lpsz); <span style=\"color: maroon;\">\/\/ Not allowed! Will cause run-time<\/span><\/p>\n<p>error!<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ After releasing the buffer, lpsz&#8217;s content<\/span><\/span><\/span><\/p>\n<p>becomes undefined<\/p>\n<p>cstr.ReleaseBuffer();<\/p>\n<p>m(cstr);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ If you want to avoid amending the<\/span><\/span><\/span><\/p>\n<p>original content of the CString,<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span style=\"color: maroon;\" lang=\"EN-AU\">\/\/ make a copy.<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">LPSTR<\/span><\/span><\/span><\/p>\n<p>lpszCopy = (LPSTR)malloc(strlen(lpsz));<\/p>\n<p>memset(lpszCopy, 0, strlen(lpsz) + 1);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">strcpy(lpszCopy, lpsz);<\/span><\/span><\/span><\/p>\n<p>m(lpszCopy);<\/p>\n<h2><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><a name=\"_Toc43522142\"><\/a><a name=\"_Toc43522778\"><\/a><span style=\"mso-bookmark: _Toc43522142;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><a name=\"_Toc43522778\"><\/a><span style=\"mso-bookmark: _Toc43522142;\">CString &lt;=&gt; Wide Character String<\/span><\/span><\/span><\/h2>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">void CICPLoginDlg::CStringToWideChar(CString<\/span><\/span><\/span><\/p>\n<p>cstr, wchar_t * pwchar, int size)<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">{<\/span><\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">int<\/span><\/span><\/span><\/p>\n<p>cstrLen = cstr.GetLength();<\/p>\n<p>ASSERT(cstrLen &lt; MAX_LENGTH);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">MultiByteToWideChar<\/span><\/strong>(CP_ACP, MB_PRECOMPOSED,<\/span><\/span><\/span><\/p>\n<p>cstr.GetBuffer(cstrLen),<\/p>\n<p>cstrLen, pwchar, size);<\/p>\n<p>cstr.ReleaseBuffer();<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc430074;\"><span style=\"mso-bookmark: _Toc534441137;\"><span lang=\"EN-AU\">}<\/span><\/span><\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"mso-bookmark: _Toc534441137;\"><a name=\"_Toc43522143\"><\/a><a name=\"_Toc43522779\"><\/a><span style=\"mso-bookmark: _Toc43522143;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><span style=\"mso-bookmark: _Toc534441137;\"><a name=\"_Toc43522779\"><\/a><span style=\"mso-bookmark: _Toc43522143;\">Allocating and Freeing BSTRs with API Functions<\/span><\/span><\/h2>\n<p class=\"MsoNormal\">BSTR stands for basic string. It is a 16-bit Unicode with a<\/p>\n<p>prefix telling the count of the bytes in this string, therefore do not need<\/p>\n<p>NULL at the end.<\/p>\n<p class=\"MsoNormal\">When a server creates and passes out a BSTR, the server<\/p>\n<p>allocates memory space for the BSTR, while the client should deallocate the<\/p>\n<p>memory with a call to API function <strong>SysFreeString<\/strong>.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Creating<\/h3>\n<p>a new BSTR<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr1 = <strong><span style=\"color: red;\">SysAllocString<\/span><\/strong>(<strong><span style=\"color: red;\">L<\/span><\/strong>&#8220;Hello world!&#8221;);<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">OLECHAR<\/span><\/strong><span lang=\"EN-AU\"> * pOleStr = OLESTR(&#8220;Good morning!&#8221;);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr2 = <strong><span style=\"color: red;\">SysAllocString<\/span><\/strong>(pOleStr);<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Modifying<\/h3>\n<p>a BSTR<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">SysReAllocString<\/span><\/strong><span lang=\"EN-AU\">(&amp;bstr1, <strong><span style=\"color: red;\">L<\/span><\/strong>&#8220;Good<\/span><\/p>\n<p>morning!&#8221;);<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Freeing<\/h3>\n<p>a BSTR<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">SysFreeString<\/span><\/strong><span lang=\"EN-AU\">(bstr1);<\/span><\/p>\n<h2><a name=\"_Toc43522144\"><\/a><a name=\"_Toc534441138\"><\/a><a name=\"_Toc43522780\"><\/a><span style=\"mso-bookmark: _Toc534441138;\"><span style=\"mso-bookmark: _Toc43522144;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522780\"><\/a><span style=\"mso-bookmark: _Toc534441138;\"><span style=\"mso-bookmark: _Toc43522144;\">BSTR &lt;=&gt; CString<\/span><\/span><\/h2>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CString cstr(\u201cHello!\u201d);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr = cstr.<strong><span style=\"color: red;\">AllocSysString<\/span><\/strong>();<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr = SysAllocString(L&#8221;Hello<\/span><\/p>\n<p>Frank!&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CString cstr(bstr);<\/span><\/p>\n<h2><a name=\"_Toc43522145\"><\/a><a name=\"_Toc534441139\"><\/a><a name=\"_Toc43522781\"><\/a><span style=\"mso-bookmark: _Toc534441139;\"><span style=\"mso-bookmark: _Toc43522145;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522781\"><\/a><span style=\"mso-bookmark: _Toc534441139;\"><span style=\"mso-bookmark: _Toc43522145;\">BSTR &lt;=&gt; Multibyte String<\/span><\/span><\/h2>\n<p class=\"MsoNormal\">Second, use function <strong>wcstombs<\/strong> (wide character string<\/p>\n<p>to multibyte string) and <strong>mbstowcs<\/strong> (multibyte string to wide character<\/p>\n<p>string):<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr1 = SysAllocString(L&#8221;Hellow<\/span><\/p>\n<p>world!&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">char * buf[80];<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">wcstombs<\/span><\/strong><span lang=\"EN-AU\">(buf, bstr1, 80);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">SysFreeString(bstr1);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">sprintf(buf, &#8220;Good morning!&#8221;);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr2;<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">mbstowcs<\/span><\/strong><span lang=\"EN-AU\">(bstr2, buf, 80);<\/span><\/p>\n<h2><a name=\"_Toc534441140\"><\/a><a name=\"_Toc43522146\"><\/a><a name=\"_Toc43522782\"><\/a><span style=\"mso-bookmark: _Toc43522146;\"><span style=\"mso-bookmark: _Toc534441140;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522782\"><\/a><span style=\"mso-bookmark: _Toc43522146;\"><span style=\"mso-bookmark: _Toc534441140;\">Multibyte String &lt;=&gt; Wide Character String<\/span><\/span><\/h2>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">char<\/span><\/span><\/p>\n<p>* mbstr = &#8220;Hello world!&#8221;;<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">int<\/span><\/span><\/p>\n<p>len1 = <strong><span style=\"color: red;\">strlen<\/span><\/strong>(mbstr);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">wchar_t<\/span><\/span><\/p>\n<p>wcbuf[80];<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">int<\/span><\/span><\/p>\n<p>len2 = <strong><span style=\"color: red;\">sizeof<\/span><\/strong>(wcbuf) \/ <strong><span style=\"color: red;\">sizeof<\/span><\/strong>(wchar_t);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><strong><span style=\"color: red;\" lang=\"EN-AU\">::memset<\/span><\/strong><span lang=\"EN-AU\">(wcbuf, 0,<\/span><\/span><\/p>\n<p>sizeof(wcbuf));<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span style=\"mso-bookmark: _Toc534441140;\"><a name=\"_Toc43522783\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">MultiByteToWideChar<\/span><\/strong><span lang=\"EN-AU\">(<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">CP_ACP, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">MB_PRECOMPOSED, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">mbstr, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">len1, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">wcbuf, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">len2);<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">char<\/span><\/span><\/p>\n<p>buf[300];<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">sprintf(buf,<\/span><\/span><\/p>\n<p>&#8220;wcbuf = %S&#8221;, wcbuf);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">::MessageBox(NULL,<\/span><\/span><\/p>\n<p>buf, NULL, MB_OK);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">wchar_t<\/span><\/span><\/p>\n<p>* wcstr = L&#8221;Hello world!&#8221;;<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">int<\/span><\/span><\/p>\n<p>len3 = <strong><span style=\"color: red;\">wcslen<\/span><\/strong>(wcstr);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">char<\/span><\/span><\/p>\n<p>mbbuf[300];<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">int<\/span><\/span><\/p>\n<p>len4 = <strong><span style=\"color: red;\">sizeof<\/span><\/strong>(mbbuf);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><strong><span style=\"color: red;\" lang=\"EN-AU\">::memset<\/span><\/strong><span lang=\"EN-AU\">(mbbuf, 0, len4);<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span style=\"mso-bookmark: _Toc534441140;\"><a name=\"_Toc43522784\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">WideCharToMultiByte<\/span><\/strong><span lang=\"EN-AU\">(<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">CP_ACP, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">WC_COMPOSITECHECK, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">wcstr, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">len3, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">mbbuf, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">len4, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">NULL, <\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">NULL);<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc534441140;\"><span lang=\"EN-AU\">::MessageBox(NULL,<\/span><\/span><\/p>\n<p>mbbuf, NULL, MB_OK);<\/p>\n<h2><span style=\"mso-bookmark: _Toc534441140;\"><a name=\"_Toc43522147\"><\/a><a name=\"_Toc43522785\"><\/a><span style=\"mso-bookmark: _Toc43522147;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><span style=\"mso-bookmark: _Toc534441140;\"><a name=\"_Toc43522785\"><\/a><span style=\"mso-bookmark: _Toc43522147;\">Converting with ATL Macros<\/span><\/span><\/h2>\n<p class=\"MsoNormal\">ATL provides a group of macros to convert between different<\/p>\n<p>types. Because one convertion involves a series of temporary variables to hold<\/p>\n<p>and swap the string buffers, the space is prepared by macro <strong>USES_CONVERSION<\/strong>,<\/p>\n<p>which should be called before any conversion. They are defined in <strong>&lt;atlconv.h&gt;<\/strong>.<\/p>\n<table class=\"MsoNormalTable\" style=\"margin-left: 33.75pt; border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext;\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr style=\"mso-yfti-irow: 0;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>ANSI to &#8230;<\/strong><\/p>\n<\/td>\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>OLE to &#8230;<\/strong><\/p>\n<\/td>\n<td style=\"width: 123.15pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>TCHAR to &#8230;<\/strong><\/p>\n<\/td>\n<td style=\"width: 123.15pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>wchar_t to &#8230;<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 1;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2BSTR<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2A<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2A<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2A<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 2;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2COLE<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2BSTR<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2BSTR<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2BSTR<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 3;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2CT<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2CA<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2CA<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2CA<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 4;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2CW<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2CT<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2COLE<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2COLE<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 5;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2OLE<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2CW<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2CW<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2CT<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 6;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2T<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2T<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2OLE<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2OLE<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 7; mso-yfti-lastrow: yes;\">\n<td style=\"width: 123.2pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">A2W<\/p>\n<\/td>\n<td style=\"width: 123.2pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">OLE2W<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">T2W<\/p>\n<\/td>\n<td style=\"width: 123.15pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"164\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">W2T<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522786\"><\/a><span lang=\"EN-AU\">USES_CONVERSION;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">MessageBox(NULL, <strong><span style=\"color: red;\">W2A<\/span><\/strong>(bstr),<\/span><\/p>\n<p>NULL, MB_OK);<\/p>\n<h2><a name=\"_Toc43522148\"><\/a><a name=\"_Toc534441141\"><\/a><a name=\"_Toc43522787\"><\/a><span style=\"mso-bookmark: _Toc534441141;\"><span style=\"mso-bookmark: _Toc43522148;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.9.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522787\"><\/a><span style=\"mso-bookmark: _Toc534441141;\"><span style=\"mso-bookmark: _Toc43522148;\">MFC&#8217;s BSTR Helper Class _bstr_t<\/span><\/span><\/h2>\n<p class=\"MsoNormal\">MFC provides class <strong>_bstr_t<\/strong> to wrap BSTR.<strong> _bstr_t<\/strong>&#8216;s<\/p>\n<p>constructor can take many types as input:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( ) throw( );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( const<strong><\/strong><\/span><\/p>\n<p>_bstr_t &amp;s1 ) throw( );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( const<strong><\/strong><\/span><\/p>\n<p>char *s2 ) throw( _com_error );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( const<strong><\/strong><\/span><\/p>\n<p>wchar_t *s3 ) throw( _com_error );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( const<strong><\/strong><\/span><\/p>\n<p>_variant_t &amp;var ) throw ( _com_error );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t( <strong><span style=\"color: red;\">BSTR<\/span><\/strong><\/span><\/p>\n<p>bstr, <strong><span style=\"color: red;\">bool<\/span><\/strong> fCopy ) throw ( _com_error );<\/p>\n<p class=\"MsoNormal\">Its assignment operator = is also overloaded for many types:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t&amp; operator=( const _<strong><span style=\"color: red;\">bstr_t &amp;<\/span><\/strong> s1 ) throw ( );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t&amp; operator=( const <strong><span style=\"color: red;\">char *<\/span><\/strong> s2 ) throw( _com_error );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t&amp; operator=( const <strong><span style=\"color: red;\">wchar_t *<\/span><\/strong> s3 ) throw( _com_error );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t&amp; operator=( const <strong><span style=\"color: red;\">_variant_t &amp;<\/span><\/strong> var ) throw( _com_error );<\/span><\/p>\n<p class=\"MsoNormal\">It has also overloaded +=, +, ! and all comparison<\/p>\n<p>operators.<\/p>\n<p class=\"MsoNormal\">To get a <strong>LPTSTR<\/strong> from<strong> _bstr_t<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t<\/span><\/p>\n<p>bstrt(&#8220;Hello!&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">LPTSTR<\/span><\/p>\n<p>lp1 = <strong><span style=\"color: red;\">(LPTSTR)<\/span><\/strong>bstrt;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">LPTSTR<\/span><\/p>\n<p>lp2 = bstrt.<strong><span style=\"color: red;\">operator char *()<\/span><\/strong>;<\/p>\n<p class=\"MsoNormal\">You can use <strong>_bstr_t<\/strong> anywhere expecting BSTR. If you like,<\/p>\n<p>you can also explicitly cast <strong>_bstr_t<\/strong> to <strong>BSTR<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">_bstr_t bstrt(&#8220;Hello!&#8221;);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr = <strong><span style=\"color: red;\">(BSTR)<\/span><\/strong>bstrt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">SysFreeString(bstr1);<\/span><\/p>\n<p class=\"MsoNormal\"><strong>_bstr_t<\/strong> object does not need to be deallocated. It is<\/p>\n<p>deallocated automatically when it leaves scope.<\/p>\n<p class=\"MsoNormal\">Class <strong>_bstr_t<\/strong> is contained in header file &lt;<strong>comdef.h<\/strong>&gt;.<\/p>\n<h2><a name=\"_Toc43522149\"><\/a><a name=\"_Toc534441142\"><\/a><a name=\"_Toc43522788\"><\/a><span style=\"mso-bookmark: _Toc534441142;\"><span style=\"mso-bookmark: _Toc43522149;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.10.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522788\"><\/a><span style=\"mso-bookmark: _Toc534441142;\"><span style=\"mso-bookmark: _Toc43522149;\">ATL&#8217;s BSTR Helper Class CComBSTR<\/span><\/span><\/h2>\n<p class=\"MsoNormal\">ATL also provides a wrapper class<strong> CComBSTR<\/strong>, which is<\/p>\n<p>more light than <strong>_bstr_t<\/strong>. CComBSTR wraps a BSTR data member <strong>m_str<\/strong>.<\/p>\n<p>Space for <strong>BSTR<\/strong> is allocated in its constructor and deallocated in the<\/p>\n<p>destructor.<\/p>\n<p class=\"MsoNormal\">Its constructor can take <strong>LPCOLESTR<\/strong> or <strong>LPCSTR<\/strong><\/p>\n<p>as input. It can also designate the size of the buffer.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( int nSize );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( int nSize, <strong><span style=\"color: red;\">LPCOLESTR<\/span><\/strong> sz );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( int nSize, <strong><span style=\"color: red;\">LPCSTR<\/span><\/strong> sz );<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( <strong><span style=\"color: red;\">LPCOLESTR<\/span><\/strong><\/span><\/p>\n<p>pSrc );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( <strong><span style=\"color: red;\">LPCSTR<\/span><\/strong><\/span><\/p>\n<p>pSrc );<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR( const CComBSTR&amp; src );<\/span><\/p>\n<p class=\"MsoNormal\">Therefore you can say:<\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">\u00a0<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR comBstr(\u201cHello!\u201d);<\/span><\/p>\n<p class=\"MsoNormal\">To detach <strong>m_str<\/strong> from <strong>CComBSTR<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr = comBstr.<strong><span style=\"color: red;\">Detach<\/span><\/strong>();<\/span><\/p>\n<p class=\"MsoNormal\">To attach a <strong>BSTR<\/strong> to a <strong>CComBSTR<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr =<\/span><\/p>\n<p>SysAllocString(L&#8221;Hello!&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR comBstr;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">comBstr.<strong><span style=\"color: red;\">Attach<\/span><\/strong>(bstr);<\/span><\/p>\n<p class=\"MsoNormal\">To get a copy of <strong>m_str<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR bstr = comBstr.<strong><span style=\"color: red;\">Copy<\/span><\/strong>();<\/span><\/p>\n<p class=\"MsoNormal\">To get the address of <strong>m_str<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR * pBstr = &amp;comBstr.<\/span><\/p>\n<p class=\"MsoNormal\">To free <strong>m_str<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">comBstr.<strong><span style=\"color: red;\">Empty<\/span><\/strong>();<\/span><\/p>\n<p class=\"MsoNormal\">The overloaded assignment operator takes <strong>LPCOLESTR<\/strong> or<\/p>\n<p><strong>LPCSTR<\/strong> as parameter. Therefore, to change the value of <strong>CComBSTR<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComBSTR comBstr();<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">comBstr = L&#8221;Good morning!&#8221;;<\/span><\/p>\n<p class=\"MsoNormal\"><strong>CComBSTR<\/strong> can only be casted to CString, which can be<\/p>\n<p>than casted to <strong>LPCSTR<\/strong> or <strong>LPCTSTR<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">cstr = (CString)comBstr;<\/span><\/p>\n<p class=\"MsoNormal\"><strong>CComBSTR<\/strong> is contained in header file &lt;<strong>atlbase.h<\/strong>&gt;,<\/p>\n<p>which also contains other wrapper classes.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522789\"><\/a><a name=\"_Toc43522150\"><\/a><a name=\"DLL_COM_programming\"><\/a><span style=\"mso-bookmark: _Toc43522789;\"><span style=\"mso-bookmark: _Toc43522150;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><span style=\"mso-bookmark: _Toc43522789;\"><span style=\"mso-bookmark: _Toc43522150;\">DLL and EXE Server Without ATL<\/span><\/span><\/h1>\n<h2><a name=\"_Toc43522151\"><\/a><a name=\"_Toc43522790\"><\/a><span style=\"mso-bookmark: _Toc43522151;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522790\"><\/a><span style=\"mso-bookmark: _Toc43522151;\">Creating a DLL Server in Purely C++ Code<\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>1:create a housing for your DLL<\/p>\n<p class=\"MsoNormal\">Create a new source file with the name of the project, say<\/p>\n<p>CarDll.cpp, with two global variables:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/************* CarDll.cpp *******************<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;windows.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG <strong><span style=\"color: red;\">g_lockCount<\/span><\/strong><\/span><\/p>\n<p>= 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG <strong><span style=\"color: red;\">g_objCount<\/span><\/strong><\/span><\/p>\n<p>= 0;<\/p>\n<p class=\"MsoNormal\">These two global variables are used for life time control of<\/p>\n<p>the DLL server (explained later). The &lt;<strong>windows.h<\/strong>&gt; header file is<\/p>\n<p>the one essential include file required in all Windows source code. It contains<\/p>\n<p>all of the definitions for Windows messages, constants, flag values, data<\/p>\n<p>structures, macros, and other mnemonics that permit the programmer to work<\/p>\n<p>without having to memorize thousands of hexadecimal values and their functions.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>2:define your interfaces<\/p>\n<p class=\"MsoNormal\">Create a header file in any name in an empty DLL project<\/p>\n<p>workspace, say &#8220;interface.h&#8221;, and define your interfaces in it:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/*************** interface.h<\/span><\/p>\n<p>***********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#ifndef _INTERFACES<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define _INTERFACES<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;unknwn.h&gt; \/\/ Needed if<\/span><\/p>\n<p>WIN32_LEAN_AND_MEAN is defined in stdafx.h<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;windows.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">struct IRegistration : public IUnknown<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">virtual HRESULT __stdcall <\/span><\/strong>GetOwner(BSTR *<\/span><\/p>\n<p>pBstrOwner) = 0;<\/p>\n<p>virtual HRESULT __stdcall SetOwner(BSTR bstrOwner) = 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">struct IStatus : public IUnknown<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>virtual HRESULT __stdcall GetSpeed)(int * pnSpeed) = 0;<\/p>\n<p>virtual HRESULT __stdcall SetSpeed)(int nSpeed) = 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#endif<\/span><\/p>\n<p class=\"MsoNormal\">Calling convention<strong> __stdcall<\/strong> defines the way function<\/p>\n<p>call arguments are pushed into stack, poped out, and name-decorating convention<\/p>\n<p>that the compiler uses to identify individual functions.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>3:define guids for interfaces<\/p>\n<p class=\"MsoNormal\">Create a new header file in any name, say iid.h. Use guid<\/p>\n<p>generator <strong>guidgen.exe<\/strong> to directly generate new guids in correct format<\/p>\n<p>for all new interfaces, and assign a constant alias for each guid:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/**************** iid.h<\/span><\/p>\n<p>*********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ {D427CA52-AF28-40a4-A5C2-97EA029DCD0F}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DEFINE_GUID(<strong><span style=\"color: red;\">IID_IRegistration<\/span><\/strong>,<\/span><\/p>\n<p>&nbsp;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">0xd427ca52, 0xaf28, 0x40a4, 0xa5, 0xc2, 0x97,<\/span><\/p>\n<p>0xea, 0x2, 0x9d, 0xcd, 0xf);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ {D518B0BF-3EE1-4976-9B6A-9F3443A2A186}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DEFINE_GUID(<strong><span style=\"color: red;\">IID_IStatus<\/span><\/strong>,<\/span><\/p>\n<p>&nbsp;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">0xd518b0bf, 0x3ee1, 0x4976, 0x9b, 0x6a, 0x9f,<\/span><\/p>\n<p>0x34, 0x43, 0xa2, 0xa1, 0x86);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ {2F481E63-C189-4d99-A705-9F3F2DFB7145}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DEFINE_GUID(<strong><span style=\"color: red;\">CLSID_Car<\/span><\/strong>,<\/span><\/p>\n<p>&nbsp;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">0x2f481e63, 0xc189, 0x4d99, 0xa7, 0x5, 0x9f,<\/span><\/p>\n<p>0x3f, 0x2d, 0xfb, 0x71, 0x45);<\/p>\n<p class=\"MsoNormal\">Create a corresponding source file iid.cpp. Simply include<\/p>\n<p>the following lines in the file:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/***************** iid.cpp<\/span><\/p>\n<p>*********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;stdafx.h&#8221; <\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;windows.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;objbase.h&gt; \/\/ Needed if<\/span><\/p>\n<p>WIN32_LEAN_AND_MEAN defined in stdafx.h<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;initguid.h&gt; \/\/ contains<\/span><\/p>\n<p>definition of DEFINE_GUID<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;iid.h&#8221;<\/span><\/p>\n<p class=\"MsoNormal\">Header file &lt;<strong>initguid.h<\/strong>&gt; should be included<\/p>\n<p>before &#8220;iid.h&#8221;. By putting the lines shown above into a cpp file and<\/p>\n<p>letting the client programming inserting this cpp file into his project, this<\/p>\n<p>precedence is guaranteed.<\/p>\n<p class=\"MsoNormal\">Note that when a client invokes for an IID or CLSID from the<\/p>\n<p>COM run time, the program will first loop up the guid definition file (iid.h in<\/p>\n<p>this case) to acquire the actual guid. That is to say, it is &#8220;<strong>0xd427ca52,<\/strong><\/p>\n<p>0xaf28, 0x40a4, 0xa5, 0xc2, 0x97, 0xea, 0x2, 0x9d, 0xcd, 0xf&#8221; not<\/p>\n<p>&#8220;<strong>IID_IRegistration<\/strong>&#8221; which is passed to the COM run time to be<\/p>\n<p>used to search in the System Registry. This is how the guid helps to maintain<\/p>\n<p>the global uniquenss of a coclass or interface.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>4:create the coclass which implements<\/p>\n<p>the interfaces<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/**************** Car.h<\/span><\/p>\n<p>**********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;interfaces.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class Car : public <strong><span style=\"color: red;\">IRegistration<\/span><\/strong>, public <strong><span style=\"color: red;\">IStatus<\/span><\/strong><\/span><\/p>\n<p>{<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p>Car();<\/p>\n<p>virtual ~Car();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>STDMETHODIMP <strong><span style=\"color: red;\">QueryInterface<\/span><\/strong>(REFIID<\/p>\n<p>riid, void ** ppAny);<\/p>\n<p>STDMETHODIMP_(ULONG) <strong><span style=\"color: red;\">AddRef<\/span><\/strong>();<\/p>\n<p>STDMETHODIMP_(ULONG) <strong><span style=\"color: red;\">Release<\/span><\/strong>();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>STDMETHODIMP GetOwner(BSTR * pBstrOwner);<\/p>\n<p>STDMETHODIMP SetOwner(BSTR bstrOwner);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>STDMETHODIMP GetSpeed(int * pnSpeed);<\/p>\n<p>STDMETHODIMP SetSpeed(int nSpeed);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">private:<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522791\"><\/a><strong><span style=\"color: red;\">ULONG m_refCount<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>char m_pcOwner[80];<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int<\/span><\/p>\n<p>m_nSpeed;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/****************** Car.cpp ************************<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;Car.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;iid.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">extern ULONG g_lockCount;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">extern ULONG g_objCount;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Car::Car()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">m_refCount = 0<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">g_objCount++<\/span><\/strong>;<\/span><\/p>\n<p>::memset(m_pcOwner, 0, 80);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Car::~Car()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">g_objCount&#8211;<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP_(ULONG) Car::<strong><span style=\"color: red;\">AddRef<\/span><\/strong>()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>return ++m_refCount;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP_(ULONG) Car::<strong><span style=\"color: red;\">Release<\/span><\/strong>()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">if(&#8211;m_refCount == 0)<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p><strong><span style=\"color: red;\">delete this<\/span><\/strong>;<\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>else<\/p>\n<p>return m_refCount;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP Car::<strong><span style=\"color: red;\">QueryInterface<\/span><\/strong>(REFIID<\/span><\/p>\n<p>riid, void ** ppAny)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/<\/span><\/p>\n<p>IID_IUnknown is the REFIID of standard interface IUnknown<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">if(riid == IID_IUnknown)<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>\/\/ to avoid confusion caused by virtual inheritance<\/p>\n<p>*ppAny = (IUnknown *)(IStatus *)this;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">else if(riid == IID_IRegistration)<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = (IRegistration *)this;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">else if(riid == IID_IStatus)<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = (IStatus *)this;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>else<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = NULL;<\/p>\n<p>return E_NOINTERFACE;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>((IUnknown *)(*ppAny))-&gt;AddRef();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">return<\/span><\/p>\n<p>S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP Car::GetOwner(BSTR * pBstrOwner)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>mbstowcs(*pBstrOwner, m_pcOwner, 80);<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP Car::SetOwner(BSTR bstrOwner)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>wcstombs(m_pcOwner, bstrOwner, 80);<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP Car::GetSpeed(int * pnSpeed)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*pnSpeed = m_nSpeed;<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP Car::SetSpeed(int nSpeed)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>m_nSpeed = nSpeed;<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\">Macro <strong>STDMETHODIMP<\/strong> and <strong>STDMETHODIMP_(Type)<\/strong> are<\/p>\n<p>used to convert the function into<strong> __stdcall<\/strong> calling convention:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define STDMETHODIMPHRESULT STDMETHODCALLTYPE<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define STDMETHODIMP_(type)type STDMETHODCALLTYPE<\/span><\/p>\n<p class=\"MsoNormal\">Pay attention the cascaded if structure in the <strong>QueryInterface<\/strong><\/p>\n<p>method. In iid.h, we stored some guids and assigned an alias for each of them.<\/p>\n<p>But actually nothing linked one guid\/ alias to one interface.Now here we find the link.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>5:Create one class factory for each<\/p>\n<p>coclass<\/p>\n<p class=\"MsoNormal\">In a separate header and source file, create a corresponding<\/p>\n<p>class factory class for each coclass. When its <strong>CreateInstance<\/strong> method is<\/p>\n<p>called, it simply create an instance of the corresponding coclass, and query<\/p>\n<p>its <strong>QueryInterface<\/strong> method for the passed REFIID.<\/p>\n<p class=\"MsoNormal\">This is where a class factory is matched to its<\/p>\n<p>corresponding coclass.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/***************** CarClassFactory.h<\/span><\/p>\n<p>***********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#ifndef _CARCLASSFACTORY<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define _CARCLASSFACTORY<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;windows.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class CarClassFactory : public <strong><span style=\"color: red;\">IClassFactory<\/span><\/strong> {<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p>CarClassFactory();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">virtual ~CarClassFactory();<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>HRESULT __stdcall QueryInterface(REFIID riid, void ** ppAny);<\/p>\n<p>ULONG __stdcall AddRef();<\/p>\n<p>ULONG __stdcall Release();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522792\"><\/a>HRESULT __stdcall <strong><span style=\"color: red;\">CreateInstance<\/span><\/strong><\/span><\/p>\n<p>(LPUNKNOWN pUnkOuter, REFIID riid, void ** ppAny);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT __stdcall <strong><span style=\"color: red;\">LockServer<\/span><\/strong>(BOOL<\/span><\/p>\n<p>fLock);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">private:<\/span><\/p>\n<p>ULONG m_refCount;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#endif<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/******************** CarClassFactory.cpp<\/span><\/p>\n<p>***********************<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;CarClassFactory.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;car.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">extern<\/span><\/strong><span lang=\"EN-AU\"> ULONG g_lockCount;<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">extern<\/span><\/strong><span lang=\"EN-AU\"> ULONG g_objCount;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CarClassFactory::CarClassFactory()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">m_refCount = 0<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">g_objCount++<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CarClassFactory::~CarClassFactory()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">g_objCount&#8211;<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG <strong><span style=\"color: red;\">__stdcall<\/span><\/strong><\/span><\/p>\n<p>CarClassFactory::AddRef()<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>return ++m_refCount;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG __stdcall CarClassFactory::Release()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">if(&#8211;m_refCount == 0)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p><strong><span style=\"color: red;\">delete this<\/span><\/strong>;<\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return m_refCount;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT <strong><span style=\"color: red;\">__stdcall<\/span><\/strong><\/span><\/p>\n<p>CarClassFactory::QueryInterface(REFIID riid, void ** ppAny)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/<\/span><\/p>\n<p>IID_IUnknown is the REFIID of standard interface IUnknown<\/p>\n<p>if(riid == IID_IUnknown)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = (IUnknown *)this;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>else if(riid == IID_IClassFactory)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = (IClassFactory *)this;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>else<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>*ppAny = NULL;<\/p>\n<p>return E_NOINTERFACE;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>((IUnknown *)(*ppAny))-&gt;AddRef();<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522793\"><\/a><span lang=\"EN-AU\">HRESULT <strong><span style=\"color: red;\">__stdcall<\/span><\/strong><\/span><\/p>\n<p>CarClassFactory::<strong><span style=\"color: red;\">CreateInstance<\/span><\/strong><\/p>\n<p>(LPUNKNOWN pUnkOuter, REFIID riid, void ** ppAny)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>if(pUnkOuter != NULL)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>return CLASS_E_NOAGGREGATION;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522794\"><\/a><strong><span style=\"color: red;\">Car * pCar = new Car()<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522795\"><\/a><strong><span style=\"color: red;\">HRESULT hr = pCar-&gt;QueryInterface(riid, ppAny)<\/span><\/strong>;<\/span><\/p>\n<p>if(FAILED(hr)) delete pCar;<\/p>\n<p>return hr;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT <strong><span style=\"color: red;\">__stdcall<\/span><\/strong><\/span><\/p>\n<p>CarClassFactory::<strong><span style=\"color: red;\">LockServer<\/span><\/strong>(BOOL fLock)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>if(fLock)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">g_lockCount++<\/span><\/strong>;<\/span><\/p>\n<p>else<\/p>\n<p><strong><span style=\"color: red;\">g_lockCount&#8211;<\/span><\/strong>;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\">Note that for this class factory class I did not use <strong>STDMETHOD<\/strong><\/p>\n<p>macros, instead I directly used <strong>__stdcall<\/strong>.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>6:implement exported functions<\/p>\n<p class=\"MsoNormal\">The mission of the exported function <strong>DllGetClassObject<\/strong><\/p>\n<p>is to hand to outside client the <strong>IClassFactory<\/strong> pointer which is implemented<\/p>\n<p>by the class factory. It takes the <strong>REFCLSID<\/strong> of a coclass, create an<\/p>\n<p>instance of its corresponding class factory and query its <strong>QueryInterface<\/strong><\/p>\n<p>for <strong>IClassFactory<\/strong> interface pointer.<\/p>\n<p class=\"MsoNormal\">This is where the <strong>REFCLSID<\/strong> of the coclass is matched<\/p>\n<p>to its corresponding class factory.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;CarClassFactory.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;iid.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG g_lockCount = 0;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ULONG g_objCount = 0;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDAPI <strong><span style=\"color: red;\">DllGetClassObject<\/span><\/strong>(REFCLSID<\/span><\/p>\n<p>rclsid, REFIID riid, void ** ppAny)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>if(rclsid != CLSID_Car)<\/p>\n<p>return CLASS_E_CLASSNOTAVAILABLE;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522796\"><\/a><strong><span style=\"color: red;\">CarClassFactory * pFactory = new CarClassFactory<\/span><\/strong>;<\/span><\/p>\n<p>HRESULT hr = pFactory-&gt;<strong><span style=\"color: red;\">QueryInterface<\/span><\/strong>(riid,<\/p>\n<p>ppAny);<\/p>\n<p>if(FAILED(hr))<\/p>\n<p>delete pFactory;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return hr;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDAPI <strong><span style=\"color: red;\">DllCanUnloadNow<\/span><\/strong>()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>if(g_lockCount == 0 &amp;&amp; g_objCount == 0)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">return S_OK;<\/span><\/p>\n<p>else<\/p>\n<p>return S_FALSE;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>7:export the Dll functions<\/p>\n<p class=\"MsoNormal\">Create a new def file (under source code) with the same name<\/p>\n<p>as the project workspace, which is <strong>CarDll.def<\/strong> to export the Dll<\/p>\n<p>functions:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522797\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">LIBRARY<\/span><\/strong><\/p>\n<p>&#8220;CarDll&#8221;<\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522798\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">EXPORTS<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DllGetClassObject@1<\/span><\/p>\n<p>PRIVATE<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DllCanUnloadNow@2<\/span><\/p>\n<p>PRIVATE<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Step<\/h3>\n<p>8:provide registration information<\/p>\n<p class=\"MsoBodyTextIndent\">Create a new reg file say <strong>CarDll.reg<\/strong> to merge<\/p>\n<p>the server information such as the GUIDs and the location into the System<\/p>\n<p>Registry:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522799\"><\/a><span lang=\"EN-AU\">REGEDIT<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CarDll.Car\\CLSID =<\/span><\/p>\n<p>{2F481E63-C189-4d99-A705-9F3F2DFB7145}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\{2F481E63-C189-4d99-A705-9F3F2DFB7145}<\/span><\/p>\n<p>= CarDll.Car<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HKEY_CLASSES_ROOT\\CLSID\\{2F481E63-C189-4d99-A705-9F3F2DFB7145}\\InprocServer32<\/span><\/p>\n<p>= D:\\My Documents\\Visual C++\\CarDLL\\debug\\CarDll.dll<\/p>\n<p class=\"MsoNormal\">Note that each line is a &#8220;key = value&#8221;. There<\/p>\n<p>should be a space on each side of the equal sign, and no space (including tab)<\/p>\n<p>elsewhere.<\/p>\n<p class=\"MsoNormal\">Double-click this reg file to merge the server information<\/p>\n<p>into the System Registry.<\/p>\n<h2><a name=\"_Toc43522152\"><\/a><a name=\"_Toc43522800\"><\/a><span style=\"mso-bookmark: _Toc43522152;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522800\"><\/a><span style=\"mso-bookmark: _Toc43522152;\">Life Time Control of a Coclass in a DLL Server<\/span><\/h2>\n<p class=\"MsoNormal\">As we can see from the above example, a COM object is<\/p>\n<p>initiated by a client through the exported function <strong>DllGetClassObject<\/strong>,<\/p>\n<p>but is deleted by itself. This is the same with class factories in a DLL.<\/p>\n<p class=\"MsoNormal\">Each coclass has a <strong>ULONG<\/strong> member <strong>m_refCount<\/strong>. In<\/p>\n<p>both the above raw C++ code and ATL\u2019s implementation, each time <strong>QueryInterface<\/strong><\/p>\n<p>successfully hands out an interface pointer, it increments the coclass<\/p>\n<p>reference count by calling <strong>AddRef<\/strong>. Therefore, after you acqure an<\/p>\n<p>interface pointer with <strong>CoCreateInstance<\/strong>, you do not need to call <strong>AddRef<\/strong>.<\/p>\n<p>However, after you make a copy of the interface pointer, you should call <strong>AddRef<\/strong>.<\/p>\n<p>A function receiving an interface pointer as parameter is also making copy of<\/p>\n<p>the pointer and thus should also call <strong>AddRef<\/strong>.<\/p>\n<p class=\"MsoNormal\">Each time you (as a client or a function which receives an<\/p>\n<p>interface pointer as parameter) finishes using an interface, you should call<\/p>\n<p>its <strong>Release<\/strong> method. The coclass implementation of <strong>Release<\/strong> will<\/p>\n<p>decrement <strong>m_refCount<\/strong>, then check whether it reaches zero. If yes, it<\/p>\n<p>will delete itself.<\/p>\n<p class=\"MsoNormal\">The correct deletion of a COM object depends on the correct<\/p>\n<p>operation of the client. If one client calls <strong>AddRef<\/strong> or <strong>Release<\/strong><\/p>\n<p>incorrectly, the COM object may be in memory when it should be deleted, or<\/p>\n<p>deleted when some one is still using it. Especially, if you call any method<\/p>\n<p>after the last <strong>Release<\/strong> call is made, you are stepping into OS\u2019s<\/p>\n<p>territory and your program will be shut down.<\/p>\n<h2><a name=\"_Toc43522153\"><\/a><a name=\"_Toc43522801\"><\/a><span style=\"mso-bookmark: _Toc43522153;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522801\"><\/a><span style=\"mso-bookmark: _Toc43522153;\">Life Time Control of a DLL Server<\/span><\/h2>\n<p class=\"MsoNormal\">A DLL server is both loaded and unloaded by the COM rum<\/p>\n<p>time. When a client calls <strong>DllGetClassObject<\/strong> with the <strong>REFCLSID<\/strong> of<\/p>\n<p>a coclass in the server, SCM will look up the System Registry, find the<\/p>\n<p>directory of the server, load the server up, then call its exported function <strong>DllGetClassObject<\/strong>.<\/p>\n<p class=\"MsoNormal\">A DLL server has two global <strong>ULONG<\/strong> counts affecting<\/p>\n<p>its life time control:<strong> g_objCount<\/strong> and <strong>g_lockCount<\/strong>. The former one<\/p>\n<p>indicates the number of live COM objects in the server and the latter one the<\/p>\n<p>number of locks imposed by clients on the server.<\/p>\n<p class=\"MsoNormal\">The constructor of a coclass and a class factory in a DLL is<\/p>\n<p>supposed to increment the <strong>g_objCount<\/strong>. Its destructor is supposed to<\/p>\n<p>decrement <strong>g_objCount<\/strong>. On the other hand, for performance reason, a<\/p>\n<p>client may decide to to load the server into memory first, and create COM<\/p>\n<p>objects later. To lock the server, he calls its <strong>LockServer<\/strong> method<\/p>\n<p>passing TRUE, which will then increment the <strong>g_lockCount<\/strong>. To release the<\/p>\n<p>lock, the client calls the same method passing FALSE.<\/p>\n<p class=\"MsoNormal\">Only when both of these two locks reaches zero, will the<\/p>\n<p>DLL\u2019s exported function <strong>DllCanUnloadNow<\/strong> return true. SCM will call this<\/p>\n<p>function at intervals to check whether the server can be unloaded. If yes it<\/p>\n<p>will unload the DLL from the memory. If a client wants the SCM to check this<\/p>\n<p>function and unload the server immediately if possible, it can call API<\/p>\n<p>function <strong>CoFreeUnusedLibraries<\/strong>.<\/p>\n<p class=\"MsoNormal\">Because DLL class factories also have to delete themselves,<\/p>\n<p>the server can not be unloaded before all objects including class objects are<\/p>\n<p>done. That\u2019s why in DLL server class factories also affect the server reference<\/p>\n<p>counting.<\/p>\n<h2><a name=\"_Toc43522154\"><\/a><a name=\"_Toc43522802\"><\/a><span style=\"mso-bookmark: _Toc43522154;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522802\"><\/a><span style=\"mso-bookmark: _Toc43522154;\">EXE Server in Raw C++ Code<\/span><\/h2>\n<p class=\"MsoNormal\">Because coclasses in EXE server are the same as those in DLL<\/p>\n<p>server, and class factories has only one difference that it does not affect any<\/p>\n<p>reference count, their code is omitted here:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522803\"><\/a><span lang=\"EN-AU\">DWORD g_allLocks;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int APIENTRY WinMain(HINSTANCE hInstance,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HINSTANCE hPrevInstance,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">LPSTRlpCmdLine,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">intnCmdShow)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522804\"><\/a>CoInitialize(NULL);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/<\/span><\/p>\n<p>register the type lib<\/p>\n<p>ITypeLib* pTLib = NULL;<\/p>\n<p>LoadTypeLibEx(L&#8221;AnyEXETypeInfo.tlb&#8221;, REGKIND_REGISTER,<\/p>\n<p>&amp;pTLib);<\/p>\n<p>pTLib-&gt;Release();<\/p>\n<p>if(strstr(lpCmdLine, &#8220;\/Embedding&#8221;) || strstr(lpCmdLine,<\/p>\n<p>&#8220;-Embedding&#8221;))<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522805\"><\/a><strong><span style=\"color: red;\">AnyClassFactory cf<\/span><\/strong>; \/\/ class factories created as<\/span><\/p>\n<p>local objects<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>DWORD regID = 0;<\/p>\n<p>CoRegisterClassObject(CLSID_Any,<\/p>\n<p>(IClassFactory*)&amp;cf,<\/p>\n<p>CLSCTX_LOCAL_SERVER,<\/p>\n<p>REGCLS_MULTIPLEUSE,<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">&amp;regID);<\/span><\/p>\n<p>MSG ms;<\/p>\n<p>while(GetMessage(&amp;ms, 0, 0, 0))<\/p>\n<p>{<\/p>\n<p>TranslateMessage(&amp;ms);<\/p>\n<p>DispatchMessage(&amp;ms);<\/p>\n<p>}<\/p>\n<p>CoRevokeClassObject(regID);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>CoUninitialize();<\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void Lock()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">++g_allLocks;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void UnLock()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>&#8211;g_allLocks;<\/p>\n<p>if(g_allLocks == 0)<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">PostQuitMessage<\/span><\/strong>(0);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<h2><a name=\"_Toc43522155\"><\/a><a name=\"_Toc43522806\"><\/a><span style=\"mso-bookmark: _Toc43522155;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522806\"><\/a><span style=\"mso-bookmark: _Toc43522155;\">Life Time Control of a Coclass and Class Factory<\/span><\/h2>\n<p>in an EXE Server<\/p>\n<h2><a name=\"_Toc43522806\"><\/a><\/h2>\n<p class=\"MsoNormal\">Coclasses in an EXE server works exactly like those in a DLL<\/p>\n<p>server.<\/p>\n<p class=\"MsoNormal\">Class objects in an EXE server has one difference from those<\/p>\n<p>in a DLL server: they don&#8217;t affect any reference count \u2013 neither their own nor<\/p>\n<p>the server\u2019s. This is because they are created in <strong>WinMain<\/strong> as local<\/p>\n<p>objects on the stack, so they do not need to be explicitly deleted. When all<\/p>\n<p>coclass objects are done, <strong>WinMain<\/strong> will end, and when <strong>WinMain<\/strong><\/p>\n<p>ends, all class objects go out of scope.<\/p>\n<p class=\"MsoNormal\">So EXE class factories use dummy implementation for <strong>AddRef<\/strong><\/p>\n<p>and <strong>Release<\/strong>: they simply returns constants like 10 or 20. The rest of the<\/p>\n<p>class factory are the same like those in a DLL server.<\/p>\n<h2><a name=\"_Toc43522156\"><\/a><a name=\"_Toc43522807\"><\/a><span style=\"mso-bookmark: _Toc43522156;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522807\"><\/a><span style=\"mso-bookmark: _Toc43522156;\">Life Tme Control of an EXE Server<\/span><\/h2>\n<p class=\"MsoNormal\">A DLL server can not be run independently. It is started by<\/p>\n<p>the client\u2019s thread. It only has some exported functions such as <strong>DllGetClassObject<\/strong><\/p>\n<p>for clients to call. It can not unload itself. In comparison, an EXE server has<\/p>\n<p>its main thread. When an EXE is started, the main thread runs global function <strong>WinMain<\/strong>.<\/p>\n<p>When it reaches its end bracket, the whole server process ends just like normal<\/p>\n<p>applications.<\/p>\n<p class=\"MsoNormal\">Unlike a DLL server which uses two global counts, an EXE<\/p>\n<p>server has only one global count <strong>g_allLocks<\/strong> for life time control.<\/p>\n<p class=\"MsoNormal\">Whenever a coclass is instantiated, its constructor will<\/p>\n<p>call global function <strong>Lock,<\/strong> which will increase the lock count. Whenever<\/p>\n<p>it is destroyed, its destructor will call a global <strong>UnLock<\/strong>, which will<\/p>\n<p>decrease the lock, then check whether it is zero. If yes, post an \u201cexit\u201d<\/p>\n<p>message to end the dummy message look. Class factory&#8217;s <strong>LockServer<\/strong> method<\/p>\n<p>also calls <strong>Lock<\/strong> and <strong>UnLock<\/strong>. So the global variable <strong>UnLock<\/strong><\/p>\n<p>controls the EXE server life time.<\/p>\n<p class=\"MsoNormal\">Class factory&#8217;s constructor and destructor doesn&#8217;t call <strong>Lock<\/strong><\/p>\n<p>and <strong>Unlock<\/strong>.<\/p>\n<h2><a name=\"_Toc43522157\"><\/a><a name=\"_Toc43522808\"><\/a><span style=\"mso-bookmark: _Toc43522157;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522808\"><\/a><span style=\"mso-bookmark: _Toc43522157;\">Nomal EXE Application vs. EXE Server<\/span><\/h2>\n<p class=\"MsoNormal\">An EXE server can be designed as purely a server, or it can<\/p>\n<p>be designed to be able to server both as a server which is loaded as terminated<\/p>\n<p>by the COM run time, and an application with user interface which is started<\/p>\n<p>and ended by the user. How the program is run is decided by the command-line<\/p>\n<p>argument \u201c<strong>Embedding<\/strong>\u201d.<\/p>\n<p class=\"MsoNormal\">When COM run time starts the EXE as a server, it will invoke<\/p>\n<p>it with argument \u201c<strong>Embedding<\/strong>\u201d. So <strong>WinMain<\/strong> knows that it is<\/p>\n<p>launched as a server. It will create the class factory objects for all the<\/p>\n<p>coclasses the server contains, register each of them in the Running Object<\/p>\n<p>Table by calling <strong>CoRegisterClassObject<\/strong>, then enter a dummy message loop<\/p>\n<p>and wait infinitely for an \u201cExit\u201d message. When the server&#8217;s global <strong>Unlock<\/strong><\/p>\n<p>function discovers that the server lock reaches zero, it will post an \u201cExit\u201d<\/p>\n<p>message to end the message loop. Then function <strong>CoRevokeClassObject<\/strong> will<\/p>\n<p>be called for each class object. Then <strong>WinMain<\/strong> ends.<\/p>\n<p class=\"MsoNormal\">When user starts the EXE as an application, he will not put<\/p>\n<p>argument \u201c<strong>Embedding<\/strong>\u201d. So <strong>WinMain<\/strong> knows that it is launched as an<\/p>\n<p>application. Instead of doing the above things, it will create and show its<\/p>\n<p>user interfaces.<\/p>\n<h2><a name=\"_Toc43522158\"><\/a><a name=\"_Toc43522809\"><\/a><span style=\"mso-bookmark: _Toc43522158;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522809\"><\/a><span style=\"mso-bookmark: _Toc43522158;\">Example of EXE Server&#8217;s WinMain<\/span><\/h2>\n<p class=\"MsoNormal\">To register and unregister a class object CoCarClassFactory<\/p>\n<p>to the running object table:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><a name=\"_Toc43522810\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">DWORD g_allLocks = 0<\/span><\/strong><span lang=\"EN-AU\">;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">int APIENTRY <strong><span style=\"color: red;\">WinMain<\/span><\/strong>(HINSTANCE hInstance,<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">HINSTANCE hPrevInstance,<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">LPSTRlpCmdLine,<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">intnCmdShow)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522811\"><\/a>CoInitialize(NULL);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">if(strstr(lpCmdLine,<\/span><\/p>\n<p>&#8220;\/Embedding&#8221;) || strstr(lpCmdLine, &#8220;-Embedding&#8221;))<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522812\"><\/a><strong><span style=\"color: red;\">CoCarClassFactory<\/span><\/strong> <strong><span style=\"color: red;\">carClassFactory<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">DWORD regID = 0;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoRegisterClassObject<\/span><\/strong>(CLSID_CoCar,<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>(IClassFactory*)&amp;<strong><span style=\"color: red;\">carClassFactory<\/span><\/strong>,<\/p>\n<p>&nbsp;<\/p>\n<p>CLSCTX_LOCAL_SERVER,<\/p>\n<p>REGCLS_MULTIPLEUSE, &amp;regID);<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">MSG ms;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">while(GetMessage(&amp;ms, 0, 0, 0))<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">TranslateMessage(&amp;ms);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">DispatchMessage(&amp;ms);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoRevokeClassObject<\/span><\/strong>(regID);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">else<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\/\/ Work as a normal application<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 0cm; page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">CoUninitialize();<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">return 0;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522159\"><\/a><a name=\"_Toc43522813\"><\/a><span style=\"mso-bookmark: _Toc43522159;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522813\"><\/a><span style=\"mso-bookmark: _Toc43522159;\">Client Invoking Server<\/span><\/h1>\n<h2><a name=\"_Toc43522160\"><\/a><a name=\"_Toc43522814\"><\/a><span style=\"mso-bookmark: _Toc43522160;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522814\"><\/a><span style=\"mso-bookmark: _Toc43522160;\">Accessing DLL and EXE Servers using Class<\/span><\/h2>\n<p>Factories<\/p>\n<h2><a name=\"_Toc43522814\"><\/a><\/h2>\n<p class=\"MsoNormal\">There are two steps to access a server (DLL server or EXE<\/p>\n<p>server alike) through class factories:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 57.3pt; text-indent: -18.0pt; mso-list: l2 level1 lfo8; tab-stops: list 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Client<\/p>\n<p>calls <strong>CoGetClassObject<\/strong> providing the <strong>REFCLSID<\/strong> of the coclass,<\/p>\n<p>which searches the System Registry, loads up the server if it is not yet<\/p>\n<p>loaded, calls the server&#8217;s exported function <strong>DllGetClassObject<\/strong>, which<\/p>\n<p>returns its <strong>IClassFactory<\/strong> pointer;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 57.3pt; text-indent: -18.0pt; mso-list: l2 level1 lfo8; tab-stops: list 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Client<\/p>\n<p>calls <strong>IClassFactory::CreateInstance<\/strong> with the <strong>REFIID<\/strong> of an<\/p>\n<p>interface of the coclass, which returns the interface pointer;<\/p>\n<p class=\"MsoNormal\">COM library API function <strong>CoGetClassObject<\/strong> calls the<\/p>\n<p>COM server\u2019s <strong>DllGetClassObject<\/strong> to acquire a class factory reference:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522815\"><\/a><span lang=\"EN-AU\">HRESULT <strong><span style=\"color: red;\">CoGetClassObject<\/span><\/strong>(<\/span><\/p>\n<p>REFCLSID rclsid,<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DWORD<\/span><\/p>\n<p>dwClsContext,<\/p>\n<p>COSERVERINFO * pServerInfo,<\/p>\n<p>REFIID riid,<\/p>\n<p>LPVOID * ppv);<\/p>\n<p class=\"MsoNormal\"><strong>COSERVERINFO<\/strong> is a structure to carry information for<\/p>\n<p>remote servers, which should be NULL if you are invoking in-proc or local<\/p>\n<p>servers.<\/p>\n<p class=\"MsoNormal\">Then you can acquire from the <strong>IClassFactory<\/strong> interface<\/p>\n<p>the interface you want.<\/p>\n<p class=\"MsoNormal\">Example:<\/p>\n<p class=\"MsoNormal\">Use AppWizard&#8217;s option &#8220;Win32 Console Application&#8221;<\/p>\n<p>and &#8220;Empty Project&#8221; to create a totally empty project. Insert the<\/p>\n<p>iid.cpp file into the project, and put the following lines into the global file<\/p>\n<p>&#8220;ProjectName.cpp&#8221;:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;..\\cardll\\<strong><span style=\"color: red;\">interfaces.h<\/span><\/strong>&#8220;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;..\\cardll\\<strong><span style=\"color: red;\">iid.h<\/span><\/strong>&#8220;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;iostream.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Note: interface definition<\/span><\/p>\n<p>&#8220;interface.h&#8221; should be included prior to<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ GUID definition &#8220;iid.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void main(int argc, char* argv[])<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoInitialize<\/span><\/strong>(NULL);<\/span><\/p>\n<p>IClassFactory * pClassFactory = NULL;<\/p>\n<p>HRESULT hr = <strong><span style=\"color: red;\">CoGetClassObject<\/span><\/strong>(<\/p>\n<p>CLSID_Car,<\/p>\n<p>CLSCTX_SERVER,<\/p>\n<p>NULL,<\/p>\n<p>IID_IClassFactory,<\/p>\n<p>(void **) &amp;pClassFactory);<\/p>\n<p>if(FAILED(hr)) \/\/ in the following code this error checking is omitted<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>cout &lt;&lt; &#8220;CoGetClassObject failed!\\n&#8221;;<\/p>\n<p>return;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>IRegistration * pRegist = NULL;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pClassFactory-&gt;<strong><span style=\"color: red;\">CreateInstance<\/span><\/strong>(<\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522816\"><\/a>NULL, <\/span><\/p>\n<p>IID_IRegistration,<\/p>\n<p>(void **) &amp;pRegist);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BSTR<\/span><\/p>\n<p>bstr = SysAllocString(L&#8221;Frank Liu&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pRegist-&gt;<strong><span style=\"color: red;\">SetOwner<\/span><\/strong>(bstr);<\/p>\n<p>SysFreeString(bstr);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pRegist-&gt;<strong><span style=\"color: red;\">GetOwner<\/span><\/strong>(&amp;bstr);<\/p>\n<p>char buf[80];<\/p>\n<p>wcstombs(buf, bstr, 80);<\/p>\n<p>cout &lt;&lt; &#8220;Owner of the car is: &#8221; &lt;&lt; buf &lt;&lt;<\/p>\n<p>endl;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>IStatus * pStatus = NULL;<\/p>\n<p>pRegist-&gt;QueryInterface(IID_IStatus, (void **)&amp;pStatus);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pStatus-&gt;<strong><span style=\"color: red;\">SetSpeed<\/span><\/strong>(120);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int<\/span><\/p>\n<p>nSpeed;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pStatus-&gt;<strong><span style=\"color: red;\">GetSpeed<\/span><\/strong>(&amp;nSpeed);<\/p>\n<p>cout &lt;&lt; &#8220;Speed of the car is now &#8221; &lt;&lt; nSpeed<\/p>\n<p>&lt;&lt; endl;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522161\"><\/a><a name=\"_Toc43522817\"><\/a><span style=\"mso-bookmark: _Toc43522161;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522817\"><\/a><span style=\"mso-bookmark: _Toc43522161;\">Accessing Server with CoCreateInstance<\/span><\/h2>\n<p class=\"MsoNormal\">COM library API function <strong>CoCreateInstance<\/strong> wraps the<\/p>\n<p>two function calls \u2013 <strong>CoGetClassObject<\/strong> and <strong>IClassFactory::CreateInterface<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;stdafx.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ The following two header files are<\/span><\/p>\n<p>generated by MIDL compiler.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Alternatively, you can import the type<\/span><\/p>\n<p>library as instructed in<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Chapter IDL.<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;..\\test\\test.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;..\\test\\test_i.c&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int main(int argc, char* argv[])<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CoInitialize(NULL);<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522818\"><\/a><strong><span style=\"color: red;\">IAny<\/span><\/strong> <strong><span style=\"color: red;\">*<\/span><\/strong> <strong><span style=\"color: red;\">pAny<\/span><\/strong> = NULL;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522819\"><\/a>HRESULT hr = <strong><span style=\"color: red;\">CoCreateInstance<\/span><\/strong>(<\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt;\"><span lang=\"EN-AU\">CLSID_Any, <\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt;\"><span lang=\"EN-AU\">NULL, <\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt;\"><span lang=\"EN-AU\">CLSCTX_INPROC_SERVER, <\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt;\"><span lang=\"EN-AU\">IID_IAny, <\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt; mso-outline-level: 1;\"><a name=\"_Toc43522820\"><\/a><span lang=\"EN-AU\">(void **)&amp;<strong><span style=\"color: red;\">pAny<\/span><\/strong>);<\/span><\/p>\n<p class=\"Program\" style=\"margin-left: 49.6pt; text-indent: 14.15pt;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">if(FAILED(hr))<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">printf(&#8220;CoCreateInstance<\/span><\/p>\n<p>failed!&#8221;);<\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522821\"><\/a>hr = <strong><span style=\"color: red;\">pAny<\/span><\/strong>-&gt;Hi();<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522822\"><\/a><strong><span style=\"color: red;\">pAny<\/span><\/strong>-&gt;Release();<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">return<\/span><\/p>\n<p>0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522162\"><\/a><a name=\"_Toc43522823\"><\/a><span style=\"mso-bookmark: _Toc43522162;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522823\"><\/a><span style=\"mso-bookmark: _Toc43522162;\">Execution Context<\/span><\/h2>\n<p class=\"MsoNormal\">There are four execution contexts you can use when calling CoCreateInstance<\/p>\n<p>or CoCreateInstanceEx:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522824\"><\/a><span lang=\"EN-AU\">CLSCTX_INPROC_SERVER<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522825\"><\/a><span lang=\"EN-AU\">CLSCTX_INPROC_HANDLER<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CLSCTX_LOCAL_SERVER<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CLSCTX_REMOTE_SERVER<\/span><\/p>\n<p class=\"MsoNormal\">CLSCTX_SERVER is an OR of the three server contexts.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522163\"><\/a><a name=\"_Toc43522826\"><\/a><span style=\"mso-bookmark: _Toc43522163;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522826\"><\/a><span style=\"mso-bookmark: _Toc43522163;\">IDL<\/span><\/h1>\n<h2><a name=\"_Toc43522164\"><\/a><a name=\"_Toc43522827\"><\/a><span style=\"mso-bookmark: _Toc43522164;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522827\"><\/a><span style=\"mso-bookmark: _Toc43522164;\">Interface Definition Language (IDL)<\/span><\/h2>\n<p class=\"MsoNormal\">With a server created purely in C++, without using IDL<\/p>\n<p>compiler,a client have to make use of<\/p>\n<p>the two header files which defines the interfaces and the guids. Because both<\/p>\n<p>these two files are in C++ syntax, clients written in other languages such as<\/p>\n<p>VB or Java can not invoke it. So such a COM server is not language independent.<\/p>\n<p class=\"MsoNormal\">Therefore we need a language-independent way to describe the<\/p>\n<p>interfaces of a COM server. Microsoft IDL (MIDL) is used for this purpose.<\/p>\n<p class=\"MsoNormal\">An IDL file does not contain any implementation information.<\/p>\n<p>Therefore you can not define a class in IDL with implemented methods. You can<\/p>\n<p>only define interfaces in IDL and implement them in a specific language such as<\/p>\n<p>VC or VB. However, you can define data structures which doesn&#8217;t contain any<\/p>\n<p>implementation.<\/p>\n<h2><a name=\"_Toc43522165\"><\/a><a name=\"_Toc43522828\"><\/a><span style=\"mso-bookmark: _Toc43522165;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522828\"><\/a><span style=\"mso-bookmark: _Toc43522165;\">Type Library<\/span><\/h2>\n<p class=\"MsoNormal\">When you define a COM server in an IDL file say <strong>Any.idl<\/strong><\/p>\n<p>and send it to VC&#8217;s integrated MIDL compiler, it will generate a C++ header<\/p>\n<p>file <strong>Any.h<\/strong> (which serves as interface definition), and a guid definition<\/p>\n<p>file<strong> Any_i.c<\/strong> for C++ clients, and a type library file <strong>Any.tlb<\/strong> containing<\/p>\n<p>all information of a COM server, which is in a language-independent binary<\/p>\n<p>format, therefore can be understood by different languages such as VC, VB,<\/p>\n<p>BJ++, etc.<\/p>\n<p class=\"MsoNormal\">When a C++ client wants to make use of type library, he can<\/p>\n<p>use #import to import the type library. When a VB client wants to invoke a COM<\/p>\n<p>server and design time, he can select from the list of registered type<\/p>\n<p>libraries from the &#8220;Project&#8221; | &#8220;Preferences&#8221; dialog. If one<\/p>\n<p>type library is not registered, he can also browse to select one.<\/p>\n<p class=\"MsoNormal\">To register a type library, under entry <strong>HKEY_CLASSES_ROOT\\TypeLib<\/strong>,<\/p>\n<p>you should create an entry of the guid of the type library, under which you<\/p>\n<p>specify the help string and directory of this type library. This is why VB can<\/p>\n<p>show you a list of registered type libraries. You should add a <strong>TypeLib<\/strong><\/p>\n<p>entry under the <strong>HKEY_CLASSES_ROOT\\CLSID<\/strong> of each coclasses contained in<\/p>\n<p>this type library, so that SCM can find the type library guid from a coclass.<\/p>\n<p>All these things can be done by ATL.<\/p>\n<p class=\"MsoNormal\">In C++, binary information defined by IDL is stored in both<\/p>\n<p>the <strong>.dll<\/strong> file and the <strong>.tlb<\/strong> file. In Visual Basic it is only<\/p>\n<p>stored in DLL file. A EXE server will have its info in the EXE file.<\/p>\n<h2><a name=\"_Toc43522166\"><\/a><a name=\"_Toc43522829\"><\/a><span style=\"mso-bookmark: _Toc43522166;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522829\"><\/a><span style=\"mso-bookmark: _Toc43522166;\">IDL Compatible Data Types<\/span><\/h2>\n<p class=\"MsoNormal\">If you only use the following IDL data types, your<\/p>\n<p>interfaces can be used by all COM-enabled interfaces:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">VARIANT_BOOL, double, float, long, short,<\/span><\/p>\n<p>BSTR, DATE, IDispatch*, IUnknown*, VARIANT, CY\/CURRENCY, SAFEARRAY<\/p>\n<p class=\"MsoNormal\">However, when you use other types such as ULONG or HRESULT<\/p>\n<p>in your IDL, they are also OK, because they have been defined by <strong>typedef<\/strong><\/p>\n<p>in &#8220;<strong>wtypes.idl<\/strong>&#8221; as IDL data types. You do not need to import<\/p>\n<p>&#8220;<strong>wtypes.idl<\/strong>&#8220;, because it will be imported by &#8220;<strong>oaidl.idl<\/strong>&#8220;.<\/p>\n<h2><a name=\"_Toc43522167\"><\/a><a name=\"_Toc43522830\"><\/a><span style=\"mso-bookmark: _Toc43522167;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522830\"><\/a><span style=\"mso-bookmark: _Toc43522167;\">Defining Coclasses, Interfaces and Libraries in<\/span><\/h2>\n<p>IDL<\/p>\n<h2><a name=\"_Toc43522830\"><\/a><\/h2>\n<p class=\"MsoNormal\" style=\"margin-left: 21.25pt; page-break-after: avoid;\">IDL file<\/p>\n<p>of an empty COM server looks like<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">import &#8220;oaidl.idl&#8221;;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">uuid<\/span><\/strong>(7013DBBD-A9FC-11D5-9866-E39F283C9930),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">version<\/span><\/strong>(1.0),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">helpstring<\/span><\/strong>(&#8220;Test 1.0 Type Library&#8221;)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">library<\/span><\/strong><span lang=\"EN-AU\"> TESTLib<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>importlib(&#8220;stdole32.tlb&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">&#8220;<strong>oaidl.idl<\/strong>&#8221; is the only IDL file you must<\/p>\n<p>import in your IDL file. Type library &#8220;<strong>stdole32.tlb<\/strong>&#8221; is the<\/p>\n<p>standard OLE type library, which must be imported by any type library.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Adding<\/h3>\n<p>a coclass<\/p>\n<p class=\"MsoNormal\">To add a new coclass, add the following coclass declaration<\/p>\n<p>lines <strong>in<\/strong> the library block:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span style=\"mso-ansi-language: IT;\" lang=\"IT\">[<\/span><\/p>\n<p class=\"Program\"><span style=\"mso-ansi-language: IT;\" lang=\"IT\">uuid(7013DBCD-A9FC-11D5-9866-E39F283C9930),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">helpstring(&#8220;MyCom<\/span><\/p>\n<p>Class&#8221;)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">coclass<\/span><\/p>\n<p>MyCom<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Adding<\/h3>\n<p>an interface and its methods<\/p>\n<p class=\"MsoNormal\">We can use AppWizard to add coclasses and their default<\/p>\n<p>interfaces, but we have to add additional interfaces ourselves. For each<\/p>\n<p>interface, we add its declaration in front of the library block. Attribute<\/p>\n<p>&#8220;<strong>object<\/strong>&#8221; indicates that this is a COM interface not a DCE IDL<\/p>\n<p>interface.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">object<\/span><\/strong>,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">uuid<\/span><\/strong>(7013DBCB-A9FC-11D5-9866-E39F283C9930),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">helpstring<\/span><\/strong>(&#8220;ICOMClass1 Interface&#8221;)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">interface<\/span><\/strong> IMyInterf : IUnknown<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[helpstring(&#8220;method<\/span><\/p>\n<p>GetBalance&#8221;)]<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT GetBalance([in] int aa, [out] LONG *<\/span><\/p>\n<p>bb);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[helpstring(&#8220;method<\/span><\/p>\n<p>Deposit&#8221;)]<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT<\/span><\/p>\n<p>Deposit([in] int aa);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">Then we add the interface name in the coclass definition:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span style=\"mso-ansi-language: IT;\" lang=\"IT\">[<\/span><\/p>\n<p class=\"Program\"><span style=\"mso-ansi-language: IT;\" lang=\"IT\">uuid(7013DBCD-A9FC-11D5-9866-E39F283C9930),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">helpstring(&#8220;MyCom<\/span><\/p>\n<p>Class&#8221;)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">coclass<\/span><\/p>\n<p>MyCom<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<strong><span style=\"color: red;\">default<\/span><\/strong>] interface IMyInterf;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">the interface with <strong>[default]<\/strong> attribute is the default<\/p>\n<p>interface of the coclass.<\/p>\n<p class=\"MsoNormal\">An interface should belong to a coclass. A standard-alone<\/p>\n<p>interface which does not belong to any coclass is alowed by MIDL compiler and<\/p>\n<p>can be implemented manually, but it is not shown when using Implement Interface<\/p>\n<p>Wizard.<\/p>\n<p class=\"MsoNormal\">Then we should let the coclass inherit from the interface,<\/p>\n<p>and in ATL we should add a COM map entry for the interface.<\/p>\n<h2><a name=\"_Toc43522168\"><\/a><a name=\"_Toc43522831\"><\/a><span style=\"mso-bookmark: _Toc43522168;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522831\"><\/a><span style=\"mso-bookmark: _Toc43522168;\">Defining Data Structures in IDL<\/span><\/h2>\n<p class=\"MsoNormal\">If your server needs to use a custom type (a class or a<\/p>\n<p>structure) internally, you can define the new type in a normal header file<\/p>\n<p>(plus cpp file if necessary) and #include the header file wherever it is used.<\/p>\n<p class=\"MsoNormal\">However, if this custom type is used as an argument in a<\/p>\n<p>method of an interface which needs to be transfered by the marshaller, then you<\/p>\n<p>should define the custom type in your main IDL file, or in a separate IDL file<\/p>\n<p>and import it in your main IDL file.<\/p>\n<p class=\"MsoNormal\">Then, when MIDL compiler compiles the main IDL file, the<\/p>\n<p>header file it generates will contain the definition of the custom type. If the<\/p>\n<p>custom type is defined in a separate IDL file, then you have to compile the<\/p>\n<p>separate IDL file first, then the main IDL file. Then the header file generated<\/p>\n<p>from the main IDL file will automatically include the header file generated<\/p>\n<p>from the separate IDL file.<\/p>\n<p class=\"MsoNormal\">Because the main IDL file either contains the definition of<\/p>\n<p>the custom type or imports its definition, the client who invokes this server<\/p>\n<p>can directly use the custom type.<\/p>\n<p class=\"MsoNormal\">If the custom type contains any variable-length array<\/p>\n<p>member, you must put <strong>size_is<\/strong> attribute in front of the variable-length<\/p>\n<p>data member to inform the marshaller of the member&#8217;s size:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef struct {<\/span><\/p>\n<p>short sSize;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<strong><span style=\"color: red;\">size_is<\/span><\/strong>(sSize)] <strong><span style=\"color: red;\">short<\/span><\/strong><\/span><\/p>\n<p>sArray[];<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">} Group;<\/span><\/p>\n<p class=\"MsoNormal\">Also notice that the array member is represented by array<\/p>\n<p>syntax &#8220;<strong>short sArray[ ]<\/strong>&#8221; not pointer syntax &#8220;<strong>short *<\/strong><\/p>\n<p>pShort&#8221;. For some reason the latter one doesn&#8217;t work.<\/p>\n<h2><a name=\"_Toc43522169\"><\/a><a name=\"_Toc43522832\"><\/a><span style=\"mso-bookmark: _Toc43522169;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522832\"><\/a><span style=\"mso-bookmark: _Toc43522169;\">Defining Enums in IDL<\/span><\/h2>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[uuid(442F&#8230;.804), <strong><span style=\"color: red;\">v1-enum<\/span><\/strong>]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef <strong><span style=\"color: red;\">enum<\/span><\/strong><\/span><\/p>\n<p>{<\/p>\n<p>HATCH = 0,<\/p>\n<p>SOLID = 1,<\/p>\n<p>POLKADOT<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">} FILLTYPE;<\/span><\/p>\n<p class=\"MsoNormal\">Attribute <strong>v1-enum<\/strong> indicates that these enums are<\/p>\n<p>32-bit, which is more efficient in marshalling.<\/p>\n<h2><a name=\"_Toc43522170\"><\/a><a name=\"_Toc43522833\"><\/a><span style=\"mso-bookmark: _Toc43522170;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522833\"><\/a><span style=\"mso-bookmark: _Toc43522170;\">MkTypLib Compatible Option<\/span><\/h2>\n<p class=\"MsoNormal\">Each VC project has a &#8220;MkTypLib Compatible&#8221;<\/p>\n<p>option. This option is found under &#8220;Project | Settings | MIDL&#8221;. This<\/p>\n<p>is by default set, which means that all IDL files must conform to older ODL<\/p>\n<p>syntax. You should turn it off. In a project generated by ATL COM AppWizard, it<\/p>\n<p>is turned off.<\/p>\n<h2><a name=\"_Toc43522171\"><\/a><a name=\"_Toc43522834\"><\/a><span style=\"mso-bookmark: _Toc43522171;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522834\"><\/a><span style=\"mso-bookmark: _Toc43522171;\">MIDL Generated Files<\/span><\/h2>\n<p class=\"MsoNormal\">Suppose the IDL file name is Shapes.idl, the files generated<\/p>\n<p>by MIDL are:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l10 level1 lfo10; tab-stops: 184.3pt;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Shapes.hInterface<\/p>\n<p>definition<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l10 level1 lfo10; tab-stops: 184.3pt;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Shapes.tlbbinary<\/p>\n<p>type library<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l10 level1 lfo10; tab-stops: 184.3pt;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Shapes_i.cdefinition<\/p>\n<p>of all guids<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l10 level1 lfo10; tab-stops: 184.3pt;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Shapes_p.c and dlldate.cused to build proxy and stub DLLs for remote accessing<\/p>\n<h2><a name=\"_Toc43522172\"><\/a><a name=\"_Toc43522835\"><\/a><span style=\"mso-bookmark: _Toc43522172;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.9.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522835\"><\/a><span style=\"mso-bookmark: _Toc43522172;\">Importing Type Library<\/span><\/h2>\n<p class=\"MsoNormal\">In C++, to invoke a server or implement an interface defined<\/p>\n<p>in it through its type library is to #import the type library wherever you need<\/p>\n<p>it \u2013 in the *.h or *.cpp file. When you #import a type library say <strong>Shapes.tlb<\/strong>,<\/p>\n<p>the compiler will generate two C++ files: <strong>Shapes.tlh<\/strong> and<strong> Shapes.tli<\/strong>,<\/p>\n<p>which contains definitions for the interfaces, guids and and smart pointers.<\/p>\n<p>Both files are placed in the output directory e.g. &#8220;debug&#8221;, and then<\/p>\n<p>read and compiled by the compiler as if they are included. So after you compile<\/p>\n<p>the project, you can actually comment out the #import line and #include the <strong>tlh<\/strong><\/p>\n<p>file.<\/p>\n<p class=\"MsoBodyTextIndent\">A typical #import line looks like:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">#import<\/span><\/strong><span lang=\"EN-AU\"> &#8220;D:\\icp97\\pc\\core\\code\\ICPCore.tlb&#8221; \\<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">no_namespace, named_guids,<\/span><\/strong><\/p>\n<p>raw_native_types, raw_interfaces_only<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>no_namespace<\/h3>\n<p class=\"MsoNormal\">If you do not put the &#8220;<strong>no_namespace<\/strong>&#8220;<\/p>\n<p>attribute after the #import, most sections in the generated <strong>tlh<\/strong> file<\/p>\n<p>will be enclosed in a namespace block, which is named after the type library<\/p>\n<p>name. This is useful to prevent name conflicts between names used in your<\/p>\n<p>client program and names imported from the COM server. To use the names in the<\/p>\n<p>COM server, you should put the following declaration immediately after the<\/p>\n<p>#import line (the name of the type library is ICPCore.tlb):<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">using namespace ICPCore;<\/span><\/p>\n<p class=\"MsoNormal\">By putting the &#8220;<strong>no_namespace<\/strong>&#8221; attribute,<\/p>\n<p>the namespace declaration in the generated <strong>tlh<\/strong> file will be supressed.<\/p>\n<p>Therefore all names in the <strong>tlh<\/strong> file are in the same namespace as your<\/p>\n<p>client program. You can directly quote them.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>named_guids<\/h3>\n<p class=\"MsoNormal\">Attribute &#8220;<strong>named_guids<\/strong>&#8221; instructs the<\/p>\n<p>compiler to define the guids contained in the <strong>tlh<\/strong> file with CLSID_, IID_<\/p>\n<p>and LIB_ prefix.<\/p>\n<p class=\"MsoNormal\">If a type library includes references to types defined in<\/p>\n<p>other type libraries, then the .TLH file will include comments of the following<\/p>\n<p>sort:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Cross-referenced type libraries:<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/<\/span><\/p>\n<p>#import &#8220;c:\\path\\typelib0.tlb&#8221;<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>raw_native_types<\/h3>\n<p class=\"MsoNormal\">By default, the high-level error-handling methods use the<\/p>\n<p>COM support classes<strong> _bstr_t<\/strong> and<strong> _variant_t<\/strong> in place of the <strong>BSTR<\/strong><\/p>\n<p>and <strong>VARIANT<\/strong> data types and raw COM interface pointers. These classes<\/p>\n<p>encapsulate the details of allocating and deallocating memory storage for these<\/p>\n<p>data types, and greatly simplify type casting and conversion operations.<\/p>\n<p class=\"MsoNormal\">This attribute is used to disable the use of these COM<\/p>\n<p>support classes in the high-level wrapper functions, and force the use of<\/p>\n<p>low-level data types instead.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>raw_interfaces_only<\/h3>\n<p class=\"MsoBodyTextIndent\">This attribute suppresses the generation of<\/p>\n<p>error-handling wrapper functions and __declspec(property) declarations that use<\/p>\n<p>those wrapper functions.<\/p>\n<p class=\"MsoNormal\">It also causes the default prefix used in naming the<\/p>\n<p>non-property functions to be removed. Normally, the prefix is <strong>raw_<\/strong>.E.g., if a method of the original interface<\/p>\n<p>is called <strong>MyMethod<\/strong> in the IDL and type library, then in the *.tlh file<\/p>\n<p>generated by the #import from the type library, it will become <strong>raw_MyMethod<\/strong>.<\/p>\n<p>If this attribute is specified, the function names are directly from the type<\/p>\n<p>library.<\/p>\n<p class=\"MsoNormal\">This attribute allows you to expose only the low-level<\/p>\n<p>contents of the type library.<\/p>\n<h2><a name=\"_Toc43522173\"><\/a><a name=\"_Toc43522836\"><\/a><span style=\"mso-bookmark: _Toc43522173;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.10.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522836\"><\/a><span style=\"mso-bookmark: _Toc43522173;\">Smart Pointers<\/span><\/h2>\n<p class=\"MsoNormal\">When VC compiler sees preprocessor directive #import *.tlb,<\/p>\n<p>it reads the type definition in the type library and generates smart pointer<\/p>\n<p>classes from IDL files, to wrap low-level functions calls such as <strong>CoCreateInstance<\/strong>,<\/p>\n<p><strong>Release<\/strong>, <strong>InterfaceSupportsErrorInfo<\/strong>, <strong>GetErrorInfo<\/strong>, <strong>GetDescription<\/strong>,<\/p>\n<p>etc.. For interface <strong>IAccount<\/strong> and <strong>IDisplay<\/strong>, there will be smart<\/p>\n<p>pointer class <strong>IAccountPtr<\/strong> and <strong>IDisplayPtr<\/strong>.<\/p>\n<p class=\"MsoNormal\">These smart pointers can automatically acquire interface<\/p>\n<p>reference with <strong>CoCreateInstance<\/strong>. You do not need to call <strong>QueryInterface<\/strong><\/p>\n<p>to acquire a new interface from the original one. You can just assign the<\/p>\n<p>original interface smart pointer to the new one. <strong>AddRef<\/strong> and <strong>Release<\/strong><\/p>\n<p>are also called automatically.<\/p>\n<p class=\"MsoNormal\">When a when a smart pointer detects an error from the<\/p>\n<p>returned HRESULT, it will throw a <strong>_com_error<\/strong> exception. You can call its<\/p>\n<p><strong>ErrorMessage<\/strong> method, which calls API function <strong>FormatMessage<\/strong> to<\/p>\n<p>return an explanation of the HRESULT, such as &#8220;Invalid pointer&#8221;. To<\/p>\n<p>retrieve the extra error information set with <strong>IErrorInfo<\/strong> objects, call <strong>_com_error<\/strong>&#8216;s<\/p>\n<p><strong>Description<\/strong> method.<\/p>\n<p class=\"MsoNormal\">A smart pointer also supports IDL attribute <strong>[out, retval]<\/strong>.<\/p>\n<p class=\"MsoBodyTextIndent\">Because smart pointer classes are higher level than<\/p>\n<p>raw interface pointers, it is more error prone. I have once run into a job<\/p>\n<p>which can be done by using raw interface pointers but not smart pointer<\/p>\n<p>classes.<\/p>\n<p class=\"MsoNormal\">To use smart pointer for interface <strong>IAccount<\/strong> and <strong>IDisplay<\/strong><\/p>\n<p>of coclass <strong>Account<\/strong> in server <strong>BankATL<\/strong>:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">try{<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522837\"><\/a><strong><span style=\"color: red;\">IAccountPtr<\/span><\/strong> <strong><span style=\"color: red;\">pAccount(&#8220;BankATL.Account.1&#8221;);<\/span><\/strong><strong><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/*<\/span><\/p>\n<p>or you can say<\/p>\n<p>IAccountPtr pAccount;<\/p>\n<p>pAccount.<strong><span style=\"color: red;\">CreateInstance<\/span><\/strong>(CLSID_Account);<\/p>\n<p>or<\/p>\n<p>IAccount pAccount(<strong><span style=\"color: red;\">__uuidof<\/span><\/strong>(CAccount));<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">*\/<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int<\/span><\/p>\n<p>balance;<\/p>\n<p>pAccount-&gt;GetBalance(&amp;balance);<\/p>\n<p>pAccount-&gt;Deposit(23);<\/p>\n<p>pAccount-&gt;GetBalance(&amp;balance);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522838\"><\/a><strong><span style=\"color: red;\">IDisplayPtr pDisplay = pAccount;<\/span><\/strong><\/span><\/p>\n<p>pDisplay-&gt;Show();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">catch(<strong><span style=\"color: red;\">_com_error<\/span><\/strong><\/span><\/p>\n<p>&amp;ex)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>MessageBox(ex.<strong><span style=\"color: red;\">ErrorMessage<\/span><\/strong>());<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\">When you pass the ProgID to a smart pointer&#8217;s constructor, a<\/p>\n<p><strong>CoCreateInstance<\/strong> call has already been done. Therefore, you should be<\/p>\n<p>cautious when you make a smart pointer a data member or especially a global<\/p>\n<p>variable \u2013 <strong>AfxOleInit<\/strong> must be called before the smart pointer is<\/p>\n<p>created.<\/p>\n<h2><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.11.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522174\"><\/a><a name=\"_Toc43522839\"><\/a><span style=\"mso-bookmark: _Toc43522174;\">[retval]<\/span><\/h2>\n<p>Attribute<\/p>\n<h2><a name=\"_Toc43522839\"><\/a><\/h2>\n<p class=\"MsoNormal\">Parameter marked with &#8220;<strong>[ out, retval ]<\/strong>&#8221; can<\/p>\n<p>be used by smart pointers or other languages such as VB as logical return type.<\/p>\n<p>Suppose method <strong>Add<\/strong> of interface <strong>IMath<\/strong> implemented by coclass <strong>CMath<\/strong><\/p>\n<p>is defined as<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT Add([in] long x, [in] long y, <strong><span style=\"color: red;\">[out, retval]<\/span><\/strong> long * z);<\/span><\/p>\n<p class=\"MsoNormal\">You can say<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">IMathPtr sp (__uuidof(CMath));<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">long <strong><span style=\"color: red;\">result<\/span><\/strong><\/span><\/p>\n<p>= sp-&gt;Add(111, 222);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/* which is equal to<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">long result;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">sp-&gt;Add(111, 222, <strong><span style=\"color: red;\">&amp;result<\/span><\/strong>);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">*\/<\/span><\/p>\n<p class=\"MsoNormal\">In VB:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522840\"><\/a><span lang=\"EN-AU\">Dim c as New CMath<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Dim ans as Integer<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ans = c.Add(111, 222)<\/span><\/p>\n<h2><a name=\"_Toc43522175\"><\/a><a name=\"_Toc43522841\"><\/a><span style=\"mso-bookmark: _Toc43522175;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.12.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522841\"><\/a><span style=\"mso-bookmark: _Toc43522175;\">[oleautomation] Compatible Data Types<\/span><\/h2>\n<p class=\"MsoNormal\">Originally COM specifications was generated to be used only<\/p>\n<p>for C\/C++. Some of C\/C++\u2019s types doesn\u2019t map to other languages such as VB. If<\/p>\n<p>your COM component has an interface method with such a data type as parameter,<\/p>\n<p>other languages may not be able to call this method.<\/p>\n<p class=\"MsoNormal\">To solve this problem, Microsoft developed a set of<\/p>\n<p>universal IDL data types that can map to all languages. It is based on VB\u2019s data<\/p>\n<p>type \u201cVariant\u201d. They are:<\/p>\n<table class=\"MsoNormalTable\" style=\"margin-left: 26.7pt; border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext;\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr style=\"mso-yfti-irow: 0;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>Universal IDL Type<\/strong><\/p>\n<\/td>\n<td style=\"width: 110.8pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>VB Mapping<\/strong><\/p>\n<\/td>\n<td style=\"width: 4.0cm; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>J++ Mapping<\/strong><\/p>\n<\/td>\n<td style=\"width: 106.3pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\"><strong>C\/C++ Mapping<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 1;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">VARIANT_BOOL<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Boolean<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">boolean<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">VARIANT_BOOL<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 2;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">double<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Double<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">double<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">double<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 3;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">float<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Single<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">float<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">float<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 4;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">long<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Long<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">long<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">long<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 5;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">short<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Integer<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">short<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">short<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 6;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">BSTR<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">String<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">java.lang.String<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">BSTR<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 7;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">DATE<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Date<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">double<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">DATE<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 8;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">IDispatch *<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Object<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">java.lang.Object<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">IDispatch *<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 9;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">IUnknown *<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Interface reference<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">com.ms.com.IUnknown<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">IUnknown *<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 10;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">VARIANT<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Variant<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">com.ms.com.Variant<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">VARIANT<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 11;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">CY\/CURRENCY<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Currency<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">long<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">CY\/CURRENCY<\/p>\n<\/td>\n<\/tr>\n<tr style=\"mso-yfti-irow: 12; mso-yfti-lastrow: yes;\">\n<td style=\"width: 101.8pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"136\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">SAFEARRAY<\/p>\n<\/td>\n<td style=\"width: 110.8pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"148\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">Variant<\/p>\n<\/td>\n<td style=\"width: 4.0cm; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"151\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">com.ms.com.SafeArray<\/p>\n<\/td>\n<td style=\"width: 106.3pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;\" valign=\"top\" width=\"142\">\n<p class=\"MsoNormal\" style=\"margin-left: 0cm;\">SAFEARRAY<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNormal\">If your COM component\u2019s interface methods all use the above universal<\/p>\n<p>data types, then the component can be invoked by client programs written in all<\/p>\n<p>languages.<\/p>\n<p class=\"MsoNormal\">In such a case, you\u2019d better put attribute <strong>[oleautomation]<\/strong><\/p>\n<p>in the interface declaration:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">object,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">uuid(C39A9A9A-1E04-11D6-9867-F05CFEE1FC30),<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">oleautomation<\/span><\/strong>,<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">helpstring(&#8220;IAny<\/span><\/p>\n<p>Interface&#8221;),<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">pointer_default(unique)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interface<\/span><\/p>\n<p>IAny : IUnknown<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[helpstring(&#8220;method<\/span><\/p>\n<p>Hi&#8221;)] HRESULT Hi([in] A a);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">With this attribute, MIDL compiler will check that all interface<\/p>\n<p>methods use only universal data types. If not, e.g. a method has a parameter of<\/p>\n<p>a custom type say CEmployee * pEmployee, it will generate a warning message<\/p>\n<p>like \u201cinterface does not conform to [oleautomation] attribute\u201d.<\/p>\n<p class=\"MsoNormal\">If you use <strong>dispinterface<\/strong> or dual interface than you<\/p>\n<p>have to stick to this standard.<\/p>\n<p class=\"MsoNormal\">If your COM component comply to the <strong>[oleautomation]<\/strong><\/p>\n<p>standard, it can make use of COM\u2019s automatic data marshalling DLL <strong>oleaut32.dll<\/strong>.<\/p>\n<p>Otherwise you have to build and register your own stub\/proxy DLL server (MIDL<\/p>\n<p>will generate the make file for you so it is not difficult either).<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522176\"><\/a><a name=\"_Toc530050361\"><\/a><a name=\"_Toc43522842\"><\/a><span style=\"mso-bookmark: _Toc530050361;\"><span style=\"mso-bookmark: _Toc43522176;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Da<\/span><\/span><a name=\"Data_marshalling\"><\/a><span style=\"mso-bookmark: _Toc43522842;\"><span style=\"mso-bookmark: _Toc530050361;\"><span style=\"mso-bookmark: _Toc43522176;\">ta<\/span><\/span><\/span><\/h1>\n<p>Marshalling<\/p>\n<h2><a name=\"_Toc43522177\"><\/a><a name=\"_Toc530050362\"><\/a><a name=\"_Toc43522843\"><\/a><span style=\"mso-bookmark: _Toc530050362;\"><span style=\"mso-bookmark: _Toc43522177;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522843\"><\/a><span style=\"mso-bookmark: _Toc530050362;\"><span style=\"mso-bookmark: _Toc43522177;\">When is Data Marshaller Needed<\/span><\/span><\/h2>\n<p class=\"MsoNormal\" style=\"page-break-after: avoid;\">When designing a DLL server,<\/p>\n<p>you can simply use a pointer to pass into the server an array, just like a<\/p>\n<p>normal method call, because the DLL server is in-process and shares the same<\/p>\n<p>address space:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[id(1), helpstring(&#8220;method<\/span><\/p>\n<p>PassShorts&#8221;)]<\/p>\n<p>HRESULT PassShorts([in] short count, [in] short * pShort);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CAny::PassShorts(<strong><span style=\"color: red;\">short *<\/span><\/strong> <strong><span style=\"color: red;\">pShort<\/span><\/strong>,<\/span><\/p>\n<p>int count)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>char temp[80];<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">for(int i = 0; i &lt; count; i++)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sprintf(temp, &#8220;%d \\n&#8221;, <strong><span style=\"color: red;\">pShort[i]<\/span><\/strong>);<\/p>\n<p>MessageBox(NULL, temp, &#8220;Server&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\">When it comes to EXE server, if you use the same code shown above,<\/p>\n<p>only pShort[0] has a legal value. If you try to access the succeeding array<\/p>\n<p>elements, the server will fail.<\/p>\n<p class=\"MsoNormal\">This is because the server and the client are not in the<\/p>\n<p>same address space, the data transfer between the client and the server is<\/p>\n<p>taken care of by the marshaller. When the client passes a pointer to the server<\/p>\n<p>or vice versa, the receiver actually does not get a pointer pointing to the<\/p>\n<p>original location in the sender&#8217;s address space. Instead it gets a pointer to a<\/p>\n<p>copy of data in his own address space allocated by the marshaller. The<\/p>\n<p>marshaller transfers the data from the sender to the receiver.<\/p>\n<p class=\"MsoNormal\">For a in-process method call, both the caller and the method<\/p>\n<p>are refering to the same piece of physical data (in case of pass-by-pointer),<\/p>\n<p>the reference itself doesn&#8217;t cause data flow. For a method call between a<\/p>\n<p>client and EXE server, however, a data reference itself will cause data flow,<\/p>\n<p>and therefore you must tell the marshaller the flow direction and the amount of<\/p>\n<p>data to be transfered.<\/p>\n<h2><a name=\"_Toc43522178\"><\/a><a name=\"_Toc530050363\"><\/a><a name=\"_Toc43522844\"><\/a><span style=\"mso-bookmark: _Toc530050363;\"><span style=\"mso-bookmark: _Toc43522178;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522844\"><\/a><span style=\"mso-bookmark: _Toc530050363;\"><span style=\"mso-bookmark: _Toc43522178;\">Data Marshalling and Parameter Direction<\/span><\/span><\/h2>\n<p>Attrubutes<\/p>\n<h2><a name=\"_Toc43522844\"><\/a><\/h2>\n<p class=\"MsoBodyTextIndent\">Data marshaller&#8217;s job is to allocate memory for the<\/p>\n<p>destination, and copy data from the corresponding source memory block to the<\/p>\n<p>allocated memory. The source and destination is decided by the parameter<\/p>\n<p>direction attributes <strong>[in]<\/strong> and <strong>[out]<\/strong>. The amount of memory to be<\/p>\n<p>allocated is decided by the type definition of the parameter and \u2013 if the<\/p>\n<p>parameter has a variable size like a variable-size array or structure \u2013 the<strong><\/strong><\/p>\n<p>[size_is]attribute.<\/p>\n<p class=\"MsoBodyTextIndent\">Notice that when the parameter is a pointer, the<\/p>\n<p>marshaller will not only allocate memory for the pointer itself, but also for<\/p>\n<p>the memory block pointed by the pointer. Otherwise the destination side can not<\/p>\n<p>make any use of the pointer.<\/p>\n<p class=\"MsoBodyTextIndent\">When the direction attribute is <strong>[in]<\/strong>, <strong>before<\/strong><\/p>\n<p>the server method is called, marshaller allocates memory for the server and<\/p>\n<p>copies data from the client to server. When the attribute is <strong>[out]<\/strong>,<\/p>\n<p>marshaller allocates memory for the client and copies data from server to it <strong>after<\/strong><\/p>\n<p>the server method returns. When the attribute is<strong> [in, out]<\/strong>, the<\/p>\n<p>marshaller does the <strong>[in]<\/strong> process before the method call, then the <strong>[out]<\/strong><\/p>\n<p>process after the method returns.<\/p>\n<p class=\"MsoBodyTextIndent\">Because the marshaller copies data from the source<\/p>\n<p>to the allocated memory of the destination, the source must have allocated the<\/p>\n<p>corresponding memory before the marshalling process starts. If not, for<\/p>\n<p>example, the source only uses a pointer to NULL to call the destination, then<\/p>\n<p>run-time error will happen when marshaller accesses the memory pointeded by the<\/p>\n<p>source pointer and tries to copy data from it.<\/p>\n<p class=\"MsoBodyTextIndent\">Becaue the marshaller usually needs to copy some<\/p>\n<p>data from server&#8217;s memory back to the client <strong>after<\/strong> the server method<\/p>\n<p>returns, the server should never delete any allocated memory \u2013 no matter it is<\/p>\n<p>allocated by the server itself or the marshaller. The marshaller will<\/p>\n<p>deallocate all server memory after it finishes the marshalling process. In<\/p>\n<p>comparison, the client should always deallocate memory \u2013 no matter it is<\/p>\n<p>allocated by the client itself or the marshaller.<\/p>\n<p class=\"MsoBodyTextIndent\">Just as in-process method calls, if you want to get<\/p>\n<p>result from the called function, you must pass the parameter by pointer. If it<\/p>\n<p>is passed by value, the server may modify his copy of the parameter but the<\/p>\n<p>client-side parameter will remain unchanged. If the object to be passed itself<\/p>\n<p>is a pointer, then it should be passed by a double pointer.<\/p>\n<h2><a name=\"_Toc530050365\"><\/a><a name=\"_Toc43522179\"><\/a><a name=\"_Toc530050364\"><\/a><a name=\"_Toc43522845\"><\/a><span style=\"mso-bookmark: _Toc530050364;\"><span style=\"mso-bookmark: _Toc43522179;\"><span style=\"mso-bookmark: _Toc530050365;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522845\"><\/a><span style=\"mso-bookmark: _Toc530050364;\"><span style=\"mso-bookmark: _Toc43522179;\"><span style=\"mso-bookmark: _Toc530050365;\">CoTaskMemAlloc &amp; CoTaskMemFree<\/span><\/span><\/span><\/h2>\n<p class=\"MsoNormal\"><span style=\"mso-bookmark: _Toc530050365;\">To safely allocate<\/span><\/p>\n<p>the memory that may be accessed by the marshaller, or deallocate memory<\/p>\n<p>allocated by the marshaller, use method <strong>CoTaskMemAlloc<\/strong> and <strong>CoTaskMemFree<\/strong>,<\/p>\n<p>which are known by the marshaller:<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">\u00a0<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">LPVOID<\/span><\/span><\/p>\n<p>CoTaskMemAlloc(ULONG ulSize);<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">void<\/span><\/span><\/p>\n<p>CoTaskMemFree(void *pv);<\/p>\n<p class=\"MsoNormal\"><span style=\"mso-bookmark: _Toc530050365;\">The initial<\/span><\/p>\n<p>contents of the memory block returned by <strong>CoTaskMemAlloc<\/strong> are undefined.<\/p>\n<p>It may be larger than required because of the space required for alignment and<\/p>\n<p>for maintenance information.<\/p>\n<p class=\"MsoNormal\"><span style=\"mso-bookmark: _Toc530050365;\">If the required<\/span><\/p>\n<p>memory size is zero, <strong>CoTaskMemAlloc<\/strong> allocates a zero-length item and<\/p>\n<p>returns a valid pointer to that item. If there is insufficient memory<\/p>\n<p>available, <strong>CoTaskMemAlloc<\/strong> returns NULL. Therefore, applications should<\/p>\n<p>always check the return value from this method, even when requesting small<\/p>\n<p>amounts of memory.<\/p>\n<p class=\"MsoNormal\"><span style=\"mso-bookmark: _Toc530050365;\">To initialize the<\/span><\/p>\n<p>allocated memory, use C run time library method <strong>memset<\/strong>. Notice that it<\/p>\n<p>is always safer to initialize the allocated memory before passing it to<\/p>\n<p>anywhere. Errors may be caused by passing uninitialized memory.<\/p>\n<p class=\"MsoNormal\"><span style=\"mso-bookmark: _Toc530050365;\">Example:<\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><strong><span style=\"color: red;\" lang=\"EN-AU\">\u00a0<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">short<\/span><\/span><\/p>\n<p>sSize = 100;<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">short<strong><span style=\"color: red;\"> * <\/span><\/strong>pShort;<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">pShort<\/span><\/span><\/p>\n<p>= reinterpret_cast&lt;short *&gt;(<strong><span style=\"color: red;\">CoTaskMemAlloc(sSize<\/span><\/strong><\/p>\n<p>* sizeof(short)));<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">if(pShort<\/span><\/span><\/p>\n<p>== NULL)<\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">{&#8230;}<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">::<strong><span style=\"color: red;\">memset<\/span><\/strong>(pShort, 0, sSize);<\/span><\/span><\/p>\n<p class=\"Program\"><span style=\"mso-bookmark: _Toc530050365;\"><span lang=\"EN-AU\">&#8230;<\/span><\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span style=\"mso-bookmark: _Toc530050365;\"><a name=\"_Toc43522846\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">CoTaskMemFree(pShort)<\/span><\/strong><span lang=\"EN-AU\">;<\/span><\/span><\/p>\n<h2><span style=\"mso-bookmark: _Toc530050365;\"><a name=\"_Toc43522180\"><\/a><a name=\"_Toc43522847\"><\/a><span style=\"mso-bookmark: _Toc43522180;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><span style=\"mso-bookmark: _Toc530050365;\"><a name=\"_Toc43522847\"><\/a><span style=\"mso-bookmark: _Toc43522180;\">Example of Passing Arrays<\/span><\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>IDL<\/h3>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">import &#8220;oaidl.idl&#8221;;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">import &#8220;ocidl.idl&#8221;;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p>object,<\/p>\n<p>uuid(5E9396EC-ECA4-45F7-BEB1-EC56C381248A),<\/p>\n<p>helpstring(&#8220;IAny Interface&#8221;),<\/p>\n<p>pointer_default(unique)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interface IAny : IUnknown<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>\/\/ Passing info from client to server<\/p>\n<p>[helpstring(&#8220;method PShortsClientAlloc&#8221;)]<\/p>\n<p>HRESULT <strong><span style=\"color: red;\">PassIn<\/span><\/strong>(<\/p>\n<p><strong><span style=\"color: red;\">[in]<\/span><\/strong> short count,<\/p>\n<p><strong><span style=\"color: red;\">[in, size_is(count)]<\/span><\/strong> short <strong><span style=\"color: red;\">*<\/span><\/strong> pShort);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>\/\/ Passing info from server to client<\/p>\n<p>[helpstring(&#8220;method GShortsServerAlloc&#8221;)]<\/p>\n<p>HRESULT <strong><span style=\"color: red;\">PassOut<\/span><\/strong>(<\/p>\n<p><strong><span style=\"color: red;\">[out]<\/span><\/strong> short <strong><span style=\"color: red;\">*<\/span><\/strong> pCount,<\/p>\n<p><strong><span style=\"color: red;\">[out, size_is(1, *pCount)]<\/span><\/strong> short <strong><span style=\"color: red;\">**<\/span><\/strong> ppShort);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>\/\/ passing info bidirectionally<\/p>\n<p>[helpstring(&#8220;method PassArray&#8221;)]<\/p>\n<p>HRESULT <strong><span style=\"color: red;\">PassBirect<\/span><\/strong>(<\/p>\n<p><strong><span style=\"color: red;\">[in, out]<\/span><\/strong> short <strong><span style=\"color: red;\">*<\/span><\/strong> psSize,<\/p>\n<p><strong><span style=\"color: red;\">[in, out, size_is(1, *psSize)]<\/span><\/strong><\/p>\n<p>short <strong><span style=\"color: red;\">**<\/span><\/strong> pps);<\/p>\n<p class=\"Program\"><strong><\/strong><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p>uuid(BA65DD03-CEBC-4E7A-A968-033C1C542FB7),<\/p>\n<p>version(1.0),<\/p>\n<p>helpstring(&#8220;Server 1.0 Type Library&#8221;)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">library SERVERLib<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>importlib(&#8220;stdole32.tlb&#8221;);<\/p>\n<p>importlib(&#8220;stdole2.tlb&#8221;);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p>uuid(963BC191-1265-4E90-A330-13787BCA9437),<\/p>\n<p>helpstring(&#8220;Any Class&#8221;)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p>coclass Any<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>[default] interface IAny;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Server<\/h3>\n<p>implementation<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CAny::<strong><span style=\"color: red;\">PassIn<\/span><\/strong>(short count, short * pShort)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>for(short i = 0; i &lt; count; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sprintf(buf, &#8220;Passed from client: %d&#8221;, pShort[i]);<\/p>\n<p>if((i % 1000) == 0)<\/p>\n<p>::MessageBox(NULL, buf, &#8220;Server&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CAny::<strong><span style=\"color: red;\">PassOut<\/span><\/strong>(short * pCount, short ** ppShort)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>short sSize = 10;<\/p>\n<p>(*pCount) = 10;<\/p>\n<p>(*ppShort) = (short *)<strong><span style=\"color: red;\">CoTaskMemAlloc<\/span><\/strong>(sSize<\/p>\n<p>* sizeof(short));<\/p>\n<p>if((*ppShort) == NULL)<\/p>\n<p>return E_OUTOFMEMORY;<\/p>\n<p>for(short i = 0; i &lt; sSize; i++)<\/p>\n<p>(*ppShort)[i] = i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CAny::<strong><span style=\"color: red;\">PassBidirect<\/span><\/strong>(short * pSize, short **pps)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>for(short i = 0; i &lt; <strong><span style=\"color: red;\">*pSize<\/span><\/strong>;<\/p>\n<p>i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">sprintf(buf, &#8220;Passed from<\/span><\/p>\n<p>client:\\n*pps[%d] = %d&#8221;, i, <strong><span style=\"color: red;\">(*pps)<\/span><\/strong>[i]);<\/p>\n<p>::MessageBox(NULL, buf, &#8220;Server&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(*pps);<\/span><\/p>\n<p>short sSize = 10;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">(*pps)<\/span><\/strong> = (short *)<strong><span style=\"color: red;\">CoTaskMemAlloc<\/span><\/strong>(sSize<\/span><\/p>\n<p>* sizeof(short));<\/p>\n<p>for(i = 0; i &lt; sSize; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p><strong><span style=\"color: red;\">(*pps)<\/span><\/strong>[i] = i * i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">(*pSize)<\/span><\/strong> = sSize;<\/span><\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Client<\/h3>\n<p>implementation<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void CClientDlg::OnPassIn() <\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>const short sSize = 7001;<\/p>\n<p>short * pShort;<\/p>\n<p>pShort = (short *)<strong><span style=\"color: red;\">CoTaskMemAlloc<\/span><\/strong>(sSize<\/p>\n<p>* sizeof(short));<\/p>\n<p>if(pShort == NULL)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>::MessageBox(NULL, &#8220;CoTaskMemAlloc failed!&#8221;,<\/p>\n<p>&#8220;Client&#8221;, MB_OK);<\/p>\n<p>return;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>for(short i = 0; i &lt; sSize; i++)<\/p>\n<p>pShort[i] = i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>HRESULT hr = m_pAny-&gt;<strong><span style=\"color: red;\">PassIn<\/span><\/strong>(sSize,<\/p>\n<p>pShort);<\/p>\n<p>if(FAILED(hr))<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">::MessageBox(NULL, &#8220;PassShorts<\/span><\/p>\n<p>failed!&#8221;, &#8220;Client&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(pShort);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void CClientDlg::OnPassOut() <\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>short sSize;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">short * pShort = NULL<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>HRESULT hr = m_pAny-&gt;<strong><span style=\"color: red;\">PassOut<\/span><\/strong>(&amp;sSize,<\/p>\n<p>&amp;pShort);<\/p>\n<p>if(FAILED(hr))<\/p>\n<p>::MessageBox(NULL, &#8220;PShortsServerAlloc failed!&#8221;,<\/p>\n<p>&#8220;Client&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>for(short i = 0; i &lt; sSize; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sprintf(buf, &#8220;Got from server: %d&#8221;, pShort[i]);<\/p>\n<p>if((i % 1000) == 0)<\/p>\n<p>::MessageBox(NULL, buf, &#8220;Client&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(pShort);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void CClientDlg::<strong><span style=\"color: red;\">OnPassBidirect<\/span><\/strong>()<\/span><\/p>\n<p>&nbsp;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sSize = 5;<\/p>\n<p>short * ps = (short *)<strong><span style=\"color: red;\">CoTaskMemAlloc<\/span><\/strong>(sSize<\/p>\n<p>* sizeof(short));<\/p>\n<p>for(i = 0; i &lt; sSize; i++)<\/p>\n<p>ps[i] = i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">hr<\/span><\/p>\n<p>= pAny-&gt;<strong><span style=\"color: red;\">PassBidirect<\/span><\/strong>(&amp;sSize,<\/p>\n<p>&amp;ps);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">if(FAILED(hr))<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>::MessageBox(NULL, &#8220;PassArray failed!&#8221;, &#8220;Client&#8221;,<\/p>\n<p>MB_OK);<\/p>\n<p>return FALSE;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>for(i = 0; i &lt; sSize; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sprintf(buf, &#8220;Passed from client:\\nps[%d] = %d&#8221;, i, ps[i]);<\/p>\n<p>::MessageBox(NULL, buf, &#8220;Server&#8221;, MB_OK);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(ps);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522181\"><\/a><a name=\"_Toc530050366\"><\/a><a name=\"_Toc43522848\"><\/a><span style=\"mso-bookmark: _Toc530050366;\"><span style=\"mso-bookmark: _Toc43522181;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522848\"><\/a><span style=\"mso-bookmark: _Toc530050366;\"><span style=\"mso-bookmark: _Toc43522181;\">Example of Passing Variable-Length Custom Types<\/span><\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>IDL<\/h3>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">import<\/span><\/p>\n<p>&#8220;oaidl.idl&#8221;;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">import<\/span><\/p>\n<p>&#8220;ocidl.idl&#8221;;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">typedef struct {<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">short sSize;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">[size_is(sSize)]<\/span><\/strong><\/span><\/p>\n<p>short sArray<strong><span style=\"color: red;\">[]<\/span><\/strong>;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">} <strong><span style=\"color: red;\">Group<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">object,<\/span><\/p>\n<p>uuid(9BF19302-65E6-4218-8C6F-55C3816123F5),<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">helpstring(&#8220;IAny Interface&#8221;),<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">pointer_default(unique)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">interface IAny : IUnknown<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>[helpstring(&#8220;method StructInOut&#8221;)]<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522849\"><\/a>HRESULT<\/span><\/p>\n<p><strong><span style=\"color: red;\">StructInOut([in, out] Group ** ppg)<\/span><\/strong>;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">uuid(185CB840-2F73-4095-A165-8FAFEDA1CBF8),<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">version(1.0),<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">helpstring(&#8220;Marshal 1.0 Type<\/span><\/p>\n<p>Library&#8221;)<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">library<\/span><\/p>\n<p>MARSHALLib<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">importlib(&#8220;stdole32.tlb&#8221;);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">importlib(&#8220;stdole2.tlb&#8221;);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">uuid(27FE57E8-26EF-4E41-AEB9-79DE4079F0E1),<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">helpstring(&#8220;Any Class&#8221;)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">coclass Any<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">[default] interface IAny;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Server<\/h3>\n<p>implementation<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">STDMETHODIMP<\/span><\/p>\n<p>CAny::<strong><span style=\"color: red;\">StructInOut<\/span><\/strong>(Group **ppg)<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">char buf[100];<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">for(short i = 0; i &lt; (*ppg)-&gt;sSize;<\/span><\/p>\n<p>i++)<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>sprintf(buf, &#8220;(*ppg)-&gt;sArray[%d] = %d&#8221;, i,<\/p>\n<p>(*ppg)-&gt;sArray[i]);<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">M(buf); \/\/ Macro to simplify function<\/span><\/p>\n<p>::MessageBox<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522850\"><\/a><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(*ppg);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">short sSize = 20;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">(*ppg) = (Group *)<strong><span style=\"color: red;\">CoTaskMemAlloc<\/span><\/strong>(sSize * sizeof(short) +<\/span><\/p>\n<p>sizeof(Group));<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">if((*ppg) == NULL) \/\/ must check the result<\/span><\/p>\n<p>of memory allocation<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">::MessageBox(NULL, &#8220;<\/span><\/p>\n<p>CoTaskMemAlloc failed!&#8221;, &#8220;Server&#8221;, MB_OK);<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">return E_OUTOFMEMORY;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">(*ppg)-&gt;sSize = sSize;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">for (i = 0; i &lt; (*ppg)-&gt;sSize; i++) <\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">(*ppg)-&gt;sArray[i] = i * i;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">return S_OK;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Client<\/h3>\n<p>implementation<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">void<\/span><\/p>\n<p>CClientDlg::OnButton3()<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">short lSize = 5;<\/span><\/p>\n<p>Group * pg;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">pg = (Group *)CoTaskMemAlloc(lSize *<\/span><\/p>\n<p>sizeof(short) + sizeof(Group));<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">if(pg == NULL)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">M(&#8220;CoTaskMemAlloc failed!&#8221;);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">return;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">pg-&gt;sSize = lSize;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">for(short i = 0; i &lt; lSize; i++)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">pg-&gt;sArray[i] = i;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">HRESULT hr = m_p-&gt;<strong><span style=\"color: red;\">StructInOut<\/span><\/strong>(&amp;pg);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">if(FAILED(hr))<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">M(&#8220;StructInOut failed&#8221;);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">char buf[100];<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">for(i = 0; i &lt; pg-&gt;sSize; i++)<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">sprintf(buf, &#8220;pg-&gt;sArray[%d] =<\/span><\/p>\n<p>%d&#8221;, i, pg-&gt;sArray[i]);<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">M(buf);<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoTaskMemFree<\/span><\/strong>(pg);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522182\"><\/a><a name=\"_Toc43522851\"><\/a><span style=\"mso-bookmark: _Toc43522182;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522851\"><\/a><span style=\"mso-bookmark: _Toc43522182;\">Proxy\/StubClasses<\/span><\/h2>\n<p class=\"MsoNormal\">A proxy resides in the client&#8217;s process and represents the<\/p>\n<p>server,and a stub resides in the<\/p>\n<p>server&#8217;s process to receive data sent from the proxy and send server&#8217;s response<\/p>\n<p>back. They are all standard COM objects residing in a DLL server. On such DLL<\/p>\n<p>server may contain many proxy\/stub classes.<\/p>\n<p class=\"MsoNormal\">Each interface in a server is represented by a separate<\/p>\n<p>proxy and stub coclass. Each proxy coclass implements two interfaces: the one<\/p>\n<p>which it represents and a standard interface <strong>IRpcProxyBuffer<\/strong>, which has<\/p>\n<p>method <strong>Connect<\/strong> and <strong>Disconnect<\/strong>.<\/p>\n<p class=\"MsoNormal\">Channel object implementing interface <strong>IRpcChannelBuffer<\/strong><\/p>\n<p>is responsible to conduct the data transfer between the proxy and the stub.<\/p>\n<p>Proxy manager is responsible to connect proxy objects to the channel object,<\/p>\n<p>and assemble the proxy objects representing different interfaces of one coclass<\/p>\n<p>together using COM aggregation, so that the cluster of proxy coclasses appears<\/p>\n<p>to the client as a cluster of interfaces of one coclass.<\/p>\n<p class=\"MsoNormal\">A stub implements <strong>IRpcStubBuffer<\/strong> and is managed by<\/p>\n<p>the stub manager. Stub manager doesn&#8217;t aggregate the stubs.<\/p>\n<p class=\"MsoNormal\">Class factories implement interface <strong>IPSFactoryBuffer<\/strong>.<\/p>\n<p>One class factory is responsible to create both the proxy and stub for a given<\/p>\n<p>server coclass with its method <strong>CreateProxy<\/strong> and <strong>CreateStub<\/strong>.<\/p>\n<h2><a name=\"_Toc43522183\"><\/a><a name=\"_Toc43522852\"><\/a><span style=\"mso-bookmark: _Toc43522183;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522852\"><\/a><span style=\"mso-bookmark: _Toc43522183;\">Marshalling Options<\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Custom<\/h3>\n<p>Marshalling<\/p>\n<p class=\"MsoNormal\">If you choose to write all marshalling code yourself, you<\/p>\n<p>should let your coclass implement interface <strong>IMarshal<\/strong>. SCM will query for<\/p>\n<p>IMarshal first. This marshalling option is called custom marshalling.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Standard<\/h3>\n<p>Marshalling<\/p>\n<p class=\"MsoNormal\">This is an easier option. When MIDL compiles the IDL file it<\/p>\n<p>will generate all files that is needed to build the proxy\/stub DLL, such as <strong>Shape_i.c<\/strong>,<\/p>\n<p><strong>Shape.h<\/strong>, <strong>Shape_p.c<\/strong> and <strong>dlldata.c<\/strong>. ATL AppWizard can<\/p>\n<p>generate a make file which can automatically build the proxy\/stub DLL from the<\/p>\n<p>above four files. To build the proxy\/stub DLL server and register it:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">nmake ProjectNameps.mk <\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">regsvr32 ProjectNameps.dll<\/span><\/p>\n<p class=\"MsoNormal\">You can put the last two commands in mene \u201cProject\u201d |<\/p>\n<p>\u201cSettings\u201d | \u201cCustom build\u201d. This way every time you build the project the rest<\/p>\n<p>is done automatically.<\/p>\n<p class=\"MsoNormal\">When client invokes an interface, SCM will find the<\/p>\n<p>interface entry under <strong>HKCR\\Interface<\/strong>, then the <strong>ProxyStubClsid32<\/strong><\/p>\n<p>entry under it, which points to the corresponding custom proxy\/stub DLL. Then<\/p>\n<p>SCM will call the class factory and instantiate a proxy\/stub object to<\/p>\n<p>prepresent the interface.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Universal<\/h3>\n<p>Marshalling<\/p>\n<p class=\"MsoNormal\">The third option is to use the universal marshaller <strong>oleaut32.dll<\/strong>.<\/p>\n<p>The <strong>ProxyStubClsid32<\/strong> entries of all interfaces should point to this<\/p>\n<p>universal marshaller, and the <strong>TypeLib<\/strong> entries point to the registered<\/p>\n<p>type library. The universal marshaller will find the registered type library of<\/p>\n<p>the invoked interface, read the type information in it, and create the<\/p>\n<p>proxy\/stub DLL on the fly.<\/p>\n<p class=\"MsoNormal\">To use universal marshaller, you have to:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 57.3pt; text-indent: -18.0pt; mso-list: l27 level1 lfo12; tab-stops: list 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Put<\/p>\n<p>attribute <strong>[oleautomation]<\/strong> in front of all interfaces and make them<\/p>\n<p>variant compatible;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 57.3pt; text-indent: -18.0pt; mso-list: l27 level1 lfo12; tab-stops: list 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Register<\/p>\n<p>the type library;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 57.3pt; text-indent: -18.0pt; mso-list: l27 level1 lfo12; tab-stops: list 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Register<\/p>\n<p>all interfaces and set the value of <strong>ProxyStubClsid32<\/strong> entry under each<\/p>\n<p>interface to the guid of <strong>oleaut32.dll<\/strong> and the value of <strong>TypeLib<\/strong><\/p>\n<p>entry to your type library guid.<\/p>\n<p class=\"MsoNormal\">You can also do all the above things through a function call<\/p>\n<p>at run time:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ITypeLib * ptlb = NULL;<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><strong><span style=\"color: red;\" lang=\"EN-AU\">LoadTypeLibEx<\/span><\/strong><span lang=\"EN-AU\">(L\u201dShapes.tlb\u201d, <strong><span style=\"color: red;\">REGKIND_REGISTER<\/span><\/strong>, &amp;ptlb);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ptlb-&gt;Release();<\/span><\/p>\n<p class=\"MsoNormal\">If there is <strong>[oleautomation]<\/strong> attribute in front of all<\/p>\n<p>interfaces in the IDL file, this function will point the <strong>ProxyStubClsid32<\/strong><\/p>\n<p>entry to the universal marshaler.<\/p>\n<h2><a name=\"_Toc43522184\"><\/a><a name=\"_Toc43522853\"><\/a><span style=\"mso-bookmark: _Toc43522184;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">6.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522853\"><\/a><span style=\"mso-bookmark: _Toc43522184;\">Hosting an DLL in a Surrogate Process<\/span><\/h2>\n<p class=\"MsoNormal\">To host a DLL in an EXE housing named dllhost.exe, you need<\/p>\n<p>to have an AppID for the DLL server and have a <strong>DllSurrogate<\/strong> entry under<\/p>\n<p>it. When its value is &#8220;&#8221;, it means that we use the default surrogate <strong>dllhost.exe<\/strong>.<\/p>\n<p class=\"MsoNormal\">To automatically assign an AppID and add a <strong>DllSurrogate<\/strong><\/p>\n<p>entry under it, open the DLL object under &#8220;All Object&#8221; entry of<\/p>\n<p>OLE\/COM Object Viewer. Tick the &#8220;Use Surrogate Process&#8221; option. The<\/p>\n<p>COM objects in the DLL server must support aggregation.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522185\"><\/a><a name=\"_Toc43522854\"><\/a><span style=\"mso-bookmark: _Toc43522185;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522854\"><\/a><span style=\"mso-bookmark: _Toc43522185;\">DCOM<\/span><\/h1>\n<h2><a name=\"_Toc43522186\"><\/a><a name=\"_Toc43522855\"><\/a><span style=\"mso-bookmark: _Toc43522186;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">7.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522855\"><\/a><span style=\"mso-bookmark: _Toc43522186;\">Configuring a Server to be Invoked Remotely<\/span><\/h2>\n<p class=\"MsoNormal\">There are three major issues to configure for a server to be<\/p>\n<p>invoked remotely. The first two can be configured machine-wide, so that you<\/p>\n<p>decide the settings for the machine, and all servers which has not been<\/p>\n<p>specifically configured take the machine-wide settings. All these things can be<\/p>\n<p>done through <strong>dcomcnfg.exe<\/strong>.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Authentication<\/h3>\n<p>Level<\/p>\n<p class=\"MsoBodyTextIndent\">Determines how often and how strict does the COM run<\/p>\n<p>time check for the server the identification of the client.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Security<\/h3>\n<p class=\"MsoNormal\">Includes Access Permission, Launch Permission and<\/p>\n<p>Configuration Permission. Each server has an AppID to store server-wide<\/p>\n<p>attributes. In System Registry, each AppID has a Access Control List (ACL),<\/p>\n<p>which lists which client has which permssion.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Server<\/h3>\n<p>Identify<\/p>\n<p class=\"MsoNormal\">A server is launched with an user account identity. It has<\/p>\n<p>three options:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 35.45pt; text-indent: -14.15pt; mso-list: l11 level1 lfo14; tab-stops: list 35.45pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>The Interactive User: all servers in a machine<\/p>\n<p>are launched with the identity of the person who is logged on to this machine.<\/p>\n<p>This is only used in debugging session when you want the server to display some<\/p>\n<p>GUI such as a message box. If you do not choose this option the server can not<\/p>\n<p>display any GUI on the machine and will appear pending.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 35.45pt; text-indent: -14.15pt; mso-list: l11 level1 lfo14; tab-stops: list 35.45pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>The Launching User: the server always has the<\/p>\n<p>identify of the person who launched it. As a side effect, the SCM will launch a<\/p>\n<p>new instance of the server for each client.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 35.45pt; text-indent: -14.15pt; mso-list: l11 level1 lfo14; tab-stops: list 35.45pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>This User: proper for production application.<\/p>\n<p>You select one or a group of users as the identity of the server.<\/p>\n<h2><a name=\"_Toc43522187\"><\/a><a name=\"_Toc43522856\"><\/a><span style=\"mso-bookmark: _Toc43522187;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">7.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522856\"><\/a><span style=\"mso-bookmark: _Toc43522187;\">Configuring a Client to Call Remote Server<\/span><\/h2>\n<p class=\"MsoNormal\">The server should be registered on the client machine. You<\/p>\n<p>can configure the client to call remote server with <strong>dcomcnfg.exe<\/strong>. Choose<\/p>\n<p>a server and double-click it to bring up the properties of the server. In the<\/p>\n<p>&#8220;Location&#8221; tab, choose correct option. You can tick either or both of<\/p>\n<p>the options: &#8220;Run application on this computer&#8221; or &#8220;Ran<\/p>\n<p>application on the following computer&#8221;, and enter the name of the remote<\/p>\n<p>computer. If you choose both, the SCM will choose the nearest one. The name of<\/p>\n<p>the computer will be assigned to a new entry <strong>RemoteServerName<\/strong> under <strong>HKCR\\AppID<\/strong>.<\/p>\n<p>When SCM sees this entry, it knows that it&#8217;s going remote.<\/p>\n<p class=\"MsoBodyTextIndent\">You can also configure a client through function <strong>CoCreateInstanceEx<\/strong>.<\/p>\n<p>It will suppress the <strong>dcomcnfg.exe<\/strong> settings:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><strong><span style=\"color: red;\" lang=\"EN-AU\">COSERVERINFO<\/span><\/strong><span lang=\"EN-AU\"> serverInfo = {0};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">serverInfo.pwszName = L&#8221;FLIU&#8221;;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">MULTI_QI<\/span><\/strong><span lang=\"EN-AU\"> interfaces[2] = {0};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interfaces[0].pIID = &amp;IID_IFirst;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interfaces[1}.pIID = &amp;IID_ISecond;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><a name=\"_Toc43522857\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">CoCreateInstanceEx<\/span><\/strong><span lang=\"EN-AU\">(<\/span><\/p>\n<p>CLSID_MyClass,<\/p>\n<p>NULL,<\/p>\n<p>CLSCTX_REMOTE_SERVER,<\/p>\n<p>&amp;serverInfo,<\/p>\n<p>2,\/\/ Size of the MULTI_QI array<\/p>\n<p>interfaces);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">if(FAILED(interfaces[0].hr))<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>::MessageBox(NULL, &#8220;Query for IID_IFirst failed!&#8221;,<\/p>\n<p>&#8220;Client&#8221;, MB_OK);<\/p>\n<p>return;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">else if(FAILED(interfaces[1].hr))<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>::MessageBox(NULL, &#8220;Query for IID_IFirst failed!&#8221;,<\/p>\n<p>&#8220;Client&#8221;, MB_OK);<\/p>\n<p>return;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">IFirst * pf = (IFirst *)interfaces[0].pItf;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ISecond * ps = (ISecond *)interfaces[1].pItf;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">&#8230;<\/span><\/p>\n<p class=\"MsoNormal\">To be able to call the DOM functions in COM library such as <strong>CoInitialize,<\/strong><\/p>\n<p><strong>CoInitializeEx<\/strong> or <strong>CoCreateInstanceEx<\/strong>, you should put the<\/p>\n<p>following line before including &lt;windows.h&gt; or in the project-wide<\/p>\n<p>#define settings:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define <strong><span style=\"color: red;\">_WIN32_DCOM<\/span><\/strong><\/span><\/p>\n<p class=\"MsoNormal\">Function <strong>CoCreateInstanceEx<\/strong> uses two structures:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><a name=\"_Toc43522858\"><\/a><span lang=\"EN-AU\">WINOLEAPI <strong><span style=\"color: red;\">CoCreateInstanceEx<\/span><\/strong>(<\/span><\/p>\n<p>REFCLSID Clsid,<\/p>\n<p>IUnknown * punkOuter,\/\/<\/p>\n<p>only relevant locally. Normally NULL<\/p>\n<p>DWORD dwClsCtx,\/\/<\/p>\n<p>CLSCTX<\/p>\n<p>COSERVERINFO * pServerInfo,\/\/<\/p>\n<p>contains server computer name<\/p>\n<p>DWORD dwCount,\/\/<\/p>\n<p>size of MULTI_QI array<\/p>\n<p>MULTI_QI * pResults );\/\/<\/p>\n<p>array of MULTI_QI<\/p>\n<p class=\"MsoNormal\">Structure <strong>COSERVERINFO<\/strong> holds the server computer<\/p>\n<p>name:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef struct_COSERVERINFO<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>DWORD dwReserved1;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid; mso-outline-level: 1;\"><strong><span style=\"color: red;\" lang=\"EN-AU\"><a name=\"_Toc43522859\"><\/a>LPWSTR pwszName;<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">COAUTHINFO __RPC_FAR *pAuthInfo;<\/span><\/p>\n<p>DWORD dwReserved2;<\/p>\n<p class=\"Program\" style=\"page-break-after: avoid;\"><span lang=\"EN-AU\">} <strong><span style=\"color: red;\">COSERVERINFO<\/span><\/strong>;<\/span><\/p>\n<p class=\"MsoNormal\">The array of structure <strong>MULTI_QI<\/strong> hold the IIDs of the<\/p>\n<p>wanted interfaces, the returned IUnknown pointers and HRESULTs:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef structtagMULTI_QI<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">const IID<\/span><\/strong> __RPC_FAR *pIID;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">IUnknown<\/span><\/strong> __RPC_FAR *pItf;<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522860\"><\/a><strong><span style=\"color: red;\">HRESULT hr<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">} <strong><span style=\"color: red;\">MULTI_QI<\/span><\/strong>;<\/span><\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522188\"><\/a><a name=\"_Toc43522861\"><\/a><span style=\"mso-bookmark: _Toc43522188;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522861\"><\/a><span style=\"mso-bookmark: _Toc43522188;\">ATL Basics<\/span><\/h1>\n<h2><a name=\"_Toc43522189\"><\/a><a name=\"_Toc43522862\"><\/a><span style=\"mso-bookmark: _Toc43522189;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522862\"><\/a><span style=\"mso-bookmark: _Toc43522189;\">ATL Macro STDMETHOD &amp; STDMETHODIMP<\/span><\/h2>\n<p class=\"MsoNormal\">ATL uses macro STDMETHOD to define a method. It is defined<\/p>\n<p>as:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define STDMETHOD(method)virtual HRESULT STDMETHODCALLTYPE method<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define STDMETHODCALLTYPE__stdcall<\/span><\/p>\n<p class=\"MsoNormal\">Therefore,<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHOD(Calculate)(int x, float y)<\/span><\/p>\n<p class=\"MsoNormal\">is in fact<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">virtual RESULT __stdcall<\/span><\/strong><span lang=\"EN-AU\"> Calculate(int x, float y)<\/span><\/p>\n<p class=\"MsoNormal\">STDMETHODIMP is used to mark the implementation of a method.<\/p>\n<p>It is defined as:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define STDMETHODIMPHRESULT STDMETHODCALLTYPE<\/span><\/p>\n<h2><a name=\"_Toc43522190\"><\/a><a name=\"_Toc43522863\"><\/a><span style=\"mso-bookmark: _Toc43522190;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522863\"><\/a><span style=\"mso-bookmark: _Toc43522190;\">Creating DLL Server with ATL<\/span><\/h2>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>1.Create a project<\/h3>\n<p class=\"MsoBodyTextIndent\">In AppWizard, choose ATL COM AppWizard and DLL<\/p>\n<p>option. It will create those entry points for the project. No coclass is<\/p>\n<p>generated yet.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>2.Add a coclass<\/h3>\n<p class=\"MsoNormal\">Choose \u201cInsert\u201d | \u201cNew ATL Object\u201d. Give the short name<\/p>\n<p>\u201cAccount\u201d. MFC will create a coclass with the initial default interface. The<\/p>\n<p>class name will be CAccount, coclass name Account, interface name IAccount.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>3.Add methods to the interface<\/h3>\n<p class=\"MsoNormal\">Right-click the interface symbol e.g. IGreet under the class<\/p>\n<p>name CAccount. The dialog prompt out will be different from normal classes.<\/p>\n<p>Return type is by default <strong>HRESULT<\/strong>, and any parameter should start with <strong>[in]<\/strong><\/p>\n<p>or <strong>[out]<\/strong> indicating whether this parameter is to pass info into or out<\/p>\n<p>of the COM, such as \u201c[in] int amount\u201d or \u201c[out] int * balance\u201d.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>4.Add data members to the coclass<\/h3>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>5.Implement the methods<\/h3>\n<p class=\"MsoNormal\">The skeletons of the methods have already been set up by the<\/p>\n<p>wizard.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>6.Add more interfaces<\/h3>\n<p class=\"MsoNormal\">Add the definition of a new interface into the <strong>ProjectName.IDL<\/strong><\/p>\n<p>file, such as<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">[<\/span><\/p>\n<p>object,<\/p>\n<p>uuid(0D6380A1-9FC8-4897-9621-47EFE50C8887),<\/p>\n<p>helpstring(&#8220;IDisplay Interface&#8221;),<\/p>\n<p class=\"Program\"><span style=\"mso-ansi-language: FR;\" lang=\"FR\">pointer_default(unique)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">]<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">interface IDisplay : IUnknown<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>[helpstring(&#8220;method Show&#8221;)] HRESULT Show();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">You need to generate the guid with \u201cMicrosoft Visual<\/p>\n<p>Studio\\Common\\Tools\\<strong>Guidgen.exe<\/strong>\u201d.<\/p>\n<p class=\"MsoNormal\">Also add the interface name to the coclass definition in<\/p>\n<p>this IDL file.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>7.Modify coclass definition for additional<\/h3>\n<p>interfaces<\/p>\n<p class=\"MsoNormal\">Let the coclass inherit from the new interfaces too. Add the<\/p>\n<p><strong>COM_INTERFACE_ENTRY<\/strong> for the new interfaces in the <strong>COM_MAP<\/strong>.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>8.Repeat step 3 ~ 6<\/h3>\n<h2><a name=\"_Toc43522191\"><\/a><a name=\"_Toc43522864\"><\/a><span style=\"mso-bookmark: _Toc43522191;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522864\"><\/a><span style=\"mso-bookmark: _Toc43522191;\">Manually Registering ATL DLL Servers<\/span><\/h2>\n<p class=\"MsoNormal\">A DLL COM server is<\/p>\n<p>supposed to export <strong>DllRegisterServer<\/strong> and <strong>DllUnregisterServer<\/strong> to<\/p>\n<p>register and unregister the server. You can invoke these functions using tool <strong>regsvr32.exe<\/strong>.<\/p>\n<p class=\"MsoNormal\">To register a DLL server:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">regsvr32 path\\bank.dll<\/span><\/p>\n<p class=\"MsoNormal\">To unregister a DLL server:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">regsvr32 <strong><span style=\"color: red;\">\/u<\/span><\/strong><\/span><\/p>\n<p>path\\bank.dll<\/p>\n<p class=\"MsoBodyTextIndent\">ATL makes it even more convenient: it inserts the following<\/p>\n<p>lines into the menu \u201cProject\u201d | \u201cSettings\u201d | \u201cCustom Build\u201d option:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">regsvr32 \/s \/c &#8220;$(TargetPath)&#8221; <\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">echo regsvr32 exec. time &gt;<\/span><\/p>\n<p>&#8220;$(OutDir)\\regsvr32.trg&#8221;<\/p>\n<p class=\"MsoNormal\">So that after each build the server will be automatically<\/p>\n<p>registered.<\/p>\n<h2><a name=\"_Toc43522192\"><\/a><a name=\"_Toc43522865\"><\/a><span style=\"mso-bookmark: _Toc43522192;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522865\"><\/a><span style=\"mso-bookmark: _Toc43522192;\">Supporting MFC in ATL Project<\/span><\/h2>\n<p class=\"MsoNormal\">When creating a new DLL ATL project with ATL COM AppWizard,<\/p>\n<p>you can tick the &#8220;Support MFC&#8221; option. But this binds your code with<\/p>\n<p>MFC and you have to ship the MFC runtime dll is shipped with your product. So<\/p>\n<p>you should always try not to select this option.<\/p>\n<p class=\"MsoNormal\">If you create an EXE ATL project, the &#8220;Support<\/p>\n<p>MFC&#8221; option is disabled. You have to add MFC support yourself.<\/p>\n<h2><a name=\"_Toc43522193\"><\/a><a name=\"_Toc43522866\"><\/a><span style=\"mso-bookmark: _Toc43522193;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522866\"><\/a><span style=\"mso-bookmark: _Toc43522193;\">Creating EXE Server with ATL<\/span><\/h2>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Create an EXE server project with ATL COM<\/p>\n<p>AppWizard;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Add an ATL object;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Add methods to the primary interface of the ATL<\/p>\n<p>object;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Add more interfaces and methods in the same way<\/p>\n<p>as with DLL server;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Add the commands to make and register the<\/p>\n<p>proxy\/stub DLL into custom build;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 46.35pt; text-indent: -18.0pt; mso-list: l8 level1 lfo16;\"><span style=\"font-family: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman';\"><span style=\"mso-list: Ignore;\">6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Build the project.<\/p>\n<h2><a name=\"_Toc43522194\"><\/a><a name=\"_Toc43522867\"><\/a><span style=\"mso-bookmark: _Toc43522194;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522867\"><\/a><span style=\"mso-bookmark: _Toc43522194;\">Manually Registering ATL EXE Servers<\/span><\/h2>\n<p class=\"MsoNormal\">Just like a DLL server, an EXE server also supports self<\/p>\n<p>registration. Simply run the program with command line argument \u201c<strong>\/RegServer<\/strong>\u201d<\/p>\n<p>to register or \u201c<strong>\/UnregServer<\/strong>\u201d to unregister:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522868\"><\/a><span lang=\"EN-AU\">ProjectName \/RegServer<\/span><\/p>\n<h2><a name=\"_Toc43522195\"><\/a><a name=\"_Toc43522869\"><\/a><span style=\"mso-bookmark: _Toc43522195;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522869\"><\/a><span style=\"mso-bookmark: _Toc43522195;\">Removing an ATL Coclass<\/span><\/h2>\n<p class=\"MsoNormal\">You can use ATL Object Wizard to insert new colcasses into<\/p>\n<p>the server, but to remove one added with ATL, you have to do the following<\/p>\n<p>things manually:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -14.2pt; mso-list: l13 level1 lfo18; tab-stops: list 42.55pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>In coclass.cpp, remove the #include of the<\/p>\n<p>coclass.h file;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -14.2pt; mso-list: l13 level1 lfo18; tab-stops: list 42.55pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>In coclass.cpp, remove the <strong>OBJECT_ENTRY<\/strong><\/p>\n<p>of the coclass;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -14.2pt; mso-list: l13 level1 lfo18; tab-stops: list 42.55pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Remove the code in IDL file;<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -14.2pt; mso-list: l13 level1 lfo18; tab-stops: list 42.55pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Open the project&#8217;s *.rc file with Wordpad or<\/p>\n<p>Notepad, locate the section beginning with &#8220;\/\/REGISTRY&#8221;, and remove<\/p>\n<p>the line containing the coclass.rgs.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -14.2pt; mso-list: l13 level1 lfo18; tab-stops: list 42.55pt 57.3pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Remove the *.cpp, *.h and *.rgs files of the<\/p>\n<p>coclass.<\/p>\n<h2><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522196\"><\/a><a name=\"_Toc43522870\"><\/a><span style=\"mso-bookmark: _Toc43522196;\">Implementing<\/span><\/h2>\n<p>an Interface in ATL<\/p>\n<h2><a name=\"_Toc43522870\"><\/a><\/h2>\n<p class=\"MsoNormal\" style=\"margin-left: 1.0cm;\">To implement an interface defined<\/p>\n<p>in the project&#8217;s IDL file, you have to<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 2.0cm; text-indent: -14.15pt; mso-list: l0 level1 lfo20; tab-stops: list 2.0cm 64.35pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>In<\/p>\n<p>the *.h file, let your coclass inherit from the interface,<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 2.0cm; text-indent: -14.15pt; mso-list: l0 level1 lfo20; tab-stops: list 2.0cm 64.35pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>In<\/p>\n<p>the *.h file, add an interface entry in the COM map,<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 2.0cm; text-indent: -14.15pt; mso-list: l0 level1 lfo20; tab-stops: list 2.0cm 64.35pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>In<\/p>\n<p>the *.h file, add the protoptypes of the interface methods:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 2.0cm; text-indent: -14.15pt; mso-list: l0 level1 lfo20; tab-stops: list 2.0cm 64.35pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>In<\/p>\n<p>the *.cpp file, implement the methods of the interface.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/**************** Any.h ********************<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class ATL_NO_VTABLE CAny : <\/span><\/p>\n<p>public CComObjectRootEx&lt;CComSingleThreadModel&gt;,<\/p>\n<p>public CComCoClass&lt;CAny, &amp;CLSID_Any&gt;,<\/p>\n<p class=\"Program\"><strong><span style=\"color: red;\" lang=\"EN-AU\">public IMyInterf\/\/ step 1<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CAny(){}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522871\"><\/a><span lang=\"EN-AU\">DECLARE_REGISTRY_RESOURCEID(IDR_ANY)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DECLARE_NOT_AGGREGATABLE(CAny)<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522872\"><\/a><span lang=\"EN-AU\">DECLARE_PROTECT_FINAL_CONSTRUCT()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">BEGIN_COM_MAP(CAny)<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><strong><span style=\"color: red;\" lang=\"EN-AU\"><a name=\"_Toc43522873\"><\/a>COM_INTERFACE_ENTRY(IMyInterf)\/\/ step 2<\/span><\/strong><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522874\"><\/a><span lang=\"EN-AU\">END_COM_MAP()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><strong><span style=\"color: red;\" lang=\"EN-AU\"><a name=\"_Toc43522875\"><\/a>STDMETHOD(Hi)();\/\/<\/span><\/strong><\/p>\n<p>step 3<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/************** Any.cpp ********************<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522876\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">STDMETHODIMP CAny::Hi()\/\/ step 4<\/span><\/strong><strong><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">return<\/span><\/p>\n<p>S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 1.0cm;\">You can also do all the above four<\/p>\n<p>steps automatically with ATL&#8217;s &#8220;Implement Interface Wizard&#8221;.<\/p>\n<p>Right-click the coclass in the class view, choose &#8220;Implement Interface&#8221;<\/p>\n<p>option, tick the unimplemented interface listed. If you do not see it listed,<\/p>\n<p>you may have forgotten to compile the IDL file.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 1.0cm;\">To be able to implement an<\/p>\n<p>interface with the wizard through type library, that interface must have been<\/p>\n<p>added into one coclass. For some reason, a stand-alone interface won&#8217;t be<\/p>\n<p>displayed by the wizard.<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 1.0cm;\">To implement an interface defined<\/p>\n<p>in another server, you only need to do one extra thing: <strong>#import<\/strong> the type<\/p>\n<p>library:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#import &#8220;D:\\My Documents\\Visual<\/span><\/p>\n<p>C++\\AnyServer\\AnyServer.tlb&#8221; \\<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">raw_interfaces_only, raw_native_types,<\/span><\/p>\n<p>no_namespace, named_guids<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 1.0cm;\">When you are using ATL&#8217;s<\/p>\n<p>&#8220;Implement Interface Wizard&#8221;, just click the &#8220;Add<\/p>\n<p>TypeLib&#8230;&#8221; button in the &#8220;Implement Interface&#8221; dialog. It will<\/p>\n<p>bring up another window containing all registered type libraries. If the type<\/p>\n<p>library is not yet registered, you can click the &#8220;Browse&#8221; button to<\/p>\n<p>browse to it. The wizard will add the #import line for you.<\/p>\n<h2><a name=\"_Toc43522197\"><\/a><a name=\"_Toc43522877\"><\/a><span style=\"mso-bookmark: _Toc43522197;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">8.9.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522877\"><\/a><span style=\"mso-bookmark: _Toc43522197;\">Debugging ATL Projects<\/span><\/h2>\n<p class=\"MsoNormal\">For debug builds, macro <strong>ATLTRACE<\/strong> prints argument into<\/p>\n<p>the debug window:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">LONG v = 1234;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">ATLTRACE(&#8220;The value is %d&#8221;, v);<\/span><\/p>\n<p class=\"MsoNormal\">For release builds it expends to nothing.<\/p>\n<p class=\"MsoNormal\"><strong>_ATL_DEBUG_QI<\/strong> preprocessor directive causes all <strong>QueryInterface<\/strong><\/p>\n<p>calls to be writtin into the debug window. Just put in <strong>stdafx.h<\/strong> the<\/p>\n<p>following line:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define _ATL_DEBUG_QI<\/span><\/p>\n<p class=\"MsoNormal\">To be able to see the interface call in form of<\/p>\n<p>&#8220;IAny&#8221;, &#8220;IMyInterface&#8221; instead of 128-bit guids, the<\/p>\n<p>interfaces should be registered.<\/p>\n<p class=\"MsoNormal\">Preprocessor directive <strong>_ATL_DEBUG_INTERFACES<\/strong> is based<\/p>\n<p>on <strong>_ATL_DEBUG_QI<\/strong> and can display the reference count and detect<\/p>\n<p>mishandling of <strong>AddRef<\/strong> and <strong>Release<\/strong>.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522198\"><\/a><a name=\"_Toc43522878\"><\/a><span style=\"mso-bookmark: _Toc43522198;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h1>\n<p>&nbsp;<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522878\"><\/a><span style=\"mso-bookmark: _Toc43522198;\">COM Threading Issues<\/span><\/h1>\n<h2><a name=\"_Toc43522199\"><\/a><a name=\"_Toc43522879\"><\/a><span style=\"mso-bookmark: _Toc43522199;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522879\"><\/a><span style=\"mso-bookmark: _Toc43522199;\">Multiple Thread Synchronization With Critical<\/span><\/h2>\n<p>Section<\/p>\n<h2><a name=\"_Toc43522879\"><\/a><\/h2>\n<p class=\"MsoNormal\">In non-COm C++ environment, different threads in the same<\/p>\n<p>process can freely talk to each other. Objects that are exposed to multiple<\/p>\n<p>threads have to make all their data thread-safe if necessary.<\/p>\n<p class=\"MsoNormal\">Following is a multithreaded example making use of <strong>CRITICAL_SECTION<\/strong><\/p>\n<p>to guarantee that a certain piece of code can only be accessed by one thread.<\/p>\n<p>The main thread creates a&#8221;ThreadParam&#8221; structureto hold parameters to pass to the new threads<\/p>\n<p>it fires. The parameters include a class object and a function pointer.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;stdafx.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &#8220;iostream.h&#8221;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#include &lt;stdio.h&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><a name=\"_Toc43522880\"><\/a><strong><span style=\"color: red;\" lang=\"EN-AU\">CRITICAL_SECTION<\/span><\/strong><span lang=\"EN-AU\"> g_cs;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef void(* Function)(int);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef struct {<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int<\/span><\/p>\n<p>a;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">} <strong><span style=\"color: red;\">Any<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef struct {<\/span><\/p>\n<p>Function f;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Any<\/span><\/p>\n<p>* pAny;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">} <strong><span style=\"color: red;\">ThreadParam<\/span><\/strong>;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void <strong><span style=\"color: red;\">ShowNumber<\/span><\/strong>(int<\/span><\/p>\n<p>a)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>sprintf(buf, &#8220;Number = %d&#8221;, a);<\/p>\n<p>m(buf);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Global thread function with arbitrary name<\/span><\/p>\n<p>but standard signature<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DWORD WINAPI Threads(void * p)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522881\"><\/a><strong><span style=\"color: red;\">EnterCriticalSection<\/span><\/strong>(&amp;g_cs);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>ThreadParam * pThreadParam = (ThreadParam *)p;<\/p>\n<p>char buf[80];<\/p>\n<p>sprintf(buf, &#8220;Beginning of thread %d&#8221;,<\/p>\n<p>(pThreadParam-&gt;pAny)-&gt;a);<\/p>\n<p>m(buf);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Any<\/span><\/p>\n<p>* pAny = pThreadParam-&gt;pAny;<\/p>\n<p>Function f = pThreadParam-&gt;f;<\/p>\n<p>f(pAny-&gt;a);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>sprintf(buf, &#8220;End of thread %d&#8221;,<\/p>\n<p>(pThreadParam-&gt;pAny)-&gt;a);<\/p>\n<p>m(buf);<\/p>\n<p>delete pThreadParam-&gt;pAny;<\/p>\n<p>delete pThreadParam;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">LeaveCriticalSection<\/span><\/strong>(&amp;g_cs);<\/span><\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">int APIENTRY WinMain(HINSTANCE hInstance,<\/span><\/p>\n<p>HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">InitializeCriticalSection<\/span><\/strong>(&amp;g_cs);<\/span><\/p>\n<p>ThreadParam * pThreadParam;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>for (int i = 1; i &lt; 10; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>pThreadParam = new ThreadParam;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">pThreadParam-&gt;pAny = new Any;<\/span><\/p>\n<p>pThreadParam-&gt;f = ShowNumber;<\/p>\n<p>pThreadParam-&gt;pAny-&gt;a = i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>DWORD dw;<\/p>\n<p>HANDLE h = <strong><span style=\"color: red;\">CreateThread<\/span><\/strong><\/p>\n<p>(NULL, 0, Threads, (void *)pThreadParam, 0, &amp;dw);<\/p>\n<p>CloseHandle(h);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">Sleep(20000);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">DeleteCriticalSection<\/span><\/strong>(&amp;g_cs);<\/span><\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522200\"><\/a><a name=\"_Toc43522882\"><\/a><span style=\"mso-bookmark: _Toc43522200;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522882\"><\/a><span style=\"mso-bookmark: _Toc43522200;\">COM Apartments<\/span><\/h2>\n<p class=\"MsoNormal\">When a thread calls <strong>CoInitializeEx<\/strong> (<strong>CoInitialize<\/strong><\/p>\n<p>maps to <strong>CoInitializeEx<\/strong>), it creates a COM apartment. If the second<\/p>\n<p>parameter of the function call is <strong>COINIT_APARTMENTTHREADED<\/strong>, a new<\/p>\n<p>Single-threaded Apartment (STA) is created. If it is <strong>COINIT_MULTITHREADED<\/strong>,<\/p>\n<p>the thread either creates a Multithreaded Apartment (MTA) if there isn\u2019t one<\/p>\n<p>created, or enters an existing one. So there can be multiple STAs in a process,<\/p>\n<p>but there is only one MTA per process.<\/p>\n<p class=\"MsoNormal\"><strong>CoInitializeEx<\/strong> Initializes the COM library for use by<\/p>\n<p>the calling thread, sets the thread&#8217;s concurrency model, and creates a new<\/p>\n<p>apartment for the thread if one is required [MSDN]. A thread must call <strong>CoInitializeEx<\/strong><\/p>\n<p>before calling any other COM library function except <strong>CoGetMalloc<\/strong> and<\/p>\n<p>other memory allocation functions.<\/p>\n<p class=\"MsoNormal\">When this thread calls <strong>CoCreateInstance<\/strong>, depending on<\/p>\n<p>whether the component\u2019s apartment type is the same, it either loads the<\/p>\n<p>component in the same apartment, or in a different one.<\/p>\n<p class=\"MsoBodyTextIndent\">Accesses to a coclass in an EXE server through<\/p>\n<p>proxy\/stub marshallers are automatically serialized, so there is no multithread<\/p>\n<p>synchronization issue when multiple clients are invoking the same EXE server.<\/p>\n<p>But different threads in a process can invoke concurrently the same DLL server.<\/p>\n<p class=\"MsoNormal\">A component should never create any threads on its own. This<\/p>\n<p>is primarily of concern to J++ and C++ developers, who have the ability to<\/p>\n<p>create threads directly. Developers creating objects in Visual Basic do not need<\/p>\n<p>to worry about this, as there is no way for them to explicitly create a thread<\/p>\n<p>[MSDN].<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>STA<\/h3>\n<p>and MTA<\/p>\n<p class=\"MsoNormal\">If one thread creates an apartment and then dispatches<\/p>\n<p>another thread which also needs to call COM library functions, the new thread<\/p>\n<p>should also call <strong>CoInitializeEx<\/strong> itself to create or enter another<\/p>\n<p>apartment.<\/p>\n<p class=\"MsoNormal\">If one STA thread wants to pass an interface pointer of a<\/p>\n<p>STA component to another STA thread, you must explicitly marshal the pointer,<\/p>\n<p>so that the calls to the component from the two threads are synchronized by the<\/p>\n<p>marshaller. Otherwise they won\u2019t be synchronized.<\/p>\n<p class=\"MsoNormal\">However, if the thread(s) and the component are in different<\/p>\n<p>types of apartments, you don\u2019t need to explicitly marshal the pointer, because<\/p>\n<p>proxy and stub will be loaded for inter-apartment calls and they will<\/p>\n<p>synchroniz all calls.<\/p>\n<p class=\"MsoNormal\">If you are passing pointer to a MTA component between MTA<\/p>\n<p>threads, don\u2019t marshal it, because a MTA component is meant to be accessed<\/p>\n<p>concurrently by multiple threads.<\/p>\n<p class=\"MsoNormal\">If we follow the above rule, we can make sure that one<\/p>\n<p>instance in a STA can only be accessed by one thread at the same time. However,<\/p>\n<p>two STA threads can access two instances of the same coclass concurrently,<\/p>\n<p>therefore they can access the same global or class data concurrently. So STA<\/p>\n<p>components must protect their global and class data. Local objects must be<\/p>\n<p>allocated on the stack.<\/p>\n<p class=\"MsoNormal\">If <strong>DllGetClassObject<\/strong> creates one class factory<\/p>\n<p>instance for each client request, the class factory does not need to be<\/p>\n<p>thread-safe. If a component uses one class factory instance for all client<\/p>\n<p>requests, then it needs to be thread-safe.<\/p>\n<p class=\"MsoNormal\">Becaue of the synchronization, the performance of a STA<\/p>\n<p>component is lower than a MTA component.<\/p>\n<p class=\"MsoNormal\">Because multiple threads can execute in an MTA concurrently,<\/p>\n<p>so you must protect all data in your component if necessary using critical<\/p>\n<p>sections or similar measures.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Primary<\/h3>\n<p>STA<\/p>\n<p class=\"MsoNormal\">Early legacy COM components are designed to be used in<\/p>\n<p>single-threaded environment. Their data is not protected at all. They also<\/p>\n<p>don&#8217;t put <strong>ThreadingModel<\/strong> entry into the System Registry.<\/p>\n<p class=\"MsoNormal\">When COM is asked to create an instance of coclass which<\/p>\n<p>doesn&#8217;t have a <strong>ThreadingModel<\/strong> entry, it will always put the instance in<\/p>\n<p>the first STA apartment. Therefore all legacy components are placed in the same<\/p>\n<p>STA apartment.It means that if one<\/p>\n<p>thread is calling any method in any componet in that STA, all other threads<\/p>\n<p>which wants to invoke any component have to wait. Therefore these components<\/p>\n<p>are 100% thread safe, including their global and class data. But there<\/p>\n<p>performance is the worst.<\/p>\n<h3><span style=\"font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol; color: windowtext; font-weight: normal; mso-bidi-font-weight: bold;\"><span style=\"mso-list: Ignore;\">\u00a8<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0 <\/span><\/span><\/span>Confusion<\/h3>\n<p class=\"MsoNormal\">Now that calls between STA and MTA are synchronized by<\/p>\n<p>proxy\/stub, and calls from two STA threads to a STA component has to be<\/p>\n<p>synchronized manually, what\u2019s the use of STA\u2019s message pump?<\/p>\n<h2><a name=\"_Toc43522201\"><\/a><a name=\"_Toc43522883\"><\/a><span style=\"mso-bookmark: _Toc43522201;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522883\"><\/a><span style=\"mso-bookmark: _Toc43522201;\">How do Components Declare Their Threading Model<\/span><\/h2>\n<p class=\"MsoBodyTextIndent\">When a coclass registers itself with *.rgs file in<\/p>\n<p>the system registery, it can register itself as one of four threading model by<\/p>\n<p>adding (or not adding) a <strong>ThreadingModel<\/strong> entry under <strong>HKCR\\CLSID\\&lt;clsid&gt;\\InprocServer32<\/strong>:<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l18 level1 lfo22; tab-stops: list 42.55pt left 120.5pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>Primary STAno<\/p>\n<p>ThreadingModel entry,<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l18 level1 lfo22; tab-stops: list 42.55pt left 120.5pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">2.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>STAThreadingModel<\/p>\n<p>= &#8220;Apartment&#8221;,<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l18 level1 lfo22; tab-stops: list 42.55pt left 120.5pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">3.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>MTAThreadingModel<\/p>\n<p>= &#8220;Free&#8221;,<\/p>\n<p class=\"MsoNormal\" style=\"margin-left: 42.55pt; text-indent: -21.25pt; mso-list: l18 level1 lfo22; tab-stops: list 42.55pt left 120.5pt;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/p>\n<p>BothThreadingModel<\/p>\n<p>= &#8220;Both&#8221;,<\/p>\n<p class=\"MsoNormal\">When you create a coclass (not a DLL or EXE housing) using<\/p>\n<p>ATL COM Wizard, you will be offered a chance to select from the above four<\/p>\n<p>options. Then the wizard will automatically generate a rgs file containing the<\/p>\n<p>correct registry entry.<\/p>\n<p class=\"MsoNormal\">Note that although a coclass can be dealt with by COM run<\/p>\n<p>time in the above four different ways, the coclass itself can be implemented in<\/p>\n<p>only two ways: STA or MTA. When using ATL it is determined by inheriting from<\/p>\n<p>template class <strong>CComObjectRootEx&lt;CComSingleThreadModel&gt;<\/strong> or <strong>CComObjectRootEx&lt;CComMultiThreadModel&gt;<\/strong>.<\/p>\n<p class=\"MsoNormal\">Especially, if you choose &#8220;Both&#8221; option, your<\/p>\n<p>component must aggregate with the free-threaded marshaller provided by COM. To<\/p>\n<p>do it, tick the &#8220;Free-threaded marshaller&#8221; option when you create an<\/p>\n<p>ATL object with the ATL Object Wizard.<\/p>\n<h2><a name=\"_Toc43522202\"><\/a><a name=\"_Toc43522884\"><\/a><span style=\"mso-bookmark: _Toc43522202;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.4.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522884\"><\/a><span style=\"mso-bookmark: _Toc43522202;\">How Does COM Choose Apartments for Components at<\/span><\/h2>\n<p>Run Time<\/p>\n<h2><a name=\"_Toc43522884\"><\/a><\/h2>\n<p class=\"MsoNormal\">A DLL coclass declares what kind of thread it can safely<\/p>\n<p>live in by putting a <strong>ThreadingModel<\/strong> entry in the System Registry.<\/p>\n<p class=\"MsoNormal\">Before a client thread invokes a component, it must first<\/p>\n<p>create a new apartment (can be STA or MTA) or enter an existing apartment<\/p>\n<p>(MTA). Then when it asks COM run time to load a COM component, COM will compare<\/p>\n<p>the apartment type of the client and the component, to decide whether to load<\/p>\n<p>the component in the same apartment as the client and let the client directly<\/p>\n<p>access it, or create a new apartment for the component alone and let the client<\/p>\n<p>talk to the component through proxy\/stub marshallers, which is less efficient<\/p>\n<p>than the first option.<\/p>\n<p class=\"MsoNormal\">To achieve better performance, COM run time will always try<\/p>\n<p>to load the component in the same apartment as the client. Only when the<\/p>\n<p>component declares that &#8220;I can only stay in xxx apartment&#8221; which is<\/p>\n<p>different from the apartment of the client, will COM create a new apartment for<\/p>\n<p>the component.<\/p>\n<p class=\"MsoNormal\">If a component declares itself to be \u201cPrimary STA\u201d, then COM<\/p>\n<p>always loads it in primary STA. Unless the client thread is also in the primary<\/p>\n<p>STA, proxy access is needed.<\/p>\n<p class=\"MsoNormal\">If a component is \u201cSTA\u201d, and the client is in primary STA or<\/p>\n<p>a normal STA, COM will create the component instance in the same apartment as<\/p>\n<p>the client so that no proxy access is needed. If the client is in MTA, proxy<\/p>\n<p>access is needed.<\/p>\n<p class=\"MsoNormal\">If a component is \u201cFree\u201d, and client is MTA, then the<\/p>\n<p>component is loaded into the process-unique MTA, and the client can directly<\/p>\n<p>access the component without any overhead. However, if client is<\/p>\n<p>single-threaded, then a proxy access is needed. This is not good.<\/p>\n<p class=\"MsoNormal\">If a component is &#8220;Both&#8221;, then a directly access<\/p>\n<p>is always guaranteed, because COM always creates the component instance in the<\/p>\n<p>same apartment as the client, no matter the client is in primary STA, STA or<\/p>\n<p>MTA. This is the best component threading model, the cost is you have to<\/p>\n<p>provide full synchronization protection for your code.<\/p>\n<h2><a name=\"_Toc43522203\"><\/a><a name=\"_Toc43522885\"><\/a><span style=\"mso-bookmark: _Toc43522203;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.5.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522885\"><\/a><span style=\"mso-bookmark: _Toc43522203;\">Proxy\/stub<\/span><\/h2>\n<p class=\"MsoNormal\">Any communication across the apartment boundary needs the<\/p>\n<p>help of a proxy\/stub DLL server, which is generated and registered with <strong>nmake<\/strong><\/p>\n<p>and <strong>regsvr32<\/strong> exactly as you do with EXE servers.<\/p>\n<h2><a name=\"_Toc43522204\"><\/a><a name=\"_Toc43522886\"><\/a><span style=\"mso-bookmark: _Toc43522204;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.6.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522886\"><\/a><span style=\"mso-bookmark: _Toc43522204;\">ATL&#8217;s Threading Support with<\/span><\/h2>\n<p>CComObjectRootEx&lt;&gt;<\/p>\n<h2><a name=\"_Toc43522886\"><\/a><\/h2>\n<p class=\"MsoNormal\">ATL&#8217;s support for thread protection i.e. synchronization at<\/p>\n<p>the end comes to four methods: <strong>Increment<\/strong> and <strong>Decrement<\/strong> which are<\/p>\n<p>used to increment and decrement the object reference count <strong>m_refCount<\/strong>,<\/p>\n<p>and <strong>Lock<\/strong> and <strong>Unlock<\/strong> which wraps proected code and extends to<\/p>\n<p>critical section function calls.<\/p>\n<p class=\"MsoNormal\">An ATL coclass always inherits from <strong>CComObjectRootEx&lt;&gt;<\/strong>,<\/p>\n<p>which takes one threading model class as template parameter, which can either<\/p>\n<p>be <strong>CComSingleThreadModel<\/strong> (for STA coclass) or <strong>CComMultiThreadModel<\/strong><\/p>\n<p>(for MTA coclass).These two classes has<\/p>\n<p>exactly the same interfaces. They contain method <strong>Increment<\/strong> and <strong>Decrement<\/strong>,<\/p>\n<p>and the <strong>typedef<\/strong> of three other classes which contain method <strong>Lock<\/strong><\/p>\n<p>and <strong>Unlock<\/strong>.<\/p>\n<p class=\"MsoNormal\"><strong>CComObjectRootEx&lt;&gt;<\/strong> itself provides four thread<\/p>\n<p>protection methods: <strong>InternalAddRef<\/strong>, <strong>InternalRelease<\/strong>, <strong>Lock<\/strong>,<\/p>\n<p><strong>Unlock<\/strong>, which all turn around and call methods of the passed threading<\/p>\n<p>model class to deal with threading issues. Method <strong>InternalAddRef<\/strong> and <strong>InternalReleas<\/strong>e<\/p>\n<p>are called by the <strong>CComObject&lt;&gt; <\/strong>template&#8217;s IUnknown method AddRef<strong><\/strong><\/p>\n<p>and<strong> <\/strong>Release, and <strong>Lock <\/strong>and <strong>Unlock<\/strong> are used to enter and<\/p>\n<p>leave critical sections.<\/p>\n<p class=\"MsoNormal\"><strong>InternalQueryInterface<\/strong> is provided elsewhere by <strong>CComObjectRootBase<\/strong>.<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">template &lt;class <strong><span style=\"color: red;\">ThreadModel<\/span><\/strong>&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class <strong><span style=\"color: red;\">CComObjectRootEx<\/span><\/strong><\/span><\/p>\n<p>: public <strong><span style=\"color: red;\">CComObjectRootBase<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">typedef<\/span><\/strong> <strong><span style=\"color: red;\">ThreadModel<\/span><\/strong><\/span><\/p>\n<p>_ThreadModel;<\/p>\n<p>typedef _ThreadModel::AutoCriticalSection _CritSec;<\/p>\n<p>typedef CComObjectLockT&lt;_ThreadModel&gt; ObjectLock;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>ULONG <strong><span style=\"color: red;\">InternalAddRef<\/span><\/strong>()<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>ATLASSERT(m_dwRef != -1L);<\/p>\n<p>return _ThreadModel::<strong><span style=\"color: red;\">Increment<\/span><\/strong>(&amp;m_dwRef);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>ULONG <strong><span style=\"color: red;\">InternalRelease<\/span><\/strong>()<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>ATLASSERT(m_dwRef &gt; 0);<\/p>\n<p>return _ThreadModel::<strong><span style=\"color: red;\">Decrement<\/span><\/strong>(&amp;m_dwRef);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>void <strong><span style=\"color: red;\">Lock<\/span><\/strong>() {m_critsec.<strong><span style=\"color: red;\">Lock<\/span><\/strong>();}<\/p>\n<p>void <strong><span style=\"color: red;\">Unlock<\/span><\/strong>() {m_critsec.<strong><span style=\"color: red;\">Unlock<\/span><\/strong>();}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">private:<\/span><\/p>\n<p>_CritSec m_critsec;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">Because the two classes has the same interfaces, if you want<\/p>\n<p>to change the threading model of an existing component, all you need to do is<\/p>\n<p>simply swapping between <strong>CComSingleThreadModel<\/strong> and <strong>CComMultiThreadModel<\/strong>.<\/p>\n<p class=\"MsoNormal\">In class <strong>CComSingleThreadModel<\/strong> which is used for STA<\/p>\n<p>components, method <strong>Increment<\/strong> and<strong>Decrement<\/strong><\/p>\n<p>simply use &#8220;++&#8221; or &#8220;- -&#8221; operation on the object reference<\/p>\n<p>count, and it typedefs <strong>CComFakeCriticalSection<\/strong> as the classes providing <strong>Lock<\/strong><\/p>\n<p>and <strong>Unlock,<\/strong> which does nothing:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class <strong><span style=\"color: red;\">CComSingleThreadModel<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p>static ULONG WINAPI <strong><span style=\"color: red;\">Increment<\/span><\/strong>(LPLONG<\/p>\n<p>p) {return ++(*p);}<\/p>\n<p>static ULONG WINAPI <strong><span style=\"color: red;\">Decrement<\/span><\/strong>(LPLONG<\/p>\n<p>p) {return &#8211;(*p);}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>typedef <strong><span style=\"color: red;\">CComFakeCriticalSection<\/span><\/strong><\/p>\n<p>AutoCriticalSection;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComFakeCriticalSection CriticalSection;<\/p>\n<p>typedef CComSingleThreadModel ThreadModelNoCS;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class CComFakeCriticalSection<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p>void <strong><span style=\"color: red;\">Lock<\/span><\/strong>() {}<\/p>\n<p>void <strong><span style=\"color: red;\">Unlock<\/span><\/strong>() {}<\/p>\n<p>void Init() {}<\/p>\n<p>void Term() {}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">Because <strong>CComSingleThreadModel<\/strong>actually provides no useful thread-protecting<\/p>\n<p>code at all, you have to use cirtical section functions to protect your global<\/p>\n<p>and static data.<\/p>\n<p class=\"MsoNormal\">In comparison, in class <strong>CComMultiThreadModel<\/strong> which is<\/p>\n<p>used for MTA components, method <strong>Increment<\/strong> and <strong>Decrement<\/strong> uses API<\/p>\n<p>function <strong>InterlockedIncrement<\/strong> and <strong>InterlockedDecrement<\/strong> to safely<\/p>\n<p>operate on data member <strong>m_refCount<\/strong>, and it typedefs <strong>CComAutoCriticalSection<\/strong><\/p>\n<p>to provide method <strong>Lock<\/strong> and <strong>Unlock<\/strong>, which extends to critical<\/p>\n<p>section function calls:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class <strong><span style=\"color: red;\">CComMultiThreadModel<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">static<\/span><\/p>\n<p>ULONG WINAPI <strong><span style=\"color: red;\">Increment<\/span><\/strong>(LPLONG p) {return <strong><span style=\"color: red;\">InterlockedIncrement<\/span><\/strong>(p);}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">static<\/span><\/p>\n<p>ULONG WINAPI <strong><span style=\"color: red;\">Decrement<\/span><\/strong>(LPLONG p) {return <strong><span style=\"color: red;\">InterlockedDecrement<\/span><\/strong>(p);}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p><strong><span style=\"color: red;\">CComAutoCriticalSection<\/span><\/strong><\/p>\n<p>AutoCriticalSection;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComCriticalSection CriticalSection;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComMultiThreadModelNoCS ThreadModelNoCS;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class <strong><span style=\"color: red;\">CComAutoCriticalSection<\/span><\/strong><\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void <strong><span style=\"color: red;\">Lock<\/span><\/strong>() {<strong><span style=\"color: red;\">EnterCriticalSection<\/span><\/strong>(&amp;m_sec);}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">void <strong><span style=\"color: red;\">Unlock<\/span><\/strong>() {<strong><span style=\"color: red;\">LeaveCriticalSection<\/span><\/strong>(&amp;m_sec);}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">CComAutoCriticalSection()<\/span><\/p>\n<p>{InitializeCriticalSection(&amp;m_sec);}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">~CComAutoCriticalSection()<\/span><\/p>\n<p>{DeleteCriticalSection(&amp;m_sec);}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CRITICAL_SECTION<\/span><\/strong> m_sec;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">};<\/span><\/p>\n<p class=\"MsoNormal\">To protect other data in the coclass, simply call method <strong>Lock<\/strong><\/p>\n<p>and <strong>Unlock<\/strong>.<\/p>\n<h2><a name=\"_Toc43522205\"><\/a><a name=\"_Toc43522887\"><\/a><span style=\"mso-bookmark: _Toc43522205;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.7.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522887\"><\/a><span style=\"mso-bookmark: _Toc43522205;\">How do Clients Decide Their Threading Model<\/span><\/h2>\n<p class=\"MsoNormal\">Because all COM components must be placed in apartments, if<\/p>\n<p>a thread wants to access a component, it must create an apartment or enter an<\/p>\n<p>existing one. This is done by calling function <strong>CoInitializeEx<\/strong> passing<\/p>\n<p>NULL and <strong>COINIT_MULTITHREADED<\/strong> for MTA or <strong>COINIT_APARTMENTTHREADED<\/strong><\/p>\n<p>for STA. Before you use <strong>CoInitializeEx<\/strong>, make sure you have defined <strong>_WIN32_DCOM<\/strong>.<\/p>\n<h2><a name=\"_Toc43522206\"><\/a><a name=\"_Toc43522888\"><\/a><span style=\"mso-bookmark: _Toc43522206;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.8.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522888\"><\/a><span style=\"mso-bookmark: _Toc43522206;\">Marshalling Interface Pointer Between<\/span><\/h2>\n<p>Appartments<\/p>\n<h2><a name=\"_Toc43522888\"><\/a><\/h2>\n<p class=\"MsoNormal\">The rule is: when you move an interface pointer across the apartment<\/p>\n<p>boundary, it must be marshalled. When you move an interface pointer through COM<\/p>\n<p>API function calls such as <strong>CoCreateInstance<\/strong> or <strong>QueryInterface<\/strong>, or<\/p>\n<p>pass it as a parameter in a COM method call, COM run time will take care of the<\/p>\n<p>marshalling. However, when COM is not involved in the marshalling, you have to<\/p>\n<p>marshal the interface pointer yourself.<\/p>\n<p class=\"MsoNormal\">In the following example, COM server <strong>Threads<\/strong> defines<\/p>\n<p>an call-back interface <strong>ICallBack<\/strong>. Another COM server implements <strong>ICallBack<\/strong><\/p>\n<p>interface. The client creates an instance of both of the servers, call server <strong>Threads<\/strong>&#8216;s<\/p>\n<p><strong>Advise<\/strong> method to pass it the pointer to the implemented <strong>ICallBack<\/strong>.<\/p>\n<p>Then the client calls coclass <strong>Source<\/strong>&#8216;s <strong>DoWork<\/strong> method, which<\/p>\n<p>spawns a new thread passing the <strong>ICallBack<\/strong> pointer. The thread will call<\/p>\n<p>the call back method of <strong>ICallBack<\/strong> to do its job.<\/p>\n<p class=\"MsoNormal\">In this example, coclass <strong>Source<\/strong> is in STA, while the<\/p>\n<p>thread it creats enters the MTA. Some book says in such case because the<\/p>\n<p>calling through interface pointer is not between client and server and thus not<\/p>\n<p>taken care of by COM run time, you have to marshal the interface yourself. So I<\/p>\n<p>did this in this example, but it works fine even if you don&#8217;t marshal it at<\/p>\n<p>all!<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CSource::Advise(ICallBack<\/span><\/p>\n<p>*pCallBack)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>m_pCallBack = pCallBack;<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">STDMETHODIMP CSource::DoWork()<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\" style=\"mso-outline-level: 1;\"><span lang=\"EN-AU\"><a name=\"_Toc43522889\"><\/a>PARAM * pParam =<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>(PARAM *)CoTaskMemAlloc(sizeof(PARAM) + 50000 * sizeof(LONG));<\/p>\n<p>pParam-&gt;sSize = 50000;<\/p>\n<p>for(LONG i = 0; i &lt; 50000; i++)<\/p>\n<p>pParam-&gt;sArray[i] = i;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>IStream * ps = NULL;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">HRESULT hr = <strong><span style=\"color: red;\">CoMarshalInterThreadInterfaceInStream<\/span><\/strong><\/span><\/p>\n<p>(IID_ICallBack, m_pCallBack, &amp;ps);<\/p>\n<p>pParam-&gt;ps = ps;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>DWORD dw;<\/p>\n<p>HANDLE h = <strong><span style=\"color: red;\">CreateThread<\/span><\/strong>(0, 0,<\/p>\n<p>AThread, (void *)pParam, 0, &amp;dw);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CloseHandle<\/span><\/strong>(h);<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>Sleep(3000);<\/p>\n<p>return S_OK;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\/\/ Global thread function with arbitrary name<\/span><\/p>\n<p>but standard signature<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">DWORD WINAPI AThread(void * p)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoInitializeEx<\/span><\/strong>(NULL, <strong><span style=\"color: red;\">COINIT_MULTITHREADED<\/span><\/strong>);<\/span><\/p>\n<p>PARAM * pParam = (PARAM *)p;<\/p>\n<p>ICallBack * pCallBack = NULL;<\/p>\n<p>HRESULT hr = <strong><span style=\"color: red;\">CoGetInterfaceAndReleaseStream<\/span><\/strong><\/p>\n<p>(pParam-&gt;ps, IID_ICallBack, (void **)&amp;pCallBack);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>char buf[80];<\/p>\n<p>for(LONG i = 0; i &lt; pParam-&gt;sSize; i++)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>if(i % 10000 == 0)<\/p>\n<p>{<\/p>\n<p>sprintf(buf, &#8220;pParam-&gt;sArray[%d] = %d&#8221;, i,<\/p>\n<p>pParam-&gt;sArray[i]);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">m(buf);<\/span><\/p>\n<p>}<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>LONG * ps = (LONG *)CoTaskMemAlloc(100000 * sizeof(LONG));<\/p>\n<p>for(i = 0; i &lt; 100000; i++)<\/p>\n<p>ps[i] = i;<\/p>\n<p>pCallBack-&gt;CallBackMethod(100000, ps);<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\"><strong><span style=\"color: red;\">CoUninitialize<\/span><\/strong>();<\/span><\/p>\n<p>return 0;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<h2><a name=\"_Toc43522207\"><\/a><a name=\"_Toc43522890\"><\/a><span style=\"mso-bookmark: _Toc43522207;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">9.9.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522890\"><\/a><span style=\"mso-bookmark: _Toc43522207;\">ATL Server&#8217;s Default Threading Support<\/span><\/h2>\n<p class=\"MsoNormal\">Every project generated with ATL COM AppWizard defines a<\/p>\n<p>default threading model in the precompiled header file stdafx.h. This model<\/p>\n<p>accounts for threading issues that you do not need to concern, such as how ATL<\/p>\n<p>locks its global data:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#define _ATL_APARTMENT_THREADED<\/span><\/p>\n<p class=\"MsoNormal\">There are three options: <strong>_ATL_SINGLE_THREADED<\/strong>, <strong>_ATL_APARTMENT_THREADED<\/strong><\/p>\n<p>and _<strong>ATL_FREE_THREADED<\/strong>.<\/p>\n<p class=\"MsoNormal\">In &lt;atlbase.h&gt;, there are following typedefs based on<\/p>\n<p>the above definition:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#if defined(_ATL_SINGLE_THREADED)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComSingleThreadModel CComObjectThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComSingleThreadModel CComGlobalsThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#elif defined(_ATL_APARTMENT_THREADED)<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComSingleThreadModel CComObjectThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComMultiThreadModel CComGlobalsThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#else<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComMultiThreadModel CComObjectThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">typedef<\/span><\/p>\n<p>CComMultiThreadModel CComGlobalsThreadModel;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">#endif<\/span><\/p>\n<p class=\"MsoNormal\">Therefore, the definition of default threading model must<\/p>\n<p>proceed the include of &lt;atlbase.h&gt;.<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522208\"><\/a><a name=\"_Toc43522891\"><\/a><span style=\"mso-bookmark: _Toc43522208;\"><span style=\"mso-fareast-font-family: Arial; mso-bidi-font-family: Arial;\"><span style=\"mso-list: Ignore;\">10.<\/span><\/span>Other<\/span><\/h1>\n<p>ATL Supporting Classes<\/p>\n<h1 style=\"margin-left: 17.85pt; text-indent: -17.85pt;\"><a name=\"_Toc43522891\"><\/a><\/h1>\n<h2><a name=\"_Toc43522209\"><\/a><a name=\"_Toc43522892\"><\/a><span style=\"mso-bookmark: _Toc43522209;\"><span style=\"mso-fareast-font-family: Arial;\"><span style=\"mso-list: Ignore;\">10.1.<span style=\"font: 7.0pt 'Times New Roman';\">\u00a0\u00a0\u00a0\u00a0<\/span><\/span><\/span><\/span><\/h2>\n<p>&nbsp;<\/p>\n<h2><a name=\"_Toc43522892\"><\/a><span style=\"mso-bookmark: _Toc43522209;\">CComObject&lt;&gt; Template Classes \u2013 Creatable<\/span><\/h2>\n<p>Coclasses<\/p>\n<h2><a name=\"_Toc43522892\"><\/a><\/h2>\n<p class=\"MsoNormal\">The coclass you create with COM AppWizard does not contain<\/p>\n<p>the implementation of <strong>IUnknown<\/strong> methods. Therefore they are abstract<\/p>\n<p>classes. They can not be directly created. Instead a coclass is passed to one<\/p>\n<p>of a set of template classes, which inherits from the coclass passed as<\/p>\n<p>template parameter, and provides a specific implementation of the <strong>IUnknown<\/strong><\/p>\n<p>methods. This template classes become the real creatable coclasses.<\/p>\n<p class=\"MsoNormal\">The reason behind these logic is to separate the custom<\/p>\n<p>implementation of coclasses from the implementation of IUnknown, so that the<\/p>\n<p>ATL coclasses are more portable.<\/p>\n<p class=\"MsoNormal\">The definition of the most commonly used template class <strong>CComObject<\/strong>&lt;&gt;<\/p>\n<p>is listed below:<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">template &lt;class <strong><span style=\"color: red;\">Base<\/span><\/strong>&gt;<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">class <strong><span style=\"color: red;\">CComObject<\/span><\/strong><\/span><\/p>\n<p>: <strong><span style=\"color: red;\">public<\/span><\/strong> <strong><span style=\"color: red;\">Base<\/span><\/strong><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">public:<\/span><\/p>\n<p>typedef Base _BaseClass;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>CComObject(void* = NULL)<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>_Module.Lock(); \/\/ _Module is the global CComModule<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p>~CComObject() \/\/ Set refcount to 1 to protect destruction<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>m_dwRef = 1L;<\/p>\n<p>FinalRelease();<\/p>\n<p>_Module.DeleteNonAddRefThunk(_GetRawUnknown());<\/p>\n<p>_Module.Unlock();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>STDMETHOD_(ULONG, <strong><span style=\"color: red;\">AddRef<\/span><\/strong>)()<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>return <strong><span style=\"color: red;\">InternalAddRef<\/span><\/strong>();<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<p>STDMETHOD_(ULONG, <strong><span style=\"color: red;\">Release<\/span><\/strong>)()<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">{<\/span><\/p>\n<p>ULONG l = <strong><span style=\"color: red;\">InternalRelease<\/span><\/strong>();<\/p>\n<p>if (l == 0)<\/p>\n<p>delete this;<\/p>\n<p>return l;<\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">}<\/span><\/p>\n<p class=\"Program\"><span lang=\"EN-AU\">\u00a0<\/span><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>COM Tutorial COM &amp; ATL Silan Liu \u00a0 1.\u00a0\u00a0\u00a0\u00a0\u00a0 COM Basics &nbsp; 1.1.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &nbsp; Service Control Manager (SCM) A Windows program called Service Control Manager (SCM) does most of the job in COM server invoking. It finds the server through &hellip; <a href=\"https:\/\/templesystems.com\/?page_id=318\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":305,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-318","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/pages\/318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/templesystems.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=318"}],"version-history":[{"count":5,"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/pages\/318\/revisions"}],"predecessor-version":[{"id":322,"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/pages\/318\/revisions\/322"}],"up":[{"embeddable":true,"href":"https:\/\/templesystems.com\/index.php?rest_route=\/wp\/v2\/pages\/305"}],"wp:attachment":[{"href":"https:\/\/templesystems.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}