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.

323 lines
8.0 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // classes used to support dll entrypoints for COM objects.
  13. //
  14. int g_cActiveObjects = 0;
  15. #include "dmocom.h"
  16. #include "dmoreg.h"
  17. #include "dmoutils.h"
  18. #include <shlwapi.h>
  19. #ifdef DEBUG
  20. bool g_fDbgInDllEntryPoint = false;
  21. #endif
  22. extern CComClassTemplate g_ComClassTemplates[];
  23. extern int g_cComClassTemplates;
  24. HINSTANCE g_hInst;
  25. //
  26. // an instance of this is created by the DLLGetClassObject entrypoint
  27. // it uses the CComClassTemplate object it is given to support the
  28. // IClassFactory interface
  29. class CClassFactory : public IClassFactory,
  30. CBaseObject
  31. {
  32. private:
  33. const CComClassTemplate *const m_pTemplate;
  34. ULONG m_cRef;
  35. static int m_cLocked;
  36. public:
  37. CClassFactory(const CComClassTemplate *);
  38. // IUnknown
  39. STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
  40. STDMETHODIMP_(ULONG)AddRef();
  41. STDMETHODIMP_(ULONG)Release();
  42. // IClassFactory
  43. STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
  44. STDMETHODIMP LockServer(BOOL fLock);
  45. // allow DLLGetClassObject to know about global server lock status
  46. static BOOL IsLocked() {
  47. return (m_cLocked > 0);
  48. };
  49. };
  50. // process-wide dll locked state
  51. int CClassFactory::m_cLocked = 0;
  52. CClassFactory::CClassFactory(const CComClassTemplate *pTemplate)
  53. : m_cRef(0)
  54. , m_pTemplate(pTemplate)
  55. {
  56. }
  57. STDMETHODIMP
  58. CClassFactory::QueryInterface(REFIID riid,void **ppv)
  59. {
  60. CheckPointer(ppv,E_POINTER)
  61. ValidateReadWritePtr(ppv,sizeof(PVOID));
  62. *ppv = NULL;
  63. // any interface on this object is the object pointer.
  64. if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
  65. *ppv = (LPVOID) this;
  66. // AddRef returned interface pointer
  67. ((LPUNKNOWN) *ppv)->AddRef();
  68. return NOERROR;
  69. }
  70. return ResultFromScode(E_NOINTERFACE);
  71. }
  72. STDMETHODIMP_(ULONG)
  73. CClassFactory::AddRef()
  74. {
  75. return ++m_cRef;
  76. }
  77. STDMETHODIMP_(ULONG)
  78. CClassFactory::Release()
  79. {
  80. if (--m_cRef == 0) {
  81. delete this;
  82. return 0;
  83. } else {
  84. return m_cRef;
  85. }
  86. }
  87. STDMETHODIMP
  88. CClassFactory::CreateInstance(
  89. LPUNKNOWN pUnkOuter,
  90. REFIID riid,
  91. void **pv)
  92. {
  93. CheckPointer(pv,E_POINTER)
  94. ValidateReadWritePtr(pv,sizeof(void *));
  95. /* Enforce the normal OLE rules regarding interfaces and delegation */
  96. if (pUnkOuter != NULL) {
  97. if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
  98. return ResultFromScode(E_NOINTERFACE);
  99. }
  100. }
  101. /* Create the new object through the derived class's create function */
  102. HRESULT hr = NOERROR;
  103. CComBase *pObj = m_pTemplate->m_lpfnNew(pUnkOuter, &hr);
  104. if (pObj == NULL) {
  105. if (SUCCEEDED(hr)) {
  106. hr = E_OUTOFMEMORY;
  107. }
  108. return hr;
  109. }
  110. /* Delete the object if we got a construction error */
  111. if (FAILED(hr)) {
  112. delete pObj;
  113. return hr;
  114. }
  115. /* Get a reference counted interface on the object */
  116. /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
  117. /* This protects any outer object from being prematurely */
  118. /* released by an inner object that may have to be created */
  119. /* in order to supply the requested interface. */
  120. pObj->NDAddRef();
  121. hr = pObj->NDQueryInterface(riid, pv);
  122. pObj->NDRelease();
  123. /* Note that if NDQueryInterface fails, it will */
  124. /* not increment the ref count, so the NDRelease */
  125. /* will drop the ref back to zero and the object will "self-*/
  126. /* destruct". Hence we don't need additional tidy-up code */
  127. /* to cope with NDQueryInterface failing. */
  128. if (SUCCEEDED(hr)) {
  129. ASSERT(*pv);
  130. }
  131. return hr;
  132. }
  133. STDMETHODIMP
  134. CClassFactory::LockServer(BOOL fLock)
  135. {
  136. if (fLock) {
  137. m_cLocked++;
  138. } else {
  139. m_cLocked--;
  140. }
  141. return NOERROR;
  142. }
  143. // --- COM entrypoints -----------------------------------------
  144. //called by COM to get the class factory object for a given class
  145. STDAPI
  146. DllGetClassObject(
  147. REFCLSID rClsID,
  148. REFIID riid,
  149. void **pv)
  150. {
  151. if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
  152. return E_NOINTERFACE;
  153. }
  154. // traverse the array of templates looking for one with this
  155. // class id
  156. for (int i = 0; i < g_cComClassTemplates; i++) {
  157. const CComClassTemplate * pT = &g_ComClassTemplates[i];
  158. if (*(pT->m_ClsID) == rClsID) {
  159. // found a template - make a class factory based on this
  160. // template
  161. *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
  162. if (*pv == NULL) {
  163. return E_OUTOFMEMORY;
  164. }
  165. ((LPUNKNOWN)*pv)->AddRef();
  166. return NOERROR;
  167. }
  168. }
  169. return CLASS_E_CLASSNOTAVAILABLE;
  170. }
  171. // called by COM to determine if this dll can be unloaded
  172. // return ok unless there are outstanding objects or a lock requested
  173. // by IClassFactory::LockServer
  174. //
  175. // CClassFactory has a static function that can tell us about the locks,
  176. // and CCOMObject has a static function that can tell us about the active
  177. // object count
  178. STDAPI
  179. DllCanUnloadNow()
  180. {
  181. if (CClassFactory::IsLocked() || g_cActiveObjects) {
  182. return S_FALSE;
  183. } else {
  184. return S_OK;
  185. }
  186. }
  187. // --- standard WIN32 entrypoints --------------------------------------
  188. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  189. BOOL WINAPI
  190. DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
  191. {
  192. #ifdef DEBUG
  193. extern bool g_fDbgInDllEntryPoint;
  194. g_fDbgInDllEntryPoint = true;
  195. #endif
  196. switch (ulReason)
  197. {
  198. case DLL_PROCESS_ATTACH:
  199. DisableThreadLibraryCalls(hInstance);
  200. g_hInst = hInstance;
  201. //DllInitClasses(TRUE);
  202. break;
  203. case DLL_PROCESS_DETACH:
  204. //DllInitClasses(FALSE);
  205. break;
  206. }
  207. #ifdef DEBUG
  208. g_fDbgInDllEntryPoint = false;
  209. #endif
  210. return TRUE;
  211. }
  212. // Automatically calls RegCloseKey when leaving scope
  213. class CAutoHKey {
  214. public:
  215. CAutoHKey(HKEY hKey, TCHAR* szSubKey, HKEY *phKey) {
  216. if (RegCreateKey(hKey, szSubKey, phKey) != ERROR_SUCCESS)
  217. m_hKey = *phKey = NULL;
  218. else
  219. m_hKey = *phKey;
  220. }
  221. ~CAutoHKey() {
  222. if (m_hKey)
  223. RegCloseKey(m_hKey);
  224. }
  225. HKEY m_hKey;
  226. };
  227. //
  228. // Creates the COM registration key with subkeys under HKCR\CLSID
  229. //
  230. STDAPI CreateCLSIDRegKey(REFCLSID clsid, const char *szName) {
  231. // Get dll name
  232. char szFileName[MAX_PATH];
  233. GetModuleFileNameA(g_hInst, szFileName, MAX_PATH);
  234. char szRegPath[80] = "CLSID\\{";
  235. HKEY hKey;
  236. DMOGuidToStrA(szRegPath + 7, clsid);
  237. strcat(szRegPath, "}");
  238. CAutoHKey k1(HKEY_CLASSES_ROOT,szRegPath,&hKey);
  239. if (!hKey)
  240. return E_FAIL;
  241. if (RegSetValueA(hKey, NULL, REG_SZ, szName, strlen(szName)) != ERROR_SUCCESS)
  242. return E_FAIL;
  243. HKEY hInprocServerKey;
  244. CAutoHKey k2(hKey,"InprocServer32",&hInprocServerKey);
  245. if (!hInprocServerKey)
  246. return E_FAIL;
  247. if (RegSetValueA(hInprocServerKey, NULL, REG_SZ, szFileName, strlen(szFileName)) != ERROR_SUCCESS)
  248. return E_FAIL;
  249. if (RegSetValueExA(hInprocServerKey, "ThreadingModel", 0, REG_SZ, (BYTE*)"Both", 4) != ERROR_SUCCESS)
  250. return E_FAIL;
  251. return NOERROR;
  252. }
  253. STDAPI RemoveCLSIDRegKey(REFCLSID clsid)
  254. {
  255. char szRegPath[80] = "CLSID\\{";
  256. DMOGuidToStrA(szRegPath + 7, clsid);
  257. strcat(szRegPath, "}");
  258. // Delete this key
  259. if (ERROR_SUCCESS == SHDeleteKey(HKEY_CLASSES_ROOT, szRegPath)) {
  260. return S_OK;
  261. } else {
  262. return E_FAIL;
  263. }
  264. }