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
1001 lines
24 KiB
//
|
|
// Microsoft Windows Media Technologies
|
|
// Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
|
|
//
|
|
|
|
//
|
|
// This workspace contains two projects -
|
|
// 1. ProgHelp which implements the Progress Interface
|
|
// 2. The Sample application WmdmApp.
|
|
//
|
|
// ProgHelp.dll needs to be registered first for the SampleApp to run.
|
|
|
|
|
|
|
|
// Includes
|
|
//
|
|
#include "appPCH.h"
|
|
|
|
// Constants
|
|
//
|
|
#define DEVFILES_LV_NUMCOLS 3
|
|
#define DEVFILES_COL_MARGIN 3
|
|
|
|
#define SMALL_IMAGE_WIDTH 16
|
|
|
|
const CLSID CLSID_WMDMProgressHelper = {0x8297A5B4,0x5113,0x11D3,{0xB2,0x76,0x00,0xC0,0x4F,0x8E,0xC2,0x21}};
|
|
const IID IID_IWMDMProgressHelper = {0x1DCB3A10,0x33ED,0x11d3,{0x84,0x70,0x00,0xC0,0x4F,0x79,0xDB,0xC5}};
|
|
|
|
const CLSID CLSID_WMDMOperationHelper = {0x9FB01A67,0xA11E,0x4653,{0x8E,0xD6,0xB5,0xCE,0x73,0xCD,0xA3,0xE3}};
|
|
const IID IID_IWMDMOperationHelper = {0x41216997,0xC4D9,0x445A,{0xA3,0x88,0x39,0x3D,0x2B,0x85,0xA0,0xE5}};
|
|
|
|
// Macros
|
|
//
|
|
|
|
// Local functions
|
|
//
|
|
INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
// Local Variables
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function implementations
|
|
//
|
|
CDevFiles::CDevFiles()
|
|
{
|
|
m_hwndDevFiles = NULL;
|
|
m_hwndDevFiles_LV = NULL;
|
|
|
|
m_iFolderIcon = 0;
|
|
|
|
m_dwTotalTicks = 0;
|
|
m_dwWorkingTicks = 0;
|
|
|
|
m_pProgHelp = NULL;
|
|
|
|
m_wndprocDevFiles_LV = NULL;
|
|
|
|
CoInitialize( NULL );
|
|
}
|
|
|
|
CDevFiles::~CDevFiles()
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
|
|
HWND CDevFiles::GetHwnd( void )
|
|
{
|
|
return m_hwndDevFiles;
|
|
}
|
|
|
|
HWND CDevFiles::GetHwnd_LV( void )
|
|
{
|
|
return m_hwndDevFiles_LV;
|
|
}
|
|
|
|
|
|
BOOL CDevFiles::Create( HWND hwndParent )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
// Create the Device Files dialog
|
|
//
|
|
m_hwndDevFiles = CreateDialogParam(
|
|
g_hInst,
|
|
MAKEINTRESOURCE( IDD_DEVICEFILES ),
|
|
hwndParent,
|
|
DevFiles_DlgProc,
|
|
(LPARAM)this
|
|
);
|
|
ExitOnNull( m_hwndDevFiles );
|
|
|
|
// Get a handle to the ListView control of the Device Files dialog
|
|
//
|
|
m_hwndDevFiles_LV = GetDlgItem( m_hwndDevFiles, IDC_LV_DEVICEFILES );
|
|
|
|
// Set the user data to be this CDevFiles class pointer
|
|
//
|
|
SetWindowLongPtr( m_hwndDevFiles_LV, GWLP_USERDATA, (LPARAM)this );
|
|
|
|
// Subclass the listview
|
|
//
|
|
m_wndprocDevFiles_LV = (WNDPROC) SetWindowLongPtr(
|
|
m_hwndDevFiles_LV,
|
|
GWLP_WNDPROC,
|
|
(LONG_PTR)WndProc_DevFiles_LV
|
|
);
|
|
|
|
// Initialize image list
|
|
//
|
|
ExitOnFalse( InitImageList() );
|
|
|
|
// Initialize columns
|
|
//
|
|
ExitOnFalse( InitColumns() );
|
|
|
|
// Handle Drag and Dropped files
|
|
//
|
|
DragAcceptFiles( m_hwndDevFiles, TRUE );
|
|
|
|
// Show the window
|
|
//
|
|
ShowWindow( m_hwndDevFiles, SW_SHOW );
|
|
|
|
fRet = TRUE;
|
|
|
|
lExit:
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
VOID CDevFiles::Destroy( void )
|
|
{
|
|
// Remove all the item from the listview control
|
|
//
|
|
RemoveAllItems();
|
|
|
|
// Destroy the window
|
|
//
|
|
if( m_hwndDevFiles )
|
|
{
|
|
DestroyWindow( m_hwndDevFiles );
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CDevFiles::InitImageList( void )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HRESULT hr;
|
|
IMalloc *pMalloc = NULL;
|
|
LPITEMIDLIST pidl = NULL;
|
|
HIMAGELIST hShellImageList = NULL;
|
|
SHFILEINFO si;
|
|
CHAR szWinPath[MAX_PATH+1];
|
|
UINT nRet;
|
|
|
|
// Get the index of the folder icon
|
|
//
|
|
nRet = GetWindowsDirectory( szWinPath, sizeof(szWinPath)/sizeof(szWinPath[0]) );
|
|
if (nRet == 0 || nRet > sizeof(szWinPath)/sizeof(szWinPath[0]))
|
|
{
|
|
// Failed to get the windows directory
|
|
goto lExit;
|
|
}
|
|
|
|
// Get a shell ID list for the desktop folder
|
|
//
|
|
hr = SHGetSpecialFolderLocation( g_hwndMain, CSIDL_DESKTOP, &pidl );
|
|
ExitOnFail( hr );
|
|
|
|
// Get the shell's small icon image list and set that to be the listview's image list
|
|
//
|
|
hShellImageList = (HIMAGELIST) SHGetFileInfo(
|
|
(LPCTSTR)pidl, 0,
|
|
&si, sizeof(si),
|
|
SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON
|
|
);
|
|
if( hShellImageList )
|
|
{
|
|
ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_SMALL );
|
|
}
|
|
|
|
// Get the shell's normal icon image list and set that to be the listview's image list
|
|
//
|
|
hShellImageList = (HIMAGELIST) SHGetFileInfo(
|
|
(LPCTSTR)pidl, 0,
|
|
&si, sizeof(si),
|
|
SHGFI_PIDL | SHGFI_SYSICONINDEX
|
|
);
|
|
if( hShellImageList )
|
|
{
|
|
ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_NORMAL );
|
|
}
|
|
|
|
SHGetFileInfo( szWinPath, 0, &si, sizeof(si), SHGFI_SYSICONINDEX );
|
|
m_iFolderIcon = si.iIcon;
|
|
|
|
// Everything went Ok
|
|
//
|
|
fRet = TRUE;
|
|
|
|
lExit:
|
|
|
|
// Free the pointer to the shell's ID list
|
|
//
|
|
if (pidl)
|
|
{
|
|
hr = SHGetMalloc( &pMalloc );
|
|
if( SUCCEEDED(hr) && pMalloc )
|
|
{
|
|
pMalloc->Free( pidl );
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL CDevFiles::InitColumns( void )
|
|
{
|
|
LVCOLUMN lvcol;
|
|
INT i;
|
|
char szCol[MAX_PATH];
|
|
|
|
//
|
|
// Add the report-view columns to the listview
|
|
// The column names and starting sizes are stored in the resource string table
|
|
//
|
|
|
|
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
|
|
lvcol.fmt = LVCFMT_LEFT;
|
|
|
|
for( i=0; i < DEVFILES_LV_NUMCOLS; i++ )
|
|
{
|
|
// Get the column size
|
|
//
|
|
LoadString( g_hInst, IDS_COLSIZE_1+i, szCol, sizeof(szCol) );
|
|
lvcol.cx = atoi( szCol );
|
|
|
|
// Get the column name
|
|
//
|
|
LoadString( g_hInst, IDS_COLNAME_1+i, szCol, sizeof(szCol) );
|
|
lvcol.pszText = szCol;
|
|
|
|
// Add the column the the listview
|
|
//
|
|
ListView_InsertColumn( m_hwndDevFiles_LV, i, &lvcol );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID CDevFiles::OnSize( LPRECT prcMain )
|
|
{
|
|
INT nX, nY, nW, nH;
|
|
RECT rcMain;
|
|
RECT rcDevice;
|
|
|
|
GetWindowRect( g_hwndMain, &rcMain );
|
|
GetWindowRect( g_cDevices.GetHwnd(), &rcDevice );
|
|
|
|
nX = (rcDevice.right - rcMain.left) - 2*GetSystemMetrics( SM_CXEDGE );
|
|
nY = 0;
|
|
nW = prcMain->right - prcMain->left - nX;
|
|
nH = prcMain->bottom - prcMain->top;
|
|
|
|
SetWindowPos( m_hwndDevFiles, NULL, nX, nY, nW, nH, SWP_NOZORDER );
|
|
SetWindowPos( m_hwndDevFiles_LV, NULL, 0, 0, nW, nH-22, SWP_NOZORDER );
|
|
}
|
|
|
|
|
|
BOOL CDevFiles::SendFilesToDevice( LPSTR pszFiles, UINT uNumFiles )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
WCHAR wszName[MAX_PATH];
|
|
CHAR szName[MAX_PATH];
|
|
LPSTR psz;
|
|
DWORD dwTotalSize = 0L;
|
|
UINT uFile;
|
|
HRESULT hr;
|
|
HTREEITEM hItem;
|
|
CItemData *pItemData;
|
|
IWMDMStorageControl *pStorageControl = NULL;
|
|
IWMDMStorage *pNewObject = NULL;
|
|
IWMDMStorage *pInStorage = NULL;
|
|
IWMDMProgress *pProgress = NULL;
|
|
IWMDMOperation *pOperation = NULL;
|
|
IWMDMOperationHelper *pOperationHelper = NULL;
|
|
IWMDMRevoked *pRevoked = NULL;
|
|
LPWSTR pwszRevokedURL = NULL;
|
|
DWORD dwRevokedURLLen = 0;
|
|
DWORD dwRevokedBitFlag;
|
|
|
|
// Get the selected device/storage
|
|
//
|
|
hItem = g_cDevices.GetSelectedItem( NULL );
|
|
ExitOnNull( hItem );
|
|
|
|
// Get the itemdata class associated with the hItem and
|
|
// retrieve the IWMDMStorage for it
|
|
//
|
|
pItemData = (CItemData *) TreeView_GetLParam( g_cDevices.GetHwnd_TV(), hItem );
|
|
ExitOnNull( pItemData );
|
|
|
|
pInStorage = ( pItemData->m_fIsDevice ? pItemData->m_pRootStorage : pItemData->m_pStorage );
|
|
ExitOnNull( pInStorage );
|
|
|
|
// Tally the file sizes
|
|
//
|
|
psz = pszFiles;
|
|
for( uFile = 0; uFile < uNumFiles; uFile++ )
|
|
{
|
|
dwTotalSize += GetTheFileSize( psz );
|
|
|
|
psz += lstrlen(psz) + 1;
|
|
}
|
|
|
|
// Create the progress dialog
|
|
//
|
|
ExitOnFalse( m_cProgress.Create(g_hwndMain) );
|
|
|
|
m_cProgress.SetOperation( "Sending Files..." );
|
|
m_cProgress.SetCount( 0, uNumFiles );
|
|
m_cProgress.SetRange( 0, 100 );
|
|
m_dwTotalTicks = dwTotalSize;
|
|
m_dwWorkingTicks = 0;
|
|
|
|
// Create the progress interface
|
|
//
|
|
hr = CoCreateInstance(
|
|
CLSID_WMDMProgressHelper,
|
|
NULL, CLSCTX_ALL,
|
|
IID_IWMDMProgress,
|
|
(void**)&pProgress
|
|
);
|
|
ExitOnFail( hr );
|
|
|
|
pProgress->AddRef();
|
|
|
|
hr = pProgress->QueryInterface(
|
|
IID_IWMDMProgressHelper,
|
|
reinterpret_cast<void**> (&m_pProgHelp)
|
|
);
|
|
ExitOnFail( hr );
|
|
|
|
m_pProgHelp->SetNotification( m_hwndDevFiles, WM_DRM_PROGRESS );
|
|
|
|
// Setup for copy using operation interface.
|
|
if( g_bUseOperationInterface )
|
|
{
|
|
// Create the progress interface
|
|
//
|
|
hr = CoCreateInstance(
|
|
CLSID_WMDMOperationHelper,
|
|
NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWMDMOperationHelper,
|
|
(void**)&pOperationHelper );
|
|
ExitOnFail( hr );
|
|
|
|
hr = pOperationHelper->QueryInterface(
|
|
IID_IWMDMOperation,
|
|
reinterpret_cast<void**> (&pOperation) );
|
|
ExitOnFail( hr );
|
|
|
|
// Pass the SecureChannelClient as a pointer to the ProgHelper object.
|
|
// The object is inproc so it should be safe to pass pointers
|
|
pOperationHelper->SetSAC( (void*)g_cWmdm.m_pSAC );
|
|
}
|
|
|
|
|
|
|
|
// Acquire the storage control interface
|
|
//
|
|
hr = pInStorage->QueryInterface(
|
|
IID_IWMDMStorageControl,
|
|
reinterpret_cast<void**>(&pStorageControl)
|
|
);
|
|
ExitOnFail( hr );
|
|
|
|
// Loop through the files, transfering each one
|
|
//
|
|
psz = pszFiles;
|
|
for( uFile = 0; uFile < uNumFiles && !m_cProgress.IsCancelled(); uFile++ )
|
|
{
|
|
hr = StringCchCopy(szName, sizeof(szName)/sizeof(szName[0]), psz);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
fRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!MultiByteToWideChar(
|
|
CP_ACP, 0,
|
|
szName, -1,
|
|
wszName, sizeof(wszName)/sizeof(wszName[0])
|
|
))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
fRet = FALSE;
|
|
break;
|
|
}
|
|
// Set progress bar stats for this file
|
|
//
|
|
m_cProgress.IncCount();
|
|
StripPath( szName );
|
|
m_cProgress.SetDetails( szName );
|
|
m_cProgress.Show( TRUE );
|
|
|
|
UiYield();
|
|
|
|
pNewObject = NULL;
|
|
|
|
// Copy using operation interface.
|
|
if( g_bUseOperationInterface )
|
|
{
|
|
// @@@@ The implementation treats the argument as a WCHAR*, not a
|
|
// BSTR, so this is ok. The simplest solution is to change the
|
|
// interface definition to WCHAR*. Will that cause any harm?
|
|
// (Interface appears to be a private one.)
|
|
//
|
|
// The alternative is to call SysAllocString. The issue with
|
|
// this approach is handling errors. Also SysAllocString inexplicably
|
|
// returns NULL when *wszName = 0. Can that happen?
|
|
//
|
|
pOperationHelper->SetFileName( wszName );
|
|
|
|
hr = pStorageControl->Insert(
|
|
WMDM_MODE_BLOCK | WMDM_CONTENT_FILE | WMDM_CONTENT_OPERATIONINTERFACE,
|
|
NULL,
|
|
pOperation,
|
|
pProgress,
|
|
&pNewObject );
|
|
}
|
|
else
|
|
{
|
|
hr = pStorageControl->Insert(
|
|
WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,
|
|
wszName,
|
|
NULL,
|
|
pProgress,
|
|
&pNewObject );
|
|
}
|
|
|
|
// Handle the case where one of the needed components was revoked
|
|
if( hr == WMDM_E_REVOKED )
|
|
{
|
|
char pszCaption[MAX_PATH];
|
|
char pszErrorMsg[MAX_PATH];
|
|
|
|
// Hide progress window before displaying error messages
|
|
m_cProgress.Show( FALSE );
|
|
|
|
// Get Revocation interface from WMDM
|
|
hr = pStorageControl->QueryInterface( IID_IWMDMRevoked, (void**)&pRevoked );
|
|
if( hr != S_OK || pRevoked == NULL )
|
|
{
|
|
// Latest version of WMDM not avalible on machine?
|
|
fRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
// Get revocation information from WMDM
|
|
hr = pRevoked->GetRevocationURL( &pwszRevokedURL, &dwRevokedURLLen, &dwRevokedBitFlag );
|
|
if( FAILED(hr) )
|
|
{
|
|
fRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
// The application has been revoked
|
|
if( dwRevokedBitFlag & WMDM_APP_REVOKED )
|
|
{
|
|
LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) );
|
|
LoadString( g_hInst, IDS_APP_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) );
|
|
|
|
::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_OK );
|
|
}
|
|
// A component needed for the transfer has been revoked, give the user
|
|
// a chance to look for an update on the internet.
|
|
else
|
|
{
|
|
LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) );
|
|
LoadString( g_hInst, IDS_COMPONENT_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) );
|
|
if( ::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_YESNO ) == IDYES )
|
|
{
|
|
ShellExecuteW(g_hwndMain, L"open", pwszRevokedURL, NULL, NULL, SW_SHOWNORMAL);
|
|
}
|
|
}
|
|
CoTaskMemFree( pwszRevokedURL );
|
|
break;
|
|
}
|
|
|
|
if( SUCCEEDED(hr) && pNewObject )
|
|
{
|
|
CItemData *pStorageItem = new CItemData;
|
|
|
|
if( pStorageItem )
|
|
{
|
|
hr = pStorageItem->Init( pNewObject );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
g_cDevFiles.AddItem( pStorageItem );
|
|
}
|
|
else
|
|
{
|
|
delete pStorageItem;
|
|
}
|
|
}
|
|
|
|
pNewObject->Release();
|
|
}
|
|
|
|
psz += lstrlen(psz) + 1;
|
|
}
|
|
|
|
// Make sure the dialog is hidden and then destroy it
|
|
//
|
|
m_cProgress.SetPos( -1 );
|
|
m_cProgress.Show( FALSE );
|
|
m_cProgress.Destroy();
|
|
|
|
// refresh the device/devicefiles display
|
|
g_cDevices.UpdateSelection( NULL, FALSE );
|
|
|
|
lExit:
|
|
if( pOperationHelper )
|
|
{
|
|
pOperationHelper->Release();
|
|
}
|
|
if( pOperation )
|
|
{
|
|
pOperation->Release();
|
|
}
|
|
if( pStorageControl )
|
|
{
|
|
pStorageControl->Release();
|
|
}
|
|
if( pRevoked )
|
|
{
|
|
pRevoked->Release();
|
|
}
|
|
|
|
if( m_pProgHelp )
|
|
{
|
|
m_pProgHelp->Release();
|
|
m_pProgHelp = NULL;
|
|
}
|
|
|
|
if( pProgress )
|
|
{
|
|
pProgress->Release();
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL CDevFiles::OnDropFiles( HWND hWnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LPSTR lpsz = NULL;
|
|
HANDLE hDrop = (HANDLE) wParam;
|
|
UINT uNumFiles;
|
|
|
|
// Turn the drop list into a double-zero-terminated list of strings
|
|
//
|
|
lpsz = DropListToBuffer( (HDROP)hDrop, LTB_NULL_TERM, &uNumFiles );
|
|
ExitOnNull( lpsz );
|
|
|
|
// Send those files to the selected device
|
|
//
|
|
SendFilesToDevice( lpsz, uNumFiles );
|
|
|
|
lExit:
|
|
|
|
// Close the dragdrop operation
|
|
//
|
|
DragFinish( (HDROP)hDrop );
|
|
|
|
if( lpsz )
|
|
{
|
|
MemFree( lpsz );
|
|
}
|
|
|
|
return 0; // return zero if we process this message
|
|
}
|
|
|
|
|
|
VOID CDevFiles::RemoveAllItems( void )
|
|
{
|
|
INT i;
|
|
INT nCount;
|
|
|
|
nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
|
|
|
|
// Remove the items one at a time, from the bottom up
|
|
//
|
|
for( i=nCount-1; i >= 0; i-- )
|
|
{
|
|
RemoveItem( i );
|
|
}
|
|
}
|
|
|
|
BOOL CDevFiles::RemoveItem( INT nItem )
|
|
{
|
|
CItemData *pStorage;
|
|
|
|
pStorage = (CItemData *) ListView_GetLParam( m_hwndDevFiles_LV, nItem );
|
|
|
|
if( pStorage )
|
|
{
|
|
delete pStorage;
|
|
}
|
|
|
|
return ListView_DeleteItem( m_hwndDevFiles_LV, nItem );
|
|
}
|
|
|
|
BOOL CDevFiles::AddItem( CItemData *pStorage )
|
|
{
|
|
LVITEM lvitem;
|
|
INT nItem;
|
|
CHAR sz[MAX_PATH];
|
|
INT m_iSysFolderIcon = 0;
|
|
|
|
// Set the icon index.
|
|
// If the storage is a folder, use the folder icon, otherwise
|
|
// use the icon associated with that file type.
|
|
//
|
|
if( pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER )
|
|
{
|
|
lvitem.iImage = m_iFolderIcon;
|
|
}
|
|
else
|
|
{
|
|
TCHAR szType[MAX_PATH];
|
|
|
|
lvitem.iImage = GetShellIconIndex(
|
|
pStorage->m_szName,
|
|
szType, sizeof(szType)/sizeof(szType[0])
|
|
);
|
|
}
|
|
|
|
lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
|
lvitem.iItem = 10000;
|
|
lvitem.iSubItem = 0;
|
|
lvitem.pszText = pStorage->m_szName;
|
|
lvitem.lParam = (LPARAM)pStorage;
|
|
|
|
// Insert the item into the listview
|
|
//
|
|
nItem = ListView_InsertItem( m_hwndDevFiles_LV, &lvitem );
|
|
if( -1 == nItem )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the size field blank for a folder, or for the file size for a file
|
|
//
|
|
ListView_SetItemText(
|
|
m_hwndDevFiles_LV,
|
|
nItem,
|
|
1,
|
|
( (pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER) ? " " : FormatBytesToSz(pStorage->m_dwSizeLow, 0, 1, sz, sizeof(sz)) )
|
|
);
|
|
|
|
// Set the description field to be the display date
|
|
//
|
|
{
|
|
SYSTEMTIME systime;
|
|
|
|
// Copy the WMDMDATETIME fields to a SYSTEMTIME structure for manipulation
|
|
//
|
|
systime.wYear = pStorage->m_DateTime.wYear;
|
|
systime.wMonth = pStorage->m_DateTime.wMonth;
|
|
systime.wDayOfWeek = 0;
|
|
systime.wDay = pStorage->m_DateTime.wDay;
|
|
systime.wHour = pStorage->m_DateTime.wHour;
|
|
systime.wMinute = pStorage->m_DateTime.wMinute;
|
|
systime.wSecond = pStorage->m_DateTime.wSecond;
|
|
systime.wMilliseconds = 0;
|
|
|
|
ListView_SetItemText(
|
|
m_hwndDevFiles_LV,
|
|
nItem,
|
|
2,
|
|
FormatSystemTimeToSz( &systime, sz, sizeof(sz) )
|
|
);
|
|
}
|
|
|
|
// Update the status bar with the changes resulting from the insertion of this item
|
|
//
|
|
UpdateStatusBar();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID CDevFiles::UpdateStatusBar( void )
|
|
{
|
|
INT nCount;
|
|
UINT uStrID;
|
|
HTREEITEM hItem = g_cDevices.GetSelectedItem( NULL );
|
|
|
|
if( NULL == hItem )
|
|
{
|
|
// If no device is selected, blank out the pane specifying the number of files
|
|
//
|
|
g_cStatus.SetTextSz( SB_PANE_DEVFILES, "" );
|
|
}
|
|
else
|
|
{
|
|
// If a device is selected, set the statusbar pane that shows the number of files
|
|
//
|
|
nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
|
|
|
|
// Get the grammatically-appropriate format string to use
|
|
//
|
|
if( nCount == 0 )
|
|
{
|
|
uStrID = IDS_SB_DEVICEFILES_MANY;
|
|
}
|
|
else if( nCount == 1 )
|
|
{
|
|
uStrID = IDS_SB_DEVICEFILES_ONE;
|
|
}
|
|
else
|
|
{
|
|
uStrID = IDS_SB_DEVICEFILES_MANY;
|
|
}
|
|
|
|
// Set the text of the pane
|
|
//
|
|
g_cStatus.SetTextFormatted( SB_PANE_DEVFILES, uStrID, nCount, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
INT CDevFiles::GetSelectedItems( INT nItems[], INT *pnSelItems )
|
|
{
|
|
INT nRet = -1;
|
|
INT nNumSelItems = ListView_GetSelectedCount( m_hwndDevFiles_LV );
|
|
INT nNumItems = ListView_GetItemCount( m_hwndDevFiles_LV );
|
|
INT nItemRoom = *pnSelItems;
|
|
INT i;
|
|
INT iIndex;
|
|
|
|
// Initialize return parameters
|
|
//
|
|
*pnSelItems = nNumSelItems;
|
|
|
|
// If there isn't enough room for all the selected items, or if there
|
|
// aren't any selected items, return -1.
|
|
// The space needed is already in the nSelItems OUT param.
|
|
//
|
|
if( nItemRoom < nNumSelItems || 0 == nNumSelItems )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Loop thru all the items to determine whether or not they are
|
|
// selected. Fill in the OUT array with the ones that are.
|
|
//
|
|
for( i=0, iIndex=0; i < nNumItems; i++ )
|
|
{
|
|
UINT uState = ListView_GetItemState( m_hwndDevFiles_LV, i, LVIS_SELECTED | LVIS_FOCUSED );
|
|
|
|
if( uState & LVIS_SELECTED )
|
|
{
|
|
nItems[iIndex++] = i;
|
|
|
|
if( uState & LVIS_FOCUSED )
|
|
{
|
|
// Remember which item has focus, so it can be returned to the caller
|
|
//
|
|
nRet = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there are selected items, but nothing has focus, use the first selected item
|
|
//
|
|
if( nRet == -1 && nNumSelItems > 0 )
|
|
{
|
|
nRet = nItems[0];
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
// Is it ok to delete the currently selected files?
|
|
BOOL CDevFiles::OkToDelete()
|
|
{
|
|
INT nNumItems = ListView_GetItemCount( GetHwnd_LV() );
|
|
CItemData *pStorage = NULL;
|
|
|
|
// Loop thru all the items to determine whether or not they are
|
|
// selected. Enable delete if any selected file can be deleted.
|
|
//
|
|
for( int iIndex=0; iIndex < nNumItems; iIndex++ )
|
|
{
|
|
if( ListView_GetItemState( GetHwnd_LV(), iIndex, LVIS_SELECTED ) )
|
|
{
|
|
pStorage = (CItemData *) ListView_GetLParam( GetHwnd_LV(), iIndex );
|
|
if( pStorage && (pStorage->m_dwAttributes & WMDM_FILE_ATTR_CANDELETE) )
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Non-C++ functions
|
|
//
|
|
|
|
|
|
INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WORD wId = LOWORD((DWORD)wParam);
|
|
WORD wNotifyCode = HIWORD((DWORD)wParam);
|
|
static CDevFiles *cDevFiles = NULL;
|
|
static HWND hwndLV = NULL;
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
cDevFiles = (CDevFiles *)lParam;
|
|
hwndLV = GetDlgItem( hWnd, IDC_LV_DEVICEFILES );
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
|
|
UINT uCode = pnmv->hdr.code;
|
|
|
|
switch( uCode )
|
|
{
|
|
case LVN_BEGINDRAG:
|
|
SendMessage( hwndLV, uMsg, wParam, lParam );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_DRM_PROGRESS:
|
|
{
|
|
PROGRESSNOTIFY *pNotify = (PROGRESSNOTIFY *)lParam;
|
|
|
|
switch( pNotify->dwMsg )
|
|
{
|
|
case SFM_BEGIN:
|
|
break;
|
|
|
|
case SFM_PROGRESS:
|
|
{
|
|
DWORD dwTicks = cDevFiles->m_dwWorkingTicks + pNotify->dwCurrentTicks;
|
|
|
|
cDevFiles->m_cProgress.SetPos(
|
|
(INT)( dwTicks*100/cDevFiles->m_dwTotalTicks )
|
|
);
|
|
cDevFiles->m_cProgress.SetBytes(
|
|
dwTicks,
|
|
cDevFiles->m_dwTotalTicks
|
|
);
|
|
}
|
|
break;
|
|
|
|
case SFM_END:
|
|
cDevFiles->m_dwWorkingTicks += pNotify->dwTotalTicks;
|
|
break;
|
|
}
|
|
|
|
UiYield();
|
|
|
|
// If the user cancelled the operation, tell the progress interface
|
|
//
|
|
if( cDevFiles->m_cProgress.IsCancelled() )
|
|
{
|
|
// Notify progress interface
|
|
//
|
|
cDevFiles->m_pProgHelp->Cancel();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static CDevFiles *cDevFiles = NULL;
|
|
WORD wId = LOWORD((DWORD)wParam);
|
|
WORD wNotifyCode = HIWORD((DWORD)wParam);
|
|
|
|
if( NULL == cDevFiles )
|
|
{
|
|
cDevFiles = (CDevFiles *) GetWindowLongPtr( hWnd, GWLP_USERDATA );
|
|
}
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_DROPFILES:
|
|
return cDevFiles->OnDropFiles( hWnd, wParam, lParam );
|
|
|
|
case WM_KEYDOWN:
|
|
if( wParam == VK_DELETE )
|
|
{
|
|
SendMessage( g_hwndMain, WM_DRM_DELETEITEM, 0, 0 );
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU :
|
|
{
|
|
HMENU hMenuAll;
|
|
HMENU hMenuStorage;
|
|
|
|
hMenuAll = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT_MENU));
|
|
hMenuStorage = GetSubMenu(hMenuAll, 1);
|
|
|
|
// Enable/disable delete
|
|
if( !cDevFiles->OkToDelete() )
|
|
{
|
|
EnableMenuItem( hMenuStorage, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED );
|
|
}
|
|
|
|
TrackPopupMenu( hMenuStorage,
|
|
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
|
|
LOWORD(lParam),
|
|
HIWORD(lParam),
|
|
0,
|
|
hWnd,
|
|
NULL);
|
|
|
|
DestroyMenu(hMenuAll);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND :
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case IDM_PROPERTIES :
|
|
{
|
|
// Display propeties dialog for this storage
|
|
INT nNumItems = ListView_GetItemCount( hWnd );
|
|
CItemData *pStorage = NULL;
|
|
|
|
// Get the storage of the item with focus.
|
|
//
|
|
for( int iIndex=0; iIndex < nNumItems; iIndex++ )
|
|
{
|
|
if( ListView_GetItemState( hWnd, iIndex, LVIS_FOCUSED ) )
|
|
{
|
|
pStorage = (CItemData *) ListView_GetLParam( hWnd, iIndex );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Display the properties dialog
|
|
if( pStorage )
|
|
{
|
|
DialogBoxParam( g_hInst,
|
|
MAKEINTRESOURCE(IDD_PROPERTIES_STORAGE),
|
|
g_hwndMain,
|
|
StorageProp_DlgProc,
|
|
(LPARAM)pStorage );
|
|
}
|
|
break;
|
|
}
|
|
case IDM_DELETE :
|
|
{
|
|
// Pass delete message on to main window
|
|
PostMessage( g_hwndMain, uMsg, wParam, lParam );
|
|
}
|
|
}
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc( cDevFiles->m_wndprocDevFiles_LV, hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|