Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
6.7 KiB

  1. // DevCon2.cpp : Implementation of DLL Exports.
  2. // Note: Proxy/Stub Information
  3. // To merge the proxy/stub code into the object DLL, add the file
  4. // dlldatax.c to the project. Make sure precompiled headers
  5. // are turned off for this file, and add _MERGE_PROXYSTUB to the
  6. // defines for the project.
  7. //
  8. // If you are not running WinNT4.0 or Win95 with DCOM, then you
  9. // need to remove the following define from dlldatax.c
  10. // #define _WIN32_WINNT 0x0400
  11. //
  12. // Further, if you are running MIDL without /Oicf switch, you also
  13. // need to remove the following define from dlldatax.c.
  14. // #define USE_STUBLESS_PROXY
  15. //
  16. // Modify the custom build rule for DevCon2.idl by adding the following
  17. // files to the Outputs.
  18. // DevCon2_p.c
  19. // dlldata.c
  20. // To build a separate proxy/stub DLL,
  21. // run nmake -f DevCon2ps.mk in the project directory.
  22. #include "stdafx.h"
  23. #include "resource.h"
  24. #include <initguid.h>
  25. #include "DevCon2.h"
  26. #include "dlldatax.h"
  27. #include "DevCon2_i.c"
  28. #include "DeviceConsole.h"
  29. #include "Devices.h"
  30. #include "xStrings.h"
  31. #include "SetupClasses.h"
  32. #include "DeviceIcon.h"
  33. #ifdef _MERGE_PROXYSTUB
  34. extern "C" HINSTANCE hProxyDll;
  35. #endif
  36. CMyModule _Module;
  37. BEGIN_OBJECT_MAP(ObjectMap)
  38. OBJECT_ENTRY(CLSID_DeviceConsole, CDeviceConsole)
  39. OBJECT_ENTRY(CLSID_Devices, CDevices)
  40. OBJECT_ENTRY(CLSID_Strings, CStrings)
  41. OBJECT_ENTRY(CLSID_SetupClasses, CSetupClasses)
  42. OBJECT_ENTRY(CLSID_DeviceIcon, CDeviceIcon)
  43. END_OBJECT_MAP()
  44. /////////////////////////////////////////////////////////////////////////////
  45. // DLL Entry Point
  46. extern "C"
  47. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  48. {
  49. lpReserved;
  50. #ifdef _MERGE_PROXYSTUB
  51. if (!PrxDllMain(hInstance, dwReason, lpReserved))
  52. return FALSE;
  53. #endif
  54. if (dwReason == DLL_PROCESS_ATTACH)
  55. {
  56. _Module.Init(ObjectMap, hInstance, &LIBID_DEVCON2Lib);
  57. DisableThreadLibraryCalls(hInstance);
  58. }
  59. else if (dwReason == DLL_PROCESS_DETACH)
  60. _Module.Term();
  61. return TRUE; // ok
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Used to determine whether the DLL can be unloaded by OLE
  65. STDAPI DllCanUnloadNow(void)
  66. {
  67. #ifdef _MERGE_PROXYSTUB
  68. if (PrxDllCanUnloadNow() != S_OK)
  69. return S_FALSE;
  70. #endif
  71. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  72. }
  73. /////////////////////////////////////////////////////////////////////////////
  74. // Returns a class factory to create an object of the requested type
  75. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  76. {
  77. #ifdef _MERGE_PROXYSTUB
  78. if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
  79. return S_OK;
  80. #endif
  81. return _Module.GetClassObject(rclsid, riid, ppv);
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. // DllRegisterServer - Adds entries to the system registry
  85. STDAPI DllRegisterServer(void)
  86. {
  87. #ifdef _MERGE_PROXYSTUB
  88. HRESULT hRes = PrxDllRegisterServer();
  89. if (FAILED(hRes))
  90. return hRes;
  91. #endif
  92. //
  93. // DCOM support - App registration via IDR_DEVCON2
  94. //
  95. _Module.UpdateRegistryFromResource(IDR_DEVCON2, TRUE);
  96. // registers object, typelib and all interfaces in typelib
  97. return _Module.RegisterServer(TRUE);
  98. }
  99. /////////////////////////////////////////////////////////////////////////////
  100. // DllUnregisterServer - Removes entries from the system registry
  101. STDAPI DllUnregisterServer(void)
  102. {
  103. #ifdef _MERGE_PROXYSTUB
  104. PrxDllUnregisterServer();
  105. #endif
  106. //
  107. // DCOM support - App cleanup via IDR_DEVCON2
  108. //
  109. _Module.UpdateRegistryFromResource(IDR_DEVCON2, FALSE);
  110. return _Module.UnregisterServer(TRUE);
  111. }
  112. //
  113. // DCOM support, allow this DLL to also run as local server
  114. // once the server is running, it needs to cleanup after a short period of time
  115. //
  116. const DWORD dwTimeOut = 5000; // time for server to be idle before shutting down
  117. static void CALLBACK ModuleTimer(HWND /*hWnd*/,UINT /*uMsg*/,UINT_PTR /*idEvent*/,DWORD /*dwTime*/)
  118. {
  119. _Module.CheckShutdown();
  120. }
  121. LONG CMyModule::Unlock()
  122. {
  123. LONG l = CComModule::Unlock();
  124. //ATLTRACE("Unlock = %u\n",l);
  125. if (bServer && (l <= (punkFact ? 1 : 0)))
  126. {
  127. //
  128. // DCOM server
  129. // as soon as lock count reaches 1 (punkFact), timer is reset
  130. // if timer times out and lock count is still 1
  131. // then we can kill the server
  132. //
  133. SetTimer(NULL,0,dwTimeOut,ModuleTimer);
  134. }
  135. return l;
  136. }
  137. void CMyModule::KillServer()
  138. {
  139. if(bServer) {
  140. //
  141. // make it a server no longer
  142. //
  143. CoRevokeClassObject(dwROC);
  144. bServer = FALSE;
  145. }
  146. if(punkFact) {
  147. punkFact->Release();
  148. punkFact = NULL;
  149. }
  150. if(m_nLockCnt != 0) {
  151. DebugBreak();
  152. }
  153. }
  154. void CMyModule::CheckShutdown()
  155. {
  156. if(m_nLockCnt>(punkFact ? 1 : 0)) {
  157. //
  158. // module is still in use
  159. //
  160. return;
  161. }
  162. //
  163. // lock count stayed at zero for dwTimeOut ms
  164. //
  165. KillServer();
  166. PostMessage(NULL, WM_QUIT, 0, 0);
  167. }
  168. HRESULT CMyModule::InitServer(GUID & ClsId)
  169. {
  170. HRESULT hr;
  171. hr = DllGetClassObject(ClsId, IID_IClassFactory, (LPVOID*)&punkFact);
  172. if(FAILED(hr)) {
  173. return hr;
  174. }
  175. hr = CoRegisterClassObject(ClsId, punkFact, CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &dwROC);
  176. if(FAILED(hr)) {
  177. punkFact->Release();
  178. punkFact = NULL;
  179. return hr;
  180. }
  181. bServer = true;
  182. return S_OK;
  183. }
  184. void WINAPI CreateLocalServerW(HWND /*hwnd*/, HINSTANCE /*hAppInstance*/, LPWSTR pszCmdLine, int /*nCmdShow*/)
  185. {
  186. GUID ClsId;
  187. HRESULT hr;
  188. LPWSTR dup;
  189. LPWSTR p;
  190. size_t len;
  191. MSG msg;
  192. hr = CoInitialize(NULL);
  193. if(FAILED(hr)) {
  194. return;
  195. }
  196. //
  197. // pszCmdLine = the class GUID we want factory for
  198. //
  199. p = wcschr(pszCmdLine,'{');
  200. if(!p) {
  201. goto final;
  202. }
  203. pszCmdLine = p;
  204. p = wcschr(pszCmdLine,'}');
  205. if(!p) {
  206. goto final;
  207. }
  208. len = p-pszCmdLine+1;
  209. dup = new WCHAR[len+1];
  210. if(!dup) {
  211. goto final;
  212. }
  213. wcsncpy(dup,pszCmdLine,len+1);
  214. dup[len] = '\0';
  215. hr = CLSIDFromString(dup,&ClsId);
  216. delete [] dup;
  217. if(FAILED(hr)) {
  218. goto final;
  219. }
  220. hr = _Module.InitServer(ClsId);
  221. if(FAILED(hr)) {
  222. goto final;
  223. }
  224. //
  225. // now go into dispatch loop until we get a quit message
  226. //
  227. while (GetMessage(&msg, NULL, 0, 0))
  228. {
  229. TranslateMessage(&msg);
  230. DispatchMessage(&msg);
  231. }
  232. _Module.KillServer();
  233. final:
  234. CoUninitialize();
  235. }
  236. #ifdef _M_IA64
  237. //$WIN64: Don't know why _WndProcThunkProc isn't defined
  238. extern "C" LRESULT CALLBACK _WndProcThunkProc(HWND, UINT, WPARAM, LPARAM )
  239. {
  240. return 0;
  241. }
  242. #endif