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.

258 lines
6.0 KiB

  1. // blkdrv.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 blkdrv.idl by adding the following
  17. // files to the Outputs.
  18. // blkdrv_p.c
  19. // dlldata.c
  20. // To build a separate proxy/stub DLL,
  21. // run nmake -f blkdrvps.mk in the project directory.
  22. #include "stdafx.h"
  23. #include <commctrl.h>
  24. #include "resource.h"
  25. #include <initguid.h>
  26. #include "blkdrv.h"
  27. #include "dlldatax.h"
  28. #include "blkdrv_i.c"
  29. #include "Driver.h"
  30. #ifdef _MERGE_PROXYSTUB
  31. extern "C" HINSTANCE hProxyDll;
  32. #endif
  33. CMyModule _Module;
  34. BEGIN_OBJECT_MAP(ObjectMap)
  35. OBJECT_ENTRY(CLSID_BlockedDrivers, CBlockedDrivers)
  36. END_OBJECT_MAP()
  37. HMODULE hHotPlug;
  38. /////////////////////////////////////////////////////////////////////////////
  39. // DLL Entry Point
  40. extern "C"
  41. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  42. {
  43. lpReserved;
  44. hHotPlug = hInstance;
  45. #ifdef _MERGE_PROXYSTUB
  46. if (!PrxDllMain(hInstance, dwReason, lpReserved))
  47. return FALSE;
  48. #endif
  49. if (dwReason == DLL_PROCESS_ATTACH)
  50. {
  51. _Module.Init(ObjectMap, hInstance);
  52. DisableThreadLibraryCalls(hInstance);
  53. InitCommonControls();
  54. }
  55. else if (dwReason == DLL_PROCESS_DETACH)
  56. _Module.Term();
  57. return TRUE; // ok
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Used to determine whether the DLL can be unloaded by OLE
  61. STDAPI DllCanUnloadNow(void)
  62. {
  63. #ifdef _MERGE_PROXYSTUB
  64. if (PrxDllCanUnloadNow() != S_OK)
  65. return S_FALSE;
  66. #endif
  67. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. // Returns a class factory to create an object of the requested type
  71. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  72. {
  73. #ifdef _MERGE_PROXYSTUB
  74. if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
  75. return S_OK;
  76. #endif
  77. return _Module.GetClassObject(rclsid, riid, ppv);
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // DllRegisterServer - Adds entries to the system registry
  81. STDAPI DllRegisterServer(void)
  82. {
  83. #ifdef _MERGE_PROXYSTUB
  84. HRESULT hRes = PrxDllRegisterServer();
  85. if (FAILED(hRes))
  86. return hRes;
  87. #endif
  88. // registers object, typelib and all interfaces in typelib
  89. return _Module.RegisterServer(TRUE);
  90. }
  91. /////////////////////////////////////////////////////////////////////////////
  92. // DllUnregisterServer - Removes entries from the system registry
  93. STDAPI DllUnregisterServer(void)
  94. {
  95. #ifdef _MERGE_PROXYSTUB
  96. PrxDllUnregisterServer();
  97. #endif
  98. return _Module.UnregisterServer();
  99. }
  100. //
  101. // DCOM support, allow this DLL to also run as local server
  102. // once the server is running, it needs to cleanup after a short period of time
  103. //
  104. const DWORD dwTimeOut = 5000; // time for server to be idle before shutting down
  105. static void CALLBACK ModuleTimer(HWND /*hWnd*/,UINT /*uMsg*/,UINT /*idEvent*/,DWORD /*dwTime*/)
  106. {
  107. _Module.CheckShutdown();
  108. }
  109. LONG CMyModule::Unlock()
  110. {
  111. LONG l = CComModule::Unlock();
  112. if (bServer && (l <= (punkFact ? 1 : 0)))
  113. {
  114. //
  115. // DCOM server
  116. // as soon as lock count reaches 1 (punkFact), timer is reset
  117. // if timer times out and lock count is still 1
  118. // then we can kill the server
  119. //
  120. SetTimer(NULL,0,dwTimeOut, (TIMERPROC)ModuleTimer);
  121. }
  122. return l;
  123. }
  124. void CMyModule::KillServer()
  125. {
  126. if(bServer) {
  127. //
  128. // make it a server no longer
  129. //
  130. CoRevokeClassObject(dwROC);
  131. bServer = FALSE;
  132. }
  133. if(punkFact) {
  134. punkFact->Release();
  135. punkFact = NULL;
  136. }
  137. if(m_nLockCnt != 0) {
  138. DebugBreak();
  139. }
  140. }
  141. void CMyModule::CheckShutdown()
  142. {
  143. if(m_nLockCnt>(punkFact ? 1 : 0)) {
  144. //
  145. // module is still in use
  146. //
  147. return;
  148. }
  149. //
  150. // lock count stayed at zero for dwTimeOut ms
  151. //
  152. KillServer();
  153. PostMessage(NULL, WM_QUIT, 0, 0);
  154. }
  155. HRESULT CMyModule::InitServer(GUID & ClsId)
  156. {
  157. HRESULT hr;
  158. hr = DllGetClassObject(ClsId, IID_IClassFactory, (LPVOID*)&punkFact);
  159. if(FAILED(hr)) {
  160. return hr;
  161. }
  162. hr = CoRegisterClassObject(ClsId, punkFact, CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &dwROC);
  163. if(FAILED(hr)) {
  164. punkFact->Release();
  165. punkFact = NULL;
  166. return hr;
  167. }
  168. bServer = true;
  169. return S_OK;
  170. }
  171. void WINAPI CreateLocalServerW(HWND /*hwnd*/, HINSTANCE /*hAppInstance*/, LPWSTR pszCmdLine, int /*nCmdShow*/)
  172. {
  173. GUID ClsId;
  174. HRESULT hr;
  175. LPWSTR dup;
  176. LPWSTR p;
  177. size_t len;
  178. MSG msg;
  179. hr = CoInitialize(NULL);
  180. if(FAILED(hr)) {
  181. return;
  182. }
  183. //
  184. // pszCmdLine = the class GUID we want factory for
  185. //
  186. p = wcschr(pszCmdLine,'{');
  187. if(!p) {
  188. goto final;
  189. }
  190. pszCmdLine = p;
  191. p = wcschr(pszCmdLine,'}');
  192. if(!p) {
  193. goto final;
  194. }
  195. len = p-pszCmdLine+1;
  196. dup = new WCHAR[len+1];
  197. if(!dup) {
  198. goto final;
  199. }
  200. wcsncpy(dup,pszCmdLine,len+1);
  201. dup[len] = '\0';
  202. hr = CLSIDFromString(dup,&ClsId);
  203. delete [] dup;
  204. if(FAILED(hr)) {
  205. goto final;
  206. }
  207. hr = _Module.InitServer(ClsId);
  208. if(FAILED(hr)) {
  209. goto final;
  210. }
  211. //
  212. // now go into dispatch loop until we get a quit message
  213. //
  214. while (GetMessage(&msg, NULL, 0, 0))
  215. {
  216. TranslateMessage(&msg);
  217. DispatchMessage(&msg);
  218. }
  219. _Module.KillServer();
  220. final:
  221. CoUninitialize();
  222. }