/////////////////////////////////////////////////////////// // // // HHFinder.cpp : Implementation of CHHFinder // // #include "header.h" #ifdef _DEBUG #undef THIS_FILE static const CHAR THIS_FILE[] = __FILE__; #endif #include "resource.h" #include "strtable.h" #include "atlinc.h" // includes for ATL. #include "HHFinder.h" #include "cdlg.h" #include "wwheel.h" #include "secwin.h" // Used to lock toplevel windows before displaying a dialog. #include "lockout.h" // defines #define HH_VERSION_1_3 // define this is build HH 1.3 or newer /////////////////////////////////////////////////////////// // // Internal Structure Definition // /////////////////////////////////////////////////////////// // // HHREMOVEABLE // typedef struct _hhremovable { UINT uiDriveType; PCSTR pszDriveLetter; PCSTR pszVolumeName; PSTR* ppszLocation; } HHREMOVABLE; /////////////////////////////////////////////////////////// // // Globals // #ifdef _DEBUG static BOOL g_bShowMessage = TRUE; #endif /////////////////////////////////////////////////////////// // // Prototypes // INT_PTR CALLBACK RemovableMediaDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); /////////////////////////////////////////////////////////// // // Functions // /////////////////////////////////////////////////////////// // // GetPathAndFileName // PCSTR GetPathAndFileName( PCSTR pszFilename, PSTR pszPathBuffer, PSTR pszFilenameBuffer ) { CHAR szPathname[MAX_PATH]; PSTR pszFile; GetFullPathName( pszFilename, sizeof(szPathname), szPathname, &pszFile ); lstrcpyn( pszPathBuffer, szPathname, (int)(((DWORD_PTR)pszFile) - ((DWORD_PTR)&szPathname)) ); strcpy( pszFilenameBuffer, pszFile ); return( pszFilename ); } ///////////////////////////////////////////////////////////////////////////// // CLocationNode class CLocationNode { public: CLocationNode::CLocationNode( PCSTR pszLocationId ) { m_pszLocationId = new CHAR[strlen(pszLocationId)+1]; strcpy( (PSTR) m_pszLocationId, pszLocationId ); m_pNext = NULL; } CLocationNode::~CLocationNode( ) { delete [] (PSTR) m_pszLocationId; } CLocationNode* GetNext() { return m_pNext; } CLocationNode* SetNext( CLocationNode* pNext ) { m_pNext = pNext; return m_pNext; } PCSTR GetLocationId() { return m_pszLocationId; } private: PCSTR m_pszLocationId; CLocationNode* m_pNext; }; ///////////////////////////////////////////////////////////////////////////// // CLocationList class CLocationList { public: CLocationList::CLocationList() { m_iCount = 0; m_pHead = NULL; m_pTail = NULL; } CLocationList::~CLocationList() { Free(); } void CLocationList::Free() { CLocationNode* pNode = m_pHead; for( int i=0; i < m_iCount; i++ ) { CLocationNode* pNodeNext = pNode->GetNext(); delete pNode; pNode = pNodeNext; } m_iCount = 0; m_pHead = NULL; m_pTail = NULL; } CLocationNode* CLocationList::Add( PCSTR pszLocationId ) { CLocationNode* pNode = new CLocationNode( pszLocationId ); if( m_iCount ) m_pTail->SetNext( pNode ); else m_pHead = pNode; m_pTail = pNode; m_iCount++; return pNode; } CLocationNode* CLocationList::Find( PCSTR pszLocationId ) { CLocationNode* pNode = m_pHead; for( int i=0; i < m_iCount; i++ ) { if( strcmp( pszLocationId, pNode->GetLocationId() ) == 0 ) break; CLocationNode* pNodeNext = pNode->GetNext(); pNode = pNodeNext; } return pNode; } private: int m_iCount; CLocationNode* m_pHead; CLocationNode* m_pTail; }; CLocationList g_LocationSkipList; ///////////////////////////////////////////////////////////////////////////// // CHHFinder HRESULT STDMETHODCALLTYPE CHHFinder::FindThisFile(const WCHAR* pwszFileName, WCHAR** ppwszPathName, BOOL* pfRecordPathInRegistry ) { CExCollection* pCollection; CExTitle* pTitle = NULL; PCSTR pszPathName = NULL; CStr PathName; HRESULT hr = S_OK; // guarantee that we never record this value in the registry since it can always change. *pfRecordPathInRegistry = FALSE; CHAR pszFileName[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, pwszFileName, -1, pszFileName, MAX_PATH, NULL, NULL); // get a pointer to the title and use this to get the fullpathname pCollection = GetCurrentCollection(NULL, pszFileName); if( pCollection ) hr = pCollection->URL2ExTitle( pszFileName, &pTitle ); #if 0 // if this is not a collection or we could not find the title then give // the ::FindThisFile function a try (since we know removable media // is not supported for non-collections anyway) if( !pCollection || !pTitle ) { // check the directory where the master file of the current collection lives CExCollection* pCurCollection = NULL; if( g_pCurrentCollection ) pCurCollection = g_pCurrentCollection; else if( g_phmData && g_phmData[0] ) pCurCollection = g_phmData[0]->m_pTitleCollection; if( pCurCollection ) { CHAR szPathName[_MAX_PATH]; CHAR szFileName[_MAX_FNAME]; CHAR szExtension[_MAX_EXT]; SplitPath((PSTR)pszFileName, NULL, NULL, szFileName, szExtension); CHAR szMasterPath[_MAX_PATH]; CHAR szMasterDrive[_MAX_DRIVE]; SplitPath((PSTR)pCurCollection->m_csFile, szMasterDrive, szMasterPath, NULL, NULL); strcpy( szPathName, szMasterDrive ); CatPath( szPathName, szMasterPath ); CatPath( szPathName, szFileName ); strcat( szPathName, szExtension ); if( (GetFileAttributes(szPathName) != HFILE_ERROR) ) { PathName = szPathName; pszPathName = PathName.psz; } } if( !pszPathName ) { if( ::FindThisFile( NULL, pszFileName, &PathName, FALSE ) ) { pszPathName = PathName.psz; } else { #ifdef _DEBUG CHAR szMsg[1024]; wsprintf( szMsg, "HHFinder Debug Message\n\nCould not locate the file \"%s\".", pszFileName ); MsgBox( szMsg, MB_OK ); #endif return S_OK; } } } #endif // Removable media support (Refresh bypasses BeforeNavigate so we need this here). // // Note, this must be one of the first things we do since the user can // change the title's location // if( pTitle ) { pszPathName = pTitle->GetPathName(); if( FAILED(hr = EnsureStorageAvailability( pTitle )) ) { return S_OK; } } // if we made it here than this mean we found it (if is does exist) // and pszPathName points to the full pathname LPMALLOC pMalloc; WCHAR pwszPathName[MAX_PATH]; *ppwszPathName = NULL; if( pszPathName && *pszPathName ) { MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, pwszPathName, MAX_PATH); // allocate and copy the pathname if( SUCCEEDED(hr = CoGetMalloc(1, &pMalloc)) ) { *ppwszPathName = (WCHAR*) pMalloc->Alloc( (wcslen(pwszPathName)+1)*sizeof(WCHAR) ); if( !*ppwszPathName ) { hr = E_OUTOFMEMORY; } else { wcscpy( *ppwszPathName, pwszPathName ); hr = S_OK; } pMalloc->Release(); } } if (*ppwszPathName == NULL) hr = STG_E_FILENOTFOUND; return hr; } ///////////////////////////////////////////////////////////////////////////// // EnsureStorageAvailability // Code to detect and handle Advanced Media Support issues (formerly RMS issues) // // Types are: // // HHRMS_TYPE_TITLE (default) // HHRMS_TYPE_COMBINED_QUERY // HHRMS_TYPE_ATTACHMENT // a.k.a Sample // // return values are as follows: // S_OK - The storage is available (party on!) // HHRMS_S_LOCATION_UPDATE - The user changed the location of the volume // E_FAIL - The storage is unknown (caller should handle this failure condition) // HHRMS_E_SKIP - User choose to skip this volume just this time // HHRMS_E_SKIP_ALWAYS - User choose to skip this volume for this entire session // // For URL navigation, we should always volume check and always prompt. // // For Queries, we should volume check for chm files and not volume check for chq files // and we will always prompt for the volume for this session unless the user // selects cancel. // HRESULT EnsureStorageAvailability( CExTitle* pTitle, UINT uiFileType, BOOL bVolumeCheckIn, BOOL bAlwaysPrompt, BOOL bNeverPrompt ) { HRESULT hr = S_OK; // if we do not have a title pointer this indicates that the URL does not belong to a // compressed title and thus we should claim the storage is available and let IE decide // what to do with it if( !pTitle ) return S_OK; BOOL bVolumeCheck = bVolumeCheckIn; // Get the location information LOCATIONHISTORY* pLocationHistory = pTitle->GetUsedLocation(); // Get the collection CExCollection* pCollection = pTitle->m_pCollection; // Only check removable media when running in a collection // if(pCollection && pCollection->IsSingleTitle()) return S_OK; // Get the location identifier CHAR szLocationId[MAX_PATH]; CLocation* pLocation = NULL; if( pLocationHistory ) { switch( uiFileType ) { case HHRMS_TYPE_TITLE: strcpy( szLocationId, pLocationHistory->LocationId ); break; case HHRMS_TYPE_COMBINED_QUERY: if( pLocationHistory->QueryLocation && pLocationHistory->QueryLocation[0] ) strcpy( szLocationId, pLocationHistory->QueryLocation ); else if( pLocationHistory->LocationId && pLocationHistory->LocationId[0] ) strcpy( szLocationId, pLocationHistory->LocationId ); break; case HHRMS_TYPE_ATTACHMENT: if( pLocationHistory->SampleLocation && pLocationHistory->SampleLocation[0] ) strcpy( szLocationId, pLocationHistory->SampleLocation ); else if( pLocationHistory->LocationId && pLocationHistory->LocationId[0] ) strcpy( szLocationId, pLocationHistory->LocationId ); break; default: strcpy( szLocationId, pLocationHistory->LocationId ); break; } pLocation = pCollection->m_Collection.FindLocation( szLocationId ); } // if we have location information then get the details about it // otherwise never prompt or volume check (check existence only). PCSTR pszVolumeLabel = NULL; PCSTR pszVolumeName = NULL; if( pLocation ) { pszVolumeLabel = pLocation->GetVolume(); // Get the volume label pszVolumeName = pLocation->GetTitle(); // Get volume's friendly name } else { bVolumeCheck = FALSE; bNeverPrompt = TRUE; } // Get the pathname PCSTR pszPathname = NULL; switch( uiFileType ) { case HHRMS_TYPE_TITLE: pszPathname = pTitle->GetPathName(); break; case HHRMS_TYPE_COMBINED_QUERY: pszPathname = pTitle->GetQueryName(); break; case HHRMS_TYPE_ATTACHMENT: pszPathname = pTitle->GetCurrentAttachmentName(); break; default: return E_FAIL; break; } // Get the location path and filename CHAR szPath[MAX_PATH]; CHAR szFilename[MAX_PATH]; PCSTR pszPath = szPath; szPath[0]= 0; szFilename[0]= 0; if( pLocation ) { strcpy( szPath, pLocation->GetPath() ); CHAR szExt[MAX_PATH]; CHAR szTmpPath[MAX_PATH]; CHAR szDrive[MAX_PATH]; CHAR szDir[MAX_PATH]; szTmpPath[0] = 0; SplitPath( pszPathname, szDrive, szDir, szFilename, szExt ); strcat( szFilename, szExt ); // make sure that the filename includes and subdirs not part of the path // // for example the path may be e:\samples but the pathname is c:\samples\sfl\samp.sfl // and thus the path is e:\samples but the filename should be sfl\samp.sfl and not // just samp.sfl if( szDrive[0] ) strcpy( szTmpPath, szDrive ); if( szDir ) strcat( szTmpPath, szDir ); // STang: // Buggy, must make sure pszPath is a prefix of szTmpPath ( except the drive letter ) // if( strlen( szTmpPath ) != strlen( pszPath ) ) if( strnicmp(pszPath+1,szTmpPath+1,(int)strlen(pszPath)-1) == 0 && strlen( szTmpPath ) > strlen( pszPath ) ) { CHAR sz[MAX_PATH]; strcpy( sz, &szTmpPath[strlen(pszPath)] ); strcat( sz, szFilename ); strcpy( szFilename, sz ); } } else GetPathAndFileName( pszPathname, szPath, szFilename ); // make sure to disable the default error message the OS displays // when doing a file check on removable media UINT uiErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS ); // get the drive of the path CHAR szDriveRoot[4]; lstrcpyn( szDriveRoot, szPath, 4 ); #define mkupper(c) ((c)-'a'+'A') if( szDriveRoot[0] >= 'a' ) szDriveRoot[0] = mkupper(szDriveRoot[0]); // make it upper case // Make copies of various settings to support location updating CHAR szVolumeLabelTry[MAX_PATH]; CHAR szPathTry[MAX_PATH]; CHAR szPathnameTry[MAX_PATH]; CHAR szDriveRootTry[4]; // setup the paths to try strcpy( szPathTry, szPath ); strcpy( szPathnameTry, pszPathname ); strcpy( szDriveRootTry, szDriveRoot ); if( bVolumeCheck ) { //HH Bug 2521: Make sure pszVolumeLabel is non-null before copy. ASSERT( pszVolumeLabel ); strcpy( szVolumeLabelTry, pszVolumeLabel ); } else { strcpy( szVolumeLabelTry, "" ); } // Setup prompting loop starting conditions BOOL bExistenceCheck = TRUE; BOOL bPrompt = FALSE; // === MAIN PROMPTING LOOP BEGINS HERE === // while( TRUE ) { // make sure to add a backslash if the second CHAR is a colon // sometimes we will get just "d:" instead of "d:\" and thus // GetDriveType will fail under this circumstance if( szDriveRootTry[1] == ':' ) { szDriveRootTry[2] = '\\'; szDriveRootTry[3] = 0; } // Get media type UINT uiDriveType = DRIVE_UNKNOWN; if( szDriveRootTry[1] == ':' && szDriveRootTry[2] == '\\' ) { uiDriveType = GetDriveType(szDriveRootTry); } else if( szDriveRootTry[0] == '\\' && szDriveRootTry[1] == '\\' ) { uiDriveType = DRIVE_REMOTE; bVolumeCheck = FALSE; // never check volume label of network drives } // Determine and handle the drive types bExistenceCheck = TRUE; switch( uiDriveType ) { case DRIVE_FIXED: case DRIVE_RAMDISK: uiDriveType = DRIVE_FIXED; // fall thru case DRIVE_REMOTE: bVolumeCheck = FALSE; break; case DRIVE_REMOVABLE: case DRIVE_CDROM: case DRIVE_UNKNOWN: case DRIVE_NO_ROOT_DIR: if( bVolumeCheckIn ) bVolumeCheck = TRUE; break; default: // unknown types bVolumeCheck = FALSE; bExistenceCheck = FALSE; break; } // Prompt for media if( bPrompt ) { CHAR szDriveLetter[4]; szDriveLetter[0] = szDriveRoot[0]; szDriveLetter[1] = szDriveRoot[1]; szDriveLetter[2] = 0; HHREMOVABLE Removable; Removable.uiDriveType = uiDriveType; Removable.pszDriveLetter = szDriveLetter; Removable.pszVolumeName = pszVolumeName; PSTR pszPathTry = szPathTry; Removable.ppszLocation = &pszPathTry; HCURSOR hCursor = GetCursor(); // Disable all of the toplevel application windows, before we bring up the dialog. CLockOut LockOut ; LockOut.LockOut(GetActiveWindow()) ; // Display the dialog box. INT_PTR iReturn = DialogBoxParam( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_REMOVEABLE_MEDIA_PROMPT), GetActiveWindow(), RemovableMediaDialogProc, (LPARAM) &Removable ); // Enable all of the windows which we disabled. LockOut.Unlock() ; SetCursor( hCursor ); if( iReturn == IDOK ) { strcpy( szPathnameTry, pszPathTry ); CatPath( szPathnameTry, szFilename ); lstrcpyn( szDriveRootTry, pszPathTry, 4 ); bPrompt = FALSE; continue; } else if( iReturn == IDCANCEL ) { if( !bAlwaysPrompt ) g_LocationSkipList.Add( szLocationId ); hr = HHRMS_E_SKIP; break; } } // Validate media is present using the volume label, if needed if( bVolumeCheck ) { CHAR szVolume[MAX_PATH]; szVolume[0] = 0; CHAR szFileSystemName[MAX_PATH]; DWORD dwMaximumComponentLength = 0; DWORD dwFileSystemFlags = 0; BOOL bReturn = GetVolumeInformation( szDriveRootTry, szVolume, sizeof(szVolume), NULL, &dwMaximumComponentLength, &dwFileSystemFlags, szFileSystemName, sizeof(szFileSystemName) ); if( bVolumeCheckIn && (!bReturn || (strcmp( szVolume, szVolumeLabelTry ) != 0)) ) bExistenceCheck = FALSE; } // if the file exists, and it matches the chi file (for title checks only) the we have the right media if( bExistenceCheck && IsFile( szPathnameTry ) && ((uiFileType==HHRMS_TYPE_TITLE)?pTitle->EnsureChmChiMatch( szPathnameTry ):TRUE ) ) { hr = S_OK; // TODO: the version of MSDN that shipped with VS 6.0 is broken for net installs. // For a network install, they erroneously set the volume label for CD2, also // known as "98VS-1033-CD2", to "DN600ENU1" instead of "DN600ENU2". To fix this we // need to ignore the language settings of "1033" or "ENU" and make the appropriate // change to the volume label. We must do this before we call UpdateLocation since // it could change the location information for CD1 when the user updates the CD2 // location information. // Never change the volume label unless the new destination is // removable media! // // Setup should adhere to the following rules: // // 1. Each local disk and network destination path must use a // volume name unique for each set of titles from each CD source // and they must be unique from the CD source volume label. // It is advised that these volume names be the volume label name // of the removable media (sahipped media) that the group came // from appended with the destination type name and number such as // "-LocalX" or "-NetX". // 2. Volume names for CD "destinations" must be identical to the // CD's volume name. // 3. Note, locations with the same volume name will automatically // get their path updated when any one of them changes. // // if the path did change then update the information, otherwise were done if( lstrcmpi( szPathTry, szPath ) != 0 ) { // STang char * pcVolume = NULL; if ( ( (uiDriveType == DRIVE_REMOVABLE) || (uiDriveType == DRIVE_CDROM) ) && bVolumeCheck ) pcVolume = szVolumeLabelTry; pCollection->UpdateLocation( (PSTR) szLocationId, szPathTry, pcVolume ); // pCollection->UpdateLocation( (PSTR) szLocationId, szPathTry, // ( (uiDriveType == DRIVE_REMOVABLE) || (uiDriveType == DRIVE_CDROM)) ? szVolumeLabelTry : NULL ); hr = HHRMS_S_LOCATION_UPDATE; } break; } // Bail out if we never want to prompt for media if( bNeverPrompt ) { #ifdef _DEBUG if( g_bShowMessage && (uiFileType != HHRMS_TYPE_COMBINED_QUERY) ) { CHAR szMsg[1024]; wsprintf( szMsg, "HHFinder Debug Message\n\n" "Could not find the file:\n \"%s\"\n" "at the location specified.", szPathnameTry ); if( pTitle && pTitle->m_pTitle ) { CHAR szMsg2[1024]; wsprintf( szMsg2, "\n\nTitle ID: \"%s\".", pTitle->m_pTitle->GetId() ); strcat( szMsg, szMsg2 ); } strcat( szMsg, "\n\nPress 'OK' to continue or 'Cancel' to disable this warning."); int iReturn = MsgBox( szMsg, MB_OKCANCEL ); if( iReturn == IDCANCEL ) g_bShowMessage = FALSE; } #endif // if existence check was desired then this is a failure condition if( bExistenceCheck ) { hr = E_FAIL; break; } // Bailout and let the caller know we are skipping this one hr = HHRMS_E_SKIP; break; } // If we do not require that we always prompt, check the volume against // our skip list if( !bAlwaysPrompt ) { if( !bNeverPrompt ) if( g_LocationSkipList.Find( szLocationId ) ) { hr = HHRMS_E_SKIP_ALWAYS; break; } } #ifdef _DEBUG // Let the user know that we could not find the title at the location specified if( bPrompt ) { CHAR szMsg[1024]; wsprintf( szMsg, "HHFinder Debug Message\n\n" "Could not find the file:\n \"%s\"\n" "at the location specified.", szFilename ); if( pTitle && pTitle->m_pTitle ) { CHAR szMsg2[1024]; wsprintf( szMsg2, "\n\nTitle ID: \"%s\".", pTitle->m_pTitle->GetId() ); strcat( szMsg, szMsg2 ); } MsgBox( szMsg, MB_OKCANCEL ); } #endif // restore the original path information, and continue strcpy( szPathTry, szPath ); strcpy( szPathnameTry, pszPathname ); strcpy( szDriveRootTry, szDriveRoot ); if( bVolumeCheck ) { //HH Bug 2521: Make sure pszVolumeLabel is non-null before copy. ASSERT( pszVolumeLabel ); strcpy( szVolumeLabelTry, pszVolumeLabel ); } else { strcpy( szVolumeLabelTry, "" ); } bPrompt = TRUE; } // === MAIN PROMPTING LOOP ENDS HERE === // // restore the previous error mode SetErrorMode( uiErrorMode ); return hr; } ///////////////////////////////////////////////////////////////////////////// // CD Swap Dialog INT_PTR CALLBACK RemovableMediaDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HHREMOVABLE* pRemovable = NULL; static HWND hWndIcon = NULL; switch( uMsg ) { case WM_INITDIALOG: { pRemovable = (HHREMOVABLE*) lParam; // get and set our dialog title title PCSTR pszTitle = GetStringResource( IDS_MSGBOX_TITLE ); SetWindowText( hDlg, pszTitle ); //get media name and icon PCSTR pszMediaName = NULL; PCSTR pszIcon = NULL; DWORD dwFormatMessage = 0; if( pRemovable->uiDriveType == DRIVE_REMOVABLE ) { pszIcon = "IconDisk350"; pszMediaName = GetStringResource( IDS_REMOVABLE_MEDIA_DISK ); // "disk" dwFormatMessage = IDS_REMOVABLE_MEDIA_MESSAGE_FORMAT; } #ifdef HH_VERSION_1_3 else if( pRemovable->uiDriveType == DRIVE_REMOTE ) { pszIcon = "IconRemote"; pszMediaName = GetStringResource( IDS_REMOVABLE_MEDIA_REMOTE ); // "Network location" dwFormatMessage = IDS_REMOVABLE_MEDIA_MESSAGE_FORMAT2; } else if( pRemovable->uiDriveType == DRIVE_FIXED ) { pszIcon = "IconFixed"; pszMediaName = GetStringResource( IDS_REMOVABLE_MEDIA_FIXED ); // "local disk" dwFormatMessage = IDS_REMOVABLE_MEDIA_MESSAGE_FORMAT2; } #endif else /* if( pRemovable->uiDriveType == DRIVE_CDROM ) */ { pszIcon = "IconCDROM"; pszMediaName = GetStringResource( IDS_REMOVABLE_MEDIA_CDROM ); // "CD-ROM disc" dwFormatMessage = IDS_REMOVABLE_MEDIA_MESSAGE_FORMAT; } CHAR szMediaName[64]; strcpy( szMediaName, pszMediaName ); // set the icon hWndIcon = CreateWindow( TEXT( "static" ), pszIcon, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_ICON, 15, 15, 0, 0, hDlg, NULL, _Module.GetModuleInstance(), NULL ); // get location message format string PCSTR pszFormat = GetStringResource( dwFormatMessage ); CHAR szFormat[256]; strcpy( szFormat, pszFormat ); // format the location message DWORD dwArgCount = 3; #ifdef HH_VERSION_1_3 if( dwFormatMessage == IDS_REMOVABLE_MEDIA_MESSAGE_FORMAT2 ) dwArgCount = 2; #endif DWORD_PTR* pArg = new DWORD_PTR[dwArgCount]; pArg[0] = (DWORD_PTR) szMediaName; pArg[1] = (DWORD_PTR) pRemovable->pszVolumeName; if( dwArgCount == 3 ) pArg[2] = (DWORD_PTR) pRemovable->pszDriveLetter; CHAR szMessage[1024]; FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, szFormat, 0, 0, szMessage, sizeof(szMessage), (va_list*) pArg ); delete [] pArg; // set the location message #ifdef HH_VERSION_1_3 ::SendMessage(GetDlgItem( hDlg, IDC_LOCATION_NAME ), WM_SETFONT, (WPARAM) _Resource.GetUIFont(), FALSE); #else ::SendMessage(GetDlgItem( hDlg, IDC_LOCATION_NAME ), WM_SETFONT, (WPARAM) _Resource.DefaultFont(), FALSE); #endif SetWindowText( GetDlgItem( hDlg, IDC_LOCATION_NAME ), szMessage ); // set the location path #ifdef HH_VERSION_1_3 ::SendMessage(GetDlgItem( hDlg, IDC_LOCATION_PATH ), WM_SETFONT, (WPARAM) _Resource.GetUIFont(), FALSE); #else ::SendMessage(GetDlgItem( hDlg, IDC_LOCATION_PATH ), WM_SETFONT, (WPARAM) _Resource.DefaultFont(), FALSE); #endif SetWindowText( GetDlgItem( hDlg, IDC_LOCATION_PATH ), *(pRemovable->ppszLocation) ); // disable the location path for now //EnableWindow( GetDlgItem( hDlg, IDC_LOCATION_PATH ), FALSE ); // center the dialog CenterWindow( GetParent( hDlg ), hDlg ); return TRUE; } case WM_COMMAND: if( LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL ) { // return the path GetWindowText( GetDlgItem( hDlg, IDC_LOCATION_PATH ), (PSTR) *(pRemovable->ppszLocation), MAX_PATH ); // make sure the returned path includes a trailing backslash PSTR* ppsz = pRemovable->ppszLocation; int iLen = (int)strlen(*ppsz); if( (*ppsz)[iLen-1] != '\\' ) { (*ppsz)[iLen] = '\\'; (*ppsz)[iLen+1] = 0; } DestroyWindow( hWndIcon ); pRemovable = NULL; hWndIcon = NULL; EndDialog( hDlg, LOWORD( wParam ) ); } else if( LOWORD(wParam) == ID_BROWSE ) { CStr strPath; if( DlgOpenDirectory( hDlg, &strPath ) ) { SetWindowText( GetDlgItem( hDlg, IDC_LOCATION_PATH ), strPath.psz ); } } break; } return FALSE; }