PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Visual Studio 2008/CppCOMClient/ImportDirective.cpp

#
C++ | 190 lines | 55 code | 27 blank | 108 comment | 1 complexity | f64d0c70528257a4c776053f71b52912 MD5 | raw file
  1. /****************************** Module Header ******************************\
  2. * Module Name: ImportDirective.cpp
  3. * Project: CppCOMClient
  4. * Copyright (c) Microsoft Corporation.
  5. *
  6. * #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), a new
  7. * directive that became available with Visual C++ 5.0, creates VC++ "smart
  8. * pointers" from a specified type library. It is very powerful, but often not
  9. * recommended because of reference-counting problems that typically occur when
  10. * used with the Microsoft Office applications. Unlike the direct API approach
  11. * in RawAPI.h/cpp, smart pointers enable us to benefit from the type info to
  12. * early/late bind the object. #import takes care of adding the messy guids to
  13. * the project and the COM APIs are encapsulated in custom classes that the
  14. * #import directive generates.
  15. *
  16. * The differences between early binding and late binding via smart pointers:
  17. *
  18. * Smart pointers make creating an object that supports early binding easy, so
  19. * does it make creating a late bound object. The only difference between early
  20. * binding and late binding via smart pointer is the .tlh and .tli files
  21. * generated by the #import directive. If the target object supports early
  22. * binding, the .tlh and .tli files will make use of the custom interface (not
  23. * IDispatch) to call the target property/method directly. If the target COM
  24. * object only support late binding, the smart pointer takes care of converting
  25. * your method calls into GetIDsOfNames()s and Invoke()s of the IDispatch
  26. * interface.
  27. *
  28. * References
  29. * http://support.microsoft.com/kb/169496
  30. *
  31. * This source is subject to the Microsoft Public License.
  32. * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  33. * All other rights reserved.
  34. *
  35. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  36. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  37. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  38. \***************************************************************************/
  39. #pragma region Includes
  40. #include <stdio.h>
  41. #include "ImportDirective.h"
  42. #pragma endregion
  43. #pragma region Import the type library
  44. // Importing mscorlib.tlb is necessary for .NET components
  45. // see:
  46. // http://msdn.microsoft.com/en-us/library/s5628ssw.aspx
  47. #import "mscorlib.tlb" raw_interfaces_only \
  48. high_property_prefixes("_get","_put","_putref") \
  49. rename("ReportEvent", "InteropServices_ReportEvent")
  50. using namespace mscorlib;
  51. // Option 1) #import the name of a file that contains a type library
  52. //
  53. // We can either specify the full path of the tlb/dll/ocx/exe file or add
  54. // the path of the file to the project's Additional Include Directories
  55. // setting.
  56. //
  57. // For .NET components, importing the assembly file (dll/exe) fails because
  58. // the type library is not embedded in the .NET assemblies. There is a
  59. // stand-alone tlb file. For native components, the type library is embedded
  60. // into the executable by default, and we can #import the dll/ocx/exe module
  61. // directly.
  62. //#import "CSDllCOMServer.tlb" no_namespace named_guids
  63. // Option 2) #import the progid of the component in the type library
  64. //
  65. // #import-ing the progid only works for native components because .NET
  66. // components do not register the typelib for its ProgID by default. As an
  67. // evidence, please open the CLSID registry node and check the TypeLib key:
  68. // HKCR\CLSID\{xxxx}\TypeLib, which is lacked by .NET components.
  69. //#import "progid:CSDllCOMServer.SimpleObject" \
  70. // no_namespace \
  71. // named_guids
  72. // Option 3) #import the libid of the type library
  73. //
  74. // In the type library of CSDllCOMServer, the library ID is
  75. // F0998D9A-0E79-4F67-B944-9E837F479587
  76. //
  77. // [uuid(F0998D9A-0E79-4F67-B944-9E837F479587), version(1.0),
  78. // custom(90883F05-3D28-11D2-8F17-00A0C9A6186D,"CSDllCOMServer,...)]
  79. // library CSDllCOMServer { ... }
  80. //
  81. // #importing the library ID works for both native an .NET components.
  82. #import "libid:F0998D9A-0E79-4F67-B944-9E837F479587" \
  83. no_namespace \
  84. named_guids
  85. #pragma endregion
  86. /*!
  87. * \brief
  88. * The definition of ImportCSharpComponent in the header file
  89. *
  90. * \see
  91. * Separate ImportDirective.h | ImportCSharpComponent
  92. */
  93. DWORD WINAPI ImportCSharpComponent(LPVOID lpParam)
  94. {
  95. HRESULT hr = S_OK;
  96. // Initializes the COM library on the current thread and identifies the
  97. // concurrency model as single-thread apartment (STA).
  98. // [-or-] ::CoInitialize(NULL);
  99. // [-or-] ::CoCreateInstance(NULL);
  100. ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  101. try
  102. {
  103. // Create the CSDllCOMServer.SimpleObject COM object using the
  104. // #import directive and smart pointers.
  105. // Option 1) Create the object using the smart pointer's constructor
  106. //
  107. // ISimpleObjectPtr is the original interface name, ISimpleObject,
  108. // with a "Ptr" suffix.
  109. //ISimpleObjectPtr spSimpleObj(
  110. // __uuidof(SimpleObject) // CLSID of the component
  111. // );
  112. // Option 2) Create the object using the smart pointer's function,
  113. // CreateInstance
  114. ISimpleObjectPtr spSimpleObj;
  115. hr = spSimpleObj.CreateInstance(__uuidof(SimpleObject));
  116. if (FAILED(hr))
  117. {
  118. wprintf(L"ISimpleObjectPtr::CreateInstance failed w/err 0x%08lx\n", hr);
  119. return hr;
  120. }
  121. //
  122. // Consume the properties and the methods of the COM object.
  123. //
  124. // Set the property: FloatProperty.
  125. {
  126. wprintf(L"Set FloatProperty = %.2f\n", 1.2f);
  127. spSimpleObj->FloatProperty = 1.2f;
  128. }
  129. // Get the property: FloatProperty.
  130. {
  131. wprintf(L"Get FloatProperty = %.2f\n", spSimpleObj->FloatProperty);
  132. }
  133. // Call the method: HelloWorld, that returns a BSTR.
  134. {
  135. // the _bstr_t object and the underlying BSTR will be cleared
  136. // automatically in the destructor when the object is out of
  137. // the scope.
  138. bstr_t bstrResult = spSimpleObj->HelloWorld();
  139. wprintf(L"Call HelloWorld => %s\n", (PCWSTR)bstrResult);
  140. }
  141. // Call the method: GetProcessThreadID, that outputs two DWORDs.
  142. {
  143. wprintf(L"The client process and thread: %ld, %ld\n",
  144. GetCurrentProcessId(), GetCurrentThreadId());
  145. DWORD dwProcessId, dwThreadId;
  146. spSimpleObj->GetProcessThreadID(&dwProcessId, &dwThreadId);
  147. wprintf(L"Call GetProcessThreadID => %ld, %ld\n",
  148. dwProcessId, dwThreadId);
  149. }
  150. // Release the COM objects.
  151. // Releasing the references is not necessary for the smart pointers
  152. // spSimpleObj.Release();
  153. wprintf(L"\n");
  154. }
  155. catch (_com_error &err)
  156. {
  157. wprintf(L"The server throws the error: %s\n", err.ErrorMessage());
  158. wprintf(L"Description: %s\n", (PCWSTR) err.Description());
  159. }
  160. // Uninitialize COM for this thread
  161. ::CoUninitialize();
  162. return hr;
  163. }