/*---------------------------------------------------------------------------- / Title; / misc.cpp / / Authors; / David De Vorchik (daviddv) / / Notes; / Misc functions /----------------------------------------------------------------------------*/ #include "pch.h" #include "atlbase.h" #include // For REGINSTALL #pragma hdrstop /*----------------------------------------------------------------------------- / GetKeyForCLSID / -------------- / Given a reference to a CLSID open up the key that represents it. / / In: / clsid = clsid reference / pSubKey -> name of sub key to be opened / phkey = receives the newly opened key / / Out: / HRESULT /----------------------------------------------------------------------------*/ EXTERN_C HRESULT GetKeyForCLSID(REFCLSID clsid, LPCTSTR pSubKey, HKEY* phkey) { HRESULT hr; TCHAR szBuffer[(MAX_PATH*2)+GUIDSTR_MAX]; TCHAR szGuid[GUIDSTR_MAX]; TraceEnter(TRACE_COMMON_MISC, "GetKeyForCLSID"); TraceGUID("clsid", clsid); Trace(TEXT("pSubKey -%s-"), pSubKey ? pSubKey:TEXT("")); TraceAssert(phkey); // - format the CLSID so we can find it in the registry // - then open it (the client is reponsible for closing it) *phkey = NULL; // incase we fail if ( 0 == GetStringFromGUID(clsid, szGuid, ARRAYSIZE(szGuid)) ) ExitGracefully(hr, E_FAIL, "Failed to convert GUID to string"); wsprintf(szBuffer, TEXT("CLSID\\%s"), szGuid); if ( pSubKey ) { StrCat(szBuffer, TEXT("\\")); StrCat(szBuffer, pSubKey); } Trace(TEXT("Trying to open -%s-"), szBuffer); if ( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuffer, NULL, KEY_READ, phkey) ) ExitGracefully(hr, E_FAIL, "Failed to open key"); hr = S_OK; // success exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / GetRealWindowInfo / ----------------- / Get the window dimensions and client position. / / In: / hwnd = window to enquire about / pRect -> receives the client position of the window / == NULL / pSize -> receives the size of the window / == NULL / / Out: / - /----------------------------------------------------------------------------*/ EXTERN_C HRESULT GetRealWindowInfo(HWND hwnd, LPRECT pRect, LPSIZE pSize) { HRESULT hr; RECT rect; TraceEnter(TRACE_COMMON_MISC, "GetRealWindowInfo"); if ( !GetWindowRect(hwnd, &rect) ) ExitGracefully(hr, E_FAIL, "Failed to get window rectangles"); MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rect, 2); if ( pRect ) *pRect = rect; if ( pSize ) { pSize->cx = rect.right - rect.left; pSize->cy = rect.bottom - rect.top; } hr = S_OK; exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / OffsetWindow / ------------ / Adjust the position of the given window by the given delta. If the / delta is 0,0 then this is a NOP. / / In: / hwnd = window to enquire about / dx, dy = offset to be applied to the window / / Out: / - /----------------------------------------------------------------------------*/ EXTERN_C VOID OffsetWindow(HWND hwnd, INT dx, INT dy) { RECT rect; TraceEnter(TRACE_COMMON_MISC, "OffsetWindow"); if ( hwnd && (dx || dy) ) { GetWindowRect(hwnd, &rect); MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rect, 2); SetWindowPos(hwnd, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER|SWP_NOSIZE); } TraceLeave(); } /*----------------------------------------------------------------------------- / CallRegInstall / -------------- / Call ADVPACK for the given section of our resource based INF> / / In: / hInstance = resource instance to get REGINST section from / szSection = section name to invoke / / Out: / HRESULT: /----------------------------------------------------------------------------*/ EXTERN_C HRESULT CallRegInstall(HINSTANCE hInstance, LPSTR szSection) { HRESULT hr = E_FAIL; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); TraceEnter(TRACE_COMMON_MISC, "CallRegInstall"); if (hinstAdvPack) { REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall"); #ifdef UNICODE if ( pfnri ) { STRENTRY seReg[] = { // These two NT-specific entries must be at the end { "25", "%SystemRoot%" }, { "11", "%SystemRoot%\\system32" }, }; STRTABLE stReg = { ARRAYSIZE(seReg), seReg }; hr = pfnri(hInstance, szSection, &stReg); } #else if (pfnri) { hr = pfnri(hInstance, szSection, NULL); } #endif FreeLibrary(hinstAdvPack); } TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / SetDefButton / ------------ / Jump through hoops, avoid barking dogs and dice with death all to set / the default button in a dialog. / / In: / hWnd, idButton = button to set / / Out: / HRESULT: /----------------------------------------------------------------------------*/ EXTERN_C VOID SetDefButton(HWND hwndDlg, int idButton) { LRESULT lr; LONG style; TraceEnter(TRACE_COMMON_MISC, "SetDefButton"); if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID) { HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr)); style = GetWindowLong(hwndOldDefButton, GWL_STYLE) & ~BS_DEFPUSHBUTTON; SendMessage (hwndOldDefButton, BM_SETSTYLE, MAKEWPARAM(style, 0), MAKELPARAM(TRUE, 0)); } SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L ); style = GetWindowLong(GetDlgItem(hwndDlg, idButton), GWL_STYLE)| BS_DEFPUSHBUTTON; SendMessage( GetDlgItem(hwndDlg, idButton), BM_SETSTYLE, MAKEWPARAM( style, 0 ), MAKELPARAM( TRUE, 0 )); TraceLeave(); } /*----------------------------------------------------------------------------- / Data collection functions /----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- / AllocStorageMedium / ------------------ / Allocate a storage medium (validating the clipboard format as required). / / In: / pFmt, pMedium -> describe the allocation / cbStruct = size of allocation / ppAlloc -> receives a pointer to the allocation / = NULL / / Out: / HRESULT /----------------------------------------------------------------------------*/ EXTERN_C HRESULT AllocStorageMedium(FORMATETC* pFmt, STGMEDIUM* pMedium, SIZE_T cbStruct, LPVOID* ppAlloc) { HRESULT hr; TraceEnter(TRACE_COMMON_MISC, "AllocStorageMedium"); TraceAssert(pFmt); TraceAssert(pMedium); // Validate parameters if ( ( cbStruct <= 0 ) || !( pFmt->tymed & TYMED_HGLOBAL ) ) ExitGracefully(hr, E_INVALIDARG, "Zero size stored medium requested or non HGLOBAL"); if ( ( pFmt->ptd ) || !( pFmt->dwAspect & DVASPECT_CONTENT) || !( pFmt->lindex == -1 ) ) ExitGracefully(hr, E_INVALIDARG, "Bad format requested"); // Allocate the medium via GlobalAlloc pMedium->tymed = TYMED_HGLOBAL; pMedium->hGlobal = GlobalAlloc(GPTR, cbStruct); pMedium->pUnkForRelease = NULL; if ( !pMedium->hGlobal ) ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate StgMedium"); hr = S_OK; // success exit_gracefully: if ( ppAlloc ) *ppAlloc = SUCCEEDED(hr) ? (LPVOID)pMedium->hGlobal:NULL; TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / CopyStorageMedium / ------------------ / Copies a storage medium (and the data in an HGLOBAL). Only works / for TYMED_HGLOBAL mediums... / / In: / pMediumDst -> where to copy to... / pFmt, pMediumSrc -> describe the source / / Out: / HRESULT /----------------------------------------------------------------------------*/ EXTERN_C HRESULT CopyStorageMedium(FORMATETC* pFmt, STGMEDIUM* pMediumDst, STGMEDIUM* pMediumSrc) { HRESULT hr; LPVOID pSrc, pDst; HGLOBAL hGlobal; SIZE_T cbStruct; TraceEnter(TRACE_COMMON_MISC, "CopyStorageMedium"); if ( !(pFmt->tymed & TYMED_HGLOBAL) ) ExitGracefully(hr, E_INVALIDARG, "Only HGLOBAL mediums suppported to copy"); // stored in a HGLOBAl, therefore get the size, allocate a new storage // object and copy the data away into it. cbStruct = GlobalSize((HGLOBAL)pMediumSrc->hGlobal); hr = AllocStorageMedium(pFmt, pMediumDst, cbStruct, (LPVOID*)&hGlobal); FailGracefully( hr, "Unable to allocated storage medium" ); *pMediumDst = *pMediumSrc; pMediumDst->hGlobal = hGlobal; pSrc = GlobalLock(pMediumSrc->hGlobal); pDst = GlobalLock(pMediumDst->hGlobal); CopyMemory(pDst, pSrc, cbStruct); GlobalUnlock(pMediumSrc->hGlobal); GlobalUnlock(pMediumDst->hGlobal); hr = S_OK; // success exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / GetStringFromGUID / ----------------- / Given a GUID convert it to a string. / / In: / rGUID = guid to be converted / psz, cchMax = buffer to fill / / Out: / NUMBER OF characters /----------------------------------------------------------------------------*/ static const BYTE c_rgbGuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 }; static const TCHAR c_szDigits[] = TEXT("0123456789ABCDEF"); EXTERN_C INT GetStringFromGUID(UNALIGNED REFGUID rguid, LPTSTR psz, INT cchMax) { INT i; const BYTE* pBytes = (const BYTE*)&rguid; if ( cchMax < GUIDSTR_MAX ) return 0; #ifdef BIG_ENDIAN // This is the slow, but portable version wsprintf(psz, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), rguid->Data1, rguid->Data2, rguid->Data3, rguid->Data4[0], rguid->Data4[1], rguid->Data4[2], rguid->Data4[3], rguid->Data4[4], rguid->Data4[5], rguid->Data4[6], rguid->Data4[7]); #else // The following algorithm is faster than the wsprintf. *psz++ = TEXT('{'); for (i = 0; i < SIZEOF(c_rgbGuidMap); i++) { if (c_rgbGuidMap[i] == TEXT('-')) // don't TEXT() this line { *psz++ = TEXT('-'); } else { // Convert a byte-value into a character representation *psz++ = c_szDigits[ (pBytes[c_rgbGuidMap[i]] & 0xF0) >> 4 ]; *psz++ = c_szDigits[ (pBytes[c_rgbGuidMap[i]] & 0x0F) ]; } } *psz++ = TEXT('}'); *psz = TEXT('\0'); #endif /* !BIG_ENDIAN */ return GUIDSTR_MAX; } /*----------------------------------------------------------------------------- / GetGUIDFromString / ----------------- / Given a string convert it to a GUID. / / In: / psz -> string to be parsed / rGUID = GUID return into / / Out: / BOOL /----------------------------------------------------------------------------*/ BOOL _HexStringToDWORD(LPCTSTR * ppsz, DWORD * lpValue, int cDigits, TCHAR chDelim) { int ich; LPCTSTR psz = *ppsz; DWORD Value = 0; BOOL fRet = TRUE; for (ich = 0; ich < cDigits; ich++) { TCHAR ch = psz[ich]; if (InRange(ch, TEXT('0'), TEXT('9'))) { Value = (Value << 4) + ch - TEXT('0'); } else if ( InRange( (ch |= (TEXT('a')-TEXT('A'))), TEXT('a'), TEXT('f')) ) { Value = (Value << 4) + ch - TEXT('a') + 10; } else return(FALSE); } if (chDelim) { fRet = (psz[ich++] == chDelim); } *lpValue = Value; *ppsz = psz+ich; return fRet; } #ifndef UNICODE EXTERN_C BOOL GetGUIDFromStringW(LPCWSTR psz, GUID* pguid) { USES_CONVERSION; return GetGUIDFromString(W2CT(psz), pguid); } #endif EXTERN_C BOOL GetGUIDFromString(LPCTSTR psz, GUID* pguid) { DWORD dw; if (*psz++ != TEXT('{') /*}*/ ) return FALSE; if (!_HexStringToDWORD(&psz, &pguid->Data1, SIZEOF(DWORD)*2, TEXT('-'))) return FALSE; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(WORD)*2, TEXT('-'))) return FALSE; pguid->Data2 = (WORD)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(WORD)*2, TEXT('-'))) return FALSE; pguid->Data3 = (WORD)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[0] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, TEXT('-'))) return FALSE; pguid->Data4[1] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[2] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[3] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[4] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[5] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0)) return FALSE; pguid->Data4[6] = (BYTE)dw; if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, /*(*/ TEXT('}'))) return FALSE; pguid->Data4[7] = (BYTE)dw; return TRUE; } // // Replacement for LoadStringW that will work on the Win95 downlevel client // #ifndef UNICODE EXTERN_C INT MyLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR pszBuffer, INT cchBuffer) { TCHAR szBuffer[MAX_PATH]; INT cchResult; cchResult = LoadString(hInstance, uID, szBuffer, ARRAYSIZE(szBuffer)); MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, pszBuffer, cchBuffer); return cchResult; } #endif