Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

565 lines
15 KiB

  1. //
  2. // Copyright 2001 - Microsoft Corporation
  3. //
  4. // Created By:
  5. // Geoff Pease (GPease) 23-JAN-2001
  6. //
  7. // Maintained By:
  8. // Geoff Pease (GPease) 23-JAN-2001
  9. //
  10. // Notes:
  11. // If ENTRY_PREFIX is defined, this indicates that your are trying to
  12. // included proxy/stub code into the DLL that is generated by the
  13. // MIDL compiler.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include "pch.h"
  17. #include <InitGuid.h>
  18. #include "Guids.h"
  19. #include <shfusion.h>
  20. #include "DocProp.h"
  21. #include "DefProp.h"
  22. #include "PropertyCacheItem.h"
  23. #include "IEditVariantsInPlace.h"
  24. #include "EditTypeItem.h"
  25. #include "MLEditTypeItem.h"
  26. #include "DropListTypeItem.h"
  27. #include "CalendarTypeItem.h"
  28. #pragma hdrstop
  29. DEFINE_MODULE("DOCPROP3")
  30. //
  31. // Classes in this Component
  32. //
  33. // This table is used to create the objects supported in this DLL. It also is
  34. // used to map a name with a particular CLSID. HrCoCreateInternalInstance() uses
  35. // this table to shortcut COM.
  36. //
  37. // CreateInstance CLSID User Friendly Name Apartment Model
  38. BEGIN_CLASSTABLE
  39. DEFINE_CLASS( CDocPropShExt::CreateInstance , CLSID_DocPropShellExtension , "Microsoft DocProp Shell Ext" , "Apartment" )
  40. DEFINE_CLASS( CEditTypeItem::CreateInstance , CLSID_DocPropEditBoxControl , "Microsoft DocProp Inplace Edit Box Control" , "Apartment" )
  41. DEFINE_CLASS( CMLEditTypeItem::CreateInstance , CLSID_DocPropMLEditBoxControl , "Microsoft DocProp Inplace ML Edit Box Control" , "Apartment" )
  42. DEFINE_CLASS( CDropListTypeItem::CreateInstance , CLSID_DocPropDropListComboControl , "Microsoft DocProp Inplace Droplist Combo Control" , "Apartment" )
  43. DEFINE_CLASS( CCalendarTypeItem::CreateInstance , CLSID_DocPropCalendarControl , "Microsoft DocProp Inplace Calendar Control" , "Apartment" )
  44. DEFINE_CLASS( CEditTypeItem::CreateInstance , CLSID_DocPropTimeControl , "Microsoft DocProp Inplace Time Control" , "Apartment" )
  45. END_CLASSTABLE
  46. //
  47. // DLL Globals
  48. //
  49. HINSTANCE g_hInstance = NULL;
  50. LONG g_cObjects = 0;
  51. LONG g_cLock = 0;
  52. TCHAR g_szDllFilename[ MAX_PATH ] = { 0 };
  53. LPVOID g_GlobalMemoryList = NULL; // Global memory tracking list
  54. #if defined( ENTRY_PREFIX )
  55. extern "C"
  56. {
  57. extern HINSTANCE hProxyDll;
  58. }
  59. #endif
  60. //
  61. // Macros to generate RPC entry points
  62. //
  63. #define __rpc_macro_expand2(a, b) a##b
  64. #define __rpc_macro_expand(a, b) __rpc_macro_expand2(a,b)
  65. #if !defined(NO_DLL_MAIN) || defined(ENTRY_PREFIX) || defined(DEBUG)
  66. //
  67. // Description:
  68. // Dll entry point.
  69. //
  70. BOOL WINAPI
  71. DllMain(
  72. HINSTANCE hInstIn, // DLL instance
  73. ULONG ulReasonIn, // DLL reason code for entrance.
  74. LPVOID // lpReservedIn
  75. )
  76. {
  77. //
  78. // KB: NO_THREAD_OPTIMIZATIONS gpease 19-OCT-1999
  79. //
  80. // By not defining this you can prvent the linker
  81. // from calling you DllEntry for every new thread.
  82. // This makes creating new thread significantly
  83. // faster if every DLL in a process does it.
  84. // Unfortunately, not all DLLs do this.
  85. //
  86. // In CHKed/DEBUG, we keep this on for memory
  87. // tracking.
  88. //
  89. #if defined( DEBUG )
  90. #define NO_THREAD_OPTIMIZATIONS
  91. #endif // DEBUG
  92. #if defined(NO_THREAD_OPTIMIZATIONS)
  93. switch( ulReasonIn )
  94. {
  95. case DLL_PROCESS_ATTACH:
  96. {
  97. SHFusionInitializeFromModule( hInstIn );
  98. #if defined(USE_WMI_TRACING)
  99. TraceInitializeProcess( g_rgTraceControlGuidList,
  100. ARRAYSIZE( g_rgTraceControlGuidList )
  101. );
  102. #else
  103. TraceInitializeProcess();
  104. #endif
  105. TraceCreateMemoryList( g_GlobalMemoryList );
  106. TraceMemoryDelete( g_GlobalMemoryList, FALSE ); // can't track this list.
  107. #if defined( DEBUG )
  108. TraceFunc( "" );
  109. TraceMessage( TEXT(__FILE__),
  110. __LINE__,
  111. __MODULE__,
  112. mtfDLL,
  113. TEXT("DLL: DLL_PROCESS_ATTACH - ThreadID = %#x"),
  114. GetCurrentThreadId( )
  115. );
  116. FRETURN( TRUE );
  117. #endif // DEBUG
  118. g_hInstance = (HINSTANCE) hInstIn;
  119. #if defined( ENTRY_PREFIX )
  120. hProxyDll = g_hInstance;
  121. #endif
  122. GetModuleFileName( g_hInstance, g_szDllFilename, MAX_PATH );
  123. break;
  124. }
  125. case DLL_PROCESS_DETACH:
  126. {
  127. #if defined( DEBUG )
  128. TraceFunc( "" );
  129. TraceMessage( TEXT(__FILE__),
  130. __LINE__,
  131. __MODULE__,
  132. mtfDLL,
  133. TEXT("DLL: DLL_PROCESS_DETACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"),
  134. GetCurrentThreadId( ),
  135. g_cLock,
  136. g_cObjects
  137. );
  138. FRETURN( TRUE );
  139. #endif // DEBUG
  140. TraceMemoryAddAddress( g_GlobalMemoryList );
  141. TraceTerminateMemoryList( g_GlobalMemoryList );
  142. #if defined(USE_WMI_TRACING)
  143. TraceTerminateProcess( g_rgTraceControlGuidList,
  144. ARRAYSIZE( g_rgTraceControlGuidList )
  145. );
  146. #else
  147. TraceTerminateProcess();
  148. #endif
  149. SHFusionUninitialize();
  150. break;
  151. }
  152. case DLL_THREAD_ATTACH:
  153. {
  154. TraceInitializeThread( NULL );
  155. #if defined( DEBUG )
  156. TraceMessage( TEXT(__FILE__),
  157. __LINE__,
  158. __MODULE__,
  159. mtfDLL,
  160. TEXT("The thread %#x has started."),
  161. GetCurrentThreadId( ) );
  162. TraceFunc( "" );
  163. TraceMessage( TEXT(__FILE__),
  164. __LINE__,
  165. __MODULE__,
  166. mtfDLL,
  167. TEXT("DLL: DLL_THREAD_ATTACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"),
  168. GetCurrentThreadId( ),
  169. g_cLock,
  170. g_cObjects
  171. );
  172. FRETURN( TRUE );
  173. #endif // DEBUG
  174. break;
  175. }
  176. case DLL_THREAD_DETACH:
  177. {
  178. #if defined( DEBUG )
  179. TraceFunc( "" );
  180. TraceMessage( TEXT(__FILE__),
  181. __LINE__,
  182. __MODULE__,
  183. mtfDLL,
  184. TEXT("DLL: DLL_THREAD_DETACH - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"),
  185. GetCurrentThreadId( ),
  186. g_cLock,
  187. g_cObjects
  188. );
  189. FRETURN( TRUE );
  190. #endif // DEBUG
  191. TraceTerminateThread( );;
  192. break;
  193. }
  194. default:
  195. {
  196. #if defined( DEBUG )
  197. TraceFunc( "" );
  198. TraceMessage( TEXT(__FILE__),
  199. __LINE__,
  200. __MODULE__,
  201. mtfDLL,
  202. TEXT("DLL: UNKNOWN ENTRANCE REASON - ThreadID = %#x [ g_cLock=%u, g_cObjects=%u ]"),
  203. GetCurrentThreadId( ),
  204. g_cLock,
  205. g_cObjects
  206. );
  207. FRETURN( TRUE );
  208. #endif // DEBUG
  209. break;
  210. }
  211. }
  212. return TRUE;
  213. #else // !NO_THREAD_OPTIMIZATIONS
  214. Assert( ulReasonIn == DLL_PROCESS_ATTACH || ulReasonIn == DLL_PROCESS_DETACH );
  215. if ( DLL_PROCESS_ATTACH == ulReasonIn )
  216. {
  217. SHFusionInitializeFromModule( hInstIn );
  218. g_hInstance = (HINSTANCE) hInstIn;
  219. #ifdef ENTRY_PREFIX
  220. hProxyDll = g_hInstance;
  221. #endif
  222. #ifdef DEBUG
  223. #ifdef USE_WMI_TRACING
  224. TraceInitializeProcess( g_rgTraceControlGuidList,
  225. ARRAYSIZE( g_rgTraceControlGuidList )
  226. );
  227. #else
  228. TraceInitializeProcess();
  229. #endif USE_WMI_TRACING
  230. #endif DEBUG
  231. GetModuleFileName( g_hInstance, g_szDllFilename, MAX_PATH );
  232. BOOL fResult = DisableThreadLibraryCalls( g_hInstance );
  233. AssertMsg( fResult, "*ERROR* DisableThreadLibraryCalls( ) failed." );
  234. }
  235. else
  236. {
  237. #ifdef DEBUG
  238. #ifdef USE_WMI_TRACING
  239. TraceTerminateProcess( g_rgTraceControlGuidList,
  240. ARRAYSIZE( g_rgTraceControlGuidList )
  241. );
  242. #else
  243. TraceTerminateProcess();
  244. #endif USE_WMI_TRACING
  245. #endif DEBUG
  246. SHFusionUninitialize();
  247. }
  248. return TRUE;
  249. #endif // NO_THREAD_OPTIMIZATIONS
  250. }
  251. #endif // !defined(NO_DLL_MAIN) && !defined(ENTRY_PREFIX) && !defined(DEBUG)
  252. //
  253. // Description:
  254. // OLE calls this to get the class factory from the DLL.
  255. //
  256. // Return Values:
  257. // S_OK
  258. // Success.
  259. //
  260. // any other HRESULT to indicate failure.
  261. //
  262. STDAPI
  263. DllGetClassObject(
  264. REFCLSID rclsidIn, // class ID of the object that the class factory should create.
  265. REFIID riidIn, // Interface of the class factory
  266. void** ppvOut // The interface pointer to the class factory.
  267. )
  268. {
  269. TraceFunc( "rclsidIn, riidIn, ppvOut" );
  270. if ( ppvOut == NULL )
  271. {
  272. HRETURN(E_POINTER);
  273. }
  274. LPCFACTORY lpClassFactory;
  275. HRESULT hr;
  276. int idx;
  277. hr = CLASS_E_CLASSNOTAVAILABLE;
  278. idx = 0;
  279. while( g_DllClasses[ idx ].rclsid )
  280. {
  281. if ( *g_DllClasses[ idx ].rclsid == rclsidIn )
  282. {
  283. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, L"rclsidIn = %s", g_DllClasses[ idx ].pszName );
  284. hr = S_OK;
  285. break;
  286. }
  287. idx++;
  288. }
  289. if ( hr == CLASS_E_CLASSNOTAVAILABLE )
  290. {
  291. TraceMsgGUID( mtfFUNC, "rclsidIn = ", rclsidIn );
  292. #if defined( ENTRY_PREFIX )
  293. //
  294. // See if the MIDL generated code can create it.
  295. //
  296. hr = STHR( __rpc_macro_expand( ENTRY_PREFIX, DllGetClassObject )( rclsidIn, riidIn, ppvOut ) );
  297. #endif // defined( ENTRY_PREFIX )
  298. goto Cleanup;
  299. }
  300. Assert( g_DllClasses[ idx ].pfnCreateInstance != NULL );
  301. lpClassFactory = new CFactory;
  302. if ( lpClassFactory == NULL )
  303. {
  304. hr = E_OUTOFMEMORY;
  305. goto Cleanup;
  306. }
  307. hr = THR( lpClassFactory->Init( g_DllClasses[ idx ].pfnCreateInstance ) );
  308. if ( FAILED( hr ) )
  309. {
  310. TraceDo( lpClassFactory->Release( ) );
  311. goto Cleanup;
  312. }
  313. // Can't safe type.
  314. hr = lpClassFactory->QueryInterface( riidIn, ppvOut );
  315. //
  316. // Release the created instance to counter the AddRef( ) in Init( ).
  317. //
  318. ((IUnknown *) lpClassFactory )->Release( );
  319. Cleanup:
  320. HRETURN(hr);
  321. }
  322. //
  323. // Description:
  324. // OLE's register entry point.
  325. //
  326. // Return Values:
  327. // S_OK
  328. // Success.
  329. //
  330. // any other HRESULT.
  331. //
  332. STDAPI
  333. DllRegisterServer( void )
  334. {
  335. HRESULT hr;
  336. TraceFunc( "" );
  337. hr = THR( HrRegisterDll( TRUE ) );
  338. #if defined( ENTRY_PREFIX )
  339. if ( SUCCEEDED( hr ) )
  340. {
  341. hr = THR( __rpc_macro_expand( ENTRY_PREFIX, DllRegisterServer )( ) );
  342. }
  343. #endif // defined( ENTRY_PREFIX )
  344. if ( SUCCEEDED( hr ) )
  345. {
  346. hr = CDocPropShExt::RegisterShellExtensions( TRUE );
  347. }
  348. HRETURN(hr);
  349. }
  350. //
  351. // Description:
  352. // OLE's unregister entry point.
  353. //
  354. // Return Values:
  355. // S_OK
  356. // Success.
  357. //
  358. // any other HRESULT
  359. //
  360. STDAPI
  361. DllUnregisterServer( void )
  362. {
  363. TraceFunc( "" );
  364. HRESULT hr;
  365. hr = THR( HrRegisterDll( FALSE ) );
  366. #if defined( ENTRY_PREFIX )
  367. if ( SUCCEEDED( hr ) )
  368. {
  369. hr = THR( __rpc_macro_expand( ENTRY_PREFIX, DllUnregisterServer )( ) );
  370. }
  371. #endif // defined( ENTRY_PREFIX )
  372. if ( SUCCEEDED( hr ) )
  373. {
  374. hr = CDocPropShExt::RegisterShellExtensions( TRUE );
  375. }
  376. HRETURN( hr );
  377. }
  378. //
  379. // Description:
  380. // OLE calls this entry point to see if it can unload the DLL.
  381. //
  382. // Return Values:
  383. // S_OK
  384. // Can unload the DLL.
  385. //
  386. // S_FALSE
  387. // Can NOT unload the DLL.
  388. //
  389. STDAPI
  390. DllCanUnloadNow( void )
  391. {
  392. TraceFunc( "" );
  393. HRESULT hr = S_OK;
  394. if ( g_cLock || g_cObjects )
  395. {
  396. TraceMsg( mtfDLL, "DLL: Can't unload - g_cLock=%u, g_cObjects=%u", g_cLock, g_cObjects );
  397. hr = S_FALSE;
  398. }
  399. #if defined( ENTRY_PREFIX )
  400. else
  401. {
  402. //
  403. // Check with the MIDL generated proxy/stubs.
  404. //
  405. hr = STHR( __rpc_macro_expand( ENTRY_PREFIX, DllCanUnloadNow )( ) );
  406. }
  407. #endif
  408. HRETURN(hr);
  409. }
  410. //
  411. // Description:
  412. // Mimic CoCreateInstance( ) except that it looks into the DLL table
  413. // to see if we can shortcut the CoCreate with a simple CreateInstance
  414. // call.
  415. //
  416. // Return Values:
  417. // S_OK
  418. // Success.
  419. //
  420. // E_OUTOFMEMORY
  421. // Out of memory.
  422. //
  423. // other HRESULT values
  424. //
  425. HRESULT
  426. HrCoCreateInternalInstance(
  427. REFCLSID rclsidIn, // Class identifier (CLSID) of the object
  428. LPUNKNOWN pUnkOuterIn, // Pointer to controlling IUnknown
  429. DWORD dwClsContextIn, // Context for running executable code
  430. REFIID riidIn, // Reference to the identifier of the interface
  431. LPVOID * ppvOut // Address of output variable that receives
  432. )
  433. {
  434. TraceFunc( "" );
  435. Assert( ppvOut != NULL );
  436. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  437. //
  438. // Limit simple CoCreate( ) only works to INPROC and non-aggregatable objects.
  439. //
  440. if ( ( dwClsContextIn & CLSCTX_INPROC_HANDLER ) // inproc only
  441. && ( NULL == pUnkOuterIn ) // no aggregation
  442. )
  443. {
  444. int idx;
  445. //
  446. // Try to find the class in our DLL table.
  447. //
  448. for( idx = 0; g_DllClasses[ idx ].rclsid != NULL; idx++ )
  449. {
  450. if ( *g_DllClasses[ idx ].rclsid == rclsidIn )
  451. {
  452. LPUNKNOWN punk;
  453. Assert( g_DllClasses[ idx ].pfnCreateInstance != NULL );
  454. hr = THR( g_DllClasses[ idx ].pfnCreateInstance( &punk ) );
  455. if ( SUCCEEDED( hr ) )
  456. {
  457. // Can't safe type.
  458. hr = THR( punk->QueryInterface( riidIn, ppvOut ) );
  459. punk->Release( );
  460. }
  461. break; // bail loop
  462. }
  463. }
  464. }
  465. //
  466. // If not found or asking for something we do not support,
  467. // use the COM version.
  468. //
  469. if ( hr == CLASS_E_CLASSNOTAVAILABLE )
  470. {
  471. //
  472. // Try it the old fashion way...
  473. //
  474. hr = THR( CoCreateInstance( rclsidIn, pUnkOuterIn, dwClsContextIn, riidIn, ppvOut ) );
  475. }
  476. HRETURN( hr );
  477. }
  478. //
  479. // TODO: gpease 27-NOV-1999
  480. // Whilest parrusing the around the MIDL SDK, I foud that
  481. // RPC creates the same type of class table we do. Maybe
  482. // we can leverage the MIDL code to create our objects(??).
  483. //