windows-nt/Source/XPSP1/NT/admin/pchealth/sr/shell/util.cpp
2020-09-26 16:20:57 +08:00

768 lines
18 KiB
C++

/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
util.cpp
Abstract:
This file contains the implementation of common utility functions.
Revision History:
Seong Kook Khang (SKKhang) 07/07/99
created
******************************************************************************/
#include "stdwin.h"
#include "resource.h"
#include "rstrpriv.h"
/////////////////////////////////////////////////////////////////////////////
//
// Utility Functions
//
/////////////////////////////////////////////////////////////////////////////
#define CAL_TYPE_GREGORIAN_LOCALZED 1
#define CAL_TYPE_GREGORIAN_ENGLISH 2
#define CAL_TYPE_ERA_JAPAN 3
#define CAL_TYPE_ERA_TAIWAN 4
#define CAL_TYPE_ERA_KOREA 5
#define CAL_TYPE_ARABIC_HIJRI 6
#define CAL_TYPE_THAI 7
#define CAL_TYPE_HEBREW 8
#define CAL_TYPE_GREGORIAN_MIDDLE_EAST_FRENCH 9
#define CAL_TYPE_GREGORIAN_ARABIC 10
#define CAL_TYPE_GREGORIAN_TRANSLITERATED_ENGLISH 11
#define CAL_TYPE_GREGORIAN_TRANSLITERATED_FRENCH 12
#define CAL_RSTRUI_GREGORIAN 1
#define CAL_RSTRUI_OTHER 2
static int s_nCalType = CAL_RSTRUI_GREGORIAN ;
int SRUtil_SetCalendarTypeBasedOnLocale(LCID locale)
{
LPCWSTR cszErr;
int nRet;
WCHAR szCalType[8];
int nCalType;
nRet = ::GetLocaleInfo( locale,
LOCALE_ICALENDARTYPE,
szCalType,
sizeof(szCalType)/sizeof(WCHAR));
if ( nRet == 0 )
{
cszErr = ::GetSysErrStr();
// ErrorTrace(TRACE_ID, "GetLocaleInfo(%d) failed - %s", locale, cszErr);
goto Exit;
}
nCalType = ::_wtoi( szCalType );
if ( CAL_TYPE_GREGORIAN_LOCALZED == nCalType ||
CAL_TYPE_GREGORIAN_ENGLISH == nCalType ||
CAL_TYPE_GREGORIAN_MIDDLE_EAST_FRENCH == nCalType ||
CAL_TYPE_GREGORIAN_ARABIC == nCalType ||
CAL_TYPE_GREGORIAN_TRANSLITERATED_ENGLISH == nCalType ||
CAL_TYPE_GREGORIAN_TRANSLITERATED_FRENCH == nCalType )
{
s_nCalType = CAL_RSTRUI_GREGORIAN ;
}
else
{
s_nCalType = CAL_RSTRUI_OTHER ;
}
Exit:
return nRet ;
}
/******************************************************************************/
LPSTR IStrDupA( LPCSTR szSrc )
{
TraceFunctEnter("IStrDupA");
int ccLen = 0 ;
LPSTR szNew = NULL;
if ( szSrc == NULL || szSrc[0] == '\0' )
goto Exit;
ccLen = ::lstrlenA( szSrc );
szNew = new char[ccLen+2];
if ( szNew != NULL )
{
::lstrcpyA( szNew, szSrc );
}
Exit:
TraceFunctLeave();
return( szNew );
}
/******************************************************************************/
LPWSTR IStrDupW( LPCWSTR wszSrc )
{
TraceFunctEnter("IStrDupW");
int ccLen = 0 ;
LPWSTR wszNew = NULL ;
if ( wszSrc == NULL || wszSrc[0] == L'\0' )
goto Exit;
ccLen = ::lstrlenW( wszSrc );
wszNew = new WCHAR[ccLen+2];
if ( wszNew != NULL )
{
::lstrcpyW( wszNew, wszSrc );
}
Exit:
TraceFunctLeave();
return( wszNew );
}
/****************************************************************************/
BOOL
SRFormatMessage( LPWSTR szMsg, UINT uFmtId, ... )
{
TraceFunctEnter("SRFormatMessage");
BOOL fRet = FALSE;
va_list marker;
WCHAR szFmt[MAX_STR_MSG];
va_start( marker, uFmtId );
::LoadString( g_hInst, uFmtId, szFmt, MAX_STR_MSG );
if ( 0 == ::FormatMessage( FORMAT_MESSAGE_FROM_STRING,
szFmt,
0,
0,
szMsg,
MAX_STR_MSG,
&marker ) )
{
LPCWSTR cszErr = ::GetSysErrStr();
ErrorTrace(0, "::FormatMessage failed - %ls", cszErr);
goto Exit;
}
va_end( marker );
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/****************************************************************************/
BOOL ShowSRErrDlg( UINT uMsgId, ... )
{
TraceFunctEnter("ShowSRErrDlg");
BOOL fRet = FALSE;
LPCWSTR cszErr;
va_list marker;
WCHAR szTitle[MAX_STR_TITLE];
WCHAR szFmt[MAX_STR_MSG];
WCHAR szMsg[MAX_STR_MSG];
if ( ::LoadString( g_hInst, IDS_RESTOREUI_TITLE, szTitle, MAX_STR_TITLE ) == 0 )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::LoadString(%u) failed - %ls", IDS_RESTOREUI_TITLE, cszErr);
goto Exit;
}
if ( ::LoadString( g_hInst, uMsgId, szFmt, MAX_STR_MSG ) == 0 )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::LoadString(%u) failed - %ls", uMsgId, cszErr);
goto Exit;
}
va_start( marker, uMsgId );
::wvsprintf( szMsg, szFmt, marker );
va_end( marker );
::MessageBox( NULL, szMsg, szTitle, MB_OK );
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/****************************************************************************/
BOOL SRGetRegDword( HKEY hKey, LPCWSTR cszSubKey, LPCWSTR cszValue, DWORD *pdwData )
{
TraceFunctEnter("SRGetRegDword");
BOOL fRet = FALSE;
DWORD dwType;
DWORD dwRes;
DWORD cbData;
dwType = REG_DWORD;
cbData = sizeof(DWORD);
dwRes = ::SHGetValue( hKey, cszSubKey, cszValue, &dwType, pdwData, &cbData );
if ( dwRes != ERROR_SUCCESS )
{
LPCWSTR cszErr = ::GetSysErrStr( dwRes );
ErrorTrace(0, "::SHGetValue failed - %ls", cszErr);
goto Exit;
}
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/******************************************************************************/
/*
static WCHAR s_wszPath[MAX_PATH];
LPWSTR PathElem2Str( PathElement *pElem )
{
TraceFunctEnter("PathElem2Str");
int cch = pElem->pe_length / sizeof(USHORT) - 1;
::StrCpyNW( s_wszPath, pElem->pe_unichars, cch+1 );
// for ( int i = 0; i < ccLen; i++ )
// wszElem[i] = pElem->pe_unichars[i];
s_wszPath[cch] = '\0';
TraceFunctLeave();
return( s_wszPath );
}
LPWSTR ParsedPath2Str( ParsedPath *pPath, LPCWSTR wszDrive )
{
TraceFunctEnter("ParsedPath2Str");
LPWSTR wszAppend;
PathElement *pElem;
int cch;
if ( pPath != NULL )
{
::lstrcpyW( s_wszPath, wszDrive );
wszAppend = s_wszPath + ::lstrlenW( s_wszPath );
for ( pElem = pPath->pp_elements; pElem->pe_length > 0; pElem = IFSNextElement( pElem ) )
{
DebugTrace(0, "pElem->pe_length=%d", pElem->pe_length);
*wszAppend++ = L'\\';
cch = pElem->pe_length / sizeof(USHORT) - 1;
::StrCpyNW( wszAppend, pElem->pe_unichars, cch+1 );
wszAppend += cch;
}
*wszAppend = L'\0';
}
else
{
*s_wszPath = L'\0';
}
TraceFunctLeave();
return( s_wszPath );
}
*/
/******************************************************************************/
//
// Check if we have enough free space in Windows directory and this is
// greater than the minimum requirments for carrying out a restore, this
// also reads and caches the registry data. If registry data cannot be
// read defaults in the code will be used
//
BOOL IsFreeSpaceOnWindowsDrive( void )
{
TraceFunctEnter("IsFreeSpaceOnWindowsDrive");
static BOOL fFirstTime = TRUE ;
static DWORD dwMinValidSpace = RSTRMAP_MIN_WIN_DISK_SPACE_MB * (1024 * 1024) ;
static WCHAR szWinPath[MAX_PATH+1];
ULARGE_INTEGER i64FreeBytesToCaller;
ULARGE_INTEGER i64FreeBytes ;
ULARGE_INTEGER i64TotalBytes ;
BOOL fResult = FALSE ;
BOOL fRetVal = TRUE ;
DWORD dwError;
LPCWSTR cszErr;
long lRetVal = 0;
HKEY hKey = NULL;
DWORD dwVal = 0;
DWORD dwType = 0;
DWORD cbData = sizeof(DWORD);
//
// Read registry and get the size of FreezeSize and set the min
// size for disk on data store
//
if ( fFirstTime )
{
#ifdef LEGACY_CODE
if ( !::GetWindowsDirectory( szWinPath, MAX_PATH ) )
{
cszErr = GetSysErrStr();
ErrorTrace(TRACE_ID, "::GetWindowsDirectory failed - %s", cszErr);
goto Exit;
}
DebugTrace(TRACE_ID, "Opening: %s", s_cszReservedDiskSpaceKey);
//
// Open HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\StateMgr\ReservedDiskSpace
// for reading
//
lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
s_cszReservedDiskSpaceKey,
0,
KEY_READ,
&hKey);
if( ERROR_SUCCESS == lRetVal)
{
DebugTrace(TRACE_ID, "Querying: %s", s_cszUIFreezeSize);
//
// Read "FreezeSize"
//
lRetVal = RegQueryValueEx(hKey,
s_cszUIFreezeSize,
0,
&dwType,
(LPBYTE)&dwVal,
&cbData);
if( ERROR_SUCCESS == lRetVal)
{
if ( dwVal < RSTRMAP_LOW_WIN_DISK_SPACE_MB )
{
dwVal = RSTRMAP_LOW_WIN_DISK_SPACE_MB;
};
dwMinValidSpace = dwVal * (1024 * 1024) ;
}
else
{
ErrorTrace(TRACE_ID, "RegQueryValueEx failed; hr=0x%x", GetLastError());
}
}
else
{
ErrorTrace(TRACE_ID, "RegOpenKeyEx failed; hr=0x%x", GetLastError());
}
#endif //def LEGACY_CODE
fFirstTime = FALSE ;
}
fRetVal = TRUE ;
fResult = GetDiskFreeSpaceEx(szWinPath,
(PULARGE_INTEGER) &i64FreeBytesToCaller,
(PULARGE_INTEGER) &i64TotalBytes,
(PULARGE_INTEGER) &i64FreeBytes);
if ( fResult )
{
//
// Now check if disk free space is greater than min space (high 4GB)
//
if (i64FreeBytes.HighPart > 0 )
{
goto Exit;
}
else if (i64FreeBytesToCaller.LowPart > dwMinValidSpace )
{
goto Exit;
}
else
{
fRetVal = FALSE ;
goto Exit;
}
}
else
{
//
// If the function fails its Ok to try to go on as the Restore Undo
// should handle it if things get very full
//
dwError = ::GetLastError();
ErrorTrace(TRACE_ID, "GetDiskFreeSpaceEx failed. ec=%d", dwError);
goto Exit;
};
Exit:
TraceFunctLeave();
return fRetVal ;
}
//
// Get the default language for the current user
//
LANGID GetDefaultUILang(void)
{
OSVERSIONINFO Osv ;
BOOL IsWindowsNT ;
LANGID wUILang = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US);
Osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
if(!GetVersionEx(&Osv))
{
goto Exit ;
}
IsWindowsNT = (BOOL) (Osv.dwPlatformId == VER_PLATFORM_WIN32_NT) ;
//
// Get the UI language by one of three methods, depending on the system
//
if(!IsWindowsNT)
{
//
// Case 1: Running on Windows 9x. Get the system UI language from registry:
//
CHAR szData[32] ;
DWORD dwErr, dwSize = sizeof(szData) ;
HKEY hKey ;
dwErr = RegOpenKeyEx(
HKEY_USERS,
TEXT(".Default\\Control Panel\\desktop\\ResourceLocale"),
0,
KEY_READ,
&hKey
) ;
if(ERROR_SUCCESS != dwErr)
{
goto Exit ;
}
dwErr = RegQueryValueEx(
hKey,
TEXT(""),
NULL, //reserved
NULL, //type
(LPBYTE) szData,
&dwSize
) ;
if(ERROR_SUCCESS != dwErr)
{
goto Exit ;
}
dwErr = RegCloseKey(hKey) ;
// Convert string to number
wUILang = (LANGID) strtol(szData, NULL, 16) ;
}
Exit:
return wUILang ;
}
/////////////////////////////////////////////////////////////////////////////
//
// CSRStr
//
/////////////////////////////////////////////////////////////////////////////
CSRStr::CSRStr()
{
TraceFunctEnter("CSRStr::CSRStr()");
m_cchW = 0;
m_strW = NULL;
m_cchA = 0;
m_strA = NULL;
TraceFunctLeave();
}
CSRStr::CSRStr( LPCWSTR wszSrc )
{
TraceFunctEnter("CSRStr::CSRStr(LPCWSTR)");
m_strW = NULL;
m_strA = NULL;
SetStr( wszSrc );
TraceFunctLeave();
}
CSRStr::CSRStr( LPCSTR szSrc )
{
TraceFunctEnter("CSRStr::CSRStr(LPCSTR)");
m_strW = NULL;
m_strA = NULL;
SetStr( szSrc );
TraceFunctLeave();
}
CSRStr::~CSRStr()
{
TraceFunctEnter("CSRStr::~CSRStr");
Empty();
TraceFunctLeave();
}
int CSRStr::LengthW()
{
TraceFunctEnter("CSRStr::CountW");
if ( m_cchW == 0 && m_strA != NULL )
ConvertA2W();
TraceFunctLeave();
return( m_cchW );
}
int CSRStr::LengthA()
{
TraceFunctEnter("CSRStr::CountA");
if ( m_cchA == 0 && m_strW != NULL )
ConvertW2A();
TraceFunctLeave();
return( m_cchA );
}
CSRStr::operator LPCWSTR()
{
TraceFunctEnter("CSRStr::operator LPCWSTR");
if ( m_strW == NULL && m_strA != NULL )
ConvertA2W();
TraceFunctLeave();
return( m_strW );
}
CSRStr::operator LPCSTR()
{
TraceFunctEnter("CSRStr::operator LPCSTR");
if ( m_strA == NULL && m_strW != NULL )
ConvertW2A();
TraceFunctLeave();
return( m_strA );
}
void CSRStr::Empty()
{
TraceFunctEnter("CSRStr::Empty");
if ( m_strW != NULL )
{
delete [] m_strW;
m_strW = NULL;
m_cchW = 0;
}
if ( m_strA != NULL )
{
delete [] m_strA;
m_strA = NULL;
m_cchA = 0;
}
TraceFunctLeave();
}
BOOL CSRStr::SetStr( LPCWSTR wszSrc, int cch )
{
TraceFunctEnter("CSRStr::SetStr(LPCWSTR,int)");
BOOL fRet = FALSE;
Empty();
if ( wszSrc == NULL )
goto Exit;
if ( cch == -1 )
cch = ::lstrlenW( wszSrc );
if ( cch > 0 )
{
m_strW = new WCHAR[cch+2];
if ( m_strW == NULL )
{
ErrorTrace(TRACE_ID, "Insufficient memory...");
goto Exit;
}
::StrCpyNW( m_strW, wszSrc, cch+1 );
m_strW[cch] = L'\0';
m_cchW = cch;
}
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
BOOL CSRStr::SetStr( LPCSTR szSrc, int cch )
{
TraceFunctEnter("CSRStr::SetStr(LPCSTR,int)");
BOOL fRet = FALSE;
Empty();
if ( szSrc == NULL )
goto Exit;
if ( cch == -1 )
cch = ::lstrlenA( szSrc );
if ( cch > 0 )
{
m_strA = new char[cch+2];
if ( m_strA == NULL )
{
ErrorTrace(TRACE_ID, "Insufficient memory...");
goto Exit;
}
::lstrcpynA( m_strA, szSrc, cch+1 );
m_strA[cch] = L'\0';
m_cchA = cch;
}
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
const CSRStr& CSRStr::operator =( LPCWSTR wszSrc )
{
TraceFunctEnter("CSRStr::operator =(LPCWSTR)");
SetStr( wszSrc );
TraceFunctLeave();
return( *this );
}
const CSRStr& CSRStr::operator =( LPCSTR szSrc )
{
TraceFunctEnter("CSRStr::operator =(LPCSTR)");
SetStr( szSrc );
TraceFunctLeave();
return( *this );
}
BOOL CSRStr::ConvertA2W()
{
TraceFunctEnter("CSRStr::ConvertA2W");
BOOL fRet = FALSE;
LPCWSTR cszErr;
int cch;
cch = ::MultiByteToWideChar( CP_ACP, 0, m_strA, m_cchA, NULL, 0 );
if ( cch == 0 )
{
cszErr = ::GetSysErrStr();
ErrorTrace(TRACE_ID, "::MultiByteToWideChar failed - %s", cszErr);
goto Exit;
}
m_strW = new WCHAR[cch+2];
if ( m_strW == NULL )
{
ErrorTrace(TRACE_ID, "Insufficient memory...");
goto Exit;
}
m_cchW = ::MultiByteToWideChar( CP_ACP, 0, m_strA, m_cchA, m_strW, cch );
if ( m_cchW != cch )
{
ErrorTrace(TRACE_ID, "::MultiByteToWideChar returns inconsistent length - %d / %d", cch, m_cchW);
delete [] m_strW;
m_strW = NULL;
m_cchW = 0;
goto Exit;
}
m_strW[m_cchW] = L'\0';
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
BOOL CSRStr::ConvertW2A()
{
TraceFunctEnter("CSRStr::ConvertW2A");
BOOL fRet = FALSE;
LPCWSTR cszErr;
int cch;
cch = ::WideCharToMultiByte( CP_ACP, 0, m_strW, m_cchW, NULL, 0, NULL, NULL );
if ( cch == 0 )
{
cszErr = GetSysErrStr();
ErrorTrace(TRACE_ID, "::WideCharToMultiByte failed - %s", cszErr);
goto Exit;
}
m_strA = new char[cch+2];
if ( m_strA == NULL )
{
ErrorTrace(TRACE_ID, "Insufficient memory...");
goto Exit;
}
m_cchA = ::WideCharToMultiByte( CP_ACP, 0, m_strW, m_cchW, m_strA, cch, NULL, NULL );
if ( m_cchA != cch )
{
ErrorTrace(TRACE_ID, "::WideCharToMultiByte returns inconsistent length - %d / %d", cch, m_cchA);
delete [] m_strA;
m_strA = NULL;
m_cchA = 0;
goto Exit;
}
m_strA[m_cchA] = '\0';
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
// end of file