651 lines
16 KiB
C++
651 lines
16 KiB
C++
/*++
|
||
|
||
Copyright (c) 1998 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
FTMan
|
||
|
||
File Name:
|
||
|
||
Global.cpp
|
||
|
||
Abstract:
|
||
|
||
Implementation of useful global functions
|
||
|
||
Author:
|
||
|
||
Cristian Teodorescu October 29, 1998
|
||
|
||
Notes:
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "stdafx.h"
|
||
|
||
#include "FTUtil.h"
|
||
#include "Global.h"
|
||
#include "Item.h"
|
||
#include "MainFrm.h"
|
||
#include "Resource.h"
|
||
|
||
#include <basetyps.h>
|
||
#include <mountmgr.h>
|
||
#include <winbase.h>
|
||
#include <winioctl.h>
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
////////////////////////////////////////////////////////////////////////////
|
||
// Display functions
|
||
|
||
/*
|
||
Global function: DisplaySystemErrorMessage
|
||
|
||
Purpose: Display the last system error message prefixed ( or not ) with another string taken from
|
||
our resources explaining the context of the failure
|
||
|
||
Parameters: [IN] UINT unContextMsgID
|
||
The ID of the string that must prefix the system error message. ID in resource.h
|
||
Default is 0 which means that the system error shouldn't be prefixed
|
||
|
||
Return value: TRUE if the functions succeeds
|
||
*/
|
||
BOOL DisplaySystemErrorMessage( UINT unContextMsgID /* =0 */)
|
||
{
|
||
MY_TRY
|
||
|
||
// Get the system error message
|
||
LPVOID lpMsgBuf;
|
||
if( !::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
NULL,
|
||
GetLastError(),
|
||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||
(LPTSTR) &lpMsgBuf,
|
||
0,
|
||
NULL ) ) // Process any inserts in lpMsgBuf.
|
||
return FALSE;
|
||
|
||
CString str;
|
||
if( unContextMsgID != 0) // The system error message must be prefixed with another string from the resources of this application
|
||
if( !str.LoadString( unContextMsgID ) ) return FALSE;
|
||
str += ((LPCTSTR)lpMsgBuf);
|
||
LocalFree( lpMsgBuf );
|
||
AfxMessageBox(str, MB_ICONSTOP);
|
||
return TRUE;
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: DisplayStatusBarMessage (1)
|
||
|
||
Purpose: Displays a message in the first pane of the main frame status bar
|
||
|
||
Parameters: [IN] LPCTSTR lpszMsg
|
||
The message to display
|
||
|
||
Return value: TRUE if the functions succeeds
|
||
*/
|
||
BOOL DisplayStatusBarMessage( LPCTSTR lpszMsg )
|
||
{
|
||
MY_TRY
|
||
|
||
CStatusBar* pStatusBar = ((CMainFrame*)AfxGetMainWnd())->GetStatusBar();
|
||
if( !pStatusBar )
|
||
return FALSE;
|
||
|
||
// Use the ID_SEPARATOR pane of the status bar
|
||
return pStatusBar->SetPaneText( 5, lpszMsg );
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: DisplayStatusBarMessage (2)
|
||
|
||
Purpose: Display a message in the first pane of the main frame status bar
|
||
|
||
Parameters: [IN] UINT unMsgID
|
||
Resource ID of the string to display
|
||
|
||
Return value: TRUE if the functions succeeds
|
||
*/
|
||
BOOL DisplayStatusBarMessage( UINT unMsgID )
|
||
{
|
||
MY_TRY
|
||
|
||
CString str;
|
||
str.LoadString(unMsgID);
|
||
return DisplayStatusBarMessage(str);
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: FormatVolumeSize
|
||
|
||
Purpose: Format the size of a volume in a "readable" way
|
||
( in GB, MB or KB depending on the size range )
|
||
|
||
Parameters: [OUT] CString& strSize
|
||
Reference to the string to receive the formatted size
|
||
[IN] LONGLONG llSize
|
||
The size to format ( in Bytes )
|
||
|
||
Return value: -
|
||
*/
|
||
|
||
void FormatVolumeSize( CString& strSize, LONGLONG llSize )
|
||
{
|
||
MY_TRY
|
||
|
||
if( llSize >= 0x40000000 ) // 1GB = 2^30 B
|
||
strSize.Format(_T("%.2f GB"), ((double)(llSize>>20))/((double)0x400));
|
||
else if (llSize >= 0x100000 ) // 1MB = 2^20 B
|
||
strSize.Format(_T("%.2f MB"), ((double)(llSize>>10))/((double)0x400));
|
||
else
|
||
strSize.Format(_T("%.2f KB"), ((double)llSize)/((double)0x400));
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: CopyW2Str
|
||
|
||
Purpose: Copy a Unicode character array into a CString
|
||
|
||
Parameters: [OUT] CString& strDest
|
||
Reference to the string to receive the formatted size
|
||
[IN] LPWSTR strSource
|
||
Unicode character array to be copied
|
||
[IN] ULONG ulLength
|
||
The number of characters to copy
|
||
|
||
Return value: -
|
||
*/
|
||
|
||
void CopyW2Str( CString& strDest, LPWSTR strSource, ULONG ulLength )
|
||
{
|
||
MY_TRY
|
||
|
||
LPTSTR lpstr = strDest.GetBuffer( ulLength + 1 );
|
||
#ifdef UNICODE
|
||
memcpy( lpstr, strSource, ulLength * sizeof(WCHAR ) );
|
||
#else
|
||
WideCharToMultiByte( CP_APP, 0, strSource, ulLength, lpstr, ulLength * sizeof(char), NULL, NULL );
|
||
#endif
|
||
|
||
lpstr[ulLength]=_T('\0');
|
||
strDest.ReleaseBuffer();
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: CopyStr2W
|
||
|
||
Purpose: Copy a CString content into a Unicode character array
|
||
|
||
Parameters: [OUT] LPWSTR strDest
|
||
Pointer to the buffer to receive the character array. It should be already allocated
|
||
[IN] CString& strSource
|
||
Reference to the string to be copied
|
||
|
||
Return value: -
|
||
*/
|
||
void CopyStr2W( LPWSTR strDest, CString& strSource )
|
||
{
|
||
MY_TRY
|
||
|
||
LPTSTR lpstr = strSource.GetBuffer(0);
|
||
int nSize = strSource.GetLength();
|
||
|
||
#ifdef UNICODE
|
||
memcpy( strDest, lpstr, nSize * sizeof(WCHAR) );
|
||
#else
|
||
MultiByteToWideChar( CP_APP, 0, lpstr, nSize, strDest, nSize * sizeof(WCHAR) );
|
||
#endif
|
||
|
||
strDest[nSize] = _T('\0');
|
||
strSource.ReleaseBuffer();
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: OpenVolume
|
||
|
||
Purpose: Open a volume given its name
|
||
The name must be like this "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
|
||
|
||
Parameters: [IN] CString& strVolumeName
|
||
Volume name
|
||
|
||
Return value: HANDLE
|
||
Handle of the open volume. INVALID_HANDLE_VALUE if the operation failed
|
||
*/
|
||
HANDLE OpenVolume( const CString& strVolumeName )
|
||
{
|
||
return CreateFile( strVolumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
|
||
}
|
||
|
||
/*
|
||
Global function: IsDOSName
|
||
|
||
Purpose: Decides wether a name is a DOS name i.e. "\DosDevices\X:"
|
||
|
||
Parameters: [IN] CString& str
|
||
The name
|
||
|
||
Return value: TRUE if it is a DOS name
|
||
*/
|
||
|
||
BOOL IsDOSName( const CString& str )
|
||
{
|
||
MY_TRY
|
||
|
||
// "\DosDevices\X:"
|
||
return( ( str.GetLength() == 14 ) &&
|
||
( str.Left(12) == _T("\\DosDevices\\") ) &&
|
||
( str[13] == _T(':') ) );
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: IsVolumeName
|
||
|
||
Purpose: Decides wether a name is a volume name i.e. "\??\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
|
||
Parameters: [IN] CString& str
|
||
The name
|
||
|
||
Return value: TRUE if it is a volume name
|
||
*/
|
||
|
||
BOOL IsVolumeName( const CString& str )
|
||
{
|
||
MY_TRY
|
||
|
||
// "\??\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
return( ( str.GetLength() == 48 ) &&
|
||
( str.Left(11) == _T("\\??\\Volume{") ) &&
|
||
( str[19] == _T('-') ) &&
|
||
( str[24] == _T('-') ) &&
|
||
( str[29] == _T('-') ) &&
|
||
( str[34] == _T('-') ) &&
|
||
( str[47] == _T('}') ) );
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: QueryDriveLetterAndVolumeName
|
||
|
||
Purpose: Query the drive letter and the name of the volume given its NT Name
|
||
The name will be like this: "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
|
||
Parameters: [IN] CString& strNTName
|
||
The NT name of the volume
|
||
[OUT] TCHAR& cDriveLetter
|
||
The drive letter of the volume
|
||
[OUT] CString& strVolumeName
|
||
The name ( to be used by FindFirst/FindNext ) of the volume
|
||
|
||
Return value: TRUE if the function succeeded
|
||
*/
|
||
|
||
BOOL QueryDriveLetterAndVolumeName( CString& strNTName, TCHAR& cDriveLetter, CString& strVolumeName )
|
||
{
|
||
MY_TRY
|
||
|
||
cDriveLetter = _T('\0');
|
||
strVolumeName = _T("");
|
||
|
||
if( strNTName.IsEmpty() )
|
||
return FALSE;
|
||
|
||
HANDLE h;
|
||
ULONG ulInputSize;
|
||
PMOUNTMGR_MOUNT_POINT pInput;
|
||
ULONG ulOutputSize;
|
||
PMOUNTMGR_MOUNT_POINTS pOutput;
|
||
ULONG ulBytes;
|
||
BOOL bResult;
|
||
USHORT unNTNameLength;
|
||
|
||
|
||
// Open the mount manager
|
||
h = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ,
|
||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
||
INVALID_HANDLE_VALUE);
|
||
if (h == INVALID_HANDLE_VALUE)
|
||
{
|
||
TRACE( _T("Error: Open mount manager failed in GetDriveLetterAndVolumeName\n") );
|
||
return FALSE;
|
||
}
|
||
|
||
// Prepare the input structure
|
||
unNTNameLength = (USHORT)strNTName.GetLength();
|
||
ulInputSize = sizeof(MOUNTMGR_MOUNT_POINT) + ((unNTNameLength + 1)*sizeof(WCHAR));
|
||
pInput = (PMOUNTMGR_MOUNT_POINT) LocalAlloc( 0, ulInputSize);
|
||
if (!pInput)
|
||
{
|
||
TRACE( _T("Error: Memory allocation failure in GetDriveLetterAndVolumeName\n") );
|
||
CloseHandle(h);
|
||
return FALSE;
|
||
}
|
||
|
||
pInput->SymbolicLinkNameLength = 0;
|
||
pInput->SymbolicLinkNameOffset = 0;
|
||
pInput->UniqueIdOffset = 0;
|
||
pInput->UniqueIdLength = 0;
|
||
pInput->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||
pInput->DeviceNameLength = unNTNameLength * sizeof(WCHAR);
|
||
CopyStr2W( (LPWSTR) ((PUCHAR) pInput + pInput->DeviceNameOffset), strNTName );
|
||
|
||
// Prepare the output structure
|
||
ulOutputSize = sizeof(MOUNTMGR_MOUNT_POINTS) + 1024;
|
||
pOutput = (PMOUNTMGR_MOUNT_POINTS) LocalAlloc( 0, ulOutputSize);
|
||
if (!pOutput)
|
||
{
|
||
TRACE( _T("Error: Memory allocation failure in GetDriveLetterAndVolumeName\n") );
|
||
CloseHandle(h);
|
||
LocalFree(pInput);
|
||
return FALSE;
|
||
}
|
||
|
||
bResult = DeviceIoControl( h, IOCTL_MOUNTMGR_QUERY_POINTS, pInput, ulInputSize,
|
||
pOutput, ulOutputSize, &ulBytes, NULL);
|
||
|
||
while (!bResult && GetLastError() == ERROR_MORE_DATA)
|
||
{
|
||
ulOutputSize = pOutput->Size;
|
||
LocalFree( pOutput );
|
||
pOutput = (PMOUNTMGR_MOUNT_POINTS)(LocalAlloc(0, ulOutputSize ));
|
||
if (!pOutput)
|
||
{
|
||
TRACE( _T("Error: Memory Allocation failure in QueryMountPoints") );
|
||
CloseHandle(h);
|
||
LocalFree(pInput);
|
||
return FALSE;
|
||
}
|
||
bResult = DeviceIoControl(h, IOCTL_MOUNTMGR_QUERY_POINTS, pInput, ulInputSize,
|
||
pOutput, ulOutputSize, &ulBytes, NULL);
|
||
}
|
||
|
||
CloseHandle(h);
|
||
LocalFree(pInput);
|
||
|
||
if( !bResult )
|
||
{
|
||
TRACE( _T("Error: IOCTL_MOUNTMGR_QUERY_POINTS failure in GetDriveLetterAndVolumeName\n") );
|
||
LocalFree(pOutput);
|
||
return FALSE;
|
||
}
|
||
|
||
//CStringArray arrMountPointName;
|
||
CString strMountPoint;
|
||
for( ULONG i=0; i < pOutput->NumberOfMountPoints; i++ )
|
||
{
|
||
PMOUNTMGR_MOUNT_POINT pMountPoint = &(pOutput->MountPoints[i]);
|
||
|
||
/*
|
||
if (!point->SymbolicLinkNameOffset) {
|
||
continue; }
|
||
*/
|
||
CopyW2Str( strMountPoint, (LPWSTR)((PCHAR)pOutput + pMountPoint->SymbolicLinkNameOffset),
|
||
pMountPoint->SymbolicLinkNameLength / sizeof(WCHAR) );
|
||
|
||
if( IsDOSName( strMountPoint ) ) // i.e. "\DosDevices\X:"
|
||
{
|
||
// I got the drive letter
|
||
cDriveLetter = strMountPoint[12];
|
||
}
|
||
else if ( IsVolumeName( strMountPoint ) ) // i.e. "\??\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
{
|
||
// I got the volume name !!!!
|
||
strVolumeName = strMountPoint;
|
||
// Make it like this : "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
strVolumeName.SetAt( 1, _T('\\') );
|
||
}
|
||
}
|
||
|
||
LocalFree(pOutput);
|
||
return TRUE;
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: QueryMountListInPath
|
||
|
||
Purpose: Query the mount manager for all mount paths of the given volumes in a certain path
|
||
Each found mount path is added to the corresponding volume in array arrItems ( if any )
|
||
|
||
Parameters: [IN] CString& strPath
|
||
The path to search in
|
||
[IN/OUT] CObArray& arrVolumesData
|
||
Array of CItemData - Tree items ( volumes ) whose mount paths we are looking for
|
||
|
||
Return value: -
|
||
*/
|
||
|
||
void QueryMountListInPath( const CString& strPath, CObArray& arrVolumesData )
|
||
{
|
||
MY_TRY
|
||
|
||
BOOL bResult;
|
||
CString strVolName, strVolMountPoint, strMountPointPath;
|
||
|
||
LPTSTR lpstr = strVolName.GetBuffer(MAX_PATH);
|
||
bResult = GetVolumeNameForVolumeMountPoint( strPath, lpstr, MAX_PATH );
|
||
strVolName.ReleaseBuffer();
|
||
if( !bResult )
|
||
return;
|
||
|
||
// Cut the final backslash of the volume name and search it in the volumes array
|
||
CString strVolName2 = strVolName.Left( strVolName.GetLength() - 1 );
|
||
for( int i = 0; i < arrVolumesData.GetSize(); i++ )
|
||
{
|
||
CItemData* pData = (CItemData*)(arrVolumesData[i]);
|
||
if( pData->GetVolumeName() == strVolName2 )
|
||
{
|
||
// Cut the final backslash of the path and add it to the volume's mount paths
|
||
CString strPath2 = strPath.Left( strPath.GetLength() - 1 );
|
||
pData->GetMountPaths().Add(strPath2);
|
||
}
|
||
}
|
||
|
||
lpstr = strVolMountPoint.GetBuffer(MAX_PATH);
|
||
HANDLE h = FindFirstVolumeMountPoint( strVolName, lpstr, MAX_PATH);
|
||
strVolMountPoint.ReleaseBuffer();
|
||
if( h == INVALID_HANDLE_VALUE )
|
||
return;
|
||
|
||
for( ; ; )
|
||
{
|
||
strMountPointPath = strPath + strVolMountPoint;
|
||
QueryMountListInPath( strMountPointPath, arrVolumesData );
|
||
|
||
lpstr = strVolMountPoint.GetBuffer(MAX_PATH);
|
||
bResult = FindNextVolumeMountPoint( h, lpstr, MAX_PATH );
|
||
strVolMountPoint.ReleaseBuffer();
|
||
if( !bResult )
|
||
break;
|
||
}
|
||
|
||
FindVolumeMountPointClose(h);
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: QueryMountList
|
||
|
||
Purpose: Query the mount manager for all mount paths of the given volumes
|
||
Each found mount path is added to the corresponding volume in array arrItems ( if any )
|
||
|
||
Parameters: [IN/OUT] CObArray& arrVolumesData
|
||
Array of CItemData - Tree items ( volumes ) whose mount paths we are looking for
|
||
|
||
Return value: -
|
||
*/
|
||
|
||
void QueryMountList( CObArray& arrVolumesData )
|
||
{
|
||
MY_TRY
|
||
|
||
CString strName = _T("X:\\");
|
||
|
||
for( TCHAR cDriveLetter = _T('A'); cDriveLetter <= _T('Z'); cDriveLetter++ )
|
||
{
|
||
strName.SetAt(0, cDriveLetter);
|
||
QueryMountListInPath( strName, arrVolumesData );
|
||
}
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: ConvertPartitionsToFT
|
||
|
||
Purpose: Scans an array of CItemData and converts all physical partitions to
|
||
FT partitions. Then return the logical volume ID's of all items in the array
|
||
|
||
Parameters: [IN] CObArray& arrVolumeData
|
||
The array of CItemData to scan
|
||
[OUT] FT_LOGICAL_DISK_ID* arrVolID
|
||
The array of logical volume ID's of all items from arrVolumeData
|
||
( arrVolID[i] is the logical volume ID of volume represented by arrVolumeData[i] )
|
||
|
||
Return value: TRUE if all physical partitions are converted succesfully
|
||
If one conversion fails then all previously converted partitions are deconverted
|
||
*/
|
||
|
||
BOOL ConvertPartitionsToFT( CObArray& arrVolumeData, FT_LOGICAL_DISK_ID* arrVolID )
|
||
{
|
||
MY_TRY
|
||
|
||
ASSERT( arrVolID );
|
||
|
||
for( int i = 0; i < arrVolumeData.GetSize(); i++ )
|
||
{
|
||
CItemData* pData = (CItemData*)(arrVolumeData[i]);
|
||
ASSERT(pData);
|
||
if( pData->GetItemType() == IT_LogicalVolume )
|
||
pData->GetVolumeID( arrVolID[i] );
|
||
else if( pData->GetItemType() == IT_PhysicalPartition )
|
||
{
|
||
ASSERT( !pData->GetVolumeName().IsEmpty() );
|
||
if( !FTPart( pData->GetVolumeName(),
|
||
pData->GetDriveLetter(),
|
||
&(arrVolID[i]) ) )
|
||
{
|
||
// Deconvert all partitions you've previously converted and return FALSE
|
||
DeconvertPartitionsFromFT( arrVolumeData, arrVolID, i );
|
||
return FALSE;
|
||
}
|
||
}
|
||
else
|
||
ASSERT(FALSE);
|
||
}
|
||
return TRUE;
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: DeconvertPartitionsFromFT
|
||
|
||
Purpose: Scans an array of CItemData and deconverts all physical partitions from
|
||
FT partitions.
|
||
|
||
Parameters: [IN] CObArray& arrVolumeData
|
||
The array of CItemData to scan
|
||
[IN] FT_LOGICAL_DISK_ID* arrVolID
|
||
The array of logical volume ID's of volumes from arrVolumeData
|
||
( arrVolID[i] is the logical volume ID of volume represented by arrVolumeData[i] )
|
||
[IN] int nItems
|
||
The number of items ( starting with offset zero ) to deconvert
|
||
If nItems = -1 then all items in the array will be scanned and deconverted
|
||
|
||
Return value: TRUE if all physical partitions are deconverted succesfully
|
||
*/
|
||
|
||
BOOL DeconvertPartitionsFromFT( CObArray& arrVolumeData, FT_LOGICAL_DISK_ID* arrVolID, int nItems /* =-1 */ )
|
||
{
|
||
MY_TRY
|
||
|
||
BOOL bResult = TRUE;
|
||
|
||
if( nItems == -1 )
|
||
nItems = (int)arrVolumeData.GetSize();
|
||
|
||
for( int i = 0; i < nItems; i++ )
|
||
{
|
||
CItemData* pData = (CItemData*)(arrVolumeData[i]);
|
||
ASSERT(pData);
|
||
if( pData->GetItemType() == IT_PhysicalPartition )
|
||
bResult = FTBreak( arrVolID[i] ) && bResult;
|
||
}
|
||
return bResult;
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|
||
/*
|
||
Global function: CheckAdministratorsMembership
|
||
|
||
Purpose: Checks whether the current user is a member of the Administrators' group
|
||
|
||
Parameters: [OUT] BOOL& bIsAdministrator
|
||
Returns TRUE if the user is a member of the administrators group
|
||
|
||
Return value: TRUE the check concluded successfully with a YES / NO answer
|
||
*/
|
||
|
||
BOOL CheckAdministratorsMembership( BOOL& bIsAdministrator )
|
||
{
|
||
MY_TRY
|
||
|
||
BYTE sidBuffer[100];
|
||
PSID pSID = (PSID)&sidBuffer;
|
||
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
|
||
|
||
// Create a SID for the BUILTIN\Administrators group.
|
||
if( !AllocateAndInitializeSid( &SIDAuth, 2,
|
||
SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
|
||
&pSID) )
|
||
{
|
||
TRACE(_T("Error in AllocateAndInitializeSid\n"));
|
||
DisplaySystemErrorMessage( IDS_ERR_CHECK_ADMINISTRATOR );
|
||
return FALSE;
|
||
}
|
||
|
||
if( !CheckTokenMembership( NULL, pSID, &bIsAdministrator ) )
|
||
{
|
||
TRACE(_T("Error in CheckTokenMembership\n"));
|
||
DisplaySystemErrorMessage( IDS_ERR_CHECK_ADMINISTRATOR );
|
||
return FALSE;
|
||
}
|
||
|
||
if (pSID)
|
||
FreeSid(pSID);
|
||
|
||
return TRUE;
|
||
|
||
MY_CATCH_AND_THROW
|
||
}
|
||
|