mirror of https://github.com/tongzx/nt5src
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.
3649 lines
102 KiB
3649 lines
102 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
|