Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

532 lines
14 KiB

/*----------------------------------------------------------------------------
/ Title;
/ misc.cpp
/
/ Authors;
/ David De Vorchik (daviddv)
/
/ Notes;
/ Misc functions
/----------------------------------------------------------------------------*/
#include "pch.h"
#include "atlbase.h"
#include <advpub.h> // 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("<none>"));
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