// // Copyright 2001 - Microsoft Corporation // // Created By: // Geoff Pease (GPease) 23-JAN-2001 // // Maintained By: // Geoff Pease (GPease) 23-JAN-2001 // // Notes: // If ENTRY_PREFIX is defined, this indicates that your are trying to // included proxy/stub code into the DLL that is generated by the // MIDL compiler. // ////////////////////////////////////////////////////////////////////////////// #include "pch.h" #include #include "Guids.h" #include #include "DocProp.h" #include "DefProp.h" #include "PropertyCacheItem.h" #include "IEditVariantsInPlace.h" #include "EditTypeItem.h" #include "MLEditTypeItem.h" #include "DropListTypeItem.h" #include "CalendarTypeItem.h" #pragma hdrstop DEFINE_MODULE("DOCPROP3") // // Classes in this Component // // This table is used to create the objects supported in this DLL. It also is // used to map a name with a particular CLSID. HrCoCreateInternalInstance() uses // this table to shortcut COM. // // CreateInstance CLSID User Friendly Name Apartment Model BEGIN_CLASSTABLE DEFINE_CLASS( CDocPropShExt::CreateInstance , CLSID_DocPropShellExtension , "Microsoft DocProp Shell Ext" , "Apartment" ) DEFINE_CLASS( CEditTypeItem::CreateInstance , CLSID_DocPropEditBoxControl , "Microsoft DocProp Inplace Edit Box Control" , "Apartment" ) DEFINE_CLASS( CMLEditTypeItem::CreateInstance , CLSID_DocPropMLEditBoxControl , "Microsoft DocProp Inplace ML Edit Box Control" , "Apartment" ) DEFINE_CLASS( CDropListTypeItem::CreateInstance , CLSID_DocPropDropListComboControl , "Microsoft DocProp Inplace Droplist Combo Control" , "Apartment" ) DEFINE_CLASS( CCalendarTypeItem::CreateInstance , CLSID_DocPropCalendarControl , "Microsoft DocProp Inplace Calendar Control" , "Apartment" ) DEFINE_CLASS( CEditTypeItem::CreateInstance , CLSID_DocPropTimeControl , "Microsoft DocProp Inplace Time Control" , "Apartment" ) END_CLASSTABLE // // DLL Globals // HINSTANCE g_hInstance = NULL; LONG g_cObjects = 0; LONG g_cLock = 0; TCHAR g_szDllFilename[ MAX_PATH ] = { 0 }; LPVOID g_GlobalMemoryList = NULL; // Global memory tracking list #if defined( ENTRY_PREFIX ) extern "C" { extern HINSTANCE hProxyDll; } #endif // // Macros to generate RPC entry points // #define __rpc_macro_expand2(a, b) a##b #define __rpc_macro_expand(a, b) __rpc_macro_expand2(a,b) #if !defined(NO_DLL_MAIN) || defined(ENTRY_PREFIX) || defined(DEBUG) // // Description: // Dll entry point. // BOOL WINAPI DllMain( HINSTANCE hInstIn, // DLL instance ULONG ulReasonIn, // DLL reason code for entrance. LPVOID // lpReservedIn ) { // // KB: NO_THREAD_OPTIMIZATIONS gpease 19-OCT-1999 // // By not defining this you can prvent the linker // from calling you DllEntry for every new thread. // This makes creating new thread significantly // faster if every DLL in a process does it. // Unfortunately, not all DLLs do this. // // In CHKed/DEBUG, we keep this on for memory // tracking. // #if defined( DEBUG ) #define NO_THREAD_OPTIMIZATIONS #endif // DEBUG #if defined(NO_THREAD_OPTIMIZATIONS) switch( ulReasonIn ) { case DLL_PROCESS_ATTACH: { SHFusionInitializeFromModule( hInstIn ); #if defined(USE_WMI_TRACING) TraceInitializeProcess( g_rgTraceControlGuidList, ARRAYSIZE( g_rgTraceControlGuidList ) ); #else TraceInitializeProcess(); #endif TraceCreateMemoryList( g_GlobalMemoryList ); TraceMemoryDelete( g_GlobalMemoryList, FALSE ); // can't track this list. #if defined( DEBUG ) TraceFunc( "" ); TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("DLL: DLL_PROCESS_ATTACH - ThreadID = %#x"), GetCurrentThreadId( ) ); FRETURN( TRUE ); #endif // DEBUG g_hInstance = (HINSTANCE) hInstIn; #if defined( ENTRY_PREFIX ) hProxyDll = g_hInstance; #endif GetModuleFileName( g_hInstance, g_szDllFilename, MAX_PATH ); break; } case DLL_PROCESS_DETACH: { #if defined( DEBUG ) TraceFunc( "" ); TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("DLL: DLL_PROCESS_DETACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"), GetCurrentThreadId( ), g_cLock, g_cObjects ); FRETURN( TRUE ); #endif // DEBUG TraceMemoryAddAddress( g_GlobalMemoryList ); TraceTerminateMemoryList( g_GlobalMemoryList ); #if defined(USE_WMI_TRACING) TraceTerminateProcess( g_rgTraceControlGuidList, ARRAYSIZE( g_rgTraceControlGuidList ) ); #else TraceTerminateProcess(); #endif SHFusionUninitialize(); break; } case DLL_THREAD_ATTACH: { TraceInitializeThread( NULL ); #if defined( DEBUG ) TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("The thread %#x has started."), GetCurrentThreadId( ) ); TraceFunc( "" ); TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("DLL: DLL_THREAD_ATTACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"), GetCurrentThreadId( ), g_cLock, g_cObjects ); FRETURN( TRUE ); #endif // DEBUG break; } case DLL_THREAD_DETACH: { #if defined( DEBUG ) TraceFunc( "" ); TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("DLL: DLL_THREAD_DETACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"), GetCurrentThreadId( ), g_cLock, g_cObjects ); FRETURN( TRUE ); #endif // DEBUG TraceTerminateThread( );; break; } default: { #if defined( DEBUG ) TraceFunc( "" ); TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfDLL, TEXT("DLL: UNKNOWN ENTRANCE REASON - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"), GetCurrentThreadId( ), g_cLock, g_cObjects ); FRETURN( TRUE ); #endif // DEBUG break; } } return TRUE; #else // !NO_THREAD_OPTIMIZATIONS Assert( ulReasonIn == DLL_PROCESS_ATTACH || ulReasonIn == DLL_PROCESS_DETACH ); if ( DLL_PROCESS_ATTACH == ulReasonIn ) { SHFusionInitializeFromModule( hInstIn ); g_hInstance = (HINSTANCE) hInstIn; #ifdef ENTRY_PREFIX hProxyDll = g_hInstance; #endif #ifdef DEBUG #ifdef USE_WMI_TRACING TraceInitializeProcess( g_rgTraceControlGuidList, ARRAYSIZE( g_rgTraceControlGuidList ) ); #else TraceInitializeProcess(); #endif USE_WMI_TRACING #endif DEBUG GetModuleFileName( g_hInstance, g_szDllFilename, MAX_PATH ); BOOL fResult = DisableThreadLibraryCalls( g_hInstance ); AssertMsg( fResult, "*ERROR* DisableThreadLibraryCalls( ) failed." ); } else { #ifdef DEBUG #ifdef USE_WMI_TRACING TraceTerminateProcess( g_rgTraceControlGuidList, ARRAYSIZE( g_rgTraceControlGuidList ) ); #else TraceTerminateProcess(); #endif USE_WMI_TRACING #endif DEBUG SHFusionUninitialize(); } return TRUE; #endif // NO_THREAD_OPTIMIZATIONS } #endif // !defined(NO_DLL_MAIN) && !defined(ENTRY_PREFIX) && !defined(DEBUG) // // Description: // OLE calls this to get the class factory from the DLL. // // Return Values: // S_OK // Success. // // any other HRESULT to indicate failure. // STDAPI DllGetClassObject( REFCLSID rclsidIn, // class ID of the object that the class factory should create. REFIID riidIn, // Interface of the class factory void** ppvOut // The interface pointer to the class factory. ) { TraceFunc( "rclsidIn, riidIn, ppvOut" ); if ( ppvOut == NULL ) { HRETURN(E_POINTER); } LPCFACTORY lpClassFactory; HRESULT hr; int idx; hr = CLASS_E_CLASSNOTAVAILABLE; idx = 0; while( g_DllClasses[ idx ].rclsid ) { if ( *g_DllClasses[ idx ].rclsid == rclsidIn ) { TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, L"rclsidIn = %s", g_DllClasses[ idx ].pszName ); hr = S_OK; break; } idx++; } if ( hr == CLASS_E_CLASSNOTAVAILABLE ) { TraceMsgGUID( mtfFUNC, "rclsidIn = ", rclsidIn ); #if defined( ENTRY_PREFIX ) // // See if the MIDL generated code can create it. // hr = STHR( __rpc_macro_expand( ENTRY_PREFIX, DllGetClassObject )( rclsidIn, riidIn, ppvOut ) ); #endif // defined( ENTRY_PREFIX ) goto Cleanup; } Assert( g_DllClasses[ idx ].pfnCreateInstance != NULL ); lpClassFactory = new CFactory; if ( lpClassFactory == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = THR( lpClassFactory->Init( g_DllClasses[ idx ].pfnCreateInstance ) ); if ( FAILED( hr ) ) { TraceDo( lpClassFactory->Release( ) ); goto Cleanup; } // Can't safe type. hr = lpClassFactory->QueryInterface( riidIn, ppvOut ); // // Release the created instance to counter the AddRef( ) in Init( ). // ((IUnknown *) lpClassFactory )->Release( ); Cleanup: HRETURN(hr); } // // Description: // OLE's register entry point. // // Return Values: // S_OK // Success. // // any other HRESULT. // STDAPI DllRegisterServer( void ) { HRESULT hr; TraceFunc( "" ); hr = THR( HrRegisterDll( TRUE ) ); #if defined( ENTRY_PREFIX ) if ( SUCCEEDED( hr ) ) { hr = THR( __rpc_macro_expand( ENTRY_PREFIX, DllRegisterServer )( ) ); } #endif // defined( ENTRY_PREFIX ) if ( SUCCEEDED( hr ) ) { hr = CDocPropShExt::RegisterShellExtensions( TRUE ); } HRETURN(hr); } // // Description: // OLE's unregister entry point. // // Return Values: // S_OK // Success. // // any other HRESULT // STDAPI DllUnregisterServer( void ) { TraceFunc( "" ); HRESULT hr; hr = THR( HrRegisterDll( FALSE ) ); #if defined( ENTRY_PREFIX ) if ( SUCCEEDED( hr ) ) { hr = THR( __rpc_macro_expand( ENTRY_PREFIX, DllUnregisterServer )( ) ); } #endif // defined( ENTRY_PREFIX ) if ( SUCCEEDED( hr ) ) { hr = CDocPropShExt::RegisterShellExtensions( TRUE ); } HRETURN( hr ); } // // Description: // OLE calls this entry point to see if it can unload the DLL. // // Return Values: // S_OK // Can unload the DLL. // // S_FALSE // Can NOT unload the DLL. // STDAPI DllCanUnloadNow( void ) { TraceFunc( "" ); HRESULT hr = S_OK; if ( g_cLock || g_cObjects ) { TraceMsg( mtfDLL, "DLL: Can't unload - g_cLock=%u, g_cObjects=%u", g_cLock, g_cObjects ); hr = S_FALSE; } #if defined( ENTRY_PREFIX ) else { // // Check with the MIDL generated proxy/stubs. // hr = STHR( __rpc_macro_expand( ENTRY_PREFIX, DllCanUnloadNow )( ) ); } #endif HRETURN(hr); } // // Description: // Mimic CoCreateInstance( ) except that it looks into the DLL table // to see if we can shortcut the CoCreate with a simple CreateInstance // call. // // Return Values: // S_OK // Success. // // E_OUTOFMEMORY // Out of memory. // // other HRESULT values // HRESULT HrCoCreateInternalInstance( REFCLSID rclsidIn, // Class identifier (CLSID) of the object LPUNKNOWN pUnkOuterIn, // Pointer to controlling IUnknown DWORD dwClsContextIn, // Context for running executable code REFIID riidIn, // Reference to the identifier of the interface LPVOID * ppvOut // Address of output variable that receives ) { TraceFunc( "" ); Assert( ppvOut != NULL ); HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; // // Limit simple CoCreate( ) only works to INPROC and non-aggregatable objects. // if ( ( dwClsContextIn & CLSCTX_INPROC_HANDLER ) // inproc only && ( NULL == pUnkOuterIn ) // no aggregation ) { int idx; // // Try to find the class in our DLL table. // for( idx = 0; g_DllClasses[ idx ].rclsid != NULL; idx++ ) { if ( *g_DllClasses[ idx ].rclsid == rclsidIn ) { LPUNKNOWN punk; Assert( g_DllClasses[ idx ].pfnCreateInstance != NULL ); hr = THR( g_DllClasses[ idx ].pfnCreateInstance( &punk ) ); if ( SUCCEEDED( hr ) ) { // Can't safe type. hr = THR( punk->QueryInterface( riidIn, ppvOut ) ); punk->Release( ); } break; // bail loop } } } // // If not found or asking for something we do not support, // use the COM version. // if ( hr == CLASS_E_CLASSNOTAVAILABLE ) { // // Try it the old fashion way... // hr = THR( CoCreateInstance( rclsidIn, pUnkOuterIn, dwClsContextIn, riidIn, ppvOut ) ); } HRETURN( hr ); } // // TODO: gpease 27-NOV-1999 // Whilest parrusing the around the MIDL SDK, I foud that // RPC creates the same type of class table we do. Maybe // we can leverage the MIDL code to create our objects(??). //