Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1242 lines
27 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
xlui.c
Abstract:
Functions used by driver user interface DLL
Environment:
PCL-XL driver user interface
Revision History:
12/11/95 -davidx-
Created it.
mm/dd/yy -author-
description
--*/
#include "xlui.h"
CRITICAL_SECTION gSemaphore; // semaphore for protecting critical sections
HANDLE ghInstance; // handle to DLL instance
INT _debugLevel; // control the amount of debug message generated
BOOL
DllInitialize(
HANDLE hModule,
ULONG reason,
PCONTEXT pContext
)
/*++
Routine Description:
DLL initialization procedure.
Arguments:
hModule - handle to DLL module
reason - reason for the call
pContext - pointer to context (not used here)
Return Value:
TRUE if DLL is initialized successfully, FALSE if there is an error
--*/
{
switch (reason) {
case DLL_PROCESS_ATTACH:
Verbose(("DLL_PROCESS_ATTACH\n"));
_debugLevel = 1;
ghInstance = hModule;
InitializeCriticalSection(&gSemaphore);
break;
case DLL_PROCESS_DETACH:
Verbose(("DLL_PROCESS_DETACH\n"));
DeleteCriticalSection(&gSemaphore);
break;
}
return TRUE;
}
PMPD
LoadMpdFile(
HANDLE hPrinter
)
/*++
Routine Description:
Load printer description data into memory
Arguments:
hPrinter - Specifies the printer we're interested in
Return Value:
Pointer to printer description data, NULL if there is an error
--*/
{
PMPD pmpd = NULL;
PDRIVER_INFO_2 pDriverInfo2 = NULL;
//
// Get the name of the driver data file and
// load printer description data into memory
//
if (pDriverInfo2 = MyGetPrinterDriver(hPrinter, 2)) {
Verbose(("Printer data file: %ws\n", pDriverInfo2->pDataFile));
pmpd = MpdCreate(pDriverInfo2->pDataFile);
MemFree(pDriverInfo2);
}
return pmpd;
}
LONG
CallComPstUI(
PUIDATA pUiData,
PCOMPROPSHEETUIHEADER pComPropSheetUIHdr,
_COMPROPSHEETUIFUNC pfnNext
)
/*++
Routine Description:
Call common UI DLL entry point dynamically
Arguments:
pUiData - Pointer to our UIDATA structure
pComPropSheetUIHdr, pfnNext - Parameters passed to common UI DLL entry point
Return Value:
Return value from common UI DLL
--*/
{
HINSTANCE hInstCompstui;
FARPROC pProc;
LONG result = ERR_CPSUI_GETLASTERROR;
//
// Only need to call the ANSI version of LoadLibrary
//
static const CHAR szCompstui[] = "compstui.dll";
static const CHAR szCommonPropSheetUI[] = "CommonPropSheetUIW";
if ((hInstCompstui = LoadLibraryA(szCompstui)) &&
(pProc = GetProcAddress(hInstCompstui, szCommonPropSheetUI)))
{
pUiData->hInstCompstui = hInstCompstui;
result = (*pProc)(pComPropSheetUIHdr, pfnNext);
}
if (hInstCompstui) {
FreeLibrary(hInstCompstui);
}
return result;
}
PWSTR
DuplicateUnicodeString(
PWSTR pSrc,
HANDLE hheap
)
/*++
Routine Description:
Duplicate a Unicode string by allocating memory from the specified heap
Arguments:
pSrc - Points to the input string to be duplicated
hheap - Specifies a heap from which to allocate memory
Return Value:
Pointer to the duplicated Unicode string
NULL if there is an error
--*/
{
PWSTR pDest;
INT length;
length = sizeof(WCHAR) * (wcslen(pSrc) + 1);
if (pDest = HeapAlloc(hheap, 0, length))
memcpy(pDest, pSrc, length);
return pDest;
}
PUIDATA
FillUiData(
HANDLE hPrinter,
PDEVMODE pdmInput,
INT caller
)
/*++
Routine Description:
Fill in the global data structure used by the driver user interface
Arguments:
hPrinter - Handle to the printer
pdmInput - Pointer to input devmode, NULL if there is none
caller - Identifier who the caller is
Return Value:
Pointer to UIDATA structure, NULL if there is an error
--*/
{
PRINTER_INFO_2 *pPrinterInfo2 = NULL;
PUIDATA pUiData = NULL;
HANDLE hheap = NULL;
DWORD cbNeeded;
//
// Create a heap to manage memory
// Allocate memory to hold UIDATA structure
// Load printer description data
// Retrieve printer properties data from registry
// Get printer info from the spooler
// Copy the driver name
//
if (! (hheap = HeapCreate(0, 4096, 0)) ||
! (pUiData = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(UIDATA))) ||
! (pUiData->pmpd = LoadMpdFile(hPrinter)) ||
! GetPrinterProperties(&pUiData->prnprop, hPrinter, pUiData->pmpd) ||
! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) ||
! (pUiData->pDriverName = DuplicateUnicodeString(pPrinterInfo2->pDriverName, hheap)))
{
if (pUiData && pUiData->pmpd)
UnloadMpdFile(pUiData->pmpd);
if (hheap)
HeapDestroy(hheap);
MemFree(pPrinterInfo2);
return NULL;
}
pUiData->hPrinter = hPrinter;
pUiData->hheap = hheap;
pUiData->signature = DRIVER_SIGNATURE;
//
// Add printer-specific forms to the global forms database
//
if (! AddDriverForms(hPrinter, pUiData->pmpd)) {
Error(("Failed to add printer-specific forms\n"));
}
//
// If we're doing document properties, combine input devmode with defaults
//
if (caller == DOCPROPDLG) {
FORM_INFO_1 formInfo;
WCHAR formName[CCHFORMNAME];
//
// Start with driver default devmode
//
DriverDefaultDevmode(&pUiData->devmode, NULL, pUiData->pmpd);
//
// Merge with system defaults and the input devmode
//
if (! MergeDevmode(&pUiData->devmode, pPrinterInfo2->pDevMode, pUiData->pmpd)) {
Error(("Invalid system default devmode\n"));
}
if (! MergeDevmode(&pUiData->devmode, pdmInput, pUiData->pmpd)) {
Error(("Invalid input devmode\n"));
}
//
// Validate the form requested by the input devmode
//
if (! ValidDevmodeForm(hPrinter, &pUiData->devmode.dmPublic, &formInfo, formName)) {
Error(("Invalid form requested\n"));
}
//
// Convert public devmode fields to printer feature selections
//
DevmodeFieldsToOptions(&pUiData->devmode,
pUiData->devmode.dmPublic.dmFields,
pUiData->pmpd);
//
// Look for conflicts between feature selections
//
CombineDocumentAndPrinterFeatureSelections(pUiData->pmpd,
pUiData->devmode.dmPrivate.options,
pUiData->devmode.dmPrivate.options,
pUiData->prnprop.options);
}
MemFree(pPrinterInfo2);
return pUiData;
}
PWSTR
GetHelpFileName(
HANDLE hPrinter,
HANDLE hheap
)
/*++
Routine Description:
Return a string which contains the driver's help filename
Arguments:
hPrinter - Handle to the printer
hheap - Handle to a heap from which to allocate memory
Return Value:
Pointer to the driver help filename, NULL if there is an error
--*/
{
static WCHAR HelpFileName[] = L"\\XLDRV.HLP";
PDRIVER_INFO_3 pDriverInfo3 = NULL;
PWSTR pHelpFile = NULL;
PWSTR pDriverDirectory;
//
// Attempt to get help file name using the new DRIVER_INFO_3
//
if ((pDriverInfo3 = MyGetPrinterDriver(hPrinter, 3)) && pDriverInfo3->pHelpFile)
pHelpFile = DuplicateUnicodeString(pDriverInfo3->pHelpFile, hheap);
MemFree(pDriverInfo3);
if (pHelpFile)
return pHelpFile;
//
// If DRIVER_INFO_3 isn't supported, generate help file name by
// concatenating the driver directory with hardcoded help filename.
//
if (pDriverDirectory = MyGetPrinterDriverDirectory(NULL, 1)) {
INT size = sizeof(HelpFileName) + sizeof(WCHAR) * (wcslen(pDriverDirectory) + 1);
if (pHelpFile = HeapAlloc(hheap, 0, size)) {
wcscpy(pHelpFile, pDriverDirectory);
wcscat(pHelpFile, HelpFileName);
}
MemFree(pDriverDirectory);
}
return pHelpFile;
}
BOOL
PrepareDataForCommonUi(
PUIDATA pUiData,
PCOMPROPSHEETUIHEADER pComPropSheetUIHdr,
PDLGPAGE pDlgPage,
PACKPROPITEMPROC pPackItemProc
)
/*++
Routine Description:
Allocate memory and partially fill out the data structures
required to call common UI routine.
Arguments:
pUiData - Pointer to our UIDATA structure
pComPropSheetUIHdr - Pointer to COMPROPSHEETUIHEADER structure
pDlgPage - Pointer to dialog pages
pPackItemProc - Callback function to fill out OPTITEM and OPTTYPE array
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PCOMPROPSHEETUI pComPropSheetUI;
PFORM_INFO_1 pFormsDB;
PACKINFO packInfo;
DWORD cForms;
DWORD count;
HANDLE hheap = pUiData->hheap;
//
// Get a list of forms in the forms database
//
pFormsDB = GetFormsDatabase(pUiData->hPrinter, &cForms);
if (pFormsDB == NULL || cForms == 0) {
Error(("Couldn't get system forms\n"));
return FALSE;
}
FilterFormsDatabase(pFormsDB, cForms, pUiData->pmpd);
//
// Enumerate the list of supported forms
//
count = EnumPaperSizes(NULL, pUiData->pmpd, pFormsDB, cForms, DC_PAPERS);
Assert(count != GDI_ERROR);
pUiData->cFormNames = count;
pUiData->pFormNames = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(WCHAR)*count*CCHPAPERNAME);
pUiData->pPapers = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(WORD)*count);
pUiData->pPaperSelections = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(WORD)*count);
if (!pUiData->pFormNames || !pUiData->pPapers || !pUiData->pPaperSelections)
return FALSE;
EnumPaperSizes(pUiData->pFormNames, pUiData->pmpd, pFormsDB, cForms, DC_PAPERNAMES);
EnumPaperSizes(pUiData->pPapers, pUiData->pmpd, pFormsDB, cForms, DC_PAPERS);
EnumPaperSizes(pUiData->pPaperSelections, pUiData->pmpd, pFormsDB, cForms, DC_EXTRA);
MemFree(pFormsDB);
//
// Allocate memory to hold COMPROPSHEETUI data structures and initialize it
//
if (! (pComPropSheetUI = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(COMPROPSHEETUI))))
return FALSE;
pComPropSheetUIHdr->pData = pComPropSheetUI;
pComPropSheetUI->cbSize = sizeof(COMPROPSHEETUI);
pComPropSheetUI->UserData = (DWORD) pUiData;
pComPropSheetUI->pDlgPage = pDlgPage;
pComPropSheetUI->cDlgPage = 0;
pComPropSheetUI->hInstCaller = ghInstance;
pComPropSheetUI->pCallerName = (PWSTR) IDS_PCLXL_DRIVER;
pComPropSheetUI->pOptItemName = pUiData->pDriverName;
pComPropSheetUI->CallerVersion = DRIVER_VERSION;
pComPropSheetUI->OptItemVersion = 0;
pComPropSheetUI->IconID = IDI_CPSUI_PRINTER2;
if (HasPermission(pUiData))
pComPropSheetUI->Flags = CPSUIF_UPDATE_PERMISSION;
if (! (pComPropSheetUI->pHelpFile = GetHelpFileName(pUiData->hPrinter, hheap))) {
Error(("Couldn't find help file\n"));
}
//
// Count the number of treeview items
//
memset(&packInfo, 0, sizeof(packInfo));
packInfo.pUiData = pUiData;
if (! pPackItemProc(&packInfo)) {
Error(("Counting treeview items failed\n"));
return FALSE;
}
//
// Allocate memory to hold OPTITEM's and OPTTYPE's
//
Assert(packInfo.cOptItem > 0 && packInfo.cOptType > 0);
packInfo.pOptItem = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(OPTITEM)*packInfo.cOptItem);
packInfo.pOptType = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(OPTTYPE)*packInfo.cOptType);
if (!packInfo.pOptItem || !packInfo.pOptType)
return FALSE;
//
// Pack the document or printer properties information into treeview items
//
packInfo.cOptItem = packInfo.cOptType = 0;
pComPropSheetUI->pOptItem = packInfo.pOptItem;
if (! pPackItemProc(&packInfo)) {
Error(("Packing treeview items failed\n"));
return FALSE;
}
pComPropSheetUI->cOptItem = packInfo.cOptItem;
return TRUE;
}
WORD
FindFormNameIndex(
PUIDATA pUiData,
PWSTR pFormName
)
/*++
Routine Description:
Given a formname, find its index in the list of supported forms
Arguments:
pUiData - Pointer to our UIDATA structure
pFormName - Specifies the form name in question
Return Value:
Index of the specified form name in the list
--*/
{
WORD index;
PWSTR pName;
//
// Check if the name appears in the list
//
for (index = 0, pName = pUiData->pFormNames;
index < pUiData->cFormNames;
index ++, pName += CCHPAPERNAME)
{
if (wcscmp(pFormName, pName) == EQUAL_STRING)
return index;
}
//
// The specified form name is not found, use the first form in the list
//
return 0;
}
POPTPARAM
FillOutOptType(
POPTTYPE pOptType,
WORD type,
WORD cParams,
HANDLE hheap
)
/*++
Routine Description:
Fill out an OPTTYPE structure
Arguments:
popttype - Pointer to OPTTYPE structure to be filled out
type - Value for OPTTYPE.Type field
cParams - Number of OPTPARAM's
hheap - Handle to a heap from which to allocate
Return Value:
Pointer to OPTPARAM array if successful, NULL otherwise
--*/
{
pOptType->cbSize = sizeof(OPTTYPE);
pOptType->Count = cParams;
pOptType->Type = (BYTE) type;
pOptType->pOptParam = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(OPTPARAM) * cParams);
return pOptType->pOptParam;
}
BOOL
PackOptItemTemplate(
PPACKINFO pPackInfo,
PWORD pItemInfo,
DWORD selection
)
/*++
Routine Description:
Fill out an OPTITEM and an OPTTYPE structure using a template
Arguments:
pPackInfo - Pointer to a PACKINFO structure
pItemInfo - Pointer to item template
selection - Current item selection
Return Value:
TRUE if successful, FALSE otherwise
Note:
The item template is a variable-length WORD array:
0: String resource ID of the item title
1: Item level in the tree view (TVITEM_LEVELx)
2: Public devmode field ID (DMPUB_xxx)
3: User data
4: Help index
5: Number of OPTPARAMs for this item
6: Item type (TVOT_xxx)
Two words for each OPTPARAM:
String resource ID for parameter data
Icon resource ID
Last word must be ITEM_INFO_SIGNATURE
Both OPTITEM and OPTTYPE structures are assumed to be zero-initialized.
--*/
{
POPTITEM pOptItem;
POPTPARAM pOptParam;
WORD cOptParam;
if ((pOptItem = pPackInfo->pOptItem) != NULL) {
FILLOPTITEM(pOptItem,
pPackInfo->pOptType,
pItemInfo[0],
selection,
(BYTE) pItemInfo[1],
(BYTE) pItemInfo[2],
pItemInfo[3],
pItemInfo[4]);
cOptParam = pItemInfo[5];
pOptParam = FillOutOptType(pPackInfo->pOptType,
pItemInfo[6],
cOptParam,
pPackInfo->pUiData->hheap);
if (pOptParam == NULL)
return FALSE;
pItemInfo += 7;
while (cOptParam--) {
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->pData = (PWSTR) *pItemInfo++;
pOptParam->IconID = *pItemInfo++;
pOptParam++;
}
Assert(*pItemInfo == ITEM_INFO_SIGNATURE);
pPackInfo->pOptItem++;
pPackInfo->pOptType++;
}
pPackInfo->cOptItem++;
pPackInfo->cOptType++;
return TRUE;
}
VOID
PackOptItemGroupHeader(
PPACKINFO pPackInfo,
WORD titleId,
WORD iconId,
WORD helpIndex
)
/*++
Routine Description:
Fill out a OPTITEM to be used as a header for a group of items
Arguments:
pPackInfo - Pointer to a PACKINFO structure
titleId - String resource ID for the item title
iconId - Icon resource ID
helpIndex - Help index
Return Value:
NONE
--*/
{
if (pPackInfo->pOptItem) {
pPackInfo->pOptItem->cbSize = sizeof(OPTITEM);
pPackInfo->pOptItem->pOptType = NULL;
pPackInfo->pOptItem->pName = (PWSTR) titleId;
pPackInfo->pOptItem->Level = TVITEM_LEVEL1;
pPackInfo->pOptItem->DMPubID = DMPUB_NONE;
pPackInfo->pOptItem->Sel = iconId;
pPackInfo->pOptItem->HelpIndex = helpIndex;
pPackInfo->pOptItem++;
}
pPackInfo->cOptItem++;
}
BOOL
PackPrinterFeatureItems(
PPACKINFO pPackInfo,
WORD installable
)
/*++
Routine Description:
Create treeview items corresponding to printer features
Arguments:
pPackInfo - Points to a PACKINFO structure
installable - Whether the caller is interested in installable options
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PBYTE pOptions;
DWORD index;
WORD helpIndex, iconId;
PFEATURE pFeature;
PMPD pmpd = pPackInfo->pUiData->pmpd;
//
// Difference between installable options and document-sticky printer features
//
if (installable == FF_INSTALLABLE) {
helpIndex = HELP_INDEX_INSTALLABLE_OPTIONS;
iconId = IDI_CPSUI_INSTALLABLE_OPTION;
pOptions = pPackInfo->pUiData->prnprop.options;
} else {
Assert(installable == 0);
helpIndex = HELP_INDEX_PRINTER_FEATURES;
iconId = IDI_CPSUI_PRINTER_FEATURE;
pOptions = pPackInfo->pUiData->devmode.dmPrivate.options;
}
for (index = 0; index < pmpd->cFeatures; index++, pOptions++) {
//
// Check whether we're interested in the feature
//
pFeature = FindIndexedFeature(pmpd, index);
if ((pFeature->flags & FF_INSTALLABLE) != installable)
continue;
if (!installable && PublicFeatureIndex(pFeature->groupId))
continue;
//
// Create a new OPTITEM and OPTTYPE
//
if (pPackInfo->pOptItem) {
BYTE selection;
WORD count, index;
POPTION pOption;
POPTPARAM pOptParam;
HANDLE hheap = pPackInfo->pUiData->hheap;
selection = *pOptions;
count = pFeature->count;
//
// Figure out the current selection. For document-sticky
// features, we always insert "Printer Default" as the
// very first choice. This is represented by an option
// index value of SELIDX_ANY.
//
if (!installable) {
selection = (selection >= count) ? 0 : selection+1;
count++;
}
FILLOPTITEM(pPackInfo->pOptItem,
pPackInfo->pOptType,
GetXlatedName(pFeature),
selection,
TVITEM_LEVEL2,
DMPUB_NONE,
pFeature,
helpIndex);
if (! (pOptParam = FillOutOptType(pPackInfo->pOptType, TVOT_LISTBOX, count, hheap)))
return FALSE;
if (! installable) {
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->pData = (PVOID) IDS_PRINTER_DEFAULT;
pOptParam->IconID = IDI_CPSUI_EMPTY;
pOptParam++;
count--;
}
for (index=0; index < count; index++) {
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->IconID = iconId;
pOption = FindIndexedSelection(pFeature, index);
pOptParam->pData = GetXlatedName(pOption);
pOptParam++;
}
pPackInfo->pOptItem++;
pPackInfo->pOptType++;
}
pPackInfo->cOptItem++;
pPackInfo->cOptType++;
}
return TRUE;
}
BOOL
OptItemSelectionsChanged(
POPTITEM pItems,
WORD cItems
)
/*++
Routine Description:
Check if any of the treeview items was changed by the user
Arguments:
pItems - Points to an array of OPTITEMs
cItems - Number of items in the array
Return Value:
TRUE if any of the treeview items was changed
FALSE otherwise
--*/
{
while (cItems--) {
if (pItems->Flags & OPTIF_CHANGEONCE)
return TRUE;
pItems++;
}
return FALSE;
}
VOID
MarkSelectionConstrained(
POPTITEM pOptItem,
INT selection,
LONG lParam
)
/*++
Routine Description:
Indicate whether an item selection is constrained
Arguments:
pOptItem - Specifies the item we're interested in
selection - Specifies the selection we're interested in
lParam - Specifies what caused the constraint, or
NO_CONFLICT if the selection is not constrained
Return Value:
NONE
--*/
{
POPTPARAM pOptParam = & pOptItem->pOptType->pOptParam[selection];
if (lParam != NO_CONFLICT && !(pOptParam->Flags & CONSTRAINED_FLAG)) {
pOptParam->Flags |= CONSTRAINED_FLAG;
pOptItem->Flags |= OPTIF_CHANGED;
} else if (lParam == NO_CONFLICT && (pOptParam->Flags & CONSTRAINED_FLAG)) {
pOptParam->Flags &= ~CONSTRAINED_FLAG;
pOptItem->Flags |= OPTIF_CHANGED;
}
pOptParam->lParam = lParam;
}
PWSTR
CrackMessageString(
PWSTR wcbuf,
HINSTANCE hInstCompstui,
DWORD dwId
)
{
//
// If pName is already a pointer, return it to the caller
//
if (dwId >= 0x10000)
return (PWSTR) dwId;
//
// If pName is a string resource ID, check if it's our
// own or if it belong to common UI library.
//
wcbuf[0] = NUL;
LoadString((dwId >= IDS_CPSUI_STRID_FIRST) ? hInstCompstui : ghInstance,
(INT) dwId,
wcbuf,
MAX_OPTION_NAME);
return wcbuf;
}
// Data structure used to pass parameters to "Conflicts" dialog
typedef struct {
HINSTANCE hInstCompstui;
PMPD pmpd;
POPTITEM pOptItem;
} CONFLICTS_DLGPARAM;
BOOL
ConflictsDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
Callback procedure for handling "Conflicts" dialog
Arguments:
hDlg - Handle to dialog window
uMsg - Message
wParam, lParam - Parameters
Return Value:
TRUE or FALSE depending on whether message is processed
--*/
{
CONFLICTS_DLGPARAM *pParam;
POPTITEM pOptItem;
POPTPARAM pOptParam;
HINSTANCE hInstCompstui;
PFEATURE pFeature;
POPTION pOption;
WCHAR wcbuf[MAX_OPTION_NAME];
switch (uMsg) {
case WM_INITDIALOG:
pParam = (CONFLICTS_DLGPARAM *) lParam;
Assert(pParam != NULL);
hInstCompstui = pParam->hInstCompstui;
pOptItem = pParam->pOptItem;
pOptParam = &pOptItem->pOptType->pOptParam[pOptItem->Sel];
//
// Display the current feature and selection
//
SetDlgItemText(hDlg,
IDC_FEATURE1,
CrackMessageString(wcbuf, hInstCompstui, (DWORD) pOptItem->pName));
SetDlgItemText(hDlg,
IDC_OPTION1,
CrackMessageString(wcbuf, hInstCompstui, (DWORD) pOptParam->pData));
//
// Display the conflicting feature and selection
//
Assert(pOptParam->lParam != NO_CONFLICT);
pFeature = FindIndexedFeature(pParam->pmpd, LOWORD(pOptParam->lParam));
if (pFeature)
pOption = FindIndexedSelection(pFeature, HIWORD(pOptParam->lParam));
if (pFeature && pOption) {
SetDlgItemText(hDlg, IDC_FEATURE2, GetXlatedName(pFeature));
SetDlgItemText(hDlg, IDC_OPTION2, GetXlatedName(pOption));
}
ShowWindow(hDlg, SW_SHOW);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
EndDialog(hDlg, CONFLICT_CANCEL);
return TRUE;
case IDC_IGNORE:
EndDialog(hDlg, CONFLICT_IGNORE);
return TRUE;
case IDC_RESOLVE:
EndDialog(hDlg, CONFLICT_RESOLVE);
return TRUE;
}
}
return FALSE;
}
INT
DoCheckConstraintsDialog(
PUIDATA pUiData,
POPTITEM pOptItem,
WORD cOptItem,
INT mode
)
/*++
Routine Description:
Check if user has chosen any constrained selection
Arguments:
pUiData - Pointer to our UIDATA structure
pOptItem - Pointer to an array of OPTITEMs
cOptItem - Number of items to be checked
mode - Whether this is called before closing the dialog
Return Value:
CONFLICT_NONE - no conflicts
CONFLICT_RESOLVE - click RESOLVE to automatically resolve conflicts
CONFLICT_CANCEL - click CANCEL to back out of changes
CONFLICT_IGNORE - click IGNORE to ignore conflicts
--*/
{
CONFLICTS_DLGPARAM dlgParam;
INT dialogId, result = CONFLICT_NONE;
dlgParam.hInstCompstui = pUiData->hInstCompstui;
dlgParam.pmpd = pUiData->pmpd;
dialogId = (mode == FINAL_CHECK) ? IDD_CONFLICTS_FINAL : IDD_CONFLICTS;
for ( ; cOptItem-- && result != CONFLICT_CANCEL; pOptItem++) {
//
// If user has clicked IGNORE before, then don't bother
// checking anymore until he tries to exit the dialog.
//
if (pUiData->bIgnoreConflict && mode != FINAL_CHECK)
break;
//
// If there is a conflict, then display a warning message
// Make sure the item can be constrained at all
//
if ((pOptItem->pOptType != NULL) &&
(pOptItem->pOptType->Type == TVOT_LISTBOX ||
pOptItem->pOptType->Type == TVOT_COMBOBOX ||
pOptItem->pOptType->Type == TVOT_2STATES ||
pOptItem->pOptType->Type == TVOT_3STATES) &&
IS_CONSTRAINED(pOptItem, pOptItem->Sel))
{
dlgParam.pOptItem = pOptItem;
result = DialogBoxParam(ghInstance,
MAKEINTRESOURCE(dialogId),
pUiData->hDlg,
ConflictsDlgProc,
(LPARAM) &dlgParam);
//
// Automatically resolve conflicts. We're being very simple-minded here,
// i.e. picking the first selection that's not constrained.
//
if (result == CONFLICT_RESOLVE) {
INT index, count;
count = pOptItem->pOptType->Count;
index = 0;
while (index < count && IS_CONSTRAINED(pOptItem, index))
index++;
if (index < count) {
pOptItem->Sel = index;
pOptItem->Flags |= OPTIF_CHANGED;
} else {
Error(("Couldn't automatically resolve conflicts.\n"));
}
} else if (result == CONFLICT_IGNORE) {
pUiData->bIgnoreConflict = TRUE;
}
}
}
return result;
}