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.

876 lines
26 KiB

  1. /*++
  2. (c) 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. PrDrive.cpp
  5. Abstract:
  6. Base file for HSM shell extensions on drives
  7. Author:
  8. Art Bragg [abragg] 04-Aug-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "rshelpid.h"
  13. //#define RS_SHOW_ALL_PCTS
  14. // Help Ids
  15. #define RS_WINDIR_SIZE (2*MAX_PATH)
  16. static DWORD pHelpIds[] =
  17. {
  18. #ifdef RS_SHOW_ALL_PCTS
  19. IDC_STATIC_LOCAL_PCT, idh_volume_percent_local_data,
  20. IDC_STATIC_LOCAL_PCT_UNIT, idh_volume_percent_local_data,
  21. #endif
  22. IDC_STATIC_LOCAL_4DIGIT, idh_volume_capacity_local_data,
  23. IDC_STATIC_LOCAL_4DIGIT_LABEL, idh_volume_capacity_local_data,
  24. IDC_STATIC_LOCAL_4DIGIT_HELP, idh_volume_capacity_local_data,
  25. #ifdef RS_SHOW_ALL_PCTS
  26. IDC_STATIC_CACHED_PCT, idh_volume_percent_remote_data_cached,
  27. IDC_STATIC_CACHED_PCT_UNIT, idh_volume_percent_remote_data_cached,
  28. #endif
  29. IDC_STATIC_CACHED_4DIGIT, idh_volume_capacity_remote_data_cached,
  30. IDC_STATIC_CACHED_4DIGIT_LABEL, idh_volume_capacity_remote_data_cached,
  31. IDC_STATIC_FREE_PCT, idh_volume_percent_free_space,
  32. IDC_STATIC_FREE_PCT_UNIT, idh_volume_percent_free_space,
  33. IDC_STATIC_FREE_4DIGIT, idh_volume_capacity_free_space,
  34. IDC_STATIC_FREE_4DIGIT_LABEL, idh_volume_capacity_free_space,
  35. IDC_STATIC_TOTAL_4DIGIT, idh_volume_disk_capacity,
  36. IDC_STATIC_TOTAL_4DIGIT_LABEL, idh_volume_disk_capacity,
  37. IDC_STATIC_REMOTE_STORAGE_4DIGIT, idh_volume_data_remote_storage,
  38. IDC_STATIC_STATS_LABEL, idh_volume_data_remote_storage,
  39. IDC_EDIT_LEVEL, idh_desired_free_space_percent,
  40. IDC_SPIN_LEVEL, idh_desired_free_space_percent,
  41. IDC_EDIT_LEVEL_LABEL, idh_desired_free_space_percent,
  42. IDC_EDIT_LEVEL_UNIT, idh_desired_free_space_percent,
  43. IDC_EDIT_SIZE, idh_min_file_size_criteria,
  44. IDC_SPIN_SIZE, idh_min_file_size_criteria,
  45. IDC_EDIT_SIZE_LABEL, idh_min_file_size_criteria,
  46. IDC_EDIT_SIZE_UNIT, idh_min_file_size_criteria,
  47. IDC_EDIT_TIME, idh_file_access_date_criteria,
  48. IDC_SPIN_TIME, idh_file_access_date_criteria,
  49. IDC_EDIT_TIME_LABEL, idh_file_access_date_criteria,
  50. IDC_EDIT_TIME_UNIT, idh_file_access_date_criteria,
  51. 0, 0
  52. };
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CPrDrive
  55. // IShellExtInit
  56. STDMETHODIMP
  57. CPrDrive::Initialize(
  58. LPCITEMIDLIST /*pidlFolder*/,
  59. IDataObject * pDataObj,
  60. HKEY /*hkeyProgID*/
  61. )
  62. {
  63. //
  64. // Initialize can be called more than once
  65. //
  66. m_pDataObj.Release( );
  67. //
  68. // duplicate the object pointer
  69. //
  70. m_pDataObj = pDataObj;
  71. return( NOERROR );
  72. }
  73. //////////////////////////////////////////////////////////////////////////////
  74. //
  75. // AddPages
  76. //
  77. //
  78. STDMETHODIMP CPrDrive::AddPages(
  79. LPFNADDPROPSHEETPAGE lpfnAddPage,
  80. LPARAM lParam
  81. )
  82. {
  83. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  84. HRESULT hr = S_OK;
  85. HPROPSHEETPAGE hPage = NULL; // Windows property page handle
  86. TCHAR szFileSystemName [256];
  87. TCHAR szDrive [MAX_PATH];
  88. int nState;
  89. CComPtr<IFsaResource> pFsaRes;
  90. FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  91. STGMEDIUM medium;
  92. CPrDrivePg * pPageDrive = 0;
  93. CPrDriveXPg * pPageXDrive = 0;
  94. try {
  95. //
  96. // Find out how many files the user has selected...
  97. //
  98. UINT cbFiles = 0;
  99. BOOL bMountedVol = FALSE;
  100. WsbAssertPointer( m_pDataObj ); //Paranoid check, m_pDataObj should have something by now...
  101. hr = m_pDataObj->GetData( &fmte, &medium ) ; // Returns hr
  102. if (FAILED(hr)) {
  103. //
  104. // Isn't a normal volume name. Maybe it's a mounted volume.
  105. // Mounted volume names come in on a different clipboard format
  106. // so we can treat them differently from normal volume
  107. // names like "C:\". A mounted volume name will be the path
  108. // to the folder hosting the mounted volume.
  109. // For mounted volumes, the DataObject provides CF "MountedVolume".
  110. //
  111. fmte.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_MOUNTEDVOLUME);
  112. WsbAffirmHr(m_pDataObj->GetData(&fmte, &medium));
  113. bMountedVol = TRUE;
  114. }
  115. cbFiles = DragQueryFile( ( HDROP )medium.hGlobal,( UINT )-1, NULL, 0 );
  116. if( 1 == cbFiles ) {
  117. //
  118. // Do we have admin privileges?
  119. //
  120. if( SUCCEEDED( WsbCheckAccess( WSB_ACCESS_TYPE_ADMINISTRATOR ) ) ) {
  121. //
  122. //OK, the user has only selected a single file, so lets go ahead
  123. //and get more information
  124. //
  125. //Get the name of the file the user has clicked on
  126. //
  127. DragQueryFile( (HDROP)medium.hGlobal,
  128. 0, (USHORT *)szDrive,
  129. (sizeof szDrive)/(sizeof szDrive[0]) );
  130. //
  131. // Is this a local drive?
  132. //
  133. if( ( GetDriveType( szDrive ) )!= DRIVE_REMOTE ) {
  134. //
  135. // Is this an NTFS drive?
  136. //
  137. GetVolumeInformation(
  138. szDrive,
  139. NULL,
  140. 0,
  141. NULL, // Serial Number
  142. NULL, // Filename length
  143. NULL, // flags
  144. szFileSystemName,
  145. 256 );
  146. if( wcscmp( szFileSystemName, L"NTFS" ) == 0 ) {
  147. //
  148. // Make sure the Fsa is running - if not do not do anything that
  149. // could cause it to load.
  150. //
  151. if( WsbCheckService( NULL, APPID_RemoteStorageFileSystemAgent ) == S_OK ) {
  152. //
  153. // Try to get the FSA object for the drive. If we fail, we don't
  154. // put up the property page.
  155. //
  156. CWsbStringPtr computerName;
  157. WsbAffirmHr( WsbGetComputerName( computerName ) );
  158. CString szFullResName = computerName;
  159. CString szResName = szDrive;
  160. //
  161. // If a drive letter is present, the format to connect is:
  162. // <computer-name>\NTFS\<drive-letter>, no trailing '\' or ':'
  163. // i.e. RAVI\NTFS\D
  164. // If it's a sticky vol. name however the format is:
  165. // <computer-name>\NTFS\<volume-name>\ (WITH the trailing '\'
  166. // i.e. RAVI\NTFS\Volume{445a4110-60aa-11d3-0060b0ededdb\
  167. //
  168. if (bMountedVol) {
  169. //
  170. // Remove the leading \\?\
  171. //
  172. szResName = szResName.Right(szResName.GetLength() - 4);
  173. szFullResName = szFullResName + "\\" + "NTFS" + "\\" + szResName;
  174. } else {
  175. szFullResName = szFullResName + "\\" + "NTFS" + "\\" + szDrive;
  176. //
  177. // Remove trailing \ and or :
  178. //
  179. if( szFullResName [szFullResName.GetLength()- 1] == '\\' ) {
  180. szFullResName = szFullResName.Left( szFullResName.GetLength( ) - 1 );
  181. }
  182. if( szFullResName [szFullResName.GetLength( )- 1] == ':' ) {
  183. szFullResName = szFullResName.Left( szFullResName.GetLength( ) - 1 );
  184. }
  185. }
  186. if( HsmConnectFromName( HSMCONN_TYPE_RESOURCE, szFullResName, IID_IFsaResource,( void** )&pFsaRes ) == S_OK ) {
  187. //
  188. // Connected to Hsm
  189. // Is the resource managed?
  190. //
  191. if( pFsaRes->IsManaged( ) == S_OK ) {
  192. nState = MANAGED;
  193. } else {
  194. nState = NOT_MANAGED;
  195. }
  196. } else {
  197. //
  198. // Couldn't connect to Fsa
  199. //
  200. nState = NO_FSA;
  201. }
  202. } else {
  203. //
  204. // Fsa is not running
  205. //
  206. nState = NO_FSA;
  207. }
  208. } else {
  209. nState = NOT_NTFS;
  210. }
  211. } else {
  212. //
  213. // Remote volume
  214. //
  215. nState = REMOTE;
  216. }
  217. } else {
  218. nState = NOT_ADMIN;
  219. }
  220. } else {
  221. nState = MULTI_SELECT;
  222. }
  223. //
  224. // For Not admin, Remote and Multi-Select, we don't even show the page
  225. //
  226. switch( nState ) {
  227. case NOT_NTFS:
  228. case NOT_ADMIN:
  229. case REMOTE:
  230. case MULTI_SELECT:
  231. //
  232. // For Not admin, Remote and Multi-Select, we don't even show the page
  233. //
  234. break;
  235. case MANAGED:
  236. {
  237. /////////////////////////////////////////////////////////////
  238. // Create the property page
  239. WsbAssertPointer( pFsaRes );
  240. //
  241. // Create the Drive property page.
  242. //
  243. pPageDrive = new CPrDrivePg( );
  244. WsbAffirmPointer( pPageDrive );
  245. //
  246. // Assign the Fsa object to the page
  247. //
  248. pPageDrive->m_pFsaResource = pFsaRes;
  249. //
  250. // Set the state
  251. //
  252. pPageDrive->m_nState = nState;
  253. hPage = CreatePropertySheetPage( &pPageDrive->m_psp );
  254. WsbAffirmHandle( hPage );
  255. //
  256. // Call the callback function with the handle to the new
  257. // page
  258. //
  259. WsbAffirm( lpfnAddPage( hPage, lParam ), E_UNEXPECTED );
  260. break;
  261. }
  262. default:
  263. {
  264. /////////////////////////////////////////////////////////////
  265. // Create the property page
  266. pPageXDrive = new CPrDriveXPg( );
  267. WsbAffirmPointer( pPageXDrive );
  268. //
  269. // Set the state
  270. //
  271. pPageXDrive->m_nState = nState;
  272. hPage = CreatePropertySheetPage( &pPageXDrive->m_psp );
  273. WsbAffirmHandle( hPage );
  274. // Call the callback function with the handle to the new
  275. // page
  276. WsbAffirm( lpfnAddPage( hPage, lParam ), E_UNEXPECTED );
  277. }
  278. }
  279. } WsbCatchAndDo( hr,
  280. if( pPageDrive ) delete pPageDrive;
  281. if( pPageXDrive ) delete pPageXDrive;
  282. );
  283. return( hr );
  284. }
  285. //
  286. // FUNCTION: CPrDrive::ReplacePage( UINT, LPFNADDPROPSHEETPAGE, LPARAM )
  287. //
  288. // PURPOSE: Called by the shell only for Control Panel property sheet
  289. // extensions
  290. //
  291. // PARAMETERS:
  292. // uPageID - ID of page to be replaced
  293. // lpfnReplaceWith - Pointer to the Shell's Replace function
  294. // lParam - Passed as second parameter to lpfnReplaceWith
  295. //
  296. // RETURN VALUE:
  297. //
  298. // E_FAIL, since we don't support this function. It should never be
  299. // called.
  300. // COMMENTS:
  301. //
  302. STDMETHODIMP
  303. CPrDrive::ReplacePage(
  304. UINT /*uPageID*/,
  305. LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/,
  306. LPARAM /*lParam*/
  307. )
  308. {
  309. return( E_FAIL );
  310. }
  311. /////////////////////////////////////////////////////////////////////////////
  312. // CPrDrivePg property page
  313. CPrDrivePg::CPrDrivePg( ): CPropertyPage( CPrDrivePg::IDD )
  314. {
  315. //{{AFX_DATA_INIT( CPrDrivePg )
  316. m_accessTime = 0;
  317. m_hsmLevel = 0;
  318. m_fileSize = 0;
  319. //}}AFX_DATA_INIT
  320. //
  321. // Lock the module while this object lives.
  322. // Otherwise, modules can call CoFreeUnusedLibraries( )
  323. // and cause us to unload before our page gets destroyed,
  324. // which causes an AV in the common control.
  325. //
  326. _Module.Lock( );
  327. //
  328. // initialize state
  329. //
  330. m_nState = NO_STATE;
  331. //
  332. // Get and save the MFC callback function.
  333. // This is so we can delete the class the dialog never gets created.
  334. //
  335. m_pMfcCallback = m_psp.pfnCallback;
  336. //
  337. // Set the call back to our callback
  338. //
  339. m_psp.pfnCallback = PropPageCallback;
  340. }
  341. CPrDrivePg::~CPrDrivePg( )
  342. {
  343. _Module.Unlock( );
  344. }
  345. void CPrDrivePg::DoDataExchange( CDataExchange* pDX )
  346. {
  347. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  348. CPropertyPage::DoDataExchange( pDX );
  349. //{{AFX_DATA_MAP( CPrDrivePg )
  350. DDX_Control( pDX, IDC_EDIT_SIZE, m_editSize );
  351. DDX_Control( pDX, IDC_EDIT_LEVEL, m_editLevel );
  352. DDX_Control( pDX, IDC_EDIT_TIME, m_editTime );
  353. DDX_Control( pDX, IDC_SPIN_TIME, m_spinTime );
  354. DDX_Control( pDX, IDC_SPIN_SIZE, m_spinSize );
  355. DDX_Control( pDX, IDC_SPIN_LEVEL, m_spinLevel );
  356. DDX_Text( pDX, IDC_EDIT_TIME, m_accessTime );
  357. DDV_MinMaxUInt( pDX, m_accessTime, HSMADMIN_MIN_INACTIVITY, HSMADMIN_MAX_INACTIVITY );
  358. DDX_Text( pDX, IDC_EDIT_LEVEL, m_hsmLevel );
  359. DDV_MinMaxUInt( pDX, m_hsmLevel, HSMADMIN_MIN_FREESPACE, HSMADMIN_MAX_FREESPACE );
  360. DDX_Text( pDX, IDC_EDIT_SIZE, m_fileSize );
  361. //}}AFX_DATA_MAP
  362. //
  363. // Since we limit the number of characters in the buddy edits, we
  364. // don't expect the previous two DDV's to ever really kick in.
  365. // However, it is possible to enter bad minumum size since both
  366. // '0' and '1' can be entered, but are not in the valid range.
  367. //
  368. //
  369. // Code is equivalent to:
  370. // DDV_MinMaxDWord( pDX, m_fileSize, HSMADMIN_MIN_MINSIZE, HSMADMIN_MAX_MINSIZE );
  371. //
  372. if( pDX->m_bSaveAndValidate &&
  373. ( m_fileSize < HSMADMIN_MIN_MINSIZE ||
  374. m_fileSize > HSMADMIN_MAX_MINSIZE ) ) {
  375. CString message;
  376. AfxFormatString2( message, IDS_ERR_MINSIZE_RANGE,
  377. CString( WsbLongAsString( (LONG)HSMADMIN_MIN_MINSIZE ) ),
  378. CString( WsbLongAsString( (LONG)HSMADMIN_MAX_MINSIZE ) ) );
  379. AfxMessageBox( message, MB_OK | MB_ICONWARNING );
  380. pDX->Fail();
  381. }
  382. }
  383. BEGIN_MESSAGE_MAP( CPrDrivePg, CPropertyPage )
  384. //{{AFX_MSG_MAP( CPrDrivePg )
  385. ON_EN_CHANGE( IDC_EDIT_TIME, OnChangeEditAccess )
  386. ON_EN_CHANGE( IDC_EDIT_LEVEL, OnChangeEditLevel )
  387. ON_EN_CHANGE( IDC_EDIT_SIZE, OnChangeEditSize )
  388. ON_WM_DESTROY( )
  389. ON_WM_CONTEXTMENU()
  390. ON_WM_HELPINFO()
  391. //}}AFX_MSG_MAP
  392. END_MESSAGE_MAP( )
  393. /////////////////////////////////////////////////////////////////////////////
  394. // CPrDrivePg message handlers
  395. BOOL CPrDrivePg::OnInitDialog( )
  396. {
  397. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  398. HRESULT hr = S_OK;
  399. LONGLONG total = 0;
  400. LONGLONG free = 0;
  401. LONGLONG premigrated = 0;
  402. LONGLONG truncated = 0;
  403. LONGLONG remoteStorage = 0;
  404. ULONG totalMB = 0;
  405. ULONG freeMB = 0;
  406. ULONG premigratedMB = 0;
  407. ULONG truncatedMB = 0;
  408. CString sFormat;
  409. CString sBufFormat;
  410. CPropertyPage::OnInitDialog( );
  411. try {
  412. WsbAffirmPointer( m_pFsaResource );
  413. //
  414. // Set the spinner ranges
  415. //
  416. m_spinTime.SetRange( HSMADMIN_MIN_INACTIVITY, HSMADMIN_MAX_INACTIVITY );
  417. m_spinSize.SetRange( HSMADMIN_MIN_MINSIZE, HSMADMIN_MAX_MINSIZE );
  418. m_spinLevel.SetRange( HSMADMIN_MIN_FREESPACE, HSMADMIN_MAX_FREESPACE );
  419. //
  420. // Set text limits
  421. //
  422. m_editTime.SetLimitText( 3 );
  423. m_editSize.SetLimitText( 5 );
  424. m_editLevel.SetLimitText( 2 );
  425. //
  426. // Get statistics
  427. //
  428. WsbAffirmHr( m_pFsaResource->GetSizes( &total, &free, &premigrated, &truncated ) );
  429. //
  430. // "Local" data
  431. //
  432. LONGLONG local = max( ( total - free - premigrated ),( LONGLONG )0 );
  433. //
  434. // Calculate percents
  435. //
  436. int freePct;
  437. int premigratedPct;
  438. if( 0 == total ) {
  439. freePct = 0;
  440. premigratedPct = 0;
  441. } else {
  442. freePct = (int)( ( free * 100 )/ total );
  443. premigratedPct = (int)( ( premigrated * 100 )/ total );
  444. }
  445. int localPct = 100 - freePct - premigratedPct;
  446. remoteStorage = premigrated + truncated;
  447. //
  448. // Show the statistics in 4-char format
  449. //
  450. RsGuiFormatLongLong4Char( local, sBufFormat );
  451. SetDlgItemText( IDC_STATIC_LOCAL_4DIGIT, sBufFormat );
  452. RsGuiFormatLongLong4Char( premigrated, sBufFormat );
  453. SetDlgItemText( IDC_STATIC_CACHED_4DIGIT, sBufFormat );
  454. RsGuiFormatLongLong4Char( free, sBufFormat );
  455. SetDlgItemText( IDC_STATIC_FREE_4DIGIT, sBufFormat );
  456. RsGuiFormatLongLong4Char( total, sBufFormat );
  457. SetDlgItemText( IDC_STATIC_TOTAL_4DIGIT, sBufFormat );
  458. RsGuiFormatLongLong4Char( remoteStorage, sBufFormat );
  459. SetDlgItemText( IDC_STATIC_REMOTE_STORAGE_4DIGIT, sBufFormat );
  460. //
  461. // Show Percents
  462. //
  463. #ifdef RS_SHOW_ALL_PCTS
  464. sFormat.Format( L"%d", localPct );
  465. SetDlgItemText( IDC_STATIC_LOCAL_PCT, sFormat );
  466. sFormat.Format( L"%d", premigratedPct );
  467. SetDlgItemText( IDC_STATIC_CACHED_PCT, sFormat );
  468. #endif
  469. sFormat.Format( L"%d", freePct );
  470. SetDlgItemText( IDC_STATIC_FREE_PCT, sFormat );
  471. //
  472. // Get levels
  473. //
  474. ULONG hsmLevel = 0;
  475. LONGLONG fileSize = 0;
  476. BOOL isRelative = TRUE; // assumed to be TRUE
  477. FILETIME accessTime;
  478. WsbAffirmHr( m_pFsaResource->GetHsmLevel( &hsmLevel ) );
  479. m_hsmLevel = hsmLevel / FSA_HSMLEVEL_1;
  480. WsbAffirmHr( m_pFsaResource->GetManageableItemLogicalSize( &fileSize ) );
  481. m_fileSize = (DWORD)(fileSize / 1024); // Show KBytes
  482. WsbAffirmHr( m_pFsaResource->GetManageableItemAccessTime( &isRelative, &accessTime ) );
  483. WsbAssert( isRelative, E_FAIL ); // We only do relative time
  484. // Convert FILETIME to days
  485. m_accessTime = (UINT)( WsbFTtoLL( accessTime ) / WSB_FT_TICKS_PER_DAY );
  486. if(m_accessTime > HSMADMIN_MAX_INACTIVITY ) {
  487. m_accessTime = HSMADMIN_MAX_INACTIVITY;
  488. }
  489. UpdateData( FALSE );
  490. // Get help file name
  491. CString helpFile;
  492. helpFile.LoadString(IDS_HELPFILEPOPUP);
  493. CWsbStringPtr winDir;
  494. WsbAffirmHr( winDir.Alloc( RS_WINDIR_SIZE ) );
  495. WsbAffirmStatus( ::GetWindowsDirectory( (WCHAR*)winDir, RS_WINDIR_SIZE ) != 0 );
  496. m_pszHelpFilePath = CString(winDir) + L"\\help\\" + helpFile;
  497. } WsbCatch( hr )
  498. return( TRUE );
  499. }
  500. void CPrDrivePg::OnChangeEditAccess( )
  501. {
  502. SetModified( );
  503. }
  504. void CPrDrivePg::OnChangeEditLevel( )
  505. {
  506. SetModified( );
  507. }
  508. void CPrDrivePg::OnChangeEditSize( )
  509. {
  510. SetModified( );
  511. }
  512. BOOL CPrDrivePg::OnApply( )
  513. {
  514. HRESULT hr;
  515. try {
  516. //
  517. // m_pFsaResource is NULL if we didn't show any properties, in which case there is nothing
  518. // to apply.. Note that apply may have been enabled by another page in the sheet.
  519. //
  520. if( m_pFsaResource ) {
  521. LONGLONG fileSize = 0;
  522. UpdateData( TRUE );
  523. WsbAffirmHr( m_pFsaResource->SetHsmLevel( m_hsmLevel * FSA_HSMLEVEL_1 ) );
  524. fileSize = ((LONGLONG)m_fileSize) * 1024;
  525. WsbAffirmHr( m_pFsaResource->SetManageableItemLogicalSize( fileSize ) );
  526. //
  527. // Convert days to FILETIME
  528. //
  529. FILETIME accessTime;
  530. accessTime = WsbLLtoFT( ( LONGLONG )m_accessTime * WSB_FT_TICKS_PER_DAY );
  531. WsbAffirmHr( m_pFsaResource->SetManageableItemAccessTime( TRUE, accessTime ) );
  532. }
  533. } WsbCatch( hr );
  534. return( CPropertyPage::OnApply( ) );
  535. }
  536. UINT CALLBACK
  537. CPrDrivePg::PropPageCallback(
  538. HWND hWnd,
  539. UINT uMessage,
  540. LPPROPSHEETPAGE ppsp )
  541. {
  542. UINT rVal = 0;
  543. HRESULT hr = S_OK;
  544. try {
  545. WsbAffirmPointer( ppsp );
  546. WsbAffirmPointer( ppsp->lParam );
  547. //
  548. // Get the page object from lParam
  549. //
  550. CPrDrivePg* pPage = (CPrDrivePg*)ppsp->lParam;
  551. WsbAssertPointer( pPage->m_pMfcCallback );
  552. rVal = ( pPage->m_pMfcCallback )( hWnd, uMessage, ppsp );
  553. switch( uMessage ) {
  554. case PSPCB_CREATE:
  555. break;
  556. case PSPCB_RELEASE:
  557. delete pPage;
  558. break;
  559. }
  560. } WsbCatch( hr );
  561. return( rVal );
  562. }
  563. void CPrDrivePg::OnContextMenu(CWnd* pWnd, CPoint point)
  564. {
  565. UNREFERENCED_PARAMETER(pWnd);
  566. UNREFERENCED_PARAMETER(point);
  567. if(pHelpIds && (m_pszHelpFilePath != L"")) {
  568. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  569. ::WinHelp(m_hWnd, m_pszHelpFilePath, HELP_CONTEXTMENU, (DWORD_PTR)pHelpIds);
  570. }
  571. }
  572. BOOL CPrDrivePg::OnHelpInfo(HELPINFO* pHelpInfo)
  573. {
  574. if( (HELPINFO_WINDOW == pHelpInfo->iContextType) &&
  575. pHelpIds &&
  576. (m_pszHelpFilePath != L"") ) {
  577. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  578. //
  579. // Look through list to see if we have help for this control
  580. // If not, we want to avoid the "No Help Available" box
  581. //
  582. DWORD *pTmp = pHelpIds;
  583. DWORD helpId = 0;
  584. DWORD tmpHelpId = 0;
  585. DWORD tmpCtrlId = 0;
  586. while( pTmp && *pTmp ) {
  587. //
  588. // Array is a pairing of control ID and help ID
  589. //
  590. tmpCtrlId = pTmp[0];
  591. tmpHelpId = pTmp[1];
  592. pTmp += 2;
  593. if(tmpCtrlId == (DWORD)pHelpInfo->iCtrlId) {
  594. helpId = tmpHelpId;
  595. break;
  596. }
  597. }
  598. if( helpId != 0 ) {
  599. ::WinHelp(m_hWnd, m_pszHelpFilePath, HELP_CONTEXTPOPUP, helpId);
  600. }
  601. }
  602. return CPropertyPage ::OnHelpInfo(pHelpInfo);
  603. }
  604. /////////////////////////////////////////////////////////////////////////////
  605. // CPrDriveXPg property page
  606. CPrDriveXPg::CPrDriveXPg( ): CPropertyPage( CPrDriveXPg::IDD )
  607. {
  608. //{{AFX_DATA_INIT( CPrDriveXPg )
  609. //}}AFX_DATA_INIT
  610. //
  611. // Lock the module while this object lives.
  612. // Otherwise, modules can call CoFreeUnusedLibraries( )
  613. // and cause us to unload before our page gets destroyed,
  614. // which causes an AV in the common control.
  615. //
  616. _Module.Lock( );
  617. m_nState = NO_STATE;
  618. //
  619. // Get and save the MFC callback function.
  620. // This is so we can delete the class the dialog never gets created.
  621. //
  622. m_pMfcCallback = m_psp.pfnCallback;
  623. //
  624. // Set the call back to our callback
  625. //
  626. m_psp.pfnCallback = PropPageCallback;
  627. }
  628. CPrDriveXPg::~CPrDriveXPg( )
  629. {
  630. _Module.Unlock( );
  631. }
  632. BEGIN_MESSAGE_MAP( CPrDriveXPg, CPropertyPage )
  633. //{{AFX_MSG_MAP( CPrDriveXPg )
  634. //}}AFX_MSG_MAP
  635. END_MESSAGE_MAP( )
  636. /////////////////////////////////////////////////////////////////////////////
  637. // CPrDriveXPg message handlers
  638. BOOL CPrDriveXPg::OnInitDialog( )
  639. {
  640. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  641. HRESULT hr = S_OK;
  642. CPropertyPage::OnInitDialog( );
  643. try {
  644. switch( m_nState ) {
  645. case NO_FSA:
  646. m_szError.LoadString( IDS_NO_FSA );
  647. break;
  648. case NOT_MANAGED:
  649. m_szError.LoadString( IDS_NOT_MANAGED );
  650. break;
  651. case NOT_NTFS:
  652. m_szError.LoadString( IDS_NOT_NTFS );
  653. break;
  654. }
  655. SetDlgItemText( IDC_STATIC_ERROR, m_szError );
  656. } WsbCatch( hr )
  657. return( TRUE );
  658. }
  659. UINT CALLBACK
  660. CPrDriveXPg::PropPageCallback(
  661. HWND hWnd,
  662. UINT uMessage,
  663. LPPROPSHEETPAGE ppsp )
  664. {
  665. UINT rVal = 0;
  666. HRESULT hr = S_OK;
  667. try {
  668. WsbAffirmPointer( ppsp );
  669. WsbAffirmPointer( ppsp->lParam );
  670. //
  671. // Get the page object from lParam
  672. //
  673. CPrDriveXPg* pPage = (CPrDriveXPg*)ppsp->lParam;
  674. WsbAssertPointer( pPage->m_pMfcCallback );
  675. rVal = ( pPage->m_pMfcCallback )( hWnd, uMessage, ppsp );
  676. switch( uMessage ) {
  677. case PSPCB_CREATE:
  678. break;
  679. case PSPCB_RELEASE:
  680. delete pPage;
  681. break;
  682. }
  683. } WsbCatch( hr );
  684. return( rVal );
  685. }