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.

858 lines
17 KiB

  1. //
  2. // Copyright 2001 - Microsoft Corporation
  3. //
  4. //
  5. // Created By:
  6. // Geoff Pease (GPease) 23-JAN-2001
  7. //
  8. // Maintained By:
  9. // Geoff Pease (GPease) 23-JAN-2001
  10. //
  11. #include "pch.h"
  12. #include "DocProp.h"
  13. #include "DefProp.h"
  14. #include "PropertyCacheItem.h"
  15. #include "PropertyCache.h"
  16. #include "SimpleDlg.h"
  17. #include "shutils.h"
  18. #include "WMUser.h"
  19. #include "PropVar.h"
  20. #pragma hdrstop
  21. DEFINE_THISCLASS( "CSimpleDlg" )
  22. //
  23. // Globals
  24. //
  25. #define SUMMARYPROP(s) { &FMTID_SummaryInformation, PIDSI_##s, IDC_##s }
  26. #define DOCSUMMARYPROP(s) { &FMTID_DocSummaryInformation, PIDDSI_##s, IDC_##s }
  27. const struct
  28. {
  29. const FMTID *pFmtId;
  30. PROPID propid;
  31. UINT idc;
  32. // could add VARTYPE if we did anything other than strings
  33. } g_rgBasicProps[] = {
  34. SUMMARYPROP(TITLE)
  35. , SUMMARYPROP(SUBJECT)
  36. , SUMMARYPROP(AUTHOR)
  37. , SUMMARYPROP(KEYWORDS)
  38. , SUMMARYPROP(COMMENTS)
  39. , DOCSUMMARYPROP(CATEGORY)
  40. };
  41. // ************************************************************************
  42. //
  43. // Constructor / Destructor
  44. //
  45. // ************************************************************************
  46. //
  47. //
  48. //
  49. HRESULT
  50. CSimpleDlg::CreateInstance(
  51. CSimpleDlg ** pSimDlgOut
  52. , HWND hwndParentIn
  53. , BOOL fMultipleIn
  54. )
  55. {
  56. TraceFunc( "" );
  57. HRESULT hr;
  58. Assert( NULL != pSimDlgOut );
  59. CSimpleDlg * pthis = new CSimpleDlg;
  60. if ( NULL != pthis )
  61. {
  62. hr = THR( pthis->Init( hwndParentIn, fMultipleIn ) );
  63. if ( SUCCEEDED( hr ) )
  64. {
  65. *pSimDlgOut = pthis;
  66. (*pSimDlgOut)->AddRef( );
  67. }
  68. pthis->Release( );
  69. }
  70. else
  71. {
  72. hr = E_OUTOFMEMORY;
  73. }
  74. HRETURN( hr );
  75. }
  76. //
  77. //
  78. //
  79. CSimpleDlg::CSimpleDlg( void )
  80. : _cRef( 1 )
  81. {
  82. TraceFunc( "" );
  83. Assert( 1 == _cRef );
  84. Assert( NULL == _hwndParent );
  85. Assert( NULL == _hdlg );
  86. Assert( FALSE == _fMultipleSources );
  87. Assert( FALSE == _fNoProperties );
  88. InterlockedIncrement( &g_cObjects );
  89. TraceFuncExit();
  90. }
  91. //
  92. //
  93. //
  94. HRESULT
  95. CSimpleDlg::Init(
  96. HWND hwndParentIn
  97. , BOOL fMultipleIn
  98. )
  99. {
  100. TraceFunc( "" );
  101. HRESULT hr = S_OK;
  102. _hwndParent = hwndParentIn;
  103. _fMultipleSources = fMultipleIn;
  104. // IUnknown stuff
  105. Assert( _cRef == 1 );
  106. //
  107. // Create the dialog
  108. //
  109. _hdlg = CreateDialogParam( g_hInstance
  110. , MAKEINTRESOURCE(IDD_SIMPLEVIEW)
  111. , _hwndParent
  112. , DlgProc
  113. , (LPARAM) this
  114. );
  115. if ( NULL == _hdlg )
  116. goto ErrorGLE;
  117. Cleanup:
  118. HRETURN( hr );
  119. ErrorGLE:
  120. {
  121. DWORD dwErr = TW32( GetLastError( ) );
  122. hr = HRESULT_FROM_WIN32( dwErr );
  123. }
  124. goto Cleanup;
  125. }
  126. //
  127. //
  128. //
  129. CSimpleDlg::~CSimpleDlg( )
  130. {
  131. TraceFunc( "" );
  132. if ( NULL != _hdlg )
  133. {
  134. DestroyWindow( _hdlg );
  135. }
  136. Assert( 0 != g_cObjects );
  137. InterlockedDecrement( &g_cObjects );
  138. TraceFuncExit();
  139. }
  140. // ************************************************************************
  141. //
  142. // IUnknown
  143. //
  144. // ************************************************************************
  145. //
  146. //
  147. //
  148. STDMETHODIMP
  149. CSimpleDlg::QueryInterface(
  150. REFIID riid,
  151. LPVOID *ppv
  152. )
  153. {
  154. TraceQIFunc( riid, ppv );
  155. HRESULT hr = E_NOINTERFACE;
  156. if ( IsEqualIID( riid, __uuidof(IUnknown) ) )
  157. {
  158. *ppv = static_cast< IUnknown * >( this );
  159. hr = S_OK;
  160. }
  161. #if 0
  162. else if ( IsEqualIID( riid, __uuidof(IShellExtInit) ) )
  163. {
  164. *ppv = TraceInterface( __THISCLASS__, IShellExtInit, this, 0 );
  165. hr = S_OK;
  166. }
  167. #endif
  168. if ( SUCCEEDED( hr ) )
  169. {
  170. ((IUnknown*) *ppv)->AddRef( );
  171. }
  172. QIRETURN( hr, riid );
  173. }
  174. //
  175. //
  176. //
  177. STDMETHODIMP_(ULONG)
  178. CSimpleDlg::AddRef( void )
  179. {
  180. TraceFunc( "[IUnknown]" );
  181. _cRef ++; // apartment
  182. RETURN( _cRef );
  183. }
  184. //
  185. //
  186. //
  187. STDMETHODIMP_(ULONG)
  188. CSimpleDlg::Release( void )
  189. {
  190. TraceFunc( "[IUnknown]" );
  191. _cRef --; // apartment
  192. if ( 0 != _cRef )
  193. RETURN( _cRef );
  194. delete this;
  195. RETURN( 0 );
  196. }
  197. // ***************************************************************************
  198. //
  199. // Dialog Proc and Property Sheet Callback
  200. //
  201. // ***************************************************************************
  202. //
  203. //
  204. //
  205. INT_PTR CALLBACK
  206. CSimpleDlg::DlgProc(
  207. HWND hDlgIn
  208. , UINT uMsgIn
  209. , WPARAM wParam
  210. , LPARAM lParam
  211. )
  212. {
  213. // Don't do TraceFunc because every mouse movement will cause this function to be called.
  214. WndMsg( hDlgIn, uMsgIn, wParam, lParam );
  215. LRESULT lr = FALSE;
  216. CSimpleDlg * pPage = (CSimpleDlg *) GetWindowLongPtr( hDlgIn, DWLP_USER );
  217. if ( uMsgIn == WM_INITDIALOG )
  218. {
  219. SetWindowLongPtr( hDlgIn, DWLP_USER, lParam );
  220. pPage = (CSimpleDlg *) lParam ;
  221. pPage->_hdlg = hDlgIn;
  222. }
  223. if ( pPage != NULL )
  224. {
  225. Assert( hDlgIn == pPage->_hdlg );
  226. switch( uMsgIn )
  227. {
  228. case WM_INITDIALOG:
  229. lr = pPage->OnInitDialog( );
  230. break;
  231. case WM_COMMAND:
  232. lr = pPage->OnCommand( HIWORD(wParam), LOWORD(wParam), lParam );
  233. break;
  234. case WM_NOTIFY:
  235. lr = pPage->OnNotify( (int) wParam, (LPNMHDR) lParam );
  236. break;
  237. case WM_DESTROY:
  238. SetWindowLongPtr( hDlgIn, DWLP_USER, NULL );
  239. lr = pPage->OnDestroy( );
  240. break;
  241. case WM_HELP:
  242. lr = pPage->OnHelp( (LPHELPINFO) lParam );
  243. break;
  244. case WM_CONTEXTMENU:
  245. lr = pPage->OnContextMenu( (HWND) wParam, LOWORD(lParam), HIWORD(lParam) );
  246. break;
  247. }
  248. }
  249. return lr;
  250. }
  251. // ***************************************************************************
  252. //
  253. // Private methods
  254. //
  255. // ***************************************************************************
  256. //
  257. // WM_INITDIALOG handler
  258. //
  259. LRESULT
  260. CSimpleDlg::OnInitDialog( void )
  261. {
  262. TraceFunc( "" );
  263. LRESULT lr = TRUE; // set focus
  264. Assert( NULL != _hdlg ); // this should have been initialized in the DlgProc.
  265. RETURN( lr );
  266. }
  267. //
  268. // WM_COMMAND handler
  269. //
  270. LRESULT
  271. CSimpleDlg::OnCommand(
  272. WORD wCodeIn
  273. , WORD wCtlIn
  274. , LPARAM lParam
  275. )
  276. {
  277. TraceFunc( "" );
  278. LRESULT lr = FALSE;
  279. switch( wCtlIn )
  280. {
  281. case IDC_ADVANCED:
  282. if ( BN_CLICKED == wCodeIn )
  283. {
  284. THR( (HRESULT) SendMessage( _hwndParent, WMU_TOGGLE, 0, 0 ) );
  285. }
  286. break;
  287. case IDC_TITLE:
  288. case IDC_SUBJECT:
  289. case IDC_AUTHOR:
  290. case IDC_CATEGORY:
  291. case IDC_KEYWORDS:
  292. case IDC_COMMENTS:
  293. if ( EN_CHANGE == wCodeIn )
  294. {
  295. PropSheet_Changed( GetParent( _hwndParent ), _hwndParent );
  296. }
  297. else if ( EN_KILLFOCUS == wCodeIn )
  298. {
  299. STHR( PersistControlInProperty( wCtlIn ) );
  300. }
  301. break;
  302. }
  303. RETURN( lr );
  304. }
  305. //
  306. // WM_NOTIFY handler
  307. //
  308. LRESULT
  309. CSimpleDlg::OnNotify(
  310. int iCtlIdIn
  311. , LPNMHDR pnmhIn
  312. )
  313. {
  314. TraceFunc( "" );
  315. LRESULT lr = FALSE;
  316. #if 0
  317. switch( pnmhIn->code )
  318. {
  319. default:
  320. break;
  321. }
  322. #endif
  323. RETURN( lr );
  324. }
  325. //
  326. // WM_DESTROY handler
  327. //
  328. LRESULT
  329. CSimpleDlg::OnDestroy( void )
  330. {
  331. TraceFunc( "" );
  332. LRESULT lr = FALSE;
  333. RETURN( lr );
  334. }
  335. //
  336. // Description:
  337. // Stores the "basic" properties into the prop variant.
  338. //
  339. // Return Values:
  340. // S_OK
  341. // Success!
  342. //
  343. // other HRESULTs.
  344. //
  345. HRESULT
  346. CSimpleDlg::PersistProperties( void )
  347. {
  348. TraceFunc( "" );
  349. HRESULT hr;
  350. ULONG idx;
  351. //
  352. // Loop the the properties updating the dialog as we go.
  353. //
  354. for ( idx = 0; idx < ARRAYSIZE(g_rgBasicProps); idx ++ )
  355. {
  356. hr = STHR( PersistControlInProperty( g_rgBasicProps[ idx ].idc ) );
  357. if ( FAILED( hr ) )
  358. goto Cleanup;
  359. }
  360. hr = S_OK;
  361. Cleanup:
  362. HRETURN( hr );
  363. }
  364. //
  365. // Description:
  366. // Stores the current value of a control into the property cache.
  367. //
  368. // Return Values:
  369. // S_OK
  370. // Success!
  371. //
  372. // S_FALSE
  373. // Nothing to save.
  374. //
  375. // E_FAIL
  376. // Property could not be persisted.
  377. //
  378. // E_OUTOFMEMORY
  379. // OutOfMemory
  380. //
  381. // other HRESULTs.
  382. //
  383. HRESULT
  384. CSimpleDlg::PersistControlInProperty(
  385. UINT uCtlIdIn
  386. )
  387. {
  388. TraceFunc( "" );
  389. HRESULT hr;
  390. int iLen;
  391. int iRet;
  392. HWND hwndCtl;
  393. UINT uCodePage;
  394. VARTYPE vt;
  395. CPropertyCacheItem * pItem;
  396. PROPVARIANT * ppropvar;
  397. LPWSTR pszBuf = NULL;
  398. hwndCtl = GetDlgItem( _hdlg, uCtlIdIn );
  399. if ( NULL == hwndCtl )
  400. goto ErrorPersistingValue;
  401. pItem = (CPropertyCacheItem *) GetWindowLongPtr( hwndCtl, GWLP_USERDATA );
  402. if ( NULL == pItem )
  403. {
  404. hr = S_FALSE;
  405. goto Cleanup;
  406. }
  407. hr = THR( pItem->GetCodePage( &uCodePage ) );
  408. if ( FAILED( hr ) )
  409. goto Cleanup;
  410. hr = THR( pItem->GetPropertyValue( &ppropvar ) );
  411. if ( FAILED( hr ) )
  412. goto Cleanup;
  413. switch ( ppropvar->vt )
  414. {
  415. case VT_EMPTY:
  416. case VT_NULL:
  417. {
  418. PropVariantInit( ppropvar );
  419. hr = THR( pItem->GetDefaultVarType( &vt ) );
  420. if ( FAILED( hr ) )
  421. goto Cleanup;
  422. }
  423. break;
  424. default:
  425. vt = ppropvar->vt;
  426. break;
  427. }
  428. iLen = GetWindowTextLength( hwndCtl );
  429. if ( iLen == 0 )
  430. {
  431. //
  432. // If nothing to get, then just clear the value and mark it dirty.
  433. //
  434. hr = THR( PropVariantClear( ppropvar ) );
  435. if ( FAILED( hr ) )
  436. goto Cleanup;
  437. hr = THR( pItem->MarkDirty( ) );
  438. goto Cleanup;
  439. }
  440. pszBuf = (LPWSTR) SysAllocStringLen( NULL, iLen );
  441. if ( NULL == pszBuf )
  442. goto OutOfMemory;
  443. iRet = GetWindowText( hwndCtl, pszBuf, iLen + 1 );
  444. Assert( iRet == iLen );
  445. hr = THR( PropVariantFromString( pszBuf, uCodePage, 0, vt, ppropvar ) );
  446. if ( FAILED( hr ) )
  447. goto Cleanup;
  448. hr = THR( pItem->MarkDirty( ) );
  449. if ( FAILED( hr ) )
  450. goto Cleanup;
  451. Cleanup:
  452. if ( NULL != pszBuf )
  453. {
  454. SysFreeString( pszBuf );
  455. }
  456. HRETURN( hr );
  457. OutOfMemory:
  458. hr = E_OUTOFMEMORY;
  459. goto Cleanup;
  460. ErrorPersistingValue:
  461. hr = THR( E_FAIL );
  462. goto Cleanup;
  463. }
  464. //
  465. // WM_HELP handler
  466. //
  467. LRESULT
  468. CSimpleDlg::OnHelp(
  469. LPHELPINFO pHelpInfoIn
  470. )
  471. {
  472. TraceFunc( "" );
  473. LRESULT lr = FALSE;
  474. THR( DoHelp( (HWND) pHelpInfoIn->hItemHandle, pHelpInfoIn->MousePos.x, pHelpInfoIn->MousePos.y, HELP_WM_HELP ) );
  475. RETURN( lr );
  476. }
  477. //
  478. // WM_CONTEXTMENU handler
  479. //
  480. LRESULT
  481. CSimpleDlg::OnContextMenu(
  482. HWND hwndIn
  483. , int iXIn
  484. , int iYIn
  485. )
  486. {
  487. TraceFunc( "" );
  488. LRESULT lr = FALSE;
  489. THR( DoHelp( hwndIn, iXIn, iYIn, HELP_CONTEXTMENU ) );
  490. RETURN( lr );
  491. }
  492. //
  493. // Description:
  494. // Handles locating the item within the list view and construct
  495. // a fake IDC to IDH to display the correct help text for the
  496. // item.
  497. //
  498. // Return Values:
  499. // S_OK
  500. // Success.
  501. //
  502. HRESULT
  503. CSimpleDlg::DoHelp(
  504. HWND hwndIn
  505. , int iXIn
  506. , int iYIn
  507. , UINT uCommandIn
  508. )
  509. {
  510. TraceFunc( "" );
  511. ULONG idx;
  512. HRESULT hr = S_OK;
  513. for ( idx = 0; idx < ARRAYSIZE(g_rgBasicProps); idx ++ )
  514. {
  515. HWND hwndCtl = GetDlgItem( _hdlg, g_rgBasicProps[ idx ].idc );
  516. AssertMsg( NULL != hwndCtl, "Missing control or table is out of date!" );
  517. if ( hwndCtl == hwndIn )
  518. {
  519. CPropertyCacheItem * pItem;
  520. pItem = (CPropertyCacheItem *) GetWindowLongPtr( hwndCtl, GWLP_USERDATA );
  521. if ( NULL != pItem )
  522. {
  523. LPCWSTR pszHelpFile; // don't free
  524. UINT uHelpId;
  525. DWORD mapIDStoIDH[ ] = { 0, 0, 0, 0 };
  526. hr = THR( pItem->GetPropertyHelpInfo( &pszHelpFile, &uHelpId ) );
  527. if ( FAILED( hr ) )
  528. goto Cleanup;
  529. mapIDStoIDH[ 0 ] = g_rgBasicProps[ idx ].idc;
  530. mapIDStoIDH[ 1 ] = uHelpId;
  531. TBOOL( WinHelp( hwndIn, pszHelpFile, uCommandIn, (DWORD_PTR)(LPSTR) mapIDStoIDH ) );
  532. }
  533. }
  534. }
  535. Cleanup:
  536. HRETURN( hr );
  537. }
  538. // ***************************************************************************
  539. //
  540. // Public methods
  541. //
  542. // ***************************************************************************
  543. //
  544. // Description:
  545. // Hides the dialog.
  546. //
  547. // Return Value:
  548. // S_OK
  549. // Success!
  550. //
  551. HRESULT
  552. CSimpleDlg::Hide( void )
  553. {
  554. TraceFunc( "" );
  555. HRESULT hr;
  556. ShowWindow( _hdlg, SW_HIDE );
  557. hr = S_OK;
  558. HRETURN( hr );
  559. }
  560. //
  561. // Description:
  562. // Shows the dialog.
  563. //
  564. // Return Values:
  565. // S_OK
  566. // Success!
  567. //
  568. // S_FALSE
  569. // Success, but there isn't anything useful to display to the user.
  570. // One might flip to the Advanced dialog if possible (and the user
  571. // didn't ask to go to the Simple dialog).
  572. //
  573. HRESULT
  574. CSimpleDlg::Show( void )
  575. {
  576. TraceFunc( "" );
  577. HRESULT hr = S_OK;
  578. ShowWindow( _hdlg, SW_SHOW );
  579. SetFocus( _hdlg );
  580. if ( _fNoProperties )
  581. {
  582. hr = S_FALSE;
  583. }
  584. HRETURN( hr );
  585. }
  586. //
  587. // Description:
  588. // Populates the properties of the dialog.
  589. //
  590. // Return Values:
  591. // S_OK
  592. // Success!
  593. //
  594. // E_INVALIDARG
  595. // ppcIn is NULL.
  596. //
  597. // other HRESULTs.
  598. //
  599. HRESULT
  600. CSimpleDlg::PopulateProperties(
  601. CPropertyCache * ppcIn
  602. , DWORD dwDocTypeIn
  603. , BOOL fMultipleIn
  604. )
  605. {
  606. TraceFunc( "" );
  607. HRESULT hr;
  608. ULONG idx;
  609. LPCWSTR pcszValue;
  610. CPropertyCacheItem * pItem;
  611. static const WCHAR s_cszNULL[] = L"";
  612. //
  613. // Check parameters
  614. //
  615. if ( NULL == ppcIn )
  616. goto InvalidArg;
  617. //
  618. // Loop the the properties updating the dialog as we go.
  619. //
  620. _fNoProperties = TRUE;
  621. for ( idx = 0; idx < ARRAYSIZE(g_rgBasicProps); idx ++ )
  622. {
  623. HWND hwndCtl = GetDlgItem( _hdlg, g_rgBasicProps[ idx ].idc );
  624. AssertMsg( NULL != hwndCtl, "Missing control or table is out of date!" );
  625. //
  626. // Search the property cache for the entry.
  627. //
  628. hr = STHR( ppcIn->FindItemEntry( g_rgBasicProps[ idx ].pFmtId
  629. , g_rgBasicProps[ idx ].propid
  630. , &pItem
  631. ) );
  632. if ( S_OK == hr )
  633. {
  634. int iImage;
  635. Assert ( NULL != pItem ); // paranoid
  636. //
  637. // Retrieve the string value.
  638. //
  639. hr = THR( pItem->GetPropertyStringValue( &pcszValue ) );
  640. if ( S_OK != hr )
  641. goto ControlFailure;
  642. if ( NULL == pcszValue )
  643. {
  644. pcszValue = s_cszNULL;
  645. }
  646. //
  647. // Update the control.
  648. //
  649. SetWindowText( hwndCtl, pcszValue );
  650. SetWindowLongPtr( hwndCtl, GWLP_USERDATA, (LPARAM) pItem );
  651. _fNoProperties = FALSE;
  652. //
  653. // If the property is read-only, change the edit control to match.
  654. //
  655. hr = THR( pItem->GetImageIndex( &iImage ) );
  656. if ( S_OK != hr )
  657. goto ControlFailure;
  658. if ( PTI_PROP_READONLY == iImage )
  659. {
  660. EnableWindow( hwndCtl, FALSE );
  661. }
  662. //
  663. // If the control has mutliple values, mark it read-only. They can edit
  664. // it in the "Advanced" view and this would be an advanced operation.
  665. //
  666. if ( _fMultipleSources )
  667. {
  668. EnableWindow( hwndCtl, FALSE );
  669. }
  670. }
  671. else
  672. {
  673. ControlFailure:
  674. //
  675. // No equivalent property was found or there is an error in the
  676. // property set. Clear and disable the control.
  677. //
  678. SetWindowText( hwndCtl, s_cszNULL );
  679. EnableWindow( hwndCtl, FALSE );
  680. }
  681. }
  682. hr = S_OK;
  683. Cleanup:
  684. HRETURN( hr );
  685. InvalidArg:
  686. hr = THR( E_INVALIDARG );
  687. goto Cleanup;
  688. }