Leaked source code of windows server 2003
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.

417 lines
12 KiB

  1. /****************************************************************************
  2. MODULE: SW_CFact.CPP
  3. Tab Settings: 5 9
  4. Copyright 1995, 1996, Microsoft Corporation, All Rights Reserved.
  5. PURPOSE: Class Object structured in a DLL server.
  6. FUNCTIONS:
  7. Author(s): Name:
  8. ---------- ----------------
  9. MEA Manolito E. Adan
  10. Revision History:
  11. -----------------
  12. Version Date Author Comments
  13. ------- ------ ----- -------------------------------------------
  14. 1.0 06-Feb-97 MEA original, Based on SWForce
  15. 23-Feb-97 MEA Modified for DirectInput FF Device Driver
  16. ****************************************************************************/
  17. #include "SW_CFact.hpp"
  18. #include "SWD_Guid.hpp"
  19. #include <olectl.h> // Self Reg errors
  20. // Needed for auto registration
  21. #include "Registry.h"
  22. #include "CritSec.h"
  23. // Define CriticalSection object for everyone
  24. CriticalSection g_CriticalSection;
  25. //
  26. // Global Data
  27. //
  28. ULONG g_cObj=0; //Count number of objects and number of locks.
  29. ULONG g_cLock=0;
  30. HINSTANCE g_MyInstance = NULL;
  31. //
  32. // External Functions
  33. //
  34. //
  35. // Internal Function Prototypes
  36. //
  37. //
  38. // External Data
  39. //
  40. #ifdef _DEBUG
  41. extern char g_cMsg[160];
  42. #endif
  43. #define BUFSIZE 80
  44. /*
  45. * DllMain
  46. *
  47. * Purpose:
  48. * Entry point provides the proper structure for each environment.
  49. */
  50. BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
  51. {
  52. switch (ulReason) {
  53. case DLL_PROCESS_ATTACH: {
  54. //
  55. // DLL is attaching to the address space of the current process.
  56. //
  57. g_MyInstance = hInstance;
  58. #ifdef _DEBUG
  59. ::OutputDebugString("sw_effct.dll: DLL_PROCESS_ATTACH\r\n");
  60. #endif
  61. return TRUE;
  62. }
  63. case DLL_THREAD_ATTACH:
  64. //
  65. // A new thread is being created in the current process.
  66. //
  67. #ifdef _DEBUG
  68. OutputDebugString("sw_effct.dll: DLL_THREAD_ATTACH\r\n");
  69. #endif
  70. break;
  71. case DLL_THREAD_DETACH:
  72. //
  73. // A thread is exiting cleanly.
  74. //
  75. #ifdef _DEBUG
  76. OutputDebugString("sw_effct.dll: DLL_THREAD_DETACH\r\n");
  77. #endif
  78. break;
  79. case DLL_PROCESS_DETACH:
  80. //
  81. // The calling process is detaching the DLL from its address space.
  82. //
  83. #ifdef _DEBUG
  84. OutputDebugString("sw_effct.dll: DLL_PROCESS_DETACH\r\n");
  85. #endif
  86. break;
  87. }
  88. return(TRUE);
  89. }
  90. // ----------------------------------------------------------------------------
  91. // Function: DllRegisterServer
  92. //
  93. // Purpose: Auto-magically puts default entries into registry
  94. //
  95. // Parameters: NONE
  96. //
  97. // Returns: HRESULT - S_OK on success.
  98. // ----------------------------------------------------------------------------
  99. STDAPI DllRegisterServer(void)
  100. {
  101. // Register CLSID for DIEffectDriver
  102. // -- Get HKEY_CLASSES_ROOT\CLSID key
  103. RegistryKey classesRootKey(HKEY_CLASSES_ROOT);
  104. RegistryKey clsidKey = classesRootKey.OpenSubkey(TEXT("CLSID"), KEY_READ | KEY_WRITE);
  105. if (clsidKey == c_InvalidKey) {
  106. return E_UNEXPECTED; // No CLSID key????
  107. }
  108. // -- If the key is there get it (else Create)
  109. RegistryKey driverKey = clsidKey.OpenCreateSubkey(CLSID_DirectInputEffectDriver_String);
  110. // -- Set value (if valid key)
  111. if (driverKey != c_InvalidKey) {
  112. driverKey.SetValue(NULL, (BYTE*)DRIVER_OBJECT_NAME, sizeof(DRIVER_OBJECT_NAME)/sizeof(TCHAR), REG_SZ);
  113. RegistryKey inproc32Key = driverKey.OpenCreateSubkey(TEXT("InProcServer32"));
  114. if (inproc32Key != c_InvalidKey) {
  115. TCHAR fileName[MAX_PATH];
  116. DWORD nameSize = ::GetModuleFileName(g_MyInstance, fileName, MAX_PATH);
  117. if (nameSize > 0) {
  118. fileName[nameSize] = '\0';
  119. inproc32Key.SetValue(NULL, (BYTE*)fileName, sizeof(fileName)/sizeof(TCHAR), REG_SZ);
  120. }
  121. inproc32Key.SetValue(TEXT("ThreadingModel"), (BYTE*)THREADING_MODEL_STRING, sizeof(THREADING_MODEL_STRING)/sizeof(TCHAR), REG_SZ);
  122. }
  123. // NotInsertable ""
  124. RegistryKey notInsertableKey = driverKey.OpenCreateSubkey(TEXT("NotInsertable"));
  125. if (notInsertableKey != c_InvalidKey) {
  126. notInsertableKey.SetValue(NULL, (BYTE*)TEXT(""), sizeof(TEXT(""))/sizeof(TCHAR), REG_SZ);
  127. }
  128. // ProgID "Sidewinder ForceFeedback blah blah2.0"
  129. RegistryKey progIDKey = driverKey.OpenCreateSubkey(TEXT("ProgID"));
  130. if (progIDKey != c_InvalidKey) {
  131. progIDKey.SetValue(NULL, (BYTE*)PROGID_NAME, sizeof(PROGID_NAME)/sizeof(TCHAR), REG_SZ);
  132. }
  133. // VersionIndpendentProgID "Sidewinder ForceFeedback blah blah"
  134. RegistryKey progIDVersionlessKey = driverKey.OpenCreateSubkey(TEXT("VersionIndpendentProgID"));
  135. if (progIDVersionlessKey != c_InvalidKey) {
  136. progIDVersionlessKey.SetValue(NULL, (BYTE*)PROGID_NOVERSION_NAME, sizeof(PROGID_NOVERSION_NAME)/sizeof(TCHAR), REG_SZ);
  137. }
  138. } else {
  139. return SELFREG_E_CLASS;
  140. }
  141. // Made it here valid driver key
  142. return S_OK;
  143. }
  144. // ----------------------------------------------------------------------------
  145. // Function: DllUnregisterServer
  146. //
  147. // Purpose: Auto-magically removed default entries from registry
  148. //
  149. // Parameters: NONE
  150. //
  151. // Returns: HRESULT - S_OK on success.
  152. // ----------------------------------------------------------------------------
  153. STDAPI DllUnregisterServer(void)
  154. {
  155. HRESULT hres = S_OK;
  156. // Unregister CLSID for DIEffectDriver
  157. // -- Get HKEY_CLASSES_ROOT\CLSID key
  158. RegistryKey classesRootKey(HKEY_CLASSES_ROOT);
  159. RegistryKey clsidKey = classesRootKey.OpenSubkey(TEXT("CLSID"), KEY_READ | KEY_WRITE);
  160. if (clsidKey == c_InvalidKey) {
  161. return E_UNEXPECTED; // No CLSID key????
  162. }
  163. // driverKey Destructor will close the key
  164. // -- If the key is there get it, else we don't have to remove it
  165. RegistryKey driverKey = clsidKey.OpenSubkey(CLSID_DirectInputEffectDriver_String);
  166. if (driverKey != c_InvalidKey) { // Is it there
  167. driverKey.RemoveSubkey(TEXT("InProcServer32"));
  168. driverKey.RemoveSubkey(TEXT("NotInsertable"));
  169. driverKey.RemoveSubkey(TEXT("ProgID"));
  170. driverKey.RemoveSubkey(TEXT("VersionIndpendentProgID"));
  171. if (driverKey.GetNumSubkeys() == 0) {
  172. hres = clsidKey.RemoveSubkey(CLSID_DirectInputEffectDriver_String);
  173. }
  174. } else {
  175. // Key is not there, count removal as a success
  176. }
  177. return hres;
  178. }
  179. // ----------------------------------------------------------------------------
  180. // Function: DllGetClassObject
  181. //
  182. // Purpose: Provides an IClassFactory for a given CLSID that this DLL is
  183. // registered to support. This DLL is placed under the CLSID
  184. // in the registration database as the InProcServer.
  185. //
  186. // Parameters: REFCLSID clsID - REFCLSID that identifies the class factory
  187. // desired. Since this parameter is passed this
  188. // DLL can handle any number of objects simply
  189. // by returning different class factories here
  190. // for different CLSIDs.
  191. //
  192. // REFIID riid - REFIID specifying the interface the caller
  193. // wants on the class object, usually
  194. // IID_ClassFactory.
  195. //
  196. // PPVOID ppv - PPVOID in which to return the interface ptr.
  197. //
  198. // Returns: HRESULT NOERROR on success, otherwise an error code.
  199. // Algorithm:
  200. // ----------------------------------------------------------------------------
  201. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PPVOID ppv)
  202. {
  203. HRESULT hr;
  204. CDirectInputEffectDriverClassFactory *pObj;
  205. #ifdef _DEBUG
  206. OutputDebugString("sw_effct.dll: DllGetClassObject()\r\n");
  207. #endif
  208. if (CLSID_DirectInputEffectDriver !=rclsid) return ResultFromScode(E_FAIL);
  209. pObj=new CDirectInputEffectDriverClassFactory();
  210. if (NULL==pObj) return ResultFromScode(E_OUTOFMEMORY);
  211. hr=pObj->QueryInterface(riid, ppv);
  212. if (FAILED(hr)) delete pObj;
  213. return hr;
  214. }
  215. // ----------------------------------------------------------------------------
  216. // Function: DllCanUnloadNow
  217. //
  218. // Purpose: Answers if the DLL can be freed, that is, if there are no
  219. // references to anything this DLL provides.
  220. //
  221. //
  222. // Parameters: none
  223. //
  224. // Returns: BOOL TRUE if nothing is using us, FALSE otherwise.
  225. // Algorithm:
  226. // ----------------------------------------------------------------------------
  227. STDAPI DllCanUnloadNow(void)
  228. {
  229. SCODE sc;
  230. //Our answer is whether there are any object or locks
  231. sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
  232. return ResultFromScode(sc);
  233. }
  234. // ----------------------------------------------------------------------------
  235. // Function: ObjectDestroyed
  236. //
  237. // Purpose: Function for the DirectInputEffectDriver object to call when it gets destroyed.
  238. // Since we're in a DLL we only track the number of objects here,
  239. // letting DllCanUnloadNow take care of the rest.
  240. //
  241. // Parameters: none
  242. //
  243. // Returns: BOOL TRUE if nothing is using us, FALSE otherwise.
  244. // Algorithm:
  245. // ----------------------------------------------------------------------------
  246. void ObjectDestroyed(void)
  247. {
  248. g_cObj--;
  249. return;
  250. }
  251. /*
  252. * CVIObjectClassFactory::CVIObjectClassFactory
  253. * CVIObjectClassFactory::~CVIObjectClassFactory
  254. *
  255. * Constructor Parameters:
  256. * None
  257. */
  258. CDirectInputEffectDriverClassFactory::CDirectInputEffectDriverClassFactory(void)
  259. {
  260. m_cRef=0L;
  261. return;
  262. }
  263. CDirectInputEffectDriverClassFactory::~CDirectInputEffectDriverClassFactory(void)
  264. {
  265. return;
  266. }
  267. /*
  268. * CDirectInputEffectDriverClassFactory::QueryInterface
  269. * CDirectInputEffectDriverClassFactory::AddRef
  270. * CDirectInputEffectDriverClassFactory::Release
  271. */
  272. STDMETHODIMP CDirectInputEffectDriverClassFactory::QueryInterface(REFIID riid, PPVOID ppv)
  273. {
  274. *ppv=NULL;
  275. if (IID_IUnknown==riid || IID_IClassFactory==riid) *ppv=this;
  276. if (NULL!=*ppv)
  277. {
  278. ((LPUNKNOWN)*ppv)->AddRef();
  279. return NOERROR;
  280. }
  281. return ResultFromScode(E_NOINTERFACE);
  282. }
  283. STDMETHODIMP_(ULONG) CDirectInputEffectDriverClassFactory::AddRef(void)
  284. {
  285. return ++m_cRef;
  286. }
  287. STDMETHODIMP_(ULONG) CDirectInputEffectDriverClassFactory::Release(void)
  288. {
  289. if (0L!=--m_cRef) return m_cRef;
  290. delete this;
  291. return 0L;
  292. }
  293. /*
  294. * CDirectInputEffectDriverClassFactory::CreateInstance
  295. *
  296. * Purpose:
  297. * Instantiates a DirectInputEffectDriver object returning an interface pointer.
  298. *
  299. * Parameters:
  300. * pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
  301. * being used in an aggregation.
  302. * riid REFIID identifying the interface the caller
  303. * desires to have for the new object.
  304. * ppvObj PPVOID in which to store the desired
  305. * interface pointer for the new object.
  306. *
  307. * Return Value:
  308. * HRESULT NOERROR if successful, otherwise E_NOINTERFACE
  309. * if we cannot support the requested interface.
  310. */
  311. STDMETHODIMP CDirectInputEffectDriverClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
  312. REFIID riid, PPVOID ppvObj)
  313. {
  314. PCDirectInputEffectDriver pObj;
  315. HRESULT hr;
  316. *ppvObj=NULL;
  317. hr=ResultFromScode(E_OUTOFMEMORY);
  318. //Verify that a controlling unknown asks for IUnknown
  319. if (NULL!=pUnkOuter && IID_IUnknown!=riid)
  320. return ResultFromScode(CLASS_E_NOAGGREGATION);
  321. //Create the object passing function to notify on destruction.
  322. pObj=new CDirectInputEffectDriver(pUnkOuter, ObjectDestroyed);
  323. if (NULL==pObj) return hr;
  324. if (pObj->Init()) hr=pObj->QueryInterface(riid, ppvObj);
  325. //Kill the object if initial creation or Init failed.
  326. if (FAILED(hr))
  327. delete pObj;
  328. else
  329. g_cObj++;
  330. return hr;
  331. }
  332. /*
  333. * CDirectInputEffectDriverClassFactory::LockServer
  334. *
  335. * Purpose:
  336. * Increments or decrements the lock count of the DLL. If the
  337. * lock count goes to zero and there are no objects, the DLL
  338. * is allowed to unload. See DllCanUnloadNow.
  339. *
  340. * Parameters:
  341. * fLock BOOL specifying whether to increment or
  342. * decrement the lock count.
  343. *
  344. * Return Value:
  345. * HRESULT NOERROR always.
  346. */
  347. STDMETHODIMP CDirectInputEffectDriverClassFactory::LockServer(BOOL fLock)
  348. {
  349. if (fLock)
  350. g_cLock++;
  351. else
  352. g_cLock--;
  353. return NOERROR;
  354. }