component B.cpp
上传用户:bjlvip
上传日期:2010-02-08
资源大小:744k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // local.cpp
  2. #define _WIN32_DCOM
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <conio.h>
  6. #include <iaccess.h>   // IAccessControl
  7. #include <iostream.h>  // For cout
  8. #include "registry.h"  // For registry functions
  9. #include "Component Bcomponent.h" // Generated by MIDL
  10. #define MB_SERVICE_NOTIFICATION          0x00200000L
  11. void display_proxy_info(IUnknown* pUnknown)
  12. {
  13. DWORD AuthnSvc;
  14. DWORD AuthzSvc;
  15. OLECHAR* ServerPrincName;
  16. DWORD AuthnLevel;
  17. DWORD ImpLevel;
  18. RPC_AUTH_IDENTITY_HANDLE pAuthInfo;
  19. DWORD Capabilities;
  20. HRESULT hr = CoQueryProxyBlanket(pUnknown, &AuthnSvc, &AuthzSvc, &ServerPrincName, &AuthnLevel, &ImpLevel, &pAuthInfo, &Capabilities);
  21. if(FAILED(hr))
  22. cout << "CoQueryProxyBlanket failed" << endl;
  23. cout << endl << "Proxy security blanket information follows:" << endl;
  24. switch(AuthnSvc)
  25. {
  26. case RPC_C_AUTHN_NONE:
  27. cout << "Authentication service is RPC_C_AUTHN_NONE." << endl;;
  28. break;
  29. case RPC_C_AUTHN_GSS_NEGOTIATE:
  30. cout << "Authentication service is RPC_C_AUTHN_GSS_NEGOTIATE." << endl;
  31. break;
  32. case RPC_C_AUTHN_GSS_KERBEROS:
  33. cout << "Authentication service is RPC_C_AUTHN_GSS_KERBEROS." << endl;
  34. break;
  35. case RPC_C_AUTHN_WINNT:
  36. cout << "Authentication service is RPC_C_AUTHN_WINNT." << endl;
  37. break;
  38. case RPC_C_AUTHN_DEFAULT:
  39. cout << "Authentication service is RPC_C_AUTHN_DEFAULT." << endl;
  40. break;
  41. }
  42. switch(AuthzSvc)
  43. {
  44. case RPC_C_AUTHZ_NONE:
  45. cout << "Authorization service is RPC_C_AUTHZ_NONE." << endl;
  46. break;
  47. case RPC_C_AUTHZ_NAME:
  48. cout << "Authorization service is RPC_C_AUTHZ_NAME." << endl;
  49. break;
  50. case RPC_C_AUTHZ_DCE:
  51. cout << "Authorization service is RPC_C_AUTHZ_DCE." << endl;
  52. break;
  53. case RPC_C_AUTHZ_DEFAULT:
  54. cout << "Authorization service is RPC_C_AUTHZ_DEFAULT." << endl;
  55. break;
  56. }
  57. wprintf(L"The current principal name is %s.n", ServerPrincName);
  58. CoTaskMemFree(ServerPrincName);
  59. switch(AuthnLevel)
  60. {
  61. case RPC_C_AUTHN_LEVEL_DEFAULT:
  62. cout << "Authentication level is RPC_C_AUTHN_LEVEL_DEFAULT." << endl;
  63. break;
  64. case RPC_C_AUTHN_LEVEL_NONE:
  65. cout << "Authentication level is RPC_C_AUTHN_LEVEL_NONE." << endl;
  66. break;
  67. case RPC_C_AUTHN_LEVEL_CONNECT:
  68. cout << "Authentication level is RPC_C_AUTHN_LEVEL_CONNECT." << endl;
  69. break;
  70. case RPC_C_AUTHN_LEVEL_CALL:
  71. cout << "Authentication level is RPC_C_AUTHN_LEVEL_CALL." << endl;
  72. break;
  73. case RPC_C_AUTHN_LEVEL_PKT:
  74. cout << "Authentication level is RPC_C_AUTHN_LEVEL_PKT." << endl;
  75. break;
  76. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  77. cout << "Authentication level is RPC_C_AUTHN_LEVEL_PKT_INTEGRITY." << endl;
  78. break;
  79. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  80. cout << "Authentication level is RPC_C_AUTHN_LEVEL_PKT_PRIVACY." << endl;
  81. break;
  82. }
  83. switch(ImpLevel)
  84. {
  85. case RPC_C_IMP_LEVEL_DEFAULT:
  86. cout << "Impersonation level is RPC_C_IMP_LEVEL_DEFAULT." << endl;
  87. break;
  88. case RPC_C_IMP_LEVEL_ANONYMOUS:
  89. cout << "Impersonation level is RPC_C_IMP_LEVEL_ANONYMOUS." << endl;
  90. break;
  91. case RPC_C_IMP_LEVEL_IDENTIFY:
  92. cout << "Impersonation level is RPC_C_IMP_LEVEL_IDENTIFY." << endl;
  93. break;
  94. case RPC_C_IMP_LEVEL_IMPERSONATE:
  95. cout << "Impersonation level is RPC_C_IMP_LEVEL_IMPERSONATE." << endl;
  96. break;
  97. case RPC_C_IMP_LEVEL_DELEGATE:
  98. cout << "Impersonation level is RPC_C_IMP_LEVEL_DELEGATE." << endl;
  99. break;
  100. }
  101. // wprintf(L"The client identity user name is %s.n", ((SEC_WINNT_AUTH_IDENTITY_W*)pAuthInfo)->User);
  102. // wprintf(L"The client identity domain name is %s.n", ((SEC_WINNT_AUTH_IDENTITY_W*)pAuthInfo)->Domain);
  103. // wprintf(L"The client identity password is %s.n", ((SEC_WINNT_AUTH_IDENTITY_W*)pAuthInfo)->Password);
  104. if((Capabilities | EOAC_NONE) == 0)
  105. cout << "Capabilities include EOAC_NONE" << endl;
  106. if((Capabilities | EOAC_DEFAULT) == 0)
  107. cout << "Capabilities include EOAC_DEFAULT" << endl;
  108. if((Capabilities | EOAC_MUTUAL_AUTH) == 0)
  109. cout << "Capabilities include EOAC_MUTUAL_AUTH" << endl;
  110. if((Capabilities | EOAC_STATIC_CLOAKING) == 0)
  111. cout << "Capabilities include EOAC_STATIC_CLOAKING" << endl;
  112. if((Capabilities | EOAC_DYNAMIC_CLOAKING) == 0)
  113. cout << "Capabilities include EOAC_DYNAMIC_CLOAKING" << endl;
  114. if((Capabilities | EOAC_SECURE_REFS) == 0)
  115. cout << "Capabilities include EOAC_SECURE_REFS" << endl;
  116. if((Capabilities | EOAC_ACCESS_CONTROL) == 0)
  117. cout << "Capabilities include EOAC_ACCESS_CONTROL" << endl;
  118. if((Capabilities | EOAC_APPID) == 0)
  119. cout << "Capabilities include EOAC_APPID" << endl;
  120. if((Capabilities | EOAC_DISABLE_AAA) == 0)
  121. cout << "Capabilities include EOAC_DISABLE_AAA" << endl;
  122. // _getch();
  123. }
  124. void funcs()
  125. {
  126. DWORD AuthnSvc = 0;
  127. DWORD AuthzSvc = 0;
  128. DWORD ImpLevel = 0;
  129. OLECHAR* ServerPrincName;
  130. DWORD AuthnLevel = 0;
  131. RPC_AUTHZ_HANDLE Privs = 0;
  132. DWORD Capabilities = 0;
  133. HRESULT hr = CoQueryClientBlanket(&AuthnSvc, &AuthzSvc, &ServerPrincName, &AuthnLevel, NULL, &Privs, &Capabilities);
  134. if(FAILED(hr))
  135. cout << "CoQueryClientBlanket failed" << endl;
  136. switch(AuthnSvc)
  137. {
  138. case RPC_C_AUTHN_NONE:
  139. cout << "RPC_C_AUTHN_NONE ";
  140. break;
  141. case RPC_C_AUTHN_GSS_NEGOTIATE  :
  142. cout << "RPC_C_AUTHN_GSS_NEGOTIATE   ";
  143. break;
  144. case RPC_C_AUTHN_GSS_KERBEROS :
  145. cout << "RPC_C_AUTHN_GSS_KERBEROS  ";
  146. break;
  147. case RPC_C_AUTHN_WINNT:
  148. cout << "RPC_C_AUTHN_WINNT ";
  149. break;
  150. case RPC_C_AUTHN_DEFAULT:
  151. cout << "RPC_C_AUTHN_DEFAULT ";
  152. break;
  153. }
  154. switch(AuthzSvc)
  155. {
  156. case RPC_C_AUTHZ_NONE:
  157. cout << "RPC_C_AUTHZ_NONE ";
  158. break;
  159. case RPC_C_AUTHZ_NAME:
  160. cout << "RPC_C_AUTHZ_NAME ";
  161. break;
  162. case RPC_C_AUTHZ_DCE:
  163. cout << "RPC_C_AUTHZ_DCE ";
  164. break;
  165. }
  166. wprintf(L"ServerPrincName %s.n", ServerPrincName);
  167. CoTaskMemFree(ServerPrincName);
  168. switch(AuthnLevel)
  169. {
  170. case RPC_C_AUTHN_LEVEL_NONE:
  171. cout << "RPC_C_AUTHN_LEVEL_NONE ";
  172. break;
  173. case RPC_C_AUTHN_LEVEL_CONNECT:
  174. cout << "RPC_C_AUTHN_LEVEL_CONNECT ";
  175. break;
  176. case RPC_C_AUTHN_LEVEL_CALL:
  177. cout << "RPC_C_AUTHN_LEVEL_CALL ";
  178. break;
  179. case RPC_C_AUTHN_LEVEL_PKT:
  180. cout << "RPC_C_AUTHN_LEVEL_PKT ";
  181. break;
  182. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  183. cout << "RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ";
  184. break;
  185. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  186. cout << "RPC_C_AUTHN_LEVEL_PKT_PRIVACY ";
  187. break;
  188. }
  189. switch(ImpLevel)
  190. {
  191. case RPC_C_IMP_LEVEL_DEFAULT      :
  192. cout << "RPC_C_IMP_LEVEL_DEFAULT ";
  193. break;
  194. case RPC_C_IMP_LEVEL_ANONYMOUS    :
  195. cout << "RPC_C_IMP_LEVEL_ANONYMOUS ";
  196. break;
  197. case RPC_C_IMP_LEVEL_IDENTIFY     :
  198. cout << "RPC_C_IMP_LEVEL_IDENTIFY ";
  199. break;
  200. case RPC_C_IMP_LEVEL_IMPERSONATE  :
  201. cout << "RPC_C_IMP_LEVEL_IMPERSONATE ";
  202. break;
  203. case RPC_C_IMP_LEVEL_DELEGATE     :
  204. cout << "RPC_C_IMP_LEVEL_DELEGATE ";
  205. break;
  206. }
  207. cout << endl;
  208. wprintf(L"Privs %sn", Privs);
  209. if((Capabilities | EOAC_NONE) == 0)
  210. cout << "Capabilities include EOAC_NONE" << endl;
  211. if((Capabilities | EOAC_DEFAULT) == 0)
  212. cout << "Capabilities include EOAC_DEFAULT" << endl;
  213. if((Capabilities | EOAC_MUTUAL_AUTH) == 0)
  214. cout << "Capabilities include EOAC_MUTUAL_AUTH" << endl;
  215. if((Capabilities | EOAC_STATIC_CLOAKING) == 0)
  216. cout << "Capabilities include EOAC_STATIC_CLOAKING" << endl;
  217. if((Capabilities | EOAC_DYNAMIC_CLOAKING) == 0)
  218. cout << "Capabilities include EOAC_DYNAMIC_CLOAKING" << endl;
  219. if((Capabilities | EOAC_SECURE_REFS) == 0)
  220. cout << "Capabilities include EOAC_SECURE_REFS" << endl;
  221. if((Capabilities | EOAC_ACCESS_CONTROL) == 0)
  222. cout << "Capabilities include EOAC_ACCESS_CONTROL" << endl;
  223. if((Capabilities | EOAC_APPID) == 0)
  224. cout << "Capabilities include EOAC_APPID" << endl;
  225. if((Capabilities | EOAC_DISABLE_AAA) == 0)
  226. cout << "Capabilities include EOAC_DISABLE_AAA" << endl;
  227. }
  228. const IID IID_IAccessControl = {0xEEDD23E0,0x8410,0x11CE,{0xA1,0xC3,0x08,0x00,0x2B,0x2B,0x8D,0x8F}};
  229. long g_cComponents = 0;
  230. long g_cServerLocks = 0;
  231. HANDLE g_hEvent;
  232. class CInsideCOM : public ISum
  233. {
  234. public:
  235. // IUnknown
  236. ULONG __stdcall AddRef();
  237. ULONG __stdcall Release();
  238. HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
  239. // ISum
  240. HRESULT __stdcall Sum(int x, int y, int* retval);
  241. CInsideCOM() : m_cRef(1) { g_cComponents++; }
  242. ~CInsideCOM() { g_cComponents--; }
  243. private:
  244. ULONG m_cRef;
  245. };
  246. ULONG CInsideCOM::AddRef()
  247. {
  248. return ++m_cRef;
  249. }
  250. ULONG CInsideCOM::Release()
  251. {
  252. if(--m_cRef != 0)
  253. return m_cRef;
  254. SetEvent(g_hEvent);
  255. delete this;
  256. return 0;
  257. }
  258. HRESULT CInsideCOM::QueryInterface(REFIID riid, void** ppv)
  259. {
  260. if(riid == IID_IUnknown)
  261. *ppv = reinterpret_cast<IUnknown*>(this);
  262. else if(riid == IID_ISum)
  263. *ppv = (ISum*)this;
  264. else 
  265. {
  266. *ppv = NULL;
  267. return E_NOINTERFACE;
  268. }
  269. AddRef();
  270. return S_OK;
  271. }
  272. HRESULT CInsideCOM::Sum(int x, int y, int* retval)
  273. {
  274. ISum* pSum = 0;
  275. IUnknown* pUnknown = 0;
  276. HRESULT hr;
  277. COSERVERINFO ServerInfo;
  278. ServerInfo.dwReserved1 = 0;
  279. ServerInfo.pwszName = L"Guy-2031";
  280. ServerInfo.pAuthInfo = 0;
  281. ServerInfo.dwReserved2 = 0;
  282. MULTI_QI qi;
  283. qi.pIID = &IID_IUnknown;
  284. qi.pItf = NULL;
  285. qi.hr = 0;
  286. /*
  287. HANDLE handle = 0;
  288. handle = CreateFile("\\Guy-2031\C\test.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  289. if(handle != INVALID_HANDLE_VALUE)
  290. {
  291. char buffer[25];
  292. DWORD bytes_read = 0;
  293. ReadFile(handle, buffer, 25, &bytes_read, NULL);
  294. CloseHandle(handle);
  295. buffer[bytes_read] = 0;
  296. cout << buffer << " Read from file" << endl;
  297. }
  298. else
  299. cout << "access denied to file" << endl;
  300. */
  301. hr = CoImpersonateClient();
  302. if(FAILED(hr))
  303. printf("CoImpersonateClient failed %0xn", hr);
  304. hr = CoCreateInstanceEx(CLSID_InsideCOM_C, NULL, CLSCTX_REMOTE_SERVER, &ServerInfo, 1, &qi);
  305. pUnknown = qi.pItf;
  306. if(FAILED(hr))
  307. {
  308. if(hr == E_ACCESSDENIED)
  309. printf("CoCreateInstance FAILED hr = E_ACCESSDENIEDn", hr);
  310. else
  311. printf("CoCreateInstance FAILED hr = %0xn", hr);
  312. _getch();
  313. exit(0);
  314. }
  315. hr = CoSetProxyBlanket(pUnknown, RPC_C_AUTHN_GSS_KERBEROS, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, // L"GuysDomain\B", 
  316. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_DEFAULT, COLE_DEFAULT_AUTHINFO, EOAC_DEFAULT);
  317. display_proxy_info(pUnknown);
  318. cout << "Client: Calling QueryInterface() for ISum on " << pUnknown << endl;
  319. hr = pUnknown->QueryInterface(IID_ISum, (void**)&pSum);
  320. if(FAILED(hr))
  321. {
  322. printf("QueryInterface ISUm FAILED %0xn", hr);
  323. _getch();
  324. exit(0);
  325. }
  326. cout << "Client: Calling Release() for pUnknown" << endl;
  327. hr = pUnknown->Release();
  328. cout << "Client: pSum = " << pSum << endl;
  329. display_proxy_info(pSum);
  330. _getch();
  331. hr = CoSetProxyBlanket(pSum, RPC_C_AUTHN_GSS_KERBEROS, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, // L"GuysDomain\B", 
  332. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_DEFAULT, COLE_DEFAULT_AUTHINFO, EOAC_DEFAULT);
  333. if(FAILED(hr))
  334. printf("CoSetProxyBlanket 2 FAILED hr = %0xn", hr);
  335. display_proxy_info(pSum);
  336. _getch();
  337. int sum;
  338. hr = pSum->Sum(4, 9, &sum);
  339. if(SUCCEEDED(hr))
  340. cout << "Client: Calling Sum() return value is " << sum << endl;
  341. if(FAILED(hr))
  342. printf("Sum failed %0xn", hr);
  343. cout << "Client: Calling Release() for pSum" << endl;
  344. hr = pSum->Release();
  345. *retval = sum;
  346. CoRevertToSelf();
  347. return S_OK;
  348. }
  349. class CFactory : public IClassFactory
  350. {
  351. public:
  352. // IUnknown
  353. ULONG __stdcall AddRef();
  354. ULONG __stdcall Release();
  355. HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
  356. // IClassFactory
  357. HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv);
  358. HRESULT __stdcall LockServer(BOOL bLock);
  359. CFactory() : m_cRef(1) { }
  360. ~CFactory() { }
  361. private:
  362. ULONG m_cRef;
  363. };
  364. ULONG CFactory::AddRef()
  365. {
  366. return ++m_cRef;
  367. }
  368. ULONG CFactory::Release()
  369. {
  370. if(--m_cRef != 0)
  371. return m_cRef;
  372. delete this;
  373. return 0;
  374. }
  375. HRESULT CFactory::QueryInterface(REFIID riid, void** ppv)
  376. {
  377. if((riid == IID_IUnknown) || (riid == IID_IClassFactory))
  378. *ppv = (IClassFactory*)this;
  379. else
  380. {
  381. *ppv = NULL;
  382. return E_NOINTERFACE;
  383. }
  384. AddRef();
  385. return S_OK;
  386. }
  387. HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
  388. {
  389. if(pUnknownOuter != NULL)
  390. return CLASS_E_NOAGGREGATION;
  391. CInsideCOM *pInsideCOM = new CInsideCOM;
  392. cout << "Component: CFactory::CreateInstance() " << pInsideCOM << endl;
  393. if(pInsideCOM == NULL)
  394. return E_OUTOFMEMORY;
  395. // QueryInterface probably for IID_IUNKNOWN
  396. HRESULT hr = pInsideCOM->QueryInterface(riid, ppv);
  397. pInsideCOM->Release();
  398. return hr;
  399. }
  400. HRESULT CFactory::LockServer(BOOL bLock)
  401. {
  402. if(bLock)
  403. g_cServerLocks++;
  404. else
  405. g_cServerLocks--;
  406. return S_OK;
  407. }
  408. void RegisterComponent()
  409. {
  410. ITypeLib* pTypeLib;
  411. LoadTypeLibEx(L"Component B.exe", REGKIND_DEFAULT, &pTypeLib);
  412. pTypeLib->Release();
  413. RegisterServer("Component B.exe", CLSID_InsideCOM_B, "Inside COM+ Sample", "Component.InsideCOM_B", "Component.InsideCOM_B.1", NULL);
  414. }
  415. void CommandLineParameters(int argc, char** argv)
  416. {
  417. RegisterComponent();
  418. if(argc < 2)
  419. {
  420. cout << "No parameter, but registered anyway" << endl;
  421. exit(false);
  422. }
  423. char* szToken = strtok(argv[1], "-/"); 
  424. if(_stricmp(szToken, "RegServer") == 0)
  425. {
  426. RegisterComponent();
  427. cout << "RegServer" << endl;
  428. exit(true);
  429. }
  430. if(_stricmp(szToken, "UnregServer") == 0)
  431. {
  432. UnRegisterTypeLib(LIBID_Component, 1, 0, LANG_NEUTRAL, SYS_WIN32);
  433. UnregisterServer(CLSID_InsideCOM_B, "Component.InsideCOM_B", "Component.InsideCOM_B.1");
  434. cout << "UnregServer" << endl;
  435. exit(true);
  436. }
  437. if(_stricmp(szToken, "Embedding") != 0)
  438. {
  439. cout << "Invalid parameter" << endl;
  440. exit(false);
  441. }
  442. }
  443. void main(int argc, char** argv)
  444. {
  445. HRESULT hr;
  446. CommandLineParameters(argc, argv);
  447. cout << "Component: CoInitializeEx()" << endl;
  448. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  449. if(FAILED(hr))
  450. cout << "CoInitializeEx Failed" << endl;
  451. SEC_WINNT_AUTH_IDENTITY_W identity;
  452. identity.User = L"B";
  453. identity.UserLength = wcslen(L"B");
  454. identity.Domain = L"GuysDomain";
  455. identity.DomainLength = wcslen(L"GuysDomain");
  456. identity.Password = L"B";
  457. identity.PasswordLength = wcslen(L"B");
  458. identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  459. SOLE_AUTHENTICATION_INFO info;
  460. info.dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS;
  461. info.dwAuthzSvc = RPC_C_AUTHZ_NONE;
  462. info.pAuthInfo = &identity;
  463. SOLE_AUTHENTICATION_LIST list;
  464. list.cAuthInfo = 1;
  465. list.aAuthInfo = &info;
  466. SOLE_AUTHENTICATION_SERVICE service;
  467. service.dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS;
  468. service.dwAuthzSvc = RPC_C_AUTHZ_NONE;
  469. service.hr = 0;
  470. service.pPrincipalName = L"GuysDomain\B";
  471. hr = CoInitializeSecurity(0, 1, &service, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_DELEGATE, 
  472. NULL, EOAC_NONE, NULL);
  473. if(FAILED(hr))
  474. {
  475. printf("CoInitializeSecurity Failed = %0xn", hr);
  476. _getch();
  477. }
  478. printf("CoInitializeSecurity service.hr = %0xn", service.hr);
  479. IClassFactory *pClassFactory = new CFactory();
  480. cout << "Component: CoRegisterClassObject()" << endl;
  481. DWORD dwRegister;
  482. CoRegisterClassObject(CLSID_InsideCOM_B, pClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
  483. g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  484. WaitForSingleObject(g_hEvent, INFINITE);
  485. CoRevokeClassObject(dwRegister);
  486. pClassFactory->Release();
  487. CoUninitialize();
  488. cout << "By Bye" << endl;
  489. // _getch();
  490. }