windows-nt/Source/XPSP1/NT/base/ntsetup/ocmanage/common/ocmisc.c
2020-09-26 16:20:57 +08:00

592 lines
12 KiB
C

#include "precomp.h"
#pragma hdrstop
// determines whether trace statements are printed
#define DBL_UNDEFINED ((DWORD)-1)
#define REGKEY_SETUP TEXT("SOFTWARE\\microsoft\\windows\\currentversion\\setup")
#define REGVAL_DBLEVEL TEXT("OC Manager Debug Level")
DWORD gDebugLevel = DBL_UNDEFINED;
//
// OC_MANAGER pointer for debugging/logging
//
extern POC_MANAGER gLastOcManager;
VOID
_DbgOut(
DWORD Severity,
LPCTSTR txt
);
DWORD
GetDebugLevel(
VOID
)
{
DWORD rc;
DWORD err;
DWORD size;
DWORD type;
HKEY hkey;
err = RegOpenKey(HKEY_LOCAL_MACHINE,
REGKEY_SETUP,
&hkey);
if (err != ERROR_SUCCESS)
return 0;
size = sizeof(DWORD);
err = RegQueryValueEx(hkey,
REGVAL_DBLEVEL,
0,
&type,
(LPBYTE)&rc,
&size);
if (err != ERROR_SUCCESS || type != REG_DWORD)
rc = 0;
RegCloseKey(hkey);
return rc;
}
UINT
_LogError(
IN POC_MANAGER OcManager,
IN OcErrorLevel ErrorLevel,
IN UINT MessageId,
...
)
{
TCHAR str[5000];
DWORD d;
va_list arglist;
va_start(arglist,MessageId);
d = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
MyModuleHandle,
MessageId,
0,
str,
sizeof(str)/sizeof(TCHAR),
&arglist
);
va_end(arglist);
if(!d) {
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
MyModuleHandle,
MSG_NOT_FOUND,
0,
str,
sizeof(str)/sizeof(TCHAR),
(va_list *)&MessageId
);
}
if ( OcManager->SetupData.OperationFlags & SETUPOP_BATCH) {
ErrorLevel |= OcErrBatch;
}
return OcLogError(ErrorLevel,str);
}
VOID
_TrcOut(
IN LPCTSTR Format,
...
)
{
TCHAR str[5000];
va_list arglist;
va_start(arglist,Format);
wvsprintf(str,Format,arglist);
va_end(arglist);
_DbgOut(OcErrTrace,str);
}
VOID
_WrnOut(
LPCTSTR Format,
...
)
{
TCHAR str[5000];
va_list arglist;
va_start(arglist,Format);
wvsprintf(str,Format,arglist);
va_end(arglist);
_DbgOut(OcErrLevWarning,str);
}
VOID
_ErrOut(
IN LPCTSTR Format,
...
)
{
TCHAR str[5000];
va_list arglist;
va_start(arglist,Format);
wvsprintf(str,Format,arglist);
va_end(arglist);
_DbgOut(OcErrLevFatal,str);
}
VOID
_DbgOut(
DWORD Severity,
IN LPCTSTR txt
)
{
#if 0
TCHAR str[5000];
va_list arglist;
va_start(arglist,Format);
wvsprintf(str,Format,arglist);
va_end(arglist);
#endif
if (gDebugLevel == DBL_UNDEFINED)
gDebugLevel = GetDebugLevel();
//
// for those people that *dont* want to see this debugger output, they can munge the registry
// to something between 50 and 100 to disable this.
// if we don't log some information on checked builds then we'll miss too many errors the first
// time around
//
if ( (gDebugLevel > 0) && (gDebugLevel < 50) )
return;
if (gLastOcManager) {
gLastOcManager->Callbacks.LogError(Severity, txt);
} else {
OutputDebugString(TEXT("OCMANAGE: "));
OutputDebugString(txt);
OutputDebugString(TEXT("\n"));
}
}
UINT
pOcCreateComponentSpecificMiniIcon(
IN POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN UINT Width,
IN UINT Height,
IN LPCTSTR DllName, OPTIONAL
IN LPCTSTR ResourceId OPTIONAL
)
{
HBITMAP BitmapFromComponent;
HBITMAP NewBitmap;
HBITMAP MaskBitmap;
HBITMAP OldBitmap1,OldBitmap2;
HDC MemDc1,MemDc2;
COLORREF BackgroundColor;
UINT Index;
BITMAP BitmapInfo;
BOOL b;
HMODULE hMod;
Index = DEFAULT_ICON_INDEX;
//
// If a dll name is given then fetch the bitmap from there.
// Otherwise, call down to the component to get the bitmap.
//
BitmapFromComponent = NULL;
if(DllName && ResourceId) {
if(hMod = LoadLibraryEx(DllName,NULL,LOAD_LIBRARY_AS_DATAFILE)) {
BitmapFromComponent = LoadBitmap(hMod,ResourceId);
FreeLibrary(hMod);
}
} else {
//
// first try OC_QUERY_IMAGE_EX for the bitmap
//
BitmapFromComponent = OcInterfaceQueryImageEx(
OcManager,
ComponentId,
Subcomponent,
SubCompInfoSmallIcon,
Width,
Height
);
#ifndef _WIN64
//
// OC_QUERY_IMAGE is broken for 64 bits, so only call this if we
// do not get an image reported for the component on 32 bit targets.
//
if (!BitmapFromComponent) {
BitmapFromComponent = OcInterfaceQueryImage(
OcManager,
ComponentId,
Subcomponent,
SubCompInfoSmallIcon,
Width,
Height
);
}
#else
if (!BitmapFromComponent) {
DbgPrintEx(
DPFLTR_SETUP_ID,
DPFLTR_ERROR_LEVEL,
"No bitmap defined for component. Ensure that component is handling OC_QUERY_IMAGE_EX callback\n");
}
#endif
}
if(!BitmapFromComponent) {
goto c0;
}
//
// Copy the bitmap given to us by the component.
// At the same time, make sure it's the right size.
//
MemDc1 = CreateCompatibleDC(NULL);
if(!MemDc1) {
goto c1;
}
MemDc2 = CreateCompatibleDC(NULL);
if(!MemDc2) {
goto c2;
}
if(!GetObject(BitmapFromComponent,sizeof(BitmapInfo),&BitmapInfo)) {
goto c3;
}
NewBitmap = CreateBitmap(Width,Height,BitmapInfo.bmPlanes,BitmapInfo.bmBitsPixel,NULL);
if(!NewBitmap) {
goto c3;
}
OldBitmap1 = SelectObject(MemDc1,BitmapFromComponent);
if(!OldBitmap1) {
goto c4;
}
OldBitmap2 = SelectObject(MemDc2,NewBitmap);
if(!OldBitmap2) {
goto c5;
}
b = StretchBlt(
MemDc2,
0,0,
Width,Height,
MemDc1,
0,0,
BitmapInfo.bmWidth,
BitmapInfo.bmHeight,
SRCCOPY
);
if(!b) {
goto c6;
}
//
// Now make the mask.
//
// The mask bitmap is monochrome. Pixels in the image bitmap that are
// the image bitmap's background color will be white in the mask;
// other pixels in the mask will be black. Assume the upper-left pixel
// of the image bitmap is the background color.
//
BackgroundColor = GetPixel(MemDc2,0,0);
if(BackgroundColor == CLR_INVALID) {
goto c6;
}
MaskBitmap = CreateBitmap(Width,Height,1,1,NULL);
if(!MaskBitmap) {
goto c6;
}
if(!SelectObject(MemDc1,MaskBitmap)) {
goto c7;
}
if(SetBkColor(MemDc2,BackgroundColor) == CLR_INVALID) {
goto c7;
}
if(!BitBlt(MemDc1,0,0,Width,Height,MemDc2,0,0,SRCCOPY)) {
goto c7;
}
//
// Black out all of the transparent parts of the image, in preparation
// for drawing.
//
SetBkColor(MemDc2,RGB(0,0,0));
SetTextColor(MemDc2,RGB(255,255,255));
if(!BitBlt(MemDc2,0,0,Width,Height,MemDc1,0,0,SRCAND)) {
goto c7;
}
//
// Before we call pSetupAddMiniIconToList we have to make sure
// neither bitmap is selected into a DC.
//
SelectObject(MemDc1,OldBitmap1);
SelectObject(MemDc2,OldBitmap2);
Index = pSetupAddMiniIconToList(NewBitmap,MaskBitmap);
if(Index == -1) {
Index = DEFAULT_ICON_INDEX;
}
c7:
DeleteObject(MaskBitmap);
c6:
SelectObject(MemDc2,OldBitmap2);
c5:
SelectObject(MemDc1,OldBitmap1);
c4:
DeleteObject(NewBitmap);
c3:
DeleteDC(MemDc2);
c2:
DeleteDC(MemDc1);
c1:
DeleteObject(BitmapFromComponent);
c0:
return(Index);
}
BOOL
pConvertStringToLongLong(
IN PCTSTR String,
OUT PLONGLONG OutValue
)
/*++
Routine Description:
Arguments:
Return Value:
Remarks:
Hexadecimal numbers are also supported. They must be prefixed by '0x' or '0X', with no
space allowed between the prefix and the number.
--*/
{
LONGLONG Value;
UINT c;
BOOL Neg;
UINT Base;
UINT NextDigitValue;
LONGLONG OverflowCheck;
BOOL b;
if(!String || !OutValue) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if(*String == TEXT('-')) {
Neg = TRUE;
String++;
} else {
Neg = FALSE;
if(*String == TEXT('+')) {
String++;
}
}
if((*String == TEXT('0')) &&
((*(String+1) == TEXT('x')) || (*(String+1) == TEXT('X')))) {
//
// The number is in hexadecimal.
//
Base = 16;
String += 2;
} else {
//
// The number is in decimal.
//
Base = 10;
}
for(OverflowCheck = Value = 0; *String; String++) {
c = (UINT)*String;
if((c >= (UINT)'0') && (c <= (UINT)'9')) {
NextDigitValue = c - (UINT)'0';
} else if(Base == 16) {
if((c >= (UINT)'a') && (c <= (UINT)'f')) {
NextDigitValue = (c - (UINT)'a') + 10;
} else if ((c >= (UINT)'A') && (c <= (UINT)'F')) {
NextDigitValue = (c - (UINT)'A') + 10;
} else {
break;
}
} else {
break;
}
Value *= Base;
Value += NextDigitValue;
//
// Check for overflow. For decimal numbers, we check to see whether the
// new value has overflowed into the sign bit (i.e., is less than the
// previous value. For hexadecimal numbers, we check to make sure we
// haven't gotten more digits than will fit in a DWORD.
//
if(Base == 16) {
if(++OverflowCheck > (sizeof(LONGLONG) * 2)) {
break;
}
} else {
if(Value < OverflowCheck) {
break;
} else {
OverflowCheck = Value;
}
}
}
if(*String) {
SetLastError(ERROR_INVALID_DATA);
return(FALSE);
}
if(Neg) {
Value = 0-Value;
}
b = TRUE;
try {
*OutValue = Value;
} except(EXCEPTION_EXECUTE_HANDLER) {
b = FALSE;
}
if(!b) {
SetLastError(ERROR_INVALID_PARAMETER);
}
return(b);
}
DWORD
tmbox(
LPCTSTR fmt,
...
)
{
TCHAR text[1024];
TCHAR caption[256];
va_list vaList;
sapiAssert(fmt);
va_start(vaList, fmt);
wvsprintf(text, fmt, vaList);
va_end(vaList);
*caption = 0;
LoadString(MyModuleHandle, IDS_SETUP, caption, sizeof(caption)/sizeof(TCHAR));
sapiAssert(*caption);
return MessageBox(WizardDialogHandle,
text,
caption,
MB_ICONINFORMATION | MB_OK);
}
#ifdef PRERELEASE
#ifdef DBG
HRESULT
FTestForOutstandingCoInits(
VOID
)
/*++
Routine Description: Determines is there was an unitialized call to OleInitialize()
Arguments:
NONE
Return Value:
an HRESULT code
Remarks:
Don't call this function in the release version.
--*/
{
HRESULT hInitRes = ERROR_SUCCESS;
#if defined(UNICODE) || defined(_UNICODE)
// perform a defensive check
hInitRes = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if ( SUCCEEDED(hInitRes) )
{
CoUninitialize();
}
else
{
goto FTestForOutstandingCoInits_Exit;
}
hInitRes = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
if ( SUCCEEDED(hInitRes) )
{
CoUninitialize();
}
else
{
goto FTestForOutstandingCoInits_Exit;
}
#endif
// it worked out OK
hInitRes = NOERROR;
goto FTestForOutstandingCoInits_Exit;
FTestForOutstandingCoInits_Exit:
return hInitRes;
}
#endif
#endif