summaryrefslogtreecommitdiff
path: root/third_party/BaseClasses/dllentry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/BaseClasses/dllentry.cpp')
-rw-r--r--third_party/BaseClasses/dllentry.cpp367
1 files changed, 367 insertions, 0 deletions
diff --git a/third_party/BaseClasses/dllentry.cpp b/third_party/BaseClasses/dllentry.cpp
new file mode 100644
index 00000000..130aad6a
--- /dev/null
+++ b/third_party/BaseClasses/dllentry.cpp
@@ -0,0 +1,367 @@
+//------------------------------------------------------------------------------
+// File: DlleEntry.cpp
+//
+// Desc: DirectShow base classes - implements classes used to support dll
+// entry points for COM objects.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#include <streams.h>
+#include <initguid.h>
+
+#ifdef DEBUG
+#ifdef UNICODE
+#ifndef _UNICODE
+#define _UNICODE
+#endif // _UNICODE
+#endif // UNICODE
+
+#include <tchar.h>
+#endif // DEBUG
+#include <strsafe.h>
+
+extern CFactoryTemplate g_Templates[];
+extern int g_cTemplates;
+
+HINSTANCE g_hInst;
+DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
+OSVERSIONINFO g_osInfo;
+
+//
+// an instance of this is created by the DLLGetClassObject entrypoint
+// it uses the CFactoryTemplate object it is given to support the
+// IClassFactory interface
+
+class CClassFactory : public IClassFactory, public CBaseObject
+{
+
+private:
+ const CFactoryTemplate *const m_pTemplate;
+
+ ULONG m_cRef;
+
+ static int m_cLocked;
+public:
+ CClassFactory(const CFactoryTemplate *);
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv);
+ STDMETHODIMP_(ULONG)AddRef();
+ STDMETHODIMP_(ULONG)Release();
+
+ // IClassFactory
+ STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out void **pv);
+ STDMETHODIMP LockServer(BOOL fLock);
+
+ // allow DLLGetClassObject to know about global server lock status
+ static BOOL IsLocked() {
+ return (m_cLocked > 0);
+ };
+};
+
+// process-wide dll locked state
+int CClassFactory::m_cLocked = 0;
+
+CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
+: CBaseObject(NAME("Class Factory"))
+, m_cRef(0)
+, m_pTemplate(pTemplate)
+{
+}
+
+
+STDMETHODIMP
+CClassFactory::QueryInterface(REFIID riid,__deref_out void **ppv)
+{
+ CheckPointer(ppv,E_POINTER)
+ ValidateReadWritePtr(ppv,sizeof(PVOID));
+ *ppv = NULL;
+
+ // any interface on this object is the object pointer.
+ if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
+ *ppv = (LPVOID) this;
+ // AddRef returned interface pointer
+ ((LPUNKNOWN) *ppv)->AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+
+STDMETHODIMP_(ULONG)
+CClassFactory::AddRef()
+{
+ return ++m_cRef;
+}
+
+STDMETHODIMP_(ULONG)
+CClassFactory::Release()
+{
+ LONG lRef = InterlockedDecrement((volatile LONG *)&m_cRef);
+ if (lRef == 0) {
+ delete this;
+ return 0;
+ } else {
+ return lRef;
+ }
+}
+
+STDMETHODIMP
+CClassFactory::CreateInstance(
+ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ __deref_out void **pv)
+{
+ CheckPointer(pv,E_POINTER)
+ ValidateReadWritePtr(pv,sizeof(void *));
+ *pv = NULL;
+
+ /* Enforce the normal OLE rules regarding interfaces and delegation */
+
+ if (pUnkOuter != NULL) {
+ if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
+ *pv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+ }
+ }
+
+ /* Create the new object through the derived class's create function */
+
+ HRESULT hr = NOERROR;
+ CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
+
+ if (pObj == NULL) {
+ *pv = NULL;
+ if (SUCCEEDED(hr)) {
+ hr = E_OUTOFMEMORY;
+ }
+ return hr;
+ }
+
+ /* Delete the object if we got a construction error */
+
+ if (FAILED(hr)) {
+ delete pObj;
+ *pv = NULL;
+ return hr;
+ }
+
+ /* Get a reference counted interface on the object */
+
+ /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
+ /* This protects any outer object from being prematurely */
+ /* released by an inner object that may have to be created */
+ /* in order to supply the requested interface. */
+ pObj->NonDelegatingAddRef();
+ hr = pObj->NonDelegatingQueryInterface(riid, pv);
+ pObj->NonDelegatingRelease();
+ /* Note that if NonDelegatingQueryInterface fails, it will */
+ /* not increment the ref count, so the NonDelegatingRelease */
+ /* will drop the ref back to zero and the object will "self-*/
+ /* destruct". Hence we don't need additional tidy-up code */
+ /* to cope with NonDelegatingQueryInterface failing. */
+
+ if (SUCCEEDED(hr)) {
+ ASSERT(*pv);
+ }
+
+ return hr;
+}
+
+STDMETHODIMP
+CClassFactory::LockServer(BOOL fLock)
+{
+ if (fLock) {
+ m_cLocked++;
+ } else {
+ m_cLocked--;
+ }
+ return NOERROR;
+}
+
+
+// --- COM entrypoints -----------------------------------------
+
+//called by COM to get the class factory object for a given class
+__control_entrypoint(DllExport) STDAPI
+DllGetClassObject(
+ __in REFCLSID rClsID,
+ __in REFIID riid,
+ __deref_out void **pv)
+{
+ *pv = NULL;
+ if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
+ return E_NOINTERFACE;
+ }
+
+ // traverse the array of templates looking for one with this
+ // class id
+ for (int i = 0; i < g_cTemplates; i++) {
+ const CFactoryTemplate * pT = &g_Templates[i];
+ if (pT->IsClassID(rClsID)) {
+
+ // found a template - make a class factory based on this
+ // template
+
+ *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
+ if (*pv == NULL) {
+ return E_OUTOFMEMORY;
+ }
+ ((LPUNKNOWN)*pv)->AddRef();
+ return NOERROR;
+ }
+ }
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+//
+// Call any initialization routines
+//
+void
+DllInitClasses(BOOL bLoading)
+{
+ int i;
+
+ // traverse the array of templates calling the init routine
+ // if they have one
+ for (i = 0; i < g_cTemplates; i++) {
+ const CFactoryTemplate * pT = &g_Templates[i];
+ if (pT->m_lpfnInit != NULL) {
+ (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
+ }
+ }
+
+}
+
+// called by COM to determine if this dll can be unloaded
+// return ok unless there are outstanding objects or a lock requested
+// by IClassFactory::LockServer
+//
+// CClassFactory has a static function that can tell us about the locks,
+// and CCOMObject has a static function that can tell us about the active
+// object count
+STDAPI
+DllCanUnloadNow()
+{
+ DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
+ CClassFactory::IsLocked(),
+ CBaseObject::ObjectsActive()));
+
+ if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
+ return S_FALSE;
+ } else {
+ return S_OK;
+ }
+}
+
+
+// --- standard WIN32 entrypoints --------------------------------------
+
+
+extern "C" void __cdecl __security_init_cookie(void);
+extern "C" BOOL WINAPI _DllEntryPoint(HINSTANCE, ULONG, __inout_opt LPVOID);
+#pragma comment(linker, "/merge:.CRT=.rdata")
+
+extern "C"
+DECLSPEC_NOINLINE
+BOOL
+WINAPI
+DllEntryPoint(
+ HINSTANCE hInstance,
+ ULONG ulReason,
+ __inout_opt LPVOID pv
+ )
+{
+ if ( ulReason == DLL_PROCESS_ATTACH ) {
+ // Must happen before any other code is executed. Thankfully - it's re-entrant
+ __security_init_cookie();
+ }
+ return _DllEntryPoint(hInstance, ulReason, pv);
+}
+
+
+DECLSPEC_NOINLINE
+BOOL
+WINAPI
+_DllEntryPoint(
+ HINSTANCE hInstance,
+ ULONG ulReason,
+ __inout_opt LPVOID pv
+ )
+{
+#ifdef DEBUG
+ extern bool g_fDbgInDllEntryPoint;
+ g_fDbgInDllEntryPoint = true;
+#endif
+
+ switch (ulReason)
+ {
+
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hInstance);
+ DbgInitialise(hInstance);
+
+ {
+ // The platform identifier is used to work out whether
+ // full unicode support is available or not. Hence the
+ // default will be the lowest common denominator - i.e. N/A
+ g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
+
+ g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
+ if (GetVersionEx(&g_osInfo)) {
+ g_amPlatform = g_osInfo.dwPlatformId;
+ } else {
+ DbgLog((LOG_ERROR, 1, TEXT("Failed to get the OS platform, assuming Win95")));
+ }
+ }
+
+ g_hInst = hInstance;
+ DllInitClasses(TRUE);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ DllInitClasses(FALSE);
+
+#ifdef DEBUG
+ if (CBaseObject::ObjectsActive()) {
+ DbgSetModuleLevel(LOG_MEMORY, 2);
+ TCHAR szInfo[512];
+ extern TCHAR m_ModuleName[]; // Cut down module name
+
+ TCHAR FullName[_MAX_PATH]; // Load the full path and module name
+ TCHAR *pName; // Searches from the end for a backslash
+
+ GetModuleFileName(NULL,FullName,_MAX_PATH);
+ pName = _tcsrchr(FullName,'\\');
+ if (pName == NULL) {
+ pName = FullName;
+ } else {
+ pName++;
+ }
+
+ (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("Executable: %s Pid %x Tid %x. "),
+ pName, GetCurrentProcessId(), GetCurrentThreadId());
+
+ (void)StringCchPrintf(szInfo+lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), TEXT("Module %s, %d objects left active!"),
+ m_ModuleName, CBaseObject::ObjectsActive());
+ DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
+
+ // If running remotely wait for the Assert to be acknowledged
+ // before dumping out the object register
+ DbgDumpObjectRegister();
+ }
+ DbgTerminate();
+#endif
+ break;
+ }
+
+#ifdef DEBUG
+ g_fDbgInDllEntryPoint = false;
+#endif
+ return TRUE;
+}
+
+