1
0

dllentry.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. //------------------------------------------------------------------------------
  2. // File: DlleEntry.cpp
  3. //
  4. // Desc: DirectShow base classes - implements classes used to support dll
  5. // entry points for COM objects.
  6. //
  7. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  8. //------------------------------------------------------------------------------
  9. #include <streams.h>
  10. #include <initguid.h>
  11. #include "combase.h"
  12. #ifdef DEBUG
  13. #ifdef UNICODE
  14. #ifndef _UNICODE
  15. #define _UNICODE
  16. #endif // _UNICODE
  17. #endif // UNICODE
  18. #include <tchar.h>
  19. #endif // DEBUG
  20. #include <strsafe.h>
  21. //extern int g_cTemplates;
  22. //extern CFactoryTemplate g_Templates[];
  23. HINSTANCE g_hInst;
  24. DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
  25. OSVERSIONINFO g_osInfo;
  26. //
  27. // an instance of this is created by the DLLGetClassObject entrypoint
  28. // it uses the CFactoryTemplate object it is given to support the
  29. // IClassFactory interface
  30. class CClassFactory : public IClassFactory, public CBaseObject
  31. {
  32. private:
  33. const CFactoryTemplate *const m_pTemplate;
  34. ULONG m_cRef;
  35. static int m_cLocked;
  36. public:
  37. CClassFactory(const CFactoryTemplate *);
  38. // IUnknown
  39. STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv);
  40. STDMETHODIMP_(ULONG)AddRef();
  41. STDMETHODIMP_(ULONG)Release();
  42. // IClassFactory
  43. STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out 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 CFactoryTemplate *pTemplate)
  53. : CBaseObject(NAME("Class Factory"))
  54. , m_cRef(0)
  55. , m_pTemplate(pTemplate)
  56. {
  57. }
  58. STDMETHODIMP
  59. CClassFactory::QueryInterface(REFIID riid,__deref_out void **ppv)
  60. {
  61. CheckPointer(ppv,E_POINTER)
  62. ValidateReadWritePtr(ppv,sizeof(PVOID));
  63. *ppv = NULL;
  64. // any interface on this object is the object pointer.
  65. if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
  66. *ppv = (LPVOID) this;
  67. // AddRef returned interface pointer
  68. ((LPUNKNOWN) *ppv)->AddRef();
  69. return NOERROR;
  70. }
  71. return ResultFromScode(E_NOINTERFACE);
  72. }
  73. STDMETHODIMP_(ULONG)
  74. CClassFactory::AddRef()
  75. {
  76. return ++m_cRef;
  77. }
  78. STDMETHODIMP_(ULONG)
  79. CClassFactory::Release()
  80. {
  81. LONG lRef = InterlockedDecrement((volatile LONG *)&m_cRef);
  82. if (lRef == 0) {
  83. delete this;
  84. return 0;
  85. } else {
  86. return lRef;
  87. }
  88. }
  89. STDMETHODIMP
  90. CClassFactory::CreateInstance(
  91. LPUNKNOWN pUnkOuter,
  92. REFIID riid,
  93. __deref_out void **pv)
  94. {
  95. CheckPointer(pv,E_POINTER)
  96. ValidateReadWritePtr(pv,sizeof(void *));
  97. *pv = NULL;
  98. /* Enforce the normal OLE rules regarding interfaces and delegation */
  99. if (pUnkOuter != NULL) {
  100. if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
  101. *pv = NULL;
  102. return ResultFromScode(E_NOINTERFACE);
  103. }
  104. }
  105. /* Create the new object through the derived class's create function */
  106. HRESULT hr = NOERROR;
  107. CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
  108. if (pObj == NULL) {
  109. *pv = NULL;
  110. if (SUCCEEDED(hr)) {
  111. hr = E_OUTOFMEMORY;
  112. }
  113. return hr;
  114. }
  115. /* Delete the object if we got a construction error */
  116. if (FAILED(hr)) {
  117. delete pObj;
  118. *pv = NULL;
  119. return hr;
  120. }
  121. /* Get a reference counted interface on the object */
  122. /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
  123. /* This protects any outer object from being prematurely */
  124. /* released by an inner object that may have to be created */
  125. /* in order to supply the requested interface. */
  126. pObj->NonDelegatingAddRef();
  127. hr = pObj->NonDelegatingQueryInterface(riid, pv);
  128. pObj->NonDelegatingRelease();
  129. /* Note that if NonDelegatingQueryInterface fails, it will */
  130. /* not increment the ref count, so the NonDelegatingRelease */
  131. /* will drop the ref back to zero and the object will "self-*/
  132. /* destruct". Hence we don't need additional tidy-up code */
  133. /* to cope with NonDelegatingQueryInterface failing. */
  134. if (SUCCEEDED(hr)) {
  135. ASSERT(*pv);
  136. }
  137. return hr;
  138. }
  139. STDMETHODIMP
  140. CClassFactory::LockServer(BOOL fLock)
  141. {
  142. if (fLock) {
  143. m_cLocked++;
  144. } else {
  145. m_cLocked--;
  146. }
  147. return NOERROR;
  148. }
  149. // --- COM entrypoints -----------------------------------------
  150. //called by COM to get the class factory object for a given class
  151. /*
  152. __control_entrypoint(DllExport) STDAPI
  153. DllGetClassObject(
  154. __in REFCLSID rClsID,
  155. __in REFIID riid,
  156. __deref_out void **pv)
  157. {
  158. *pv = NULL;
  159. if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
  160. return E_NOINTERFACE;
  161. }
  162. // traverse the array of templates looking for one with this
  163. // class id
  164. for (int i = 0; i < g_cTemplates; i++) {
  165. const CFactoryTemplate * pT = &g_Templates[i];
  166. if (pT->IsClassID(rClsID)) {
  167. // found a template - make a class factory based on this
  168. // template
  169. *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
  170. if (*pv == NULL) {
  171. return E_OUTOFMEMORY;
  172. }
  173. ((LPUNKNOWN)*pv)->AddRef();
  174. return NOERROR;
  175. }
  176. }
  177. return CLASS_E_CLASSNOTAVAILABLE;
  178. }
  179. */
  180. //
  181. // Call any initialization routines
  182. //
  183. /*
  184. void
  185. DllInitClasses(BOOL bLoading)
  186. {
  187. int i;
  188. // traverse the array of templates calling the init routine
  189. // if they have one
  190. for (i = 0; i < g_cTemplates; i++) {
  191. const CFactoryTemplate * pT = &g_Templates[i];
  192. if (pT->m_lpfnInit != NULL) {
  193. (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
  194. }
  195. }
  196. }
  197. */
  198. // called by COM to determine if this dll can be unloaded
  199. // return ok unless there are outstanding objects or a lock requested
  200. // by IClassFactory::LockServer
  201. //
  202. // CClassFactory has a static function that can tell us about the locks,
  203. // and CCOMObject has a static function that can tell us about the active
  204. // object count
  205. STDAPI
  206. DllCanUnloadNow()
  207. {
  208. DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
  209. CClassFactory::IsLocked(),
  210. CBaseObject::ObjectsActive()));
  211. if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
  212. return S_FALSE;
  213. } else {
  214. return S_OK;
  215. }
  216. }
  217. // --- standard WIN32 entrypoints --------------------------------------
  218. /*
  219. extern "C" void __cdecl __security_init_cookie(void);
  220. extern "C" BOOL WINAPI _DllEntryPoint(HINSTANCE, ULONG, __inout_opt LPVOID);
  221. #pragma comment(linker, "/merge:.CRT=.rdata")
  222. extern "C"
  223. DECLSPEC_NOINLINE
  224. BOOL
  225. WINAPI
  226. DllEntryPoint(
  227. HINSTANCE hInstance,
  228. ULONG ulReason,
  229. __inout_opt LPVOID pv
  230. )
  231. {
  232. if ( ulReason == DLL_PROCESS_ATTACH ) {
  233. // Must happen before any other code is executed. Thankfully - it's re-entrant
  234. __security_init_cookie();
  235. }
  236. return _DllEntryPoint(hInstance, ulReason, pv);
  237. }
  238. DECLSPEC_NOINLINE
  239. BOOL
  240. WINAPI
  241. _DllEntryPoint(
  242. HINSTANCE hInstance,
  243. ULONG ulReason,
  244. __inout_opt LPVOID pv
  245. )
  246. {
  247. #ifdef DEBUG
  248. extern bool g_fDbgInDllEntryPoint;
  249. g_fDbgInDllEntryPoint = true;
  250. #endif
  251. switch (ulReason)
  252. {
  253. case DLL_PROCESS_ATTACH:
  254. DisableThreadLibraryCalls(hInstance);
  255. DbgInitialise(hInstance);
  256. {
  257. // The platform identifier is used to work out whether
  258. // full unicode support is available or not. Hence the
  259. // default will be the lowest common denominator - i.e. N/A
  260. g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
  261. g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
  262. if (GetVersionEx(&g_osInfo)) {
  263. g_amPlatform = g_osInfo.dwPlatformId;
  264. } else {
  265. DbgLog((LOG_ERROR, 1, TEXT("Failed to get the OS platform, assuming Win95")));
  266. }
  267. }
  268. g_hInst = hInstance;
  269. DllInitClasses(TRUE);
  270. break;
  271. case DLL_PROCESS_DETACH:
  272. DllInitClasses(FALSE);
  273. #ifdef DEBUG
  274. if (CBaseObject::ObjectsActive()) {
  275. DbgSetModuleLevel(LOG_MEMORY, 2);
  276. TCHAR szInfo[512];
  277. extern TCHAR m_ModuleName[]; // Cut down module name
  278. TCHAR FullName[_MAX_PATH]; // Load the full path and module name
  279. TCHAR *pName; // Searches from the end for a backslash
  280. GetModuleFileName(NULL,FullName,_MAX_PATH);
  281. pName = _tcsrchr(FullName,'\\');
  282. if (pName == NULL) {
  283. pName = FullName;
  284. } else {
  285. pName++;
  286. }
  287. (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("Executable: %s Pid %x Tid %x. "),
  288. pName, GetCurrentProcessId(), GetCurrentThreadId());
  289. (void)StringCchPrintf(szInfo+lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), TEXT("Module %s, %d objects left active!"),
  290. m_ModuleName, CBaseObject::ObjectsActive());
  291. DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
  292. // If running remotely wait for the Assert to be acknowledged
  293. // before dumping out the object register
  294. DbgDumpObjectRegister();
  295. }
  296. DbgTerminate();
  297. #endif
  298. break;
  299. }
  300. #ifdef DEBUG
  301. g_fDbgInDllEntryPoint = false;
  302. #endif
  303. return TRUE;
  304. }
  305. */