Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

830 lines
26 KiB

///////////////////////////////////////////////////////////
//
//
// 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;
}