Leaked source code of windows server 2003
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.
 
 
 
 
 
 

6121 lines
167 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
wizard.cpp
Abstract:
Code for the Fix Wizard
Author:
kinshu created July 2, 2001
Notes:
1. Whenever we are using Delete*****, please make sure that after return the
arg passed is nulled as well.
Revision History:
--*/
#include "precomp.h"
//////////////////////// Extern variables /////////////////////////////////////
extern HINSTANCE g_hInstance;
extern HIMAGELIST g_hImageList;
extern struct DataBase GlobalDataBase;
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Defines //////////////////////////////////////////////
// The tree in the matching file page of the wizard has its own imagelist. This is the index of
// the attribute image in that imagelist
#define IMAGE_ATTRIBUTE_MATCHTREE 1;
// These are the various pages of the wizard
// The first page, we get the app info here
#define PAGE_APPNAME 0
// The second page, we get the layers to be applied here
#define PAGE_LAYERS 1
// The third page, we get the shims to be applied here
#define PAGE_SHIMS 2
// The fourth page, we get the mathcing files for the entry here
#define PAGE_MATCH 3
// Total number of pages in the wizard
#define NUM_PAGES 4
// The first column in the get params dialog list view. The type of module, include or exclude
#define COLUMN_TYPE 0
// The second column in the get params dialog. The name of the module
#define COLUMN_NAME 1
//
// maximum number of matching files that we should be considered. Note that this does
// not mean that an entry can have MAX_FILES matching files. From MAX_FILES files we will
// select the largest MAX_AUTO_MATCH files
#define MAX_FILES 100
// The length of the module name in chars. This does not include the terminating NULL
#define MAX_MODULE_NAME (MAX_PATH - 1)
// The length of the command line in chars. This does not include the terminating NULL
#define MAX_COMMAND_LINE (511)
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Global Variables /////////////////////////////////////
//
// Should we test for the checking off of the check boxes? We do it only if this variable is TRUE
// Otherwise when we show all the items in ShowItems(), we might get the prompt even then
// This is a hack and needs to be corrected <TODO>
BOOL g_bNowTest = FALSE;
/*++
WARNING: Do not change the position of these strings, they should match
with the dialog IDD_LAYERS radio buttons
--*/
// The names of the various OS layers as they are in the system db: sysmain.sdb
TCHAR *s_arszOsLayers[] = {
TEXT("Win95"),
TEXT("NT4SP5"),
TEXT("Win98"),
TEXT("Win2000")
};
// The layers have changed since the last time we have populated the shims list
BOOL g_bLayersChanged = FALSE;
//
// The LUA layer needs to be treated specially - when the user selects it
// on the select layer page, we only check the checkbox but really add the
// shims in the layer to the shim fix list instead of add the layer to the
// layer fix list. This allows us to later change the lua data around in
// the DBENTRY without affect the layer globally.
BOOL g_bIsLUALayerSelected = FALSE;
//
// Used for indicating whether the LUA wizard should start when the app fix wizard
// is completed
BOOL g_bShouldStartLUAWizard = FALSE;
// The pointer to the current wizard object
CShimWizard* g_pCurrentWizard = NULL;
// The handle to the matching file tree
static HWND s_hwndTree = NULL;
// The handle to the tool tip control associated with the list view in the shims page
static HWND s_hwndToolTipList;
// The image list for the tree in the matching files page
static HIMAGELIST s_hMatchingFileImageList;
// This will be true if we change some stuff in the shim page.
static BOOL s_bLayerPageRefresh;
// The handle to the layer list view in the second wizard page
static HWND s_hwndLayerList;
// The handle to the fixes list view in the second wizard page
static HWND s_hwndShimList;
// Are we showing all the shims or only the selected shims
static BOOL s_bAllShown = TRUE;
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Function Declarations ////////////////////////////////
INT_PTR
GetAppNameDlgOnCommand(
HWND hDlg,
WPARAM wParam
);
INT_PTR
GetAppNameDlgOnInitDialog(
HWND hDlg
);
INT_PTR
GetAppNameDlgOnNotify(
HWND hDlg,
LPARAM lParam
);
INT_PTR
SelectLayerDlgOnCommand(
HWND hDlg,
WPARAM wParam
);
INT_PTR
SelectLayerDlgOnDestroy(
void
);
INT_PTR
SelectLayerDlgOnNotify(
HWND hDlg,
LPARAM lParam
);
INT_PTR
SelectLayerDlgOnInitDialog(
HWND hDlg
);
INT_PTR
SelectShimsDlgOnNotify(
HWND hDlg,
LPARAM lParam
);
INT_PTR
SelectShimsDlgOnInitDialog(
HWND hDlg
);
INT_PTR
SelectFilesDlgOnInitDialog(
HWND hDlg
);
INT_PTR
SelectFilesDlgOnCommand(
HWND hDlg,
WPARAM wParam
);
INT_PTR
SelectFilesDlgOnMatchingTreeRefresh(
IN HWND hDlg
);
INT_PTR
SelectFilesDlgOnNotify(
HWND hDlg,
LPARAM lParam
);
INT_PTR
SelectShimsDlgOnCommand(
HWND hDlg,
WPARAM wParam
);
INT_PTR
SelectShimsDlgOnTimer(
HWND hDlg
);
INT_PTR
SelectShimsDlgOnDestroy(
void
);
BOOL
AddLuaShimsInEntry(
PDBENTRY pEntry,
CSTRINGLIST* pstrlShimsAdded = NULL
);
void
ShowParams(
HWND hDlg,
HWND hwndList
);
void
AddMatchingFileToTree(
HWND hwndTree,
PMATCHINGFILE pMatch,
BOOL bAddToMatchingList
);
INT_PTR
CALLBACK
SelectShims(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
void
HandleShowAllAtrr(
HWND hdlg
);
void
ChangeShimIcon(
LPCTSTR pszItem
);
void
HandleAddMatchingFile(
HWND hdlg,
CSTRING& strFilename,
CSTRING& strRelativePath,
DWORD dwMask = DEFAULT_MASK
);
BOOL
HandleAttributeTreeNotification(
HWND hdlg,
LPARAM lParam
);
///////////////////////////////////////////////////////////////////////////////
BOOL
LayerPresent(
IN PLAYER_FIX plf,
IN PDBENTRY pEntry,
OUT PLAYER_FIX_LIST* ppLayerFixList
)
/*++
LayerPresent
Desc: Checks if the entry pEntry is fixed with layer plf.
If yes and ppLayerFixList is not NULL, stores the corresponding pointer to layer-fix
list for plf in pEntry in ppLayerFixList
Params:
IN PLAYER_FIX plf : The layer to search
IN PDBENTRY pEntry : The entry in which to search
OUT PLAYER_FIX_LIST* ppLayerFixList : If the layer is present in pEntry and
ppLayerFixList is not NULL, stores the corresponding pointer to layer-fix
list for plf in pEntry in ppLayerFixList
Return:
TRUE : pEntry is fixed with plf
FALSE : Otherwise
--*/
{
if (pEntry == NULL) {
assert(FALSE);
return FALSE;
}
PLAYER_FIX_LIST plfl = pEntry->pFirstLayer;
//
// For all layers applied to this entry, check if one of them is the one that we
// are looking for
//
while (plfl) {
if (plfl->pLayerFix == plf) {
if (ppLayerFixList) {
*ppLayerFixList = plfl;
}
return TRUE;
}
plfl = plfl->pNext;
}
return FALSE;
}
BOOL
ShimPresent(
IN PSHIM_FIX psf,
IN PDBENTRY pEntry,
OUT PSHIM_FIX_LIST* ppShimFixList
)
/*++
ShimPresent
Desc: Checks if the entry pEntry is fixed with shim psf.
If yes and ppShimFixList is not NULL, stores the corresponding pointer to shim-fix
list for psf in pEntry in ppShimFixList
Params:
IN PSHIM_FIX psf: The shim to search
IN PDBENTRY pEntry: The entry in which to search
OUT PSHIM_FIX_LIST* ppShimFixList: If the shim is present in pEntry and
ppShimFixList is not NULL, stores the corresponding pointer to shim-fix
list for psf in pEntry in ppShimFixList
Return:
TRUE: pEntry is fixed with psf
FALSE: Otherwise
--*/
{
if (pEntry == NULL) {
assert(FALSE);
return FALSE;
}
PSHIM_FIX_LIST psfList = pEntry->pFirstShim;
//
// For all the shims applied to this entry check if,one of them is the one we are lookign for
//
while (psfList) {
if (psfList->pShimFix)
if (psfList->pShimFix == psf) {
if (ppShimFixList) {
*ppShimFixList = psfList;
}
return TRUE;
}
psfList = psfList->pNext;
}
return FALSE;
}
BOOL
FlagPresent(
IN PFLAG_FIX pff,
IN PDBENTRY pEntry,
OUT PFLAG_FIX_LIST* ppFlagFixList
)
/*++
FlagPresent
Desc: Checks if the entry pEntry is fixed with flag pff.
If yes and ppFlagFixList is not NULL, stores the corresponding pointer to flag-fix
list for pff in pEntry in ppFlagFixList
Params:
IN PFLAG_FIX pff: The flag to search
IN PDBENTRY pEntry: The entry in which to search
OUT PFLAG_FIX_LIST* ppFlagFixList: If the flag is present in pEntry and
ppFlagFixList is not NULL, stores the corresponding pointer to flag-fix
list for pff in pEntry in ppFlagFixList
Return:
TRUE : pEntry is fixed with pff
FALSE : Otherwise
--*/
{
if (pEntry == NULL) {
assert(FALSE);
return FALSE;
}
PFLAG_FIX_LIST pffList = pEntry->pFirstFlag;
//
// For all the flags applied to this entry check if,one of them is the one
// we are looking for
//
while (pffList) {
if (pffList->pFlagFix)
if (pffList->pFlagFix == pff) {
if (ppFlagFixList) {
*ppFlagFixList = pffList;
}
return TRUE;
}
pffList = pffList->pNext;
}
return FALSE;
}
CShimWizard::CShimWizard()
/*++
CShimWizard::CShimWizard
Desc: Constructor for CShimWizard
--*/
{
dwMaskOfMainEntry = DEFAULT_MASK;
}
BOOL
CShimWizard::CheckAndSetLongFilename(
IN HWND hDlg,
IN INT iStrID
)
/*++
CShimWizard::CheckAndSetLongFilename
Desc: If we do not have the complete path of the present entry being fixed,
prompts for that and pops up a open common dialog box to select the file, and
to get the complete path
Params:
IN HWND hDlg: Parent for the open common dialog or any messagebox
IN INT iStrID: String resource id for the prompt message asking for
the complete path of the file being fixed
Return:
TRUE: The complete path has been successfully set
FALSE: Otherwise
--*/
{
TCHAR chTemp;
CSTRING strFilename;
CSTRING strExename;
TCHAR szBuffer[512] = TEXT("");
if (g_pCurrentWizard->m_Entry.strFullpath.Length() == 0) {
g_pCurrentWizard->m_Entry.strFullpath = TEXT("XXXXXX");
}
if (g_pCurrentWizard->m_Entry.strFullpath.GetChar(1, &chTemp)) {
if (chTemp != TEXT(':')) {
//
// Check if the file is on a network. filenames will begin with "\\"
//
if (chTemp == TEXT('\\')) {
g_pCurrentWizard->m_Entry.strFullpath.GetChar(0, &chTemp);
if (chTemp == TEXT('\\')) {
return TRUE;
}
}
//
// We do not have the complete path.
//
MessageBox(hDlg,
CSTRING(iStrID),
g_szAppName,
MB_OK | MB_ICONINFORMATION);
//
// Get the long file name. The g_pCurrentWizard->m_Entry.strFullpath has been
// set in the first page. So if we are editing and we do not have the complete
// path, g_pCurrentWizard->m_Entry.strFullpath will have at least have
// the exe name
//
strExename = g_pCurrentWizard->m_Entry.strFullpath;
strExename.ShortFilename();
GetString(IDS_EXEFILTER, szBuffer, ARRAYSIZE(szBuffer));
//
// Prompt the user to give us the complete path for the file being fixed
// We need the complete path, so that we can get the relative paths for
// any matching files that we might add
//
while (1) {
if (GetFileName(hDlg,
CSTRING(IDS_GETLONGNAME),
szBuffer,
TEXT(""),
CSTRING(IDS_EXE_EXT),
OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
TRUE,
strFilename)) {
CSTRING strTemp = strFilename;
strTemp.ShortFilename();
if (strExename != strTemp) {
//
// The user gave us the path of some file, whose file and exe components
// do not match the program file being fixed
//
MessageBox(hDlg,
CSTRING(IDS_DOESNOTMATCH),
g_szAppName,
MB_ICONWARNING);
//
// So we ask the user to try again
//
continue;
}
//
// We now have the complete path for the file being fixed
//
m_Entry.strFullpath = strFilename;
return TRUE;
} else {
return FALSE;
}
}
}
} else {
//
// There was some error
//
assert(FALSE);
return FALSE;
}
return TRUE;
}
BOOL
IsOsLayer(
IN PCTSTR pszLayerName
)
/*++
IsOsLayer
Desc: Is the passed layer name an OS layer?
Params:
IN TCHAR *pszLayerName: The layer name to check for
Return:
TRUE: If this is the name of an OS layer
FALSE: Otherwise
--*/
{
INT iTotalOsLayers = sizeof (s_arszOsLayers) / sizeof(s_arszOsLayers[0]);
for (int iIndex = 0;
iIndex < iTotalOsLayers;
++iIndex) {
if (lstrcmpi(s_arszOsLayers[iIndex], pszLayerName) == 0) {
return TRUE;
}
}
return FALSE;
}
BOOL
CShimWizard::BeginWizard(
IN HWND hParent,
IN PDBENTRY pEntry,
IN PDATABASE pDatabase,
IN PBOOL pbShouldStartLUAWizard
)
/*++
CShimWizard::BeginWizard
Desc: Starts up the wizard
Params:
IN HWND hParent: The parent of the wizard
IN PDBENTRY pEntry: The entry which has to be editted. If this is NULL, then we
want to create a new fix entry.
IN PDATABASE pDatabase: The present database.
Return:
TRUE: If the user presses FINISH
FALSE: Otherwise
--*/
{
PROPSHEETPAGE Pages[11] = {0};
g_bIsLUALayerSelected = FALSE;
g_bShouldStartLUAWizard = FALSE;
m_pDatabase = pDatabase;
ZeroMemory(Pages, sizeof(Pages));
if (pEntry == NULL) {
//
// Create a new fix.
//
ZeroMemory(&m_Entry, sizeof(m_Entry));
GUID Guid;
CoCreateGuid(&Guid);
StringCchPrintf(m_Entry.szGUID,
ARRAYSIZE(m_Entry.szGUID),
TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
Guid.Data1,
Guid.Data2,
Guid.Data3,
Guid.Data4[0],
Guid.Data4[1],
Guid.Data4[2],
Guid.Data4[3],
Guid.Data4[4],
Guid.Data4[5],
Guid.Data4[6],
Guid.Data4[7]);
m_bEditing = FALSE;
} else {
//
// Edit the passed fix.
//
m_bEditing = TRUE;
//
// Make a copy of the fix that we are going to edit
//
m_Entry = *pEntry;
}
//
// Setup wizard variables
//
g_pCurrentWizard = this;
//
// We are in fix wizard and not in AppHelp wizard
//
m_uType = TYPE_FIXWIZARD;
//
// Begin the wizard
//
PROPSHEETHEADER Header = {0};
Header.dwSize = sizeof(PROPSHEETHEADER);
Header.dwFlags = PSH_WIZARD97 | PSH_HEADER | PSH_WATERMARK | PSH_PROPSHEETPAGE;
Header.hwndParent = hParent;
Header.hInstance = g_hInstance;
Header.nStartPage = 0;
Header.ppsp = Pages;
Header.nPages = NUM_PAGES;
Header.pszbmHeader = MAKEINTRESOURCE(IDB_WIZBMP);
Header.pszbmWatermark = MAKEINTRESOURCE(IDB_TOOL);
if (m_bEditing) {
Header.dwFlags |= PSH_WIZARDHASFINISH;
}
Pages[PAGE_APPNAME].dwSize = sizeof(PROPSHEETPAGE);
Pages[PAGE_APPNAME].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE ;
Pages[PAGE_APPNAME].hInstance = g_hInstance;
Pages[PAGE_APPNAME].pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_APPINFO);
Pages[PAGE_APPNAME].pfnDlgProc = GetAppName;
Pages[PAGE_APPNAME].pszHeaderTitle = MAKEINTRESOURCE(IDS_GIVEAPPINFO);
Pages[PAGE_APPNAME].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_GIVEAPPINFOSUBHEADING);
Pages[PAGE_LAYERS].dwSize = sizeof(PROPSHEETPAGE);
Pages[PAGE_LAYERS].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
Pages[PAGE_LAYERS].hInstance = g_hInstance;
Pages[PAGE_LAYERS].pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_MODES);
Pages[PAGE_LAYERS].pfnDlgProc = SelectLayer;
Pages[PAGE_LAYERS].pszHeaderTitle = MAKEINTRESOURCE(IDS_SELECTLAYERS);
Pages[PAGE_LAYERS].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SELECTLAYERS_SUBHEADING);
Pages[PAGE_SHIMS].dwSize = sizeof(PROPSHEETPAGE);
Pages[PAGE_SHIMS].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
Pages[PAGE_SHIMS].hInstance = g_hInstance;
Pages[PAGE_SHIMS].pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_SHIMS);
Pages[PAGE_SHIMS].pfnDlgProc = SelectShims;
Pages[PAGE_SHIMS].pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPATFIXES);
Pages[PAGE_SHIMS].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SELECTSHIMS_SUBHEADING);
Pages[PAGE_MATCH].dwSize = sizeof(PROPSHEETPAGE);
Pages[PAGE_MATCH].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
Pages[PAGE_MATCH].hInstance = g_hInstance;
Pages[PAGE_MATCH].pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_MATCHINGINFO);
Pages[PAGE_MATCH].pfnDlgProc = SelectFiles;
Pages[PAGE_MATCH].pszHeaderTitle = MAKEINTRESOURCE(IDS_MATCHINFO);
Pages[PAGE_MATCH].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_MATCHINFO_SUBHEADING);
BOOL bReturn = FALSE;
if (0 < PropertySheet(&Header)) {
//
// The user pressed finish in the wizard
//
bReturn = TRUE;
} else {
//
// The user pressed cancel in the wizard
//
bReturn = FALSE;
}
ENABLEWINDOW(g_hDlg, TRUE);
*pbShouldStartLUAWizard = g_bShouldStartLUAWizard;
return bReturn;
}
INT_PTR
CALLBACK
GetAppName(
IN HWND hDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
GetAppName
Desc: Dialog proc for the first page of the wizard. Gets the app info and also sets the
Full path of the entry
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
INT_PTR ipReturn = 0;
switch (uMsg) {
case WM_INITDIALOG:
ipReturn = GetAppNameDlgOnInitDialog(hDlg);
break;
case WM_NOTIFY:
ipReturn = GetAppNameDlgOnNotify(hDlg, lParam);
break;
case WM_COMMAND:
ipReturn = GetAppNameDlgOnCommand(hDlg, wParam);
break;
default: ipReturn = 0;
}
return ipReturn;
}
INT_PTR
CALLBACK
SelectLayer(
IN HWND hDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SelectLayer
Desc: Dialog proc for the second page of the wizard. Gets the layers that have to be
applied to the entry
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
INT_PTR ipReturn = 0;
switch (uMsg) {
case WM_INITDIALOG:
ipReturn = SelectLayerDlgOnInitDialog(hDlg);
break;
case WM_DESTROY:
ipReturn = SelectLayerDlgOnDestroy();
break;
case WM_COMMAND:
ipReturn = SelectLayerDlgOnCommand(hDlg, wParam);
break;
case WM_NOTIFY:
ipReturn = SelectLayerDlgOnNotify(hDlg, lParam);
break;
default: ipReturn = FALSE;
}
return ipReturn;
}
BOOL
CALLBACK
SelectShims(
IN HWND hDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SelectShims
Desc: Dialog proc for the third page of the wizard. Gets the shims that have to be
applied to the entry
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
INT_PTR ipReturn = 0;
switch (uMsg) {
case WM_INITDIALOG:
ipReturn = SelectShimsDlgOnInitDialog(hDlg);
break;
case WM_COMMAND:
ipReturn = SelectShimsDlgOnCommand(hDlg, wParam);
break;
case WM_TIMER:
ipReturn = SelectShimsDlgOnTimer(hDlg);
break;
case WM_DESTROY:
ipReturn = SelectShimsDlgOnDestroy();
break;
case WM_NOTIFY:
ipReturn = SelectShimsDlgOnNotify(hDlg, lParam);
break;
default:
return FALSE;
}
return ipReturn;
}
INT_PTR
CALLBACK
SelectFiles(
IN HWND hDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SelectFiles
Desc: Dialog proc for the matching files page of the wizard. This page is
common to both the fix wizard and the apphelp wizard
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
INT ipReturn = 0;
switch (uMsg) {
case WM_INITDIALOG:
ipReturn = SelectFilesDlgOnInitDialog(hDlg);
break;
case WM_DESTROY:
ImageList_Destroy(s_hMatchingFileImageList);
s_hMatchingFileImageList = NULL;
ipReturn = TRUE;
break;
case WM_USER_MATCHINGTREE_REFRESH:
ipReturn = SelectFilesDlgOnMatchingTreeRefresh(hDlg);
break;
case WM_NOTIFY:
ipReturn = SelectFilesDlgOnNotify(hDlg, lParam);
break;
case WM_COMMAND:
ipReturn = SelectFilesDlgOnCommand(hDlg, wParam);
break;
default:
return FALSE;
}
return ipReturn;
}
void
FileTreeToggleCheckState(
IN HWND hwndTree,
IN HTREEITEM hItem
)
/*++
FileTreeToggleCheckState
Desc: Changes the check state on the attributes tree.
Params:
IN HWND hwndTree: The handle to the attribute tree (In the matching files page)
IN HTREEITEM hItem: The tree item whose check state we want to change
IN int uMode:
--*/
{
BOOL bSate = TreeView_GetCheckState(hwndTree, hItem) ? TRUE:FALSE;
TreeView_SetCheckState(hwndTree, hItem, !bSate);
}
void
AddMatchingFileToTree(
IN HWND hwndTree,
IN PMATCHINGFILE pMatch,
IN BOOL bAddToMatchingList
)
/*++
AddMatchingFileToTree
Desc: Creates a new tree item for pMatch and adds it to the matching tree. If bAddToMatchingList
is TRUE, also adds it to the PMATCHINGFLE for the entry
Params:
IN HWND hwndTree: The matching tree
IN PMATCHINGFILE pMatch: The PMATCHINGFILE to add to the tree
IN BOOL bAddToMatchingList: This will be false, when we are
populating for edit. The pMatch is already in the list and we do not want to
add it again
Return:
void
--*/
{
TVINSERTSTRUCT is;
TCHAR* pszFileNameForImage = NULL;
if (g_pCurrentWizard == NULL || pMatch == NULL) {
assert(FALSE);
return;
}
if (bAddToMatchingList) {
//
// Now add this pMatch to the list for this entry.
//
pMatch->pNext = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
g_pCurrentWizard->m_Entry.pFirstMatchingFile = pMatch;
}
if (g_pCurrentWizard->m_Entry.strFullpath.Length()
&& (pMatch->strFullName == g_pCurrentWizard->m_Entry.strFullpath)) {
pMatch->strMatchName = TEXT("*");
}
is.hParent = TVI_ROOT;
is.item.lParam = (LPARAM)pMatch;
is.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
if (pMatch->strMatchName == TEXT("*")) {
TCHAR szTemp[MAX_PATH + 100]; // 100 is for any text that we might need to add to the file. Such as "Program being fixed"
*szTemp = 0;
StringCchPrintf(szTemp,
ARRAYSIZE(szTemp),
TEXT("%s ( %s )"),
GetString(IDS_MAINEXE),
g_pCurrentWizard->m_Entry.strExeName.pszString);
is.item.pszText = szTemp;
is.hInsertAfter = TVI_FIRST;
if (pMatch->strFullName.Length()) {
pszFileNameForImage = pMatch->strFullName.pszString;
} else {
pszFileNameForImage = g_pCurrentWizard->m_Entry.strExeName.pszString;
}
} else {
is.item.pszText = pMatch->strMatchName;
is.hInsertAfter = TVI_LAST;
if (pMatch->strFullName.Length()) {
pszFileNameForImage = pMatch->strFullName.pszString;
} else {
pszFileNameForImage = pMatch->strMatchName.pszString;
}
}
is.item.iImage = LookupFileImage(s_hMatchingFileImageList,
pszFileNameForImage,
0,
0,
0);
is.item.iSelectedImage = is.item.iImage;
HTREEITEM hParent = TreeView_InsertItem(hwndTree, &is);
is.hInsertAfter = TVI_LAST;
is.hParent = hParent;
is.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
is.item.iSelectedImage = is.item.iImage = IMAGE_ATTRIBUTE_MATCHTREE;
TCHAR szItem[260];
PATTRINFO_NEW pAttr = pMatch->attributeList.pAttribute;
for (DWORD dwIndex = 0; dwIndex < ATTRIBUTE_COUNT; ++dwIndex) {
*szItem = 0;
if (pAttr[dwIndex].dwFlags & ATTRIBUTE_AVAILABLE) {
if (!SdbFormatAttribute(&pAttr[dwIndex], szItem, ARRAYSIZE(szItem))) {
continue;
}
int iPos = TagToIndex(pAttr[dwIndex].tAttrID);
if (iPos == -1) {
continue;
}
if (pMatch->dwMask & (1 << (iPos + 1))) {
is.item.state = INDEXTOSTATEIMAGEMASK(2); //Selected
} else {
is.item.state = INDEXTOSTATEIMAGEMASK(1); //Unselected
}
is.item.stateMask = TVIS_STATEIMAGEMASK;
is.item.pszText = szItem;
is.item.lParam = pAttr[dwIndex].tAttrID;
is.item.iImage = is.item.iSelectedImage = IMAGE_ATTRIBUTE_MATCHTREE;
TreeView_InsertItem(hwndTree, &is);
}
}
TreeView_Expand(hwndTree, hParent, TVE_EXPAND);
TreeView_SelectItem(hwndTree, hParent);
}
PMATCHINGFILE
GetMatchingFileFromAttributes(
IN CSTRING& strFullPath,
IN CSTRING& strRelativePath,
IN PATTRINFO pAttrInfo
)
/*++
GetMatchingFileFromAttributes
Desc: This function takes a PATTRINFO and makes a PMATCHINGFILE out of it and returns that
Params:
IN CSTRING &strFullPath: The full path of the matching file
IN CSTRING &strRelativePath: The relative path of the matching file w.r.t the program
file being fixed
IN PATTRINFO pAttrInfo: The pointer to the array of attributes
Return:
The newly created PMATCHINGFILE if successful
NULL otherwise
--*/
{
PMATCHINGFILE pMatch = new MATCHINGFILE;
if (pMatch == NULL) {
MEM_ERR;
goto error_handler;
}
pMatch->strFullName = strFullPath;
pMatch->strMatchName = strRelativePath;
pMatch->attributeList = pAttrInfo;
return pMatch;
error_handler:
if (pMatch) {
delete pMatch;
}
return NULL;
}
void
HandleAddMatchingFile(
IN HWND hdlg,
IN CSTRING& strFilename,
IN CSTRING& strRelativePath,
IN DWORD dwMask //(DEFAULT_MASK)
)
/*++
HandleAddMatchingFile
Desc: This is the interface function that should be called when we have a matching file and
want to add it.
This routine calls SdbGetFileAttributes() to get the attributes for
the file and then calls GetMatchingFileFromAttributes() to get a PMATCHINGFILE
and AddMatchingFileToTree() to add this PMATCHINGFILE to the tree and to the entry.
Params:
IN HWND hdlg: The matching file wizard page
IN CSTRING &strFilename: The complete path of the matching file
IN CSTRING &strRelativePath: The relative path w.r.t to the program file being fixed
IN DWORD dwMask (DEFAULT_MASK): This is helpful when we are updating the
attributes (showing all attributes) during editing.
This then will contain the previous flags and once the attribute tree is refreshed,
will help us in selecting them,
Return:
void
--*/
{
DWORD dwAttrCount;
BOOL bAlreadyExists = FALSE;
HWND hwndTree = GetDlgItem(hdlg, IDC_FILELIST);
PMATCHINGFILE pMatch = NULL;
PATTRINFO pAttrInfo = NULL;
CSTRING strMessage;
if (g_pCurrentWizard == NULL) {
assert(NULL);
return;
}
pMatch = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
while (pMatch) {
if (pMatch->strMatchName == strRelativePath) {
//
// Already exists .. do not allow
//
bAlreadyExists = TRUE;
break;
} else if (pMatch->strMatchName == TEXT("*")
&& strFilename == g_pCurrentWizard->m_Entry.strFullpath) {
//
// This function is also called to add the matching file info for the
// program file being fixed. So we do not make a check in the beginning
// if the full path is same as the the program being fixed
//
bAlreadyExists = TRUE;
break;
}
pMatch = pMatch->pNext;
}
if (bAlreadyExists == TRUE) {
MessageBox(hdlg,
CSTRING(IDS_MATCHFILEEXISTS),
g_szAppName,
MB_ICONWARNING);
return;
}
//
// Call the attribute manager to get all the attributes for this file.
//
if (SdbGetFileAttributes(strFilename, &pAttrInfo, &dwAttrCount)) {
pMatch = GetMatchingFileFromAttributes(strFilename,
strRelativePath,
pAttrInfo);
if (pMatch) {
pMatch->dwMask = dwMask;
} else {
assert(FALSE);
}
if (pAttrInfo) {
SdbFreeFileAttributes(pAttrInfo);
}
SendMessage(s_hwndTree, WM_SETREDRAW, FALSE, 0);
AddMatchingFileToTree(hwndTree, pMatch, TRUE);
SendMessage(s_hwndTree, WM_SETREDRAW, TRUE, 0);
} else {
//
// We could not get the Attributes... Probably the file was deleted
//
strMessage.Sprintf(GetString(IDS_MATCHINGFILE_DELETED), (LPCTSTR)strFilename);
MessageBox(hdlg, (LPCTSTR) strMessage, g_szAppName, MB_ICONWARNING);
}
}
BOOL
HandleAttributeTreeNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleAttributeTreeNotification
Desc: Handle all the notifications we care about for the matching file tree.
Params:
IN HWND hdlg: The mathching file wizard page
IN LPARAM lParam: the lParam that comes with WM_NOTIFY
Return:
void
--*/
{
HWND hwndTree = GetDlgItem(hdlg, IDC_FILELIST);
LPNMHDR pnm = (LPNMHDR)lParam;
HWND hwndButton;
switch (pnm->code) {
case NM_CLICK:
{
TVHITTESTINFO HitTest;
HTREEITEM hItem;
GetCursorPos(&HitTest.pt);
ScreenToClient(hwndTree, &HitTest.pt);
TreeView_HitTest(hwndTree, &HitTest);
if (HitTest.flags & TVHT_ONITEMSTATEICON) {
FileTreeToggleCheckState(hwndTree, HitTest.hItem);
} else if (HitTest.flags & TVHT_ONITEMLABEL) {
hItem = TreeView_GetParent(hwndTree, HitTest.hItem);
//
// Enable Remove Files button only if we are on a matching file item and not on
// an attribute item
//
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFILES),
hItem == NULL);
}
break;
}
case TVN_KEYDOWN:
{
LPNMTVKEYDOWN lpKeyDown = (LPNMTVKEYDOWN)lParam;
HTREEITEM hItem;
if (lpKeyDown->wVKey == VK_SPACE) {
hItem = TreeView_GetSelection(hwndTree);
if (hItem != NULL) {
FileTreeToggleCheckState(hwndTree, hItem);
}
}
break;
}
default:
return FALSE;
}
return TRUE;
}
void
CShimWizard::WipeEntry(
IN BOOL bMatching,
IN BOOL bShims,
IN BOOL bLayer,
IN BOOL bFlags
)
/*++
WipeEntry
Desc: Removes stuff from m_Entry
Params:
IN BOOL bMatching: Should we remove all the matching files from m_Entry
IN BOOL bShims: Should we remove all the shims from m_Entry
IN BOOL bLayer: Should we remove all the layers from m_Entry
IN BOOL bFlags: Should we remove all the flags from m_Entry
Return:
void
--*/
{
//
// Delete mathcing files, if asked to
//
if (bMatching) {
DeleteMatchingFiles(m_Entry.pFirstMatchingFile);
m_Entry.pFirstMatchingFile = NULL;
}
//
// Delete shims, if asked to
//
if (bShims) {
DeleteShimFixList(m_Entry.pFirstShim);
m_Entry.pFirstShim = NULL;
}
//
// Delete layers, if asked to
//
if (bLayer) {
DeleteLayerFixList(m_Entry.pFirstLayer);
m_Entry.pFirstLayer = NULL;
}
//
// Delete flags, if asked to
//
if (bFlags) {
DeleteFlagFixList(m_Entry.pFirstFlag);
m_Entry.pFirstFlag = NULL;
}
}
void
AddToMatchingFilesList(
IN OUT PMATCHINGFILE* ppMatchListHead,
IN CSTRING& strFileName,
IN CSTRING& strRelativePath
)
/*++
AddToMatchingFilesList
Desc: Adds a PMATCHINGFILE for strFileName, strRelativePath and adds it to ppMatchListHead
Params:
IN OUT PMATCHINGFILE *ppMatchListHead: Pointer to head of a list of PMATCHINGFILE
IN CSTRING &strFileName: Full path of the matching file
IN CSTRING &strRelativePath: Relative path of the matching file w.r.t
to the program file being fixed
Notes: This function is used, when we are using the auto-generate feature.
The WalkDirectory(..) gets the different files from the various directories
and then calls this function.
This function creates a PMATCHINGFILE from the name of the file and then it
adds the PMATCHINGFILE to a list. The list is sorted on the basis of the
non-inc. size of the matching file found.
When WalkDirectory finally returns to GrabMatchingInfo, it takes the first n number of
PMATCHINGFILE (they are the largest ones) and adds them to the tree.
--*/
{
PATTRINFO pAttrInfo = NULL;
DWORD dwAttrCount = 0;
PMATCHINGFILE pMatch = NULL;
PATTRINFO_NEW pAttr = NULL;
DWORD dwSize = 0;
DWORD dwSizeOther = 0;
PMATCHINGFILE pMatchPrev = NULL;
PMATCHINGFILE pMatchTemp = NULL;
if (!SdbGetFileAttributes(strFileName, &pAttrInfo, &dwAttrCount)) {
ASSERT(FALSE);
return;
}
pMatch = GetMatchingFileFromAttributes(strFileName,
strRelativePath,
pAttrInfo);
if (pMatch == NULL) {
return;
}
pAttr = pMatch->attributeList.pAttribute;
//
// Get the size attribute, we need this so that we can sort files based on their size
//
GET_SIZE_ATTRIBUTE(pAttr, dwAttrCount, dwSize);
//
// Is the list empty ?
//
if (*ppMatchListHead == NULL) {
*ppMatchListHead = pMatch;
return;
}
//
// Is the first element in the list smaller than this one ?
//
pAttr = (*ppMatchListHead)->attributeList.pAttribute;
GET_SIZE_ATTRIBUTE(pAttr, dwAttrCount, dwSizeOther);
if (dwSize > dwSizeOther) {
pMatch->pNext = *ppMatchListHead;
*ppMatchListHead = pMatch;
return;
}
//
// Else insert at the proper position.
//
pMatchPrev = *ppMatchListHead;
pMatchTemp = pMatchPrev->pNext;
//
// Look at all the matching files in the list headed by *ppMatchListHead
// and add this matching file in its correct position so that the list is
// sorted in non-increasing order of size
//
while (pMatchTemp) {
pAttr = pMatchTemp->attributeList.pAttribute;
GET_SIZE_ATTRIBUTE(pAttr, dwAttrCount, dwSizeOther);
if (dwSize > dwSizeOther) {
//
// We have found the position where we need to insert.
//
break;
}
pMatchPrev = pMatchTemp;
pMatchTemp = pMatchTemp->pNext;
}
pMatch->pNext = pMatchTemp;
pMatchPrev->pNext = pMatch;
}
void
CShimWizard::WalkDirectory(
IN OUT PMATCHINGFILE* ppMatchListHead,
IN LPCTSTR pszDir,
IN int nDepth
)
/*++
CShimWizard::WalkDirectory
Desc: Walks the specified directory and gets matching files when using the AutoGenerate feature
Takes a pointer to pointer to a PMATCHING and pouplates it with the matching files found.
This function is called only by GrabMatchingInfo
Params:
IN OUT PMATCHINGFILE* ppMatchListHead: Pointer to head of a list of PMATCHINGFILE
IN LPCTSTR pszDir: The dir from where we should start
IN int nDepth The depth of sub-directories to look into
Return:
void
Notes: We restrict the depth till where we should recurse and so there will be no stack overflow
--*/
{
HANDLE hFile;
WIN32_FIND_DATA Data;
TCHAR szCurrentDir[MAX_PATH_BUFFSIZE + 1];
TCHAR szDirectory[MAX_PATH];
CSTRING szShortName;
CSTRING strFileName;
CSTRING strRelativePath;
int nFiles = 0;
DWORD dwResult = 0;
*szCurrentDir = *szDirectory = 0;
SafeCpyN(szDirectory, pszDir, ARRAYSIZE(szDirectory));
ADD_PATH_SEPARATOR(szDirectory, ARRAYSIZE(szDirectory));
//
// This is to allow recursion and only look into only 2 level subdirs.
//
if (nDepth >= 2) {
return;
}
szShortName = m_Entry.strFullpath;
szShortName.ShortFilename();
//
// Save the current directory
//
dwResult = GetCurrentDirectory(MAX_PATH, szCurrentDir);
if (dwResult == 0 || dwResult >= MAX_PATH) {
assert(FALSE);
Dbg(dlError, "WalkDirectory", "GetCurrentDirectory returned %d", dwResult);
return;
}
ADD_PATH_SEPARATOR(szCurrentDir, ARRAYSIZE(szCurrentDir));
//
// Set to the new directory
//
SetCurrentDirectory(szDirectory);
hFile = FindFirstFile(TEXT("*.*"), &Data);
if (INVALID_HANDLE_VALUE == hFile) {
SetCurrentDirectory(szCurrentDir);
return;
}
//
// Generate automated matching file information.
//
do {
if (0 == (Data.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))) {
//
// Hidden or system files are not included when we do a auto-generate matching info
//
if (FILE_ATTRIBUTE_DIRECTORY == (Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
//
// We found a directory
//
if (TEXT('.') != Data.cFileName[0]) {
//
// Let us get the matching files from this directory
//
WalkDirectory(ppMatchListHead, Data.cFileName, nDepth + 1);
}
} else {
//
// This is a file and we should now try to add it
//
++nFiles;
if (nFiles >= MAX_FILES) {
//
// We have found enough files, later we should take the largest MAX_AUTO_MATCH from these
//
break;
}
if (0 == (Data.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))) {
if (szDirectory[0] == TEXT('.')) {
strFileName.Sprintf(TEXT("%s%s"),
szCurrentDir,
Data.cFileName);
} else {
strFileName.Sprintf(TEXT("%s%s%s"),
szCurrentDir,
szDirectory,
Data.cFileName);
}
strRelativePath = strFileName;
strRelativePath.RelativeFile(g_pCurrentWizard->m_Entry.strFullpath);
//
// The main exe has been added before calling WalkDirectory()
//
if (strFileName != g_pCurrentWizard->m_Entry.strFullpath) {
//
// Add this to the list of matching files. Finally we will choose the
// largest MAX_AUTO_MATCH from them, to serve as the matching files for the present
// entry
//
AddToMatchingFilesList(ppMatchListHead,
strFileName,
strRelativePath);
}
}
}
}
} while (FindNextFile(hFile, &Data));
FindClose(hFile);
//
// Restore old directory
//
SetCurrentDirectory(szCurrentDir);
}
void
CShimWizard::GrabMatchingInfo(
IN HWND hdlg
)
/*++
CShimWizard::GrabMatchingInfo
Desc: Handles the pressinG of "Auto-Generate button. Removes all the existing matching files
for m_Entry
Params:
IN HWND hdlg: The matching file wizard page
Return:
void
--*/
{
PMATCHINGFILE pMatchTemp;
PMATCHINGFILE pMatchNext;
TCHAR* pchTemp;
TCHAR szCurrentDir[MAX_PATH];
TCHAR szDir[MAX_PATH]; // The directory of the file being fixed
PMATCHINGFILE pMatchingFileHead = NULL;
int iCount = 0;
DWORD dwResult = 0;
*szCurrentDir = *szDir = 0;
dwResult = GetCurrentDirectory(ARRAYSIZE(szCurrentDir), szCurrentDir);
if (dwResult == 0 || dwResult >= ARRAYSIZE(szCurrentDir)) {
assert(FALSE);
Dbg(dlError, "[CShimWizard::GrabMatchingInfo]: GetCurrentDirectory failed");
return;
}
//
// Get the complete path of the program file being fixed, so that
// we can generate relative file paths for the matching files
//
if (g_pCurrentWizard->CheckAndSetLongFilename(hdlg, IDS_GETCOMPLETEPATH) == FALSE) {
return;
}
//
// Remove any matching if present.
//
TreeDeleteAll(s_hwndTree);
g_pCurrentWizard->WipeEntry(TRUE, FALSE, FALSE, FALSE);
*szDir = 0;
SafeCpyN(szDir, (LPCTSTR)g_pCurrentWizard->m_Entry.strFullpath, ARRAYSIZE(szDir));
pchTemp = _tcsrchr(szDir, TEXT('\\'));
if (pchTemp) {
//
// Make sure that we get the trailing slash. Otherwise we migth have problems if we haev file
// names as c:\abc.exe
//
*pchTemp = 0;
} else {
//
// g_pCurrentWizard->m_Entry.strFullpath did not have a complete path!!
// We should not have come in this function in the first place
//
assert(FALSE);
Dbg(dlError, "[CShimWizard::GrabMatchingInfo]: Did not have a complete path for g_pCurrentWizard->m_Entry.strFullpath");
return;
}
SetCurrentDirectory(szDir);
//
// Generate automated matching file information. pMatchingFileHead will
// be the head of a linked list of all the matching files that we found
//
WalkDirectory(&pMatchingFileHead, TEXT("."), 0);
//
// Now, take the first MAX_AUTO_MATCH entries and discard the rest.
//
SendMessage(s_hwndTree, WM_SETREDRAW, FALSE, 0);
while (iCount < MAX_AUTO_MATCH && pMatchingFileHead) {
pMatchNext = pMatchingFileHead->pNext;
//
// NOTE: AddMatchingFileToTree() will change the pMatchingFileHead->pNext,
// when it adds it to the list of matching files for the entry !!!.
// So we have saved the pMatchingFileHead->pNext earlier.
//
AddMatchingFileToTree(s_hwndTree, pMatchingFileHead, TRUE);
++iCount;
pMatchingFileHead = pMatchNext;
}
SendMessage(s_hwndTree, WM_SETREDRAW, TRUE, 0);
//
// Remove the other ones.
//
while (pMatchingFileHead) {
pMatchTemp = pMatchingFileHead->pNext;
delete pMatchingFileHead;
pMatchingFileHead = pMatchTemp;
}
if (g_pCurrentWizard) {
//
// Add the file being fixed.
//
HandleAddMatchingFile(hdlg,
g_pCurrentWizard->m_Entry.strFullpath,
g_pCurrentWizard->m_Entry.strExeName);
}
SetCurrentDirectory(szCurrentDir);
}
void
AddModuleToListView(
IN PTSTR pszModuleName,
IN UINT uOption,
IN HWND hwndModuleList
)
/*++
AddModuleToListView
Desc: Adds the specified module to the list view.
Params:
IN PTSTR pszModuleName: Name of the module to be included or excluded
IN UINT uOption: Either INCLUDE or EXCLUDE
IN HWND hwndModuleList: Handle to the list view
Return;
void
--*/
{
LVITEM lvi;
int nIndex;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.lParam = uOption == INCLUDE ? 1 : 0;
lvi.pszText = uOption == INCLUDE ? GetString(IDS_INCLUDE) : GetString(IDS_EXCLUDE);
lvi.iItem = ListView_GetItemCount(hwndModuleList);
lvi.iSubItem = COLUMN_TYPE;
nIndex = ListView_InsertItem(hwndModuleList, &lvi);
ListView_SetItemText(hwndModuleList,
nIndex,
COLUMN_NAME,
pszModuleName);
}
void
HandleModuleListNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleModuleListNotification
Desc: Handle all the notifications we care about for the list in the params
dialog
Params:
IN HWND hdlg: The handle to the Params Dialog Box
IN LPARAM lParam: lParam that comes with WM_NOTIFY
Return:
void
--*/
{
LPNMHDR pnm = (LPNMHDR)lParam;
HWND hwndModuleList = GetDlgItem(hdlg, IDC_MOD_LIST);
switch (pnm->code) {
case NM_CLICK:
{
LVHITTESTINFO lvhti;
GetCursorPos(&lvhti.pt);
ScreenToClient(hwndModuleList, &lvhti.pt);
ListView_HitTest(hwndModuleList, &lvhti);
//
// If the user clicked on a list view item,
// enable the Remove button
//
if (lvhti.flags & LVHT_ONITEMLABEL) {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFROMLIST), TRUE);
} else {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFROMLIST), FALSE);
}
break;
}
default:
break;
}
}
INT_PTR CALLBACK
ParamsDlgProc(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
OptionsDlgProc
Description: Handles messages for the options dialog.
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
TCHAR szTitle[MAX_PATH];
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
static TYPE s_type = TYPE_UNKNOWN;
HWND hwndModuleList = GetDlgItem(hdlg, IDC_MOD_LIST);
switch (uMsg) {
case WM_INITDIALOG:
{
s_type = ConvertLparam2Type(lParam);
SetWindowLongPtr(hdlg, DWLP_USER, lParam);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFROMLIST), FALSE);
InsertColumnIntoListView(hwndModuleList, GetString(IDS_TYPE), COLUMN_TYPE, 30);
InsertColumnIntoListView(hwndModuleList, GetString(IDS_MODULENAME), COLUMN_NAME, 70);
ListView_SetExtendedListViewStyle(hwndModuleList, LVS_EX_LABELTIP |LVS_EX_FULLROWSELECT);
//
// Restrict the length of the command line to MAX_COMMAND_LINE chars
//
SendMessage(GetDlgItem(hdlg, IDC_SHIM_CMD_LINE),
EM_LIMITTEXT,
(WPARAM)MAX_COMMAND_LINE,
(LPARAM)0);
//
// Restrict the length of the module name to MAX_MODULE_NAME
//
SendMessage(GetDlgItem(hdlg, IDC_MOD_NAME),
EM_LIMITTEXT,
(WPARAM)MAX_MODULE_NAME,
(LPARAM)0);
if (s_type == FIX_LIST_SHIM) {
PSHIM_FIX_LIST psfl = (PSHIM_FIX_LIST)lParam;
if (psfl->pShimFix == NULL) {
assert(FALSE);
break;
}
StringCchPrintf(szTitle,
ARRAYSIZE(szTitle),
GetString(IDS_OPTIONS),
psfl->pShimFix->strName);
SetWindowText(hdlg, szTitle);
if (psfl->strCommandLine.Length()) {
SetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, psfl->strCommandLine);
}
CheckDlgButton(hdlg, IDC_INCLUDE, BST_CHECKED);
//
// Add any modules to the list view
//
PSTRLIST strlTemp = psfl->strlInExclude.m_pHead;
while (strlTemp) {
AddModuleToListView(strlTemp->szStr,
strlTemp->data,
hwndModuleList);
strlTemp = strlTemp->pNext;
}
} else {
PFLAG_FIX_LIST pffl = (PFLAG_FIX_LIST)lParam;
if (pffl->pFlagFix == NULL) {
assert(FALSE);
break;
}
StringCchPrintf(szTitle,
ARRAYSIZE(szTitle),
GetString(IDS_PRAMS_DLGCAPTION),
pffl->pFlagFix->strName);
SetWindowText(hdlg, szTitle);
if (pffl->strCommandLine.Length()) {
SetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, pffl->strCommandLine);
}
ENABLEWINDOW(GetDlgItem(hdlg, IDC_MOD_NAME), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_INCLUDE), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_EXCLUDE), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_ADDTOLIST), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFROMLIST), FALSE);
}
SendMessage(hdlg,
WM_COMMAND,
MAKEWPARAM(IDC_MOD_NAME, EN_CHANGE),
0);
break;
}
case WM_NOTIFY:
HandleModuleListNotification(hdlg, lParam);
break;
case WM_COMMAND:
switch (wCode) {
case IDC_MOD_NAME:
{
if (EN_CHANGE == HIWORD(wParam)) {
TCHAR szModName[MAX_MODULE_NAME + 1];
GetDlgItemText(hdlg, IDC_MOD_NAME, szModName, ARRAYSIZE(szModName));
if (CSTRING::Trim(szModName)) {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_ADDTOLIST), TRUE);
} else {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_ADDTOLIST), FALSE);
}
}
break;
}
case IDC_ADDTOLIST:
{
TCHAR szModName[MAX_MODULE_NAME + 1] = _T("");
UINT uInclude, uExclude;
GetDlgItemText(hdlg, IDC_MOD_NAME, szModName, ARRAYSIZE(szModName));
CSTRING::Trim(szModName);
uInclude = IsDlgButtonChecked(hdlg, IDC_INCLUDE);
uExclude = IsDlgButtonChecked(hdlg, IDC_EXCLUDE);
if ((BST_CHECKED == uInclude) || (BST_CHECKED == uExclude)) {
AddModuleToListView(szModName, uInclude, hwndModuleList);
SetDlgItemText(hdlg, IDC_MOD_NAME, _T(""));
SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
} else {
SetFocus(GetDlgItem(hdlg, IDC_INCLUDE));
}
break;
}
case IDC_REMOVEFROMLIST:
{
int nIndex;
nIndex = ListView_GetSelectionMark(hwndModuleList);
ListView_DeleteItem(hwndModuleList, nIndex);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_REMOVEFROMLIST), FALSE);
SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
break;
}
case IDOK:
{
//
// Now add the commandline
//
if (s_type == FIX_LIST_SHIM) {
PSHIM_FIX_LIST psfl = (PSHIM_FIX_LIST)GetWindowLongPtr(hdlg, DWLP_USER);
TCHAR szTemp[MAX_COMMAND_LINE + 1];
psfl->strCommandLine.Release();
psfl->strlInExclude.DeleteAll();
*szTemp = 0;
GetDlgItemText(hdlg,
IDC_SHIM_CMD_LINE,
szTemp,
ARRAYSIZE(szTemp));
if (CSTRING::Trim(szTemp)) {
psfl->strCommandLine = szTemp;
}
//
// Add the InExclude
//
int iTotal = ListView_GetItemCount(hwndModuleList);
for (int iIndex = 0; iIndex < iTotal; ++iIndex) {
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
if (!ListView_GetItem(hwndModuleList, &lvi)) {
assert(FALSE);
continue;
}
ListView_GetItemText(hwndModuleList, iIndex, 1, szTemp, ARRAYSIZE(szTemp));
if (CSTRING::Trim(szTemp)) {
psfl->strlInExclude.AddString(szTemp, lvi.lParam);
}
}
} else {
PFLAG_FIX_LIST pffl = (PFLAG_FIX_LIST)GetWindowLongPtr(hdlg, DWLP_USER);
TCHAR szTemp[MAX_COMMAND_LINE + 1];
pffl->strCommandLine.Release();
*szTemp = 0;
GetDlgItemText(hdlg,
IDC_SHIM_CMD_LINE,
szTemp,
ARRAYSIZE(szTemp));
if (CSTRING::Trim(szTemp)) {
pffl->strCommandLine = szTemp;
}
}
EndDialog(hdlg, TRUE);
break;
}
case IDCANCEL:
EndDialog(hdlg, FALSE);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void
ShowParams(
IN HWND hDlg,
IN HWND hwndList
)
/*++
ShowParams
Desc: Pops up the params dialog
Params:
IN HWND hDlg: The dialog box that contains the list box that shows the params
IN HWND hwndList: The list box that shows the params
Notes: The same function is called for both configuring the params in the shim wizard and
the custom layer proc
We can show and customize params only in the expert mode
Return:
void
--*/
{
if (!g_bExpert) {
return;
}
int iSelected = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
if (iSelected == -1) {
return;
}
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iItem = iSelected;
lvi.iSubItem = 0;
if (!ListView_GetItem(hwndList, &lvi)) {
return;
}
if (lvi.lParam == NULL) {
assert(FALSE);
return;
}
TYPE type = ((PDS_TYPE)lvi.lParam)->type;
//
// We want to process this only for shims and flags.
//
PSHIM_FIX_LIST psfl = NULL;
PFLAG_FIX_LIST pffl = NULL;
if (type == FIX_LIST_SHIM) {
psfl = (PSHIM_FIX_LIST)lvi.lParam;
} else if (type == FIX_LIST_FLAG) {
pffl = (PFLAG_FIX_LIST)lvi.lParam;
} else {
assert(FALSE);
return;
}
if (DialogBoxParam(g_hInstance,
MAKEINTRESOURCE(IDD_OPTIONS),
hDlg,
ParamsDlgProc,
(LPARAM)lvi.lParam)) {
if (type == FIX_LIST_SHIM) {
ListView_SetItemText(hwndList, iSelected, 1, psfl->strCommandLine);
if (psfl->strlInExclude.IsEmpty()) {
ListView_SetItemText(hwndList, iSelected, 2, GetString(IDS_NO));
} else {
ListView_SetItemText(hwndList, iSelected, 2, GetString(IDS_YES));
}
} else {
ListView_SetItemText(hwndList, iSelected, 1, pffl->strCommandLine);
ListView_SetItemText(hwndList, iSelected, 2, GetString(IDS_NO));
}
}
}
void
HandleShowAllAtrr(
IN HWND hdlg
)
/*++
HandleShowAllAtrr
Desc: Shows all the attributes of all the matching files.
When we save a database, only the attributes that are in selected are in the XML
So we might need to see all the other attributes if we wish to add some new
attributes
Params:
IN HWND hdlg: The matching file wizard page
Return:
void
--*/
{
TCHAR szDir[MAX_PATH];
PMATCHINGFILE pMatchTemp;
HWND hwndTree = GetDlgItem(hdlg, IDC_FILELIST);
PATTRINFO pAttrInfo;
PTCHAR pchTemp = NULL;
//
// Get the long file name of the file being fixed.
//
if (g_pCurrentWizard->CheckAndSetLongFilename(hdlg, IDS_GETCOMPLETEPATH) == FALSE) {
//
// User pressed cancel there or there was some error
//
return;
}
//
// Get the directory of the exe being fixed
//
*szDir = 0;
SafeCpyN(szDir, g_pCurrentWizard->m_Entry.strFullpath, ARRAYSIZE(szDir));
pchTemp = _tcsrchr(szDir, TEXT('\\'));
if (pchTemp && pchTemp < (szDir + ARRAYSIZE(szDir) - 1)) {
*(++pchTemp) = 0;
}
TreeDeleteAll(hwndTree);
pMatchTemp = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
//
// For all the matching files that are associated with the entry,
// get their complete attributes
//
while (pMatchTemp) {
CSTRING strFullName = szDir;
//
// Get the full path of the matching file
//
strFullName.Strcat(pMatchTemp->strMatchName);
if (pMatchTemp->strMatchName == TEXT("*")) {
pMatchTemp->strFullName = g_pCurrentWizard->m_Entry.strFullpath;
} else {
pMatchTemp->strFullName = strFullName;
}
if (SdbGetFileAttributes(pMatchTemp->strFullName, &pAttrInfo, NULL)) {
//
// SdbGetFileAttributes can fail if the file does not exist on the target
// machine
//
pMatchTemp->attributeList = pAttrInfo;
}
pMatchTemp = pMatchTemp->pNext;
}
//
// Refresh the list now.
//
SendMessage(hdlg, WM_USER_MATCHINGTREE_REFRESH, 0, 0);
}
void
SetMask(
IN HWND hwndTree
)
/*++
SetMask
Desc: Checks which attributes are selected in the matching files tree and sets the
dwMask of PMATCHINGFILE accordingly
Params:
IN HWND hwndTree: The matching file tree
--*/
{
LPARAM lParam;
HTREEITEM hItemMatch = TreeView_GetRoot(hwndTree), hItemAttr;
PMATCHINGFILE pMatch = NULL;
while (hItemMatch) {
TVITEM Item;
Item.mask = TVIF_PARAM;
Item.hItem = hItemMatch;
if (!TreeView_GetItem(hwndTree, &Item)) {
assert(FALSE);
goto Next_Match;
}
lParam = Item.lParam;
pMatch = (PMATCHINGFILE)lParam;
pMatch->dwMask = 0;
//
// Now Traverse this tree and then set the mask properly
//
hItemAttr = TreeView_GetChild(hwndTree, hItemMatch);
while (hItemAttr) {
Item.mask = TVIF_PARAM;
Item.hItem = hItemAttr;
if (!TreeView_GetItem(hwndTree, &Item)) {
assert(FALSE);
goto Next_Attr;
}
lParam = Item.lParam;
int iPos = TagToIndex((TAG)lParam);
if (iPos != -1 && TreeView_GetCheckState(hwndTree, hItemAttr) == 1) {
pMatch->dwMask |= 1 << (iPos + 1);
}
Next_Attr:
hItemAttr = TreeView_GetNextSibling(hwndTree, hItemAttr);
}
Next_Match:
hItemMatch = TreeView_GetNextSibling(hwndTree, hItemMatch);
}
}
BOOL
HandleLayersNext(
IN HWND hdlg,
IN BOOL bCheckAndAddLua,
OUT CSTRINGLIST* pstrlAddedLuaShims //(NULL)
)
/*++
HandleLayersNext
Desc: Handles the pressing of Next/Finish button for the layers wizard page
Params:
IN HWND hdlg: The layers wizard page
IN BOOL bCheckAndAddLua: Should we check if the user has selected LUA layer and add
the shims if he has.
OUT CSTRINGLIST* pstrlShimsAdded(NULL): This is passed to AddLuaShimsInEntry. See the description
in that routine to see how this is used
Return:
FALSE: If there is some error, or the entry contains no shim, flag or layer
TRUE: Otherwise
--*/
{
g_bIsLUALayerSelected = FALSE;
g_pCurrentWizard->WipeEntry(FALSE, FALSE, TRUE, FALSE);
HWND hwndRadio = GetDlgItem(hdlg, IDC_RADIO_NONE);
//
// Get the Selected Layers
//
if (SendMessage(hwndRadio, BM_GETCHECK, 0, 0) != BST_CHECKED) {
PLAYER_FIX_LIST plfl = new LAYER_FIX_LIST;
if (plfl == NULL) {
MEM_ERR;
return FALSE;
}
hwndRadio = GetDlgItem(hdlg, IDC_RADIO_95);
if (SendMessage(hwndRadio, BM_GETCHECK, 0, 0) == BST_CHECKED) {
plfl->pLayerFix = (PLAYER_FIX)FindFix(s_arszOsLayers[0], FIX_LAYER);
goto LAYER_RADIO_DONE;
}
hwndRadio = GetDlgItem(hdlg, IDC_RADIO_NT);
if (SendMessage(hwndRadio, BM_GETCHECK, 0, 0) == BST_CHECKED) {
plfl->pLayerFix = (PLAYER_FIX)FindFix(s_arszOsLayers[1], FIX_LAYER);
goto LAYER_RADIO_DONE;
}
hwndRadio = GetDlgItem(hdlg, IDC_RADIO_98);
if (SendMessage(hwndRadio, BM_GETCHECK, 0, 0) == BST_CHECKED) {
plfl->pLayerFix = (PLAYER_FIX)FindFix(s_arszOsLayers[2], FIX_LAYER);
goto LAYER_RADIO_DONE;
}
hwndRadio = GetDlgItem(hdlg, IDC_RADIO_2K);
if (SendMessage(hwndRadio, BM_GETCHECK, 0, 0) == BST_CHECKED) {
plfl->pLayerFix = (PLAYER_FIX)FindFix(s_arszOsLayers[3], FIX_LAYER);
goto LAYER_RADIO_DONE;
}
LAYER_RADIO_DONE:
//
// Add the selected Layer
//
g_pCurrentWizard->m_Entry.pFirstLayer = plfl;
}
//
// Now add the layers selected in the List View
//
UINT uIndex;
UINT uLayerCount = ListView_GetItemCount(s_hwndLayerList);
PLAYER_FIX_LIST plflInList = NULL;
for (uIndex = 0 ; uIndex < uLayerCount; ++uIndex) {
LVITEM Item;
Item.mask = LVIF_PARAM;
Item.iItem = uIndex;
Item.iSubItem = 0;
if (!ListView_GetItem(s_hwndLayerList, &Item)) {
assert(FALSE);
continue;
}
if (ListView_GetCheckState(s_hwndLayerList, uIndex)) {
plflInList = (PLAYER_FIX_LIST)Item.lParam;
assert(plflInList);
//
// If the layer is LUA, we need to add the shims individually because
// when we pass a PDBENTRY around, we don't want to change the PLUADATA
// in the shim of the layer (which will be global).
//
if (plflInList->pLayerFix->strName == TEXT("LUA")) {
g_bIsLUALayerSelected = TRUE;
} else {
PLAYER_FIX_LIST plfl = new LAYER_FIX_LIST;
if (plfl == NULL) {
MEM_ERR;
return FALSE;
}
plfl->pLayerFix = plflInList->pLayerFix;
plfl->pNext = g_pCurrentWizard->m_Entry.pFirstLayer;
g_pCurrentWizard->m_Entry.pFirstLayer = plfl;
}
}
}
//
// If have seleted LUA layer and we have pressed the Finish button, that means
// that we are in editing mode and we want to add LUA layer and close the dialog
// In this case we must check if the LUA shims exist and if not then we must add
// the lua shims ourselves
//
if (g_bIsLUALayerSelected && bCheckAndAddLua) {
AddLuaShimsInEntry(&g_pCurrentWizard->m_Entry, pstrlAddedLuaShims);
}
PDBENTRY pEntry = &g_pCurrentWizard->m_Entry;
if (pEntry && pEntry->pFirstFlag || pEntry->pFirstLayer || pEntry->pFirstShim) {
//
// The entry contains some fix or layer
//
return TRUE;
}
return FALSE;
}
BOOL
HandleShimsNext(
IN HWND hdlg
)
/*++
HandleShimsNext
Desc: Handles the pressing of Next/Finish button for the shims wizard page
Params:
IN HWND hdlg: The shims wizard page
Return:
FALSE: If there is some error, or the entry contains no shim, flag or layer
TRUE: Otherwise
--*/
{
PLAYER_FIX_LIST plfl = NULL;
HWND hwndShimList = NULL;
UINT uShimCount = 0;
g_pCurrentWizard->WipeEntry(FALSE, TRUE, FALSE, TRUE);
hwndShimList = GetDlgItem(hdlg, IDC_SHIMLIST);
uShimCount = ListView_GetItemCount(hwndShimList);
for (UINT uIndex = 0 ; uIndex < uShimCount; ++uIndex) {
LVITEM Item;
Item.lParam = 0;
Item.mask = LVIF_PARAM;
Item.iItem = uIndex;
Item.iSubItem = 0;
if (!ListView_GetItem(hwndShimList, &Item)) {
assert(FALSE);
}
if (ListView_GetCheckState(hwndShimList, uIndex)) {
TYPE type = ((PDS_TYPE)Item.lParam)->type;
if (type == FIX_LIST_SHIM) {
PSHIM_FIX_LIST psfl= (PSHIM_FIX_LIST)Item.lParam;
assert(psfl);
//
// Check if this is already part of some layer.
//
plfl = g_pCurrentWizard->m_Entry.pFirstLayer;
while (plfl) {
if (IsShimInlayer(plfl->pLayerFix, psfl->pShimFix, &psfl->strCommandLine, &psfl->strlInExclude)) {
break;
}
plfl = plfl->pNext;
}
if (plfl) {
//
// This shim is a part of some mode
//
continue;
}
PSHIM_FIX_LIST psflNew = new SHIM_FIX_LIST;
if (psflNew == NULL) {
MEM_ERR;
return FALSE;
}
psflNew->pShimFix = psfl->pShimFix;
psflNew->strCommandLine = psfl->strCommandLine;
psflNew->strlInExclude = psfl->strlInExclude;
if (psfl->pLuaData) {
psflNew->pLuaData = new LUADATA;
if (psflNew->pLuaData) {
psflNew->pLuaData->Copy(psfl->pLuaData);
}
}
psflNew->pNext = g_pCurrentWizard->m_Entry.pFirstShim;
g_pCurrentWizard->m_Entry.pFirstShim = psflNew;
} else if (type == FIX_LIST_FLAG) {
PFLAG_FIX_LIST pffl = (PFLAG_FIX_LIST)Item.lParam;
assert(pffl);
plfl = g_pCurrentWizard->m_Entry.pFirstLayer;
while (plfl) {
if (IsFlagInlayer(plfl->pLayerFix, pffl->pFlagFix, &pffl->strCommandLine)) {
break;
}
plfl = plfl->pNext;
}
if (plfl) {
//
// This flag is a part of some layer
//
continue;
}
PFLAG_FIX_LIST pfflNew = new FLAG_FIX_LIST;
if (pfflNew == NULL) {
MEM_ERR;
return FALSE;
}
pfflNew->pFlagFix = pffl->pFlagFix;
pfflNew->strCommandLine = pffl->strCommandLine;
pfflNew->pNext = g_pCurrentWizard->m_Entry.pFirstFlag;
g_pCurrentWizard->m_Entry.pFirstFlag = pfflNew;
}
}
}
PDBENTRY pEntry = &g_pCurrentWizard->m_Entry;
if (pEntry->pFirstFlag || pEntry->pFirstLayer || pEntry->pFirstShim) {
return TRUE;
}
return FALSE;
}
void
ShowSelected(
IN HWND hdlg
)
/*++
ShowSelected
Desc: Show only the checked shims/flags. Deletes the shims/flags that are not checked.
This function is called from the SelectShims(...)
Params:
IN HWND hdlg: The shims wizard page
--*/
{
HWND hwndShimList = GetDlgItem(hdlg, IDC_SHIMLIST);
UINT uShimCount = ListView_GetItemCount(hwndShimList);
INT uCheckedCount = 0;
LVITEM lvi = {0};
uCheckedCount = uShimCount;
SendMessage(hwndShimList, WM_SETREDRAW, FALSE, 0);
for (INT iIndex = uShimCount - 1 ; iIndex >= 0 ; --iIndex) {
LVITEM Item;
Item.lParam = 0;
Item.mask = LVIF_PARAM;
Item.iItem = iIndex;
Item.iSubItem = 0;
if (!ListView_GetItem(hwndShimList, &Item)) {
assert(FALSE);
}
if (!ListView_GetCheckState(hwndShimList, iIndex)) {
TYPE type = ((PDS_TYPE)Item.lParam)->type;
if (type == FIX_LIST_SHIM) {
DeleteShimFixList((PSHIM_FIX_LIST)Item.lParam);
} else if (type == FIX_LIST_FLAG) {
DeleteFlagFixList((PFLAG_FIX_LIST)Item.lParam);
}
ListView_DeleteItem(hwndShimList, iIndex);
--uCheckedCount;
}
}
SendMessage(hwndShimList, WM_SETREDRAW, TRUE, 0);
UpdateWindow(hwndShimList);
s_bAllShown = FALSE;
SetDlgItemText(hdlg, IDC_SHOW, GetString(IDS_SHOW_BUTTON_ALL));
if (ListView_GetSelectedCount(hwndShimList) > 0) {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), TRUE);
} else {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), FALSE);
}
//
// Select the first item.
//
if (uCheckedCount) {
//
// If the first shim is part of a layer, then the parms button will
// get disabled in the handler for LVN_ITEMCHANGED.
//
ListView_SetSelectionMark(hwndShimList, 0);
ListView_SetItemState(hwndShimList,
0,
LVIS_FOCUSED | LVIS_SELECTED ,
LVIS_FOCUSED | LVIS_SELECTED);
lvi.mask = LVIF_IMAGE;
lvi.iItem = 0;
lvi.iSubItem = 0;
//
// The above does not work always. We will disable the param button if the shim is part of
// a layer
//
if (ListView_GetItem(hwndShimList, &lvi)) {
if (lvi.iImage == IMAGE_SHIM) {
//
// This shim is not part of a layer
//
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), TRUE);
} else {
//
// This shim is part of a layer, we must now allow to change paramters for this
//
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), FALSE);
}
} else {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), FALSE);
}
} else {
//
// There are no shims, better disable the params button.
//
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), FALSE);
}
}
void
ShowItems(
IN HWND hdlg
)
/*++
ShowItems
Desc: Populates the fixes list view in the shims wizard page
Params:
IN HWND hdlg: The shims wizard page
Return:
void
--*/
{
g_bNowTest = FALSE;
HWND hwndList = GetDlgItem(hdlg, IDC_SHIMLIST);
PSHIM_FIX psf = GlobalDataBase.pShimFixes;
SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// Read the shims.
//
LVFINDINFO lvfind;
LVITEM lvi;
UINT uCount = 0;
while (psf) {
if (psf->bGeneral || g_bExpert) {
PSHIM_FIX_LIST psflAsInLayer = NULL;
BOOL bShimInLayer = ShimPresentInLayersOfEntry(&g_pCurrentWizard->m_Entry,
psf,
&psflAsInLayer);
BOOL bLUAShimInLayer =
(g_bIsLUALayerSelected &&
(psf->strName == TEXT("LUARedirectFS") ||
psf->strName == TEXT("LUARedirectReg")));
//
// Check if the shim is already present in the list.
//
lvfind.flags = LVFI_STRING;
lvfind.psz = psf->strName.pszString;
INT iIndex = ListView_FindItem(hwndList, -1, &lvfind);
if (-1 == iIndex) {
PSHIM_FIX_LIST pShimFixList = new SHIM_FIX_LIST;
if (pShimFixList == NULL) {
MEM_ERR;
break;
}
//
// This will contain a ptr to the shimlist, if there is a layer
// that has this shim and the layer has been applied to the entry
//
pShimFixList->pShimFix = psf;
//
// If this is present in some selected layer, set the param for this just as they are in the layer
//
if (psflAsInLayer) {
pShimFixList->strCommandLine= psflAsInLayer->strCommandLine;
pShimFixList->strlInExclude = psflAsInLayer->strlInExclude;
}
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvi.pszText = psf->strName;
lvi.iItem = uCount;
lvi.iSubItem = 0;
lvi.iImage = (bShimInLayer || bLUAShimInLayer) ? IMAGE_LAYERS : IMAGE_SHIM;
lvi.lParam = (LPARAM)pShimFixList;
iIndex = ListView_InsertItem(hwndList, &lvi);
ListView_SetCheckState(hwndList,
iIndex,
bShimInLayer || bLUAShimInLayer);
//
// If we are in edit mode, then select the used ones and set the params appropriately
//
PSHIM_FIX_LIST psflFound = NULL; // the pshimfix list found in the entry. This is used for populating the previous commandline etc.
if (g_pCurrentWizard->m_bEditing && ShimPresent(psf, &g_pCurrentWizard->m_Entry, &psflFound)) {
ListView_SetCheckState(hwndList, iIndex, TRUE);
//
// Add the commandline for this shim
//
if (psflFound && psflFound->strCommandLine.Length() > 0) {
pShimFixList->strCommandLine = psflFound->strCommandLine;
}
//
// Add the include exclude for this shim
//
if (psflFound && !psflFound->strlInExclude.IsEmpty()) {
pShimFixList->strlInExclude = psflFound->strlInExclude;
}
//
// Add the LUA data for this shim
//
if (psflFound && psflFound->pLuaData) {
pShimFixList->pLuaData = new LUADATA;
if (pShimFixList->pLuaData) {
pShimFixList->pLuaData->Copy(psflFound->pLuaData);
} else {
MEM_ERR;
}
}
}
if (g_bExpert) {
ListView_SetItemText(hwndList, iIndex, 1, pShimFixList->strCommandLine);
CSTRING strModulePresent;
strModulePresent= pShimFixList->strlInExclude.IsEmpty() ? GetString(IDS_NO) : GetString(IDS_YES);
ListView_SetItemText(hwndList, iIndex, 2, strModulePresent);
}
} else {
PSHIM_FIX_LIST pShimFixList = NULL;
//
// We might need to change the state of some of the existing shims.
//
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_IMAGE | LVIF_PARAM;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
if (!ListView_GetItem(hwndList, &lvi)) {
assert(FALSE);
return;
}
pShimFixList = (PSHIM_FIX_LIST)lvi.lParam;
if (pShimFixList == NULL) {
assert(FALSE);
return;
}
INT iPrevImage = lvi.iImage, iNewImage = 0;
iNewImage = lvi.iImage = (bShimInLayer || bLUAShimInLayer) ? IMAGE_LAYERS : IMAGE_SHIM;
ListView_SetItem(hwndList, &lvi);
//
// If this is present in some selected layer, set the param for this just as they are in the layer
//
if (bShimInLayer) {
if (psflAsInLayer) {
pShimFixList->strCommandLine= psflAsInLayer->strCommandLine;
pShimFixList->strlInExclude = psflAsInLayer->strlInExclude;
} else {
assert(FALSE);
}
}
if (iPrevImage != iNewImage) {
ListView_SetCheckState(hwndList,
iIndex,
bShimInLayer || bLUAShimInLayer);
//
// if this shim was earlier a part of layer, we must change the param. Remove All
//
if (iPrevImage != IMAGE_SHIM) {
pShimFixList->strCommandLine = TEXT("");
pShimFixList->strlInExclude.DeleteAll();
}
}
//
// Must now refresh the params in the list box.
//
if (g_bExpert) {
ListView_SetItemText(hwndList, iIndex, 1, pShimFixList->strCommandLine);
CSTRING strModulePresent;
strModulePresent= pShimFixList->strlInExclude.IsEmpty() ? GetString(IDS_NO) : GetString(IDS_YES);
ListView_SetItemText(hwndList, iIndex, 2, strModulePresent);
}
}
++uCount;
}
psf = psf->pNext;
}
//
// Now read in the flags as well.
//
PFLAG_FIX pff = GlobalDataBase.pFlagFixes;
while (pff) {
if (pff->bGeneral || g_bExpert) {
PFLAG_FIX_LIST pfflAsInLayer = NULL;
BOOL bFlagInLayer = FlagPresentInLayersOfEntry(&g_pCurrentWizard->m_Entry,
pff,
&pfflAsInLayer);
//
// Check if the flag is already present in the list.
//
lvfind.flags = LVFI_STRING;
lvfind.psz = pff->strName.pszString;
INT iIndex = ListView_FindItem(hwndList, -1, &lvfind);
if (-1 == iIndex) {
PFLAG_FIX_LIST pFlagFixList = new FLAG_FIX_LIST;
if (pFlagFixList == NULL) {
MEM_ERR;
break;
}
pFlagFixList->pFlagFix = pff;
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvi.pszText = pff->strName;
lvi.iItem = uCount;
lvi.iSubItem = 0;
lvi.iImage = bFlagInLayer ? IMAGE_LAYERS : IMAGE_SHIM;
lvi.lParam = (LPARAM)pFlagFixList;
INT iIndexInserted = ListView_InsertItem(hwndList, &lvi);
ListView_SetCheckState(hwndList, iIndexInserted, bFlagInLayer);
ListView_SetItemText(hwndList, iIndexInserted, 2, GetString(IDS_NO));
//
// If we are in edit mode, then select the used ones and set the params appropritely
//
//
// the pflagfix list found in the entry. This is used for populating the previous commandline etc.
//
PFLAG_FIX_LIST pfflFound = NULL;
if (g_pCurrentWizard->m_bEditing && FlagPresent(pff,
&g_pCurrentWizard->m_Entry,
&pfflFound)) {
ListView_SetCheckState(hwndList, iIndexInserted, TRUE);
//
// Add the commandline for this flag
//
if (pfflFound && pfflFound->strCommandLine.Length() > 0) {
pFlagFixList->strCommandLine = pfflFound->strCommandLine;
}
//
// Refresh the command-line for this flag in the list view
//
if (g_bExpert) {
ListView_SetItemText(hwndList, iIndexInserted, 1, pFlagFixList->strCommandLine);
ListView_SetItemText(hwndList, iIndexInserted, 2, GetString(IDS_NO));
}
}
} else {
//
// We might need to change the state of some of the existing flags.
//
PFLAG_FIX_LIST pFlagFixList = NULL;
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_IMAGE | LVIF_PARAM;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
if (!ListView_GetItem(hwndList, &lvi)) {
assert(FALSE);
return;
}
pFlagFixList = (PFLAG_FIX_LIST)lvi.lParam;
if (pFlagFixList == NULL) {
assert(FALSE);
return;
}
INT iPrevImage = lvi.iImage, iNewImage = 0;
iNewImage = lvi.iImage = (bFlagInLayer) ? IMAGE_LAYERS : IMAGE_SHIM;
ListView_SetItem(hwndList, &lvi);
//
// Set the commandline for this flag appropriately
//
if (bFlagInLayer) {
pFlagFixList->strCommandLine= pfflAsInLayer->strCommandLine;
}
if (iPrevImage != iNewImage) {
ListView_SetCheckState(hwndList, iIndex, bFlagInLayer);
//
// if this flag was earlier a part of layer, we must change the param. Remove it.
//
if (iPrevImage != IMAGE_SHIM) {
pFlagFixList->strCommandLine = TEXT("");
}
}
//
// Refresh the command-line for this flag in the list view
//
if (g_bExpert) {
ListView_SetItemText(hwndList, iIndex, 1, pFlagFixList->strCommandLine);
ListView_SetItemText(hwndList, iIndex, 2, GetString(IDS_NO));
}
}
++uCount;
}
pff = pff->pNext;
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
UpdateWindow(hwndList);
s_bAllShown = TRUE;
SetDlgItemText(hdlg, IDC_SHOW, GetString(IDS_SHOW_BUTTON_SEL));
if (ListView_GetSelectionMark(hwndList) != -1) {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), TRUE);
} else {
ENABLEWINDOW(GetDlgItem(hdlg, IDC_PARAMS), FALSE);
}
//
// Set the column width of the last column in the list view appropriately to
// cover the width of the list view
// Assumption: The list view has only one column or 3 cloumns depending upon
// whether we are in expert mode or not.
//
if (g_bExpert) {
ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
} else {
ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
}
g_bNowTest = TRUE;
}
BOOL
ShimPresentInLayersOfEntry(
IN PDBENTRY pEntry,
IN PSHIM_FIX psf,
OUT PSHIM_FIX_LIST* ppsfList, // (NULL)
OUT PLAYER_FIX_LIST* pplfList // (NULL)
)
/*++
ShimPresentInLayersOfEntry
Desc: Checks if the shim psf occurs in any any of the layers that have
been applied to pEntry.
Params:
IN PDBENTRY pEntry: The entry for which the check has to be made
IN PSHIM_FIX psf: The shim to check for
OUT PSHIM_FIX_LIST* ppsfList (NULL): Pointer to the shim fix list in the layer
So that we might get the params for this shim in the layer
OUT PLAYER_FIX_LIST* pplfList (NULL): Pointer to the layer fix list
--*/
{
PLAYER_FIX_LIST plfl = pEntry->pFirstLayer;
PLAYER_FIX plf;
PSHIM_FIX_LIST psfl;
while (plfl) {
plf = plfl->pLayerFix;
psfl = plf->pShimFixList;
while (psfl) {
if (psfl->pShimFix == psf) {
if (ppsfList) {
*ppsfList = psfl;
}
if (pplfList) {
*pplfList = plfl;
}
return TRUE;
}
psfl = psfl->pNext;
}
plfl = plfl->pNext;
}
return FALSE;
}
BOOL
FlagPresentInLayersOfEntry(
IN PDBENTRY pEntry,
IN PFLAG_FIX pff,
OUT PFLAG_FIX_LIST* ppffList, // (NULL)
OUT PLAYER_FIX_LIST* pplfl // (NULL)
)
/*++
FlagPresentInLayersOfEntry
Desc: Checks if the flag psf occurs in any any of the layers that have
been applied to pEntry.
Params:
IN PDBENTRY pEntry: The entry for which the check has to be made
IN PFLAG_FIX pff: The flag to check for
OUT PFLAG_FIX_LIST* ppffList (NULL): Pointer to the flag fix list in the layer
So that we might get the params for this flag in the layer
OUT PLAYER_FIX_LIST* pplfList (NULL): Pointer to the layer fix list
--*/
{
PLAYER_FIX_LIST plfl = pEntry->pFirstLayer;
PLAYER_FIX plf;
PFLAG_FIX_LIST pffl;
while (plfl) {
plf = plfl->pLayerFix;
pffl = plf->pFlagFixList;
while (pffl) {
if (pffl->pFlagFix == pff) {
if (ppffList) {
*ppffList = pffl;
}
if (pplfl) {
*pplfl = plfl;
}
return TRUE;
}
pffl = pffl->pNext;
}
plfl = plfl->pNext;
}
return FALSE;
}
void
CheckLayers(
IN HWND hDlg
)
/*++
CheckLayers
Desc: Deselects all the radio buttons and then checks the one that is appropriate.
For the layers in the list view, only checks the layers that have been
applied for the present entry.
Params:
IN HWND hDlg: The layer wizard page
Return:
void
--*/
{
INT id = -1;
LVFINDINFO lvfind;
HWND hwndList = GetDlgItem(hDlg, IDC_LAYERLIST);
PLAYER_FIX_LIST plfl = g_pCurrentWizard->m_Entry.pFirstLayer;
INT iTotal = ListView_GetItemCount(hwndList);
INT iIndex = 0;
CheckDlgButton(hDlg, IDC_RADIO_95, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_NT, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_98, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_2K, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_NONE, BST_UNCHECKED);
for (iIndex = 0; iIndex < iTotal; ++ iIndex) {
ListView_SetCheckState(hwndList, iIndex, FALSE);
}
ZeroMemory(&lvfind, sizeof(lvfind));
lvfind.flags = LVFI_STRING;
id = -1;
//
// Take care of the LUA layer first.
//
if (g_bIsLUALayerSelected) {
lvfind.psz = TEXT("LUA");
if ((iIndex = ListView_FindItem(hwndList, -1, &lvfind)) != -1) {
ListView_SetCheckState(hwndList, iIndex, TRUE);
}
}
while (plfl) {
assert(plfl->pLayerFix);
if (id == -1) {
if (lstrcmpi(plfl->pLayerFix->strName, s_arszOsLayers[0]) == 0) {
id = IDC_RADIO_95;
} else if (lstrcmpi(plfl->pLayerFix->strName, s_arszOsLayers[1]) == 0) {
id = IDC_RADIO_NT;
} else if (lstrcmpi(plfl->pLayerFix->strName, s_arszOsLayers[2]) == 0) {
id = IDC_RADIO_98;
} else if (lstrcmpi(plfl->pLayerFix->strName, s_arszOsLayers[3]) == 0) {
id = IDC_RADIO_2K;
}
if (id != -1) {
CheckDlgButton(hDlg, id, BST_CHECKED);
goto Next_loop;
}
}
lvfind.flags = LVFI_STRING;
lvfind.psz = plfl->pLayerFix->strName;
iIndex = ListView_FindItem(hwndList, -1, &lvfind);
if (iIndex != -1) {
ListView_SetCheckState(hwndList, iIndex, TRUE);
}
Next_loop:
plfl = plfl->pNext;
}
if (id == -1) {
//
// None of the OS layers were selected
//
CheckDlgButton(hDlg, IDC_RADIO_NONE, BST_CHECKED);
}
}
BOOL
HandleLayerListNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleLayerListNotification
Params:
IN HWND hdlg: The layers wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Desc: Handles the notification messages for the layer list.
Return: TRUE: If the message was handled
FALSE: Otherwise
--*/
{
HWND hwndList = GetDlgItem(hdlg, IDC_LAYERLIST);
LPNMHDR pnm = (LPNMHDR)lParam;
switch (pnm->code) {
case NM_CLICK:
{
LVHITTESTINFO lvhti;
GetCursorPos(&lvhti.pt);
ScreenToClient(s_hwndLayerList, &lvhti.pt);
ListView_HitTest(s_hwndLayerList, &lvhti);
//
// If the check box state has changed toggle the selection
//
if (lvhti.flags & LVHT_ONITEMSTATEICON) {
INT iPos = ListView_GetSelectionMark(s_hwndLayerList);
if (iPos != -1) {
//
// De-select it.
//
ListView_SetItemState(s_hwndLayerList,
iPos,
0,
LVIS_FOCUSED | LVIS_SELECTED);
}
}
ListView_SetItemState(s_hwndLayerList,
lvhti.iItem,
LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED);
ListView_SetSelectionMark(s_hwndLayerList, lvhti.iItem);
break;
}
default: return FALSE;
}
return TRUE;
}
BOOL
HandleShimDeselect(
IN HWND hdlg,
IN INT iIndex
)
/*++
HandleShimDeselect
Desc: This function prompts the user if he is unchecking a shim that is part of
some mode. If the user selects OK then we remove all the layers that
have this shim and for all the shims in all those layes, we change their icons
Params:
IN HWND hdlg: The shims wizard page
IN INT iIndex: The index of the list view item where all the action is
Return: TRUE, if the user agrees to remove the previous layer.
FALSE, otherwise
--*/
{
HWND hwndList = GetDlgItem(hdlg, IDC_SHIMLIST);
LVITEM lvi;
PSHIM_FIX psf = NULL;
PSHIM_FIX_LIST psfl = NULL;
PFLAG_FIX_LIST pffl = NULL;
PLAYER_FIX_LIST plfl = NULL;
TYPE type;
BOOL bFoundInLayer = FALSE;
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM | LVIF_IMAGE;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
if (ListView_GetItem(hwndList, &lvi)) {
type = ConvertLparam2Type(lvi.lParam);
} else {
assert(FALSE);
return FALSE;
}
if (lvi.iImage != IMAGE_LAYERS) {
return TRUE;
}
if (type == FIX_LIST_FLAG) {
pffl = (PFLAG_FIX_LIST) lvi.lParam;
} else if (type == FIX_LIST_SHIM) {
psfl = (PSHIM_FIX_LIST) lvi.lParam;
}
if (psfl) {
psf = psfl->pShimFix;
//
// We take care of it here if it's a LUA shim because we didn't add it to
// the layer fix list.
//
if (psf->strName == TEXT("LUARedirectFS") ||
psf->strName == TEXT("LUARedirectReg")) {
if (g_bIsLUALayerSelected) {
if (IDYES == MessageBox(hdlg, GetString(IDS_SHIMINLAYER), g_szAppName, MB_ICONWARNING | MB_YESNO)) {
//
// The only thing we need to do is changing the icon back to the shim
// icon. We need to change this for both shims in the layer.
//
ChangeShimIcon(TEXT("LUARedirectFS"));
ChangeShimIcon(TEXT("LUARedirectReg"));
g_bIsLUALayerSelected = FALSE;
} else {
return FALSE;
}
}
return TRUE;
}
//
// Othewise just go through the normal path.
//
bFoundInLayer = ShimPresentInLayersOfEntry(&g_pCurrentWizard->m_Entry,
psf,
NULL,
&plfl);
} else if (pffl) {
bFoundInLayer = FlagPresentInLayersOfEntry(&g_pCurrentWizard->m_Entry,
pffl->pFlagFix,
NULL,
&plfl);
}
if (bFoundInLayer) {
if (IDYES == MessageBox(hdlg, GetString(IDS_SHIMINLAYER), g_szAppName, MB_ICONWARNING | MB_YESNO)) {
s_bLayerPageRefresh = TRUE;
//
// For all the layers that have this shim,
// 1. Change the icons,
// 2. As for now, we retain the params just as the that in the layer
// 3. Remove the layer from the entry
//
PLAYER_FIX_LIST plflTemp = g_pCurrentWizard->m_Entry.pFirstLayer;
PLAYER_FIX_LIST plflTempPrev = NULL;
PLAYER_FIX_LIST plflTempNext = NULL;
//
// Go to the first layer that has this shim or flag
//
while (plflTemp) {
if (plflTemp == plfl) {
break;
} else {
plflTempPrev = plflTemp;
}
plflTemp = plflTemp->pNext;
}
while (plflTemp) {
//
// Now for all the layers following and including this layer,
// check if it has the selected shim or flag.
// If it has then, we change the icons of all the shims and flags that are present in this layer
// and remove it from the list of layers applied to this entry
//
bFoundInLayer = FALSE;
if (psfl) {
bFoundInLayer = IsShimInlayer(plflTemp->pLayerFix, psfl->pShimFix, NULL, NULL);
} else if (pffl) {
bFoundInLayer = IsFlagInlayer(plflTemp->pLayerFix, pffl->pFlagFix, NULL);
}
if (bFoundInLayer) {
ChangeShimFlagIcons(hdlg, plflTemp);
if (plflTempPrev == NULL) {
g_pCurrentWizard->m_Entry.pFirstLayer = plflTemp->pNext;
} else {
plflTempPrev->pNext = plflTemp->pNext;
}
plflTempNext = plflTemp->pNext;
//
// Do not do a DeleteLayerFixList here as this will remove
// all layer fix lists following this as well.
//
delete plflTemp;
plflTemp = plflTempNext;
} else {
plflTempPrev = plflTemp;
plflTemp = plflTemp->pNext;
}
}
} else {
return FALSE;
}
}
return TRUE;
}
void
ChangeShimIcon(
IN LPCTSTR pszItem
)
/*++
ChangeShimIcon
Desc: Changes the icon of the shim/flag with the name pszItem to a shim icon.
Params:
IN LPCTSTR pszItem: The name of the shim or flag
--*/
{
LVFINDINFO lvfind;
LVITEM lvi;
INT iIndex = -1;
ZeroMemory(&lvfind, sizeof(lvfind));
lvfind.flags = LVFI_STRING;
lvfind.psz = pszItem;
if ((iIndex = ListView_FindItem(s_hwndShimList, -1, &lvfind)) != -1) {
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_IMAGE;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
lvi.iImage = IMAGE_SHIM;
ListView_SetItem(s_hwndShimList, &lvi);
}
}
void
ChangeShimFlagIcons(
IN HWND hdlg,
IN PLAYER_FIX_LIST plfl
)
/*++
ChangeShimFlagIcons
Desc: For All the shims and flags that are present in plfl,
this routine changes their icons to indicate that they
are no longer part of some layer
Params:
IN HWND hdlg: The shims wizard page
IN PLAYER_FIX_LIST plfl: The layer for which is abou to be removed, so we need to
change the icons for all the shims and flags that are part of this layer.
Return:
void
--*/
{
PSHIM_FIX_LIST psfl = plfl->pLayerFix->pShimFixList;
PFLAG_FIX_LIST pffl = plfl->pLayerFix->pFlagFixList;
//
// First for the shims
//
while (psfl) {
assert(psfl->pShimFix);
ChangeShimIcon(psfl->pShimFix->strName.pszString);
psfl= psfl->pNext;
}
//
// Now for the flags
//
while (pffl) {
assert(pffl->pFlagFix);
ChangeShimIcon(pffl->pFlagFix->strName.pszString);
pffl = pffl->pNext;
}
}
BOOL
AddLuaShimsInEntry(
IN PDBENTRY pEntry,
OUT CSTRINGLIST* pstrlShimsAdded //(NULL)
)
/*++
AddLuaShimsInEntry
Desc: Adds the lua shims which are present in LUA layer to an entry. First checks
if the shim is already present, if yes does not add it.
Params:
IN PDBENTRY pEntry: The entry to which we want to add the lua shims
OUT CSTRINGLIST* pstrlShimsAdded(NULL): The names of the lua shims that this routine has added
We need this because if we are doing a test run then after the test-run is over, we
will have to remove these shims
Return:
TRUE: Success
FALSE: Otherwise
--*/
{
PLAYER_FIX plfLua = NULL;
PSHIM_FIX_LIST psflInLua = NULL;
PSHIM_FIX_LIST psflNew = NULL;
if (pEntry == NULL) {
assert(FALSE);
return FALSE;
}
plfLua = (PLAYER_FIX)FindFix(TEXT("LUA"), FIX_LAYER, &GlobalDataBase);
if (plfLua == NULL) {
assert(FALSE);
return FALSE;
} else {
//
// For all the shims in LUA add them to this entry. But first check if that
// shim is already present in the entry
//
psflInLua = plfLua->pShimFixList;
while (psflInLua) {
//
// Do not add a shim that is already present
//
if (!IsShimInEntry(psflInLua->pShimFix->strName,
pEntry)) {
psflNew = new SHIM_FIX_LIST;
if (psflNew == NULL) {
MEM_ERR;
break;
}
psflNew->pShimFix = psflInLua->pShimFix;
//
// Add this to the entry
//
psflNew->pNext = pEntry->pFirstShim;
pEntry->pFirstShim = psflNew;
//
// Keep track of what lua shims we have added
//
if (pstrlShimsAdded) {
pstrlShimsAdded->AddString(psflInLua->pShimFix->strName);
}
}
psflInLua = psflInLua->pNext;
}
}
return TRUE;
}
INT_PTR
GetAppNameDlgOnInitDialog(
IN HWND hDlg
)
/*++
GetAppNameDlgOnInitDialog
Desc: The handler of WM_INITDIALOG for the first wizard page
Params:
IN HWND hDlg: The first wizard page
Return:
TRUE
--*/
{
HWND hwndParent = GetParent(hDlg);
//
// Center the wizard window with respect to the main app window
//
CenterWindow(GetParent(hwndParent), hwndParent);
if (g_pCurrentWizard->m_bEditing
&& (g_pCurrentWizard->m_Entry.pFirstFlag
|| g_pCurrentWizard->m_Entry.pFirstLayer
|| g_pCurrentWizard->m_Entry.pFirstShim
|| g_pCurrentWizard->m_Entry.pFirstPatch)) {
//
// Edit an application fix. Some fixes already exist.
//
SetWindowText(hwndParent, CSTRING(IDS_WIZ_EDITFIX));
} else if (g_pCurrentWizard->m_bEditing) {
//
// There are no fixes but still we are editting. This means the entry contains
// an apphelp. We have to "add" a fix
//
SetWindowText(hwndParent, CSTRING(IDS_WIZ_ADDFIX));
} else {
//
// Create a new fix
//
SetWindowText(hwndParent, CSTRING(IDS_WIZ_CREATEFIX));
}
SendMessage(GetDlgItem(hDlg, IDC_NAME), EM_LIMITTEXT, (WPARAM)LIMIT_APP_NAME, (LPARAM)0);
SendMessage(GetDlgItem(hDlg, IDC_VENDOR), EM_LIMITTEXT, (WPARAM)LIMIT_APP_NAME, (LPARAM)0);
SendMessage(GetDlgItem(hDlg, IDC_EXEPATH), EM_LIMITTEXT, (WPARAM)MAX_PATH-1, (LPARAM)0);
SHAutoComplete(GetDlgItem(hDlg, IDC_EXEPATH), AUTOCOMPLETE);
if (g_pCurrentWizard->m_bEditing) {
//
// Make the App. text field and the exe name read only
//
SendMessage(GetDlgItem(hDlg, IDC_NAME),
EM_SETREADONLY,
TRUE,
0);
SendMessage(GetDlgItem(hDlg, IDC_EXEPATH),
EM_SETREADONLY,
TRUE,
0);
ENABLEWINDOW(GetDlgItem(hDlg, IDC_BROWSE), FALSE);
}
if (0 == g_pCurrentWizard->m_Entry.strAppName.Length()) {
g_pCurrentWizard->m_Entry.strAppName = GetString(IDS_DEFAULT_APP_NAME);
}
SetDlgItemText(hDlg, IDC_NAME, g_pCurrentWizard->m_Entry.strAppName);
if (g_pCurrentWizard->m_Entry.strVendor.Length() == 0) {
g_pCurrentWizard->m_Entry.strVendor = GetString(IDS_DEFAULT_VENDOR_NAME);
}
SetDlgItemText(hDlg, IDC_VENDOR, g_pCurrentWizard->m_Entry.strVendor);
if (g_pCurrentWizard->m_bEditing) {
SetDlgItemText(hDlg, IDC_EXEPATH, g_pCurrentWizard->m_Entry.strExeName);
}
SendMessage(GetDlgItem(hDlg, IDC_NAME), EM_SETSEL, 0,-1);
//
// Force proper Next button state.
//
SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_NAME, EN_CHANGE), 0);
return TRUE;
}
INT_PTR
GetAppNameDlgOnNotifyOnFinish_Next(
IN HWND hDlg
)
/*++
GetAppNameDlgOnNotifyOnFinish_Next
Desc: Handles the pressing of the next or the finish button in the first page of the wizard
Params:
IN HWND hDlg: The first page of the wizard
Return:
-1: Do not allow to comlete finish or navigate away from this page
There was some error (No shims, flags or layers have been selected)
0: Otherwise
--*/
{
TCHAR szTemp[MAX_PATH];
INT_PTR ipReturn = 0;
CSTRING strTemp;
GetDlgItemText(hDlg, IDC_NAME, szTemp, ARRAYSIZE(szTemp));
CSTRING::Trim(szTemp);
if (!IsValidAppName(szTemp)) {
//
// The app name contains invalid chars
//
DisplayInvalidAppNameMessage(hDlg);
SetFocus(GetDlgItem(hDlg, IDC_NAME));
SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
ipReturn = -1;
goto End;
}
g_pCurrentWizard->m_Entry.strAppName = szTemp;
GetDlgItemText(hDlg, IDC_EXEPATH, szTemp, MAX_PATH);
strTemp = szTemp;
CSTRING::Trim(szTemp);
//
// Set the exe name and the long file name
//
if (!g_pCurrentWizard->m_bEditing) {
//
// Test if the file exists
//
HANDLE hFile = CreateFile(szTemp,
0,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile) {
//
// The file name could not be located
//
MessageBox(hDlg,
GetString(IDS_INVALIDEXE),
g_szAppName,
MB_ICONWARNING);
//
// We do not allow to go to the next page
//
SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
ipReturn = -1;
goto End;
}
CloseHandle(hFile);
//
// Set the full path
//
g_pCurrentWizard->m_Entry.strFullpath = szTemp;
g_pCurrentWizard->m_Entry.strFullpath.ConvertToLongFileName();
//
// Set the default mask for the matching attributes to be used
//
g_pCurrentWizard->dwMaskOfMainEntry = DEFAULT_MASK;
//
// Set the exe name that will be written in the xml
//
SafeCpyN(szTemp, (LPCTSTR)g_pCurrentWizard->m_Entry.strFullpath, ARRAYSIZE(szTemp));
PathStripPath(szTemp);
g_pCurrentWizard->m_Entry.strExeName= szTemp;
} else if (g_pCurrentWizard->m_Entry.strFullpath.Length() == 0) {
//
// This SDB was loaded from the disk
//
g_pCurrentWizard->m_Entry.strFullpath = szTemp;
}
//
// Set the vendor information
//
GetDlgItemText(hDlg, IDC_VENDOR, szTemp, ARRAYSIZE(szTemp));
if (CSTRING::Trim(szTemp)) {
g_pCurrentWizard->m_Entry.strVendor = szTemp;
} else {
g_pCurrentWizard->m_Entry.strVendor = GetString(IDS_DEFAULT_VENDOR_NAME);
}
End:
return ipReturn;
}
INT_PTR
GetAppNameDlgOnNotify(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
GetAppNameDlgOnNotify
Desc: The handler of WM_NOTIFY for the first wizard page
Params:
IN HWND hDlg: The first wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Return: Please see the return types for the notification messages
Handler for PSN_* messages return -1 if the message should not be accepted
and 0 if the message has been handled properly
For other notification messages we return TRUE if we processed the message, FALSE otherwise
--*/
{
NMHDR* pHdr = (NMHDR*)lParam;
INT_PTR ipReturn = FALSE;
if (pHdr == NULL) {
return FALSE;
}
switch (pHdr->code) {
case PSN_SETACTIVE:
SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_NAME, EN_CHANGE), 0);
ipReturn = 0;
break;
case PSN_WIZFINISH:
case PSN_WIZNEXT:
ipReturn = GetAppNameDlgOnNotifyOnFinish_Next(hDlg);
break;
default: ipReturn = 0;
}
return ipReturn;
}
INT_PTR
GetAppNameDlgOnCommand(
IN HWND hDlg,
IN WPARAM wParam
)
/*++
GetAppNameDlgOnCommand
Desc: The handler of WM_COMMAND for the first wizard page
Params:
IN HWND hDlg: The first wizard page
IN WPARAM wParam: The wParam that comes with WM_COMMAND
Return:
TRUE: We processed the message
FALSE: Otherwise
--*/
{
INT_PTR ipReturn = TRUE;
switch (LOWORD(wParam)) {
case IDC_VENDOR:
case IDC_NAME:
case IDC_EXEPATH:
if (EN_CHANGE == HIWORD(wParam)) {
TCHAR szText[MAX_PATH_BUFFSIZE];
DWORD dwFlags;
BOOL bEnable;
*szText = 0;
GetWindowText(GetDlgItem(hDlg, IDC_NAME), szText, ARRAYSIZE(szText));
bEnable = ValidInput(szText);
GetWindowText(GetDlgItem(hDlg, IDC_EXEPATH), szText, MAX_PATH);
bEnable &= ValidInput(szText);
dwFlags = 0;
if (bEnable) {
dwFlags |= PSWIZB_NEXT;
if (g_pCurrentWizard->m_bEditing) {
dwFlags |= PSWIZB_FINISH;
}
} else {
if (g_pCurrentWizard->m_bEditing) {
dwFlags |= PSWIZB_DISABLEDFINISH;
}
}
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, dwFlags);
}
break;
case IDC_BROWSE:
{
CSTRING szFilename;
HWND hwndFocus = GetFocus();
TCHAR szBuffer[512] = TEXT("");
GetString(IDS_EXEFILTER, szBuffer, ARRAYSIZE(szBuffer));
if (GetFileName(hDlg,
CSTRING(IDS_FINDEXECUTABLE),
szBuffer,
TEXT(""),
GetString(IDS_EXE_EXT),
OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
TRUE,
szFilename)) {
SetDlgItemText(hDlg, IDC_EXEPATH, szFilename);
//
// Force proper Next button state.
//
SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_EXEPATH, EN_CHANGE), 0);
}
SetFocus(hwndFocus);
break;
}
default: ipReturn = FALSE;
}
return ipReturn;
}
INT_PTR
SelectLayerDlgOnInitDialog(
IN HWND hDlg
)
/*++
SelectLayerDlgOnInitDialog
Desc: The handler of WM_INITDIALOG for the second wizard page
Params:
IN HWND hDlg: The second wizard page
Return:
TRUE: Message Handled
FALSE: There was some error. (Memory could not be allocated)
--*/
{
HWND hwndRadio;
//
// If we are creating a new fix then we choose WIN 95 layer by default
//
if (g_pCurrentWizard->m_bEditing == FALSE) {
hwndRadio = GetDlgItem(hDlg, IDC_RADIO_95);
} else {
hwndRadio = GetDlgItem(hDlg, IDC_RADIO_NONE);
}
SendMessage(hwndRadio, BM_SETCHECK, BST_CHECKED, 0);
s_hwndLayerList = GetDlgItem(hDlg, IDC_LAYERLIST);
ListView_SetImageList(s_hwndLayerList, g_hImageList, LVSIL_SMALL);
ListView_SetExtendedListViewStyleEx(s_hwndLayerList,
0,
LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_CHECKBOXES);
//
// Add the Sytem Layers.
//
InsertColumnIntoListView(s_hwndLayerList, 0, 0, 100);
LVITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvi.iSubItem = 0;
lvi.iImage = IMAGE_LAYERS;
UINT uCount = 0;
PLAYER_FIX plf = GlobalDataBase.pLayerFixes;
while (plf) {
if (!IsOsLayer(plf->strName)) {
PLAYER_FIX_LIST plfl = new LAYER_FIX_LIST;
if (plfl == NULL) {
MEM_ERR;
return FALSE;
}
plfl->pLayerFix = plf;
lvi.pszText = plf->strName;
lvi.iItem = uCount;
lvi.lParam = (LPARAM)plfl;
INT iIndex = ListView_InsertItem(s_hwndLayerList, &lvi);
if (g_pCurrentWizard->m_bEditing) {
PLAYER_FIX_LIST plflExists = NULL;
if (LayerPresent (plf, &g_pCurrentWizard->m_Entry, &plflExists)) {
assert(plflExists);
ListView_SetCheckState(s_hwndLayerList, iIndex, TRUE);
}
}
uCount++;
} else if (g_pCurrentWizard->m_bEditing) {
if (LayerPresent (plf, &g_pCurrentWizard->m_Entry, NULL)) {
//
// Set the correct Radio Button
//
INT id = 0;
//
// DeSelect All
//
CheckDlgButton(hDlg, IDC_RADIO_95, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_NT, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_98, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_2K, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_RADIO_NONE, BST_UNCHECKED);
if (lstrcmpi(plf->strName, s_arszOsLayers[0]) == 0) {
id = IDC_RADIO_95;
} else if (lstrcmpi(plf->strName, s_arszOsLayers[1]) == 0) {
id = IDC_RADIO_NT;
} else if (lstrcmpi(plf->strName, s_arszOsLayers[2]) == 0) {
id = IDC_RADIO_98;
} else if (lstrcmpi(plf->strName, s_arszOsLayers[3]) == 0) {
id = IDC_RADIO_2K;
}
CheckDlgButton(hDlg, id, BST_CHECKED);
}
}
plf = plf->pNext;
}
//
// Add the Custom Layers
//
plf = (g_pCurrentWizard->m_pDatabase->type == DATABASE_TYPE_WORKING) ?
g_pCurrentWizard->m_pDatabase->pLayerFixes : NULL;
while (plf) {
PLAYER_FIX_LIST plfl = new LAYER_FIX_LIST;
if (plfl == NULL) {
MEM_ERR;
return FALSE;
}
plfl->pLayerFix = plf;
lvi.pszText = plf->strName;
lvi.iItem = uCount;
lvi.lParam = (LPARAM)plfl;
INT iIndex = ListView_InsertItem(s_hwndLayerList, &lvi);
PLAYER_FIX_LIST plflExists = NULL;
if (g_pCurrentWizard->m_bEditing && LayerPresent(plf,
&g_pCurrentWizard->m_Entry,
&plflExists)) {
assert(plflExists);
ListView_SetCheckState(s_hwndLayerList, iIndex, TRUE);
}
uCount++;
plf = plf->pNext;
}
return TRUE;
}
INT_PTR
SelectLayerDlgOnDestroy(
void
)
/*++
SelectLayerDlgOnDestroy
Desc: The handler of WM_DESTROY for the second wizard page
The list view of this page contains pointers to LAYER_FIX_LIST objects
and these have to be freed here
Params:
IN HWND hDlg: The second wizard page
Return:
TRUE
--*/
{
UINT uCount = ListView_GetItemCount(s_hwndLayerList);
for (UINT uIndex = 0; uIndex < uCount; ++uIndex) {
LVITEM Item;
Item.mask = LVIF_PARAM;
Item.iItem = uIndex;
Item.iSubItem = 0;
if (!ListView_GetItem(s_hwndLayerList, &Item)) {
assert(FALSE);
continue;
}
TYPE type = ((PDS_TYPE)Item.lParam)->type ;
if (type == FIX_LIST_LAYER) {
delete ((PLAYER_FIX_LIST)Item.lParam);
} else {
assert(FALSE);
}
}
return TRUE;
}
void
DoLayersTestRun(
IN HWND hDlg
)
/*++
DoLayersTestRun
Desc: Does the test run when we are on the layers page
Params:
IN HWND hDlg: The layer page in the wizard
Return:
void
--*/
{
CSTRINGLIST strlAddedLuaShims;
PSHIM_FIX_LIST psfl = NULL;
PSHIM_FIX_LIST psflNext = NULL;
PSHIM_FIX_LIST psflPrev = NULL;
INT iCountAddedLuaShims = 0;
if (g_bAdmin == FALSE) {
//
// Test run will need to call sdbinst.exe which will not run if we are
// not an admin
//
MessageBox(hDlg,
GetString(IDS_ERRORNOTADMIN),
g_szAppName,
MB_ICONINFORMATION);
goto End;
}
if (!HandleLayersNext(hDlg, TRUE, &strlAddedLuaShims)) {
//
// There were no layers, shims, patches for this entry
//
MessageBox(hDlg, CSTRING(IDS_SELECTFIX), g_szAppName, MB_ICONWARNING);
goto End;
}
//
// Invoke test run dialog. Please make sure that this function does not return till the
// app has finished executing.
//
TestRun(&g_pCurrentWizard->m_Entry,
&g_pCurrentWizard->m_Entry.strFullpath,
NULL,
hDlg);
//
// <HACK>This is a hack!!!. TestRun launches a process using CreateProcess
// and then the modal wizard starts behaving like a modeless wizard
//
ENABLEWINDOW(g_hDlg, FALSE);
//
// Now test run is over. So we should now check if we had to add any lua shims
// and if yes, we must remove those shims
//
for (PSTRLIST pslist = strlAddedLuaShims.m_pHead;
pslist != NULL;
pslist = pslist->pNext) {
psfl = g_pCurrentWizard->m_Entry.pFirstShim;
psflPrev = NULL;
//
// For all the shims that are in the entry, check if it is
// same as the one in pslist, if yes remove it
//
while (psfl) {
if (psfl->pShimFix->strName == pslist->szStr) {
//
// Found. We have to remove this shim list from this entry
//
if (psflPrev == NULL) {
g_pCurrentWizard->m_Entry.pFirstShim = psfl->pNext;
} else {
psflPrev->pNext = psfl->pNext;
}
delete psfl;
break;
} else {
//
// Keep looking
//
psflPrev = psfl;
psfl = psfl->pNext;
}
}
}
End:
SetActiveWindow(hDlg);
SetFocus(hDlg);
}
INT_PTR
SelectLayerDlgOnCommand(
IN HWND hDlg,
IN WPARAM wParam
)
/*++
SelectLayerDlgOnCommand
Desc: The handler of WM_COMMAND for the second wizard page
Params:
IN HWND hDlg: The second wizard page
IN WPARAM wParam: The wParam that comes with WM_COMMAND
Return:
TRUE: We processed the message
FALSE: Otherwise
--*/
{
INT_PTR ipReturn = TRUE;
switch (LOWORD(wParam)) {
case IDC_TESTRUN:
DoLayersTestRun(hDlg);
break;
default: ipReturn = FALSE;
}
return ipReturn;
}
INT_PTR
SelectLayerDlgOnNotify(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
SelectLayerDlgOnNotify
Desc: The handler of WM_NOTIFY for the second wizard page
Params:
IN HWND hDlg: The second wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Return: Please see the return types for the notification messages
Handler for PSN_* messages return -1 if the message should not be accepted
and 0 if the message has been handled properly
For other notification messages we return TRUE if we processed the message,
FALSE otherwise
--*/
{
NMHDR* pHdr = (NMHDR*)lParam;
LPARAM buttons = 0;
INT_PTR ipRet = 0;
if (pHdr->hwndFrom == s_hwndLayerList) {
return HandleLayerListNotification(hDlg, lParam);
}
switch (pHdr->code) {
case PSN_SETACTIVE:
buttons = PSWIZB_BACK | PSWIZB_NEXT;
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, buttons);
if (s_bLayerPageRefresh) {
CheckLayers(hDlg);
}
s_bLayerPageRefresh = FALSE;
ipRet = 0;
break;
case PSN_WIZFINISH:
HandleLayersNext(hDlg, TRUE);
if (g_pCurrentWizard->m_Entry.pFirstLayer == NULL
&& g_pCurrentWizard->m_Entry.pFirstShim == NULL
&& g_pCurrentWizard->m_Entry.pFirstFlag == NULL) {
//
// No fix has been selected
//
MessageBox(hDlg,
CSTRING(IDS_SELECTFIX),
g_szAppName,
MB_ICONWARNING);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
ipRet = -1;
} else {
ipRet = 0;
}
break;
case PSN_WIZNEXT:
HandleLayersNext(hDlg, FALSE);
g_bLayersChanged = TRUE;
ipRet= 0;
break;
default: ipRet = FALSE;
}
return ipRet;
}
INT_PTR
SelectShimsDlgOnInitDialog(
IN HWND hDlg
)
/*++
SelectShimsDlgOnInitDialog
Desc: The handler of WM_INITDIALOG for the third wizard page
Params:
IN HWND hDlg: The third wizard page
Return:
TRUE
--*/
{
UINT uCount = 0;
LPARAM uTime = 32767;
s_bAllShown = TRUE;
s_hwndShimList = GetDlgItem(hDlg, IDC_SHIMLIST);
ListView_SetImageList(GetDlgItem(hDlg, IDC_SHIMLIST), g_hImageList, LVSIL_SMALL);
ListView_SetExtendedListViewStyleEx(s_hwndShimList,
0,
LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_CHECKBOXES);
//
// Add the columns
//
InsertColumnIntoListView(s_hwndShimList,
CSTRING(IDS_COL_FIXNAME),
0,
g_bExpert ? 50 : 100);
if (g_bExpert) {
InsertColumnIntoListView(s_hwndShimList, CSTRING(IDS_COL_CMDLINE), 1, 30);
InsertColumnIntoListView(s_hwndShimList, CSTRING(IDS_COL_MODULE), 2, 20);
} else {
ShowWindow(GetDlgItem(hDlg, IDC_PARAMS), SW_HIDE);
}
ShowItems(hDlg);
SetTimer(hDlg, 0, 100, NULL);
s_hwndToolTipList = ListView_GetToolTips(s_hwndShimList);
SendMessage(s_hwndToolTipList, TTM_SETDELAYTIME, TTDT_AUTOPOP, (LPARAM)MAKELONG(uTime, 0));
SendMessage(s_hwndToolTipList, TTM_SETDELAYTIME, TTDT_INITIAL, (LPARAM)0);
SendMessage(s_hwndToolTipList, TTM_SETMAXTIPWIDTH, 0, 100);
return TRUE;
}
void
DoShimTestRun(
IN HWND hDlg
)
/*++
DoShimTestRun
Desc: Does the test run when we are on the shims page
Params:
IN HWND hDlg: The shim page in the wizard
Return:
void
--*/
{
PSHIM_FIX_LIST psflInEntry = NULL;
if (g_bAdmin == FALSE) {
//
// Only admins can do a test run because we need to call sdbinst.exe, which
// can run only in admin mode
//
MessageBox(hDlg,
GetString(IDS_ERRORNOTADMIN),
g_szAppName,
MB_ICONINFORMATION);
goto End;
}
//
// We need to save the shims that have been applied to the entry
// before we do a test run. Because we add the shims to the entry during test run,
// when we will end doing test run we will wish to revert to the shims that were
// present in the entry. Otherwise if the user clears some of the shims and goes
// to the layers page then we will still have the shims applied to the entry
//
if (g_pCurrentWizard->m_Entry.pFirstShim) {
//
// Get the applied shims
//
CopyShimFixList(&psflInEntry, &g_pCurrentWizard->m_Entry.pFirstShim);
}
if (!HandleShimsNext(hDlg)) {
//
// No fixes have been selected
//
MessageBox(hDlg,
CSTRING(IDS_SELECTFIX),
g_szAppName,
MB_ICONWARNING);
goto End;
}
TestRun(&g_pCurrentWizard->m_Entry,
&g_pCurrentWizard->m_Entry.strFullpath,
NULL,
hDlg);
//
// <HACK>This is a hack!!!. TestRun launches a process using CreateProcess
// and then the modal wizard starts behaving like a modeless wizard
//
ENABLEWINDOW(g_hDlg, FALSE);
SetActiveWindow(hDlg);
SetFocus(hDlg);
//
// Revert to the shims that were actually applied before we did a test run
//
CopyShimFixList(&g_pCurrentWizard->m_Entry.pFirstShim, &psflInEntry);
End:
if (psflInEntry) {
//
// Some shims were already applied to this entry (g_pCurrentWizard->m_Entry)
// and we psflInEntry has
// been populated with them, we must free this linked list as we no longer
// need it
//
DeleteShimFixList(psflInEntry);
psflInEntry = NULL;
}
}
INT_PTR
SelectShimsDlgOnCommand(
IN HWND hDlg,
IN WPARAM wParam
)
/*++
SelectShimsDlgOnCommand
Desc: The handler of WM_COMMAND for the second wizard page
Params:
IN HWND hDlg: The second wizard page
IN WPARAM wParam: The wParam that comes with WM_COMMAND
Return:
TRUE: We processed the message
FALSE: Otherwise
--*/
{
UINT uCount = ListView_GetItemCount(s_hwndShimList);
INT_PTR ipReturn = TRUE;
switch (LOWORD(wParam)) {
case IDC_CLEARALL:
for (UINT uIndex = 0; uIndex < uCount; ++uIndex) {
ListView_SetCheckState(s_hwndShimList, uIndex, FALSE);
}
SetTimer(hDlg, 0, 100, NULL);
break;
case IDC_SHOW:
{
if (s_bAllShown) {
//
// Now show only the selected shims
//
ShowSelected(hDlg);
} else {
//
// Now show all the shims
//
ShowItems(hDlg);
}
//
// Select the first item. We need to do this so that, we can disable
// the params button if the shim is a part of a layer.
//
SetFocus(s_hwndShimList);
ListView_SetSelectionMark(s_hwndShimList, 0);
LVITEM lvi;
lvi.mask = LVIF_STATE;
lvi.iItem = 0;
lvi.iSubItem = 0;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
ListView_SetItem(s_hwndShimList, &lvi);
SetTimer(hDlg, 0, 100, NULL);
break;
}
case IDC_PARAMS:
ShowParams(hDlg, GetDlgItem(hDlg, IDC_SHIMLIST));
break;
case IDC_TESTRUN:
DoShimTestRun(hDlg);
break;
default: ipReturn = FALSE;
}
return ipReturn;
}
INT_PTR
SelectShimsDlgOnTimer(
IN HWND hDlg
)
/*++
SelectShimsDlgOnTimer
Desc: Handles the WM_TIMER Message and shows the count of all the shims that have
been selected
Params:
IN HWND hDlg: The shim selection page. This is the third wizard page
Return: TRUE
--*/
{
UINT uTotal = 0;
UINT uSelected = 0;
UINT uCount = 0;
CSTRING szText;
DWORD dwFlags;
KillTimer(hDlg, 0);
//
// Count the selected shims
//
uCount = ListView_GetItemCount(s_hwndShimList);
for (UINT uIndex = 0; uIndex < uCount; ++uIndex) {
if (ListView_GetCheckState(s_hwndShimList, uIndex)) {
++uSelected;
}
}
ENABLEWINDOW(GetDlgItem(hDlg, IDC_CLEARALL),
uSelected == 0 ? FALSE : TRUE);
szText.Sprintf(TEXT("%s %d of %d"), GetString(IDS_SELECTED), uSelected, uCount);
SetWindowText(GetDlgItem(hDlg, IDC_STATUS),(LPCTSTR)szText);
dwFlags = PSWIZB_BACK | PSWIZB_NEXT;
if (0 == uSelected && !g_pCurrentWizard->m_Entry.pFirstLayer) {
dwFlags &= ~PSWIZB_NEXT;
}
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, dwFlags);
return TRUE;
}
INT_PTR
SelectShimsDlgOnDestroy(
void
)
/*++
SelectShimsDlgOnDestroy
Desc: The handler of WM_DESTROY for the third wizard page
The list view of this page contains pointers to SHIM_FIX_LIST and
FLAG_FIX_LIST objects and these have to be freed here
Params:
IN HWND hDlg: The third wizard page
Return:
TRUE
--*/
{
UINT uCount = ListView_GetItemCount(s_hwndShimList);
TYPE type;
LVITEM Item;
for (UINT uIndex = 0; uIndex < uCount; ++uIndex) {
Item.mask = LVIF_PARAM;
Item.iItem = uIndex;
Item.iSubItem = 0;
if (!ListView_GetItem(s_hwndShimList, &Item)) {
assert(FALSE);
continue;
}
type = ((PDS_TYPE)Item.lParam)->type ;
if (type == FIX_LIST_SHIM) {
DeleteShimFixList((PSHIM_FIX_LIST)Item.lParam);
} else if (type == FIX_LIST_FLAG) {
DeleteFlagFixList((PFLAG_FIX_LIST)Item.lParam);
}
}
return TRUE;
}
INT_PTR
SelectShimsDlgOnNotifyFinish_Next(
IN HWND hDlg
)
/*++
SelectShimsDlgOnNotifyFinish_Next
Desc: Handles the pressing of the next or finish button in the shim page
Params:
IN HWND hdlg: The shim page in the wizard
Return:
-1: Do not allow to comlete finish or navigate away from this page
There was some error (No shims, flags or layers have been selected)
0: Otherwise
--*/
{
INT ipReturn = 0;
HandleShimsNext(hDlg);
if (g_pCurrentWizard->m_Entry.pFirstLayer == NULL &&
g_pCurrentWizard->m_Entry.pFirstShim == NULL &&
g_pCurrentWizard->m_Entry.pFirstFlag == NULL) {
//
// No shim, flags or layers have been selected
//
MessageBox(hDlg,
CSTRING(IDS_SELECTFIX),
g_szAppName,
MB_ICONWARNING);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
ipReturn = -1;
goto End;
} else {
ipReturn = 0;
}
End:
return ipReturn;
}
INT_PTR
SelectShimsDlgOnNotifyOnSetActive(
IN HWND hDlg
)
/*++
SelectShimsDlgOnNotifyOnSetActive
Desc: Handles the PSN_SETACTIVE notification in the shim page. Sets the focus
to the list view and selects the first item in that.
Params:
IN HWND hdlg: The shim page in the wizard
Return:
0
--*/
{
INT_PTR ipReturn = 0;
//
// If we are coming from the layers page, then we might need to again refresh
// the list of shims, as it is possible that some of them might have been in the
// layers chosen. (Some might get removed as well, because the layer was de-selected)
//
if (g_bLayersChanged) {
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowItems(hDlg);
SetTimer(hDlg, 0, 100, NULL);
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
LPARAM buttons = PSWIZB_BACK | PSWIZB_NEXT;
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, buttons);
//
// Select the first item. We need to do this so that, we can disable
// the params button if the shim is a part of a layer.
//
SetFocus(s_hwndShimList);
ListView_SetSelectionMark(s_hwndShimList, 0);
LVITEM lvi;
lvi.mask = LVIF_STATE;
lvi.iItem = 0;
lvi.iSubItem = 0;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
ListView_SetItem(s_hwndShimList, &lvi);
return ipReturn;
}
INT_PTR
SelectShimsDlgOnNotifyOnClick(
IN HWND hDlg
)
/*++
SelectShimsDlgOnNotifyOnClick
Desc: Handles the NM_CLICK notification in the shim page. This actually changes
the state of the check box in in the shim list view
Params:
IN HWND hdlg: The shim page in the wizard
Return:
TRUE
--*/
{
INT_PTR ipReturn = TRUE;
LVHITTESTINFO lvhti;
GetCursorPos(&lvhti.pt);
ScreenToClient(s_hwndShimList, &lvhti.pt);
ListView_HitTest(s_hwndShimList, &lvhti);
//
// If the check box state has changed,
// toggle the selection.
//
if (lvhti.flags & LVHT_ONITEMSTATEICON) {
INT iPos = ListView_GetSelectionMark(s_hwndShimList);
if (iPos != -1) {
//
// De-select it.
//
ListView_SetItemState(s_hwndShimList,
iPos,
0,
LVIS_FOCUSED | LVIS_SELECTED);
}
}
ListView_SetItemState(s_hwndShimList,
lvhti.iItem,
LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED);
ListView_SetSelectionMark(s_hwndShimList, lvhti.iItem);
SetTimer(hDlg, 0, 100, NULL);
if (ListView_GetSelectedCount(s_hwndShimList) == 0) {
ENABLEWINDOW(GetDlgItem(hDlg, IDC_PARAMS), FALSE);
}
ipReturn = TRUE;
return ipReturn;
}
INT_PTR
SelectShimsDlgOnNotifyOnLVItemChanged(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
SelectShimsDlgOnNotifyOnLVItemChanged
Desc: Handles the LVN_ITEMCHANGED notification in the shim page. We handle
this mesage so that we can enable disable the 'Parameters'button that
is visible when we are in expert mode
Params:
IN HWND hdlg: The shim page in the wizard
IN LPARAM lParam: The lParam that comes with WM_NOTIFY. This is typecasted
to a LPNMLISTVIEW.
Return:
TRUE
--*/
{
LPNMLISTVIEW lpnmlv;
INT_PTR ipReturn = 0;
if (s_hwndToolTipList) {
SendMessage(s_hwndToolTipList, TTM_UPDATE, 0, 0);
}
lpnmlv = (LPNMLISTVIEW)lParam;
if (lpnmlv && (lpnmlv->uChanged & LVIF_STATE)) {
if (lpnmlv->uNewState & LVIS_SELECTED) {
//
// For Shims or flags that are part of layers we should not be
// able to customize the parameters.
// We check if it is a part of a layer by checking the icon
// If the icon type is IMAGE_SHIM then that is not a part of a layer
//
LVITEM lvi;
lvi.mask = LVIF_IMAGE;
lvi.iItem = lpnmlv->iItem;
lvi.iSubItem = 0;
if (ListView_GetItem(s_hwndShimList, &lvi)) {
if (lvi.iImage == IMAGE_SHIM) {
ENABLEWINDOW(GetDlgItem(hDlg, IDC_PARAMS), TRUE);
} else {
ENABLEWINDOW(GetDlgItem(hDlg, IDC_PARAMS), FALSE);
}
} else {
assert(FALSE);
ENABLEWINDOW(GetDlgItem(hDlg, IDC_PARAMS), FALSE);
}
}
if ((lpnmlv->uChanged & LVIF_STATE)
&& (((lpnmlv->uNewState ^ lpnmlv->uOldState) >> 12) != 0)
&& !ListView_GetCheckState(s_hwndShimList, lpnmlv->iItem)
&& g_bNowTest) {
if (!HandleShimDeselect(hDlg, lpnmlv->iItem)) {
ListView_SetCheckState(s_hwndShimList, lpnmlv->iItem, TRUE);
}
}
}
ipReturn = TRUE;
return ipReturn;
}
INT_PTR
SelectShimsDlgOnNotifyOnLV_Tip(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
SelectShimsDlgOnNotifyOnLV_Tip
Desc: Handles the LVN_GETINFOTIP notification in the shim page. Generates the
tool tip showing the description of the shim or flag
Params:
IN HWND hdlg: The shim page in the wizard
IN LPARAM lParam: The lParam that comes with WM_NOTIFY. This is typecasted
to a LPNMLVGETINFOTIP.
Return:
TRUE
--*/
{
LPNMLVGETINFOTIP lpGetInfoTip = (LPNMLVGETINFOTIP)lParam;
INT_PTR ipReturn = TRUE;
TCHAR szText[256];
LVITEM lvItem;
CSTRING strToolTip;
*szText = 0;
if (lpGetInfoTip) {
//
// Get the lParam and the text of the item.
//
lvItem.mask = LVIF_PARAM | LVIF_TEXT;
lvItem.iItem = lpGetInfoTip->iItem;
lvItem.iSubItem = 0;
lvItem.pszText = szText;
lvItem.cchTextMax = ARRAYSIZE(szText);
if (!ListView_GetItem(s_hwndShimList, &lvItem)) {
assert(FALSE);
goto End;
}
GetDescriptionString(lvItem.lParam,
strToolTip,
s_hwndToolTipList,
lvItem.pszText,
NULL,
s_hwndShimList,
lpGetInfoTip->iItem);
if (strToolTip.Length() > 0) {
SafeCpyN(lpGetInfoTip->pszText,
strToolTip.pszString,
lpGetInfoTip->cchTextMax);
}
}
End:
ipReturn = TRUE;
return ipReturn;
}
INT_PTR
SelectShimsDlgOnNotify(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
SelectShimsDlgOnNotify
Desc: The handler of WM_NOTIFY for the second wizard page
Params:
IN HWND hDlg: The second wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Return: Please see the return types for the notification messages
Handler for PSN_* messages return -1 if the message should not be accepted
and 0 if the message has been handled properly
For other notification messages we return TRUE if we processed the message,
FALSE otherwise
--*/
{
NMHDR* pHdr = (NMHDR*)lParam;
INT_PTR ipReturn = FALSE;
switch (pHdr->code) {
case PSN_WIZFINISH:
case PSN_WIZNEXT:
ipReturn = SelectShimsDlgOnNotifyFinish_Next(hDlg);
g_bLayersChanged = FALSE;
break;
case PSN_SETACTIVE:
ipReturn = SelectShimsDlgOnNotifyOnSetActive(hDlg);
break;
case NM_CLICK:
ipReturn = SelectShimsDlgOnNotifyOnClick(hDlg);
break;
case LVN_KEYDOWN:
{
LPNMLVKEYDOWN plvkd = (LPNMLVKEYDOWN)lParam ;
if (plvkd->wVKey == VK_SPACE) {
SetTimer(hDlg, 0, 100, NULL);
}
ipReturn = TRUE;
break;
}
case LVN_ITEMCHANGED:
ipReturn = SelectShimsDlgOnNotifyOnLVItemChanged(hDlg, lParam);
break;
case LVN_GETINFOTIP:
ipReturn = SelectShimsDlgOnNotifyOnLV_Tip(hDlg, lParam);
break;
default:
ipReturn = FALSE;
}
return ipReturn;
}
INT_PTR
SelectFilesDlgOnInitDialog(
IN HWND hDlg
)
/*++
SelectFilesDlgOnInitDialog
Desc: The handler of WM_INITDIALOG for the matching files wizard page.
This page is shared both by the fix wizard and the app help wizard
Also initializes s_hwndTree to the handle of the matching files tree
Params:
IN HWND hDlg: The matching files wizard page
Return:
TRUE
--*/
{
s_hwndTree = GetDlgItem(hDlg, IDC_FILELIST);
s_hMatchingFileImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 7, 1);
ImageList_AddIcon(s_hMatchingFileImageList,
LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_FILE)));
ImageList_AddIcon(s_hMatchingFileImageList,
LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ATTRIBUTE)));
TreeView_SetImageList(s_hwndTree, s_hMatchingFileImageList, TVSIL_NORMAL);
HIMAGELIST hImage = ImageList_LoadImage(g_hInstance,
MAKEINTRESOURCE(IDB_CHECK),
16,
0,
CLR_DEFAULT,
IMAGE_BITMAP,
LR_LOADTRANSPARENT);
if (hImage != NULL) {
TreeView_SetImageList(s_hwndTree,
hImage,
TVSIL_STATE);
}
PostMessage(hDlg, WM_USER_MATCHINGTREE_REFRESH, 0, 0);
//
// The "Show all attributes" button should be visible only if we are
// in editing mode
//
ShowWindow(GetDlgItem(hDlg, IDC_SHOWALLATTR),
(g_pCurrentWizard->m_bEditing) ? SW_SHOW : SW_HIDE);
return TRUE;
}
INT_PTR
CheckLUADlgOnNotifyOnFinish(
IN HWND hDlg
)
/*++
CheckLUADlgOnNotifyOnFinish
Desc: Handles the pressing of the finish button in the fifth page of the wizard
Params:
IN HWND hDlg: The fifth page of the wizard
Return:
-1: Do not allow to comlete finish or navigate away from this page
0: Otherwise
--*/
{
INT_PTR ipReturn = 0;
if (IsDlgButtonChecked(hDlg, IDC_FIXWIZ_CHECKLUA_YES) == BST_CHECKED) {
g_bShouldStartLUAWizard = TRUE;
}
return ipReturn;
}
INT_PTR
CheckLUADlgOnNotify(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
CheckLUADlgOnNotify
Desc: The handler of WM_NOTIFY for the fifth wizard page
Params:
IN HWND hDlg: The fifth wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Return: Please see the return types for the notification messages
Handler for PSN_* messages return -1 if the message should not be accepted
and 0 if the message has been handled properly
For other notification messages we return TRUE if we processed the message, FALSE otherwise
--*/
{
NMHDR* pHdr = (NMHDR*)lParam;
INT_PTR ipReturn = FALSE;
if (pHdr == NULL) {
return FALSE;
}
switch (pHdr->code) {
case PSN_SETACTIVE:
{
LPARAM buttons = PSWIZB_BACK | PSWIZB_FINISH;
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, buttons);
//
// We processed the message and everything is OK. The value should be FALSE
//
ipReturn = 0;
}
break;
case PSN_WIZFINISH:
ipReturn = CheckLUADlgOnNotifyOnFinish(hDlg);
break;
default: ipReturn = 0;
}
return ipReturn;
}
INT_PTR
CALLBACK
CheckLUA(
IN HWND hDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
CheckLUA
Desc: Dialog proc for the last page of the wizard.
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
INT_PTR ipReturn = 0;
switch (uMsg) {
case WM_INITDIALOG:
//
// We want to set the default to Yes because we want the user to customize LUA now.
//
CheckDlgButton(hDlg, IDC_FIXWIZ_CHECKLUA_YES, BST_CHECKED);
return TRUE;
case WM_NOTIFY:
CheckLUADlgOnNotify(hDlg, lParam);
break;
default: ipReturn = 0;
}
return ipReturn;
}
BOOL
AddCheckLUAPage(
HWND hwndWizard
)
{
PROPSHEETPAGE PageCheckLUA;
ZeroMemory(&PageCheckLUA, sizeof(PROPSHEETPAGE));
PageCheckLUA.dwSize = sizeof(PROPSHEETPAGE);
PageCheckLUA.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
PageCheckLUA.hInstance = g_hInstance;
PageCheckLUA.pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_CHECKLUA);
PageCheckLUA.pfnDlgProc = CheckLUA;
PageCheckLUA.pszHeaderTitle = MAKEINTRESOURCE(IDS_CHECKLUA);
PageCheckLUA.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_CHECKLUASUBHEADING);
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&PageCheckLUA);
if (hPage == NULL) {
return FALSE;
} else {
return PropSheet_AddPage(hwndWizard, hPage);
}
}
INT_PTR
SelectFilesDlgOnNotify(
IN HWND hDlg,
IN LPARAM lParam
)
/*++
SelectFilesDlgOnNotify
Desc: The handler of WM_NOTIFY for the matching files wizard page
Params:
IN HWND hDlg: The matching files wizard page
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
Return: Please see the return types for the notification messages
Handler for PSN_* messages return -1 if the message should not be accepted
and 0 if the message has been handled properly
For other notification messages we return TRUE if we processed the message,
FALSE otherwise
--*/
{
NMHDR* pHdr = (NMHDR*)lParam;
INT_PTR ipReturn = FALSE;
static BOOL s_bIsLUARedirectFSPresent;
if (pHdr->idFrom == IDC_FILELIST) {
//
// Messages for the matching files tree
//
return HandleAttributeTreeNotification(hDlg, lParam);
}
switch (pHdr->code) {
case PSN_SETACTIVE:
{
SendMessage(hDlg, WM_USER_MATCHINGTREE_REFRESH, 0, 0);
LPARAM buttons = PSWIZB_BACK;
s_bIsLUARedirectFSPresent = FALSE;
if (TYPE_APPHELPWIZARD == g_pCurrentWizard->m_uType) {
buttons |= PSWIZB_NEXT;
} else {
//
// Check if the user has selected either the LUA layer or the LUARedirectFS
// shim; if so we need to ask if he wants to customize LUA settings now.
//
if (IsLUARedirectFSPresent(&g_pCurrentWizard->m_Entry)) {
buttons |= PSWIZB_NEXT;
s_bIsLUARedirectFSPresent = TRUE;
} else {
buttons |= PSWIZB_FINISH;
}
}
SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, buttons);
//
// We processed the message and everything is OK. The value should be FALSE
//
ipReturn = FALSE;
}
break;
case PSN_WIZBACK:
{
CSTRING szFile = g_pCurrentWizard->m_Entry.strFullpath;
szFile.ShortFilename();
SetMask(s_hwndTree);
//
// Remove the matching info for the current file if it exists. Otherwise,
// it's possible that if the file is changed, we'll have bogus information
// about it.
//
PMATCHINGFILE pWalk = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
PMATCHINGFILE pPrev = NULL;
while (NULL != pWalk && !g_pCurrentWizard->m_bEditing) { // Only if not in editing mode
if (pWalk->strMatchName == szFile || pWalk->strMatchName == TEXT("*")) {
//
// Remove this entry.
//
if (pWalk == g_pCurrentWizard->m_Entry.pFirstMatchingFile) {
g_pCurrentWizard->m_Entry.pFirstMatchingFile = g_pCurrentWizard->m_Entry.pFirstMatchingFile->pNext;
} else {
assert(pPrev);
pPrev->pNext = pWalk->pNext;
}
g_pCurrentWizard->dwMaskOfMainEntry = pWalk->dwMask;
delete (pWalk);
break;
}
pPrev = pWalk;
pWalk = pWalk->pNext;
}
ipReturn = FALSE;
}
break;
case PSN_WIZFINISH:
case PSN_WIZNEXT:
{
PMATCHINGFILE pMatch = NULL;
ipReturn = FALSE;
//
// Set the mask for all the matching files.
//
SetMask(s_hwndTree);
if (TYPE_APPHELPWIZARD == g_pCurrentWizard->m_uType) {
ipReturn = TRUE;
break;
}
if (s_bIsLUARedirectFSPresent) {
ipReturn = !AddCheckLUAPage(pHdr->hwndFrom);
}
break;
}
}
return ipReturn;
}
INT_PTR
SelectFilesDlgOnCommand(
IN HWND hDlg,
IN WPARAM wParam
)
/*++
SelectFilesDlgOnCommand
Desc: The handler of WM_COMMAND for the matching files wizard page
Params:
IN HWND hDlg: The matching files wizard page
IN WPARAM wParam: The wParam that comes with WM_COMMAND
Return:
TRUE: We processed the message
FALSE: Otherwise
--*/
{
INT_PTR ipReturn = TRUE;
switch (LOWORD(wParam)) {
case IDC_GENERATE:
{
HCURSOR hRestore;
hRestore = SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// Do the actual task of generating the matching files
//
g_pCurrentWizard->GrabMatchingInfo(hDlg);
SetCursor(hRestore);
break;
}
case IDC_ADDFILES:
{
CSTRING szFilename;
HWND hwndFocus = GetFocus();
TCHAR szBuffer[512] = TEXT("");
GetString(IDS_EXEALLFILTER, szBuffer, ARRAYSIZE(szBuffer));
if (g_pCurrentWizard->CheckAndSetLongFilename(hDlg, IDS_GETPATH_ADD) == FALSE) {
break;
}
if (GetFileName(hDlg,
CSTRING(IDS_FINDMATCHINGFILE),
szBuffer,
TEXT(""),
GetString(IDS_EXE_EXT),
OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
TRUE,
szFilename)) {
szFilename.ConvertToLongFileName();
CSTRING szCheck = szFilename;
//
// Is this on the same drive as the original file
//
if (szCheck.RelativeFile(g_pCurrentWizard->m_Entry.strFullpath) == FALSE) {
//
// The matching file is not on the same drive as the program
// file being fixed
//
MessageBox(hDlg,
GetString(IDS_NOTSAMEDRIVE),
g_szAppName,
MB_ICONWARNING);
break;
}
HandleAddMatchingFile(hDlg, szFilename, szCheck);
}
SetFocus(hwndFocus);
}
break;
case IDC_REMOVEALL:
{
PMATCHINGFILE pMatch = NULL;
TVITEM Item;
HTREEITEM hItem;
HTREEITEM hItemNext;
g_pCurrentWizard->m_Entry.pFirstMatchingFile;
SendMessage(s_hwndTree, WM_SETREDRAW, FALSE, 0);
hItem = TreeView_GetChild(s_hwndTree, TVI_ROOT), hItemNext;
while (hItem) {
hItemNext = TreeView_GetNextSibling(s_hwndTree, hItem);
Item.mask = TVIF_PARAM;
Item.hItem = hItem;
if (!TreeView_GetItem(s_hwndTree, &Item)) {
assert(FALSE);
goto Next;
}
pMatch = (PMATCHINGFILE)Item.lParam;
if (pMatch == NULL) {
assert(FALSE);
Dbg(dlError, "SelectFilesDlgOnCommand", "pMatch == NULL");
break;
}
if (pMatch->strMatchName != TEXT("*")) {
//
// Must not delete the entry for the exe being fixed
//
TreeView_SelectItem(s_hwndTree, hItem);
SendMessage(hDlg, WM_COMMAND, IDC_REMOVEFILES, 0);
}
Next:
hItem = hItemNext;
}
SendMessage(s_hwndTree, WM_SETREDRAW, TRUE, 0);
}
break;
case IDC_REMOVEFILES:
{
PMATCHINGFILE pWalk;
PMATCHINGFILE pHold;
PMATCHINGFILE pMatch;
HTREEITEM hItem = TreeView_GetSelection(GetDlgItem(hDlg, IDC_FILELIST));
TVITEM Item;
//
// To be a matching file an item should be a root element,
// otherwise it is an attribute
//
if (NULL != hItem && TreeView_GetParent(s_hwndTree, hItem) == NULL) {
Item.mask = TVIF_PARAM;
Item.hItem = hItem;
if (!TreeView_GetItem(GetDlgItem(hDlg, IDC_FILELIST), &Item)) {
break;
}
pMatch = (PMATCHINGFILE)Item.lParam;
assert(pMatch);
if (pMatch->strMatchName == TEXT("*")) {
//
// This is the program file being fixed. This cannot be removed
//
MessageBox(hDlg,
CSTRING(IDS_REQUIREDFORMATCHING),
g_szAppName,
MB_ICONINFORMATION);
break;
}
pWalk = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
//
// NOTE: The lparam for the items in the tree should be to the corresponding PMATCHINGFILE
//
while (NULL != pWalk) {
if (pWalk == (PMATCHINGFILE)Item.lParam) {
break;
}
pHold = pWalk;
pWalk = pWalk->pNext;
}
if (pWalk == g_pCurrentWizard->m_Entry.pFirstMatchingFile) {
//
// Delete first matching file
//
g_pCurrentWizard->m_Entry.pFirstMatchingFile = pWalk->pNext;
} else {
pHold->pNext = pWalk->pNext;
}
delete pWalk;
TreeView_DeleteItem(s_hwndTree, hItem);
} else {
//
// No matching file has been selected, need to select one for deletion
//
MessageBox(hDlg,
CSTRING(IDS_SELECTMATCHFIRST),
g_szAppName,
MB_ICONWARNING);
}
}
break;
case IDC_SELECTALL:
case IDC_UNSELECTALL:
{
BOOL bSelect = (LOWORD(wParam) == IDC_SELECTALL);
HTREEITEM hItem = TreeView_GetSelection(s_hwndTree);
HTREEITEM hItemParent;
if (hItem == NULL) {
//
// No matching file has been selected
//
MessageBox(hDlg,
CSTRING(IDS_SELECTMATCHFIRST),
g_szAppName,
MB_ICONWARNING);
break;
}
hItemParent = TreeView_GetParent(s_hwndTree, hItem);
if (hItemParent != NULL) {
hItem = hItemParent;
}
hItemParent = hItem; // So that we can expand this one.
//
// Now for all the attributes of this matching file
//
hItem = TreeView_GetChild(s_hwndTree, hItem);
while (hItem) {
TreeView_SetCheckState(s_hwndTree, hItem, bSelect);
hItem = TreeView_GetNextSibling(s_hwndTree, hItem);
}
TreeView_Expand(s_hwndTree, hItemParent, TVM_EXPAND);
}
break;
case IDC_SHOWALLATTR:
if (!g_pCurrentWizard->m_bEditing) {
break;
}
//
// Show all the attributes of all the files
//
HandleShowAllAtrr(hDlg);
break;
default:
ipReturn = FALSE;
}
return ipReturn;
}
INT_PTR
SelectFilesDlgOnMatchingTreeRefresh(
IN HWND hDlg
)
/*++
SelectFilesDlgOnMatchingTreeRefresh
Desc: Refreshes the matching tree
Params:
IN HWND hDlg: The matching files wizard page
Return:
TRUE
--*/
{
PMATCHINGFILE pMatch = g_pCurrentWizard->m_Entry.pFirstMatchingFile;
BOOL bMainFound = FALSE;
SendMessage(s_hwndTree, WM_SETREDRAW, FALSE, 0);
TreeView_DeleteAllItems(s_hwndTree);
while (NULL != pMatch) {
if (pMatch->strMatchName == TEXT("*")) {
bMainFound = TRUE;
}
AddMatchingFileToTree(s_hwndTree, pMatch, FALSE);
pMatch = pMatch->pNext;
}
if (bMainFound == FALSE) {
//
// The matching file for program being fixed is not there, let us add it
//
HandleAddMatchingFile(hDlg,
g_pCurrentWizard->m_Entry.strFullpath,
g_pCurrentWizard->m_Entry.strExeName,
g_pCurrentWizard->dwMaskOfMainEntry);
}
SendMessage(s_hwndTree, WM_SETREDRAW, TRUE, 0);
return TRUE;
}