windows-nt/Source/XPSP1/NT/inetsrv/query/apps/srch/srchutil.cxx
2020-09-26 16:20:57 +08:00

787 lines
18 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999.
//
// File: srchutil.cxx
//
// Contents:
//
// History: 15 Aug 1996 DLee Created
//
//--------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
void SetReg(
WCHAR const * pwcName,
WCHAR const * pwcValue)
{
HKEY hKeyParent;
if (ERROR_SUCCESS ==
RegOpenKeyEx(HKEY_CURRENT_USER,CISEARCH_PARENT_REG_KEY,0,
KEY_ALL_ACCESS,&hKeyParent))
{
DWORD dwDisp;
HKEY hKey;
if (ERROR_SUCCESS ==
RegCreateKeyEx(hKeyParent,CISEARCH_REG_SUBKEY,0,L"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,0,&hKey,&dwDisp))
{
RegSetValueEx(hKey,pwcName,0,REG_SZ,(LPBYTE) pwcValue,
sizeof(WCHAR) * (wcslen(pwcValue) + 1));
RegCloseKey(hKey);
}
RegCloseKey(hKeyParent);
}
} //SetReg
BOOL GetReg(
WCHAR const * pwcName,
WCHAR * pwcValue,
DWORD * pdwSize)
{
BOOL fOk = FALSE;
HKEY hKeyParent;
if (ERROR_SUCCESS ==
RegOpenKeyEx(HKEY_CURRENT_USER,CISEARCH_PARENT_REG_KEY,0,
KEY_ALL_ACCESS,&hKeyParent))
{
DWORD dwDisp;
HKEY hKey;
if (ERROR_SUCCESS ==
RegCreateKeyEx(hKeyParent,CISEARCH_REG_SUBKEY,0,L"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,0,&hKey,&dwDisp))
{
DWORD dwType;
if (ERROR_SUCCESS == RegQueryValueEx(hKey,pwcName,0,&dwType,
(LPBYTE) pwcValue,pdwSize))
fOk = TRUE;
RegCloseKey(hKey);
}
RegCloseKey(hKeyParent);
}
return fOk;
} //GetReg
LCID GetRegLCID(
WCHAR const * pwcName,
LCID defLCID )
{
WCHAR awc[100];
DWORD dw = sizeof awc;
if (GetReg(pwcName,awc,&dw))
return _wtoi(awc);
else
return defLCID;
} //GetRegLCID
void SetRegLCID(
WCHAR const * pwcName,
LCID lcid )
{
WCHAR awc[20];
// itow is not in all C runtimes _itow(iValue,awc,10);
swprintf( awc, L"%d", lcid );
SetReg( pwcName, awc );
} //SetRegLCID
int GetRegInt(
WCHAR const * pwcName,
int iDef)
{
WCHAR awc[100];
DWORD dw = sizeof awc;
if (GetReg(pwcName,awc,&dw))
return _wtoi(awc);
else
return iDef;
} //GetRegInt
void SetRegInt(
WCHAR const * pwcName,
int iValue)
{
WCHAR awc[20];
// itow is not in all C runtimes _itow(iValue,awc,10);
swprintf( awc, L"%d", iValue );
SetReg( pwcName, awc );
} //SetRegInt
BOOL IsSpecificClass(
HWND hwnd,
WCHAR const * pwcClass)
{
WCHAR awcClass[60];
GetClassName(hwnd,awcClass,(sizeof awcClass / sizeof WCHAR) - 1);
return !wcscmp( awcClass, pwcClass );
} //IsSpecificClass
int GetLineHeight(
HWND hwnd,
HFONT hFont)
{
if (hFont == 0)
hFont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
HDC hdc;
int iHeight=0;
if (hdc = GetDC(hwnd))
{
HFONT hOldFont;
if (hOldFont = (HFONT) SelectObject(hdc,hFont))
{
TEXTMETRIC tm;
GetTextMetrics(hdc,&tm);
iHeight = (tm.tmHeight + 2 * tm.tmExternalLeading);
SelectObject(hdc,hOldFont);
}
ReleaseDC(hwnd,hdc);
}
return iHeight;
} //GetLineHeight
int GetAvgWidth(
HWND hwnd,
HFONT hFont)
{
if (hFont == 0)
hFont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
HDC hdc;
LONG cpWidth = 0;
if (hdc = GetDC(hwnd))
{
HFONT hOldFont;
if (hOldFont = (HFONT) SelectObject(hdc,hFont))
{
TEXTMETRIC tm;
GetTextMetrics(hdc,&tm);
cpWidth = tm.tmAveCharWidth;
SelectObject(hdc,hOldFont);
}
ReleaseDC(hwnd,hdc);
}
return cpWidth;
} //GetAvgWidth
INT_PTR DoModalDialog(
DLGPROC fp,
HWND hParent,
WCHAR * pwcName,
LPARAM lParam)
{
return DialogBoxParam(MyGetWindowInstance(hParent),
pwcName,
hParent,
fp,
lParam);
} //DoModalDialog
void SaveWindowRect(
HWND hwnd,
WCHAR const * pwc )
{
if (! (IsZoomed(hwnd) || IsIconic(hwnd)))
{
RECT rc;
GetWindowRect(hwnd,&rc);
WCHAR awc[100];
swprintf(awc,L"%d %d %d %d",rc.left,rc.top,rc.right,rc.bottom);
SetReg( pwc, awc );
}
} //SaveWindowRect
BOOL LoadWindowRect(
int * left,
int * top,
int * right,
int * bottom,
WCHAR const * pwc )
{
WCHAR awc[100];
DWORD dw = sizeof awc;
if ( GetReg( pwc, awc, &dw ) )
{
swscanf(awc,L"%d %d %d %d",left,top,right,bottom);
*right = *right - *left;
*bottom = *bottom - *top;
return TRUE;
}
else
{
*left = *top = *right = *bottom = CW_USEDEFAULT;
return FALSE;
}
} //LoadWindowRect
int GetWindowState(
BOOL bApp)
{
WCHAR awcValue[100],awcBuf[100];
if (bApp)
wcscpy(awcBuf,L"main");
else
wcscpy(awcBuf,L"mdi");
wcscat(awcBuf,L"-state");
DWORD dw = sizeof awcValue;
int iState;
if (GetReg(awcBuf,awcValue,&dw))
iState = awcValue[0] - L'0';
else
iState = 1;
return iState;
} //GetWindowState
void PassOnToEdit(
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
HWND hwndActive = GetFocus();
if ( 0 != hwndActive )
{
WCHAR awcBuf[60];
int r = GetClassName(hwndActive,awcBuf,(sizeof awcBuf / sizeof WCHAR) - 1);
if ( 0 == r )
return;
if ( ( !_wcsicmp( awcBuf, L"Edit" ) ) ||
( !_wcsicmp( awcBuf, L"RichEdit" ) ) )
SendMessage( hwndActive, msg, wParam, lParam);
}
} //PassOnToEdit
void WINAPI CenterDialog(
HWND hdlg)
{
RECT rcParent;
RECT rc;
GetWindowRect(hdlg,(LPRECT) &rc);
GetWindowRect(GetParent(hdlg),(LPRECT) &rcParent);
LONG xbias = rcParent.left + (rcParent.right - rcParent.left)/2;
LONG ybias = rcParent.top + (rcParent.bottom - rcParent.top)/2;
LONG lWidth = rc.right - rc.left;
LONG lHeight = rc.bottom - rc.top;
MoveWindow(hdlg, xbias - lWidth/2,
ybias - lHeight/2,
lWidth,lHeight,FALSE);
} //CenterDialog
//+---------------------------------------------------------------------------
//
// Function: ConvertGroupingStringToInt
//
// Synopsis: Converts a grouping string from the registry to an integer,
// as required by the Win32 number formatting API
//
// History: 5-Feb-99 dlee Stole from the Win32 implementation
//
//----------------------------------------------------------------------------
int ConvertGroupingStringToInt( WCHAR const * pwcGrouping )
{
XGrowable<WCHAR> xDest( 1 + wcslen( pwcGrouping ) );
WCHAR * pDest = xDest.Get();
//
// Filter out all non-numeric values and all zero values.
// Store the result in the destination buffer.
//
WCHAR const * pSrc = pwcGrouping;
while (0 != *pSrc)
{
if ( ( *pSrc < L'1' ) || ( *pSrc > L'9' ) )
{
pSrc++;
}
else
{
if (pSrc != pDest)
*pDest = *pSrc;
pSrc++;
pDest++;
}
}
//
// Make sure there is something in the destination buffer.
// Also, see if we need to add a zero in the case of 3;2 becomes 320.
//
if ( ( pDest == xDest.Get() ) || ( *(pSrc - 1) != L'0' ) )
{
*pDest = L'0';
pDest++;
}
// Null terminate the buffer.
*pDest = 0;
// Convert the string to an integer.
return _wtoi( xDest.Get() );
} //ConvertGroupingStringToInt
void LoadNumberFormatInfo(
NUMBERFMT & rFormat)
{
LCID lcid = GetUserDefaultLCID();
WCHAR awcBuf[cwcBufSize];
// Get the number of decimal digits.
GetLocaleInfo(lcid,LOCALE_IDIGITS,awcBuf,cwcBufSize);
rFormat.NumDigits = _wtoi(awcBuf);
// Get the leading zero in decimal fields option.
GetLocaleInfo(lcid,LOCALE_ILZERO,awcBuf,cwcBufSize);
rFormat.LeadingZero = _wtoi(awcBuf);
// Get the negative ordering.
GetLocaleInfo(lcid,LOCALE_INEGNUMBER,awcBuf,cwcBufSize);
rFormat.NegativeOrder = _wtoi(awcBuf);
// Get the grouping left of the decimal.
GetLocaleInfo(lcid,LOCALE_SGROUPING,awcBuf,cwcBufSize);
rFormat.Grouping = ConvertGroupingStringToInt( awcBuf );
// Get the decimal separator.
GetLocaleInfo(lcid,LOCALE_SDECIMAL,awcBuf,cwcBufSize);
rFormat.lpDecimalSep = new WCHAR[wcslen(awcBuf) + 1];
wcscpy(rFormat.lpDecimalSep,awcBuf);
// Get the thousand separator.
GetLocaleInfo(lcid,LOCALE_STHOUSAND,awcBuf,cwcBufSize);
rFormat.lpThousandSep = new WCHAR[wcslen(awcBuf) + 1];
wcscpy(rFormat.lpThousandSep,awcBuf);
} //LoadNumberFormatInfo
void FreeNumberFormatInfo(
NUMBERFMT & rFormat)
{
delete rFormat.lpDecimalSep;
delete rFormat.lpThousandSep;
} //FreeNumberFormatInfo
void SearchError(
HWND hParent,
ULONG dwErrorID,
WCHAR const * pwcTitle)
{
CResString str( dwErrorID );
MessageBox( hParent, str.Get(), pwcTitle, MB_OK | MB_ICONEXCLAMATION );
} //SearchError
void PutInClipboard(
WCHAR const * pwcBuffer )
{
if ( OpenClipboard( App.AppWindow() ) )
{
EmptyClipboard();
HGLOBAL hglbCopy = GlobalAlloc( GMEM_DDESHARE,
( wcslen( pwcBuffer ) + 1 ) *
sizeof WCHAR );
if ( 0 != hglbCopy )
{
WCHAR *pwc = (WCHAR *) GlobalLock( hglbCopy );
wcscpy( pwc, pwcBuffer );
GlobalUnlock( hglbCopy );
SetClipboardData( CF_UNICODETEXT, hglbCopy );
}
CloseClipboard();
}
} //PutInClipboard
BOOL GetRegEditor(
WCHAR const * pwcName,
WCHAR * pwcValue,
DWORD * pdwSize)
{
BOOL fOk = FALSE;
HKEY hKeyParent;
if (ERROR_SUCCESS ==
RegOpenKeyEx(HKEY_CURRENT_USER,L"software\\microsoft",0,
KEY_ALL_ACCESS,&hKeyParent))
{
DWORD dwDisp;
HKEY hKey;
if (ERROR_SUCCESS ==
RegCreateKeyEx(hKeyParent,L"Windiff",0,L"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,0,&hKey,&dwDisp))
{
DWORD dwType;
if (ERROR_SUCCESS == RegQueryValueEx(hKey,pwcName,0,&dwType,
(LPBYTE) pwcValue,pdwSize))
fOk = TRUE;
RegCloseKey(hKey);
}
RegCloseKey(hKeyParent);
}
return fOk;
} //GetRegEditor
void FormatSrchError( SCODE sc, WCHAR * pwc, LCID lcid )
{
LCID SaveLCID = GetThreadLocale();
SetThreadLocale( lcid );
ULONG Win32status = sc;
if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(L"query.dll"),
sc,
0,
pwc,
MAX_PATH,
0 ) )
{
//
// Try looking up the error in the Win32 list of error codes
//
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(L"kernel32.dll"),
Win32status,
0,
pwc,
MAX_PATH,
0 ) )
{
swprintf( pwc, L"0x%x", sc );
}
}
SetThreadLocale(SaveLCID);
} //FormatSrchError
BOOL CopyURL( WCHAR const * pwcURL, WCHAR * awcTempName )
{
WCHAR const * pwcSlash = wcsrchr( pwcURL, L'/' );
if ( 0 == pwcSlash )
return FALSE;
pwcSlash++;
DWORD cwc = GetTempPath( MAX_PATH, awcTempName );
if ( 0 == cwc || cwc > MAX_PATH )
return FALSE;
wcscat( awcTempName, pwcSlash );
XIHandle xhI( InternetOpenW( L"srch",
INTERNET_OPEN_TYPE_PRECONFIG,
0,
0,
0 ) );
if ( xhI.IsNull() )
return FALSE;
XIHandle xhUrl( InternetOpenUrlW( xhI.Get(), pwcURL, 0, 0,
INTERNET_FLAG_RELOAD |
INTERNET_FLAG_DONT_CACHE |
INTERNET_FLAG_PRAGMA_NOCACHE |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_COOKIES |
INTERNET_FLAG_NO_UI,
0 ) );
if ( xhUrl.IsNull() )
return FALSE;
FILE * fp = _wfopen( awcTempName, L"wb" );
if ( 0 == fp )
return FALSE;
char ac[ 1024 * 16 ];
do
{
DWORD cbRead = 0;
BOOL fOK = InternetReadFile( xhUrl.Get(),
ac,
sizeof ac,
&cbRead );
if ( !fOK )
{
fclose( fp );
return FALSE;
}
if ( 0 == cbRead )
break;
fwrite( ac, 1, cbRead, fp );
} while( TRUE );
fclose( fp );
return TRUE;
} //CopyURL
BOOL InvokeBrowser(
WCHAR const * pwcFilePath,
DBCOMMANDTREE * prstQuery )
{
WCHAR awcTempFile[MAX_PATH];
BOOL fDeleteWhenDone = FALSE;
if ( !_wcsnicmp( pwcFilePath, L"file:", 5 ) )
pwcFilePath += 5;
else if ( !_wcsnicmp( pwcFilePath, L"http:", 5 ) )
{
if ( !CopyURL( pwcFilePath, awcTempFile ) )
return FALSE;
pwcFilePath = awcTempFile;
fDeleteWhenDone = TRUE;
}
BOOL fOK = TRUE;
CQueryResult *pResult = new CQueryResult( pwcFilePath, prstQuery, fDeleteWhenDone );
// call internal mdi browser
if (pwcFilePath)
{
HWND h = App.CreateBrowser( pwcFilePath, (LPARAM) pResult );
if ( 0 == h )
{
WCHAR awcError[ MAX_PATH ];
FormatSrchError( App.BrowseLastError(), awcError, App.GetLocale() );
WCHAR awcMsg[ MAX_PATH ];
CResString strErr( IDS_ERR_CANT_BROWSE_FILE );
swprintf( awcMsg, strErr.Get(), awcError );
MessageBox( App.AppWindow(),
awcMsg,
pwcFilePath,
MB_OK|MB_ICONEXCLAMATION );
fOK = FALSE;
}
}
return fOK;
} //InvokeBrowser
void ExecApp(
WCHAR const * pwcCmd)
{
STARTUPINFO si;
memset( &si, 0, sizeof si );
si.cb = sizeof si;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWDEFAULT;
PROCESS_INFORMATION pi;
CreateProcess( 0, (WCHAR *) pwcCmd, 0, 0, FALSE, 0, 0, 0, &si, &pi );
} //ExecApp
BOOL ViewFile(
WCHAR const * pwcPath,
enumViewFile eViewType,
int iLineNumber,
DBCOMMANDTREE * prstQuery )
{
BOOL fOK = TRUE;
WCHAR awcCmd[MAX_PATH + cwcBufSize];
DWORD cbCmd = sizeof awcCmd;
if ( fileOpen == eViewType )
{
HINSTANCE hinst = ShellExecute( HWND_DESKTOP,
0,
pwcPath,
0,
0,
SW_SHOWNORMAL );
if ( 32 > (DWORD_PTR) hinst )
{
// if no app is registered for this extension, use notepad
wcscpy( awcCmd, L"notepad " );
wcscat( awcCmd, pwcPath );
ExecApp( awcCmd );
}
}
else if ( fileBrowse == eViewType )
{
fOK = InvokeBrowser( (WCHAR *) pwcPath, prstQuery );
}
else if ( fileEdit == eViewType )
{
WCHAR awcEditor[ MAX_PATH ];
if ( GetReg( CISEARCH_REG_EDITOR, awcEditor, &cbCmd ) )
{
// cool -- use it.
}
else
{
// try to use windiff's configuration
cbCmd = sizeof awcCmd;
if ( GetRegEditor( L"Editor", awcEditor, &cbCmd ) )
{
WCHAR *p = wcsstr( awcEditor, L"%p" );
if ( p )
*(p+1) = L's';
p = wcsstr( awcEditor, L"%l" );
if ( p )
*(p+1) = L'd';
}
else
{
//wcscpy( awcEditor, L"s %ws -#%d" );
// no editor configured -- open the file
return ViewFile( pwcPath, fileOpen, iLineNumber, prstQuery );
}
}
TRY
{
swprintf( awcCmd, awcEditor, pwcPath, iLineNumber );
ExecApp( awcCmd );
}
CATCH( CException, e )
{
fOK = FALSE;
}
END_CATCH;
}
return fOK;
} //ViewFile
BOOL GetCatListItem( const XGrowable<WCHAR> & const_xCatList,
unsigned iItem,
WCHAR * pwszMachine,
WCHAR * pwszCatalog,
WCHAR * pwszScope,
BOOL & fDeep )
{
XGrowable<WCHAR> xCatList = const_xCatList;
Win4Assert( pwszMachine && pwszCatalog && pwszScope );
*pwszMachine = *pwszCatalog = *pwszScope = 0;
fDeep = FALSE;
unsigned ii;
WCHAR * pStart = xCatList.Get();
for( ii = 0; ii < iItem; ii++ )
{
pStart = wcschr( pStart, L';' );
if ( pStart )
{
pStart++;
}
else
break;
if ( 0 == *pStart )
{
break;
}
}
if ( 0 == pStart || 0 == *pStart )
{
return FALSE;
}
WCHAR * pEnd;
// machine
pEnd = wcschr( pStart, L',' );
if ( !pEnd )
{
return FALSE;
}
*pEnd = 0;
wcscpy( pwszMachine, pStart );
pStart = pEnd + 1;
// catalog
pEnd = wcschr( pStart, L',' );
if ( !pEnd )
{
return FALSE;
}
*pEnd = 0;
wcscpy( pwszCatalog, pStart );
pStart = pEnd + 1;
// scope
pEnd = wcschr( pStart, L',' );
if ( !pEnd )
{
return FALSE;
}
*pEnd = 0;
wcscpy( pwszScope, pStart );
pStart = pEnd + 1;
// depth
fDeep = ( L'd' == *pStart || L'D' == *pStart );
return TRUE;
}