00001
00002
00003
00004
00005
00006 #include <streams.h>
00007
00008 #ifdef DEBUG
00009 #ifdef UNICODE
00010 #ifndef _UNICODE
00011 #define _UNICODE
00012 #endif
00013 #endif
00014
00015 #include <tchar.h>
00016 #endif
00017
00018 extern CFactoryTemplate g_Templates[];
00019 extern int g_cTemplates;
00020
00021 HINSTANCE g_hInst;
00022 DWORD g_amPlatform;
00023 OSVERSIONINFO g_osInfo;
00024
00025 class CClassFactory : public IClassFactory, public CBaseObject
00026 {
00027
00028 private:
00029 const CFactoryTemplate *const m_pTemplate;
00030
00031 ULONG m_cRef;
00032
00033 static int m_cLocked;
00034 public:
00035 CClassFactory(const CFactoryTemplate *);
00036
00037 STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
00038 STDMETHODIMP_(ULONG)AddRef();
00039 STDMETHODIMP_(ULONG)Release();
00040
00041 STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
00042 STDMETHODIMP LockServer(BOOL fLock);
00043
00044 static BOOL IsLocked() {
00045 return (m_cLocked > 0);
00046 };
00047 };
00048
00049 int CClassFactory::m_cLocked = 0;
00050
00051 CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
00052 : CBaseObject(NAME("Class Factory"))
00053 , m_cRef(0)
00054 , m_pTemplate(pTemplate)
00055 {
00056 }
00057
00058 STDMETHODIMP
00059 CClassFactory::QueryInterface(REFIID riid,void **ppv)
00060 {
00061 CheckPointer(ppv,E_POINTER)
00062 ValidateReadWritePtr(ppv,sizeof(PVOID));
00063 *ppv = NULL;
00064
00065
00066 if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
00067 *ppv = (LPVOID) this;
00068
00069 ((LPUNKNOWN) *ppv)->AddRef();
00070 return NOERROR;
00071 }
00072
00073 return ResultFromScode(E_NOINTERFACE);
00074 }
00075
00076 STDMETHODIMP_(ULONG)
00077 CClassFactory::AddRef()
00078 {
00079 return ++m_cRef;
00080 }
00081
00082 STDMETHODIMP_(ULONG)
00083 CClassFactory::Release()
00084 {
00085 if (--m_cRef == 0) {
00086 delete this;
00087 return 0;
00088 } else {
00089 return m_cRef;
00090 }
00091 }
00092
00093 STDMETHODIMP
00094 CClassFactory::CreateInstance(
00095 LPUNKNOWN pUnkOuter,
00096 REFIID riid,
00097 void **pv)
00098 {
00099 CheckPointer(pv,E_POINTER)
00100 ValidateReadWritePtr(pv,sizeof(void *));
00101
00102 if (pUnkOuter != NULL) {
00103 if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
00104 return ResultFromScode(E_NOINTERFACE);
00105 }
00106 }
00107
00108 HRESULT hr = NOERROR;
00109 CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
00110
00111 if (pObj == NULL) {
00112 if (SUCCEEDED(hr)) {
00113 hr = E_OUTOFMEMORY;
00114 }
00115 return hr;
00116 }
00117
00118 if (FAILED(hr)) {
00119 delete pObj;
00120 return hr;
00121 }
00122
00123 pObj->NonDelegatingAddRef();
00124 hr = pObj->NonDelegatingQueryInterface(riid, pv);
00125 pObj->NonDelegatingRelease();
00126
00127 if (SUCCEEDED(hr)) {
00128 ASSERT(*pv);
00129 }
00130
00131 return hr;
00132 }
00133
00134 STDMETHODIMP
00135 CClassFactory::LockServer(BOOL fLock)
00136 {
00137 if (fLock) {
00138 m_cLocked++;
00139 } else {
00140 m_cLocked--;
00141 }
00142 return NOERROR;
00143 }
00144
00145 STDAPI
00146 DllGetClassObject(
00147 REFCLSID rClsID,
00148 REFIID riid,
00149 void **pv)
00150 {
00151 if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
00152 return E_NOINTERFACE;
00153 }
00154
00155 for (int i = 0; i < g_cTemplates; i++) {
00156 const CFactoryTemplate * pT = &g_Templates[i];
00157 if (pT->IsClassID(rClsID)) {
00158
00159 *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
00160 if (*pv == NULL) {
00161 return E_OUTOFMEMORY;
00162 }
00163 ((LPUNKNOWN)*pv)->AddRef();
00164 return NOERROR;
00165 }
00166 }
00167 return CLASS_E_CLASSNOTAVAILABLE;
00168 }
00169
00170 void
00171 DllInitClasses(BOOL bLoading)
00172 {
00173 int i;
00174
00175 for (i = 0; i < g_cTemplates; i++) {
00176 const CFactoryTemplate * pT = &g_Templates[i];
00177 if (pT->m_lpfnInit != NULL) {
00178 (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
00179 }
00180 }
00181
00182 }
00183
00184 STDAPI
00185 DllCanUnloadNow()
00186 {
00187 DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
00188 CClassFactory::IsLocked(),
00189 CBaseObject::ObjectsActive()));
00190
00191 if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
00192 return S_FALSE;
00193 } else {
00194 return S_OK;
00195 }
00196 }
00197
00198 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00199
00200 BOOL WINAPI
00201 DllEntryPoint(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
00202 {
00203 #ifdef DEBUG
00204 extern bool g_fDbgInDllEntryPoint;
00205 g_fDbgInDllEntryPoint = true;
00206 #endif
00207
00208 switch (ulReason)
00209 {
00210
00211 case DLL_PROCESS_ATTACH:
00212 DisableThreadLibraryCalls(hInstance);
00213 DbgInitialise(hInstance);
00214
00215 {
00216
00217 g_amPlatform = VER_PLATFORM_WIN32_WINDOWS;
00218
00219 g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
00220 if (GetVersionEx(&g_osInfo)) {
00221 g_amPlatform = g_osInfo.dwPlatformId;
00222 } else {
00223 DbgLog((LOG_ERROR, 1, TEXT("Failed to get the OS platform, assuming Win95")));
00224 }
00225 }
00226 g_hInst = hInstance;
00227 DllInitClasses(TRUE);
00228 break;
00229
00230 case DLL_PROCESS_DETACH:
00231 DllInitClasses(FALSE);
00232
00233 #ifdef DEBUG
00234 if (CBaseObject::ObjectsActive()) {
00235 DbgSetModuleLevel(LOG_MEMORY, 2);
00236 TCHAR szInfo[512];
00237 extern TCHAR m_ModuleName[];
00238
00239 TCHAR FullName[_MAX_PATH];
00240 TCHAR *pName;
00241
00242 GetModuleFileName(NULL,FullName,_MAX_PATH);
00243 pName = _tcsrchr(FullName,'\\');
00244 if (pName == NULL) {
00245 pName = FullName;
00246 } else {
00247 pName++;
00248 }
00249
00250 DWORD cch = wsprintf(szInfo, TEXT("Executable: %s Pid %x Tid %x. "),
00251 pName, GetCurrentProcessId(), GetCurrentThreadId());
00252
00253 wsprintf(szInfo+cch, TEXT("Module %s, %d objects left active!"),
00254 m_ModuleName, CBaseObject::ObjectsActive());
00255 DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
00256
00257 DbgDumpObjectRegister();
00258 }
00259 DbgTerminate();
00260 #endif
00261 break;
00262 }
00263
00264 #ifdef DEBUG
00265 g_fDbgInDllEntryPoint = false;
00266 #endif
00267 return TRUE;
00268 }
00269