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.

1001 lines
24 KiB

  1. //
  2. // Microsoft Windows Media Technologies
  3. // Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
  4. //
  5. //
  6. // This workspace contains two projects -
  7. // 1. ProgHelp which implements the Progress Interface
  8. // 2. The Sample application WmdmApp.
  9. //
  10. // ProgHelp.dll needs to be registered first for the SampleApp to run.
  11. // Includes
  12. //
  13. #include "appPCH.h"
  14. // Constants
  15. //
  16. #define DEVFILES_LV_NUMCOLS 3
  17. #define DEVFILES_COL_MARGIN 3
  18. #define SMALL_IMAGE_WIDTH 16
  19. const CLSID CLSID_WMDMProgressHelper = {0x8297A5B4,0x5113,0x11D3,{0xB2,0x76,0x00,0xC0,0x4F,0x8E,0xC2,0x21}};
  20. const IID IID_IWMDMProgressHelper = {0x1DCB3A10,0x33ED,0x11d3,{0x84,0x70,0x00,0xC0,0x4F,0x79,0xDB,0xC5}};
  21. const CLSID CLSID_WMDMOperationHelper = {0x9FB01A67,0xA11E,0x4653,{0x8E,0xD6,0xB5,0xCE,0x73,0xCD,0xA3,0xE3}};
  22. const IID IID_IWMDMOperationHelper = {0x41216997,0xC4D9,0x445A,{0xA3,0x88,0x39,0x3D,0x2B,0x85,0xA0,0xE5}};
  23. // Macros
  24. //
  25. // Local functions
  26. //
  27. INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  28. LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  29. // Local Variables
  30. //
  31. /////////////////////////////////////////////////////////////////////
  32. //
  33. // Function implementations
  34. //
  35. CDevFiles::CDevFiles()
  36. {
  37. m_hwndDevFiles = NULL;
  38. m_hwndDevFiles_LV = NULL;
  39. m_iFolderIcon = 0;
  40. m_dwTotalTicks = 0;
  41. m_dwWorkingTicks = 0;
  42. m_pProgHelp = NULL;
  43. m_wndprocDevFiles_LV = NULL;
  44. CoInitialize( NULL );
  45. }
  46. CDevFiles::~CDevFiles()
  47. {
  48. CoUninitialize();
  49. }
  50. HWND CDevFiles::GetHwnd( void )
  51. {
  52. return m_hwndDevFiles;
  53. }
  54. HWND CDevFiles::GetHwnd_LV( void )
  55. {
  56. return m_hwndDevFiles_LV;
  57. }
  58. BOOL CDevFiles::Create( HWND hwndParent )
  59. {
  60. BOOL fRet = FALSE;
  61. // Create the Device Files dialog
  62. //
  63. m_hwndDevFiles = CreateDialogParam(
  64. g_hInst,
  65. MAKEINTRESOURCE( IDD_DEVICEFILES ),
  66. hwndParent,
  67. DevFiles_DlgProc,
  68. (LPARAM)this
  69. );
  70. ExitOnNull( m_hwndDevFiles );
  71. // Get a handle to the ListView control of the Device Files dialog
  72. //
  73. m_hwndDevFiles_LV = GetDlgItem( m_hwndDevFiles, IDC_LV_DEVICEFILES );
  74. // Set the user data to be this CDevFiles class pointer
  75. //
  76. SetWindowLongPtr( m_hwndDevFiles_LV, GWLP_USERDATA, (LPARAM)this );
  77. // Subclass the listview
  78. //
  79. m_wndprocDevFiles_LV = (WNDPROC) SetWindowLongPtr(
  80. m_hwndDevFiles_LV,
  81. GWLP_WNDPROC,
  82. (LONG_PTR)WndProc_DevFiles_LV
  83. );
  84. // Initialize image list
  85. //
  86. ExitOnFalse( InitImageList() );
  87. // Initialize columns
  88. //
  89. ExitOnFalse( InitColumns() );
  90. // Handle Drag and Dropped files
  91. //
  92. DragAcceptFiles( m_hwndDevFiles, TRUE );
  93. // Show the window
  94. //
  95. ShowWindow( m_hwndDevFiles, SW_SHOW );
  96. fRet = TRUE;
  97. lExit:
  98. return fRet;
  99. }
  100. VOID CDevFiles::Destroy( void )
  101. {
  102. // Remove all the item from the listview control
  103. //
  104. RemoveAllItems();
  105. // Destroy the window
  106. //
  107. if( m_hwndDevFiles )
  108. {
  109. DestroyWindow( m_hwndDevFiles );
  110. }
  111. }
  112. BOOL CDevFiles::InitImageList( void )
  113. {
  114. BOOL fRet = FALSE;
  115. HRESULT hr;
  116. IMalloc *pMalloc = NULL;
  117. LPITEMIDLIST pidl = NULL;
  118. HIMAGELIST hShellImageList = NULL;
  119. SHFILEINFO si;
  120. CHAR szWinPath[MAX_PATH+1];
  121. UINT nRet;
  122. // Get the index of the folder icon
  123. //
  124. nRet = GetWindowsDirectory( szWinPath, sizeof(szWinPath)/sizeof(szWinPath[0]) );
  125. if (nRet == 0 || nRet > sizeof(szWinPath)/sizeof(szWinPath[0]))
  126. {
  127. // Failed to get the windows directory
  128. goto lExit;
  129. }
  130. // Get a shell ID list for the desktop folder
  131. //
  132. hr = SHGetSpecialFolderLocation( g_hwndMain, CSIDL_DESKTOP, &pidl );
  133. ExitOnFail( hr );
  134. // Get the shell's small icon image list and set that to be the listview's image list
  135. //
  136. hShellImageList = (HIMAGELIST) SHGetFileInfo(
  137. (LPCTSTR)pidl, 0,
  138. &si, sizeof(si),
  139. SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON
  140. );
  141. if( hShellImageList )
  142. {
  143. ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_SMALL );
  144. }
  145. // Get the shell's normal icon image list and set that to be the listview's image list
  146. //
  147. hShellImageList = (HIMAGELIST) SHGetFileInfo(
  148. (LPCTSTR)pidl, 0,
  149. &si, sizeof(si),
  150. SHGFI_PIDL | SHGFI_SYSICONINDEX
  151. );
  152. if( hShellImageList )
  153. {
  154. ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_NORMAL );
  155. }
  156. SHGetFileInfo( szWinPath, 0, &si, sizeof(si), SHGFI_SYSICONINDEX );
  157. m_iFolderIcon = si.iIcon;
  158. // Everything went Ok
  159. //
  160. fRet = TRUE;
  161. lExit:
  162. // Free the pointer to the shell's ID list
  163. //
  164. if (pidl)
  165. {
  166. hr = SHGetMalloc( &pMalloc );
  167. if( SUCCEEDED(hr) && pMalloc )
  168. {
  169. pMalloc->Free( pidl );
  170. }
  171. }
  172. return fRet;
  173. }
  174. BOOL CDevFiles::InitColumns( void )
  175. {
  176. LVCOLUMN lvcol;
  177. INT i;
  178. char szCol[MAX_PATH];
  179. //
  180. // Add the report-view columns to the listview
  181. // The column names and starting sizes are stored in the resource string table
  182. //
  183. lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
  184. lvcol.fmt = LVCFMT_LEFT;
  185. for( i=0; i < DEVFILES_LV_NUMCOLS; i++ )
  186. {
  187. // Get the column size
  188. //
  189. LoadString( g_hInst, IDS_COLSIZE_1+i, szCol, sizeof(szCol) );
  190. lvcol.cx = atoi( szCol );
  191. // Get the column name
  192. //
  193. LoadString( g_hInst, IDS_COLNAME_1+i, szCol, sizeof(szCol) );
  194. lvcol.pszText = szCol;
  195. // Add the column the the listview
  196. //
  197. ListView_InsertColumn( m_hwndDevFiles_LV, i, &lvcol );
  198. }
  199. return TRUE;
  200. }
  201. VOID CDevFiles::OnSize( LPRECT prcMain )
  202. {
  203. INT nX, nY, nW, nH;
  204. RECT rcMain;
  205. RECT rcDevice;
  206. GetWindowRect( g_hwndMain, &rcMain );
  207. GetWindowRect( g_cDevices.GetHwnd(), &rcDevice );
  208. nX = (rcDevice.right - rcMain.left) - 2*GetSystemMetrics( SM_CXEDGE );
  209. nY = 0;
  210. nW = prcMain->right - prcMain->left - nX;
  211. nH = prcMain->bottom - prcMain->top;
  212. SetWindowPos( m_hwndDevFiles, NULL, nX, nY, nW, nH, SWP_NOZORDER );
  213. SetWindowPos( m_hwndDevFiles_LV, NULL, 0, 0, nW, nH-22, SWP_NOZORDER );
  214. }
  215. BOOL CDevFiles::SendFilesToDevice( LPSTR pszFiles, UINT uNumFiles )
  216. {
  217. BOOL fRet = FALSE;
  218. WCHAR wszName[MAX_PATH];
  219. CHAR szName[MAX_PATH];
  220. LPSTR psz;
  221. DWORD dwTotalSize = 0L;
  222. UINT uFile;
  223. HRESULT hr;
  224. HTREEITEM hItem;
  225. CItemData *pItemData;
  226. IWMDMStorageControl *pStorageControl = NULL;
  227. IWMDMStorage *pNewObject = NULL;
  228. IWMDMStorage *pInStorage = NULL;
  229. IWMDMProgress *pProgress = NULL;
  230. IWMDMOperation *pOperation = NULL;
  231. IWMDMOperationHelper *pOperationHelper = NULL;
  232. IWMDMRevoked *pRevoked = NULL;
  233. LPWSTR pwszRevokedURL = NULL;
  234. DWORD dwRevokedURLLen = 0;
  235. DWORD dwRevokedBitFlag;
  236. // Get the selected device/storage
  237. //
  238. hItem = g_cDevices.GetSelectedItem( NULL );
  239. ExitOnNull( hItem );
  240. // Get the itemdata class associated with the hItem and
  241. // retrieve the IWMDMStorage for it
  242. //
  243. pItemData = (CItemData *) TreeView_GetLParam( g_cDevices.GetHwnd_TV(), hItem );
  244. ExitOnNull( pItemData );
  245. pInStorage = ( pItemData->m_fIsDevice ? pItemData->m_pRootStorage : pItemData->m_pStorage );
  246. ExitOnNull( pInStorage );
  247. // Tally the file sizes
  248. //
  249. psz = pszFiles;
  250. for( uFile = 0; uFile < uNumFiles; uFile++ )
  251. {
  252. dwTotalSize += GetTheFileSize( psz );
  253. psz += lstrlen(psz) + 1;
  254. }
  255. // Create the progress dialog
  256. //
  257. ExitOnFalse( m_cProgress.Create(g_hwndMain) );
  258. m_cProgress.SetOperation( "Sending Files..." );
  259. m_cProgress.SetCount( 0, uNumFiles );
  260. m_cProgress.SetRange( 0, 100 );
  261. m_dwTotalTicks = dwTotalSize;
  262. m_dwWorkingTicks = 0;
  263. // Create the progress interface
  264. //
  265. hr = CoCreateInstance(
  266. CLSID_WMDMProgressHelper,
  267. NULL, CLSCTX_ALL,
  268. IID_IWMDMProgress,
  269. (void**)&pProgress
  270. );
  271. ExitOnFail( hr );
  272. pProgress->AddRef();
  273. hr = pProgress->QueryInterface(
  274. IID_IWMDMProgressHelper,
  275. reinterpret_cast<void**> (&m_pProgHelp)
  276. );
  277. ExitOnFail( hr );
  278. m_pProgHelp->SetNotification( m_hwndDevFiles, WM_DRM_PROGRESS );
  279. // Setup for copy using operation interface.
  280. if( g_bUseOperationInterface )
  281. {
  282. // Create the progress interface
  283. //
  284. hr = CoCreateInstance(
  285. CLSID_WMDMOperationHelper,
  286. NULL, CLSCTX_INPROC_SERVER,
  287. IID_IWMDMOperationHelper,
  288. (void**)&pOperationHelper );
  289. ExitOnFail( hr );
  290. hr = pOperationHelper->QueryInterface(
  291. IID_IWMDMOperation,
  292. reinterpret_cast<void**> (&pOperation) );
  293. ExitOnFail( hr );
  294. // Pass the SecureChannelClient as a pointer to the ProgHelper object.
  295. // The object is inproc so it should be safe to pass pointers
  296. pOperationHelper->SetSAC( (void*)g_cWmdm.m_pSAC );
  297. }
  298. // Acquire the storage control interface
  299. //
  300. hr = pInStorage->QueryInterface(
  301. IID_IWMDMStorageControl,
  302. reinterpret_cast<void**>(&pStorageControl)
  303. );
  304. ExitOnFail( hr );
  305. // Loop through the files, transfering each one
  306. //
  307. psz = pszFiles;
  308. for( uFile = 0; uFile < uNumFiles && !m_cProgress.IsCancelled(); uFile++ )
  309. {
  310. hr = StringCchCopy(szName, sizeof(szName)/sizeof(szName[0]), psz);
  311. if (FAILED(hr))
  312. {
  313. fRet = FALSE;
  314. break;
  315. }
  316. if (!MultiByteToWideChar(
  317. CP_ACP, 0,
  318. szName, -1,
  319. wszName, sizeof(wszName)/sizeof(wszName[0])
  320. ))
  321. {
  322. hr = HRESULT_FROM_WIN32(GetLastError());
  323. fRet = FALSE;
  324. break;
  325. }
  326. // Set progress bar stats for this file
  327. //
  328. m_cProgress.IncCount();
  329. StripPath( szName );
  330. m_cProgress.SetDetails( szName );
  331. m_cProgress.Show( TRUE );
  332. UiYield();
  333. pNewObject = NULL;
  334. // Copy using operation interface.
  335. if( g_bUseOperationInterface )
  336. {
  337. // @@@@ The implementation treats the argument as a WCHAR*, not a
  338. // BSTR, so this is ok. The simplest solution is to change the
  339. // interface definition to WCHAR*. Will that cause any harm?
  340. // (Interface appears to be a private one.)
  341. //
  342. // The alternative is to call SysAllocString. The issue with
  343. // this approach is handling errors. Also SysAllocString inexplicably
  344. // returns NULL when *wszName = 0. Can that happen?
  345. //
  346. pOperationHelper->SetFileName( wszName );
  347. hr = pStorageControl->Insert(
  348. WMDM_MODE_BLOCK | WMDM_CONTENT_FILE | WMDM_CONTENT_OPERATIONINTERFACE,
  349. NULL,
  350. pOperation,
  351. pProgress,
  352. &pNewObject );
  353. }
  354. else
  355. {
  356. hr = pStorageControl->Insert(
  357. WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,
  358. wszName,
  359. NULL,
  360. pProgress,
  361. &pNewObject );
  362. }
  363. // Handle the case where one of the needed components was revoked
  364. if( hr == WMDM_E_REVOKED )
  365. {
  366. char pszCaption[MAX_PATH];
  367. char pszErrorMsg[MAX_PATH];
  368. // Hide progress window before displaying error messages
  369. m_cProgress.Show( FALSE );
  370. // Get Revocation interface from WMDM
  371. hr = pStorageControl->QueryInterface( IID_IWMDMRevoked, (void**)&pRevoked );
  372. if( hr != S_OK || pRevoked == NULL )
  373. {
  374. // Latest version of WMDM not avalible on machine?
  375. fRet = FALSE;
  376. break;
  377. }
  378. // Get revocation information from WMDM
  379. hr = pRevoked->GetRevocationURL( &pwszRevokedURL, &dwRevokedURLLen, &dwRevokedBitFlag );
  380. if( FAILED(hr) )
  381. {
  382. fRet = FALSE;
  383. break;
  384. }
  385. // The application has been revoked
  386. if( dwRevokedBitFlag & WMDM_APP_REVOKED )
  387. {
  388. LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) );
  389. LoadString( g_hInst, IDS_APP_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) );
  390. ::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_OK );
  391. }
  392. // A component needed for the transfer has been revoked, give the user
  393. // a chance to look for an update on the internet.
  394. else
  395. {
  396. LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) );
  397. LoadString( g_hInst, IDS_COMPONENT_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) );
  398. if( ::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_YESNO ) == IDYES )
  399. {
  400. ShellExecuteW(g_hwndMain, L"open", pwszRevokedURL, NULL, NULL, SW_SHOWNORMAL);
  401. }
  402. }
  403. CoTaskMemFree( pwszRevokedURL );
  404. break;
  405. }
  406. if( SUCCEEDED(hr) && pNewObject )
  407. {
  408. CItemData *pStorageItem = new CItemData;
  409. if( pStorageItem )
  410. {
  411. hr = pStorageItem->Init( pNewObject );
  412. if( SUCCEEDED(hr) )
  413. {
  414. g_cDevFiles.AddItem( pStorageItem );
  415. }
  416. else
  417. {
  418. delete pStorageItem;
  419. }
  420. }
  421. pNewObject->Release();
  422. }
  423. psz += lstrlen(psz) + 1;
  424. }
  425. // Make sure the dialog is hidden and then destroy it
  426. //
  427. m_cProgress.SetPos( -1 );
  428. m_cProgress.Show( FALSE );
  429. m_cProgress.Destroy();
  430. // refresh the device/devicefiles display
  431. g_cDevices.UpdateSelection( NULL, FALSE );
  432. lExit:
  433. if( pOperationHelper )
  434. {
  435. pOperationHelper->Release();
  436. }
  437. if( pOperation )
  438. {
  439. pOperation->Release();
  440. }
  441. if( pStorageControl )
  442. {
  443. pStorageControl->Release();
  444. }
  445. if( pRevoked )
  446. {
  447. pRevoked->Release();
  448. }
  449. if( m_pProgHelp )
  450. {
  451. m_pProgHelp->Release();
  452. m_pProgHelp = NULL;
  453. }
  454. if( pProgress )
  455. {
  456. pProgress->Release();
  457. }
  458. return fRet;
  459. }
  460. BOOL CDevFiles::OnDropFiles( HWND hWnd, WPARAM wParam, LPARAM lParam )
  461. {
  462. LPSTR lpsz = NULL;
  463. HANDLE hDrop = (HANDLE) wParam;
  464. UINT uNumFiles;
  465. // Turn the drop list into a double-zero-terminated list of strings
  466. //
  467. lpsz = DropListToBuffer( (HDROP)hDrop, LTB_NULL_TERM, &uNumFiles );
  468. ExitOnNull( lpsz );
  469. // Send those files to the selected device
  470. //
  471. SendFilesToDevice( lpsz, uNumFiles );
  472. lExit:
  473. // Close the dragdrop operation
  474. //
  475. DragFinish( (HDROP)hDrop );
  476. if( lpsz )
  477. {
  478. MemFree( lpsz );
  479. }
  480. return 0; // return zero if we process this message
  481. }
  482. VOID CDevFiles::RemoveAllItems( void )
  483. {
  484. INT i;
  485. INT nCount;
  486. nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
  487. // Remove the items one at a time, from the bottom up
  488. //
  489. for( i=nCount-1; i >= 0; i-- )
  490. {
  491. RemoveItem( i );
  492. }
  493. }
  494. BOOL CDevFiles::RemoveItem( INT nItem )
  495. {
  496. CItemData *pStorage;
  497. pStorage = (CItemData *) ListView_GetLParam( m_hwndDevFiles_LV, nItem );
  498. if( pStorage )
  499. {
  500. delete pStorage;
  501. }
  502. return ListView_DeleteItem( m_hwndDevFiles_LV, nItem );
  503. }
  504. BOOL CDevFiles::AddItem( CItemData *pStorage )
  505. {
  506. LVITEM lvitem;
  507. INT nItem;
  508. CHAR sz[MAX_PATH];
  509. INT m_iSysFolderIcon = 0;
  510. // Set the icon index.
  511. // If the storage is a folder, use the folder icon, otherwise
  512. // use the icon associated with that file type.
  513. //
  514. if( pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER )
  515. {
  516. lvitem.iImage = m_iFolderIcon;
  517. }
  518. else
  519. {
  520. TCHAR szType[MAX_PATH];
  521. lvitem.iImage = GetShellIconIndex(
  522. pStorage->m_szName,
  523. szType, sizeof(szType)/sizeof(szType[0])
  524. );
  525. }
  526. lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  527. lvitem.iItem = 10000;
  528. lvitem.iSubItem = 0;
  529. lvitem.pszText = pStorage->m_szName;
  530. lvitem.lParam = (LPARAM)pStorage;
  531. // Insert the item into the listview
  532. //
  533. nItem = ListView_InsertItem( m_hwndDevFiles_LV, &lvitem );
  534. if( -1 == nItem )
  535. {
  536. return FALSE;
  537. }
  538. // Set the size field blank for a folder, or for the file size for a file
  539. //
  540. ListView_SetItemText(
  541. m_hwndDevFiles_LV,
  542. nItem,
  543. 1,
  544. ( (pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER) ? " " : FormatBytesToSz(pStorage->m_dwSizeLow, 0, 1, sz, sizeof(sz)) )
  545. );
  546. // Set the description field to be the display date
  547. //
  548. {
  549. SYSTEMTIME systime;
  550. // Copy the WMDMDATETIME fields to a SYSTEMTIME structure for manipulation
  551. //
  552. systime.wYear = pStorage->m_DateTime.wYear;
  553. systime.wMonth = pStorage->m_DateTime.wMonth;
  554. systime.wDayOfWeek = 0;
  555. systime.wDay = pStorage->m_DateTime.wDay;
  556. systime.wHour = pStorage->m_DateTime.wHour;
  557. systime.wMinute = pStorage->m_DateTime.wMinute;
  558. systime.wSecond = pStorage->m_DateTime.wSecond;
  559. systime.wMilliseconds = 0;
  560. ListView_SetItemText(
  561. m_hwndDevFiles_LV,
  562. nItem,
  563. 2,
  564. FormatSystemTimeToSz( &systime, sz, sizeof(sz) )
  565. );
  566. }
  567. // Update the status bar with the changes resulting from the insertion of this item
  568. //
  569. UpdateStatusBar();
  570. return TRUE;
  571. }
  572. VOID CDevFiles::UpdateStatusBar( void )
  573. {
  574. INT nCount;
  575. UINT uStrID;
  576. HTREEITEM hItem = g_cDevices.GetSelectedItem( NULL );
  577. if( NULL == hItem )
  578. {
  579. // If no device is selected, blank out the pane specifying the number of files
  580. //
  581. g_cStatus.SetTextSz( SB_PANE_DEVFILES, "" );
  582. }
  583. else
  584. {
  585. // If a device is selected, set the statusbar pane that shows the number of files
  586. //
  587. nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
  588. // Get the grammatically-appropriate format string to use
  589. //
  590. if( nCount == 0 )
  591. {
  592. uStrID = IDS_SB_DEVICEFILES_MANY;
  593. }
  594. else if( nCount == 1 )
  595. {
  596. uStrID = IDS_SB_DEVICEFILES_ONE;
  597. }
  598. else
  599. {
  600. uStrID = IDS_SB_DEVICEFILES_MANY;
  601. }
  602. // Set the text of the pane
  603. //
  604. g_cStatus.SetTextFormatted( SB_PANE_DEVFILES, uStrID, nCount, NULL );
  605. }
  606. }
  607. INT CDevFiles::GetSelectedItems( INT nItems[], INT *pnSelItems )
  608. {
  609. INT nRet = -1;
  610. INT nNumSelItems = ListView_GetSelectedCount( m_hwndDevFiles_LV );
  611. INT nNumItems = ListView_GetItemCount( m_hwndDevFiles_LV );
  612. INT nItemRoom = *pnSelItems;
  613. INT i;
  614. INT iIndex;
  615. // Initialize return parameters
  616. //
  617. *pnSelItems = nNumSelItems;
  618. // If there isn't enough room for all the selected items, or if there
  619. // aren't any selected items, return -1.
  620. // The space needed is already in the nSelItems OUT param.
  621. //
  622. if( nItemRoom < nNumSelItems || 0 == nNumSelItems )
  623. {
  624. return -1;
  625. }
  626. // Loop thru all the items to determine whether or not they are
  627. // selected. Fill in the OUT array with the ones that are.
  628. //
  629. for( i=0, iIndex=0; i < nNumItems; i++ )
  630. {
  631. UINT uState = ListView_GetItemState( m_hwndDevFiles_LV, i, LVIS_SELECTED | LVIS_FOCUSED );
  632. if( uState & LVIS_SELECTED )
  633. {
  634. nItems[iIndex++] = i;
  635. if( uState & LVIS_FOCUSED )
  636. {
  637. // Remember which item has focus, so it can be returned to the caller
  638. //
  639. nRet = i;
  640. }
  641. }
  642. }
  643. // If there are selected items, but nothing has focus, use the first selected item
  644. //
  645. if( nRet == -1 && nNumSelItems > 0 )
  646. {
  647. nRet = nItems[0];
  648. }
  649. return nRet;
  650. }
  651. // Is it ok to delete the currently selected files?
  652. BOOL CDevFiles::OkToDelete()
  653. {
  654. INT nNumItems = ListView_GetItemCount( GetHwnd_LV() );
  655. CItemData *pStorage = NULL;
  656. // Loop thru all the items to determine whether or not they are
  657. // selected. Enable delete if any selected file can be deleted.
  658. //
  659. for( int iIndex=0; iIndex < nNumItems; iIndex++ )
  660. {
  661. if( ListView_GetItemState( GetHwnd_LV(), iIndex, LVIS_SELECTED ) )
  662. {
  663. pStorage = (CItemData *) ListView_GetLParam( GetHwnd_LV(), iIndex );
  664. if( pStorage && (pStorage->m_dwAttributes & WMDM_FILE_ATTR_CANDELETE) )
  665. return TRUE;
  666. }
  667. }
  668. return FALSE;
  669. }
  670. /////////////////////////////////////////////////////////////////////
  671. //
  672. // Non-C++ functions
  673. //
  674. INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  675. {
  676. WORD wId = LOWORD((DWORD)wParam);
  677. WORD wNotifyCode = HIWORD((DWORD)wParam);
  678. static CDevFiles *cDevFiles = NULL;
  679. static HWND hwndLV = NULL;
  680. switch( uMsg )
  681. {
  682. case WM_INITDIALOG:
  683. cDevFiles = (CDevFiles *)lParam;
  684. hwndLV = GetDlgItem( hWnd, IDC_LV_DEVICEFILES );
  685. break;
  686. case WM_NOTIFY:
  687. {
  688. LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
  689. UINT uCode = pnmv->hdr.code;
  690. switch( uCode )
  691. {
  692. case LVN_BEGINDRAG:
  693. SendMessage( hwndLV, uMsg, wParam, lParam );
  694. break;
  695. default:
  696. break;
  697. }
  698. }
  699. break;
  700. case WM_DRM_PROGRESS:
  701. {
  702. PROGRESSNOTIFY *pNotify = (PROGRESSNOTIFY *)lParam;
  703. switch( pNotify->dwMsg )
  704. {
  705. case SFM_BEGIN:
  706. break;
  707. case SFM_PROGRESS:
  708. {
  709. DWORD dwTicks = cDevFiles->m_dwWorkingTicks + pNotify->dwCurrentTicks;
  710. cDevFiles->m_cProgress.SetPos(
  711. (INT)( dwTicks*100/cDevFiles->m_dwTotalTicks )
  712. );
  713. cDevFiles->m_cProgress.SetBytes(
  714. dwTicks,
  715. cDevFiles->m_dwTotalTicks
  716. );
  717. }
  718. break;
  719. case SFM_END:
  720. cDevFiles->m_dwWorkingTicks += pNotify->dwTotalTicks;
  721. break;
  722. }
  723. UiYield();
  724. // If the user cancelled the operation, tell the progress interface
  725. //
  726. if( cDevFiles->m_cProgress.IsCancelled() )
  727. {
  728. // Notify progress interface
  729. //
  730. cDevFiles->m_pProgHelp->Cancel();
  731. }
  732. }
  733. break;
  734. default:
  735. break;
  736. }
  737. return 0;
  738. }
  739. LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  740. {
  741. static CDevFiles *cDevFiles = NULL;
  742. WORD wId = LOWORD((DWORD)wParam);
  743. WORD wNotifyCode = HIWORD((DWORD)wParam);
  744. if( NULL == cDevFiles )
  745. {
  746. cDevFiles = (CDevFiles *) GetWindowLongPtr( hWnd, GWLP_USERDATA );
  747. }
  748. switch( uMsg )
  749. {
  750. case WM_DROPFILES:
  751. return cDevFiles->OnDropFiles( hWnd, wParam, lParam );
  752. case WM_KEYDOWN:
  753. if( wParam == VK_DELETE )
  754. {
  755. SendMessage( g_hwndMain, WM_DRM_DELETEITEM, 0, 0 );
  756. return 0;
  757. }
  758. break;
  759. case WM_CONTEXTMENU :
  760. {
  761. HMENU hMenuAll;
  762. HMENU hMenuStorage;
  763. hMenuAll = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT_MENU));
  764. hMenuStorage = GetSubMenu(hMenuAll, 1);
  765. // Enable/disable delete
  766. if( !cDevFiles->OkToDelete() )
  767. {
  768. EnableMenuItem( hMenuStorage, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED );
  769. }
  770. TrackPopupMenu( hMenuStorage,
  771. TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  772. LOWORD(lParam),
  773. HIWORD(lParam),
  774. 0,
  775. hWnd,
  776. NULL);
  777. DestroyMenu(hMenuAll);
  778. break;
  779. }
  780. case WM_COMMAND :
  781. {
  782. switch (wParam)
  783. {
  784. case IDM_PROPERTIES :
  785. {
  786. // Display propeties dialog for this storage
  787. INT nNumItems = ListView_GetItemCount( hWnd );
  788. CItemData *pStorage = NULL;
  789. // Get the storage of the item with focus.
  790. //
  791. for( int iIndex=0; iIndex < nNumItems; iIndex++ )
  792. {
  793. if( ListView_GetItemState( hWnd, iIndex, LVIS_FOCUSED ) )
  794. {
  795. pStorage = (CItemData *) ListView_GetLParam( hWnd, iIndex );
  796. break;
  797. }
  798. }
  799. // Display the properties dialog
  800. if( pStorage )
  801. {
  802. DialogBoxParam( g_hInst,
  803. MAKEINTRESOURCE(IDD_PROPERTIES_STORAGE),
  804. g_hwndMain,
  805. StorageProp_DlgProc,
  806. (LPARAM)pStorage );
  807. }
  808. break;
  809. }
  810. case IDM_DELETE :
  811. {
  812. // Pass delete message on to main window
  813. PostMessage( g_hwndMain, uMsg, wParam, lParam );
  814. }
  815. }
  816. }
  817. default:
  818. break;
  819. }
  820. return CallWindowProc( cDevFiles->m_wndprocDevFiles_LV, hWnd, uMsg, wParam, lParam );
  821. }