// // 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" #include "appRC.h" // Constants // #define _szWNDCLASS_MAIN "DrmXferAppWnd_Main" #define _szMUTEX_APP "DrmXferApplication_Mutex" #define MIN_MAINWND_W 400 #define SHOWBUFFER 10 // Macros // // Global variables // HINSTANCE g_hInst = NULL; HWND g_hwndMain = NULL; CStatus g_cStatus; CDevices g_cDevices; CDevFiles g_cDevFiles; CWMDM g_cWmdm; BOOL g_bUseOperationInterface = FALSE; // Local variables // static HANDLE _hMutexDrmXfer = NULL; // Local functions // static VOID _CleanUp( void ); static VOID _InitSize( void ); static VOID _OnSize( HWND hwnd, WPARAM wParam, LPARAM lParam ); static VOID _OnMove( HWND hwnd, WPARAM wParam, LPARAM lParam ); static BOOL _InitWindow( void ); static BOOL _RegisterWindowClass( void ); static BOOL _UsePrevInstance( void ); // Local non-static functions // int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ); BOOL CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); // Command handlers // #define _nNUM_HANDLERS 5 typedef VOID (*HandleFunc) ( WPARAM wParam, LPARAM lParam ); static VOID _OnDeviceReset( WPARAM wParam, LPARAM lParam ); static VOID _OnDeviceClose( WPARAM wParam, LPARAM lParam ); static VOID _OnViewRefresh( WPARAM wParam, LPARAM lParam ); static VOID _OnFileDelete( WPARAM wParam, LPARAM lParam ); static VOID _OnOptionsUseOperationInterface( WPARAM wParam, LPARAM lParam ); struct { UINT uID; HandleFunc pfnHandler; } _handlers[ _nNUM_HANDLERS ] = { { IDM_DEVICE_RESET, _OnDeviceReset }, { IDM_CLOSE, _OnDeviceClose }, { IDM_REFRESH, _OnViewRefresh }, { IDM_DELETE, _OnFileDelete }, { IDM_OPTIONS_USE_OPERATION_INTERFACE, _OnOptionsUseOperationInterface }, }; // // int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WPARAM wParam; g_hInst = hInstance; InitCommonControls(); if( _UsePrevInstance() ) { return 0; } // Initialize COM // ExitOnFail( CoInitialize(NULL) ); // Initialize registry // SetRegistryParams( g_hInst, HKEY_LOCAL_MACHINE ); // Initialize the local environment and windows // ExitOnFalse( _RegisterWindowClass() ); ExitOnFalse( _InitWindow() ); // Initialize the WMDM // ExitOnFail( g_cWmdm.Init()); // Enter message pump until app is closed // wParam = DoMsgLoop( TRUE ); // Uninitialize COM // CoFreeUnusedLibraries(); CoUninitialize(); return (int)wParam; lExit: return 0; } LRESULT CALLBACK WndProc_Main(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WORD wId = LOWORD( (DWORD)wParam ); WORD wNotifyCode = HIWORD( (DWORD)wParam ); switch( uMsg ) { case WM_CREATE: PostMessage( hWnd, WM_DRM_INIT, 0, 0 ); break; case WM_DRM_INIT: _OnViewRefresh( 0, 0 ); break; case WM_DRM_DELETEITEM: _OnFileDelete( 0, 0 ); break; case WM_COMMAND: // Menu item selected if( BN_CLICKED == wNotifyCode || 0 == wNotifyCode || 1 == wNotifyCode ) { INT i; for( i=0; i < _nNUM_HANDLERS; i++ ) { if( wId == _handlers[i].uID ) { (*_handlers[i].pfnHandler)( wParam, lParam ); return 0; } } } break; case WM_ENDSESSION: if( (BOOL)wParam ) { // shutting down _CleanUp(); } break; case WM_SIZE: _OnSize( hWnd, wParam, lParam ); return 0; case WM_SYSCOMMAND: if( SC_MAXIMIZE == wParam ) { _OnSize( hWnd, wParam, lParam ); return 0; } break; case WM_CLOSE: _CleanUp(); PostQuitMessage( 0 ); break; case WM_MOVE: _OnMove( hWnd, wParam, lParam ); return 0; case WM_KEYDOWN: if( wParam == VK_F5 ) { _OnViewRefresh( 0, 0 ); return 0; } break; case WM_GETMINMAXINFO: { LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam; lpmmi->ptMinTrackSize.x = MIN_MAINWND_W; } return 0; case WM_INITMENU: // Enable/disable 'Delete' - command EnableMenuItem( (HMENU)wParam, IDM_DELETE, MF_BYCOMMAND | (g_cDevFiles.OkToDelete()) ? MF_ENABLED : MF_GRAYED ); break; default: break; } return DefWindowProc( hWnd, uMsg, wParam, lParam ); } VOID _OnViewRefresh( WPARAM wParam, LPARAM lParam ) { HRESULT hr; HCURSOR hCursorPrev; // Show a wait cursor // hCursorPrev = SetCursor( LoadCursor(NULL, IDC_WAIT) ); // Remove all current files // g_cDevFiles.RemoveAllItems(); // Process messages to allow UI to refresh // UiYield(); // Remove all devices // g_cDevices.RemoveAllItems(); // Reset the device enumerator // hr = g_cWmdm.m_pEnumDevice->Reset(); ExitOnFail( hr ); // Loop through all devices and add them to the list // while( TRUE ) { IWMDMDevice *pWmdmDevice; CItemData *pItemDevice; ULONG ulFetched; hr = g_cWmdm.m_pEnumDevice->Next( 1, &pWmdmDevice, &ulFetched ); if( hr != S_OK ) { break; } if( ulFetched != 1 ) { ExitOnFail( hr = E_UNEXPECTED ); } pItemDevice = new CItemData; if( pItemDevice ) { hr = pItemDevice->Init( pWmdmDevice ); if( SUCCEEDED(hr) ) { g_cDevices.AddItem( pItemDevice ); } else { delete pItemDevice; } } pWmdmDevice->Release(); } // Update the device portion of the status bar // g_cDevices.UpdateStatusBar(); // Update the file portion of the status bar // g_cDevFiles.UpdateStatusBar(); // Use the default selection // g_cDevices.UpdateSelection( NULL, FALSE ); // Return cursor to previous state // SetCursor( hCursorPrev ); lExit: return; } VOID _OnDeviceReset( WPARAM wParam, LPARAM lParam ) { CProgress cProgress; CItemData *pItemDevice; HRESULT hr; HTREEITEM hItem; // Get the selected device to reset // hItem = g_cDevices.GetSelectedItem( (LPARAM *)&pItemDevice ); ExitOnNull( hItem ); ExitOnNull( pItemDevice ); // You can only format devices, not individual folders // ExitOnFalse( pItemDevice->m_fIsDevice ); // Create a progress dialog // ExitOnFalse( cProgress.Create(g_hwndMain) ); // Set operation progress values // cProgress.SetOperation( "Initializing Device..." ); cProgress.SetDetails( pItemDevice->m_szName ); cProgress.SetRange( 0, 100 ); cProgress.SetCount( -1, -1 ); cProgress.SetBytes( -1, -1 ); cProgress.Show( TRUE ); hr = pItemDevice->m_pStorageGlobals->Initialize( WMDM_MODE_BLOCK, NULL ); cProgress.Show( FALSE ); cProgress.Destroy(); lExit: // Refresh the display // g_cDevices.UpdateSelection( NULL, FALSE ); } VOID _OnFileDelete( WPARAM wParam, LPARAM lParam ) { CProgress cProgress; HRESULT hr; INT i; INT *pnSelItems = NULL; INT nNumSel; // Get the number of selected items. // Exit if there are no items selected. // nNumSel = 0; g_cDevFiles.GetSelectedItems( pnSelItems, &nNumSel ); ExitOnTrue( 0 == nNumSel ); // Allocate space to hold them the selected items // pnSelItems = new INT[ nNumSel ]; ExitOnNull( pnSelItems ); // Get the selected file(s) to delete // ExitOnTrue( -1 == g_cDevFiles.GetSelectedItems(pnSelItems, &nNumSel) ); // Create a progress dialog // ExitOnFalse( cProgress.Create(g_hwndMain) ); // Set operation progress values // cProgress.SetOperation( "Deleting Files..." ); cProgress.SetRange( 0, nNumSel ); cProgress.SetCount( 0, nNumSel ); cProgress.SetBytes( -1, -1 ); for( i=nNumSel-1; i >= 0; i-- ) { CItemData *pStorage; // Get the storage object for the current item to delete // pStorage = (CItemData *)ListView_GetLParam( g_cDevFiles.GetHwnd_LV(), pnSelItems[i] ); if( NULL != pStorage ) { IWMDMStorageControl *pStorageControl; // Set the name of the object and show the progress dialog // cProgress.SetDetails( pStorage->m_szName ); cProgress.IncCount(); cProgress.IncPos( 1 ); cProgress.Show( TRUE ); hr = pStorage->m_pStorage->QueryInterface( IID_IWMDMStorageControl, reinterpret_cast(&pStorageControl) ); if( SUCCEEDED(hr) ) { hr = pStorageControl->Delete( WMDM_MODE_BLOCK, NULL ); if( SUCCEEDED(hr) ) { ListView_DeleteItem( g_cDevFiles.GetHwnd_LV(), pnSelItems[i] ); } pStorageControl->Release(); } } } cProgress.Show( FALSE ); cProgress.Destroy(); lExit: if( pnSelItems ) { delete [] pnSelItems; } // Refresh the device/devicefiles display // g_cDevices.UpdateSelection( NULL, FALSE ); } VOID _OnDeviceClose( WPARAM wParam, LPARAM lParam ) { PostMessage( g_hwndMain, WM_CLOSE, (WPARAM)0, (LPARAM)0 ); } // VOID _OnOptionsUseOperationInterface( WPARAM wParam, LPARAM lParam ) { HMENU hMainMenu; HMENU hOptionsMenu; // Remember new state g_bUseOperationInterface = !g_bUseOperationInterface; // Check uncheck menu hMainMenu = GetMenu(g_hwndMain); hOptionsMenu = GetSubMenu( hMainMenu, 1 ); CheckMenuItem( hOptionsMenu, IDM_OPTIONS_USE_OPERATION_INTERFACE, MF_BYCOMMAND | (g_bUseOperationInterface ? MF_CHECKED : MF_UNCHECKED)); } BOOL _InitWindow( void ) { BOOL fRet = FALSE; CHAR szApp[MAX_PATH]; LoadString( g_hInst, IDS_APP_TITLE, szApp, sizeof(szApp) ); g_hwndMain = CreateWindowEx( 0L, _szWNDCLASS_MAIN, szApp, WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | DS_3DLOOK | WS_CLIPCHILDREN, 0, 0, 0, 0, NULL, NULL, g_hInst, NULL ); ExitOnNull( g_hwndMain ); ExitOnFalse( g_cDevices.Create(g_hwndMain) ); ExitOnFalse( g_cDevFiles.Create(g_hwndMain) ); ExitOnFalse( g_cStatus.Create(g_hwndMain) ); _InitSize(); // Show the window // ShowWindow( g_hwndMain, SW_SHOW ); fRet = TRUE; lExit: return fRet; } BOOL _RegisterWindowClass (void) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc_Main; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = g_hInst; wc.hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE(IDI_ICON) ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.lpszMenuName = MAKEINTRESOURCE( IDR_MENU ); wc.lpszClassName = _szWNDCLASS_MAIN; return RegisterClass( &wc ); } VOID _CleanUp( void ) { if( _hMutexDrmXfer ) { ReleaseMutex( _hMutexDrmXfer ); CloseHandle( _hMutexDrmXfer ); } g_cDevices.Destroy(); g_cDevFiles.Destroy(); } BOOL _UsePrevInstance( void ) { HWND hwnd; DWORD dwErr; // Look for the mutex created by another instance of this app // _hMutexDrmXfer = CreateMutex( NULL, TRUE, _szMUTEX_APP ); dwErr = GetLastError(); if( !_hMutexDrmXfer ) { // The function failed... don't use this instance // return TRUE; } // If mutex didn't exist, don't use a previous instance // if( dwErr != ERROR_ALREADY_EXISTS ) { return FALSE; } hwnd = FindWindow( _szWNDCLASS_MAIN, NULL ); if( !hwnd ) { // Mutex exists, but the window doesn't? // ReleaseMutex( _hMutexDrmXfer ); CloseHandle( _hMutexDrmXfer ); return TRUE; } // Show main window that already exists // BringWndToTop( hwnd ); return TRUE; } INT _GetRegSize( UINT uStrID_RegPath, UINT uStrID_DefVal ) { DWORD dwRet; dwRet = GetRegDword_StrTbl( IDS_REG_PATH_BASE, uStrID_RegPath, (DWORD)-1, FALSE ); if( (DWORD)-1 == dwRet && -1 != uStrID_DefVal ) { char szDef[32]; LoadString( g_hInst, uStrID_DefVal, szDef, sizeof(szDef) ); dwRet = (DWORD)atoi( szDef ); } return (INT) dwRet; } VOID _InitSize( void ) { INT nX, nY, nW, nH; // // Get the window position values from the registry // nX = _GetRegSize( IDS_REG_KEY_XPOS, (UINT)-1 ); nY = _GetRegSize( IDS_REG_KEY_YPOS, (UINT)-1 ); nW = _GetRegSize( IDS_REG_KEY_WIDTH, IDS_DEF_WIDTH ); nH = _GetRegSize( IDS_REG_KEY_HEIGHT, IDS_DEF_HEIGHT ); // if the position didn't exist in the registry or // the position is off the screen ( +/- nSHOWBUFFER ) // then center the window, otherwise use the position if( nX == -1 || nY == -1 || nX + nW < SHOWBUFFER || nX + SHOWBUFFER > GetSystemMetrics(SM_CXSCREEN) || nY + nH < SHOWBUFFER || nY + SHOWBUFFER > GetSystemMetrics(SM_CYSCREEN) ) { SetWindowPos( g_hwndMain, NULL, 0, 0, nW, nH, SWP_NOMOVE | SWP_NOZORDER ); CenterWindow( g_hwndMain, NULL ); } else { SetWindowPos( g_hwndMain, NULL, nX, nY, nW, nH, SWP_NOZORDER ); } } VOID _OnSize( HWND hwnd, WPARAM wParam, LPARAM lParam ) { WINDOWPLACEMENT wndpl; wndpl.length = sizeof( WINDOWPLACEMENT ); if( GetWindowPlacement(hwnd, &wndpl) ) { DWORD dwW = wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left; DWORD dwH = wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top; RECT rcMain; WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_WIDTH, dwW ); WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_HEIGHT, dwH ); GetClientRect( hwnd, &rcMain ); // set the position and size of the device window // g_cDevices.OnSize( &rcMain ); // set the position and size of the device files window // g_cDevFiles.OnSize( &rcMain ); // set the position of the status bar // g_cStatus.OnSize( &rcMain ); } } VOID _OnMove( HWND hwnd, WPARAM wParam, LPARAM lParam ) { WINDOWPLACEMENT wndpl; if( hwnd != g_hwndMain ) { return; } wndpl.length = sizeof(WINDOWPLACEMENT); if( GetWindowPlacement(hwnd, &wndpl) ) { WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_XPOS, wndpl.rcNormalPosition.left ); WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_YPOS, wndpl.rcNormalPosition.top ); } }