/******************************************************************** Copyright (c) 1999-2000 Microsoft Corporation Module Name: util.cpp Abstract: utility functions implementation Revision History: DerekM created 05/01/99 ********************************************************************/ #include "stdafx.h" #include "util.h" ///////////////////////////////////////////////////////////////////////////// // tracing #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile HANDLE g_hPFPrivateHeap = NULL; ////////////////////////////////////////////////////////////////////////////// // string stuff // *************************************************************************** WCHAR *MyStrStrIW(const WCHAR *wcs1, const WCHAR *wcs2) { WCHAR *cp = (WCHAR *)wcs1; WCHAR *s1, *s2; while (*cp != '\0') { s1 = cp; s2 = (WCHAR *) wcs2; while (*s1 != '\0' && *s2 !='\0' && (towlower(*s1) - towlower(*s2)) == 0) s1++, s2++; if (*s2 == '\0') return(cp); cp++; } return(NULL); } // *************************************************************************** CHAR *MyStrStrIA(const CHAR *cs1, const CHAR *cs2) { CHAR *cp = (CHAR *)cs1; CHAR *s1, *s2; while (*cp != '\0') { s1 = cp; s2 = (CHAR *) cs2; while (*s1 != '\0' && *s2 !='\0' && (tolower(*s1) - tolower(*s2)) == 0) s1++, s2++; if (*s2 == '\0') return(cp); cp++; } return(NULL); } // ************************************************************************** HRESULT MyURLEncode(LPWSTR wszDest, DWORD cchDest, LPWSTR wszSrc) { USE_TRACING("URLEncode"); HRESULT hr = NOERROR; DWORD cb; CHAR *pszDest = NULL, *pszSrc; CHAR *szSrcBuf, *szDestBuf, ch; VALIDATEPARM(hr, (wszDest == NULL || wszSrc == NULL)); if (FAILED(hr)) goto done; // alloc enuf space to hold the src array as bytes cb = (wcslen(wszSrc) + 1) * sizeof(WCHAR); __try { szSrcBuf = (CHAR *)_alloca(cb); szDestBuf = (CHAR *)_alloca(cb * 3); _ASSERT(szSrcBuf != NULL); } __except(1) { szSrcBuf = NULL; szDestBuf = NULL; } VALIDATEEXPR(hr, (szSrcBuf == NULL || szDestBuf == NULL), E_OUTOFMEMORY); if (FAILED(hr)) goto done; // convert to multibyte so I can properly URL encode the string TESTBOOL(hr, (WideCharToMultiByte(CP_ACP, 0, wszSrc, -1, szSrcBuf, cb, NULL, NULL) != 0)); if (FAILED(hr)) goto done; pszDest = szDestBuf; for(pszSrc = szSrcBuf; *pszSrc != L'\0'; pszSrc++) { if (isalpha(*pszSrc) || isdigit(*pszSrc)) { *pszDest++ = *pszSrc; } else { *pszDest++ = L'%'; // get the trailing byte ch = (*pszSrc >> 4) & 0x0F; *pszDest++ = (ch < 10) ? ch + L'0' : (ch - 10) + L'A'; ch = *pszSrc & 0x0F; *pszDest++ = (ch < 10) ? ch + L'0' : (ch - 10) + L'A'; } } *pszDest = '\0'; // convert back to unicode TESTBOOL(hr, (MultiByteToWideChar(CP_ACP, 0, szDestBuf, -1, wszDest, cchDest) != 0)); if (FAILED(hr)) goto done; done: return hr; } //////////////////////////////////////////////////////////////////////////// // File mapping // ************************************************************************** HRESULT OpenFileMapped(LPWSTR wszFile, LPVOID *ppvFile, DWORD *pcbFile) { USE_TRACING("OpenFileMapped"); HRESULT hr = NOERROR; HANDLE hMMF = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; LPVOID pvFile = NULL; DWORD cbFile = 0; VALIDATEPARM(hr, (wszFile == NULL || ppvFile == NULL)); if (FAILED(hr)) goto done; *ppvFile = NULL; if (pcbFile != NULL) *pcbFile = 0; hFile = CreateFileW(wszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); TESTBOOL(hr, (hFile != INVALID_HANDLE_VALUE)); if (FAILED(hr)) goto done; cbFile = GetFileSize(hFile, NULL); TESTBOOL(hr, (cbFile != (DWORD)-1)); if (FAILED(hr)) goto done; hMMF = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, cbFile, NULL); TESTBOOL(hr, (hMMF != NULL)); if (FAILED(hr)) goto done; pvFile = MapViewOfFile(hMMF, FILE_MAP_READ, 0, 0, 0); TESTBOOL(hr, (pvFile != NULL)); if (FAILED(hr)) goto done; *ppvFile = pvFile; if (pcbFile != NULL) *pcbFile = cbFile; done: if (hMMF != NULL) CloseHandle(hMMF); if (hFile != NULL) CloseHandle(hFile); return hr; } // ************************************************************************** HRESULT DeleteTempFile(LPWSTR wszFile) { USE_TRACING("DeleteTempFile"); HRESULT hr = NOERROR; WCHAR *pwsz; if (wszFile == NULL) return NOERROR; // strip off the extension at the end (if it's not a .tmp) for(pwsz = wszFile + wcslen(wszFile); *pwsz != L'.' && pwsz > wszFile; pwsz--); if (pwsz > wszFile && _wcsicmp(pwsz, L".tmp") != 0) *pwsz = L'\0'; if (DeleteFileW(wszFile) == FALSE) hr = Err2HR(GetLastError()); // can do this even if the extension was a tmp since the value pointed to // by pwsz is '.' if it's greater than wszFile... if (pwsz > wszFile) *pwsz = L'.'; return hr; } ////////////////////////////////////////////////////////////////////////////// // Registry stuff // ************************************************************************** HRESULT OpenRegKey(HKEY hkeyMain, LPCWSTR wszSubKey, BOOL fWantWrite, HKEY *phkey) { USE_TRACING("OpenRegKey"); HRESULT hr = NOERROR; REGSAM samDesired; DWORD dwErr; VALIDATEPARM(hr, (hkeyMain == NULL || wszSubKey == NULL || phkey == NULL)); if (FAILED(hr)) goto done; *phkey = NULL; samDesired = (fWantWrite) ? KEY_ALL_ACCESS : KEY_READ; // first try calling RegCreateKeyEx to make sure we create the key if // it doesn't exist TESTERR(hr, RegCreateKeyExW(hkeyMain, wszSubKey, 0, NULL, 0, samDesired, NULL, phkey, NULL)); if (FAILED(hr)) { // ok, that didn't work, so try opening the key instead TESTERR(hr, RegOpenKeyExW(hkeyMain, wszSubKey, 0, samDesired, phkey)); } done: return hr; } // ************************************************************************** HRESULT ReadRegEntry(HKEY hkey, LPCWSTR wszValName, DWORD *pdwType, PBYTE pbBuffer, DWORD *pcbBuffer, PBYTE pbDefault, DWORD cbDefault) { USE_TRACING("ReadRegEntry"); HRESULT hr = NOERROR; DWORD dwErr; VALIDATEPARM(hr, (hkey == NULL || wszValName == NULL)); if (FAILED(hr)) goto done; dwErr = RegQueryValueExW(hkey, wszValName, 0, pdwType, pbBuffer, pcbBuffer); VALIDATEEXPR(hr, (dwErr != ERROR_PATH_NOT_FOUND && dwErr != ERROR_FILE_NOT_FOUND), Err2HR(dwErr)); if (FAILED(hr)) goto done; if (dwErr != ERROR_SUCCESS && pbDefault != NULL) { VALIDATEPARM(hr, (pcbBuffer == NULL && pbBuffer != NULL)); if (FAILED(hr)) goto done; // if the receiving buffer is NULL, just return the error that // RegQueryValueEx gave us cuz the user doesn't really want the // value anyway VALIDATEEXPR(hr, (pcbBuffer == NULL), Err2HR(dwErr)); if (FAILED(hr)) goto done; if (pbBuffer == NULL) { *pcbBuffer = cbDefault; hr = NOERROR; goto done; } else if (cbDefault > *pcbBuffer) { *pcbBuffer = cbDefault; hr = Err2HR(ERROR_MORE_DATA); goto done; } CopyMemory(pbBuffer, pbDefault, cbDefault); *pcbBuffer = cbDefault; if (pdwType != NULL) *pdwType = REG_BINARY; hr = NOERROR; goto done; } done: return hr; } ///////////////////////////////////////////////////////////////////////////// // ia64 data alignment workarounds #ifdef _WIN64 // *************************************************************************** ULONG64 AlignTo8Bytes(PBYTE pb) { ULONG64 ul; switch((DWORD_PTR)pb & 0x8) { // yay! already aligned case 0: ul = *(ULONG64 *)pb; break; case 1: case 5: ul = *pb << 56; ul |= *(ULONG32 *)(pb + 1) << 24; ul |= *(USHORT *)(pb + 5) << 8; ul |= *(pb + 7); break; case 2: case 6: ul = *(USHORT *)pb << 48; ul |= *(ULONG32 *)(pb + 2) << 16; ul |= *(USHORT *)(pb + 6); break; case 3: case 7: ul = *pb << 56; ul |= *(USHORT *)(pb + 1) << 48; ul |= *(ULONG32 *)(pb + 3) << 16; ul |= *(pb + 7); break; case 4: ul = *(ULONG32 *)pb << 32; ul |= *(ULONG32 *)(pb + 4); break; } return ul; } // *************************************************************************** ULONG32 AlignTo4Bytes(PBYTE pb) { ULONG32 ul; switch((DWORD_PTR)pb & 0x4) { // yay! already aligned case 0: ul = *(ULONG32 *)pb; break; case 1: case 3: ul = *pb << 24; ul |= *(short *)(pb + 1) << 8; ul |= *(pb + 3); break; case 2: ul = *(short *)pb << 16; ul |= *(short *)(pb + 2); break; } return ul; } #endif