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.

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