// 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 WinXP PS Driver Features and Options. // // // // PLATFORMS: Windows XP, Windows Server 2003 // // #include "precomp.h" #include "debug.h" #include "oemui.h" #include "stringutils.h" // StrSafe.h needs to be included last // to disallow bad string functions. #include // Create a list of pointers to the strings // in a multi-sz. HRESULT MakeStrPtrList(HANDLE hHeap, PCSTR pmszMultiSz, PCSTR **pppszList, PWORD pwCount) { PCSTR *ppszList = NULL; HRESULT hrResult = S_OK; // Validate parameters if( (NULL == hHeap) || (NULL == pmszMultiSz) || (NULL == pppszList) || (NULL == pwCount) ) { return E_INVALIDARG; } // Get the count of strings in the multi-sz. *pwCount = mstrcount(pmszMultiSz); if(0 == *pwCount) { WARNING(DLLTEXT("MakeStrPtrList() pmszMultiSz contains no strings.\r\n")); goto Exit; } // Allocate pointer list. *pppszList = (PCSTR *) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, (*pwCount) * sizeof(PCSTR)); if(NULL == *pppszList) { ERR(ERRORTEXT("MakeStrPtrList() failed to allote array of PCSTR.\r\n")); hrResult = E_OUTOFMEMORY; goto Exit; } ppszList = *pppszList; // Walk multi-sz mapping string pointers. for(WORD wIndex = 0; wIndex < *pwCount; ++wIndex) { ppszList[wIndex] = pmszMultiSz; pmszMultiSz += lstrlenA(pmszMultiSz) + 1; } Exit: return hrResult; } // Determine how many strings are in the multi-sz. WORD mstrcount(PCSTR pmszMultiSz) { WORD wCount = 0; // NULL string pointers have no strings. if(NULL == pmszMultiSz) { return 0; } // Walk list of strings counting them. while(pmszMultiSz[0] != '\0') { ++wCount; pmszMultiSz += lstrlenA(pmszMultiSz) + 1; } return wCount; } // Allocates and converts ANSI string to Unicode. PWSTR MakeUnicodeString(HANDLE hHeap, PCSTR pszAnsi) { int nSize = 0; PWSTR pszUnicode = NULL; // Validate parameters if( (NULL == hHeap) || (NULL == pszAnsi) ) { return NULL; } // Get the size needed for UNICODE string. nSize = MultiByteToWideChar(CP_ACP, 0, pszAnsi, -1, NULL, 0); if(0 != nSize) { // Allocate unicode string. pszUnicode = (PWSTR) HeapAlloc(hHeap, 0, nSize * sizeof(WCHAR)); if(NULL != pszUnicode) { // Convert ANSI to Unicode nSize = MultiByteToWideChar(CP_ACP, 0, pszAnsi, -1, pszUnicode, nSize); if(0 == nSize) { // INVARIANT: failed to convert. // free buffer and return NULL. HeapFree(hHeap, 0, pszUnicode); pszUnicode = NULL; } } } return pszUnicode; } // Allocates and copies source string. PWSTR MakeStringCopy(HANDLE hHeap, PCWSTR pszSource) { PWSTR pszCopy = NULL; DWORD dwSize; // Validate parameters if( (NULL == hHeap) || (NULL == pszSource) ) { return NULL; } // Allocate memory for string duplication, and duplicate the string. dwSize = (wcslen(pszSource) + 1) * sizeof(WCHAR); pszCopy = (PWSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize); if(NULL != pszCopy) { HRESULT hResult; hResult = StringCbCopyW(pszCopy, dwSize, pszSource); if(FAILED(hResult)) { HeapFree(hHeap, 0, pszCopy); pszCopy = NULL; SetLastError(hResult); } } return pszCopy; } // Allocates and copies source string. PSTR MakeStringCopy(HANDLE hHeap, PCSTR pszSource) { PSTR pszCopy = NULL; DWORD dwSize; // Validate parameters if( (NULL == hHeap) || (NULL == pszSource) ) { return NULL; } // Allocate memory for string duplication, and duplicate the string. dwSize = (lstrlenA(pszSource) + 1) * sizeof(CHAR); pszCopy = (PSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize); if(NULL != pszCopy) { HRESULT hResult; hResult = StringCbCopyA(pszCopy, dwSize, pszSource); if(FAILED(hResult)) { HeapFree(hHeap, 0, pszCopy); pszCopy = NULL; SetLastError(hResult); } } return pszCopy; } // Frees list of strings. // NOTE: don't use this for string list made with MakeStrPtrList(), since // the strings pointed to be list made with MakeStrPtrList() will // be freed when the multi-sz is freed. void FreeStringList(HANDLE hHeap, PWSTR *ppszList, WORD wCount) { // Validate parameters. if( (NULL == hHeap) || (NULL == ppszList) ) { return; } // Free each of the strings in the list. for(WORD wIndex = 0; wIndex < wCount; ++wIndex) { if(NULL != ppszList[wIndex]) HeapFree(hHeap, 0, ppszList[wIndex]); } // Free list. HeapFree(hHeap, 0, ppszList); } // Retrieves pointer to a String resource. HRESULT GetStringResource(HANDLE hHeap, HMODULE hModule, UINT uResource, PWSTR *ppszString) { int nResult; DWORD dwSize = MAX_PATH; PWSTR pszString = NULL; HRESULT hrResult = S_OK; VERBOSE(DLLTEXT("GetStringResource(%#x, %#x, %d) entered.\r\n"), hHeap, hModule, uResource); // Validate parameters. if( (NULL == hHeap) || (NULL == ppszString) ) { return E_INVALIDARG; } // Allocate buffer for string resource from heap; let the driver clean it up. pszString = (PWSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR)); if(NULL == pszString) { ERR(ERRORTEXT("GetStringResource() failed to allocate string buffer!\r\n")); hrResult = E_OUTOFMEMORY; goto Exit; } // Load string resource; resize after loading so as not to waste memory. nResult = LoadString(hModule, uResource, pszString, dwSize); if(nResult > 0) { PWSTR pszTemp; VERBOSE(DLLTEXT("LoadString() returned %d!\r\n"), nResult); VERBOSE(DLLTEXT("String load was \"%s\".\r\n"), pszString); pszTemp = (PWSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pszString, (nResult + 1) * sizeof(WCHAR)); if(NULL != pszTemp) { pszString = pszTemp; } else { WARNING(DLLTEXT("GetStringResource() HeapReAlloc() of string retrieved failed! (Last Error was %d)\r\n"), GetLastError()); } } else { DWORD dwError = GetLastError(); ERR(ERRORTEXT("LoadString() returned %d! (Last Error was %d)\r\n"), nResult, GetLastError()); ERR(ERRORTEXT("GetStringResource() failed to load string resource %d!\r\n"), uResource); HeapFree(hHeap, 0, pszString); pszString = NULL; hrResult = HRESULT_FROM_WIN32(dwError); } Exit: // Save string pointer to caller. // NOTE: string pointer will be NULL on failure. *ppszString = pszString; return hrResult; } // Retrieves pointer to a String resource. HRESULT GetStringResource(HANDLE hHeap, HMODULE hModule, UINT uResource, PSTR *ppszString) { int nResult; DWORD dwSize = MAX_PATH; PSTR pszString = NULL; HRESULT hrResult = S_OK; VERBOSE(DLLTEXT("GetStringResource(%#x, %#x, %d) entered.\r\n"), hHeap, hModule, uResource); // Validate parameters. if( (NULL == hHeap) || (NULL == ppszString) ) { return E_INVALIDARG; } // Allocate buffer for string resource from heap; let the driver clean it up. pszString = (PSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR)); if(NULL == pszString) { ERR(ERRORTEXT("GetStringResource() failed to allocate string buffer!\r\n")); hrResult = E_OUTOFMEMORY; goto Exit; } // Load string resource; resize after loading so as not to waste memory. nResult = LoadStringA(hModule, uResource, pszString, dwSize); if(nResult > 0) { PSTR pszTemp; VERBOSE(DLLTEXT("LoadString() returned %d!\r\n"), nResult); VERBOSE(DLLTEXT("String load was \"%hs\".\r\n"), pszString); pszTemp = (PSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pszString, nResult + 1); if(NULL != pszTemp) { pszString = pszTemp; } else { WARNING(DLLTEXT("GetStringResource() HeapReAlloc() of string retrieved failed! (Last Error was %d)\r\n"), GetLastError()); } } else { DWORD dwError = GetLastError(); ERR(ERRORTEXT("LoadString() returned %d! (Last Error was %d)\r\n"), nResult, GetLastError()); ERR(ERRORTEXT("GetStringResource() failed to load string resource %d!\r\n"), uResource); HeapFree(hHeap, 0, pszString); pszString = NULL; hrResult = HRESULT_FROM_WIN32(dwError); } Exit: // Save string pointer to caller. // NOTE: string pointer will be NULL on failure. *ppszString = pszString; return hrResult; }