566 lines
15 KiB
C++
566 lines
15 KiB
C++
//
|
|
// 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 <InitGuid.h>
|
|
#include "Guids.h"
|
|
|
|
#include <shfusion.h>
|
|
|
|
#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(??).
|
|
//
|