psxa.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 8k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // PSXA.C   --   PropSheetExtArray implementation
  4. //
  5. // Manipulates a group of property sheet extension objects (see PSXA.H)
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #include "shellprv.h"
  9. #pragma  hdrstop
  10. //-----------------------------------------------------------------------------
  11. //
  12. // PSXA
  13. //
  14. // header for an array of IShellPropSheetExt interface pointers
  15. //
  16. //-----------------------------------------------------------------------------
  17. typedef struct
  18. {
  19.     UINT count, alloc;
  20.     IShellPropSheetExt *interfaces[ 0 ];
  21. } PSXA;
  22. //-----------------------------------------------------------------------------
  23. //
  24. // _PSXACALLINFO
  25. //
  26. // used to forward LPFNADDPROPSHEETPAGE calls with added error checking
  27. //
  28. //-----------------------------------------------------------------------------
  29. typedef struct
  30. {
  31.     LPFNADDPROPSHEETPAGE pfn;
  32.     LPARAM lparam;
  33.     UINT count;
  34.     BOOL allowmulti;
  35.     BOOL alreadycalled;
  36. } _PSXACALLINFO;
  37. //-----------------------------------------------------------------------------
  38. //
  39. // _PsxaCallOwner
  40. //
  41. // forwards an LPFNADDPROPSHEETPAGE call with added error checking
  42. //
  43. //-----------------------------------------------------------------------------
  44. BOOL CALLBACK _PsxaCallOwner( HPROPSHEETPAGE hpage, LPARAM lparam )
  45. {
  46.     _PSXACALLINFO *callinfo = (_PSXACALLINFO *)lparam;
  47.     if( callinfo )
  48.     {
  49.         if( !callinfo->allowmulti && callinfo->alreadycalled )
  50.             return FALSE;
  51.         if( callinfo->pfn( hpage, callinfo->lparam ) )
  52.         {
  53.             callinfo->alreadycalled = TRUE;
  54.             callinfo->count++;
  55.             return TRUE;
  56.         }
  57.     }
  58.     return FALSE;
  59. }
  60. //-----------------------------------------------------------------------------
  61. //
  62. // InitPropSheetExt
  63. //
  64. // creates an instance of the property sheet extension referred to by szCLSID
  65. // initializes it via the IShellExtInit (if IShellExtInit is supported)
  66. //
  67. //-----------------------------------------------------------------------------
  68. BOOL InitPropSheetExt(IShellPropSheetExt **ppspx, LPCTSTR pszCLSID, HKEY hKey, IDataObject *pDataObj)
  69. {
  70.     if (SUCCEEDED(SHExtCoCreateInstance( pszCLSID, NULL, NULL, &IID_IShellPropSheetExt, ppspx)))
  71.     {
  72.         IShellExtInit *psxi;
  73.         if( SUCCEEDED( (*ppspx)->lpVtbl->QueryInterface( *ppspx,
  74.             &IID_IShellExtInit, &psxi ) ) )
  75.         {
  76.             if( !SUCCEEDED( psxi->lpVtbl->Initialize( psxi, NULL, pDataObj, hKey ) ) )
  77.             {
  78.                 (*ppspx)->lpVtbl->Release( *ppspx );
  79.                 *ppspx = NULL;
  80.             }
  81.             psxi->lpVtbl->Release( psxi );
  82.         }
  83.     }
  84.     return BOOLFROMPTR(*ppspx);
  85. }
  86. //-----------------------------------------------------------------------------
  87. //
  88. // SHCreatePropSheetExtArray
  89. //
  90. // uses hKey and pszSubKey to find property sheet handlers in the registry
  91. // loads up to max_iface IShellPropSheetExt interfaces (so I'm lazy...)
  92. // returns a handle (pointer) to a newly allocated PSXA
  93. //
  94. //-----------------------------------------------------------------------------
  95. HPSXA SHCreatePropSheetExtArrayEx( HKEY hKey, LPCTSTR pszLocation, UINT max_iface, IDataObject * pDataObj)
  96. {
  97.     BOOL success = FALSE;
  98.     PSXA *psxa =
  99.         LocalAlloc( LPTR, SIZEOF( PSXA ) +
  100.         SIZEOF( IShellPropSheetExt * ) * max_iface );
  101.     if( psxa )
  102.     {
  103.         IShellPropSheetExt **spsx = psxa->interfaces;
  104.         HKEY hkLocation;
  105.         UINT i;
  106.         psxa->count = 0;
  107.         psxa->alloc = max_iface;
  108.         for( i = 0; i < psxa->alloc; i++, spsx++ )
  109.             *spsx = NULL;
  110.         if( RegOpenKey( hKey, pszLocation, &hkLocation ) == ERROR_SUCCESS )
  111.         {
  112.             HKEY hkHandlers;
  113.             if( RegOpenKey( hkLocation, c_szPropSheet, &hkHandlers ) ==
  114.                 ERROR_SUCCESS )
  115.             {
  116.                 TCHAR szChild[ 64 ]; // yes, this is totally arbitrary...
  117.                 // fill until there's no room or no more subkeys to get
  118.                 for( i = 0;
  119.                     ( psxa->count < psxa->alloc ) &&
  120.                     ( RegEnumKey( hkHandlers, (int)i, szChild,
  121.                     ARRAYSIZE( szChild ) ) == ERROR_SUCCESS );
  122.                     i++ )
  123.                 {
  124.                     TCHAR szCLSID[ MAX_PATH ];
  125.                     LONG len_szCLSID = ARRAYSIZE( szCLSID );
  126.                     if( SHRegQueryValue( hkHandlers, szChild, szCLSID,
  127.                         &len_szCLSID ) == ERROR_SUCCESS )
  128.                     {
  129.                         if( InitPropSheetExt( &psxa->interfaces[ psxa->count ],
  130.                             szCLSID, hKey, pDataObj) )
  131.                         {
  132.                             psxa->count++;
  133.                         }
  134.                     }
  135.                 }
  136.                 RegCloseKey( hkHandlers );
  137.                 success = TRUE;
  138.             }
  139.             RegCloseKey( hkLocation );
  140.         }
  141.     }
  142.     if( !success )
  143.     {
  144.         SHDestroyPropSheetExtArray( (HPSXA)psxa );
  145.         psxa = NULL;
  146.     }
  147.     return (HPSXA)psxa;
  148. }
  149. HPSXA SHCreatePropSheetExtArray( HKEY hKey, LPCTSTR pszLocation, UINT max_iface )
  150. {
  151.     return SHCreatePropSheetExtArrayEx( hKey, pszLocation, max_iface, NULL );
  152. }
  153. //-----------------------------------------------------------------------------
  154. //
  155. // SHDestroyPropSheetExtArray
  156. //
  157. // releases interfaces in a PSXA and frees the memory it occupies
  158. //
  159. //-----------------------------------------------------------------------------
  160. void SHDestroyPropSheetExtArray( HPSXA hpsxa )
  161. {
  162.     PSXA *psxa = (PSXA *)hpsxa;
  163.     IShellPropSheetExt **spsx = psxa->interfaces;
  164.     UINT i;
  165.     // release the interfaces
  166.     for( i = 0; i < psxa->count; i++, spsx++ )
  167.         (*spsx)->lpVtbl->Release( *spsx );
  168.     LocalFree( psxa );
  169. }
  170. //-----------------------------------------------------------------------------
  171. //
  172. // SHAddFromPropSheetExtArray
  173. //
  174. // asks each interface in a PSXA to add pages for a proprty sheet
  175. // returns the number of pages actually added
  176. //
  177. //-----------------------------------------------------------------------------
  178. UINT SHAddFromPropSheetExtArray( HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam )
  179. {
  180.     PSXA *psxa = (PSXA *)hpsxa;
  181.     IShellPropSheetExt **spsx = psxa->interfaces;
  182.     _PSXACALLINFO callinfo = { lpfnAddPage, lParam, 0, TRUE, FALSE };
  183.     UINT i;
  184.     for( i = 0; i < psxa->count; i++, spsx++ )
  185.         (*spsx)->lpVtbl->AddPages( *spsx, _PsxaCallOwner, (LPARAM)&callinfo );
  186.     return callinfo.count;
  187. }
  188. //-----------------------------------------------------------------------------
  189. //
  190. // SHReplaceFromPropSheetExtArray
  191. //
  192. // asks each interface in a PSXA to replace a page in a prop sheet
  193. // each interface is only allowed to add up to one replacement
  194. // returns the total number of replacements added
  195. //
  196. //-----------------------------------------------------------------------------
  197. UINT SHReplaceFromPropSheetExtArray(HPSXA hpsxa, UINT uPageID,
  198.                                     LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
  199. {
  200.     PSXA *psxa = (PSXA *)hpsxa;
  201.     IShellPropSheetExt **spsx = psxa->interfaces;
  202.     _PSXACALLINFO callinfo = { lpfnReplaceWith, lParam, 0, FALSE, FALSE };
  203.     UINT i;
  204.     for( i = 0; i < psxa->count; i++, spsx++ )
  205.     {
  206.         // reset the call flag so that each provider gets a chance
  207.         callinfo.alreadycalled = FALSE;
  208.         if ((*spsx)->lpVtbl->ReplacePage)
  209.             (*spsx)->lpVtbl->ReplacePage( *spsx, uPageID, _PsxaCallOwner, (LPARAM)&callinfo );
  210.     }
  211.     return callinfo.count;
  212. }