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

Windows编程

开发平台:

Visual C++

  1. // component.cpp
  2. #define _WIN32_DCOM
  3. #include <windows.h>
  4. #include <iostream.h>
  5. #include <conio.h>
  6. #include "Componentcomponent.h"
  7. #include "registry.h"
  8. CLSID CLSID_InsideCOMProxy = {0x10000004,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};
  9. long g_cComponents = 0;
  10. long g_cServerLocks = 0;
  11. HANDLE hFileMap, hStubEvent, hProxyEvent;
  12. struct SumTransmit
  13. {
  14. int x;
  15. int y;
  16. int sum;
  17. };
  18. class CInsideCOM : public ISum, public IMarshal
  19. {
  20. public:
  21. // IUnknown
  22. ULONG __stdcall AddRef();
  23. ULONG __stdcall Release();
  24. HRESULT __stdcall QueryInterface(REFIID riid, void **ppv);
  25. // IMarshal
  26. HRESULT __stdcall GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags, CLSID* pClsid);
  27. HRESULT __stdcall GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags, DWORD* pSize);
  28. HRESULT __stdcall MarshalInterface(IStream* pStream, REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags);
  29. HRESULT __stdcall DisconnectObject(DWORD dwReserved);
  30. HRESULT __stdcall UnmarshalInterface(IStream* pStream, REFIID riid, void** ppv);
  31. HRESULT __stdcall ReleaseMarshalData(IStream* pStream);
  32. // ISum
  33. HRESULT __stdcall Sum(int x, int y, int *sum);
  34. CInsideCOM() : m_cRef(1) { g_cComponents++; }
  35. ~CInsideCOM() { cout << "Component: CInsideCOM::~CInsideCOM()" << endl, g_cComponents--; }
  36. private:
  37. long m_cRef;
  38. };
  39. CInsideCOM *g_pInsideCOM;
  40. HRESULT CInsideCOM::GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags, CLSID* pClsid)
  41. {
  42. // We only handle the local marshaling case
  43. // Under Windows NT/2000, MSHCTX_DIFFERENTMACHINE is returned in somes cases even when the 
  44. // connection is local.  The solution is to either comment out the if statement 
  45. // below or use the "CoGetClassObject client.cpp" file which uses CoGetClassObject
  46. // instead of CoCreateInstance.  This ensures that the correct MSHCTX_ flag is used.
  47. // This happens because when the client calls CoCreateInstance(), the SCM on the server 
  48. // is doing the CreateInstance and the SCM has in the past had no way to tell the
  49. // server whether the client is in a different machine so the worst case
  50. // assumption is required.
  51. // This may have been corrected by the time you read this
  52. if(dwDestContext == MSHCTX_DIFFERENTMACHINE)
  53. {
  54. IMarshal* pMarshal;
  55. CoGetStandardMarshal(riid, (ISum*)pv, dwDestContext, pvDestContext, dwFlags, &pMarshal);
  56. HRESULT hr = pMarshal->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, dwFlags, pClsid);
  57. pMarshal->Release();
  58. return hr;
  59. }
  60. *pClsid = CLSID_InsideCOMProxy;
  61. return S_OK;
  62. }
  63. HRESULT CInsideCOM::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags, DWORD* pSize)
  64. {
  65. // We only handle the local marshaling case
  66. // Under NT/2000, MSHCTX_DIFFERENTMACHINE is returned in somes cases even when the 
  67. // connection is local.  The solution is to either comment out the if statement 
  68. // below or use the "CoGetClassObject client.cpp" file which uses CoGetClassObject
  69. // instead of CoCreateInstance.  This ensures that the correct MSHCTX_ flag is used.
  70. // This happens because when the client calls CoCreateInstance(), the SCM on the server 
  71. // is doing the CreateInstance and the SCM has in the past had no way to tell the
  72. // server whether the client is in a different machine so the worst case
  73. // assumption is required.
  74. // This may have been corrected by the time you read this
  75. if(dwDestContext == MSHCTX_DIFFERENTMACHINE)
  76. {
  77. IMarshal* pMarshal;
  78. CoGetStandardMarshal(riid, (ISum*)pv, dwDestContext, pvDestContext, dwFlags, &pMarshal);
  79. HRESULT hr = pMarshal->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, dwFlags, pSize);
  80. pMarshal->Release();
  81. return hr;
  82. }
  83.   *pSize = 255;
  84. return S_OK;
  85. }
  86. HRESULT CInsideCOM::MarshalInterface(IStream* pStream, REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD dwFlags)
  87. {
  88. // We only handle the local marshaling case
  89. // Under NT/2000, MSHCTX_DIFFERENTMACHINE is returned in somes cases even when the 
  90. // connection is local.  The solution is to either comment out the if statement 
  91. // below or use the "CoGetClassObject client.cpp" file which uses CoGetClassObject
  92. // instead of CoCreateInstance.  This ensures that the correct MSHCTX_ flag is used.
  93. // This happens because when the client calls CoCreateInstance(), the SCM on the server 
  94. // is doing the CreateInstance and the SCM has in the past had no way to tell the
  95. // server whether the client is in a different machine so the worst case
  96. // assumption is required.
  97. // This may have been corrected by the time you read this
  98. if(dwDestContext == MSHCTX_DIFFERENTMACHINE)
  99. {
  100. IMarshal* pMarshal;
  101. CoGetStandardMarshal(riid, (ISum*)pv, dwDestContext, pvDestContext, dwFlags, &pMarshal);
  102. HRESULT hr = pMarshal->MarshalInterface(pStream, riid, pv, dwDestContext, pvDestContext, dwFlags);
  103. pMarshal->Release();
  104. return hr;
  105. }
  106. ULONG num_written;
  107. char* szFileMapName = "FileMap";
  108. char* szStubEventName = "StubEvent";
  109. char* szProxyEventName = "ProxyEvent";
  110. char buffer_to_write[255];
  111. AddRef();
  112. hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 255, szFileMapName);
  113. hStubEvent = CreateEvent(NULL, FALSE, FALSE, szStubEventName);
  114. hProxyEvent = CreateEvent(NULL, FALSE, FALSE, szProxyEventName);
  115. strcpy(buffer_to_write, szFileMapName);
  116. strcat(buffer_to_write, ",");
  117. strcat(buffer_to_write, szStubEventName);
  118. strcat(buffer_to_write, ",");
  119. strcat(buffer_to_write, szProxyEventName);
  120. cout << "Component: CInsideCOM::MarshalInterface() = " << buffer_to_write << endl;
  121. return pStream->Write(buffer_to_write, strlen(buffer_to_write)+1, &num_written);
  122. }
  123. HRESULT CInsideCOM::DisconnectObject(DWORD dwReserved)
  124.     {
  125. cout << "DisconnectObject" << endl;
  126. CloseHandle(hFileMap);
  127. CloseHandle(hStubEvent);
  128. CloseHandle(hProxyEvent);
  129.     return E_NOTIMPL;
  130.     }
  131. HRESULT CInsideCOM::ReleaseMarshalData(IStream* pStream)
  132.     {
  133. cout << "ReleaseMarshalData" << endl;
  134.     return S_OK;
  135.     }
  136. HRESULT CInsideCOM::UnmarshalInterface(IStream* pStream, REFIID riid, void** ppv)
  137.     {
  138. cout << "UnmarshalInterface" << endl;
  139.     return E_UNEXPECTED;
  140.     }
  141. ULONG CInsideCOM::AddRef()
  142. {
  143. cout << "Component: CInsideCOM::AddRef() m_cRef = " << m_cRef + 1 << endl;
  144. return m_cRef++;
  145. }
  146. ULONG CInsideCOM::Release()
  147. {
  148. cout << "Component: CInsideCOM::Release() m_cRef = " << m_cRef - 1 << endl;
  149. if(--m_cRef != 0)
  150. return m_cRef;
  151. delete this;
  152. return 0;
  153. }
  154. HRESULT CInsideCOM::QueryInterface(REFIID riid, void **ppv)
  155. {
  156. if(riid == IID_IUnknown)
  157. {
  158. cout << "Component: CInsideCOM::QueryInterface() for IUnknown" << endl;
  159. *ppv = (ISum*)this;
  160. }
  161. else if(riid == IID_IMarshal)
  162. {
  163. cout << "Component: CInsideCOM::QueryInterface for IMarshal" << endl;
  164. *ppv = (IMarshal*)this;
  165. }
  166. else if(riid == IID_ISum)
  167. {
  168. cout << "Component: CInsideCOM::QueryInterface() for ISum" << endl;
  169. *ppv = (ISum*)this;
  170. }
  171. else
  172. {
  173. *ppv = NULL;
  174. return E_NOINTERFACE;
  175. }
  176. AddRef();
  177. return S_OK;
  178. }
  179. HRESULT CInsideCOM::Sum(int x, int y, int *sum)
  180. {
  181. cout << "Component: CInsideCOM::Sum() " << x << " + " << y << " = " << x + y << endl;
  182. *sum = x + y;
  183. return S_OK;
  184. }
  185. class CFactory : public IClassFactory
  186. {
  187. public:
  188. // IUnknown
  189. ULONG __stdcall AddRef();
  190. ULONG __stdcall Release();
  191. HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
  192. // IClassFactory
  193. HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv);
  194. HRESULT __stdcall LockServer(BOOL bLock);
  195. CFactory() : m_cRef(1) { }
  196. ~CFactory() { cout << "Component: CFactory::~CFactory()" << endl; }
  197. private:
  198. long m_cRef;
  199. };
  200. ULONG CFactory::AddRef()
  201. {
  202. cout << "Component: CFactory::AddRef() m_cRef = " << m_cRef + 1 << endl;
  203. return m_cRef++;
  204. }
  205. ULONG CFactory::Release()
  206. {
  207. cout << "Component: CFactory::Release() m_cRef = " << m_cRef - 1 << endl;
  208. if(--m_cRef != 0)
  209. return m_cRef;
  210. delete this;
  211. return 0;
  212. }
  213. HRESULT CFactory::QueryInterface(REFIID riid, void **ppv)
  214. {
  215. if((riid == IID_IUnknown) || (riid == IID_IClassFactory))
  216. {
  217. cout << "Component: CFactory::QueryInteface() for IUnknown or IClassFactory " << this << endl;
  218. *ppv = (IClassFactory *)this;
  219. }
  220. else 
  221. {
  222. *ppv = NULL;
  223. return E_NOINTERFACE;
  224. }
  225. AddRef();
  226. return S_OK;
  227. }
  228. HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void **ppv)
  229. {
  230. if(pUnknownOuter != NULL)
  231. return CLASS_E_NOAGGREGATION;
  232. CInsideCOM *pInsideCOM = new CInsideCOM;
  233. g_pInsideCOM = pInsideCOM;
  234. cout << "Component: CFactory::CreateInstance() " << pInsideCOM << endl;
  235. if(pInsideCOM == NULL)
  236. return E_OUTOFMEMORY;
  237. HRESULT hr = pInsideCOM->QueryInterface(riid, ppv);
  238. pInsideCOM->Release();
  239. return hr;
  240. }
  241. HRESULT CFactory::LockServer(BOOL bLock)
  242. {
  243. if(bLock)
  244. g_cServerLocks++;
  245. else
  246. g_cServerLocks--;
  247. return S_OK;
  248. }
  249. void RegisterComponent()
  250. {
  251. ITypeLib* pTypeLib;
  252. HRESULT hr = LoadTypeLibEx(L"component.exe", REGKIND_DEFAULT, &pTypeLib);
  253. pTypeLib->Release();
  254. RegisterServer("component.exe", CLSID_InsideCOM, "Inside COM Sample", "Component.InsideCOM", "Component.InsideCOM.1", NULL);
  255. }
  256. void CommandLineParameters(int argc, char** argv)
  257. {
  258. RegisterComponent();
  259. if(argc < 2)
  260. {
  261. cout << "No parameter, but registered anyway..." << endl;
  262. exit(false);
  263. }
  264. char* szToken = strtok(argv[1], "-/"); 
  265. if(_stricmp(szToken, "RegServer") == 0)
  266. {
  267. RegisterComponent();
  268. cout << "RegServer" << endl;
  269. exit(true);
  270. }
  271. if(_stricmp(szToken, "UnregServer") == 0)
  272. {
  273. UnRegisterTypeLib(LIBID_Component, 1, 0, LANG_NEUTRAL, SYS_WIN32);
  274. UnregisterServer(CLSID_InsideCOM, "Component.InsideCOM", "Component.InsideCOM.1");
  275. cout << "UnregServer" << endl;
  276. exit(true);
  277. }
  278. if(_stricmp(szToken, "Embedding") != 0)
  279. {
  280. cout << "Invalid parameter" << endl;
  281. exit(false);
  282. }
  283. }
  284. void TalkToProxy()
  285. {
  286. while(hStubEvent == 0)
  287. Sleep(0);
  288. void* pMem = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
  289. short method_id = 0;
  290. while(true)
  291. {
  292. WaitForSingleObject(hStubEvent, INFINITE);
  293. memcpy(&method_id, pMem, sizeof(short));
  294. switch(method_id) // What method did the proxy call?
  295. {
  296. case 1: // IUnknown::Release
  297. cout << "Component: Proxy request to call ISum::Release()" << endl;
  298. CoDisconnectObject(reinterpret_cast<IUnknown*>(g_pInsideCOM), 0);
  299. g_pInsideCOM->Release();
  300. return;
  301. case 2: // ISum::Sum
  302. SumTransmit s;
  303. memcpy(&s, (short*)pMem+1, sizeof(SumTransmit));
  304. cout << "Component: Proxy request to call ISum::Sum()" << endl;
  305. g_pInsideCOM->Sum(s.x, s.y, &s.sum);
  306. memcpy(pMem, &s, sizeof(s));
  307. SetEvent(hProxyEvent);
  308. }
  309. }
  310. }
  311. void main(int argc, char** argv)
  312. {
  313. CoInitializeEx(NULL, COINIT_MULTITHREADED);
  314. CommandLineParameters(argc, argv);
  315. DWORD dwRegister;
  316. IClassFactory *pIFactory = new CFactory();
  317. CoRegisterClassObject(CLSID_InsideCOM, pIFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
  318. TalkToProxy();
  319. CoRevokeClassObject(dwRegister);
  320. pIFactory->Release();
  321. CoUninitialize();
  322. _getch();
  323. }