diff options
Diffstat (limited to 'print/OEM Printer Customization Plug-in Samples/C++/PSUIRep/Features.cpp')
| -rw-r--r-- | print/OEM Printer Customization Plug-in Samples/C++/PSUIRep/Features.cpp | 2858 |
1 files changed, 0 insertions, 2858 deletions
diff --git a/print/OEM Printer Customization Plug-in Samples/C++/PSUIRep/Features.cpp b/print/OEM Printer Customization Plug-in Samples/C++/PSUIRep/Features.cpp deleted file mode 100644 index acee806b..00000000 --- a/print/OEM Printer Customization Plug-in Samples/C++/PSUIRep/Features.cpp +++ /dev/null @@ -1,2858 +0,0 @@ -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright 2001 - 2003 Microsoft Corporation. All Rights Reserved. -// -// FILE: Features.cpp -// -// PURPOSE: Implementation wrapper class for PScript Driver Features and Options. -// - -#include "precomp.h" -#include "resource.h" -#include "debug.h" -#include "globals.h" -#include "devmode.h" -#include "stringutils.h" -#include "helper.h" -#include "features.h" -#include "oemui.h" - -// This indicates to Prefast that this is a usermode driver file. -_Analysis_mode_(_Analysis_code_type_user_driver_); - - -//////////////////////////////////////////////////////// -// Internal Defines and Macros -//////////////////////////////////////////////////////// - -#define INITIAL_ENUM_FEATURES_SIZE 1024 -#define INITIAL_ENUM_OPTIONS_SIZE 64 -#define INITIAL_FEATURE_DISPLAY_NAME_SIZE 64 -#define INITIAL_OPTION_DISPLAY_NAME_SIZE 32 -#define INITIAL_GET_OPTION_SIZE 64 -#define INITIAL_GET_REASON_SIZE 1024 - -#define DRIVER_FEATURE_PREFIX '%' -#define IS_DRIVER_FEATURE(f) (DRIVER_FEATURE_PREFIX == (f)[0]) - -// Flags that the uDisplayNameID should be returned as -// MAKEINTRESOURCE() instead of loading the string resource. -#define RETURN_INT_RESOURCE 1 - -// Macros to test for conditions of KEYWORDMAP entry. -#define IS_MAPPING_INT_RESOURCE(p) ((p)->dwFlags & RETURN_INT_RESOURCE) - -// TAG the identifies feature OPTITEM data stuct. -#define FEATURE_OPTITEM_TAG 'FETR' - - -//////////////////////////////////////////////////////// -// Type Definitions -//////////////////////////////////////////////////////// - -// Struct used to identify OPTITEM as -// feature OPTITEM and to map back from -// an OPTITEM to the feature. -typedef struct _tagFeatureOptitemData -{ - DWORD dwSize; - DWORD dwTag; - PCSTR pszFeatureKeyword; - COptions *pOptions; - -} FEATUREOPTITEMDATA, *PFEATUREOPTITEMDATA; - - - -//////////////////////////////////////////////////////// -// Internal Constants -//////////////////////////////////////////////////////// - -static KEYWORDMAP gkmFeatureMap[] = -{ - "%AddEuro", NULL, IDS_ADD_EURO, OEMCUIP_PRNPROP, 0, - "%CtrlDAfter", NULL, IDS_CTRLD_AFTER, OEMCUIP_PRNPROP, 0, - "%CtrlDBefore", NULL, IDS_CTRLD_BEFORE, OEMCUIP_PRNPROP, 0, - //"%CustomPageSize", NULL, IDS_PSCRIPT_CUSTOMSIZE, OEMCUIP_DOCPROP, 0, - "%GraphicsTrueGray", NULL, IDS_TRUE_GRAY_GRAPH, OEMCUIP_PRNPROP, 0, - "%JobTimeout", NULL, IDS_JOBTIMEOUT, OEMCUIP_PRNPROP, 0, - "%MaxFontSizeAsBitmap", NULL, IDS_PSMAXBITMAP, OEMCUIP_PRNPROP, 0, - "%MetafileSpooling", NULL, IDS_METAFILE_SPOOLING, OEMCUIP_DOCPROP, 0, - "%MinFontSizeAsOutline", NULL, IDS_PSMINOUTLINE, OEMCUIP_PRNPROP, 0, - "%Mirroring", NULL, IDS_MIRROR, OEMCUIP_DOCPROP, 0, - "%Negative", NULL, IDS_NEGATIVE_PRINT, OEMCUIP_DOCPROP, 0, - "%Orientation", TEXT("COMPSTUI.DLL"), IDS_CPSUI_ORIENTATION, OEMCUIP_DOCPROP, RETURN_INT_RESOURCE, - "%OutputFormat", NULL, IDS_PSOUTPUT_OPTION, OEMCUIP_DOCPROP, 0, - "%OutputProtocol", NULL, IDS_PSPROTOCOL, OEMCUIP_PRNPROP, 0, - "%OutputPSLevel", NULL, IDS_PSLEVEL, OEMCUIP_DOCPROP, 0, - "%PageOrder", TEXT("COMPSTUI.DLL"), IDS_CPSUI_PAGEORDER, OEMCUIP_DOCPROP, RETURN_INT_RESOURCE, - "%PagePerSheet", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP, OEMCUIP_DOCPROP, RETURN_INT_RESOURCE, - "%PSErrorHandler", NULL, IDS_PSERROR_HANDLER, OEMCUIP_DOCPROP, 0, - "%PSMemory", NULL, IDS_POSTSCRIPT_VM, OEMCUIP_PRNPROP, 0, - "%TextTrueGray", NULL, IDS_TRUE_GRAY_TEXT, OEMCUIP_PRNPROP, 0, - "%TTDownloadFormat", NULL, IDS_PSTT_DLFORMAT, OEMCUIP_DOCPROP, 0, - "%WaitTimeout", NULL, IDS_WAITTIMEOUT, OEMCUIP_PRNPROP, 0, -}; -static const NUM_FEATURE_MAP = (sizeof(gkmFeatureMap)/sizeof(gkmFeatureMap[0])); - - -static KEYWORDMAP gkmOptionMap[] = -{ - "True", TEXT("COMPSTUI.DLL"), IDS_CPSUI_TRUE, 0, RETURN_INT_RESOURCE, - "False", TEXT("COMPSTUI.DLL"), IDS_CPSUI_FALSE, 0, RETURN_INT_RESOURCE, - "Portrait", TEXT("COMPSTUI.DLL"), IDS_CPSUI_PORTRAIT, 0, RETURN_INT_RESOURCE, - "Landscape", TEXT("COMPSTUI.DLL"), IDS_CPSUI_LANDSCAPE, 0, RETURN_INT_RESOURCE, - "RotatedLandscape", TEXT("COMPSTUI.DLL"), IDS_CPSUI_ROT_LAND, 0, RETURN_INT_RESOURCE, - "Speed", NULL, IDS_PSOPT_SPEED, 0, RETURN_INT_RESOURCE, - "Portability", NULL, IDS_PSOPT_PORTABILITY, 0, 0, - "EPS", NULL, IDS_PSOPT_EPS, 0, 0, - "Archive", NULL, IDS_PSOPT_ARCHIVE, 0, 0, - "ASCII", NULL, IDS_PSPROTOCOL_ASCII, 0, 0, - "BCP", NULL, IDS_PSPROTOCOL_BCP, 0, 0, - "TBCP", NULL, IDS_PSPROTOCOL_TBCP, 0, 0, - "Binary", NULL, IDS_PSPROTOCOL_BINARY, 0, 0, - "FrontToBack", TEXT("COMPSTUI.DLL"), IDS_CPSUI_FRONTTOBACK, 0, RETURN_INT_RESOURCE, - "BackToFront", TEXT("COMPSTUI.DLL"), IDS_CPSUI_BACKTOFRONT, 0, RETURN_INT_RESOURCE, - "1", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_NORMAL, 0, RETURN_INT_RESOURCE, - "2", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_TWOUP, 0, RETURN_INT_RESOURCE, - "4", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_FOURUP, 0, RETURN_INT_RESOURCE, - "6", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_SIXUP, 0, RETURN_INT_RESOURCE, - "9", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_NINEUP, 0, RETURN_INT_RESOURCE, - "16", TEXT("COMPSTUI.DLL"), IDS_CPSUI_NUP_SIXTEENUP, 0, RETURN_INT_RESOURCE, - "Booklet", TEXT("COMPSTUI.DLL"), IDS_CPSUI_BOOKLET, 0, RETURN_INT_RESOURCE, - "Automatic", NULL, IDS_TTDL_DEFAULT, 0, 0, - "Outline", NULL, IDS_TTDL_TYPE1, 0, 0, - "Bitmap", NULL, IDS_TTDL_TYPE3, 0, 0, - "NativeTrueType", NULL, IDS_TTDL_TYPE42, 0, 0, -}; -static const NUM_OPTION_MAP = (sizeof(gkmOptionMap)/sizeof(gkmOptionMap[0])); - - - - -//////////////////////////////////////////// -// -// COptions Methods -// - -// -// Private Methods -// - -// Initializes class data members. -void COptions::Init() -{ - m_wOptions = 0; - m_cType = TVOT_COMBOBOX; - m_pmszRaw = NULL; - m_pszFeature = NULL; - m_ppszOptions = NULL; - m_ptRange.x = 0; - m_ptRange.y = 0; - m_dwSize = 0; - m_pszUnits = NULL; - m_hHeap = NULL; - m_pInfo = NULL; -} - -void COptions::Clear() -{ - // Free memory associated with data members. - if(NULL != m_pmszRaw) HeapFree(m_hHeap, 0, m_pmszRaw); - if(NULL != m_ppszOptions) HeapFree(m_hHeap, 0, m_ppszOptions); - if( (NULL != m_pszUnits) && !IS_INTRESOURCE(m_pszUnits)) HeapFree(m_hHeap, 0, m_pszUnits); - - // Free option info. - FreeOptionInfo(); - - // Initialize data members. - Init(); -} - -// Frees memory associated with Option Info array. -void COptions::FreeOptionInfo() -{ - // Validate parameters. - if( (NULL == m_hHeap) - || - (NULL == m_pInfo) - ) - { - return; - } - - // Free strings in the array. - for(WORD wIndex = 0; wIndex < m_wOptions; ++wIndex) - { - PWSTR pszDisplay = m_pInfo[wIndex].pszDisplayName; - - if( (NULL != pszDisplay) - && - !(IS_INTRESOURCE(pszDisplay)) - ) - { - HeapFree(m_hHeap, 0, pszDisplay); - } - } - - // Free the array. - HeapFree(m_hHeap, 0, m_pInfo); - m_pInfo = NULL; -} - -// Will do init for features that need special handling. -HRESULT COptions::GetOptionsForSpecialFeatures(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - HRESULT hrResult = E_NOTIMPL; - - - // See if this is a special feature. - // If it is, then call the special option init for the - // feature. - if(!lstrcmpA(m_pszFeature, "%CustomPageSize")) - { - // There is no option init for CustomPageSize. - // The item itself must be handled specially. - hrResult = S_OK; - } - else if( !lstrcmpA(m_pszFeature, "%JobTimeout") - || - !lstrcmpA(m_pszFeature, "%WaitTimeout") - ) - { - // JobTimeout and WaitTimeout feature options are string representations - // of an integer that represents number of seconds in the range 0 through - // 2,147,483,647 (i.e. LONG_MAX). However, COMPSTUI limits us to - // WORD size, which has range of 0 to 32,767 (i.e. SHRT_MAX). - m_cType = TVOT_UDARROW; - m_ptRange.x = 0; - m_ptRange.y = SHRT_MAX; - hrResult = GetOptionSelectionShort(Helper, poemuiobj); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForSpecialFeatures() failed to get current selection for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - } - else if( !lstrcmpA(m_pszFeature, "%MaxFontSizeAsBitmap") - || - !lstrcmpA(m_pszFeature, "%MinFontSizeAsOutline") - ) - { - // MaxFontSizeAsBitmap, and MinFontSizeAsOutline feature options - // are string representations of an integer that represents number - // of pixels in the range 0 through 32,767 (i.e. SHRT_MAX). - m_cType = TVOT_UDARROW; - m_ptRange.x = 0; - m_ptRange.y = SHRT_MAX; - hrResult = GetOptionSelectionShort(Helper, poemuiobj); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForSpecialFeatures() failed to get current selection for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - } - else if( !lstrcmpA(m_pszFeature, "%PSMemory") ) - { - DWORD dwType; - DWORD dwLevel; - DWORD dwNeeded; - - - // PSMemory option is string representation of an integer - // that represents number of seconds in the range 0 - // through 32,767 (i.e. SHRT_MAX). - // However, the minimum is 172 KB for Level 1 and 249 KB for level 2 - m_cType = TVOT_UDARROW; - m_ptRange.y = SHRT_MAX; - hrResult = GetOptionSelectionShort(Helper, poemuiobj); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForSpecialFeatures() failed to get current selection for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // Get the global attribute for max language level. - hrResult = Helper.GetGlobalAttribute(poemuiobj, - 0, - "LanguageLevel", - &dwType, - (PBYTE) &dwLevel, - sizeof(dwLevel), - &dwNeeded); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForSpecialFeatures() failed to get global attribute \"LanguageLevel\". (hrResult = 0x%x)\r\n"), - hrResult); - - goto Exit; - } - - // Set minimum range based on PS Max Language level. - switch(dwLevel) - { - case 1: - m_ptRange.x = 172; - break; - - default: - case 2: - case 3: - m_ptRange.x = 249; - break; - } - - // Get Units string. - //GetStringResource(m_pszUnits - } - else if(!lstrcmpA(m_pszFeature, "%OutputPSLevel")) - { - hrResult = GetOptionsForOutputPSLevel(Helper, poemuiobj); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForSpecialFeatures() failed to get current selection for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - } - - -Exit: - - return hrResult; -} - -// Do init for PS Level options. -HRESULT COptions::GetOptionsForOutputPSLevel(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - WORD wCount = 0; - DWORD dwLevel = 0; - DWORD dwType = 0; - DWORD dwNeeded = 0; - HRESULT hrResult = E_NOTIMPL; - - - // PS Level is integers from 1 to "LanguageLevel" - // global atribute. - m_cType = TVOT_COMBOBOX; - - // Get the global attribute for max language level. - hrResult = Helper.GetGlobalAttribute(poemuiobj, - 0, - "LanguageLevel", - &dwType, - (PBYTE) &dwLevel, - sizeof(dwLevel), - &dwNeeded); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to get global attribute \"LanguageLevel\". (hrResult = 0x%x)\r\n"), - hrResult); - - goto Exit; - } - - // - // Create Options for PS Level - // - - // Set the number of options to the PS Level supported. - m_wOptions = (WORD) dwLevel; - - // Allocate keyword list. - // Allocate memory for pointer to keyword and the keyword itself, so that - // the memory for the keyword strings will get de-allocated with the keyword list - // on object destruction, just like regular features for which EnumOptions works. - // User the size of a pointer (4 bytes on x86, and 8 on IA64) so that - // it begining of the keyword strings will be DWORD or QUADWORD aligned - // for x86 and IA64 respectively. Keyword strings aren't required to - // be DWORD or QUADWORD aligned, but it is more optimal. Also, this gives - // some additional space for the case of %OutputPSLevel keywords, which are - // in the range of 1 through the max PostScript level supported, and only - // require 2 CHARs (1 for the digit and one for the NULL terminator). - m_ppszOptions = (PCSTR *) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_wOptions * ( sizeof(PSTR) + sizeof(PCSTR *) ) ); - if(NULL == m_ppszOptions) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to allocate option keyword array for PS Level.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - - // Allocate option info array. - m_pInfo = (POPTION_INFO) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_wOptions * sizeof(OPTION_INFO)); - if(NULL == m_pInfo) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to allocate info array for PS Level.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Init the option info. - for(wCount = 0; wCount < m_wOptions; ++wCount) - { - // Init keyword. - // The memory for both the keyword list and the keyword strings was allocated above. - m_ppszOptions[wCount] = (PSTR)(m_ppszOptions + m_wOptions) + (sizeof(PSTR) * wCount); - hrResult = StringCbPrintfA(const_cast<PSTR>(m_ppszOptions[wCount]), sizeof(PSTR), "%d", wCount + 1); - if(FAILED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to string representation of item %d.\r\n"), - wCount + 1); - - goto Exit; - } - - // Init option display name. - m_pInfo[wCount].pszDisplayName = (PWSTR) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, 2 * sizeof(WCHAR)); - if(NULL == m_pInfo[wCount].pszDisplayName) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to allocate display string for Level %d.\r\n"), - wCount); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Init option display name. - hrResult = StringCchPrintfW(m_pInfo[wCount].pszDisplayName, 2, TEXT("%d"), wCount + 1); - if(FAILED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionsForOutputPSLevel() failed to create display name for item %d.\r\n"), - wCount + 1); - - goto Exit; - } - } - - // - // Get Current Selection - // - - hrResult = GetOptionSelectionIndex(Helper, poemuiobj); - - -Exit: - - // Don't need to clean up memory allocation on error, since - // all memory allocated are assigned to data members, which - // will be cleaned up in the object destructor. - - return hrResult; -} - -HRESULT COptions::GetOptionSelectionString(CUIHelper &Helper, POEMUIOBJ poemuiobj, _Outptr_result_maybenull_ PSTR *ppszSel) -{ - PSTR pmszFeature = NULL; - PSTR pmszBuf = NULL; - WORD wCount = 0; - PCSTR *ppszList = NULL; - DWORD dwFeatureSize = 0; - DWORD dwNeeded = 0; - DWORD dwSize = INITIAL_GET_OPTION_SIZE; - HRESULT hrResult = S_OK; - - *ppszSel = NULL; - - - // - // Make single feature multi-sz. - // - - // Allocate single feature multi-sz buffer that's the size of the Feature name, plus two bytes for multi-sz termination - if (FAILED(hrResult = SizeTToDWord(strlen(m_pszFeature) + 2, &dwFeatureSize))) - { - goto Exit; - } - - pmszFeature = (PSTR) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, dwFeatureSize); - if(NULL == pmszFeature) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to allocate buffer for single feature multi-sz for feature %hs.\r\n"), - m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Just need to do a regular string copy, since the buffer is already zero filled. - hrResult = StringCbCopyA(pmszFeature, dwFeatureSize, m_pszFeature); - if(FAILED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to copy feature string %hs.\r\n"), m_pszFeature); - } - - // Allocated initial buffer of reasonible size. - pmszBuf = (PSTR) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, dwSize); - if(NULL == pmszBuf) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to allocate buffer to get current setting for feature %hs.\r\n"), - m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Get current option selection. - hrResult = Helper.GetOptions(poemuiobj, - 0, - pmszFeature, - dwFeatureSize, - pmszBuf, - dwSize, - &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) && (dwSize < dwNeeded) ) - { - PSTR pTemp = NULL; - - - // INVARIANT: initial buffer not large enough. - - // Re-alloc buffer and try again. - pTemp = (PSTR) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, pmszBuf, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to re-allocate buffer to get current setting for feature %hs.\r\n"), - m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - pmszBuf = pTemp; - - - // Try to get current option selection again. - hrResult = Helper.GetOptions(poemuiobj, - 0, - pmszFeature, - dwFeatureSize, - pmszBuf, - dwNeeded, - &dwNeeded); - } - - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to get current setting for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // NOTE: The return string from GetOptions() may return - // contain no strings and not return a HRESULT error - // when the feature isn't supported in the current document or - // printer sticky mode. - if('\0' == pmszBuf[0]) - { - // Feature not supported for this sticky mode. - goto Exit; - } - - // Parse the results buffer to see what the current setting is. - hrResult = MakeStrPtrList(m_hHeap, pmszBuf, &ppszList, &wCount); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to make string list for GetOptions() return for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // Check that we got 2 strings back. - if(2 != wCount) - { - WARNING(DLLTEXT("COptions::GetOptionSelectionString() the GetOption() return string list for \r\n\tfeature %hs is not of size 2.\r\n\tNumber of string is %d\r\n"), - m_pszFeature, - wCount); - - // Bail if we don't have at least 2 strings. - if(2 > wCount) - { - goto Exit; - } - } - - // Return copy of just the GetOption() result. - *ppszSel = MakeStringCopy(m_hHeap, ppszList[1]); - if(NULL == *ppszSel) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionString() failed to duplicate string GetOptions() return for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - -Exit: - - // Free local buffers. - if(NULL != pmszFeature) HeapFree(m_hHeap, 0, pmszFeature); - if(NULL != pmszBuf) HeapFree(m_hHeap, 0, pmszBuf); - if(NULL != ppszList) HeapFree(m_hHeap, 0, ppszList); - - return hrResult; -} - -// Gets current Options selection for LONG value. -HRESULT COptions::GetOptionSelectionLong(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - PSTR pszSel = NULL; - HRESULT hrResult = S_OK; - - - // Get option selection string. - hrResult = GetOptionSelectionString(Helper, poemuiobj, &pszSel); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionLong() failed to get string for GetOptions() return for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // Convert string option to LONG and uses that as the selection. - if(NULL != pszSel) m_Sel = atol(pszSel); - - -Exit: - - // Free local buffers. - if(NULL != pszSel) HeapFree(m_hHeap, 0, pszSel); - - return hrResult; -} - -// Gets current Options selection for SHORT value. -HRESULT COptions::GetOptionSelectionShort(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - PSTR pszSel = NULL; - HRESULT hrResult = S_OK; - - - // Get option selection string. - hrResult = GetOptionSelectionString(Helper, poemuiobj, &pszSel); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionLong() failed to get string for GetOptions() return for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // Convert string option to LONG and uses that as the selection. - if(NULL != pszSel) m_Sel = atoi(pszSel) & 0x00ffff; - - -Exit: - - // Free local buffers. - if(NULL != pszSel) HeapFree(m_hHeap, 0, pszSel); - - return hrResult; -} - -// Gets current option selection for feature. -HRESULT COptions::GetOptionSelectionIndex(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - PSTR pszSel = NULL; - HRESULT hrResult = S_OK; - - - // Get option selection string. - hrResult = GetOptionSelectionString(Helper, poemuiobj, &pszSel); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::GetOptionSelectionIndex() failed to get string for GetOptions() return for feature %hs. (hrResult = 0x%x)\r\n"), - m_pszFeature, - hrResult); - - goto Exit; - } - - // Find the matching option for the string returned from GetOption. - m_Sel = FindOption(pszSel, m_wOptions - 1); - - -Exit: - - // Free local buffers. - if(NULL != pszSel) HeapFree(m_hHeap, 0, pszSel); - - return hrResult; -} - - - -// -// Public Methods -// - -// Default constructor -COptions::COptions() -{ - Init(); -} - -// Destructor -COptions::~COptions() -{ - Clear(); -} - -// Get the option list for a feature -HRESULT COptions::Acquire(_In_ HANDLE hHeap, - CUIHelper &Helper, - _In_ POEMUIOBJ poemuiobj, - _In_ PCSTR pszFeature) -{ - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - VERBOSE(DLLTEXT("COptions::Acquire(0x%p, Helper, 0x%p, %hs) entered.\r\n"), - hHeap, - poemuiobj, - pszFeature ? pszFeature : "NULL"); - - // Don't retreive the Options again if we already got them. - if( (0 < m_wOptions) - && - (NULL != m_pszFeature) - && - !lstrcmpA(m_pszFeature, pszFeature) - ) - { - VERBOSE(DLLTEXT("COptions::Acquire() already have options for feature %hs.\r\n"), m_pszFeature); - VERBOSE(DLLTEXT("COptions::Acquire() returning with HRESULT of S_OK\r\n")); - - return S_OK; - } - - // Save the heap handle for use later, such as freeing memory at destruction. - m_hHeap = hHeap; - - // Store Keyword string. - m_pszFeature = pszFeature; - - - // - // Enumerate Options. - // - - - // Some features require special handling for initializing their options. - // EnumOpionts isn't implemented for these features. - // Return of E_NOTIMPL indicates it isn't the feature doesn't - // need special handling. - hrResult = GetOptionsForSpecialFeatures(Helper, poemuiobj); - if( SUCCEEDED(hrResult) - || - (!SUCCEEDED(hrResult) && (E_NOTIMPL != hrResult) ) - ) - { - // We either dealt with the special feature or incounter an error - // trying to deal with the special feature. - - goto Exit; - } - - // To try to cut down on having to call EnumOptions more than once, - // pre-allocate a buffer of reasonable size. - m_dwSize = INITIAL_ENUM_OPTIONS_SIZE; - m_pmszRaw = (PSTR) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_dwSize); - if(NULL == m_pmszRaw) - { - ERR(ERRORTEXT("COptions::Acquire() alloc for options for feature %hs failed.\r\n"), m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - - // Try to get options list with initial buffer. - hrResult = Helper.EnumOptions(poemuiobj, 0, m_pszFeature, m_pmszRaw, m_dwSize, &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) && (m_dwSize < dwNeeded)) - { - PSTR pTemp; - - - // INVARIANT: options list multi-sz wasn't large enough. - - // Re-allocate the buffer and try again. - pTemp = (PSTR) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_pmszRaw, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("COptions::Acquire() re-alloc for options list for feature %hs failed.\r\n"), m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - m_pmszRaw = pTemp; - m_dwSize = dwNeeded; - - // Try again to get the options list. - hrResult = Helper.EnumOptions(poemuiobj, 0, m_pszFeature, m_pmszRaw, m_dwSize, &dwNeeded); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::Acquire() failed to EnumOptions() for feature %hs after re-allocating buffer.\r\n"), m_pszFeature); - - goto Exit; - } - } - - // Make sure we got the option list. - // Can't do anything more with out it. - if(!SUCCEEDED(hrResult)) - { - if(E_NOTIMPL != hrResult) ERR(ERRORTEXT("COptions::Acquire() failed to enumerate options for feature %hs. (hrResult = 0x%x)\r\n"), m_pszFeature, hrResult); - - goto Exit; - } - - // INVARIANT: successfully got option keyword list. - - // Create array of string pointers to the Option names - // in the multi-sz we got from EnumOptions(). - hrResult = MakeStrPtrList(m_hHeap, m_pmszRaw, &m_ppszOptions, &m_wOptions); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::Acquire() failed to create pointer list to options. (hrResult = 0x%x)\r\n"), hrResult); - - goto Exit; - } - - // - // Build Option Information - // - - // Allocate array to hold feature info - m_pInfo = (POPTION_INFO) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_wOptions * sizeof(OPTION_INFO)); - if(NULL == m_pInfo) - { - ERR(ERRORTEXT("COptions::Acquire() failed to alloc feature info array.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // For each option, build or get useful information, such as display name. - for(WORD wIndex = 0; wIndex < m_wOptions; ++wIndex) - { - POPTION_INFO pCurrent = m_pInfo + wIndex; - - - // Get or build a keyword mapping entry - // that maps from keyword to usefully where to get info, such as - // display name, icon, option type, for keywords that may not be - // able to get info for from Helper. - pCurrent->pMapping = FindKeywordMapping(gkmOptionMap, NUM_OPTION_MAP, m_ppszOptions[wIndex]); - - // Get display names for each of the Options. - // The function implements a heuristic for detemining the display name, - // since can't get the display name from the UI Helper for all Options. - hrResult = DetermineOptionDisplayName(m_hHeap, - Helper, - poemuiobj, - m_pszFeature, - m_ppszOptions[wIndex], - pCurrent->pMapping, - &pCurrent->pszDisplayName); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("COptions::Acquire() failed to get display name for %hs of feature %hs. (hrResult = 0x%x)\r\n"), - m_ppszOptions[wIndex], - m_pszFeature, - hrResult); - - goto Exit; - } - } - - // - // Get current option selection. - // - - hrResult = GetOptionSelectionIndex(Helper, poemuiobj); - - -Exit: - - // Clean up if weren't successful. - if(!SUCCEEDED(hrResult)) - { - Clear(); - } - - VERBOSE(DLLTEXT("COptions::Acquire() returning with HRESULT of 0x%x\r\n"), hrResult); - - return hrResult; -} - -// Return nth options keyword. -PCSTR COptions::GetKeyword(WORD wIndex) const -{ - // Validate parameters. - if( (wIndex >= m_wOptions) - || - (NULL == m_ppszOptions) - ) - { - return NULL; - } - - return m_ppszOptions[wIndex]; -} - -// Return nth options display name. -PCWSTR COptions::GetName(WORD wIndex) const -{ - // Validate parameters. - if( (wIndex >= m_wOptions) - || - (NULL == m_pInfo) - ) - { - ERR(ERRORTEXT("COptions::GetName() invalid parameters.\r\n")); - - return NULL; - } - - if(NULL == m_pInfo[wIndex].pszDisplayName) ERR(ERRORTEXT("COptions::GetName() returning NULL option display name.\r\n")); - - return m_pInfo[wIndex].pszDisplayName; -} - -// Find option with matching keyword string. -WORD COptions::FindOption(_In_opt_ PCSTR pszOption, WORD wDefault) const -{ - BOOL bFound = FALSE; - WORD wMatch = wDefault; - - - // Validate parameters. - if( (NULL == pszOption) - || - (NULL == m_ppszOptions) - ) - { - return wDefault; - } - - // Walk the option keyword looking for a match. - for(WORD wIndex = 0; !bFound && (wIndex < m_wOptions); ++wIndex) - { - bFound = !lstrcmpA(pszOption, m_ppszOptions[wIndex]); - if(bFound) - { - wMatch = wIndex; - } - } - - return wMatch; -} - -// Initializes OptItem with options for a feature. -HRESULT COptions::InitOptItem(_In_ HANDLE hHeap, POPTITEM pOptItem) -{ - WORD wParams = 0; - WORD wOptions = 0; - HRESULT hrResult = S_OK; - - - // Set option selection. - pOptItem->pSel = m_pSel; - - // Get count of number of options. - // NOTE: Some feature options have no counts. - wOptions = GetCount(); - - // Different OPTTYPE types require different number of OPTPARAMs. - switch(m_cType) - { - // For up down arrow control, the OPTPARAMs need is 2. - case TVOT_UDARROW: - wParams = 2; - break; - - // For combobox, the OPTPARAMs needed is on per options. - case TVOT_COMBOBOX: - wParams = wOptions; - break; - - // The default is the option count. - default: - WARNING(DLLTEXT("COptions::InitOptItem() OPTTYPE type %d num of OPTPARAMs not handled. Default to option count of %d.\r\n"), - m_cType, - wOptions); - wParams = wOptions; - break; - } - - // Only do OPTTYPEs if we have non-Zero number of OPTPARAMs. - // Every OPTTYPE has at leas one OPTPARAM. - if(0 < wParams) - { - // Allocate memory for feature options. - pOptItem->pOptType = CreateOptType(hHeap, wParams); - if(NULL == pOptItem->pOptType) - { - ERR(ERRORTEXT("COptions::InitOptItem() failed to allocate OPTTYPEs for OPTITEM %hs.\r\n"), - m_pszFeature); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Set OPTTYPE. - pOptItem->pOptType->Type = m_cType; - - // Different OPTTYPE types require different initialization. - switch(m_cType) - { - // For up down arrow control, OPTPARAM[0] is used by the contrl. - // pOptParam[0]->pData is the Units description string. - // pOptParam[1].IconID is the min limit. - // pOptParam[1].lParam is the max limit. - case TVOT_UDARROW: - assert(2 == wParams); - pOptItem->pOptType->pOptParam[0].pData = m_pszUnits; - pOptItem->pOptType->pOptParam[1].IconID = m_ptRange.x; - pOptItem->pOptType->pOptParam[1].lParam = m_ptRange.y; - break; - - // For combobox, the pOptParam[n].pData is the display name of the option. - case TVOT_COMBOBOX: - for(WORD wIndex = 0; wIndex < wParams; ++wIndex) - { - pOptItem->pOptType->pOptParam[wIndex].pData = const_cast<PWSTR>(GetName(wIndex)); - } - break; - - default: - ERR(ERRORTEXT("COptions::InitOptItem() OPTTYPE type %d OPTTYPE init not handled.\r\n"), - m_cType); - break; - } - } - - -Exit: - - return hrResult; -} - -// Refresh option selection. -HRESULT COptions::RefreshSelection(CUIHelper &Helper, POEMUIOBJ poemuiobj) -{ - HRESULT hrResult = S_OK; - - - // Method for getting option selection is based - // on OPTTYPE type. - switch(m_cType) - { - - case TVOT_UDARROW: - hrResult = GetOptionSelectionShort(Helper, poemuiobj); - break; - - case TVOT_COMBOBOX: - hrResult = GetOptionSelectionIndex(Helper, poemuiobj); - break; - - default: - ERR(ERRORTEXT("COptions::RefreshSelection() not handled for type %d OPTTYPE.\r\n"), - m_cType); - break; - } - - return hrResult; -} - - - -//////////////////////////////////////////// -// -// CFeatures Methods -// - -// -// Private Methods -// - -// Initializes class -void CFeatures::Init() -{ - // Initialize data members. - m_wFeatures = 0; - m_wDocFeatures = 0; - m_wPrintFeatures = 0; - m_pmszRaw = NULL; - m_ppszKeywords = NULL; - m_dwSize = 0; - m_hHeap = NULL; - m_pInfo = NULL; -} - -// Cleans up class and re-initialize it. -void CFeatures::Clear() -{ - // Free memory associated with data members. - if(NULL != m_pmszRaw) HeapFree(m_hHeap, 0, m_pmszRaw); - if(NULL != m_ppszKeywords) HeapFree(m_hHeap, 0, m_ppszKeywords); - - // Free feature info - FreeFeatureInfo(); - - // Re-initialize - Init(); -} - -// Free feature info -void CFeatures::FreeFeatureInfo() -{ - // Validate parameters. - if( (NULL == m_hHeap) - || - (NULL == m_pInfo) - ) - { - return; - } - - // Free memory associated with feature info. - for(WORD wIndex = 0; wIndex < m_wFeatures; ++wIndex) - { - PWSTR pszDisplay = m_pInfo[wIndex].pszDisplayName; - - - // Free display name. - if( (NULL != pszDisplay) - && - !IS_INTRESOURCE(pszDisplay) - ) - { - HeapFree(m_hHeap, 0, pszDisplay); - } - } - - // Free feature info array. - // Feature Info array allocated with new so - // that each of the constructors for COptions - // in fhte Feature Info array will be called. - delete[] m_pInfo; -} - -// Turns index for mode to modeless index, which -// is the real index to the feature. -WORD CFeatures::GetModelessIndex(WORD wIndex, DWORD dwMode) const -{ - WORD wCount = 0; - - - switch(dwMode) - { - // Number of features, all modes - case 0: - wCount = wIndex; - break; - - // Find the nth feature that matches the mode - case OEMCUIP_DOCPROP: - case OEMCUIP_PRNPROP: - // Walk the feature list looking for nth feature - // with matching mode. - for(wCount = 0; wCount < m_wFeatures; ++wCount) - { - // Count down to the feature we want. - // Only count down for matching modes. - if(dwMode == m_pInfo[wCount].dwMode) - { - if(0 == wIndex) - { - break; - } - else - { - --wIndex; - } - } - } - break; - } - - return wCount; -} - - -// -// Public Methods -// - -// Default constructor -CFeatures::CFeatures() -{ - Init(); -} - -// Destructor -CFeatures::~CFeatures() -{ - // Clean up class. - Clear(); -} - -// Gets Core Driver Features, if not already retrieved. -HRESULT CFeatures::Acquire(_In_ HANDLE hHeap, - CUIHelper &Helper, - _In_ POEMUIOBJ poemuiobj - ) -{ - WORD wIndex = 0; - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - VERBOSE(DLLTEXT("CFeatures::Acquire(0x%p, Helper, 0x%p) entered.\r\n"), - hHeap, - poemuiobj); - - // Don't retreive the Features again if we already got them. - if(0 < m_wFeatures) - { - VERBOSE(DLLTEXT("CFeatures::Acquire() features already enumerated.\r\n")); - VERBOSE(DLLTEXT("CFeatures::Acquire() returning S_OK.\r\n")); - - return S_OK; - } - - // Save the heap handle for use later, such as freeing memory at destruction. - m_hHeap = hHeap; - - // - // Enumerate features. - // - - // To try to cut down on having to call EnumFeatures more than once, - // pre-allocate a buffer of reasonable size. - m_dwSize = INITIAL_ENUM_FEATURES_SIZE; - m_pmszRaw = (PSTR) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_dwSize); - if(NULL == m_pmszRaw) - { - ERR(ERRORTEXT("CFeatures::Acquire() alloc for feature list failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - - // Try to get feature list with initial buffer. - hrResult = Helper.EnumFeatures(poemuiobj, 0, m_pmszRaw, m_dwSize, &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) && (m_dwSize < dwNeeded)) - { - PSTR pTemp; - - - // INVARIANT: feature list multi-sz wasn't large enough. - - - // Re-allocate the buffer and try again. - pTemp = (PSTR) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_pmszRaw, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("CFeatures::Acquire() re-alloc for feature list failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - m_pmszRaw = pTemp; - m_dwSize = dwNeeded; - - // Try again to get the feature list. - hrResult = Helper.EnumFeatures(poemuiobj, 0, m_pmszRaw, m_dwSize, &dwNeeded); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to EnumFeatures() after re-allocating buffer.\r\n")); - - goto Exit; - } - } - - // Make sure we got the feature list. - // Can't do anything more with out it. - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to enumerate features. (hrResult = 0x%x)\r\n"), hrResult); - - goto Exit; - } - - // INVARIANT: successfully got feature keyword list. - - // Create array of string pointers to the feature keywords - // in the multi-sz we got from EnumFreatures(). - hrResult = MakeStrPtrList(m_hHeap, m_pmszRaw, &m_ppszKeywords, &m_wFeatures); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to create pointer list to keywords. (hrResult = 0x%x)\r\n"), hrResult); - - goto Exit; - } - - - // - // Build Feature Information - // - - - // Allocate array to hold feature info - // Use new for allocation so class - // constructors/destructors get called. - m_pInfo = new FEATURE_INFO[m_wFeatures]; - if(NULL == m_pInfo) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to alloc feature info array.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // For each feature, build/get feature info.... - for(wIndex = 0; wIndex < m_wFeatures; ++wIndex) - { - PFEATURE_INFO pCurrent = m_pInfo + wIndex; - - - // Get or build a keyword mapping entry - // that maps from keyword to usefully where to get info, such as - // display name, icon, option type, for keywords that may not be - // able to get info for from Helper. - pCurrent->pMapping = FindKeywordMapping(gkmFeatureMap, NUM_FEATURE_MAP, m_ppszKeywords[wIndex]); - - // Get display names for each of the featurs. - // The function implements a heuristic for detemining the display name, - // since can't get the display name from the UI Helper for all features. - hrResult = DetermineFeatureDisplayName(m_hHeap, - Helper, - poemuiobj, - m_ppszKeywords[wIndex], - pCurrent->pMapping, - &pCurrent->pszDisplayName); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to get display name for feature %hs. (hrResult = 0x%x)\r\n"), - m_ppszKeywords[wIndex], - hrResult); - - goto Exit; - } - - // Get options for each feature. - // NOTE: some features don't have options; the HRESULT will be E_NOTIMPL for these. - hrResult = pCurrent->Options.Acquire(hHeap, - Helper, - poemuiobj, - m_ppszKeywords[wIndex]); - if(!SUCCEEDED(hrResult) && (E_NOTIMPL != hrResult)) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to get options for feature %hs. (hrResult = 0x%x)\r\n"), - m_ppszKeywords[wIndex], - hrResult); - - goto Exit; - } - - // Determine if feature is Printer or Document sticky. - hrResult = DetermineStickiness(Helper, - poemuiobj, - m_ppszKeywords[wIndex], - pCurrent->pMapping, - &pCurrent->dwMode); - // Don't propagate error if failure from unhandled driver feature. - if( !SUCCEEDED(hrResult) - && - !IS_DRIVER_FEATURE(m_ppszKeywords[wIndex]) - ) - { - ERR(ERRORTEXT("CFeatures::Acquire() failed to determine stickiness for feature %hs. (hrResult = 0x%x)\r\n"), - m_ppszKeywords[wIndex], - hrResult); - - goto Exit; - } - - // Keep track of mode counts. - switch(pCurrent->dwMode) - { - case OEMCUIP_DOCPROP: - ++m_wDocFeatures; - break; - - case OEMCUIP_PRNPROP: - ++m_wPrintFeatures; - break; - - default: - ERR(ERRORTEXT("CFeatures::Acquire() unknown stickiness for feature %hs.\r\n"), - m_ppszKeywords[wIndex]); - break; - } - - } - - // INVARIANT: successfully build feature list. - - // Make sure that we always return success if we reach this point. - hrResult = S_OK; - - -Exit: - - // Clean up if weren't successful. - if(!SUCCEEDED(hrResult)) - { - Clear(); - } - - - VERBOSE(DLLTEXT("CFeatures::Acquire() returning HRESULT of 0x%x.\r\n"), hrResult); - - return hrResult; -} - -// Returns number of features contained in class instance. -WORD CFeatures::GetCount(DWORD dwMode) const -{ - WORD wCount = 0; - - - switch(dwMode) - { - // Number of features, all modes - case 0: - wCount = m_wFeatures; - break; - - case OEMCUIP_DOCPROP: - wCount = m_wDocFeatures; - break; - - case OEMCUIP_PRNPROP: - wCount = m_wPrintFeatures; - break; - - } - - VERBOSE(DLLTEXT("CFeatures::GetCount() returning %d\r\n"), wCount); - - return wCount; -} - -// Returns nth feature's keyword -PCSTR CFeatures::GetKeyword(WORD wIndex, DWORD dwMode) const -{ - // Validate parameters. - if( (wIndex >= GetCount(dwMode)) - || - (NULL == m_ppszKeywords) - ) - { - return NULL; - } - - // Get internal index. - wIndex = GetModelessIndex(wIndex, dwMode); - - // Return keyword - return m_ppszKeywords[wIndex]; -} - -// Return nth feature's Display Name. -PCWSTR CFeatures::GetName(WORD wIndex, DWORD dwMode) const -{ - // Validate parameters. - if( (wIndex >= GetCount(dwMode)) - || - (NULL == m_pInfo) - ) - { - return NULL; - } - - // Get internal index. - wIndex = GetModelessIndex(wIndex, dwMode); - - // Return display name. - return m_pInfo[wIndex].pszDisplayName; -} - -// Returns pointer to option class for nth feature. -COptions* CFeatures::GetOptions(WORD wIndex, DWORD dwMode) const -{ - // Validate parameters. - if( (wIndex >= GetCount(dwMode)) - || - (NULL == m_pInfo) - ) - { - return NULL; - } - - // Get internal index. - wIndex = GetModelessIndex(wIndex, dwMode); - - // Return options pointer. - return &m_pInfo[wIndex].Options; -} - -// Formats OPTITEM for specied feature. -HRESULT CFeatures::InitOptItem(_In_ HANDLE hHeap, POPTITEM pOptItem, WORD wIndex, DWORD dwMode) -{ - COptions *pOptions = NULL; - HRESULT hrResult = S_OK; - PFEATUREOPTITEMDATA pData = NULL; - - - // Validate parameters. - if( (wIndex >= GetCount(dwMode)) - || - (NULL == m_pInfo) - || - (NULL == pOptItem) - ) - { - return E_INVALIDARG; - } - - // Map mode index to internal index. - wIndex = GetModelessIndex(wIndex, dwMode); - - // Get name of feature. - pOptItem->pName = const_cast<PWSTR>(GetName(wIndex)); - - // Add feature OPTITEM data to OPTITEM to facilitate saving - // selection changes. - pData = (PFEATUREOPTITEMDATA) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(FEATUREOPTITEMDATA)); - if(NULL == pData) - { - ERR(ERRORTEXT("CFeatures::InitOptItem() failed to allocated memory for feature OPTITEM data.")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - pData->dwSize = sizeof(FEATUREOPTITEMDATA); - pData->dwTag = FEATURE_OPTITEM_TAG; - pData->pszFeatureKeyword = GetKeyword(wIndex); - pData->pOptions = GetOptions(wIndex); - pOptItem->UserData = (ULONG_PTR) pData; - - - // Get pointer to options for this feature. - // NOTE: some features do not have option list for various reasons. - pOptions = GetOptions(wIndex); - if(NULL != pOptions) - { - // Initialize COption parts of the OPTITEM - hrResult = pOptions->InitOptItem(hHeap, pOptItem); - } - -Exit: - - Dump(pOptItem); - - return hrResult; -} - -////////////////////////////////////////////////// -// -// Regular functions not part of class -// -////////////////////////////////////////////////// - - -// Maps feature keywords to display names for the features. -HRESULT DetermineFeatureDisplayName(_In_ HANDLE hHeap, - CUIHelper &Helper, - POEMUIOBJ poemuiobj, - _In_ PCSTR pszKeyword, - const PKEYWORDMAP pMapping, - _Outptr_result_maybenull_ PWSTR *ppszDisplayName) -{ - DWORD dwDataType = 0; - DWORD dwSize = INITIAL_FEATURE_DISPLAY_NAME_SIZE; - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - // Validate parameters. - if( (NULL == hHeap) - || - (NULL == pszKeyword) - || - (NULL == ppszDisplayName) - ) - { - ERR(ERRORTEXT("DetermineFeatureDisplayName() invalid arguement.\r\n")); - - hrResult = E_INVALIDARG; - goto Exit; - } - - // - // Call the Helper function. - // - - // Helper will return Display Names for PPD Features, but - // not for Driver Synthisized features (i.e. features prefixed with %). - // Do it for Driver Synthisized features, just in case the helper - // interface changes to support it. - - // Pre-allocate a buffer of reasonable size to try - // to one have to call GetFeatureAttribute() once. - *ppszDisplayName = (PWSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize); - if(NULL == *ppszDisplayName) - { - ERR(ERRORTEXT("DetermineFeatureDisplayName() alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Try to get diplay name for feature from Helper. - hrResult = Helper.GetFeatureAttribute(poemuiobj, - 0, - pszKeyword, - "DisplayName", - &dwDataType, - (PBYTE) *ppszDisplayName, - dwSize, - &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) && (dwSize < dwNeeded)) - { - PWSTR pTemp; - - - // INVARIANT: initial buffer wasn't large enough. - - // Re-alloc buffer and try again. - pTemp = (PWSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, *ppszDisplayName, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("DetermineFeatureDisplayName() re-alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - *ppszDisplayName = pTemp; - - // Try to get the display name from Helper, again. - hrResult = Helper.GetFeatureAttribute(poemuiobj, - 0, - pszKeyword, - "DisplayName", - &dwDataType, - (PBYTE) *ppszDisplayName, - dwNeeded, - &dwNeeded); - } - - if(SUCCEEDED(hrResult)) - { - // INVARIANT: Successfully got display name from Helper for feature. - // Don't need to do anything more. - - // Check the data type, it should be kADT_UNICODE. - if(kADT_UNICODE != dwDataType) WARNING(DLLTEXT("DetermineFeatureDisplayName() feature attribute type not kADT_UNICODE. (dwDataType = %d)\r\n"), dwDataType); - - goto Exit; - } - - // INVARIANT: Did not get the display name from the Helper. - - // Free memory allocated for call to Helper. - if(NULL != *ppszDisplayName) - { - HeapFree(hHeap, 0, *ppszDisplayName); - *ppszDisplayName = NULL; - } - - // Try alternative methods for getting the display name other - // than from the Helper function. - // If we have a mapping entry, then try to get resource string - // for the display name. - // Otherwise, covert the keyword to UNICODE and use that. - if(NULL != pMapping) - { - // - // Try mapping the keyword to resource string. - // - - hrResult = GetDisplayNameFromMapping(hHeap, pMapping, ppszDisplayName); - } - else - { - // - // Convert the keyword to UNICODE and use that. - // - - // Convert ANSI keyword to Unicode string for display name. - // Need to remove the % for Driver Synthisized features. - // For debug version, add marker that shows that the display name was faked. - PCSTR pConvert = IS_DRIVER_FEATURE(pszKeyword) ? pszKeyword + 1 : pszKeyword; - #if DBG - CHAR szTemp[256]; - if(FAILED(StringCbPrintfA(szTemp, sizeof(szTemp), "%s (Keyword)", pConvert))) - { - ERR(ERRORTEXT("DetermineFeatureDisplayName() StringCbPrintfA() called failed.\r\n")); - } - pConvert = szTemp; - #endif - *ppszDisplayName = MakeUnicodeString(hHeap, pConvert); - if(NULL == *ppszDisplayName) - { - ERR(ERRORTEXT("DetermineFeatureDisplayName() alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Return success even though we faked a display name. - hrResult = S_OK; - } - - -Exit: - - // If failed, then return no string. - if(!SUCCEEDED(hrResult)) - { - if(ppszDisplayName && NULL != *ppszDisplayName) - { - HeapFree(hHeap, 0, *ppszDisplayName); - *ppszDisplayName = NULL; - } - } - - return hrResult; -} - -// Maps option keywords to display names for the option. -HRESULT DetermineOptionDisplayName(_In_ HANDLE hHeap, - CUIHelper &Helper, - POEMUIOBJ poemuiobj, - _In_ PCSTR pszFeature, - _In_ PCSTR pszOption, - const PKEYWORDMAP pMapping, - _Outptr_result_maybenull_ PWSTR *ppszDisplayName) -{ - DWORD dwDataType = 0; - DWORD dwSize = INITIAL_OPTION_DISPLAY_NAME_SIZE; - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - // Validate parameters. - if( (NULL == hHeap) - || - (NULL == pszFeature) - || - (NULL == pszOption) - || - (NULL == ppszDisplayName) - ) - { - ERR(ERRORTEXT("DetermineOptionDisplayName() invalid arguement.\r\n")); - - hrResult = E_INVALIDARG; - goto Exit; - } - - // - // Call the Helper function. - // - - // Helper will return Display Names for PPD Feature Options, but - // not for Driver Synthisized features options (i.e. features prefixed with %). - // Do it for all options, just in case the helper interface changes to support it. - - // Pre-allocate a buffer of reasonable size to try - // to one have to call GetOptionAttribute() once. - *ppszDisplayName = (PWSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize); - if(NULL == *ppszDisplayName) - { - ERR(ERRORTEXT("DetermineOptionDisplayName() alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Try to get diplay name for feature from Helper. - hrResult = Helper.GetOptionAttribute(poemuiobj, - 0, - pszFeature, - pszOption, - "DisplayName", - &dwDataType, - (PBYTE) *ppszDisplayName, - dwSize, - &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) && (dwSize < dwNeeded)) - { - PWSTR pTemp; - - - // INVARIANT: initial buffer wasn't large enough. - - // Re-alloc buffer and try again. - pTemp = (PWSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, *ppszDisplayName, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("GetOptionAttribute() re-alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - *ppszDisplayName = pTemp; - - // Try to get the display name from Helper, again. - hrResult = Helper.GetOptionAttribute(poemuiobj, - 0, - pszFeature, - pszOption, - "DisplayName", - &dwDataType, - (PBYTE) *ppszDisplayName, - dwNeeded, - &dwNeeded); - } - - if(SUCCEEDED(hrResult)) - { - // INVARIANT: Successfully got display name from Helper for feature. - // Don't need to do anything more. - - // Check the data type, it should be kADT_UNICODE. - if(kADT_UNICODE != dwDataType) WARNING(DLLTEXT("DetermineOptionDisplayName() feature attribute type not kADT_UNICODE. (dwDataType = %d)\r\n"), dwDataType); - - goto Exit; - } - - // INVARIANT: Did not get the display name from the Helper. - - // Free memory allocated for call to Helper. - if(NULL != *ppszDisplayName) - { - HeapFree(hHeap, 0, *ppszDisplayName); - *ppszDisplayName = NULL; - } - - // Try alternative methods for getting the display name other - // than from the Helper function. - // If we have a mapping entry, then try to get resource string - // for the display name. - // Otherwise, covert the keyword to UNICODE and use that. - if(NULL != pMapping) - { - // - // Try mapping the keyword to resource string. - // - - hrResult = GetDisplayNameFromMapping(hHeap, pMapping, ppszDisplayName); - } - else - { - // - // Convert the keyword to UNICODE and use that. - // - - // Convert ANSI keyword to Unicode string for display name. - // For debug version, add marker that shows that the display name was faked. - PCSTR pConvert = pszOption; - #if DBG - CHAR szTemp[256]; - if(FAILED(StringCbPrintfA(szTemp, sizeof(szTemp), "%s (Keyword)", pConvert))) - { - ERR(ERRORTEXT("DetermineOptionDisplayName() StringCbPrintfA() called failed.\r\n")); - } - pConvert = szTemp; - #endif - *ppszDisplayName = MakeUnicodeString(hHeap, pConvert); - if(NULL == *ppszDisplayName) - { - ERR(ERRORTEXT("DetermineOptionDisplayName() alloc for feature display name failed.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Return success even though we faked a display name. - hrResult = S_OK; - } - - -Exit: - - // If failed, then return no string. - if(!SUCCEEDED(hrResult)) - { - if(ppszDisplayName && NULL != *ppszDisplayName) - { - HeapFree(hHeap, 0, *ppszDisplayName); - *ppszDisplayName = NULL; - } - } - - return hrResult; -} - -// Determines sticky mode for the feature. -HRESULT DetermineStickiness(CUIHelper &Helper, - POEMUIOBJ poemuiobj, - PCSTR pszKeyword, - const PKEYWORDMAP pMapping, - PDWORD pdwMode) -{ - CHAR szGroupType[32] = {0}; - DWORD dwType = 0; - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - // Use mapping to see what stickiness of the feature is. - if(NULL != pMapping) - { - *pdwMode = pMapping->dwMode; - goto Exit; - } - - // By default make feature Document sticky, if we don't have mapping. - *pdwMode = OEMCUIP_DOCPROP; - - // Try to use Helper to determine stickiness. - hrResult = Helper.GetFeatureAttribute(poemuiobj, - 0, - pszKeyword, - "OpenGroupType", - &dwType, - (PBYTE) szGroupType, - sizeof(szGroupType), - &dwNeeded); - if(SUCCEEDED(hrResult)) - { - // INVARIANT: found out if feature is an installable option. - // Installable options are the only PPD features - // that are Printer sticky. - - if(!lstrcmpA(szGroupType, "InstallableOptions")) - { - *pdwMode = OEMCUIP_PRNPROP; - } - goto Exit; - } - - -Exit: - - return hrResult; -} - -// Find the mapping entry from the keyword. -PKEYWORDMAP FindKeywordMapping(PKEYWORDMAP pKeywordMap, WORD wMapSize, PCSTR pszKeyword) -{ - BOOL bFound = FALSE; - PKEYWORDMAP pMapping = NULL; - - - // Walk mapping array for matching keyword. - for(WORD wIndex = 0; !bFound && (wIndex < wMapSize); ++wIndex) - { - bFound = !lstrcmpA(pszKeyword, pKeywordMap[wIndex].pszKeyword); - if(bFound) - { - pMapping = pKeywordMap + wIndex; - } - } - - return pMapping; -} - -// Get display name from mapping entry. -HRESULT GetDisplayNameFromMapping(_In_ HANDLE hHeap, PKEYWORDMAP pMapping, _Outptr_result_maybenull_ PWSTR *ppszDisplayName) -{ - HMODULE hModule = NULL; - HRESULT hrResult = S_OK; - - - // Validate parameters. - if( (NULL == hHeap) - || - (NULL == pMapping) - || - (NULL == ppszDisplayName) - ) - { - hrResult = E_INVALIDARG; - goto Exit; - } - - // Check for simple case of returning INT resource. - if( (NULL == pMapping->pwszModule) - || - IS_MAPPING_INT_RESOURCE(pMapping) - ) - { - // Just need to do MAKEINTRESOURCE on the resource ID and return. - *ppszDisplayName = MAKEINTRESOURCE(pMapping->uDisplayNameID); - goto Exit; - } - - // We only need to get the module if we aren't loading the resource from - // this module (i.e. if module name isn't NULL). - // Also, as an optimization, we assume that the module has already been loaded, - // since the only cases currently are this module, driver ui, and Compstui.dll. - hModule = GetModuleHandle(pMapping->pwszModule); - if(NULL == hModule) - { - DWORD dwError = GetLastError(); - - - ERR(ERRORTEXT("GetDisplayNameFromMapping() for failed to load module %s. (Error %d)\r\n"), - pMapping->pwszModule, - dwError); - - hrResult = HRESULT_FROM_WIN32(dwError); - goto Exit; - } - - // INVARIANT: have handle to module to load resource from or the - // resource is being loaded from this module. - - // Get the string resouce. - hrResult = GetStringResource(hHeap, hModule, pMapping->uDisplayNameID, ppszDisplayName); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("GetDisplayNameFromMapping() failed to load string. (hrResult = 0x%x)\r\n"), - hrResult); - goto Exit; - } - - -Exit: - - return hrResult; -} - -// Test if an OPTITEM is an OPTITEM for a feature. -// Macro for testing if OPTITEM is feature OPTITEM -BOOL IsFeatureOptitem(POPTITEM pOptItem) -{ - BOOL bRet = FALSE; - PFEATUREOPTITEMDATA pData = NULL; - - - // Make sure pointers are NULL. - if( (NULL == pOptItem) - || - (NULL == pOptItem->UserData) - ) - { - // INVARIANT: can't be feature OPTITEM, since one of - // the necessary pointer are NULL. - - return FALSE; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem->UserData); - - // Check size and tag. - bRet = (sizeof(FEATUREOPTITEMDATA) == pData->dwSize) - && - (FEATURE_OPTITEM_TAG == pData->dwTag); - - return bRet; -} - - - -// Walks array of OPTITEMs saving each feature OPTITEM -// that has changed. -HRESULT SaveFeatureOptItems(_In_ HANDLE hHeap, - CUIHelper *pHelper, - POEMUIOBJ poemuiobj, - HWND hWnd, - POPTITEM pOptItem, - WORD wItems) -{ - PSTR pmszPairs = NULL; - WORD wPairs = 0; - WORD wReasons = 0; - DWORD dwSize = 0; - DWORD dwResult = 0; - PCSTR *ppszReasons = NULL; - PWSTR pszConfilictFeature = NULL; - PWSTR pszConfilictOption = NULL; - PWSTR pszCaption = NULL; - PWSTR pszFormat = NULL; - PWSTR pszMessage = NULL; - HRESULT hrResult = S_OK; - - - // Validate parameters - if( (NULL == hHeap) - || - (NULL == pHelper) - || - (NULL == pOptItem) - ) - { - ERR(ERRORTEXT("SaveFeatureOptItems() called with invalid parameters.\r\n")); - - hrResult = E_INVALIDARG; - goto Exit; - } - - // Get feature option pairs to save. - hrResult = GetChangedFeatureOptions(hHeap, pOptItem, wItems, &pmszPairs, &wPairs, &dwSize); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() failed to get changed feature option pairs. (hrResult = 0x%x)\r\n"), - hrResult); - - goto Exit; - } - - // Don't need to do anything more if no feature options changed. - if(0 == wPairs || !pmszPairs) - { - VERBOSE(DLLTEXT("SaveFeatureOptItems() no feature options that need to be set.\r\n")); - - goto Exit; - } - - // Set the change feature options. - // For the first SetOptions() call, don't have the - // core driver UI resolve conflicts, so we can - // prompt user for automatic resolution or let - // them do the conflict resolving. - hrResult = pHelper->SetOptions(poemuiobj, - SETOPTIONS_FLAG_KEEP_CONFLICT, - pmszPairs, - dwSize, - &dwResult); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() call to SetOptions() failed. (hrResult = 0x%x, dwResult = %d\r\n"), - hrResult, - dwResult); - - goto Exit; - } - - // Check to see if we were able to save changed feature options, - // or if there is a conflict that needs resolution. - if(SETOPTIONS_RESULT_CONFLICT_REMAINED == dwResult) - { - int nRet; - DWORD dwRet; - CONFLICT Conflict; - PKEYWORDMAP pMapping = NULL; - - - // INVARIANT: constraint conflict, options weren't saved. - - // Get list of all features that have conflict. - hrResult = GetFirstConflictingFeature(hHeap, - pHelper, - poemuiobj, - pOptItem, - wItems, - &Conflict); - if(!SUCCEEDED(hrResult)) - { - goto Exit; - } - - // Create string pointer list in to multi-sz of first conflict. - hrResult = MakeStrPtrList(hHeap, Conflict.pmszReasons, &ppszReasons, &wReasons); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() failed to make string list for conflict reasons. (hrResult = 0x%x)\r\n"), - hrResult); - - goto Exit; - } - - // Ensure that we have at least 2 reasons. Later code assumes that we do. - if (wReasons < 2) - { - hrResult = E_UNEXPECTED; - - goto Exit; - } - - // - // Get display versions of feature/option conflict reason. - // - - // Get or build a keyword mapping entry - // that maps from keyword to usefully where to get info, such as - // display name, icon, option type, for keywords that may not be - // able to get info for from Helper. - pMapping = FindKeywordMapping(gkmFeatureMap, NUM_FEATURE_MAP, ppszReasons[0]); - - // Get display names for each of the featurs. - // The function implements a heuristic for detemining the display name, - // since can't get the display name from the UI Helper for all features. - hrResult = DetermineFeatureDisplayName(hHeap, - *pHelper, - poemuiobj, - ppszReasons[0], - pMapping, - &pszConfilictFeature); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems failed to get display name for feature %hs. (hrResult = 0x%x)\r\n"), - ppszReasons[0], - hrResult); - - goto Exit; - } - - // Get or build a keyword mapping entry - // that maps from keyword to usefully where to get info, such as - // display name, icon, option type, for keywords that may not be - // able to get info for from Helper. - pMapping = FindKeywordMapping(gkmOptionMap, NUM_OPTION_MAP, ppszReasons[1]); - - // Get option display name. - hrResult = DetermineOptionDisplayName(hHeap, - *pHelper, - poemuiobj, - ppszReasons[0], - ppszReasons[1], - pMapping, - &pszConfilictOption); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() failed to get display name for %hs of feature %hs. (hrResult = 0x%x)\r\n"), - ppszReasons[1], - ppszReasons[0], - hrResult); - - goto Exit; - } - - // - // Prompt user about how to resolve conflict. - // - - // Get caption name. - hrResult = GetStringResource(hHeap, ghInstance, IDS_NAME, &pszCaption); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() failed to get caption name. (hrResult = 0x%x)\r\n"), - hrResult); - goto Exit; - } - - // Get message body format string. - hrResult = GetStringResource(hHeap, ghInstance, IDS_CONSTRAINT_CONFLICT, &pszFormat); - if(!SUCCEEDED(hrResult)) - { - ERR(ERRORTEXT("SaveFeatureOptItems() failed to get constraint conflict format. (hrResult = 0x%x)\r\n"), - hrResult); - goto Exit; - } - - - // Get messsage body. - PVOID paArgs[4] = {pszConfilictFeature, - pszConfilictOption, - const_cast<PWSTR>(Conflict.pszFeature), - Conflict.pszOption - }; - dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, - pszFormat, - 0, - 0, - (PWSTR) &pszMessage, - 0, - (va_list *) paArgs); - if(0 == dwRet) - { - DWORD dwError = GetLastError(); - - ERR(ERRORTEXT("SaveFeatureOptItems() failed to FormatMessage() for constraint conflict of feature %hs option %hs. (Last Error %d)\r\n"), - Conflict.pszFeatureKeyword, - Conflict.pszOptionKeyword, - dwError); - - hrResult = HRESULT_FROM_WIN32(dwError); - goto Exit; - } - - // Display simple message box with prompt. - nRet = MessageBox(hWnd, pszMessage, pszCaption, MB_YESNO | MB_ICONWARNING); - - // Check to see how user wants to resolve conflict. - if(IDYES == nRet) - { - // Let core driver resolve conflict resolution. - hrResult = pHelper->SetOptions(poemuiobj, - SETOPTIONS_FLAG_RESOLVE_CONFLICT, - pmszPairs, - dwSize, - &dwResult); - - // Conflict resolution requires refreshing current option - // selection for each feature, since selection may have - // changed because of conflict resolution. - RefreshOptItemSelection(pHelper, poemuiobj, pOptItem, wItems); - } - - // Return failure if there are still conflictts. - if(SETOPTIONS_RESULT_CONFLICT_REMAINED == dwResult) - { - hrResult = E_FAIL; - } - } - - -Exit: - - // Clean up... - - // cleanup heap allocs. - if(NULL != pmszPairs) HeapFree(hHeap, 0, pmszPairs); - if(NULL != ppszReasons) HeapFree(hHeap, 0, ppszReasons); - if(NULL != pszConfilictFeature) HeapFree(hHeap, 0, pszConfilictFeature); - if(NULL != pszConfilictOption) HeapFree(hHeap, 0, pszConfilictOption); - if(NULL != pszCaption) HeapFree(hHeap, 0, pszCaption); - if(NULL != pszFormat) HeapFree(hHeap, 0, pszFormat); - if(NULL != pszMessage) LocalFree(pszMessage); - - return hrResult; -} - -// Allocates buffer, if needed, and calls IPrintCoreUI2::WhyConsrained -// to get reason for constraint. -HRESULT GetWhyConstrained(_In_ HANDLE hHeap, - CUIHelper *pHelper, - POEMUIOBJ poemuiobj, - _In_ PCSTR pszFeature, - _In_ PCSTR pszOption, - _Inout_ PSTR *ppmszReason, - _Inout_ PDWORD pdwSize) -{ - PSTR pmszReasonList = *ppmszReason; - DWORD dwNeeded = 0; - HRESULT hrResult = S_OK; - - - // If buffer wasn't passed in, then allocate one. - if( (NULL == pmszReasonList) || (0 == *pdwSize) ) - { - // If no size or size is smaller than default, then change to default - // size. We want to try to only allocate and call once. - if(*pdwSize < INITIAL_GET_REASON_SIZE) - { - *pdwSize = INITIAL_GET_REASON_SIZE; - } - - // Alloc initial buffer for reason constrained. - pmszReasonList = (PSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, *pdwSize); - if(NULL == pmszReasonList) - { - ERR(ERRORTEXT("GetWhyConstrained() failed to alloc buffer for constraint reasons for feature %hs and option %hs.\r\n"), - pszFeature, - pszOption); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - } - - // Get reason for constraint. - hrResult = pHelper->WhyConstrained(poemuiobj, - 0, - pszFeature, - pszOption, - pmszReasonList, - *pdwSize, - &dwNeeded); - if( (E_OUTOFMEMORY == hrResult) - && - (*pdwSize < dwNeeded) - ) - { - PSTR pTemp; - - - // INVARIANT: initial buffer not large enough. - - // Re-alloc buffer to needed size. - pTemp = (PSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pmszReasonList, dwNeeded); - if(NULL == pTemp) - { - ERR(ERRORTEXT("GetWhyConstrained() failed to re-allocate buffer for constraint reason for feature %hs and option %hs.\r\n"), - pszFeature, - pszOption); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - pmszReasonList = pTemp; - *pdwSize = dwNeeded; - - // Retry getting constaint reason. - hrResult = pHelper->WhyConstrained(poemuiobj, - 0, - pszFeature, - pszOption, - pmszReasonList, - *pdwSize, - &dwNeeded); - } - - -Exit: - - // On error, do clean up. - if(!SUCCEEDED(hrResult)) - { - // Free reason buffer. - if(NULL != pmszReasonList) HeapFree(hHeap, 0, pmszReasonList); - - // Return NULL and zero size. - *ppmszReason = NULL; - *pdwSize = 0; - } - else - { - *ppmszReason = pmszReasonList; - } - - return hrResult; -} - -// Creates multi-sz list of feature option pairs that have changed. -HRESULT GetChangedFeatureOptions(_In_ HANDLE hHeap, - POPTITEM pOptItem, - WORD wItems, - _Outptr_result_maybenull_ PSTR *ppmszPairs, - _Out_ PWORD pwPairs, - _Out_ PDWORD pdwSize) -{ - WORD wCount = 0; - WORD wChanged = 0; - WORD wPairs = 0; - PSTR pmszPairs = NULL; - DWORD dwNeeded = 2; - DWORD dwOffset = 0; - HRESULT hrResult = S_OK; - PFEATUREOPTITEMDATA pData = NULL; - - - // Walk OPTITEM array looking or changed options, - // and calculating size needed for multi-sz buffer. - for(wCount = 0; wCount < wItems; ++wCount) - { - PSTR pszOption = NULL; - - - // Just go to next item if this OPTITEM hasn't - // changed or isn't a feature OPTITEM. - if( !(OPTIF_CHANGEONCE & pOptItem[wCount].Flags) - || - !IsFeatureOptitem(pOptItem + wCount) - ) - { - continue; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem[wCount].UserData); - - // Increment options changed and size needed. - pszOption = GetOptionKeywordFromOptItem(hHeap, pOptItem + wCount); - if(NULL != pszOption) - { - ++wChanged; - - DWORD dwTmp = 0; - - if (FAILED(hrResult = SizeTToDWord(strlen(pData->pszFeatureKeyword) + strlen(pszOption) + 2, &dwTmp))) - { - goto Exit; - } - - dwNeeded += dwTmp; - - // Need to free option keyword string copy - // allocated in GetOptionKeywordFromOptItem(). - HeapFree(hHeap, 0, pszOption); - pszOption = NULL; - } - } - - // Don't need to do anything more if no feature options changed. - if(0 == wChanged) - { - goto Exit; - } - - // Allocate multi-sz buffer. - pmszPairs = (PSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwNeeded); - if(NULL == pmszPairs) - { - ERR(ERRORTEXT("GetChangedFeatureOptions() failed to allocate multi-sz.\r\n")); - - hrResult = E_OUTOFMEMORY; - goto Exit; - } - - // Build mult-sz list of feature option pairs - // that changed. - for(wCount = 0, wPairs = 0; (wCount < wItems) && (wPairs < wChanged); ++wCount) - { - PSTR pszOption = NULL; - - - // Just go to next item if this OPTITEM hasn't - // changed or isn't a feature OPTITEM. - if( !(OPTIF_CHANGEONCE & pOptItem[wCount].Flags) - || - !IsFeatureOptitem(pOptItem + wCount) - ) - { - continue; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem[wCount].UserData); - - // Add feature option pair. - pszOption = GetOptionKeywordFromOptItem(hHeap, pOptItem + wCount); - if(NULL != pszOption) - { - if (FAILED(hrResult = StringCbCopyA(pmszPairs + dwOffset, dwNeeded - dwOffset, pData->pszFeatureKeyword))) - { - goto Exit; - } - - DWORD dwTmp = 0; - - if (FAILED(hrResult = SizeTToDWord(strlen(pData->pszFeatureKeyword) + 1, &dwTmp))) - { - goto Exit; - } - - dwOffset += dwTmp; - - if (FAILED(hrResult = StringCbCopyA(pmszPairs + dwOffset, dwNeeded - dwOffset, pszOption))) - { - goto Exit; - } - - if (FAILED(hrResult = SizeTToDWord(strlen(pszOption) + 1, &dwTmp))) - { - goto Exit; - } - - dwOffset += dwTmp; - - // Keep track of number of pairs added, so - // we are able to exit loop as soon as - // we added all changed feature options. - ++wPairs; - - // Need to free option keyword string copy - // allocated in GetOptionKeywordFromOptItem(). - HeapFree(hHeap, 0, pszOption); - pszOption = NULL; - } - } - - -Exit: - - if(SUCCEEDED(hrResult)) - { - // INVARIANT: either successfully build mutli-sz of changed - // feature option pairs, or there are no feature - // that options changed. - - // Return pairs and number of pairs. - *pwPairs = wPairs; - *pdwSize = dwNeeded; - *ppmszPairs = pmszPairs; - } - else - { - // INVARINAT: error. - - // Clean up. - if(NULL == pmszPairs) HeapFree(hHeap, 0, pmszPairs); - - // Return NULL and zero count. - *pwPairs = 0; - *pdwSize = 0; - *ppmszPairs = NULL; - } - - return hrResult; -} - -// Returns pointer to option keyword for a feature OPTITEM. -PSTR GetOptionKeywordFromOptItem(_In_ HANDLE hHeap, POPTITEM pOptItem) -{ - char szNumber[16] = {0}; - PSTR pszOption = NULL; - PFEATUREOPTITEMDATA pData = NULL; - - - // Validate parameter. - if(!IsFeatureOptitem(pOptItem)) - { - ERR(ERRORTEXT("GetOptionKeywordFromOptItem() invalid parameter.\r\n")); - - goto Exit; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem->UserData); - - // Option selection is based on type of OPTTYPE. - switch(pOptItem->pOptType->Type) - { - // For up down arrow control, selection is just pOptItem->Sel - // converted to string. - case TVOT_UDARROW: - if(FAILED(StringCbPrintfA(szNumber, sizeof(szNumber)/sizeof(szNumber[0]), "%u", pOptItem->Sel))) - { - ERR(ERRORTEXT("GetOptionKeywordFromOptItem() failed to convert number to string.\r\n")); - } - szNumber[sizeof(szNumber)/sizeof(szNumber[0]) - 1] = '\0'; - pszOption = MakeStringCopy(hHeap, szNumber); - break; - - // For combobox, pOptItem->Sel is the index in to the - // option array. - case TVOT_COMBOBOX: - pszOption = MakeStringCopy(hHeap, pData->pOptions->GetKeyword((WORD)pOptItem->Sel)); - break; - - // The default is the option count. - default: - ERR(ERRORTEXT("GetOptionKeywordFromOptItem() OPTTYPE type %d num of OPTPARAMs not handled.\r\n"), - pOptItem->pOptType->Type); - - goto Exit; - break; - } - - -Exit: - - return pszOption; -} - -// Returns pointer to option display name for a feature OPTITEM. -PWSTR GetOptionDisplayNameFromOptItem(_In_ HANDLE hHeap, POPTITEM pOptItem) -{ - WCHAR szNumber[16] = {0}; - PWSTR pszOption = NULL; - PFEATUREOPTITEMDATA pData = NULL; - - - // Validate parameter. - if(!IsFeatureOptitem(pOptItem)) - { - ERR(ERRORTEXT("GetOptionDisplayNameFromOptItem() invalid parameter.\r\n")); - - goto Exit; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem->UserData); - - // Option selection is based on type of OPTTYPE. - switch(pOptItem->pOptType->Type) - { - // For up down arrow control, selection is just pOptItem->Sel - // converted to string. - case TVOT_UDARROW: - if(FAILED(StringCbPrintfW(szNumber, sizeof(szNumber)/sizeof(szNumber[0]), L"%u", pOptItem->Sel))) - { - ERR(ERRORTEXT("GetOptionDisplayNameFromOptItem() failed to convert number to string.\r\n")); - } - szNumber[sizeof(szNumber)/sizeof(szNumber[0]) - 1] = L'\0'; - pszOption = MakeStringCopy(hHeap, szNumber); - break; - - // For combobox, pOptItem->Sel is the index in to the - // option array. - case TVOT_COMBOBOX: - pszOption = MakeStringCopy(hHeap, pOptItem->pOptType->pOptParam[pOptItem->Sel].pData); - break; - - // The default is the option count. - default: - ERR(ERRORTEXT("GetOptionDisplayNameFromOptItem() OPTTYPE type %d num of OPTPARAMs not handled.\r\n"), - pOptItem->pOptType->Type); - - goto Exit; - break; - } - - -Exit: - - return pszOption; -} - -// Refreshes option selection for each feature OPTITEM -HRESULT RefreshOptItemSelection(CUIHelper *pHelper, - POEMUIOBJ poemuiobj, - POPTITEM pOptItems, - WORD wItems) -{ - HRESULT hrResult = S_OK; - PFEATUREOPTITEMDATA pData = NULL; - - - // Walk OPTITEM array refreshing feature OPTITEMs. - for(WORD wCount = 0; wCount < wItems; ++wCount) - { - // Just go to next item if this OPTITEM isn't a feature OPTITEM. - if(!IsFeatureOptitem(pOptItems + wCount)) - { - continue; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItems[wCount].UserData); - - // Refresh COption selection. - pData->pOptions->RefreshSelection(*pHelper, poemuiobj); - - // Assign COption selection to OPTITEM selection. - pOptItems[wCount].pSel = pData->pOptions->GetSelection(); - - } - - return hrResult; -} - -// Creates array of conflict features. -HRESULT GetFirstConflictingFeature(_In_ HANDLE hHeap, - CUIHelper *pHelper, - POEMUIOBJ poemuiobj, - POPTITEM pOptItem, - WORD wItems, - PCONFLICT pConflict) -{ - WORD wCount = 0; - HRESULT hrResult = S_OK; - PFEATUREOPTITEMDATA pData = NULL; - - - // Walk OPTITEM array looking or changed options that are in conflict. - for(wCount = 0; wCount < wItems; ++wCount) - { - // Just go to next item if this OPTITEM hasn't - // changed or isn't a feature OPTITEM. - if( !(OPTIF_CHANGEONCE & pOptItem[wCount].Flags) - || - !IsFeatureOptitem(pOptItem + wCount) - ) - { - continue; - } - - // For convienience, assign to pointer to feature OPTITEM data. - pData = (PFEATUREOPTITEMDATA)(pOptItem[wCount].UserData); - - // Init conflict record if this feature is in conflict. - pConflict->pszOptionKeyword = GetOptionKeywordFromOptItem(hHeap, pOptItem + wCount); - if(NULL != pConflict->pszOptionKeyword) - { - // Get reason for conflict - // If the feature isn't in conflict, - // then the pmszReasonList will start - // with NULL terminator. - hrResult = GetWhyConstrained(hHeap, - pHelper, - poemuiobj, - pData->pszFeatureKeyword, - pConflict->pszOptionKeyword, - &pConflict->pmszReasons, - &pConflict->dwReasonsSize); - if(!SUCCEEDED(hrResult)) - { - // NOTE: driver features aren't supported by WhyConstrained. - if((E_INVALIDARG == hrResult) && IS_DRIVER_FEATURE(pData->pszFeatureKeyword)) - { - // Need to reset the result in case it is the last - // feature OPTITEM. - hrResult = S_OK; - continue; - } - - ERR(ERRORTEXT("GetConflictingFeatures() failed to get reason for feature %hs option %hs constraint. (hrResult = 0x%x)\r\n"), - pData->pszFeatureKeyword, - pConflict->pszOptionKeyword, - hrResult); - - goto Exit; - } - - // Record conflict if feature is in conflict. - if( (NULL != pConflict->pmszReasons) - && - (pConflict->pmszReasons[0] != '\0') - ) - { - // Save pointer to feature keyword. - pConflict->pszFeatureKeyword = pData->pszFeatureKeyword; - pConflict->pszFeature = pOptItem[wCount].pName; - pConflict->pszOption = GetOptionDisplayNameFromOptItem(hHeap, pOptItem + wCount); - - // Found first conflict. - break; - } - } - } - - -Exit: - - return hrResult; -} - - - |
