windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/tools/upgwiz/upgwiz.c

1562 lines
36 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
upgwiz.c
Abstract:
Implements a stub tool that is designed to run with Win9x-side
upgrade code.
Author:
<full name> (<alias>) <date>
Revision History:
ovidiut 01/14/99 Reverted calls to underlying libs in pCallEntryPoints ()
when Reason == DLL_PROCESS_DETACH
--*/
#include "pch.h"
typedef UINT (GIVEVERSION_PROTOTYPE) (VOID);
typedef GIVEVERSION_PROTOTYPE * GIVEVERSION;
typedef PDATATYPE (GIVEDATATYPELIST_PROTOTYPE)(PUINT Count);
typedef BOOL (GATHERINFOUI_PROTOTYPE)(HINSTANCE LocalDllInstance, UINT DataTypeId);
typedef GATHERINFOUI_PROTOTYPE * GATHERINFOUI;
typedef GIVEDATATYPELIST_PROTOTYPE * GIVEDATATYPELIST;
typedef PDATAOBJECT (GIVEDATAOBJECTLIST_PROTOTYPE)(UINT DataTypeId, PUINT Count);
typedef GIVEDATAOBJECTLIST_PROTOTYPE * GIVEDATAOBJECTLIST;
typedef BOOL (HANDLE_RMOUSE_PROTOTYPE)(HINSTANCE LocalDllInstance, HWND Owner, PDATAOBJECT DataObject, PPOINT pt);
typedef HANDLE_RMOUSE_PROTOTYPE * HANDLE_RMOUSE;
typedef BOOL (DISPLAYOPTIONALUI_PROTOTYPE)(POUTPUTARGS Args);
typedef DISPLAYOPTIONALUI_PROTOTYPE * DISPLAYOPTIONALUI;
typedef BOOL (GENERATEOUTPUT_PROTOTYPE)(POUTPUTARGS Args);
typedef GENERATEOUTPUT_PROTOTYPE * GENERATEOUTPUT;
typedef VOID (WIZTOOLSMAIN_PROTOTYPE)(DWORD Reason);
typedef WIZTOOLSMAIN_PROTOTYPE * WIZTOOLSMAIN;
typedef struct {
UINT Selection;
PDATATYPE *DataTypePtrs;
UINT PtrCount;
BOOL NoSave;
} SELECTDATAARGS, *PSELECTDATAARGS;
typedef struct {
PDATAOBJECT DataObjectArray;
UINT ArraySize;
PCSTR Name;
BOOL SelectOneOnly;
PBOOL StartOverFlag;
} SELECTOBJECTSARGS, *PSELECTOBJECTSARGS;
typedef struct {
PCSTR TextTitle;
PCSTR DescTitle;
PCSTR *NewText;
PCSTR *NewDesc;
UINT MaxSize;
PCSTR DataTypeName;
PCSTR DataObjectName;
BOOL NoDesc;
BOOL ReqDesc;
BOOL NoText;
BOOL ReqText;
PBOOL StartOverFlag;
} SUPPLYTEXTARGS, *PSUPPLYTEXTARGS;
typedef struct {
HANDLE Library;
GIVEVERSION GiveVersion;
GIVEDATATYPELIST GiveDataTypeList;
GATHERINFOUI GatherInfoUI;
GIVEDATAOBJECTLIST GiveDataObjectList;
HANDLE_RMOUSE Handle_RMouse;
DISPLAYOPTIONALUI DisplayOptionalUI;
GENERATEOUTPUT GenerateOutput;
PDATATYPE DataTypes;
UINT DataTypeCount;
PDATAOBJECT DataObjects;
UINT DataObjectCount;
} DGDLL, *PDGDLL;
UINT g_Selections;
CHAR g_Msg[2048];
PCSTR g_DataPath = "\\\\popcorn\\public\\win9xupg";
GROWBUFFER g_DllList;
POOLHANDLE g_DllListData;
PCSTR g_SrcInfPath = NULL;
PCSTR g_DestPath = NULL;
static CHAR g_ModulePath[MAX_MBCHAR_PATH];
static CHAR g_CleanThisDir[MAX_MBCHAR_PATH];
BOOL g_DontSave;
PDGDLL g_CurrentDll = NULL;
WIZTOOLSMAIN g_WizToolsMainProc = NULL;
UINT
pSelectDataType (
IN PDATATYPE *DataTypePtrs,
IN UINT PtrCount,
OUT PBOOL DontSave
);
BOOL
pSelectDataObjects (
IN OUT PDATAOBJECT DataObjectArray,
IN UINT ArraySize,
IN PDATATYPE DataType,
OUT PBOOL StartOverFlag
);
BOOL
pGetOptionalText (
IN PCSTR TextTitle, OPTIONAL
IN PCSTR DescTitle, OPTIONAL
IN PCSTR *NewDesc,
IN PCSTR *Buffer,
IN UINT MaxSize,
IN PDATATYPE DataType,
IN PDATAOBJECT DataObject, OPTIONAL
OUT PBOOL StartOverFlag
);
VOID
pThankYouBox (
IN PBOOL StartOverFlag
);
VOID
pFreeDllList (
IN OUT PGROWBUFFER List,
IN POOLHANDLE Buffer
);
HANDLE g_hHeap;
HINSTANCE g_hInst;
PSTR g_WinDir;
BOOL WINAPI MemDb_Entry (HINSTANCE, DWORD, PVOID);
BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
BOOL WINAPI FileEnum_Entry (HINSTANCE, DWORD, PVOID);
BOOL
pCallEntryPoints (
DWORD Reason
)
{
HINSTANCE Instance;
static CHAR WinDir[MAX_PATH];
GetWindowsDirectory (WinDir, MAX_PATH);
g_WinDir = WinDir;
//
// Simulate DllMain
//
Instance = g_hInst;
//
// Initialize the common libs
//
if (Reason == DLL_PROCESS_ATTACH) {
if (!MigUtil_Entry (Instance, Reason, NULL)) {
return FALSE;
}
if (!MemDb_Entry (Instance, Reason, NULL)) {
return FALSE;
}
if (!FileEnum_Entry (Instance, Reason, NULL)) {
return FALSE;
}
} else if (Reason == DLL_PROCESS_DETACH) {
if (!FileEnum_Entry (Instance, Reason, NULL)) {
return FALSE;
}
if (!MemDb_Entry (Instance, Reason, NULL)) {
return FALSE;
}
if (!MigUtil_Entry (Instance, Reason, NULL)) {
return FALSE;
}
}
return TRUE;
}
BOOL CALLBACK
pSetDefGuiFontProc(
IN HWND hwnd,
IN LPARAM lParam)
{
SendMessage(hwnd, WM_SETFONT, lParam, 0L);
return TRUE;
}
void
pSetDefGUIFont(
IN HWND hdlg
)
{
EnumChildWindows(hdlg, pSetDefGuiFontProc, (LPARAM)GetStockObject(DEFAULT_GUI_FONT));
}
BOOL
Init (
VOID
)
{
g_hHeap = GetProcessHeap();
g_hInst = GetModuleHandle (NULL);
return pCallEntryPoints (DLL_PROCESS_ATTACH);
}
VOID
Terminate (
VOID
)
{
if (g_CleanThisDir[0]) {
DeleteDirectoryContents (g_CleanThisDir);
RemoveDirectory (g_CleanThisDir);
}
pCallEntryPoints (DLL_PROCESS_DETACH);
}
BOOL
pLoadDataGatherDlls (
BOOL FirstTimeInit,
BOOL Local
);
VOID
pTryToLoadNewUpgWiz (
VOID
);
BOOL
pDoTheWizard (
VOID
);
VOID
HelpAndExit (
VOID
)
{
printf ("Command Line Syntax:\n\n"
"upgwiz [-l] [-n:path] [-i:src_inf_path] [-d:path]\n\n"
"-l Specifies local mode\n"
"-n Specifies network path\n"
"-i Specifies the source INF path\n"
"-d Specifies destination path\n"
);
exit(1);
}
INT
__cdecl
main (
INT argc,
CHAR *argv[]
)
{
CHAR ModulePath[MAX_MBCHAR_PATH];
BOOL Local = FALSE;
INT i;
PSTR p;
BOOL Loop;
BOOL FirstTimeInit = TRUE;
if (!Init()) {
printf ("Unable to initialize!\n");
return 255;
}
GetCurrentDirectory (MAX_MBCHAR_PATH, ModulePath);
GetModuleFileName (g_hInst, g_ModulePath, MAX_MBCHAR_PATH);
p = _mbsrchr (g_ModulePath, '\\');
*p = 0;
wsprintf (ModulePath, TEXT("%s\\wiztools.dll"), g_ModulePath);
if (DoesFileExist (ModulePath)) {
Local = TRUE;
}
if (GetDriveType (g_ModulePath) == DRIVE_REMOVABLE) {
Local = TRUE;
}
if (StringIMatch (g_ModulePath, g_DataPath)) {
wsprintf (g_Msg, "This tool cannot be run from %s.", g_DataPath);
MessageBox (NULL, g_Msg, NULL, MB_OK);
return 255;
}
for (i = 1 ; i < argc ; i++) {
if (argv[i][0] == '-' || argv[i][0] == '/') {
switch (tolower (argv[i][1])) {
case 'l':
Local = TRUE;
g_DataPath = g_ModulePath;
break;
case 'n':
if (argv[i][2] == ':') {
g_DataPath = &argv[i][3];
} else if (i + 1 < argc) {
g_DataPath = argv[i + 1];
} else {
HelpAndExit();
}
if (!DoesFileExist (g_DataPath)) {
printf ("Can't access %s\n", g_DataPath);
exit (2);
}
break;
case 'i':
if (argv[i][2] == ':') {
g_SrcInfPath = &argv[i][3];
} else if (i + 1 < argc) {
g_SrcInfPath = argv[i + 1];
} else {
HelpAndExit();
}
if (!DoesFileExist (g_SrcInfPath)) {
printf ("Can't access %s\n", g_SrcInfPath);
exit (2);
}
break;
case 'd':
if (argv[i][2] == ':') {
g_DestPath = &argv[i][3];
} else if (i + 1 < argc) {
g_DestPath = argv[i + 1];
} else {
HelpAndExit();
}
if (!DoesFileExist (g_DestPath)) {
printf ("Can't access %s\n", g_DestPath);
exit (2);
}
break;
default:
HelpAndExit();
}
} else {
HelpAndExit();
}
}
if (!g_SrcInfPath) {
g_SrcInfPath = g_DataPath;
}
if (!g_DestPath) {
g_DestPath = g_DataPath;
}
printf ("Src Path: %s\n", g_SrcInfPath);
printf ("Dest Path: %s\n", g_DestPath);
Loop = FALSE;
do {
if (!pLoadDataGatherDlls (FirstTimeInit, Local)) {
wsprintf (g_Msg, "Can't load any DLLs from %s.", g_DataPath);
MessageBox (NULL, g_Msg, NULL, MB_OK);
} else {
FirstTimeInit = FALSE;
Loop = pDoTheWizard();
}
} while (Loop);
Terminate();
if (g_WizToolsMainProc) {
g_WizToolsMainProc (DLL_PROCESS_DETACH);
}
return 0;
}
VOID
pCreateDllList (
OUT PGROWBUFFER List,
OUT POOLHANDLE *Buffer
)
{
ZeroMemory (List, sizeof (GROWBUFFER));
*Buffer = PoolMemInitNamedPool ("DLL List");
}
BOOL
pCopyBinaryToTemp (
IN PCSTR DllPath,
OUT PSTR TempPath
)
{
if (!g_CleanThisDir[0]) {
StringCopy (TempPath, g_WinDir);
StringCopy (AppendWack (TempPath), "upgwiz");
MakeSurePathExists (TempPath, TRUE);
StringCopy (g_CleanThisDir, TempPath);
} else {
StringCopy (TempPath, g_CleanThisDir);
}
StringCopy (AppendWack (TempPath), GetFileNameFromPath (DllPath));
if (DoesFileExist (TempPath)) {
return TRUE;
}
if (!CopyFile (DllPath, TempPath, FALSE)) {
wsprintf (
g_Msg,
"Can't copy %s to %s. If the network is working fine, the file "
"may already have been copied and is running already, or you "
"may need to update your copy of upgwiz.exe.",
DllPath,
TempPath
);
MessageBox (NULL, g_Msg, NULL, MB_OK);
return FALSE;
} else {
printf ("%s copied to %s\n", DllPath, TempPath);
}
return TRUE;
}
BOOL
pPutDllInList (
IN OUT PGROWBUFFER List,
IN OUT POOLHANDLE Buffer,
IN PCSTR DllPath
)
{
DGDLL Dll;
PDGDLL FinalDll;
BOOL b = FALSE;
CHAR TempPath[MAX_MBCHAR_PATH];
ZeroMemory (&Dll, sizeof (Dll));
__try {
pCopyBinaryToTemp (DllPath, TempPath);
Dll.Library = LoadLibraryEx (TempPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!Dll.Library) {
DWORD rc;
rc = GetLastError();
__leave;
}
Dll.GiveVersion = (GIVEVERSION) GetProcAddress (Dll.Library, "GiveVersion");
Dll.GiveDataTypeList = (GIVEDATATYPELIST) GetProcAddress (Dll.Library, "GiveDataTypeList");
Dll.GatherInfoUI = (GATHERINFOUI) GetProcAddress (Dll.Library, "GatherInfoUI");
Dll.GiveDataObjectList = (GIVEDATAOBJECTLIST) GetProcAddress (Dll.Library, "GiveDataObjectList");
Dll.Handle_RMouse = (HANDLE_RMOUSE) GetProcAddress (Dll.Library, "Handle_RMouse");
Dll.DisplayOptionalUI = (DISPLAYOPTIONALUI) GetProcAddress (Dll.Library, "DisplayOptionalUI");
Dll.GenerateOutput = (GENERATEOUTPUT) GetProcAddress (Dll.Library, "GenerateOutput");
if (!Dll.GiveVersion || !Dll.GiveDataTypeList ||
!Dll.GiveDataObjectList || !Dll.GenerateOutput
) {
__leave;
}
if (Dll.GiveVersion() != UPGWIZ_VERSION) {
__leave;
}
b = TRUE;
}
__finally {
if (!b) {
if (Dll.Library) {
FreeLibrary (Dll.Library);
}
}
}
if (b) {
FinalDll = (PDGDLL) GrowBuffer (List, sizeof (DGDLL));
CopyMemory (FinalDll, &Dll, sizeof (Dll));
}
return b;
}
VOID
pFreeDllList (
IN OUT PGROWBUFFER List,
IN POOLHANDLE Buffer
)
{
UINT Count;
PDGDLL Dll;
Dll = (PDGDLL) List->Buf;
Count = List->End / sizeof (DGDLL);
while (Count > 0) {
Count--;
FreeLibrary (Dll->Library);
Dll++;
}
FreeGrowBuffer (List);
PoolMemDestroyPool (Buffer);
}
BOOL
pLoadDataGatherDlls (
BOOL FirstTimeInit,
BOOL Local
)
{
FILE_ENUM e;
BOOL b = FALSE;
CHAR HelperBin[MAX_MBCHAR_PATH];
CHAR TempPath[MAX_MBCHAR_PATH];
HINSTANCE Library;
CHAR wiztoolsPath[MAX_MBCHAR_PATH];
if (Local || !DoesFileExist (g_DataPath)) {
g_DataPath = g_ModulePath;
}
pCreateDllList (&g_DllList, &g_DllListData);
wsprintf (wiztoolsPath, "%s\\wiztools.dll", g_DataPath);
if (!Local) {
//
// Copy everything that is needed to run this app
//
wsprintf (HelperBin, "%s\\msvcrt.dll", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
wsprintf (HelperBin, "%s\\twid.exe", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
wsprintf (HelperBin, "%s\\setupapi.dll", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
wsprintf (HelperBin, "%s\\cfgmgr32.dll", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
wsprintf (HelperBin, "%s\\imagehlp.dll", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
wsprintf (HelperBin, "%s\\wiztools.dll", g_DataPath);
pCopyBinaryToTemp (HelperBin, TempPath);
StringCopy (wiztoolsPath, TempPath);
}
if (FirstTimeInit) {
Library = LoadLibraryEx (wiztoolsPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
g_WizToolsMainProc = (WIZTOOLSMAIN) GetProcAddress (Library, "WizToolsMain");
if (g_WizToolsMainProc) {
g_WizToolsMainProc (DLL_PROCESS_ATTACH);
}
}
if (EnumFirstFile (&e, g_DataPath, "*.dll")) {
do {
if (StringIMatch (e.FileName, "setupapi.dll") ||
StringIMatch (e.FileName, "cfgmgr32.dll") ||
StringIMatch (e.FileName, "wiztools.dll") ||
StringIMatch (e.FileName, "msvcrt.dll") ||
StringIMatch (e.FileName, "imagehlp.dll")
) {
continue;
}
if (pPutDllInList (&g_DllList, g_DllListData, e.FullPath)) {
b = TRUE;
}
} while (EnumNextFile (&e));
}
if (!b) {
pFreeDllList (&g_DllList, g_DllListData);
g_DllListData = NULL;
}
return b;
}
VOID
pTryToLoadNewUpgWiz (
VOID
)
{
CHAR TempExe[MAX_MBCHAR_PATH];
CHAR PopcornExe[MAX_MBCHAR_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
StringCopy (PopcornExe, g_DataPath);
StringCopy (AppendWack (PopcornExe), "upgwiz.exe");
if (!pCopyBinaryToTemp (PopcornExe, TempExe)) {
return;
}
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
si.dwFlags = STARTF_FORCEOFFFEEDBACK;
CreateProcessA (
NULL,
TempExe,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
g_DataPath,
&si,
&pi
);
}
BOOL
pDoTheWizard (
VOID
)
{
GROWBUFFER DataTypes = GROWBUF_INIT;
UINT Count;
UINT Pos;
PDGDLL Dll;
PDATATYPE DataTypeList;
PDATATYPE *Ptr;
PDATAOBJECT DataObjectList;
UINT DataObjectCount;
UINT DataTypeListSize;
UINT u;
OUTPUTARGS Args;
PDATAOBJECT SelectedDataObject;
BOOL StartOverFlag = FALSE;
BOOL Saved;
ZeroMemory (&Args, sizeof (Args));
Dll = (PDGDLL) g_DllList.Buf;
Count = g_DllList.End / sizeof (DGDLL);
for (Pos = 0 ; Pos < Count ; Pos++) {
DataTypeListSize = 0;
DataTypeList = Dll[Pos].GiveDataTypeList (&DataTypeListSize);
if (!DataTypeList) {
DataTypeListSize = 0;
}
for (u = 0 ; u < DataTypeListSize ; u++) {
Ptr = (PDATATYPE *) GrowBuffer (&DataTypes, sizeof (PDATATYPE));
*Ptr = &DataTypeList[u];
(*Ptr)->Reserved = (PVOID) Pos;
}
}
if (DataTypes.End == 0) {
MessageBox (NULL, "No data type DLLs to select from. There may be network access problems.", NULL, MB_OK);
return FALSE;
}
__try {
//
// User selects data type
//
Pos = pSelectDataType ((PDATATYPE *) DataTypes.Buf, DataTypes.End / sizeof (PDATATYPE), &g_DontSave);
if (Pos == 0xffffffff) {
__leave;
}
DataTypeList = ((PDATATYPE *) DataTypes.Buf)[Pos];
//
// Get the data objects
//
DataObjectCount = 0;
Dll = (PDGDLL) g_DllList.Buf;
Dll += (UINT) DataTypeList->Reserved;
g_CurrentDll = Dll;
//
// Gather Info UI
//
if (Dll->GatherInfoUI) {
if (!Dll->GatherInfoUI (Dll->Library, DataTypeList->DataTypeId)) {
__leave;
}
}
if (!(DataTypeList->Flags & (DTF_NO_DATA_OBJECT))) {
TurnOnWaitCursor();
DataObjectList = Dll->GiveDataObjectList (DataTypeList->DataTypeId, &DataObjectCount);
TurnOffWaitCursor();
if (!DataObjectList || !DataObjectCount) {
MessageBox (NULL, "There are no items of this type to choose from.", NULL, MB_OK);
StartOverFlag = TRUE;
__leave;
}
//
// User selects them here
//
if (!pSelectDataObjects (DataObjectList, DataObjectCount, DataTypeList, &StartOverFlag)) {
__leave;
}
}
//
// Display Optional UI
//
Args.Version = UPGWIZ_VERSION;
Args.InboundInfDir = g_SrcInfPath;
Args.OutboundDir = g_DestPath;
Args.DataTypeId = DataTypeList->DataTypeId;
Args.StartOverFlag = &StartOverFlag;
if (Dll->DisplayOptionalUI) {
if (!Dll->DisplayOptionalUI (&Args)) {
__leave;
}
}
//
// Optional text
//
if (DataTypeList->Flags & (DTF_REQUEST_TEXT|DTF_REQUEST_DESCRIPTION)) {
SelectedDataObject = NULL;
for (u = 0 ; u < DataObjectCount ; u++) {
if (DataObjectList[u].Flags & DOF_SELECTED) {
if (SelectedDataObject) {
SelectedDataObject = NULL;
break;
}
SelectedDataObject = &DataObjectList[u];
}
}
Args.OptionalText = MemAlloc (g_hHeap, 0, DataTypeList->MaxTextSize + 1);
Args.OptionalDescription = MemAlloc (g_hHeap, 0, 81);
if (!pGetOptionalText (
DataTypeList->OptionalTextTitle,
DataTypeList->OptionalDescTitle,
&Args.OptionalDescription,
&Args.OptionalText,
DataTypeList->MaxTextSize,
DataTypeList,
SelectedDataObject,
&StartOverFlag
)) {
__leave;
}
if (*Args.OptionalText == 0) {
MemFree (g_hHeap, 0, Args.OptionalText);
Args.OptionalText = NULL;
}
if (*Args.OptionalDescription == 0) {
MemFree (g_hHeap, 0, Args.OptionalDescription);
Args.OptionalDescription = NULL;
}
}
//
// Generate the output
//
Args.Version = UPGWIZ_VERSION;
Args.InboundInfDir = g_SrcInfPath;
Args.OutboundDir = g_DestPath;
Args.DataTypeId = DataTypeList->DataTypeId;
if (!g_DontSave) {
TurnOnWaitCursor();
if (Dll->GenerateOutput (&Args)) {
Saved = TRUE;
TurnOffWaitCursor();
} else {
TurnOffWaitCursor();
MessageBox (NULL, "An error occurred while trying to save the report information.", "Report Not Saved", MB_OK);
Saved = FALSE;
}
} else {
Saved = TRUE;
}
if (Saved) {
pThankYouBox (&StartOverFlag);
}
if (Args.OptionalText) {
MemFree (g_hHeap, 0, Args.OptionalText);
}
if (Args.OptionalDescription) {
MemFree (g_hHeap, 0, Args.OptionalDescription);
}
g_CurrentDll = NULL;
}
__finally {
//
// Done
//
pFreeDllList (&g_DllList, g_DllListData);
FreeGrowBuffer (&DataTypes);
}
return StartOverFlag;
}
BOOL
CALLBACK
pDataTypeProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static PSELECTDATAARGS Args;
PDATATYPE DataType;
UINT u;
HWND List;
UINT Index;
switch (uMsg) {
case WM_INITDIALOG:
pSetDefGUIFont(hdlg);
Args = (PSELECTDATAARGS) lParam;
List = GetDlgItem (hdlg, IDC_DT_LIST);
for (u = 0 ; u < Args->PtrCount ; u++) {
DataType = Args->DataTypePtrs[u];
Index = SendMessage (List, LB_ADDSTRING, 0, (LPARAM) DataType->Name);
SendMessage (List, LB_SETITEMDATA, Index, u);
}
CheckDlgButton (hdlg, IDC_DONT_SAVE, Args->NoSave ? BST_CHECKED : BST_UNCHECKED);
EnableWindow (GetDlgItem (hdlg, IDOK), FALSE);
return FALSE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDC_DT_LIST:
if (HIWORD (wParam) == LBN_SELCHANGE) {
EnableWindow (GetDlgItem (hdlg, IDOK), TRUE);
List = GetDlgItem (hdlg, IDC_DT_LIST);
Index = SendMessage (List, LB_GETCURSEL, 0, 0);
u = SendMessage (List, LB_GETITEMDATA, Index, 0);
DataType = Args->DataTypePtrs[u];
SetDlgItemText (hdlg, IDC_DESCRIPTION, DataType->Description);
} else if (HIWORD (wParam) == LBN_DBLCLK) {
PostMessage (hdlg, WM_COMMAND, MAKELPARAM(IDOK,BN_CLICKED), 0);
}
break;
case IDOK:
List = GetDlgItem (hdlg, IDC_DT_LIST);
Index = SendMessage (List, LB_GETCURSEL, 0, 0);
Args->Selection = SendMessage (List, LB_GETITEMDATA, Index, 0);
Args->NoSave = IsDlgButtonChecked (hdlg, IDC_DONT_SAVE);
EndDialog (hdlg, LOWORD (wParam));
break;
case IDCANCEL:
EndDialog (hdlg, LOWORD (wParam));
break;
}
break;
}
return FALSE;
}
UINT
pSelectDataType (
IN PDATATYPE *DataTypePtrs,
IN UINT PtrCount,
IN OUT PBOOL DontSave
)
{
SELECTDATAARGS Args;
Args.Selection = 0xffffffff;
Args.DataTypePtrs = DataTypePtrs;
Args.PtrCount = PtrCount;
Args.NoSave = *DontSave;
DialogBoxParam (g_hInst, MAKEINTRESOURCE(IDD_DATA_TYPE), NULL, pDataTypeProc, (LPARAM) &Args);
*DontSave = Args.NoSave;
return Args.Selection;
}
VOID
pToggleSelection (
HWND TreeView,
HTREEITEM TreeItem,
BOOL OneSelection
)
{
static HTREEITEM LastSet;
UINT State;
PDATAOBJECT DataObject;
TVITEM Item;
Item.mask = TVIF_HANDLE|TVIF_STATE|TVIF_PARAM;
Item.hItem = TreeItem;
Item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_GetItem (TreeView, &Item);
State = Item.state & TVIS_STATEIMAGEMASK;
DataObject = (PDATAOBJECT) Item.lParam;
if (State) {
if (((State >> 12) & 0x03) == 2) {
State = INDEXTOSTATEIMAGEMASK(1);
g_Selections--;
DataObject->Flags &= ~DOF_SELECTED;
} else {
if (OneSelection && g_Selections == 1) {
pToggleSelection (TreeView, LastSet, FALSE);
}
State = INDEXTOSTATEIMAGEMASK(2);
g_Selections++;
DataObject->Flags |= DOF_SELECTED;
LastSet = TreeItem;
}
Item.mask = TVIF_HANDLE|TVIF_STATE;
Item.hItem = TreeItem;
Item.state = State;
Item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_SetItem (TreeView, &Item);
InvalidateRect (TreeView, NULL, TRUE);
}
}
HTREEITEM
TreeView_FindItem (
IN HWND TreeView,
IN PCSTR String,
IN HTREEITEM Parent OPTIONAL
)
{
HTREEITEM Child;
TVITEM Item;
CHAR Buffer[1024];
if (!Parent) {
Child = TreeView_GetRoot (TreeView);
} else {
Child = TreeView_GetChild (TreeView, Parent);
}
while (Child) {
Item.mask = TVIF_TEXT|TVIF_HANDLE;
Item.hItem = Child;
Item.pszText = Buffer;
Item.cchTextMax = 1024;
TreeView_GetItem (TreeView, &Item);
if (StringIMatch (String, Buffer)) {
break;
}
Child = TreeView_GetNextSibling (TreeView, Child);
}
return Child;
}
VOID
pAddSubStringToTreeControl (
IN HWND TreeView,
IN PSTR Path,
IN BOOL Checked,
IN HTREEITEM Parent, OPTIONAL
IN LPARAM lParam
)
{
TVINSERTSTRUCT is;
PSTR p;
HTREEITEM Child;
BOOL CheckThis = FALSE;
BOOL HasBitmap = FALSE;
HTREEITEM ExistingItem;
PDATAOBJECT d = (PDATAOBJECT) lParam;
p = _mbschr (Path, '\\');
if (p && !(d->Flags & DOF_NO_SPLIT_ON_WACK)) {
*p = 0;
} else {
CheckThis = Checked;
HasBitmap = TRUE;
}
RestoreWacks (Path);
is.hParent = Parent;
is.hInsertAfter = d->Flags & DOF_NO_SORT ? TVI_LAST : TVI_SORT;
ExistingItem = TreeView_FindItem (TreeView, Path, Parent);
is.item.mask = 0;
if (!ExistingItem) {
is.item.mask = TVIF_TEXT;
is.item.pszText = Path;
} else {
is.item.mask = TVIF_HANDLE;
is.item.hItem = ExistingItem;
}
if (HasBitmap) {
is.item.mask |= TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
is.item.iImage = 0;
is.item.iSelectedImage = 1;
is.item.state = CheckThis ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1);
is.item.stateMask = TVIS_STATEIMAGEMASK;
is.item.lParam = lParam;
if (CheckThis) {
g_Selections++;
}
}
if (ExistingItem) {
if (is.item.mask) {
TreeView_SetItem (TreeView, &is.item);
}
Child = ExistingItem;
} else {
Child = TreeView_InsertItem (TreeView, &is);
}
if (p && !(d->Flags & DOF_NO_SPLIT_ON_WACK)) {
pAddSubStringToTreeControl (TreeView, p + 1, Checked, Child, lParam);
}
}
VOID
pAddStringToTreeControl (
IN HWND TreeView,
IN PCSTR Path,
IN BOOL Checked,
IN LPARAM lParam
)
{
PSTR PathCopy;
PathCopy = DuplicateText (Path);
pAddSubStringToTreeControl (TreeView, PathCopy, Checked, NULL, lParam);
FreeText (PathCopy);
}
BOOL
CALLBACK
pDataObjectProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static PSELECTOBJECTSARGS Args;
static HIMAGELIST ImageList;
static BOOL OneSelection;
UINT u;
HWND TreeView;
LPNMHDR pnmh;
TVHITTESTINFO HitTest;
HTREEITEM TreeItem;
LPNMTVKEYDOWN KeyDown;
TVITEM Item;
PDATAOBJECT DataObject;
POINT pt;
switch (uMsg) {
case WM_INITDIALOG:
pSetDefGUIFont(hdlg);
Args = (PSELECTOBJECTSARGS) lParam;
OneSelection = Args->SelectOneOnly;
if (OneSelection) {
SetDlgItemText (hdlg, IDC_DESCRIPTION, "&Select the Item to Report:");
}
SetWindowText (hdlg, Args->Name);
g_Selections = 0;
TreeView = GetDlgItem (hdlg, IDC_OBJECTS);
ImageList = ImageList_LoadImage (
g_hInst,
MAKEINTRESOURCE(IDB_TREE_IMAGES),
16,
0,
CLR_DEFAULT,
IMAGE_BITMAP,
LR_LOADTRANSPARENT
);
TreeView_SetImageList (TreeView, ImageList, TVSIL_STATE);
for (u = 0 ; u < Args->ArraySize ; u++) {
pAddStringToTreeControl (
TreeView,
Args->DataObjectArray[u].NameOrPath,
OneSelection ? FALSE : (Args->DataObjectArray[u].Flags & DOF_SELECTED) ? TRUE : FALSE,
(LPARAM) (&Args->DataObjectArray[u])
);
}
InvalidateRect (TreeView, NULL, TRUE);
EnableWindow (GetDlgItem (hdlg, IDOK), g_Selections != 0);
return FALSE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDC_START_OVER:
*Args->StartOverFlag = TRUE;
EndDialog (hdlg, LOWORD (wParam));
break;
case IDOK:
EndDialog (hdlg, LOWORD (wParam));
break;
case IDCANCEL:
EndDialog (hdlg, LOWORD (wParam));
break;
}
break;
case WM_NOTIFY:
pnmh = (LPNMHDR) lParam;
if (pnmh->code == NM_CLICK) {
GetCursorPos (&HitTest.pt);
ScreenToClient (pnmh->hwndFrom, &HitTest.pt);
TreeView_HitTest (pnmh->hwndFrom, &HitTest);
if (HitTest.flags & TVHT_ONITEMSTATEICON) {
pToggleSelection (pnmh->hwndFrom, HitTest.hItem, OneSelection);
EnableWindow (GetDlgItem (hdlg, IDOK), g_Selections != 0);
}
}
else if (pnmh->code == NM_RCLICK) {
GetCursorPos (&HitTest.pt);
pt.x = HitTest.pt.x;
pt.y = HitTest.pt.y;
ScreenToClient (pnmh->hwndFrom, &HitTest.pt);
TreeView_HitTest (pnmh->hwndFrom, &HitTest);
Item.mask = TVIF_HANDLE|TVIF_PARAM;
Item.hItem = HitTest.hItem;
TreeView_GetItem (pnmh->hwndFrom, &Item);
TreeView_SelectItem (pnmh->hwndFrom, HitTest.hItem);
DataObject = (PDATAOBJECT) Item.lParam;
if (g_CurrentDll->Handle_RMouse) {
if (g_CurrentDll->Handle_RMouse (g_CurrentDll->Library, pnmh->hwndFrom, DataObject, &pt)) {
Item.pszText = (PSTR)DataObject->NameOrPath;
Item.cchTextMax = strlen (DataObject->NameOrPath);
Item.mask = TVIF_HANDLE|TVIF_TEXT;
TreeView_SetItem (pnmh->hwndFrom, &Item);
InvalidateRect (pnmh->hwndFrom, NULL, TRUE);
}
}
}
//
// The tree control beeps with keyboard input; we have no way
// to eat the messages. This codes is disabled.
//
else if (pnmh->code == TVN_KEYDOWN && pnmh->code == 0) {
KeyDown = (LPNMTVKEYDOWN) pnmh;
if (KeyDown->wVKey == VK_SPACE) {
TreeItem = TreeView_GetSelection (pnmh->hwndFrom);
if (TreeItem) {
pToggleSelection (pnmh->hwndFrom, TreeItem, OneSelection);
EnableWindow (GetDlgItem (hdlg, IDOK), g_Selections != 0);
}
}
}
break;
case WM_DESTROY:
ImageList_Destroy (ImageList);
break;
}
return FALSE;
}
BOOL
pSelectDataObjects (
IN OUT PDATAOBJECT DataObjectArray,
IN UINT ArraySize,
IN PDATATYPE DataType,
OUT PBOOL StartOverFlag
)
{
SELECTOBJECTSARGS Args;
Args.DataObjectArray = DataObjectArray;
Args.ArraySize = ArraySize;
Args.Name = DataType->Name;
Args.SelectOneOnly = (DataType->Flags & DTF_ONE_SELECTION) != 0;
Args.StartOverFlag = StartOverFlag;
return IDOK == DialogBoxParam (
g_hInst,
MAKEINTRESOURCE(IDD_DATA_OBJECTS),
NULL,
pDataObjectProc,
(LPARAM) &Args
);
}
BOOL
CALLBACK
pSupplyTextProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static PSUPPLYTEXTARGS Args;
BOOL b;
CHAR name[MEMDB_MAX];
switch (uMsg) {
case WM_INITDIALOG:
pSetDefGUIFont(hdlg);
Args = (PSUPPLYTEXTARGS) lParam;
if (Args->TextTitle) {
SetDlgItemText (hdlg, IDC_TEXT_TITLE, Args->TextTitle);
}
if (Args->DescTitle) {
SetDlgItemText (hdlg, IDC_DESC_TITLE, Args->DescTitle);
}
SetDlgItemText (hdlg, IDC_DATA_TYPE, Args->DataTypeName);
if (Args->DataObjectName) {
StringCopy (name, Args->DataObjectName);
RestoreWacks(name);
SetDlgItemText (hdlg, IDC_SELECTION, name);
}
SendMessage (GetDlgItem (hdlg, IDC_DESCRIPTION), EM_LIMITTEXT, 80, 0);
SendMessage (GetDlgItem (hdlg, IDC_TEXT_MSG), EM_LIMITTEXT, Args->MaxSize, 0);
if (Args->NoText) {
SetDlgItemText (hdlg, IDC_TEXT_MSG, "(not applicable)");
EnableWindow (GetDlgItem (hdlg, IDC_TEXT_MSG), FALSE);
} else if (Args->NoDesc) {
SetDlgItemText (hdlg, IDC_DESCRIPTION, "(not applicable)");
EnableWindow (GetDlgItem (hdlg, IDC_DESCRIPTION), FALSE);
}
if (Args->ReqDesc || Args->ReqText) {
EnableWindow (GetDlgItem (hdlg, IDOK), FALSE);
}
return FALSE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDC_DESCRIPTION:
case IDC_TEXT_MSG:
if (HIWORD (wParam) == EN_CHANGE) {
b = !Args->ReqDesc || GetWindowTextLength (GetDlgItem (hdlg, IDC_DESCRIPTION)) != 0;
b &= !Args->ReqText || GetWindowTextLength (GetDlgItem (hdlg, IDC_TEXT_MSG)) != 0;
EnableWindow (GetDlgItem (hdlg, IDOK), b);
}
break;
case IDC_START_OVER:
*Args->StartOverFlag = TRUE;
EndDialog (hdlg, LOWORD (wParam));
break;
case IDOK:
if (Args->NoDesc) {
*((PSTR) (*Args->NewDesc)) = 0;
} else {
GetDlgItemText (hdlg, IDC_DESCRIPTION, (PSTR) (*Args->NewDesc), 81);
}
if (Args->NoText) {
*((PSTR) (*Args->NewText)) = 0;
} else {
GetDlgItemText (hdlg, IDC_TEXT_MSG, (PSTR) (*Args->NewText), Args->MaxSize + 1);
}
EndDialog (hdlg, LOWORD (wParam));
break;
case IDCANCEL:
EndDialog (hdlg, LOWORD (wParam));
break;
}
break;
}
return FALSE;
}
BOOL
pGetOptionalText (
IN PCSTR TextTitle, OPTIONAL
IN PCSTR DescTitle,
IN PCSTR *NewDesc,
IN PCSTR *NewText,
IN UINT MaxSize,
IN PDATATYPE DataType,
IN PDATAOBJECT DataObject, OPTIONAL
OUT PBOOL StartOverFlag
)
{
SUPPLYTEXTARGS Args;
BOOL b = FALSE;
Args.TextTitle = TextTitle;
Args.DescTitle = DescTitle;
Args.NewText = NewText;
Args.NewDesc = NewDesc;
Args.MaxSize = MaxSize;
Args.DataTypeName = DataType->Name;
if (DataObject) {
Args.DataObjectName = DataObject->NameOrPath;
} else {
Args.DataObjectName = NULL;
}
Args.NoDesc = ((DataType->Flags & DTF_REQUEST_DESCRIPTION) == 0);
Args.NoText = ((DataType->Flags & DTF_REQUEST_TEXT) == 0);
Args.ReqDesc = ((DataType->Flags & DTF_REQUIRE_TEXT) == DTF_REQUIRE_TEXT);
Args.ReqText = ((DataType->Flags & DTF_REQUIRE_DESCRIPTION) == DTF_REQUIRE_DESCRIPTION);
Args.StartOverFlag = StartOverFlag;
if (IDOK == DialogBoxParam (
g_hInst,
MAKEINTRESOURCE(IDD_SUPPLY_TEXT),
NULL,
pSupplyTextProc,
(LPARAM) &Args
)) {
b = TRUE;
}
return b;
}
BOOL
CALLBACK
pThankYouProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDC_START_OVER:
EndDialog (hdlg, LOWORD (wParam));
break;
case IDCANCEL:
EndDialog (hdlg, LOWORD (wParam));
break;
}
break;
}
return FALSE;
}
VOID
pThankYouBox (
IN PBOOL StartOverFlag
)
{
if (IDC_START_OVER == DialogBox (g_hInst, MAKEINTRESOURCE(IDD_DONE), NULL, pThankYouProc)) {
*StartOverFlag = TRUE;
}
}