|
|
/*++
Microsoft Confidential Copyright (c) 1992-1997 Microsoft Corporation All rights reserved
Module Name:
util.c
Abstract:
Utility functions for System Control Panel Applet
Author:
Eric Flo (ericflo) 19-Jun-1995
Revision History:
15-Oct-1997 scotthal Complete overhaul
--*/ #include "sysdm.h"
#include <strsafe.h>
#include <ntdddisk.h>
//
// Constants
//
#define CCH_MAX_DEC 12 // Number of chars needed to hold 2^32
#define MAX_SWAPSIZE_X86 (4 * 1024) // 4 Gb (number stored in megabytes)
#define MAX_SWAPSIZE_X86_PAE (16 * 1024 * 1024) // 16 Tb
#define MAX_SWAPSIZE_IA64 (32 * 1024 * 1024) // 32 Tb
#define MAX_SWAPSIZE_AMD64 (16 * 1024 * 1024) // 16 Tb
void ErrMemDlg( IN HWND hParent ) /*++
Routine Description:
Displays "out of memory" message.
Arguments:
hParent - Supplies parent window handle.
Return Value:
None.
--*/ { MessageBox( hParent, g_szErrMem, g_szSystemApplet, MB_OK | MB_ICONHAND | MB_SYSTEMMODAL ); return; }
LPTSTR SkipWhiteSpace( IN LPTSTR sz ) /*++
Routine Description:
SkipWhiteSpace For the purposes of this fuction, whitespace is space, tab, cr, or lf.
Arguments:
sz - Supplies a string (which presumably has leading whitespace)
Return Value:
Pointer to string without leading whitespace if successful.
--*/ { while( IsWhiteSpace(*sz) ) sz++;
return sz; }
int StringToInt( IN LPTSTR sz ) /*++
Routine Description:
TCHAR version of atoi
Arguments:
sz - Supplies the string to convert
Return Value:
Integer representation of the string
--*/ { int i = 0;
sz = SkipWhiteSpace(sz);
while( IsDigit( *sz ) ) { i = i * 10 + DigitVal( *sz ); sz++; }
return i; }
BOOL Delnode_Recurse( IN LPTSTR lpDir ) /*++
Routine Description:
Recursive delete function for Delnode
Arguments:
lpDir - Supplies directory to delete
Return Value:
TRUE if successful. FALSE if an error occurs.
--*/ { WIN32_FIND_DATA fd; HANDLE hFile;
//
// Setup the current working dir
//
if (!SetCurrentDirectory (lpDir)) { return FALSE; }
//
// Find the first file
//
hFile = FindFirstFile(TEXT("*.*"), &fd);
if (hFile == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) { return TRUE; } else { return FALSE; } }
do { //
// Check for "." and ".."
//
if (!lstrcmpi(fd.cFileName, TEXT("."))) { continue; }
if (!lstrcmpi(fd.cFileName, TEXT(".."))) { continue; }
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
//
// Found a directory.
//
if (!Delnode_Recurse(fd.cFileName)) { FindClose(hFile); return FALSE; }
if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; SetFileAttributes (fd.cFileName, fd.dwFileAttributes); }
RemoveDirectory (fd.cFileName);
} else {
//
// We found a file. Set the file attributes,
// and try to delete it.
//
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) { SetFileAttributes (fd.cFileName, FILE_ATTRIBUTE_NORMAL); }
DeleteFile (fd.cFileName);
}
//
// Find the next entry
//
} while (FindNextFile(hFile, &fd));
//
// Close the search handle
//
FindClose(hFile);
//
// Reset the working directory
//
if (!SetCurrentDirectory (TEXT(".."))) { return FALSE; }
//
// Success.
//
return TRUE; }
BOOL Delnode( IN LPTSTR lpDir ) /*++
Routine Description:
Recursive function that deletes files and directories.
Arguments:
lpDir - Supplies directory to delete.
Return Value:
TRUE if successful FALSE if an error occurs
--*/ { TCHAR szCurWorkingDir[MAX_PATH];
if (GetCurrentDirectory(ARRAYSIZE(szCurWorkingDir), szCurWorkingDir)) {
Delnode_Recurse (lpDir);
SetCurrentDirectory (szCurWorkingDir);
if (!RemoveDirectory (lpDir)) { return FALSE; }
} else { return FALSE; }
return TRUE;
}
LONG MyRegSaveKey( IN HKEY hKey, IN LPCTSTR lpSubKey ) /*++
Routine Description:
Saves a registry key.
Arguments:
hKey - Supplies handle to a registry key.
lpSubKey - Supplies the name of the subkey to save.
Return Value:
ERROR_SUCCESS if successful. Error code from RegSaveKey() if an error occurs.
--*/ {
HANDLE hToken = NULL; LUID luid; DWORD dwSize = 1024; PTOKEN_PRIVILEGES lpPrevPrivilages = NULL; TOKEN_PRIVILEGES tp; LONG error;
//
// Allocate space for the old privileges
//
lpPrevPrivilages = GlobalAlloc(GPTR, dwSize);
if (!lpPrevPrivilages) { error = GetLastError(); goto Exit; }
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { error = GetLastError(); goto Exit; }
if (!LookupPrivilegeValue( NULL, SE_BACKUP_NAME, &luid )) { error = GetLastError(); goto Exit; }
tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges( hToken, FALSE, &tp, dwSize, lpPrevPrivilages, &dwSize )) {
if (GetLastError() == ERROR_MORE_DATA) { PTOKEN_PRIVILEGES lpTemp;
lpTemp = GlobalReAlloc(lpPrevPrivilages, dwSize, GMEM_MOVEABLE);
if (!lpTemp) { error = GetLastError(); goto Exit; }
lpPrevPrivilages = lpTemp;
if (!AdjustTokenPrivileges( hToken, FALSE, &tp, dwSize, lpPrevPrivilages, &dwSize )) { error = GetLastError(); goto Exit; }
} else { error = GetLastError(); goto Exit; }
}
//
// Save the hive
//
error = RegSaveKey(hKey, lpSubKey, NULL);
if (!AdjustTokenPrivileges( hToken, FALSE, lpPrevPrivilages, 0, NULL, NULL )) { ASSERT(FALSE); }
Exit:
if (hToken) { CloseHandle (hToken); }
if (lpPrevPrivilages) { GlobalFree(lpPrevPrivilages); }
return error; }
LONG MyRegLoadKey( IN HKEY hKey, IN LPTSTR lpSubKey, IN LPTSTR lpFile ) /*++
Routine Description:
Loads a hive into the registry
Arguments:
hKey - Supplies a handle to a registry key which will be the parent of the created key.
lpSubKey - Supplies the name of the subkey to create.
lpFile - Supplies the name of the file containing the hive.
Return Value:
ERROR_SUCCESS if successful. Error code from RegLoadKey if unsuccessful.
--*/ { NTSTATUS Status; BOOLEAN WasEnabled; int error;
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
if (NT_SUCCESS(Status)) {
error = RegLoadKey(hKey, lpSubKey, lpFile);
//
// Restore the privilege to its previous state
//
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
} else {
error = GetLastError(); }
return error; }
LONG MyRegUnLoadKey( IN HKEY hKey, IN LPTSTR lpSubKey ) /*++
Routine Description:
Unloads a registry key.
Arguments:
hKey - Supplies handle to parent key
lpSubKey - Supplies name of subkey to delete
Return Value:
ERROR_SUCCESS if successful Error code if unsuccessful
--*/ { LONG error; NTSTATUS Status; BOOLEAN WasEnabled;
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
if (NT_SUCCESS(Status)) {
error = RegUnLoadKey(hKey, lpSubKey);
//
// Restore the privilege to its previous state
//
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
} else {
error = GetLastError(); }
return error; }
int GetSelectedItem( IN HWND hCtrl ) /*++
Routine Description: Determines which item in a list view control is selected
Arguments:
hCtrl - Supplies handle to the desired list view control.
Return Value:
The index of the selected item, if an item is selected. -1 if no item is selected.
--*/ { int i, n;
n = (int)SendMessage (hCtrl, LVM_GETITEMCOUNT, 0, 0L);
if (n != LB_ERR) { for (i = 0; i < n; i++) { if (SendMessage (hCtrl, LVM_GETITEMSTATE, i, (LPARAM) LVIS_SELECTED) == LVIS_SELECTED) { return i; } } }
return -1; }
BOOL _DriveIsNTFS( INT iDrive // drive to check on
) { TCHAR szDrive[4]; TCHAR szDriveNameBuffer[MAX_PATH]; DWORD dwMaxFnameLen; DWORD dwFSFlags; TCHAR szDriveFormatName[MAX_PATH]; BOOL fRetVal = FALSE; PathBuildRoot(szDrive, iDrive); if (GetVolumeInformation(szDrive, szDriveNameBuffer, ARRAYSIZE(szDriveNameBuffer), NULL, &dwMaxFnameLen, &dwFSFlags, szDriveFormatName, ARRAYSIZE(szDriveFormatName))) { if (StrStrI(szDriveFormatName, TEXT("NTFS"))) { fRetVal = TRUE; } }
return fRetVal; }
DWORD GetMaxPagefileSizeInMB( INT iDrive // drive to check on
) { #if defined(_AMD64_)
return MAX_SWAPSIZE_AMD64; #elif defined(_X86_)
if ((USER_SHARED_DATA->ProcessorFeatures[PF_PAE_ENABLED]) && _DriveIsNTFS(iDrive)) { return MAX_SWAPSIZE_X86_PAE; } else { return MAX_SWAPSIZE_X86; } #elif defined(_IA64_)
return MAX_SWAPSIZE_IA64; #else
return 0; #endif
}
int MsgBoxParam( IN HWND hWnd, IN DWORD wText, IN DWORD wCaption, IN DWORD wType, ... ) /*++
Routine Description:
Combination of MessageBox and printf
Arguments:
hWnd - Supplies parent window handle
wText - Supplies ID of a printf-like format string to display as the message box text
wCaption - Supplies ID of a string to display as the message box caption
wType - Supplies flags to MessageBox()
Return Value:
Whatever MessageBox() returns.
--*/
{ TCHAR szText[ 4 * MAX_PATH ], szCaption[ 2 * MAX_PATH ]; int ival; va_list parg;
va_start( parg, wType );
if( wText == IDS_INSUFFICIENT_MEMORY ) goto NoMem;
if( !LoadString( hInstance, wText, szCaption, ARRAYSIZE( szCaption ) ) ) goto NoMem;
if (FAILED(StringCchVPrintf(szText, ARRAYSIZE(szText), szCaption, parg))) goto NoMem; if( !LoadString( hInstance, wCaption, szCaption, ARRAYSIZE( szCaption ) ) ) goto NoMem; if( (ival = MessageBox( hWnd, szText, szCaption, wType ) ) == 0 ) goto NoMem;
va_end( parg );
return( ival );
NoMem: va_end( parg );
ErrMemDlg( hWnd ); return 0; }
DWORD SetLBWidthEx( IN HWND hwndLB, IN LPTSTR szBuffer, IN DWORD cxCurWidth, IN DWORD cxExtra ) /*++
Routine Description:
Set the width of a listbox, in pixels, acording to the size of the string passed in
Arguments:
hwndLB - Supples listbox to resize
szBuffer - Supplies string to resize listbox to
cxCurWidth - Supplies current width of the listbox
cxExtra - Supplies some kind of slop factor
Return Value:
The new width of the listbox
--*/ { HDC hDC; SIZE Size; LONG cx; HFONT hfont, hfontOld;
// Get the new Win4.0 thin dialog font
hfont = (HFONT)SendMessage(hwndLB, WM_GETFONT, 0, 0);
hDC = GetDC(hwndLB);
// if we got a font back, select it in this clean hDC
if (hfont != NULL) hfontOld = SelectObject(hDC, hfont);
// If cxExtra is 0, then give our selves a little breathing space.
if (cxExtra == 0) { GetTextExtentPoint32(hDC, TEXT("1234"), 4 /* lstrlen("1234") */, &Size); cxExtra = Size.cx; }
// Set scroll width of listbox
GetTextExtentPoint32(hDC, szBuffer, lstrlen(szBuffer), &Size);
Size.cx += cxExtra;
// Get the name length and adjust the longest name
if ((DWORD) Size.cx > cxCurWidth) { cxCurWidth = Size.cx; SendMessage (hwndLB, LB_SETHORIZONTALEXTENT, (DWORD)Size.cx, 0L); }
// retstore the original font if we changed it
if (hfont != NULL) SelectObject(hDC, hfontOld);
ReleaseDC(NULL, hDC);
return cxCurWidth; }
VOID SetDefButton( IN HWND hwndDlg, IN int idButton ) /*++
Routine Description:
Sets the default button for a dialog box or proppage The old default button, if any, has its default status removed
Arguments:
hwndDlg - Supplies window handle
idButton - Supplies ID of button to make default
Return Value:
None
--*/ { LRESULT lr;
if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID) { HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
SendMessage (hwndOldDefButton, BM_SETSTYLE, MAKEWPARAM(BS_PUSHBUTTON, 0), MAKELPARAM(TRUE, 0)); }
SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L ); SendMessage( GetDlgItem(hwndDlg, idButton), BM_SETSTYLE, MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ), MAKELPARAM( TRUE, 0 )); }
void HourGlass( IN BOOL bOn ) /*++
Routine Description:
Turns hourglass mouse cursor on or off
Arguments:
bOn - Supplies desired status of hourglass mouse cursor
Return Value:
None
--*/ { if( !GetSystemMetrics( SM_MOUSEPRESENT ) ) ShowCursor( bOn );
SetCursor( LoadCursor( NULL, bOn ? IDC_WAIT : IDC_ARROW ) ); }
VCREG_RET OpenRegKey( IN LPTSTR pszKeyName, OUT PHKEY phk ) /*++
Routine Description:
Opens a subkey of HKEY_LOCAL_MACHINE
Arguments:
pszKeyName - Supplies the name of the subkey to open
phk - Returns a handle to the key if successfully opened Returns NULL if an error occurs
Return Value:
VCREG_OK if successful VCREG_READONLY if the key was opened with read-only access VCREG_OK if an error occurred
*/ { LONG Error;
Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKeyName, 0, KEY_READ | KEY_WRITE, phk);
if (Error != ERROR_SUCCESS) { Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKeyName, 0, KEY_READ, phk);
if (Error != ERROR_SUCCESS) { *phk = NULL; return VCREG_ERROR; }
/*
* We only have Read access. */ return VCREG_READONLY; }
return VCREG_OK; }
LONG CloseRegKey( IN HKEY hkey ) /*++
Routine Description:
Closes a registry key opened by OpenRegKey()
Arguments:
hkey - Supplies handle to key to close
Return Value:
Whatever RegCloseKey() returns
--*/ { return RegCloseKey(hkey); }
/*
* UINT VMGetDriveType( LPCTSTR lpszDrive ) * * Gets the drive type. This function differs from Win32's GetDriveType * in that it returns DRIVE_FIXED for lockable removable drives (like * bernolli boxes, etc). * * On IA64 we don't do this, however, requiring all pagefiles be on actual * fixed drives. */ const TCHAR c_szDevice[] = TEXT("\\Device");
UINT VMGetDriveType( LPCTSTR lpszDrive ) { UINT i; TCHAR szDevName[MAX_PATH];
ASSERT(tolower(*lpszDrive) >= 'a' && tolower(*lpszDrive) <= 'z');
// Check for subst drive
if (QueryDosDevice( lpszDrive, szDevName, ARRAYSIZE( szDevName ) ) != 0) {
// If drive does not start with '\Device', then it is not FIXED
szDevName[ARRAYSIZE(c_szDevice) - 1] = '\0'; if ( lstrcmpi(szDevName, c_szDevice) != 0 ) { return DRIVE_REMOTE; } }
i = GetDriveType( lpszDrive ); #ifndef _WIN64
if ( i == DRIVE_REMOVABLE ) { TCHAR szNtDrive[20]; DWORD cb; DISK_GEOMETRY dgMediaInfo; HANDLE hDisk;
/*
* 'Removable' drive. Check to see if it is a Floppy or lockable * drive. */
if (SUCCEEDED(PathBuildFancyRoot(szNtDrive, ARRAYSIZE(szNtDrive), tolower(lpszDrive[0]) - 'a'))) { hDisk = CreateFile( szNtDrive, /* GENERIC_READ */ 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); // fine
if (hDisk != INVALID_HANDLE_VALUE ) {
if (DeviceIoControl( hDisk, IOCTL_DISK_GET_MEDIA_TYPES, NULL, 0, &dgMediaInfo, sizeof(dgMediaInfo), &cb, NULL) == FALSE && GetLastError() != ERROR_MORE_DATA) { /*
* Drive is not a floppy */ i = DRIVE_FIXED; }
CloseHandle(hDisk); } else if (GetLastError() == ERROR_ACCESS_DENIED) { /*
* Could not open the drive, either it is bad, or else we * don't have permission. Since everyone has permission * to open floppies, then this must be a bernoulli type device. */ i = DRIVE_FIXED; } } } #endif
return i; }
STDAPI PathBuildFancyRoot( LPTSTR szRoot, UINT cchRoot, int iDrive ) { return StringCchPrintf(szRoot, cchRoot, TEXT("\\\\.\\%c:"), iDrive + 'a'); }
__inline BOOL _SafeGetHwndTextAux( HWND hwnd, UINT ulIndex, UINT msgGetLen, UINT msgGetString, LRESULT err, LPTSTR pszBuffer, UINT cchBuffer) { BOOL fRet = FALSE; UINT cch = (UINT)SendMessage(hwnd, msgGetLen, (WPARAM)ulIndex, 0); if (cch < cchBuffer && cch != err) { if (err != SendMessage(hwnd, msgGetString, (WPARAM)ulIndex, (LPARAM)pszBuffer)) { fRet = TRUE; }
} return fRet; }
BOOL SafeGetComboBoxListText( HWND hCombo, UINT ulIndex, LPTSTR pszBuffer, UINT cchBuffer) { return _SafeGetHwndTextAux(hCombo, ulIndex, CB_GETLBTEXTLEN, CB_GETLBTEXT, CB_ERR, pszBuffer, cchBuffer); }
BOOL SafeGetListBoxText( HWND hCombo, UINT ulIndex, LPTSTR pszBuffer, UINT cchBuffer) { return _SafeGetHwndTextAux(hCombo, ulIndex, LB_GETTEXTLEN, LB_GETTEXT, LB_ERR, pszBuffer, cchBuffer); }
|