|
|
//----------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
// All rights reserved.
//
// File Name:
// adddirs.c
//
// Description:
// This file contains the dlgproc and friends of the additional
// dirs page.
//
//----------------------------------------------------------------------------
#include "pch.h"
#include "resource.h"
//
// These are the names of our special roots in the tree-view. They are
// loaded from the resource.
//
static TCHAR *StrOemRootName; static TCHAR *StrSysDriveName; static TCHAR *StrSysDirName; static TCHAR *StrOtherDrivesName; static TCHAR *StrPnpDriversName; static TCHAR *StrTempFilesName; static TCHAR *StrSysprepFilesName; static TCHAR *StrTextmodeFilesName;
//
// The below types and vars support the extra data that we put on tree-view
// items (the lParam in a TVITEM).
//
// We ONLY put this data on our special keys.
//
// All other tree-view entries must have NULL for the lParam.
//
// This extra data on these special tree-view keys supports a number of
// activities. It helps ComputeFullPathOfItem() figure out the diskpath.
// It helps OnSelectionChange() figure out whether to grey buttons (e.g.
// you can't delete "User Supplied Files", etc...)
//
// The on-disk pathname is computed at run-time (init-time) because we
// don't know where the dist folder is until run-time.
//
enum { KEY_OEMROOT, KEY_SYSDRIVE, KEY_SYSDIR, KEY_OTHERDRIVES, KEY_PNPDRIVERS, KEY_TEMPFILES, KEY_LANGFILES, KEY_SYSPREP, KEY_TEXTMODE };
typedef struct { UINT iSpecialKeyId; // which special key?
TCHAR OnDiskPathName[MAX_PATH]; // the disk-path the key maps to
TCHAR *Description; // description to display on the ui
} SPECIAL_KEY_DATA;
SPECIAL_KEY_DATA gOemRootData = { KEY_OEMROOT, _T(""), _T("") };
SPECIAL_KEY_DATA gSysDriveData = { KEY_SYSDRIVE, _T(""), _T("") };
SPECIAL_KEY_DATA gSysDirData = { KEY_SYSDIR, _T(""), _T("") };
SPECIAL_KEY_DATA gOtherDrivesData = { KEY_OTHERDRIVES, _T(""), _T("") };
SPECIAL_KEY_DATA gPnpDriversData = { KEY_PNPDRIVERS, _T(""), _T("") };
SPECIAL_KEY_DATA gTempFilesData = { KEY_TEMPFILES, _T(""), _T("") };
SPECIAL_KEY_DATA gSysprepData = { KEY_SYSPREP, _T(""), _T("") };
SPECIAL_KEY_DATA gTextmodeData = { KEY_TEXTMODE, _T(""), _T("") };
//
// The below variable is used to keep track of some info about the current
// selection on the tree-view.
//
// Each time the user changes the current selection, we update the below
// variable. Later, when the user pushes the ADD or REMOVE buttons, these
// fields are read. This isolates all of the goo about figuring out disk
// paths to the OnSelectionChange() event.
//
// We set a "Current Item" and a "Current Folder" derived from the current
// tree-view selection. User deletes the current item, and copies go into
// the current folder. CurrentItem == CurrentFolder if user selects a
// directory on the tree-view.
//
typedef struct {
TCHAR lpCurItemPath[MAX_PATH]; TCHAR lpCurFolderPath[MAX_PATH]; HTREEITEM hCurItem; HTREEITEM hCurFolderItem;
} ADDDIRS_CURSEL_INF;
ADDDIRS_CURSEL_INF gCurSel;
//
// This type and the vars are used to cache info about the shell icons
// associated with files and dirents.
//
// As we walk directory trees, we query the shell to get the icons
// associated with that file or directory. Since we don't know how many
// icons we need before-hand, we cache unique icons onto the linked list
// below. When we're done walking trees, we make the Image_List and
// repaint the tree-view control.
//
typedef struct icon_info_tag {
HIMAGELIST hSysImageList; int iSysIdx; int iOurIdx; HICON hIcon; struct icon_info_tag *next;
} ICON_INFO;
static ICON_INFO *pHeadOfIconList = NULL; static int gCurIconIdx = 0;
//
// This array is used by CreateSkeletonOemTree() to build an empty
// $oem$ tree.
//
TCHAR *DefaultOemTree[] = { _T("$$"), _T("$$\\system32"), _T("$1"), _T("$1\\drivers"), _T("C"), _T("D"), _T("Textmode") };
//
// Sysprep string constants
//
static TCHAR const SYSPREP_EXE[] = _T("sysprep.exe"); static TCHAR const SETUPCL_EXE[] = _T("setupcl.exe");
static TCHAR SYSPREP_FILE_EXTENSION[] = _T("exe");
static TCHAR* StrExecutableFiles; static TCHAR* StrAllFiles; static TCHAR g_szSysprepFileFilter[MAX_PATH + 1];
static TCHAR* StrSelectFileOrFolderToCopy = NULL;
//
// Variables to pass data between the SetupIterateCabinet function and its callback
//
static TCHAR szFileSearchingFor[MAX_PATH + 1]; static TCHAR szDestinationPath[MAX_PATH + 1]; static BOOL bFileCopiedFromCab = FALSE;
#define SIZE_DEFAULT_OEM_TREE ( sizeof(DefaultOemTree) / sizeof(TCHAR*) )
//
// The below type is needed for WalkTreeAndAddItems() which walks the
// distribution folder and populates the tree-view at init time.
//
// In the case of the TempFiles key, it maps to distfold\$oem$. When
// we look at the disk to populate this tree we must not recurse down
// into $$ $1 C D ... We only want the remainder.
//
// In the case of System Drive, we must not recurse down $oem$\$1\drivers
// because those files should appear under the special key PnPDrivers.
//
// The other special keys are safe and use INIT_NORMAL when calling
// WalkTreeAndAddItems().
//
typedef enum {
INIT_NORMAL, INIT_SYSDRIVE, INIT_TEMPFILES
} INIT_FLAG;
//
// Keeps track of what product they had chosen when they last got to
// this page. It is initialized to NO_PREVIOUS_PRODUCT_CHOSEN because the
// first time they get to this page they were never here before. This is
// used to determine if we should redraw the entire tree or not. The tree
// view is different for NT work/serv than it is for Sysprep.
//
#define NO_PREVIOUS_PRODUCT_CHOSEN -1
static INT g_iLastProductInstall = NO_PREVIOUS_PRODUCT_CHOSEN;
//---------------------------------------------------------------------------
//
// This section of code is the support for queuing icons.
//
// Notes:
// - Currently, there is only support for queueing icons obtained
// from the shell. Some engineering will be required to add
// fixed IDI_* icons onto the list. Please delete this comment
// if you do this work.
//
// - None of the icon routines report errors to the user. The caller
// should do that if they want to report errors.
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// Function: FindCachedIcon
//
// Purpose: This is a support routine for cacheing icons. Don't call it,
// use LoadShellIcon().
//
// This function searches our global list of shell icon info
// and returns a pointer to that node. If we have not yet
// cached info about this icon, this function creates the node.
//
// Arguments:
// HIMAGELIST hSysImageList - the system image list where icon resides
// int SysIdx - index on the give list of icon
//
// Returns:
// Pointer to ICON_INFO node or NULL if out of memory
//
//---------------------------------------------------------------------------
ICON_INFO *FindCachedIcon(HIMAGELIST hSysImageList, int SysIdx) { ICON_INFO *p = pHeadOfIconList;
//
// See if we've ever seen this icon before. We detect uniqueness
// by the imagelist,idx pair.
//
while ( p ) { if ( p->hSysImageList == hSysImageList && p->iSysIdx == SysIdx ) break; p = p->next; }
//
// If we haven't cached any info about this icon yet, do so now
//
if ( ! p ) {
if ( (p = malloc(sizeof(ICON_INFO))) == NULL ) return NULL;
p->hSysImageList = hSysImageList; p->iSysIdx = SysIdx; p->iOurIdx = gCurIconIdx++; p->hIcon = ImageList_GetIcon(hSysImageList, SysIdx, 0); p->next = pHeadOfIconList; pHeadOfIconList = p; }
return p; }
//---------------------------------------------------------------------------
//
// Function: LoadShellIcon
//
// Purpose: Given the full pathname of a file or directory, this function
// will query the shell and find out the icon associatted with
// that file or directory.
//
// Arguments:
// LPTSTR lpPath - full path of item
// UINT iWhichIcon - pass either SHGFI_SMALLICON or SHGFI_OPENICON
//
// Notes:
// - Since we only make 1 image list, this routine will only work
// to query small icons (either the normal or the open). It won't
// work for icons that are not 16X16.
//
//---------------------------------------------------------------------------
int LoadShellIcon(LPTSTR lpPath, UINT iWhichIcon) { SHFILEINFO FileInfo; ICON_INFO *pIconInfo; HIMAGELIST hSysImageList;
hSysImageList = (HIMAGELIST) SHGetFileInfo(lpPath, 0, &FileInfo, sizeof(FileInfo), SHGFI_SYSICONINDEX | iWhichIcon);
if ( hSysImageList == NULL ) return -1;
pIconInfo = FindCachedIcon(hSysImageList, FileInfo.iIcon);
if ( pIconInfo == NULL ) return -1;
return pIconInfo->iOurIdx; }
//---------------------------------------------------------------------------
//
// Function: SetOurImageList
//
// Purpose: Whenever more items have been added to the tree, this function
// is called to update the icon list.
//
// Arguments:
// HWND hTv - Handle to the tree-view control
//
// Returns:
// void
//
//---------------------------------------------------------------------------
void SetOurImageList(HWND hTv) { HIMAGELIST hNewImageList, hCurImageList; ICON_INFO *p = pHeadOfIconList; int i;
//
// Make the image list now that we know how big it needs to be.
//
hNewImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK, gCurIconIdx, 0);
if ( hNewImageList == NULL ) return;
//
// Add a dummy icon in each spot. This is necessary becase
// ImageList_ReplaceIcon() will only work if an icon has already been
// added to the offset in question.
//
if ( p == NULL ) return;
for ( i=0; i<gCurIconIdx; i++ ) ImageList_AddIcon(hNewImageList, p->hIcon);
//
// Now walk our list of unique icons and put them at the correct
// offset in the image_list.
//
// Note that when we walked the tree, LoadShellIcon() returned the
// index that each tree-view entry should use for it's icons. Thus,
// we must ensure that the correct icon is at the correct offset
// in the tree-view's image_list.
//
for ( p=pHeadOfIconList; p; p=p->next ) ImageList_ReplaceIcon(hNewImageList, p->iOurIdx, p->hIcon);
//
// If there is an old image_list on the tree-view, free it first
//
if ( (hCurImageList = TreeView_GetImageList(hTv, TVSIL_NORMAL)) != NULL ) ImageList_Destroy(hCurImageList);
TreeView_SetImageList(hTv, hNewImageList, TVSIL_NORMAL); }
//---------------------------------------------------------------------------
//
// This section of code is some miscellaneous low-level support.
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// Function: InsertSingleItem
//
// Purpose: Adds a single item to the tree view. It will be a child
// of the given hParentItem.
//
// This function lives only to support UpdateTreeViewDisplay()
// and should not be called otherwise.
//
// Arguments:
// HWND hwnd - current window
// LPTSTR lpItemName - name to display
// int SmallIconIdx - idx into the image_list
// int OpenIconIdx - idx into the image_list
// SPECIAL_KEY_DATA *lpExtraData - data to keep on the tree-view item
// HTREEITEM hParentItem - parent on the display
//
// Returns:
// HTREEITEM, NULL if it fails
//
// Notes:
// - pass NULL for lpExtraData unless it is one of our pre-defined
// special keys.
//
//---------------------------------------------------------------------------
HTREEITEM InsertSingleItem(HWND hwnd, LPTSTR lpItemName, int SmallIconIdx, int OpenIconIdx, SPECIAL_KEY_DATA *lpExtraData, HTREEITEM hParentItem) { HTREEITEM hItem; TVINSERTSTRUCT TvInsert; UINT ItemMask = TVIF_TEXT | TVIF_PARAM;
if ( SmallIconIdx >= 0 ) { ItemMask |= TVIF_IMAGE; }
if ( OpenIconIdx >= 0 ) { ItemMask |= TVIF_SELECTEDIMAGE; }
TvInsert.hParent = hParentItem; TvInsert.hInsertAfter = TVI_LAST; TvInsert.item.mask = ItemMask; TvInsert.item.pszText = lpItemName; TvInsert.item.iImage = SmallIconIdx; TvInsert.item.iSelectedImage = OpenIconIdx; TvInsert.item.lParam = (LPARAM) lpExtraData;
hItem = TreeView_InsertItem(GetDlgItem(hwnd, IDC_FILETREE), &TvInsert);
if ( hItem == NULL ) { ReportErrorId(hwnd, MSGTYPE_ERR, IDS_ERR_ADDING_TVITEM); }
return hItem; }
//---------------------------------------------------------------------------
//
// Function: GetItemlParam
//
// Purpose: Gets the lParam off a tree-view item. In this app, it is
// null unless it's one of our special keys.
//
// Arguments:
// HWND hTv
// HTREEITEM hItem
//
// Returns:
// Value of the lParam. In this app, it is SPECIAL_KEY_DATA*. It
// is generally null except for our few special keys.
//
//---------------------------------------------------------------------------
SPECIAL_KEY_DATA *GetItemlParam(HWND hTv, HTREEITEM hItem) { TVITEM TvItem;
TvItem.hItem = hItem; TvItem.mask = TVIF_PARAM;
if ( ! TreeView_GetItem(hTv, &TvItem) ) return NULL;
return (SPECIAL_KEY_DATA*) TvItem.lParam; }
//---------------------------------------------------------------------------
//
// Function: GetItemName
//
// Purpose: Retrieves the display name of a tree-view item given its handle.
//
// Arguments:
// HWND hTv
// HTREEITEM hItem
// LPTSTR NameBuffer - output
//
// Returns: BOOL - success
//
//---------------------------------------------------------------------------
BOOL GetItemName(HWND hTv, HTREEITEM hItem, LPTSTR NameBuffer) { TVITEM TvItem;
TvItem.hItem = hItem; TvItem.mask = TVIF_TEXT; TvItem.pszText = NameBuffer; TvItem.cchTextMax = MAX_PATH;
return TreeView_GetItem(hTv, &TvItem); }
//---------------------------------------------------------------------------
//
// Function: FindItemByName
//
// Purpose: Searches the children of a given tree-view item and returns
// a handle to the one with the given name.
//
// Arguments:
// HWND hTv
// HTREEITEM hItem
// LPTSTR lpName
//
// Returns:
// HTREEITEM, null if not found
//
//---------------------------------------------------------------------------
HTREEITEM FindItemByName(HWND hTv, HTREEITEM hItem, LPTSTR lpName) { HTREEITEM hChildItem; TCHAR NameBuffer[MAX_PATH];
hChildItem = TreeView_GetChild(hTv, hItem);
while ( hChildItem != NULL ) {
if ( ! GetItemName(hTv, hChildItem, NameBuffer) ) return NULL;
if ( lstrcmpi(NameBuffer, lpName) == 0 ) break;
hChildItem = TreeView_GetNextSibling(hTv, hChildItem); }
return hChildItem; }
//
// The below functions build the on-disk pathname for each of our special
// root names.
//
// SysDrive maps to $oem$\$1
// SysDir maps to $oem$\$$
// OtherDrives maps to $oem$\%c (where %c is a fixed drive letter)
// PnpDrivers maps to $oem$\$1\drivers
// TempFiles maps to $oem$ (and must skip $$, $1, etc)
//
//----------------------------------------------------------------------------
//
// Function: MakeSysprepSetupFilesPath
//
// Purpose: Computes the path to where sysprep.exe and setupcl.exe are to be
// copied.
//
// Arguments: TCHAR* szSysprepPath - returns the sysprep path, assumed to be
// able to hold MAX_PATH chars
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID MakeSysprepSetupFilesPath( TCHAR* szSysprepPath ) {
if (0 == ExpandEnvironmentStrings( _T("%SystemDrive%"), szSysprepPath, MAX_PATH )) { TerminateTheWizard(IDS_ERROR_OUTOFMEMORY); }
lstrcatn( szSysprepPath, _T("\\sysprep"), MAX_PATH );
}
//----------------------------------------------------------------------------
//
// Function: MakeSysprepPath
//
// Purpose: Computes the path to where the language files for sysprep are to
// be copied.
//
// Arguments: TCHAR* szSysprepPath - returns the sysprep path
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeSysprepPath( TCHAR* szSysprepPath ) {
MakeSysprepSetupFilesPath( szSysprepPath );
lstrcatn( szSysprepPath, _T("\\i386"), MAX_PATH );
}
//----------------------------------------------------------------------------
//
// Function: MakeTempFilesName
//
// Purpose: Computes the path to where the temp files are to be copied.
//
// Arguments: TCHAR* Buffer - returns the temp files path
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeTempFilesName( TCHAR* Buffer ) {
lstrcpyn( Buffer, WizGlobals.OemFilesPath, AS(Buffer) );
}
//----------------------------------------------------------------------------
//
// Function: MakePnpDriversName
//
// Purpose: Computes the path to where the Plug and Play drivers are to be
// copied.
//
// Arguments: TCHAR* Buffer - returns the path to where the PnP files go
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakePnpDriversName( TCHAR* Buffer ) { HRESULT hrPrintf;
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) {
ExpandEnvironmentStrings( _T("%SystemDrive%"), Buffer, MAX_PATH );
lstrcatn( Buffer, _T("\\drivers"), MAX_PATH );
} else { hrPrintf=StringCchPrintf( Buffer, AS(Buffer), _T("%s\\$1\\drivers"), WizGlobals.OemFilesPath ); }
}
//----------------------------------------------------------------------------
//
// Function: MakeOemRootName
//
// Purpose: Computes the path to where the OEM files are to be copied.
//
// Arguments: TCHAR* Buffer - returns the path to where the OEM files go
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeOemRootName( TCHAR* Buffer ) { lstrcpyn( Buffer, WizGlobals.OemFilesPath, AS(Buffer) ); }
//----------------------------------------------------------------------------
//
// Function: MakeSysDriveName
//
// Purpose: Computes the path to the System drive files are to be copied
//
// Arguments: TCHAR* Buffer - returns the path to the where the System drive
// files are to be copied.
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeSysDriveName( TCHAR* Buffer ) { HRESULT hrPrintf;
hrPrintf=StringCchPrintf( Buffer, AS(Buffer), _T("%s\\$1"), WizGlobals.OemFilesPath );
}
//----------------------------------------------------------------------------
//
// Function: MakeSysDirName
//
// Purpose: Computes the path to the System Directory files are to be copied
//
// Arguments: TCHAR* Buffer - returns the path to the where the System
// Directory files are to be copied.
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeSysDirName( TCHAR* Buffer ) { HRESULT hrPrintf;
hrPrintf=StringCchPrintf( Buffer, AS(Buffer), _T("%s\\$$"), WizGlobals.OemFilesPath );
}
//----------------------------------------------------------------------------
//
// Function: MakeOtherDriveName
//
// Purpose: Computes the path to the Other Drive files are to be copied
//
// Arguments: TCHAR* Buffer - returns the path to the where the Other
// Drive files are to be copied.
// TCHAR c - the drive we are making the path for
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeOtherDriveName( TCHAR* Buffer, TCHAR c ) { HRESULT hrPrintf;
hrPrintf=StringCchPrintf( Buffer, AS(Buffer), c ? _T("%s\\%c") : _T("%s"), WizGlobals.OemFilesPath, c );
}
//----------------------------------------------------------------------------
//
// Function: MakeLangFilesName
//
// Purpose: Computes the path to where the language files are to be copied.
//
// Arguments: TCHAR* Buffer - returns the path to where the language files go
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeLangFilesName( TCHAR* Buffer ) {
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) {
MakeSysprepPath( Buffer );
} else { lstrcpyn( Buffer, WizGlobals.OemFilesPath, AS(Buffer) ); }
}
//----------------------------------------------------------------------------
//
// Function: MakeSysprepLangFilesGroupName
//
// Purpose: Computes the path to where the language dirs are to be copied for
// the language groups.
//
// Arguments: TCHAR* Buffer - returns the path to where the language files go
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeSysprepLangFilesGroupName( TCHAR* Buffer ) {
MakeSysprepPath( Buffer );
lstrcatn( Buffer, _T("\\lang"), MAX_PATH );
}
//----------------------------------------------------------------------------
//
// Function: MakeTextmodeFilesName
//
// Purpose: Computes the path to where the OEM boot files are to be copied
//
// Arguments: TCHAR* Buffer - returns the path to the where the textmode
// (HAL and SCSI) files are to be copied.
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID MakeTextmodeFilesName( TCHAR* Buffer ) { HRESULT hrPrintf;
hrPrintf=StringCchPrintf( Buffer, AS(Buffer), _T("%s\\Textmode"), WizGlobals.OemFilesPath );
}
//----------------------------------------------------------------------------
//
// This section of code is for WM_INIT
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: CreateSkeletonOemTree
//
// Purpose: This function creates a skeleton OEM tree. The directories
// created are based on the global array DefaultOemTree[].
//
// If the tree already exists, this function becomes a no-op.
//
// This is called at init-time and is a support routine for
// the OnInit() routine. Don't call it otherwise.
//
// Returns:
// TRUE - no errors, proceed
// FALSE - errors making tree
//
// Notes:
// - Errors are reported to the user.
//
//----------------------------------------------------------------------------
BOOL CreateSkeletonOemTree(HWND hwnd) { int i; TCHAR PathBuffer[MAX_PATH];
//
// Ensure the $oem$ dir exists
//
if ( ! EnsureDirExists(WizGlobals.OemFilesPath) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_CREATE_FOLDER, WizGlobals.OemFilesPath);
return FALSE; }
//
// Now make all of the default sub-dirs in the $oem$ tree if it is not
// a sysprep
//
if( WizGlobals.iProductInstall != PRODUCT_SYSPREP ) {
for ( i=0; i<SIZE_DEFAULT_OEM_TREE; i++ ) {
lstrcpyn(PathBuffer, WizGlobals.OemFilesPath, AS(PathBuffer));
ConcatenatePaths(PathBuffer, DefaultOemTree[i], NULL);
if ( ! EnsureDirExists(PathBuffer) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_CREATE_FOLDER, PathBuffer); return FALSE; } }
}
return( TRUE ); }
//---------------------------------------------------------------------------
//
// Function: WalkTreeAndAddItems
//
// Purpose: This function walks a tree on the disk and inserts each
// dirent and file found into the tree-view display.
//
// The directory tree will become a child of the given tree-view
// item as hParent.
//
// This function supports OnInitAddDirs() and should not be
// called otherwise.
//
// Arguments:
// HWND hwnd - parent window
// LPTSTR RootBuffer - tree to recurse down
// HTREEITEM hParent - the parent tree view item
// BOOL bTempFiles - special case for "Temp Files"
//
// Returns: VOID
//
// Notes:
//
// - RootBuffer must be MAX_PATH wide.
//
// - Any paths that this routine encounters that are >= MAX_PATH in
// length are silently skipped.
//
// - Always pass bTempFiles=FALSE except when filling in the TempFiles
// root in the tree-view. TempFiles maps to $oem$ on disk, but the
// other special locations are sub-dirs of this. Thus, this findfirst/
// findnext loop must skip those special cases ($1, $$, etc...)
//
//---------------------------------------------------------------------------
VOID WalkTreeAndAddItems(HWND hwnd, LPTSTR RootBuffer, HTREEITEM hParent, INIT_FLAG iInitFlag) { LPTSTR RootPathEnd = RootBuffer + lstrlen(RootBuffer); HANDLE FindHandle; WIN32_FIND_DATA FindData; HTREEITEM hItem; int iSmallIcon; int iOpenIcon; TCHAR szOriginalPath[MAX_PATH] = _T("");
//
// Backup the original path so it can be restored later
//
lstrcpyn( szOriginalPath, RootBuffer, AS(szOriginalPath) );
//
// Look for * in this dir
//
if ( ! ConcatenatePaths(RootBuffer, _T("*"), NULL) ) {
//
// Restore the original path before returning
//
lstrcpyn( RootBuffer, szOriginalPath, AS(RootBuffer) );
return; }
FindHandle = FindFirstFile(RootBuffer, &FindData); if ( FindHandle == INVALID_HANDLE_VALUE ) {
//
// Restore the original path before returning
//
lstrcpyn( RootBuffer, szOriginalPath, AS(RootBuffer) );
return; }
do {
*RootPathEnd = _T('\0');
//
// skip over the . and .. entries
//
if (0 == lstrcmp(FindData.cFileName, _T(".")) || 0 == lstrcmp(FindData.cFileName, _T(".."))) continue;
//
// TempFiles maps to %distfold%\$oem$, but the others map to a
// sub-directory of $oem$, (e.g. SysDrive maps to $oem$\$1).
//
// By definition, TempFiles is anything under $oem$ that is not
// a special name. So, in the case that we are building the
// Temporary Files tree, be sure we don't recurse down into a
// special $oem$ sub-dir.
//
// Note that we do this check based on fully qualified pathnames
// else comparisons would be ambiguous.
//
if ( iInitFlag == INIT_TEMPFILES ) {
TCHAR Buffer1[MAX_PATH], Buffer2[MAX_PATH], c; BOOL bContinue;
lstrcpyn(Buffer1, RootBuffer, AS(RootBuffer)); if ( ! ConcatenatePaths(Buffer1, FindData.cFileName, NULL) ) continue;
//
// skip %distfold%\$oem$\$1
//
MakeSysDriveName(Buffer2); if ( _wcsicmp(Buffer1, Buffer2) == 0 ) continue;
//
// skip %distfold%\$oem$\$$
//
MakeSysDirName(Buffer2); if ( _wcsicmp(Buffer1, Buffer2) == 0 ) continue;
//
// skip %distfold%\$oem$\textmode
//
MakeTextmodeFilesName(Buffer2); if ( _wcsicmp(Buffer1, Buffer2) == 0 ) continue;
//
// skip %distfold%\$oem$\%c where %c is any drive letter
//
for ( bContinue=FALSE, c=_T('A'); c<=_T('Z'); c++ ) { MakeOtherDriveName(Buffer2, c); if ( _wcsicmp(Buffer1, Buffer2) == 0 ) { bContinue = TRUE; break; } } if ( bContinue ) continue; }
//
// The other special case is SYSDRIVE which maps to $oem$\$1.
//
// Whe must skip $oem$\$1\drivers because that is the root for the
// special key PnPDrivers.
//
else if ( iInitFlag == INIT_SYSDRIVE ) {
TCHAR Buffer1[MAX_PATH], Buffer2[MAX_PATH];
lstrcpyn(Buffer1, RootBuffer, AS(RootBuffer)); if ( ! ConcatenatePaths(Buffer1, FindData.cFileName, NULL) ) continue;
//
// Skip %distfold%\$oem$\$1\drivers
//
MakePnpDriversName(Buffer2); if ( _wcsicmp(Buffer1, Buffer2) == 0 ) continue; }
//
// Build the full pathname, if >= MAX_PATH, skip it
//
if ( ! ConcatenatePaths(RootBuffer, FindData.cFileName, NULL) ) continue;
//
// Get the shell icons associated with this file/dir
//
iSmallIcon = LoadShellIcon(RootBuffer, SHGFI_SMALLICON); iOpenIcon = LoadShellIcon(RootBuffer, SHGFI_OPENICON);
//
// Add this item as a child of the given parent.
//
if ( (hItem = InsertSingleItem(hwnd, FindData.cFileName, iSmallIcon, iOpenIcon, NULL, hParent)) == NULL ) { continue; }
//
// If this is a dirent, recurse.
//
if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) WalkTreeAndAddItems(hwnd, RootBuffer, hItem, iInitFlag);
} while ( FindNextFile(FindHandle, &FindData) );
*RootPathEnd = _T('\0'); FindClose(FindHandle);
//
// Restore the original path
//
lstrcpyn( RootBuffer, szOriginalPath, AS(RootBuffer) );
}
//---------------------------------------------------------------------------
//
// Function: OnInitAddDirs
//
// Purpose: Called before the dialog first displays. We ensure that
// OemFilesPath and OemPnpDriversPath have good defaults and
// that the skeleton OEM tree exists.
//
//---------------------------------------------------------------------------
VOID OnInitAddDirs(HWND hwnd) { HRESULT hrPrintf;
//
// Create the $oem$, $oem$\$1, etc in %distfold%
//
// If there's any errors creating this skeleton distfolder tree, it's
// hopeless. CreateSkeletonOemTree() already reported an error, skip
// this page.
//
//
// ISSUE-2002/02/28-stelo- The fact that the user gets this error before we even
// initialize means there is no good context. Currently,
// the error message is generic.
//
// Go down this path by connecting to a share that you
// only have read access to. This is a good edit scenario.
// OemFilesPath should get computed. User could select
// Oem Branding files directly from a read-only dist folder.
// In that case, I think we no-op the copy.
//
// It must be tested what EnsureDirExists() does in this
// context.
//
if ( ! CreateSkeletonOemTree(hwnd) ) { return; }
//
// Load the hard-coded special root names that you see initially
// on the tree-view and their descriptions
//
StrOemRootName = MyLoadString( IDS_OEMROOT_NAME ); StrSysDriveName = MyLoadString( IDS_SYSDRIVE_NAME ); StrSysDirName = MyLoadString( IDS_SYSDIR_NAME ); StrOtherDrivesName = MyLoadString( IDS_OTHERDRIVES_NAME ); StrPnpDriversName = MyLoadString( IDS_PNPDRIVERS_NAME ); StrTempFilesName = MyLoadString( IDS_TEMPFILES_NAME ); StrSysprepFilesName = MyLoadString( IDS_SYSPREPFILES_NAME ); StrTextmodeFilesName = MyLoadString( IDS_TEXTMODE_NAME );
gOemRootData.Description = MyLoadString( IDS_ADD_DESCR_ROOT ); gSysDriveData.Description = MyLoadString( IDS_ADD_DESCR_SYSDRIVE ); gSysDirData.Description = MyLoadString( IDS_ADD_DESCR_WINNT ); gOtherDrivesData.Description = MyLoadString( IDS_ADD_DESCR_OTHER ); gPnpDriversData.Description = MyLoadString( IDS_ADD_DESCR_PNP ); gTempFilesData.Description = MyLoadString( IDS_ADD_DESCR_TEMP ); gSysprepData.Description = MyLoadString( IDS_ADD_DESCR_SYSPREP ); gTextmodeData.Description = MyLoadString( IDS_ADD_DESCR_TEXTMODE );
//
// Compute the on-disk path names for each of our special keys.
//
MakeOemRootName( gOemRootData.OnDiskPathName ); MakeSysDriveName( gSysDriveData.OnDiskPathName ); MakeSysDirName( gSysDirData.OnDiskPathName ); MakeOtherDriveName( gOtherDrivesData.OnDiskPathName, _T('\0') );
//
// Load and tweak the browse strings
//
StrExecutableFiles = MyLoadString( IDS_EXECUTABLE_FILES ); StrAllFiles = MyLoadString( IDS_ALL_FILES );
//
// The question marks (?) are just placehoders for where the NULL char
// will be inserted.
//
hrPrintf=StringCchPrintf( g_szSysprepFileFilter, AS(g_szSysprepFileFilter), _T("%s (*.exe)?*.exe?%s (*.*)?*.*?"), StrExecutableFiles, StrAllFiles );
ConvertQuestionsToNull( g_szSysprepFileFilter );
//
// ISSUE-2002/02/28-stelo- leave this comment in, but move it to a more appropriate place
//
// Currently, all of our special keys use the shell folder icon
// and the shell open_folder icon. So load these icons now and
// use the same idx for all of the special keys.
//
// Note that if we make our own IDI_* for these special keys,
// you'll have to write a new routine in the icon_queing support
// to load an IDI_ and you'll need to fiddle with the icon_info
// type and call the new routine from here. You'll need to fix
// these comments too, (unless you're too much of a wimp to
// delete things that should be deleted).
//
}
//---------------------------------------------------------------------------
//
// Function: DrawSysprepTreeView
//
// Purpose:
//
// Arguments: HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//
//---------------------------------------------------------------------------
VOID DrawSysprepTreeView( IN HWND hwnd ) {
HWND hTv = GetDlgItem(hwnd, IDC_FILETREE); TCHAR c; INT iSmallIcon; INT iOpenIcon; TCHAR szLangFilesPath[MAX_PATH + 1];
HTREEITEM hRoot, hPnpDrivers, hSysprepFiles, hLangFiles;
//
// Delete the old tree so we can build it up fresh
//
TreeView_DeleteAllItems( hTv );
//
// Compute the on-disk path names for the special keys that change on
// a sysprep tree view.
//
MakePnpDriversName(gPnpDriversData.OnDiskPathName); MakeSysprepSetupFilesPath(gSysprepData.OnDiskPathName); MakeSysprepLangFilesGroupName(szLangFilesPath);
//
// Make sure the language files dir gets created
//
EnsureDirExists( szLangFilesPath );
iSmallIcon = LoadShellIcon(gOemRootData.OnDiskPathName, SHGFI_SMALLICON); iOpenIcon = LoadShellIcon(gOemRootData.OnDiskPathName, SHGFI_OPENICON);
//
// The drivers dir is outside the rest of the tree so ensure it gets
// created here.
//
EnsureDirExists( gPnpDriversData.OnDiskPathName );
//
// Insert each of our special locations into the tree-view.
//
hRoot = InsertSingleItem(hwnd, StrOemRootName, iSmallIcon, iOpenIcon, &gOemRootData, TVI_ROOT);
hPnpDrivers = InsertSingleItem(hwnd, StrPnpDriversName, iSmallIcon, iOpenIcon, &gPnpDriversData, hRoot);
hSysprepFiles = InsertSingleItem(hwnd, StrSysprepFilesName, iSmallIcon, iOpenIcon, &gSysprepData, hRoot);
//
// Now go out and read from the disk and populate each of these
// special trees.
//
// Note that there is nothing but special keys under OEM_ROOT,
// so there is no tree walking to do for OEM_ROOT, we've already
// added all of it's children above.
//
WalkTreeAndAddItems(hwnd, gPnpDriversData.OnDiskPathName, hPnpDrivers, INIT_NORMAL);
WalkTreeAndAddItems(hwnd, gSysprepData.OnDiskPathName, hSysprepFiles, INIT_TEMPFILES);
//
// Set the imagelist (the icons on the tree-view)
//
SetOurImageList(GetDlgItem(hwnd, IDC_FILETREE));
//
// All buttons are grey to start with
//
EnableWindow(GetDlgItem(hwnd, IDC_REMOVEFILE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_ADDFILE), FALSE);
//
// Expand our special keys
//
TreeView_Expand(hTv, hRoot, TVE_EXPAND);
}
//---------------------------------------------------------------------------
//
// Function: DrawStandardTreeView
//
// Purpose:
//
// Arguments: HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//
//---------------------------------------------------------------------------
VOID DrawStandardTreeView( IN HWND hwnd ) {
HWND hTv = GetDlgItem(hwnd, IDC_FILETREE); TCHAR c; INT iSmallIcon; INT iOpenIcon;
HTREEITEM hRoot, hSysDrive, hSysDir, hOtherDrives, hPnpDrivers, hTempFiles, hTextmodeFiles;
//
// Delete the old tree so we can build it up fresh
//
TreeView_DeleteAllItems( hTv );
//
// Compute the on-disk path names for the special keys that change on
// a standard tree view.
//
MakePnpDriversName(gPnpDriversData.OnDiskPathName); MakeTempFilesName(gTempFilesData.OnDiskPathName); MakeTextmodeFilesName(gTextmodeData.OnDiskPathName);
iSmallIcon = LoadShellIcon(gOemRootData.OnDiskPathName, SHGFI_SMALLICON); iOpenIcon = LoadShellIcon(gOemRootData.OnDiskPathName, SHGFI_OPENICON);
//
// Insert each of our special locations into the tree-view.
//
hRoot = InsertSingleItem(hwnd, StrOemRootName, iSmallIcon, iOpenIcon, &gOemRootData, TVI_ROOT);
hSysDrive = InsertSingleItem(hwnd, StrSysDriveName, iSmallIcon, iOpenIcon, &gSysDriveData, hRoot);
hSysDir = InsertSingleItem(hwnd, StrSysDirName, iSmallIcon, iOpenIcon, &gSysDirData, hSysDrive);
hOtherDrives = InsertSingleItem(hwnd, StrOtherDrivesName, iSmallIcon, iOpenIcon, &gOtherDrivesData, hRoot);
hPnpDrivers = InsertSingleItem(hwnd, StrPnpDriversName, iSmallIcon, iOpenIcon, &gPnpDriversData, hSysDrive);
hTempFiles = InsertSingleItem(hwnd, StrTempFilesName, iSmallIcon, iOpenIcon, &gTempFilesData, hRoot);
hTextmodeFiles = InsertSingleItem(hwnd, StrTextmodeFilesName, iSmallIcon, iOpenIcon, &gTextmodeData, hTempFiles);
//
// Now go out and read from the disk and populate each of these
// special trees.
//
// Note that there is nothing but special keys under OEM_ROOT,
// so there is no tree walking to do for OEM_ROOT, we've already
// added all of it's children above.
//
WalkTreeAndAddItems(hwnd, gSysDriveData.OnDiskPathName, hSysDrive, INIT_SYSDRIVE);
WalkTreeAndAddItems(hwnd, gSysDirData.OnDiskPathName, hSysDir, INIT_NORMAL);
for ( c=_T('A'); c<=_T('Z'); c++ ) {
HTREEITEM hDrive; TCHAR DriveLetterBuff[2]; TCHAR PathBuffer[MAX_PATH]; HRESULT hrPrintf;
MakeOtherDriveName(PathBuffer, c);
if ( DoesFolderExist(PathBuffer) ) {
hrPrintf=StringCchPrintf(DriveLetterBuff,AS(DriveLetterBuff), _T("%c"), c);
hDrive = InsertSingleItem(hwnd, DriveLetterBuff, iSmallIcon, iOpenIcon, NULL, hOtherDrives); WalkTreeAndAddItems(hwnd, PathBuffer, hDrive, INIT_NORMAL); } }
WalkTreeAndAddItems(hwnd, gPnpDriversData.OnDiskPathName, hPnpDrivers, INIT_NORMAL);
WalkTreeAndAddItems(hwnd, gTempFilesData.OnDiskPathName, hTempFiles, INIT_TEMPFILES);
WalkTreeAndAddItems(hwnd, gTextmodeData.OnDiskPathName, hTextmodeFiles, INIT_TEMPFILES);
//
// Set the imagelist (the icons on the tree-view)
//
SetOurImageList(GetDlgItem(hwnd, IDC_FILETREE));
//
// All buttons are grey to start with
//
EnableWindow(GetDlgItem(hwnd, IDC_REMOVEFILE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_ADDFILE), FALSE);
//
// Expand our special keys
//
TreeView_Expand(hTv, hRoot, TVE_EXPAND);
}
//---------------------------------------------------------------------------
//
// Function: OnSetActiveAddDirs
//
// Purpose: Determines if the tree view needs to be redrawn and if it does,
// redraws it.
//
// Arguments: HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//---------------------------------------------------------------------------
VOID OnSetActiveAddDirs( IN HWND hwnd ) {
if( g_iLastProductInstall == NO_PREVIOUS_PRODUCT_CHOSEN ) { //
// This is their first time seeing this page, so draw the approprate
// tree view.
//
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) { DrawSysprepTreeView( hwnd ); } else { DrawStandardTreeView( hwnd ); }
} else if( g_iLastProductInstall == PRODUCT_SYSPREP && WizGlobals.iProductInstall != PRODUCT_SYSPREP ) {
DrawStandardTreeView( hwnd );
} else if( g_iLastProductInstall != PRODUCT_SYSPREP && WizGlobals.iProductInstall == PRODUCT_SYSPREP ) {
DrawSysprepTreeView( hwnd );
}
g_iLastProductInstall = WizGlobals.iProductInstall;
}
//----------------------------------------------------------------------------
//
// This section of code implements OnTreeViewSelectionChange() which
// is called whenever the user selects a different tree-view item.
//
// On this event, we query the currently selected tree-view item and
// do some processing to figure out where this tree-view item maps to
// on disk storage. Once we figure out all we want to know about the
// current selection, we update all of the fields of gCurSel.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: ComputeFullPathOfItem
//
// Purpose: We continually query the parent of the given tree view item
// until we get to one of our specially defined roots. Then
// we fill in the buffer with the full path name of where
// to copy files to.
//
// This function supports OnTreeViewSelectionChange() and should
// not be called otherwise. That is, we only did this processing
// when the user picks a new destination. We scribble the info
// we might need later into globals.
//
// Arguments:
// HTREEITEM hItem - handle to tree item
// LPTSTR PathBuffer - output, caller must pass a MAX_PATH buffer
// SPECIAL_KEY_DATA **SpecialRoot - output
//
// Returns: VOID
//
// Notes:
// - check PathBuffer[0] == _T('\0') for success
//
//----------------------------------------------------------------------------
VOID ComputeFullPathOfItem(IN HWND hwnd, IN HTREEITEM hItem, OUT LPTSTR PathBuffer, OUT SPECIAL_KEY_DATA **pSpecialRoot) { TVITEM TvItemData; HTREEITEM hParent; TCHAR ItemName[MAX_PATH], TempBuffer[MAX_PATH]; int NumCharsReplace; SPECIAL_KEY_DATA *pSpecialKeyData;
PathBuffer[0] = _T('\0');
//
// The TvItemData is used to query the name of the hItem. We
// receive the name in ItemName[]. Set the fields that won't
// change in the loop.
//
TvItemData.mask = TVIF_TEXT | TVIF_PARAM; TvItemData.pszText = ItemName; TvItemData.cchTextMax = MAX_PATH;
//
// Now continually query the name of the parent and keep prefixing
// the parent's name to build the on-disk pathname. Stop when we
// get to one of our special root keys.
//
// We detect hitting a special key because the lParam will be
// non-null. Once we get there, we know the on-disk prefix.
//
do {
TvItemData.hItem = hItem; TreeView_GetItem(GetDlgItem(hwnd, IDC_FILETREE), &TvItemData);
if ( TvItemData.lParam != (LPARAM) NULL ) break;
TempBuffer[0] = _T('\0'); ConcatenatePaths(TempBuffer, ItemName, PathBuffer, NULL); lstrcpyn(PathBuffer, TempBuffer, AS(PathBuffer));
hParent = TreeView_GetParent(GetDlgItem(hwnd, IDC_FILETREE), hItem);
if ( hParent == NULL ) break;
hItem = hParent;
} while ( TRUE );
//
// The final item queried in the above loop should have a non-null
// lParam i.e. the loop should only terminate when it encounters
// a special key.
//
pSpecialKeyData = (SPECIAL_KEY_DATA*) TvItemData.lParam;
Assert(pSpecialKeyData != NULL);
//
// Prefix the disk path of our special root key onto the PathBuffer
// we computed in the loop above.
//
TempBuffer[0] = _T('\0'); ConcatenatePaths(TempBuffer, pSpecialKeyData->OnDiskPathName, PathBuffer, NULL); lstrcpyn(PathBuffer, TempBuffer, AS(PathBuffer));
//
// Give the caller the address of the special key data. This is how
// caller knows what description to display on the ui
//
(*pSpecialRoot) = pSpecialKeyData; }
//----------------------------------------------------------------------------
//
// Function: OnTreeViewSelectionChange
//
// Purpose: This function is called when the user changes the file/dir
// selected on the tree-view.
//
// We compute the full path of the tree-view item now selected
// and update the global gCurSel.
//
//----------------------------------------------------------------------------
VOID OnTreeViewSelectionChange(HWND hwnd) { HWND hTv = GetDlgItem(hwnd, IDC_FILETREE);
TCHAR PathBuffer[MAX_PATH], *pEnd; HTREEITEM hItem; DWORD dwAttribs; LPTSTR lpFileNamePart; BOOL bEnableCopy;
SPECIAL_KEY_DATA *pCurItemlParam, *pCurFolderlParam;
SPECIAL_KEY_DATA *RootSpecialData = NULL;
//
// Get the currently selected item and figure out the on-disk pathname
// for it and figure out which of the 6 special roots this item is under
// (RootSpecialData, that is).
//
hItem = TreeView_GetSelection(hTv);
ComputeFullPathOfItem(hwnd, hItem, PathBuffer, &RootSpecialData);
//
// Save this info in the global gCurSel
//
gCurSel.hCurItem = hItem; lstrcpyn(gCurSel.lpCurItemPath, PathBuffer, AS(gCurSel.lpCurItemPath));
//
// If the CurItem is a directory, the CurFolder should be the same.
// If the CurItem is a file, the CurFolder should be the parent.
//
// Copy & NewFolder goes into the CurFolder, deletes use the CurItem.
//
lstrcpyn(gCurSel.lpCurFolderPath, gCurSel.lpCurItemPath,AS(gCurSel.lpCurFolderPath)); gCurSel.hCurFolderItem = gCurSel.hCurItem;
if ( DoesFileExist(gCurSel.lpCurItemPath) ) {
lpFileNamePart = MyGetFullPath(gCurSel.lpCurFolderPath);
if ( lpFileNamePart == NULL || *(lpFileNamePart-1) != _T('\\') ) { AssertMsg(FALSE, "Could not parse filename. This should not happen."); TerminateTheWizard(IDS_ERROR_OUTOFMEMORY); }
*(lpFileNamePart-1) = _T('\0');
gCurSel.hCurFolderItem = TreeView_GetParent(hTv, gCurSel.hCurFolderItem); }
//
// Grey/ungrey the buttons.
//
// If an lParam is non-null, then it's one of our special keys.
//
// User cannot delete any special keys.
//
// User can copy, unless the current dest folder is KEY_OEMROOT or
// KEY_OTHERDRIVES.
//
pCurItemlParam = GetItemlParam(hTv, gCurSel.hCurItem); pCurFolderlParam = GetItemlParam(hTv, gCurSel.hCurFolderItem);
EnableWindow(GetDlgItem(hwnd, IDC_REMOVEFILE), pCurItemlParam == NULL);
bEnableCopy = ( pCurFolderlParam == NULL || ( pCurFolderlParam->iSpecialKeyId != KEY_OEMROOT && pCurFolderlParam->iSpecialKeyId != KEY_OTHERDRIVES) );
EnableWindow(GetDlgItem(hwnd, IDC_ADDFILE), bEnableCopy);
//
// Set the description on the ui.
//
Assert(RootSpecialData != NULL);
SetDlgItemText(hwnd, IDC_ADDDIRS_DESCR, RootSpecialData->Description); }
//---------------------------------------------------------------------------
//
// This section of code implements OnAddFileDir() which is called when
// the user pushes the ADD button. We have to allow the user to Browse
// for the source file/dir, then do the copy/tree-copy and update the
// tree-view display.
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// Function: BrowseForSourceDir
//
// Purpose: This function pulls up the SHBrowseForFolder dialog and allows
// the user to select a directory to copy NT binaries into.
//
// Arguments:
// HWND hwnd - owning window
// LPTSTR PathBuffer - MAX_PATH buffer to receive results
//
// Returns: BOOL - TRUE if the user entered a path
// FALSE if the user canceled out of the dialog
//
// Notes:
//
//---------------------------------------------------------------------------
BOOL BrowseForSourceDir(HWND hwnd, LPTSTR PathBuffer) { BROWSEINFO BrowseInf; UINT ulFlags = BIF_BROWSEINCLUDEFILES | BIF_RETURNONLYFSDIRS | BIF_EDITBOX; LPITEMIDLIST lpIdList;
if( StrSelectFileOrFolderToCopy == NULL ) { StrSelectFileOrFolderToCopy = MyLoadString( IDS_SELECT_FILE_OR_FOLDER ); }
//
// ISSUE-2002/02/28-stelo-
// - No initial root, should go back where it was last time
// - Need a callback to grey out root of drive
//
//
// Go browse
//
BrowseInf.hwndOwner = hwnd; BrowseInf.pidlRoot = NULL; // root == desktop
BrowseInf.pszDisplayName = PathBuffer; // output (useless)
BrowseInf.lpszTitle = StrSelectFileOrFolderToCopy; BrowseInf.ulFlags = ulFlags; BrowseInf.lpfn = NULL; // no callback
BrowseInf.lParam = (LPARAM) 0; // no callback
BrowseInf.iImage = 0; // no image
lpIdList = SHBrowseForFolder(&BrowseInf);
//
// Get the pathname out of this idlist returned and free up the memory
//
if ( lpIdList == NULL ) { PathBuffer[0] = _T('\0');
return( FALSE ); } else { SHGetPathFromIDList(lpIdList, PathBuffer); MyGetFullPath(PathBuffer); ILFreePriv(lpIdList);
return( TRUE ); } }
//----------------------------------------------------------------------------
//
// Function: AdditionalDirsCopyTree
//
// Purpose: Copies a directory tree to the given folder. The tree-view
// display is not updated or anything of the sort. It simply
// copies the tree.
//
// This is a support routine for OnAddFileDir() and should
// not be called otherwise.
//
// Arguements:
// HWND hwnd - owning window
// LPTSTR lpSource - MAX_PATH buffer
// LPTSTR lpDest - MAX_PATH buffer
// LPTSTR lpFileNamePart - if d:\foo\bar, this should be "bar"
// HTREEITEM hParentItem - parent item on the display
//
// Returns: VOID
//
// Notes:
// - Both lpSource and lpDest must be directories, and each must
// be a MAX_PATH buffer.
//
// - Any paths >= MAX_PATH in length are silently skipped.
//
// - lpFileNamePart can point to any buffer anywhere, it does not
// have to point into lpSource or lpDest buffers. It just has to
// have the right data.
//
//----------------------------------------------------------------------------
VOID AdditionalDirsCopyTree(HWND hwnd, LPTSTR lpSource, LPTSTR lpDest, LPTSTR lpFileNamePart, HTREEITEM hParentItem) { LPTSTR SrcPathEnd = lpSource + lstrlen(lpSource); LPTSTR DestPathEnd = lpDest + lstrlen(lpDest); HANDLE FindHandle; WIN32_FIND_DATA FindData; int iSmallIcon, iOpenIcon; HTREEITEM hItem;
//
// Create the folder
//
if ( ! CreateDirectory(lpDest, NULL) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_CREATE_FOLDER, lpDest); return; }
//
// Add the tree-view item for this folder
//
iSmallIcon = LoadShellIcon(lpSource, SHGFI_SMALLICON); iOpenIcon = LoadShellIcon(lpSource, SHGFI_OPENICON);
if ( (hItem = InsertSingleItem(hwnd, lpFileNamePart, iSmallIcon, iOpenIcon, NULL, hParentItem)) == NULL ) { return; }
//
// loop over lpSource\*
//
if ( ! ConcatenatePaths(lpSource, _T("*"), NULL) ) return;
FindHandle = FindFirstFile(lpSource, &FindData); if ( FindHandle == INVALID_HANDLE_VALUE ) return;
do {
*SrcPathEnd = _T('\0'); *DestPathEnd = _T('\0');
//
// skip over the . and .. entries
//
if (0 == lstrcmp(FindData.cFileName, _T(".")) || 0 == lstrcmp(FindData.cFileName, _T(".."))) continue;
//
// Build the new source and dest names
//
if ( ! ConcatenatePaths(lpSource, FindData.cFileName, NULL) || ! ConcatenatePaths(lpDest, FindData.cFileName, NULL) ) continue;
//
// If the source is a file, copy it. If it's a directory, create
// the directory at the destination and recurse.
//
if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
if ( ! CopyFile(lpSource, lpDest, TRUE) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_COPY_FILE, lpSource, lpDest); continue; }
SetFileAttributes(lpDest, FILE_ATTRIBUTE_NORMAL);
//
// Add the tree-view item for this file
//
iSmallIcon = LoadShellIcon(lpSource, SHGFI_SMALLICON); iOpenIcon = LoadShellIcon(lpSource, SHGFI_OPENICON);
if ( InsertSingleItem(hwnd, FindData.cFileName, iSmallIcon, iOpenIcon, NULL, hItem) == NULL ) { continue; } }
else {
AdditionalDirsCopyTree(hwnd, lpSource, lpDest, FindData.cFileName, hItem); }
} while ( FindNextFile(FindHandle, &FindData) );
*SrcPathEnd = _T('\0'); *DestPathEnd = _T('\0'); FindClose(FindHandle); }
//----------------------------------------------------------------------------
//
// Function: OnAddFileDir
//
// Purpose: This function is called when the AddFile button is pushed.
//
// Arguments:
// HWND hwnd - owning window
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID OnAddFileDir(HWND hwnd) { TCHAR SrcPathBuffer[MAX_PATH]; TCHAR DestPathBuffer[MAX_PATH]; HTREEITEM hItem; TCHAR *lpFileNamePart; BOOL bSrcIsDir;
//
// Browse for the source path. User can cancel on the source, so
// be sure to check.
//
BrowseForSourceDir(hwnd, SrcPathBuffer); if ( SrcPathBuffer[0] == _T('\0') ) return;
//
// Get the simple filename out of the src. e.g. d:\foo\bar, we want
// the "bar".
//
// Note:
//
// If there's no "bar" there, then the user probably selected the
// root of a drive (c:\ or d:\ etc.) In that case we'll give a
// generic stop message "Setup Manager cannot copy path %s". We
// can't assume in the error text that it was the root the user
// tried to copy. (although I don't know of another cause, there
// might be one).
//
// ISSUE-2002/02/28-stelo- Turn this into an assert when SHBrowseForFolder call is fixed.
//
lpFileNamePart = MyGetFullPath(SrcPathBuffer);
if ( lpFileNamePart == NULL ) { ReportErrorId(hwnd, MSGTYPE_ERR, IDS_ERR_CANNOT_COPY_PATH, SrcPathBuffer); return; }
//
// We will always copy into the current folder, cat the simple name
// of source onto the destination folder.
//
lstrcpyn(DestPathBuffer, gCurSel.lpCurFolderPath, AS(DestPathBuffer)); if ( ! ConcatenatePaths(DestPathBuffer, lpFileNamePart, NULL) ) return;
//
// Copy it
//
if ( DoesFolderExist(SrcPathBuffer) ) { AdditionalDirsCopyTree(hwnd, SrcPathBuffer, DestPathBuffer, lpFileNamePart, gCurSel.hCurFolderItem); }
else {
int iSmallIcon = LoadShellIcon(SrcPathBuffer, SHGFI_SMALLICON); int iOpenIcon = LoadShellIcon(SrcPathBuffer, SHGFI_OPENICON);
if ( ! CopyFile(SrcPathBuffer, DestPathBuffer, TRUE) ) {
ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_COPY_FILE, SrcPathBuffer, DestPathBuffer); return; }
SetFileAttributes(DestPathBuffer, FILE_ATTRIBUTE_NORMAL);
if ( (hItem = InsertSingleItem(hwnd, lpFileNamePart, iSmallIcon, iOpenIcon, NULL, gCurSel.hCurFolderItem)) == NULL ) { return; } }
//
// We have to update the tree-view's image list because we added
// files and we may have encountered icons we haven't seen before.
//
SetOurImageList(GetDlgItem(hwnd, IDC_FILETREE)); }
//----------------------------------------------------------------------------
//
// This section of code implements OnRemoveFileDir() which is called
// when the user pushes the REMOVE button.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: AddDirsDeleteNode
//
// Purpose: Function to delete a node from a disk. This function is
// support for OnRemoveFileDir() and should not be called
// otherwise.
//
// Arguments:
// HWND hwnd - owning window
// LPTSTR lpRoot - fully qualified root path
// LPTSTR lpFileNamePart - if lpRoot==d:\foo\bar, pass "bar"
// HTREEITEM hItem - item for lpRoot
//
// Returns:
// VOID
//
// Notes:
// - lpRoot must be a buffer MAX_PATH wide
// - Paths >= MAX_PATH in length are silently skipped
//
//----------------------------------------------------------------------------
VOID AddDirsDeleteNode(HWND hwnd, LPTSTR lpRoot, LPTSTR lpFileNamePart, HTREEITEM hItem) { LPTSTR lpRootEnd = lpRoot + lstrlen(lpRoot); HWND hTv = GetDlgItem(hwnd, IDC_FILETREE); HANDLE FindHandle; WIN32_FIND_DATA FindData; HTREEITEM hCurItem;
//
// loop over lpRoot\*
//
if ( ! ConcatenatePaths(lpRoot, _T("*"), NULL) ) return;
FindHandle = FindFirstFile(lpRoot, &FindData); if ( FindHandle == INVALID_HANDLE_VALUE ) return;
do {
*lpRootEnd = _T('\0');
//
// skip over the . and .. entries
//
if (0 == lstrcmp(FindData.cFileName, _T(".")) || 0 == lstrcmp(FindData.cFileName, _T(".."))) continue;
//
// Build the new path name
//
if ( ! ConcatenatePaths(lpRoot, FindData.cFileName, NULL) ) continue;
//
// Find the corresponding tree-view item for this file/dir
//
hCurItem = FindItemByName(hTv, hItem, FindData.cFileName);
//
// If the source is a file, delete it, else recurse.
//
if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
if ( ! DeleteFile(lpRoot) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_DELETE_FILE, lpRoot); continue; }
if ( hCurItem != NULL ) TreeView_DeleteItem(hTv, hCurItem); }
else { AddDirsDeleteNode(hwnd, lpRoot, FindData.cFileName, hCurItem); }
} while ( FindNextFile(FindHandle, &FindData) );
*lpRootEnd = _T('\0'); FindClose(FindHandle);
//
// Remove the root directory
//
if ( ! RemoveDirectory(lpRoot) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_DELETE_FOLDER, lpRoot); return; }
//
// Only delete the tree-view entry if there are no children left.
//
// There could be children left in this dir because a DeleteFile()
// could have failed on a recursive call. e.g. a read-only file.
//
if ( TreeView_GetChild(hTv, hItem) == NULL ) TreeView_DeleteItem(hTv, hItem); }
//----------------------------------------------------------------------------
//
// Function: OnRemoveFileDir
//
// Purpose: This function is called when the RemoveFile button is pushed.
//
//----------------------------------------------------------------------------
VOID OnRemoveFileDir(HWND hwnd) { LPTSTR lpPath = gCurSel.lpCurItemPath; HTREEITEM hItem = gCurSel.hCurItem; HWND hTv = GetDlgItem(hwnd, IDC_FILETREE); int iRet;
//
// Look at the current selection, and delete the file or delete
// the node.
//
if ( DoesFolderExist(lpPath) ) {
iRet = ReportErrorId(hwnd, MSGTYPE_YESNO, IDS_DELETE_FOLDER_CONFIRM, lpPath);
if ( iRet == IDYES ) { AddDirsDeleteNode(hwnd, lpPath, MyGetFullPath(lpPath), hItem); } }
else {
iRet = ReportErrorId(hwnd, MSGTYPE_YESNO, IDS_DELETE_FILE_CONFIRM, lpPath);
if ( iRet == IDYES ) {
if ( ! DeleteFile(lpPath) ) { ReportErrorId(hwnd, MSGTYPE_ERR | MSGTYPE_WIN32, IDS_ERR_DELETE_FILE, lpPath); }
TreeView_DeleteItem(hTv, hItem); } } }
//----------------------------------------------------------------------------
//
// This section of code is for Sysprep functions
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: CopySysprepFileLow
//
// Purpose: Copies one file to the destination specified. Handles any errors
// that occur during the copy.
//
// Arguments:
// HWND hwnd - handle to the dialog box
// TCHAR *szSysprepPathandFileNameSrc - path and file name of source file to copy
// TCHAR *szSysprepPathandFileNameDest - path and file name of where to copy the file
// TCHAR *szSysprepPath - the path to the sysprep dir
// TCHAR *szDirectory - directory to begin the search for the file
// TCHAR const * const szFileName - the file name to copy
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID CopySysprepFileLow( IN HWND hwnd, IN TCHAR *szSysprepPathandFileNameSrc, IN TCHAR *szSysprepPathandFileNameDest, IN TCHAR *szSysprepPath, IN TCHAR *szDirectory, IN TCHAR const * const szFileName ) { BOOL bCopyRetVal = FALSE; INT iRetVal;
//
// Only do the copy if the file isn't already there
//
if( ! DoesFileExist( szSysprepPathandFileNameDest ) ) {
//
// If the file is in the current dir, just copy it,
// else prompt the user for the location
//
if( DoesFileExist( szSysprepPathandFileNameSrc ) ) {
bCopyRetVal = CopyFile( szSysprepPathandFileNameSrc, szSysprepPathandFileNameDest, TRUE );
} else {
BOOL bCopyCompleted = FALSE;
do {
ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_SPECIFY_FILE, szFileName );
iRetVal = ShowBrowseFolder( hwnd, g_szSysprepFileFilter, SYSPREP_FILE_EXTENSION, OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, szDirectory, szSysprepPathandFileNameSrc );
if( ! iRetVal ) { // user pressed cancel on the Browse dialog
ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_UNABLE_TO_COPY_SYSPREP_FILE, szFileName, szSysprepPath );
break; }
if( szSysprepPathandFileNameSrc && ( lstrcmpi( MyGetFullPath( szSysprepPathandFileNameSrc ), szFileName ) == 0 ) ) {
bCopyRetVal = CopyFile( szSysprepPathandFileNameSrc, szSysprepPathandFileNameDest, TRUE );
bCopyCompleted = TRUE;
}
} while( ! bCopyCompleted );
}
if( ! bCopyRetVal && iRetVal ) {
ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_UNABLE_TO_COPY_SYSPREP_FILE, szFileName, szSysprepPath );
}
SetFileAttributes( szSysprepPathandFileNameDest, FILE_ATTRIBUTE_NORMAL ); }
}
//----------------------------------------------------------------------------
//
// Function: CopySysprepFiles
//
// Purpose: Copies sysprep.exe and setupcl.exe to the sysprep dir on the
// system drive. Handles any errors that occur during the copy.
//
// Arguments: HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID CopySysprepFiles( IN HWND hwnd ) {
BOOL bCancel; TCHAR szSysprepPath[MAX_PATH] = _T(""); TCHAR szCurrentDirectory[MAX_PATH+1] = _T(""); TCHAR szSysprepPathandFileNameSrc[MAX_PATH] = _T(""); TCHAR szSysprepPathandFileNameDest[MAX_PATH] = _T("");
MakeSysprepSetupFilesPath( szSysprepPath );
EnsureDirExists( szSysprepPath );
// GetModuleFileName may not terminate path if path is truncated in the case
// of the file spec using the //?/ format and exceeding MAX_PATH. This should
// never happen in our case, but we will make the check and NULL terminate
if (GetModuleFileName( NULL, szCurrentDirectory, MAX_PATH) >= MAX_PATH) szCurrentDirectory[MAX_PATH]='\0';
//
// Copy sysprep.exe to the sysprep dir
//
ConcatenatePaths( szSysprepPathandFileNameSrc, szCurrentDirectory, SYSPREP_EXE, NULL );
ConcatenatePaths( szSysprepPathandFileNameDest, szSysprepPath, SYSPREP_EXE, NULL );
CopySysprepFileLow( hwnd, szSysprepPathandFileNameSrc, szSysprepPathandFileNameDest, szSysprepPath, szCurrentDirectory, SYSPREP_EXE );
//
// Store the path where the 1st file was found
//
GetPathFromPathAndFilename( szSysprepPathandFileNameSrc, szCurrentDirectory, AS(szCurrentDirectory));
//
// Copy setupcl.exe to the sysprep dir
//
szSysprepPathandFileNameSrc[0] = _T('\0'); szSysprepPathandFileNameDest[0] = _T('\0');
ConcatenatePaths( szSysprepPathandFileNameSrc, szCurrentDirectory, SETUPCL_EXE, NULL );
ConcatenatePaths( szSysprepPathandFileNameDest, szSysprepPath, SETUPCL_EXE, NULL );
CopySysprepFileLow( hwnd, szSysprepPathandFileNameSrc, szSysprepPathandFileNameDest, szSysprepPath, szCurrentDirectory, SETUPCL_EXE );
}
//----------------------------------------------------------------------------
//
// Function: CopyAllFilesInDir
//
// Purpose:
//
// Arguments: HWND hwnd - handle to the dialog box
// TCHAR *szSrcDir - dir of all the files to copy
// TCHAR *szDestDir - dest where the files are to be copied to
//
// Returns: BOOL
// TRUE - if all the files in the dir were successfully copied
// FALSE - if there were errors during the copy
//
//----------------------------------------------------------------------------
static BOOL CopyAllFilesInDir( IN HWND hwnd, IN TCHAR *szSrcDir, IN TCHAR *szDestDir ) {
HANDLE FindHandle; WIN32_FIND_DATA FindData; TCHAR szSrcRootPath[MAX_PATH]; TCHAR szDestRootPath[MAX_PATH]; TCHAR szDirectoryWithTheFiles[MAX_PATH] = _T("");
lstrcpyn( szDirectoryWithTheFiles, szSrcDir, AS(szDirectoryWithTheFiles) );
lstrcatn( szDirectoryWithTheFiles, _T("\\*"), MAX_PATH );
FindHandle = FindFirstFile( szDirectoryWithTheFiles, &FindData );
// ISSUE-2002/02/28-stelo- on the returns should I signal an error?
// ISSUE-2002/02/28-stelo- test to make sure this will copy a subdirectory if one exists
if ( FindHandle == INVALID_HANDLE_VALUE ) return( FALSE );
do {
szSrcRootPath[0] = _T('\0'); szDestRootPath[0] = _T('\0');
if( lstrcmp( FindData.cFileName, _T(".") ) == 0 || lstrcmp( FindData.cFileName, _T("..") ) == 0 ) continue;
if( ! ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ) {
BOOL test;
ConcatenatePaths( szSrcRootPath, szSrcDir, FindData.cFileName, NULL );
ConcatenatePaths( szDestRootPath, szDestDir, FindData.cFileName, NULL );
CopyFile( szSrcRootPath, szDestRootPath, FALSE );
SetFileAttributes( szDestRootPath, FILE_ATTRIBUTE_NORMAL );
} else {
//
// Create the dir and recurse
//
if ( ! EnsureDirExists( szDestDir ) ) {
UINT iRet;
iRet = ReportErrorId( hwnd, MSGTYPE_RETRYCANCEL | MSGTYPE_WIN32, IDS_ERR_CREATE_FOLDER, szDestDir );
return( FALSE );
}
if ( ! CopyAllFilesInDir( hwnd, szSrcRootPath, szDestDir ) ) { return( FALSE ); } }
} while ( FindNextFile( FindHandle, &FindData ) );
return( TRUE );
}
//----------------------------------------------------------------------------
//
// Function: FindFileInWindowsSourceFiles
//
// Purpose: To look through the windows source files for a particular file.
//
// Arguments: IN HWND hwnd - handle to the dialog box
// IN TCHAR *pszFile - the file to search for
// IN TCHAR *pszSourcePath - path to the Windows source files
// OUT TCHAR *pszFoundPath - path to the found file, if found
//
// pszFoundPath is assumed to be able to hold a string of MAX_PATH chars
//
// Returns: BOOL - TRUE if the file is found, FALSE if not
//
//----------------------------------------------------------------------------
static BOOL FindFileInWindowsSourceFiles( IN HWND hwnd, IN TCHAR *pszFile, IN TCHAR *pszSourcePath, OUT TCHAR *pszFoundPath ) {
HANDLE FindHandle; WIN32_FIND_DATA FindData; TCHAR szOriginalPath[MAX_PATH + 1]; TCHAR szPossiblePath[MAX_PATH + 1] = _T(""); TCHAR szPossiblePathAndFileName[MAX_PATH + 1] = _T("");
ConcatenatePaths( szPossiblePathAndFileName, pszSourcePath, pszFile, NULL );
if( DoesFileExist( szPossiblePathAndFileName ) ) {
lstrcpyn( pszFoundPath, pszSourcePath, MAX_PATH );
return( TRUE );
}
//
// Look through the sub-directories for it
//
//
// Save the original path so it can be restored later
//
lstrcpyn( szOriginalPath, pszSourcePath, AS(szOriginalPath) );
//
// Look for * in this dir
//
if ( ! ConcatenatePaths( pszSourcePath, _T("*"), NULL ) ) {
//
// Restore the original path before returning
//
lstrcpyn( pszSourcePath, szOriginalPath, MAX_PATH );
return( FALSE ); }
FindHandle = FindFirstFile( pszSourcePath, &FindData );
if( FindHandle == INVALID_HANDLE_VALUE ) { return( FALSE ); }
do {
//
// skip over the . and .. entries
//
if (0 == lstrcmp(FindData.cFileName, _T(".")) || 0 == lstrcmp(FindData.cFileName, _T(".."))) { continue; }
//
// If this is a dirent, recurse.
//
if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
BOOL bFoundStatus;
pszSourcePath[0] = _T('\0');
if ( ! ConcatenatePaths( pszSourcePath, szOriginalPath, FindData.cFileName, NULL ) ) continue;
bFoundStatus = FindFileInWindowsSourceFiles( hwnd, pszFile, pszSourcePath, pszFoundPath );
if( bFoundStatus ) { return( TRUE ); }
}
} while( FindNextFile( FindHandle, &FindData ) );
FindClose( FindHandle );
//
// Restore the original path
//
lstrcpyn( pszSourcePath, szOriginalPath, MAX_PATH );
lstrcpyn( pszFoundPath, _T(""), MAX_PATH );
return( FALSE );
}
//----------------------------------------------------------------------------
//
// Function: CabinetCallback
//
// Purpose:
//
// Arguments:
//
// Returns: LRESULT
//
//----------------------------------------------------------------------------
UINT WINAPI CabinetCallback( IN PVOID pMyInstallData, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2 ) {
UINT lRetVal = NO_ERROR; FILE_IN_CABINET_INFO *pInfo = NULL;
switch( Notification ) { case SPFILENOTIFY_FILEINCABINET:
pInfo = (FILE_IN_CABINET_INFO *) Param1;
lstrcpyn( pInfo->FullTargetName, szDestinationPath, AS(pInfo->FullTargetName) );
if( lstrcmpi( szFileSearchingFor, pInfo->NameInCabinet) == 0 ) { lRetVal = FILEOP_DOIT; // Extract the file.
bFileCopiedFromCab = TRUE; } else { lRetVal = FILEOP_SKIP; }
break;
default: lRetVal = NO_ERROR; break;
}
return( lRetVal );
}
//----------------------------------------------------------------------------
//
// Function: CopyFromDriverCab
//
// Purpose:
//
// Arguments:
//
// Returns: BOOL
//
//----------------------------------------------------------------------------
static BOOL CopyFromDriverCab( TCHAR *pszCabPathAndFileName, TCHAR* pszFileName, TCHAR* pszDest ) {
lstrcpyn( szFileSearchingFor, pszFileName, AS(szFileSearchingFor) );
lstrcpyn( szDestinationPath, pszDest, AS(szDestinationPath) );
if( ! SetupIterateCabinet( pszCabPathAndFileName, 0, CabinetCallback, 0 ) ) { return( FALSE ); }
//
// See if the file was actually found and copied.
//
if( bFileCopiedFromCab ) { bFileCopiedFromCab = FALSE;
return( TRUE ); } else { return( FALSE ); }
}
//----------------------------------------------------------------------------
//
// Function: AddCompressedFileUnderscore
//
// Purpose: Given a filename it converts it to its compressed name.
//
// Arguments:
// IN OUT TCHAR *pszFileName - the file name to change into its
// compressed file name
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID AddCompressedFileUnderscore( IN OUT TCHAR *pszFileName ) {
TCHAR *pCurrentChar;
pCurrentChar = pszFileName;
while( *pCurrentChar != _T('\0') && *pCurrentChar != _T('.') ) { pCurrentChar++; }
if( *pCurrentChar == _T('\0') ) { AssertMsg( FALSE, "Filename does not contain a period(.)." );
} else { pCurrentChar = pCurrentChar + 3;
*pCurrentChar = _T('_');
*(pCurrentChar + 1) = _T('\0'); }
}
//----------------------------------------------------------------------------
//
// Function: CopyAdditionalLangFiles
//
// Purpose: Copies the additional lang files that are specified in the
// intl.inf for the language groups being installed.
//
// Arguments: IN HWND hwnd - handle to the dialog box
// IN TCHAR *pszSourcePath - source path - must be at least size MAX_PATH
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID CopyAdditionalLangFiles( IN HWND hwnd, IN TCHAR *pszSourcePath ) {
INT i; INT j; INT nEntries; TCHAR *pszLangGroup; INT nLangGroup; INT nNumFilesToCopy; TCHAR szOriginalPath[MAX_PATH + 1]; TCHAR szLangBaseDir[MAX_PATH + 1] = _T(""); TCHAR szSrc[MAX_PATH + 1] = _T(""); TCHAR szDest[MAX_PATH + 1] = _T(""); TCHAR *pFileName; BOOL bFoundFile;
//
// Save the original path so it can be restored later
//
lstrcpyn( szOriginalPath, pszSourcePath, AS(szOriginalPath) );
MakeLangFilesName( szLangBaseDir );
if( ! EnsureDirExists( szLangBaseDir ) ) { // ISSUE-2002/02/28-stelo- report an error
}
nEntries = GetNameListSize( &GenSettings.LanguageGroups );
for( i = 0; i < nEntries; i++ ) {
pszLangGroup = GetNameListName( &GenSettings.LanguageGroups, i );
nLangGroup = _ttoi( pszLangGroup );
nNumFilesToCopy = GetNameListSize( &FixedGlobals.LangGroupAdditionalFiles[ nLangGroup - 1 ] );
AssertMsg( nNumFilesToCopy >= 0, "Bad value for the number of lang files to copy." );
for( j = 0; j < nNumFilesToCopy; j++ ) {
szSrc[0] = _T('\0'); szDest[0] = _T('\0');
//
// Restore the original path as it might have changed on the last iteration
//
lstrcpyn( pszSourcePath, szOriginalPath, MAX_PATH );
pFileName = GetNameListName( &FixedGlobals.LangGroupAdditionalFiles[ nLangGroup - 1 ], j );
ConcatenatePaths( szDest, szLangBaseDir, pFileName, NULL );
bFoundFile = FindFileInWindowsSourceFiles( hwnd, pFileName, pszSourcePath, szSrc );
ConcatenatePaths( szSrc, pFileName, NULL );
if( ! bFoundFile ) {
TCHAR szFileName[MAX_PATH + 1];
//
// If the file doesn't exist, look for the compressed form
//
lstrcpyn( szFileName, pFileName, AS(szFileName) );
AddCompressedFileUnderscore( szFileName );
bFoundFile = FindFileInWindowsSourceFiles( hwnd, szFileName, pszSourcePath, szSrc );
if( bFoundFile ) { TCHAR *pszFileName;
ConcatenatePaths( szSrc, szFileName, NULL );
pszFileName = MyGetFullPath( szDest );
AddCompressedFileUnderscore( pszFileName ); } else {
TCHAR szCabPathAndFileName[MAX_PATH + 1] = _T("");
ConcatenatePaths( szCabPathAndFileName, pszSourcePath, _T("driver.cab"), NULL );
if( ! CopyFromDriverCab( szCabPathAndFileName, pFileName, szDest ) ) {
//
// If the compressed form isn't found either, print an error
// message and move on to the next file
//
ConcatenatePaths( szSrc, pszSourcePath, pFileName, NULL );
ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_CANNOT_FIND_LANG_FILE, szSrc ); }
continue;
}
}
CopyFile( szSrc, szDest, FALSE );
SetFileAttributes( szDest, FILE_ATTRIBUTE_NORMAL );
}
}
//
// Restore the original path
//
lstrcpyn( pszSourcePath, szOriginalPath, MAX_PATH );
}
//----------------------------------------------------------------------------
//
// Function: CopyLanguageFiles
//
// Purpose:
//
// Arguments: IN HWND hwnd - handle to the dialog box
//
// Returns: BOOL - TRUE if a path was specified to the Windows Setup files
// FALSE if not path was specifed, the user canceled the dialog
//
//----------------------------------------------------------------------------
static BOOL CopyLanguageFiles( IN HWND hwnd ) {
INT iLangCount; INT iNumLangsToInstall; INT iCurrentLang = 0; BOOL bCopySuccessful; TCHAR *pszLangPartialPath; TCHAR PathBuffer[MAX_PATH + 1]; TCHAR WindowsSetupPath[MAX_PATH + 1]; TCHAR szLangBaseDir[MAX_PATH + 1] = _T(""); TCHAR szLangPathAndFilesSrc[MAX_PATH + 1] = _T(""); TCHAR szLangPathAndFilesDest[MAX_PATH + 1] = _T("");
MakeLangFilesName( szLangBaseDir );
// ISSUE-2002/02/28-stelo- what if they copied they lang files by hand, then I don't
// want any pop-ups here
iNumLangsToInstall = GetNameListSize( &GenSettings.LanguageGroups );
//
// See if they are any lang files to copy
//
if( iNumLangsToInstall == 0 ) { return( TRUE ); }
if( ! EnsureDirExists( szLangBaseDir ) ) { // ISSUE-2002-02-28-stelo- report an error
}
do {
BOOL bUserProvidedPath;
PathBuffer[0] = _T('\0'); WindowsSetupPath[0] = _T('\0');
ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_SPECIFY_LANG_PATH );
bUserProvidedPath = BrowseForSourceDir( hwnd, PathBuffer );
if( ! bUserProvidedPath ) { return( FALSE ); }
ConcatenatePaths( WindowsSetupPath, PathBuffer, DOSNET_INF, NULL );
} while( ! DoesFileExist( WindowsSetupPath ) );
//
// Copy the language files needed but that are not in each language groups sub-dir
//
CopyAdditionalLangFiles( hwnd, PathBuffer );
iLangCount = GetNameListSize( &GenSettings.LanguageFilePaths );
//
// Advance until we find a language that we need to copy files over for or
// we run out of languages
//
for( iCurrentLang = 0; iCurrentLang < iLangCount; iCurrentLang++ ) {
pszLangPartialPath = GetNameListName( &GenSettings.LanguageFilePaths, iCurrentLang );
//
// If there is actually a lang sub-dir to copy
//
if( lstrcmp( pszLangPartialPath, _T("") ) != 0 ) {
szLangPathAndFilesSrc[0] = _T('\0'); szLangPathAndFilesDest[0] = _T('\0');
ConcatenatePaths( szLangPathAndFilesSrc, PathBuffer, pszLangPartialPath, NULL );
ConcatenatePaths( szLangPathAndFilesDest, szLangBaseDir, pszLangPartialPath, NULL );
//
// Copy the lang files over
//
EnsureDirExists( szLangPathAndFilesDest );
bCopySuccessful = CopyAllFilesInDir( hwnd, szLangPathAndFilesSrc, szLangPathAndFilesDest );
if( ! bCopySuccessful ) { ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_UNABLE_TO_COPY_LANG_DIR, szLangPathAndFilesSrc, szLangPathAndFilesDest ); }
}
}
return( TRUE );
}
//----------------------------------------------------------------------------
//
// This section of code supports the WIZ_NEXT event
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: ComputePnpDriverPathR
//
// Purpose: This is support to compute OemPnpDriversPath. Every dir in
// $oem$\$1\drivers that we find a .inf file in, we add it to the
// OemPnPDriversPath.
//
// ComputePnpDriverPath() is the real entry, not this one.
//
//----------------------------------------------------------------------------
VOID ComputePnpDriverPathR(HWND hwnd, LPTSTR lpRoot) { LPTSTR lpRootEnd = lpRoot + lstrlen(lpRoot); HANDLE FindHandle; WIN32_FIND_DATA FindData; BOOL bAddToSearchPath = FALSE; HRESULT hrCat;
//
// loop over lpRoot\*
//
if ( ! ConcatenatePaths(lpRoot, _T("*"), NULL) ) return;
FindHandle = FindFirstFile(lpRoot, &FindData); if ( FindHandle == INVALID_HANDLE_VALUE ) return;
//
// If it is a sysprep
//
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) {
}
do {
*lpRootEnd = _T('\0');
//
// skip over the . and .. entries
//
if (0 == lstrcmp(FindData.cFileName, _T(".")) || 0 == lstrcmp(FindData.cFileName, _T(".."))) continue;
//
// Build the new path name
//
if ( ! ConcatenatePaths(lpRoot, FindData.cFileName, NULL) ) continue;
//
// If we have a .inf file, mark this directory to be included
// in the search path.
//
{ int len = lstrlen(FindData.cFileName);
if ( ( len > 4 ) && ( LSTRCMPI( &FindData.cFileName[len - 4], _T(".inf") ) == 0 ) ) { bAddToSearchPath = TRUE; } }
//
// If a dirent, recurse.
//
if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
ComputePnpDriverPathR(hwnd, lpRoot); }
} while ( FindNextFile(FindHandle, &FindData) );
*lpRootEnd = _T('\0'); FindClose(FindHandle);
//
// If we found a .inf in this dir, add it to the PnpDriver search path
//
// Note, we don't want c:\win2000dist\$oem$\$1\drivers\foo. We only want
// part of it. We want \drivers\foo. So jump past the SysDrive portion.
//
// Note that this code assumes that \drivers is a sub-dir of the SysDir.
//
if ( bAddToSearchPath ) {
TCHAR Buffer[MAX_PATH]; int len;
if ( WizGlobals.OemPnpDriversPath[0] != _T('\0') ) hrCat=StringCchCat(WizGlobals.OemPnpDriversPath, AS(WizGlobals.OemPnpDriversPath), _T(";"));
MakeSysDriveName(Buffer); len = lstrlen(Buffer);
hrCat=StringCchCat(WizGlobals.OemPnpDriversPath,AS(WizGlobals.OemPnpDriversPath), lpRoot + len); } }
//----------------------------------------------------------------------------
//
// Function: ComputeSysprepPnpPath
//
// Purpose: Determines the path to the sysprep PnP drivers.
//
// The path will always be %systemdrive%\drivers so all we have to do is
// check to see if there are any files there. If there are set the path, if
// not, then do not set the path.
//
//----------------------------------------------------------------------------
VOID ComputeSysprepPnpPath( TCHAR* Buffer ) {
HANDLE FindHandle; WIN32_FIND_DATA FindData; INT iFileCount = 0; TCHAR szDriverFiles[MAX_PATH] = _T("");
if ( ! ConcatenatePaths(szDriverFiles, Buffer, _T("*"), NULL) ) return;
FindHandle = FindFirstFile(szDriverFiles, &FindData); if( FindHandle == INVALID_HANDLE_VALUE ) { return; }
do { iFileCount++; } while( FindNextFile( FindHandle, &FindData ) && iFileCount < 3 );
//
// every directory contains 2 files, "." and "..", so we have to check
// for 3 or more to determine if there are any real files there.
//
if( iFileCount >= 3) { lstrcpyn( WizGlobals.OemPnpDriversPath, Buffer, AS(WizGlobals.OemPnpDriversPath) ); }
}
//----------------------------------------------------------------------------
//
// Function: ComputePnpDriverPath
//
// Purpose: When user hits the NEXT button, we compute the OemPnpDriversPath
// based on what we find in $oem$\$1\drivers.
//
// Every sub-dir that has a .inf in it, gets put on the path.
//
//----------------------------------------------------------------------------
VOID ComputePnpDriverPath(HWND hwnd) { TCHAR Buffer[MAX_PATH] = NULLSTR; WizGlobals.OemPnpDriversPath[0] = _T('\0'); MakePnpDriversName(Buffer);
//
// If it is a sysprep, then we know the drivers are in %systemdrive%\drivers.
// Just check to see if there are any files there.
// If it is not a sysprep, then we need to cat together the paths to the
// driver directories.
//
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) { ComputeSysprepPnpPath( Buffer ); } else { ComputePnpDriverPathR(hwnd, Buffer); } }
//----------------------------------------------------------------------------
//
// Function: OnWizNextAddDirs
//
// Purpose:
//
// Arguments: IN HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//----------------------------------------------------------------------------
BOOL OnWizNextAddDirs( IN HWND hwnd ) {
BOOL bUserCanceled = TRUE;
ComputePnpDriverPath(hwnd);
//
// If it is a sysprep, make sure the sysprep directory exists
// and the appropriate files are copied
//
if( WizGlobals.iProductInstall == PRODUCT_SYSPREP ) {
TCHAR szBuffer[MAX_PATH + 1] = _T("");
//
// Make the necessary sysprep directories
//
MakeLangFilesName( szBuffer ); if ( szBuffer[0] ) { CreateDirectory( szBuffer, NULL );
MakePnpDriversName( szBuffer ); CreateDirectory( szBuffer, NULL );
CopySysprepFiles( hwnd );
bUserCanceled = CopyLanguageFiles( hwnd ); }
}
//
// See if we need to copy the IE Branding file and if we do then copy it.
//
if( ( GenSettings.IeCustomizeMethod == IE_USE_BRANDING_FILE ) && ( GenSettings.szInsFile[0] != _T('\0') ) ) {
if( DoesFileExist( GenSettings.szInsFile ) ) { TCHAR szDestPathAndFileName[MAX_PATH + 1] = _T(""); TCHAR *pszFileName = NULL;
pszFileName = MyGetFullPath( GenSettings.szInsFile );
ConcatenatePaths( szDestPathAndFileName, WizGlobals.OemFilesPath, pszFileName, NULL );
CopyFile( GenSettings.szInsFile, szDestPathAndFileName, FALSE ); } else { ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_INS_FILE_NO_COPY, WizGlobals.OemFilesPath ); }
} else { }
//
// Route the wizard
//
return (!bUserCanceled);
}
//----------------------------------------------------------------------------
//
// This section of code is the skeleton of a dialog procedure for
// this page.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: DlgAdditionalDirsPage
//
// Purpose: This is the dialog procedure the additional dirs page
//
//----------------------------------------------------------------------------
INT_PTR CALLBACK DlgAdditionalDirsPage( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { BOOL bStatus = TRUE;
switch (uMsg) {
case WM_INITDIALOG: OnInitAddDirs(hwnd); break;
case WM_COMMAND: { int nButtonId;
switch ( nButtonId = LOWORD(wParam) ) {
case IDC_ADDFILE: if ( HIWORD(wParam) == BN_CLICKED ) OnAddFileDir(hwnd); break;
case IDC_REMOVEFILE: if ( HIWORD(wParam) == BN_CLICKED ) OnRemoveFileDir(hwnd); break;
default: bStatus = FALSE; break; } } break;
case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lParam; LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam; LPNMTVDISPINFO pnmdisp = (LPNMTVDISPINFO) lParam; LPNMTVKEYDOWN pnmkey = (LPNMTVKEYDOWN) lParam;
if ( pnmh->idFrom == IDC_FILETREE ) {
switch( pnmh->code ) {
case TVN_SELCHANGED: OnTreeViewSelectionChange(hwnd); break;
default: bStatus = FALSE; break; } }
else {
switch( pnmh->code ) {
case PSN_QUERYCANCEL: CancelTheWizard(hwnd); break;
case PSN_SETACTIVE:
OnSetActiveAddDirs( hwnd );
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | PSWIZB_NEXT); break;
case PSN_WIZBACK: break;
case PSN_WIZNEXT:
if ( !OnWizNextAddDirs( hwnd ) ) WIZ_FAIL(hwnd);
break;
default: bStatus = FALSE; break; } } } break;
default: bStatus = FALSE; break; } return bStatus; }
|