|
|
/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
Helper.cpp
Abstract:
Various funtion encapsulate HELP user account validation, creating.
Author:
HueiWang 2/17/2000
--*/
#include "stdafx.h"
#include <time.h>
#include <stdio.h>
#ifndef __WIN9XBUILD__
#include <windows.h>
#include <ntsecapi.h>
#include <lmcons.h>
#include <lm.h>
#include <sspi.h>
#include <wtsapi32.h>
#include <winbase.h>
#include <security.h>
#endif
#include "Helper.h"
#ifndef __WIN9XBUILD__
#if DBG
void DebugPrintf( IN LPCTSTR format, ... ) /*++
Routine Description:
sprintf() like wrapper around OutputDebugString().
Parameters:
hConsole : Handle to console. format : format string.
Returns:
None.
Note:
To be replace by generic tracing code.
++*/ { TCHAR buf[8096]; // max. error text
DWORD dump; va_list marker; va_start(marker, format);
SYSTEMTIME sysTime; GetSystemTime(&sysTime);
try {
memset( buf, 0, sizeof(buf) );
_sntprintf( buf, sizeof(buf)/sizeof(buf[0]), _TEXT(" %d [%d:%d:%d:%d:%d.%d] : "), GetCurrentThreadId(), sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds );
_vsntprintf( buf + lstrlen(buf), sizeof(buf)/sizeof(buf[0]) - lstrlen(buf), format, marker );
OutputDebugString(buf); } catch(...) { }
va_end(marker); return; } #endif
#endif
void UnixTimeToFileTime( time_t t, LPFILETIME pft ) { LARGE_INTEGER li;
li.QuadPart = Int32x32To64(t, 10000000) + 116444736000000000;
pft->dwHighDateTime = li.HighPart; pft->dwLowDateTime = li.LowPart; }
#ifndef __WIN9XBUILD__
/*----------------------------------------------------------------------------
Routine Description:
This function checks to see whether the specified sid is enabled in the specified token.
Arguments:
TokenHandle - If present, this token is checked for the sid. If not present then the current effective token will be used. This must be an impersonation token.
SidToCheck - The sid to check for presence in the token
IsMember - If the sid is enabled in the token, contains TRUE otherwise false.
Return Value:
TRUE - The API completed successfully. It does not indicate that the sid is a member of the token.
FALSE - The API failed. A more detailed status code can be retrieved via GetLastError()
Note : Code modified from 5.0 \\rastaman\ntwin\src\base\advapi\security.c ----------------------------------------------------------------------------*/ BOOL TLSCheckTokenMembership( IN HANDLE TokenHandle OPTIONAL, IN PSID SidToCheck, OUT PBOOL IsMember ) { HANDLE ProcessToken = NULL; HANDLE EffectiveToken = NULL; DWORD Status = ERROR_SUCCESS; PISECURITY_DESCRIPTOR SecDesc = NULL; ULONG SecurityDescriptorSize; GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ, STANDARD_RIGHTS_EXECUTE, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_ALL }; //
// The size of the privilege set needs to contain the set itself plus
// any privileges that may be used. The privileges that are used
// are SeTakeOwnership and SeSecurity, plus one for good measure
//
BYTE PrivilegeSetBuffer[sizeof(PRIVILEGE_SET) + 3*sizeof(LUID_AND_ATTRIBUTES)]; PPRIVILEGE_SET PrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer; ULONG PrivilegeSetLength = sizeof(PrivilegeSetBuffer); ACCESS_MASK AccessGranted = 0; BOOL AccessStatus = FALSE; PACL Dacl = NULL;
#define MEMBER_ACCESS 1
*IsMember = FALSE;
//
// Get a handle to the token
//
if (TokenHandle != NULL) { EffectiveToken = TokenHandle; } else { if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, // don't open as self
&EffectiveToken)) { //
// if there is no thread token, try the process token
//
if((Status=GetLastError()) == ERROR_NO_TOKEN) { if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &ProcessToken)) { Status = GetLastError(); }
//
// If we have a process token, we need to convert it to an
// impersonation token
//
if (Status == ERROR_SUCCESS) { BOOL Result; Result = DuplicateToken(ProcessToken, SecurityImpersonation, &EffectiveToken); CloseHandle(ProcessToken); if (!Result) { return(FALSE); } } }
if (Status != ERROR_SUCCESS) { goto Cleanup; } } }
//
// Construct a security descriptor to pass to access check
//
//
// The size is equal to the size of an SD + twice the length of the SID
// (for owner and group) + size of the DACL = sizeof ACL + size of the
// ACE, which is an ACE + length of
// ths SID.
//
SecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(ACL) + 3 * GetLengthSid(SidToCheck);
SecDesc = (PISECURITY_DESCRIPTOR) LocalAlloc(LMEM_ZEROINIT, SecurityDescriptorSize ); if (SecDesc == NULL) { Status = ERROR_OUTOFMEMORY; goto Cleanup; } Dacl = (PACL) (SecDesc + 1);
InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
//
// Fill in fields of security descriptor
//
SetSecurityDescriptorOwner(SecDesc, SidToCheck, FALSE); SetSecurityDescriptorGroup(SecDesc, SidToCheck, FALSE);
if(!InitializeAcl( Dacl, SecurityDescriptorSize - sizeof(SECURITY_DESCRIPTOR), ACL_REVISION)) { Status=GetLastError(); goto Cleanup; }
if(!AddAccessAllowedAce(Dacl, ACL_REVISION, MEMBER_ACCESS, SidToCheck)) { Status=GetLastError(); goto Cleanup; }
if(!SetSecurityDescriptorDacl(SecDesc, TRUE, Dacl, FALSE)) { Status=GetLastError(); goto Cleanup; }
if(!AccessCheck(SecDesc, EffectiveToken, MEMBER_ACCESS, &GenericMapping, PrivilegeSet, &PrivilegeSetLength, &AccessGranted, &AccessStatus)) { Status=GetLastError(); goto Cleanup; }
//
// if the access check failed, then the sid is not a member of the
// token
//
if ((AccessStatus == TRUE) && (AccessGranted == MEMBER_ACCESS)) { *IsMember = TRUE; }
Cleanup: if (TokenHandle == NULL && EffectiveToken != NULL) { CloseHandle(EffectiveToken); }
if (SecDesc != NULL) { LocalFree(SecDesc); }
return (Status == ERROR_SUCCESS) ? TRUE : FALSE; }
/*------------------------------------------------------------------------
BOOL IsUserAdmin(BOOL)
returns TRUE if user is an admin FALSE if user is not an admin ------------------------------------------------------------------------*/ DWORD IsUserAdmin( BOOL* bMember ) { PSID psidAdministrators; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; DWORD dwStatus=ERROR_SUCCESS;
do { if(!AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators)) { dwStatus=GetLastError(); continue; }
// assume that we don't find the admin SID.
if(!TLSCheckTokenMembership(NULL, psidAdministrators, bMember)) { dwStatus=GetLastError(); }
FreeSid(psidAdministrators);
} while(FALSE);
return dwStatus; }
#endif
DWORD GetRandomNumber( HCRYPTPROV hProv, DWORD* pdwRandom ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; if( NULL == hProv ) { dwStatus = ERROR_INVALID_PARAMETER; } else { if( !CryptGenRandom(hProv, sizeof(*pdwRandom), (PBYTE)pdwRandom) ) { dwStatus = GetLastError(); } }
MYASSERT( ERROR_SUCCESS == dwStatus ); return dwStatus; }
//-----------------------------------------------------
DWORD ShuffleCharArray( IN HCRYPTPROV hProv, IN int iSizeOfTheArray, IN OUT TCHAR *lptsTheArray ) /*++
Routine Description:
Random shuffle content of a char. array.
Parameters:
iSizeOfTheArray : Size of array. lptsTheArray : On input, the array to be randomly shuffer, on output, the shuffled array.
Returns:
None. Note:
Code Modified from winsta\server\wstrpc.c
--*/ { int i; int iTotal; DWORD dwStatus = ERROR_SUCCESS;
if( NULL == hProv ) { dwStatus = ERROR_INVALID_PARAMETER; } else { iTotal = iSizeOfTheArray / sizeof(TCHAR); for (i = 0; i < iTotal && ERROR_SUCCESS == dwStatus; i++) { DWORD RandomNum; TCHAR c;
dwStatus = GetRandomNumber(hProv, &RandomNum);
if( ERROR_SUCCESS == dwStatus ) { c = lptsTheArray[i]; lptsTheArray[i] = lptsTheArray[RandomNum % iTotal]; lptsTheArray[RandomNum % iTotal] = c; } } }
return dwStatus; }
//-----------------------------------------------------
DWORD GenerateRandomBytes( IN DWORD dwSize, IN OUT LPBYTE pbBuffer ) /*++
Description:
Generate fill buffer with random bytes.
Parameters:
dwSize : Size of buffer pbBuffer point to. pbBuffer : Pointer to buffer to hold the random bytes.
Returns:
TRUE/FALSE
--*/ { HCRYPTPROV hProv = NULL; DWORD dwStatus = ERROR_SUCCESS;
//
// Create a Crypto Provider to generate random number
//
if( !CryptAcquireContext( &hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) ) { dwStatus = GetLastError(); goto CLEANUPANDEXIT; }
if( !CryptGenRandom(hProv, dwSize, pbBuffer) ) { dwStatus = GetLastError(); }
CLEANUPANDEXIT:
if( NULL != hProv ) { CryptReleaseContext( hProv, 0 ); }
return dwStatus; }
DWORD GenerateRandomString( IN DWORD dwSizeRandomSeed, IN OUT LPTSTR* pszRandomString ) /*++
--*/ { PBYTE lpBuffer = NULL; DWORD dwStatus = ERROR_SUCCESS; BOOL bSuccess; DWORD cbConvertString = 0;
if( 0 == dwSizeRandomSeed || NULL == pszRandomString ) { dwStatus = ERROR_INVALID_PARAMETER; MYASSERT(FALSE); goto CLEANUPANDEXIT; }
*pszRandomString = NULL;
lpBuffer = (PBYTE)LocalAlloc( LPTR, dwSizeRandomSeed ); if( NULL == lpBuffer ) { dwStatus = GetLastError(); goto CLEANUPANDEXIT; }
dwStatus = GenerateRandomBytes( dwSizeRandomSeed, lpBuffer );
if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
// Convert to string
bSuccess = CryptBinaryToString( lpBuffer, dwSizeRandomSeed, CRYPT_STRING_BASE64, 0, &cbConvertString ); if( FALSE == bSuccess ) { dwStatus = GetLastError(); goto CLEANUPANDEXIT; }
*pszRandomString = (LPTSTR)LocalAlloc( LPTR, (cbConvertString+1)*sizeof(TCHAR) ); if( NULL == *pszRandomString ) { dwStatus = GetLastError(); goto CLEANUPANDEXIT; }
bSuccess = CryptBinaryToString( lpBuffer, dwSizeRandomSeed, CRYPT_STRING_BASE64, *pszRandomString, &cbConvertString ); if( FALSE == bSuccess ) { dwStatus = GetLastError(); } else { if( (*pszRandomString)[cbConvertString - 1] == '\n' && (*pszRandomString)[cbConvertString - 2] == '\r' ) { (*pszRandomString)[cbConvertString - 2] = 0; } }
CLEANUPANDEXIT:
if( ERROR_SUCCESS != dwStatus ) { if( NULL != *pszRandomString ) { LocalFree(*pszRandomString); } }
if( NULL != lpBuffer ) { LocalFree(lpBuffer); }
return dwStatus; }
DWORD CreatePassword( OUT TCHAR *pszPassword ) /*++
Routine Description:
Routine to randomly create a password.
Parameters:
pszPassword : Pointer to buffer to received a randomly generated password, buffer must be at least MAX_HELPACCOUNT_PASSWORD+1 characters.
Returns:
None.
Note:
Code copied from winsta\server\wstrpc.c
--*/ { HCRYPTPROV hProv = NULL;
int nLength = MAX_HELPACCOUNT_PASSWORD; int iTotal = 0; DWORD RandomNum = 0; int i; time_t timeVal; DWORD dwStatus = ERROR_SUCCESS;
TCHAR six2pr[64] = { _T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F'), _T('G'), _T('H'), _T('I'), _T('J'), _T('K'), _T('L'), _T('M'), _T('N'), _T('O'), _T('P'), _T('Q'), _T('R'), _T('S'), _T('T'), _T('U'), _T('V'), _T('W'), _T('X'), _T('Y'), _T('Z'), _T('a'), _T('b'), _T('c'), _T('d'), _T('e'), _T('f'), _T('g'), _T('h'), _T('i'), _T('j'), _T('k'), _T('l'), _T('m'), _T('n'), _T('o'), _T('p'), _T('q'), _T('r'), _T('s'), _T('t'), _T('u'), _T('v'), _T('w'), _T('x'), _T('y'), _T('z'), _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'), _T('7'), _T('8'), _T('9'), _T('*'), _T('_') };
TCHAR something1[12] = { _T('!'), _T('@'), _T('#'), _T('$'), _T('^'), _T('&'), _T('*'), _T('('), _T(')'), _T('-'), _T('+'), _T('=') };
TCHAR something2[10] = { _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'), _T('7'), _T('8'), _T('9') };
TCHAR something3[26] = { _T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F'), _T('G'), _T('H'), _T('I'), _T('J'), _T('K'), _T('L'), _T('M'), _T('N'), _T('O'), _T('P'), _T('Q'), _T('R'), _T('S'), _T('T'), _T('U'), _T('V'), _T('W'), _T('X'), _T('Y'), _T('Z') };
TCHAR something4[26] = { _T('a'), _T('b'), _T('c'), _T('d'), _T('e'), _T('f'), _T('g'), _T('h'), _T('i'), _T('j'), _T('k'), _T('l'), _T('m'), _T('n'), _T('o'), _T('p'), _T('q'), _T('r'), _T('s'), _T('t'), _T('u'), _T('v'), _T('w'), _T('x'), _T('y'), _T('z') };
//
// Create a Crypto Provider to generate random number
//
if( !CryptAcquireContext( &hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) ) { dwStatus = GetLastError(); goto CLEANUPANDEXIT; }
//
// Shuffle around the six2pr[] array.
//
dwStatus = ShuffleCharArray(hProv, sizeof(six2pr), six2pr); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
//
// Assign each character of the password array.
//
iTotal = sizeof(six2pr) / sizeof(TCHAR); for (i=0; i<nLength && ERROR_SUCCESS == dwStatus; i++) { dwStatus = GetRandomNumber(hProv, &RandomNum); if( ERROR_SUCCESS == dwStatus ) { pszPassword[i]=six2pr[RandomNum%iTotal]; } }
if( ERROR_SUCCESS != dwStatus ) { MYASSERT(FALSE); goto CLEANUPANDEXIT; }
//
// In order to meet a possible policy set upon passwords, replace chars
// 2 through 5 with these:
//
// 1) something from !@#$%^&*()-+=
// 2) something from 1234567890
// 3) an uppercase letter
// 4) a lowercase letter
//
dwStatus = ShuffleCharArray(hProv, sizeof(something1), (TCHAR*)&something1); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
dwStatus = ShuffleCharArray(hProv, sizeof(something2), (TCHAR*)&something2); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
dwStatus = ShuffleCharArray(hProv, sizeof(something3), (TCHAR*)&something3); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
dwStatus = ShuffleCharArray(hProv, sizeof(something4), (TCHAR*)&something4); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
dwStatus = GetRandomNumber(hProv, &RandomNum); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
iTotal = sizeof(something1) / sizeof(TCHAR); pszPassword[2] = something1[RandomNum % iTotal];
dwStatus = GetRandomNumber(hProv, &RandomNum); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
iTotal = sizeof(something2) / sizeof(TCHAR); pszPassword[3] = something2[RandomNum % iTotal];
dwStatus = GetRandomNumber(hProv, &RandomNum); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
iTotal = sizeof(something3) / sizeof(TCHAR); pszPassword[4] = something3[RandomNum % iTotal];
dwStatus = GetRandomNumber(hProv, &RandomNum); if( ERROR_SUCCESS != dwStatus ) { goto CLEANUPANDEXIT; }
iTotal = sizeof(something4) / sizeof(TCHAR); pszPassword[5] = something4[RandomNum % iTotal];
pszPassword[nLength] = _T('\0');
CLEANUPANDEXIT:
if( NULL != hProv ) { CryptReleaseContext( hProv, 0 ); }
return dwStatus; }
//--------------------------------------------------------
#ifndef __WIN9XBUILD__
BOOL LookupAliasFromRid( LPWSTR pTargetComputer, DWORD Rid, LPWSTR pName, PDWORD cchName ) { BOOL fRet; PSID pSid = NULL; SID_IDENTIFIER_AUTHORITY SidIdentifierAuthority = SECURITY_NT_AUTHORITY; SID_NAME_USE SidNameUse; ULONG cchDomainName; WCHAR szDomainName[256];
//
// Sid is the same regardless of machine, since the well-known
// BUILTIN domain is referenced.
//
fRet = AllocateAndInitializeSid( &SidIdentifierAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, Rid, 0, 0, 0, 0, 0, 0, &pSid );
if (fRet) { cchDomainName = sizeof(szDomainName)/sizeof(szDomainName);
fRet = LookupAccountSidW( pTargetComputer, pSid, pName, cchName, szDomainName, &cchDomainName, &SidNameUse );
FreeSid(pSid); }
return(fRet); }
DWORD IsUserInLocalGroup( IN PBYTE pbUserSid, IN LPCTSTR pszLocalGroup, OUT BOOL* pbInGroup ) /*++
Routine Description:
Check if user is member of specific local group.
Parameters:
pbUserSid : SID of user to be verified. pszLocalGroup : Name of local group. pbInGroup : Return TRUE if user is in group, FALSE otherwise.
Returns:
ERROR_SUCCESS or error code, membership is returned via pbInGroup parameter. Note:
If 'everyone' is member of the specfied group, routine will immediately return SUCCESS.
--*/ { NET_API_STATUS netErr; LOCALGROUP_MEMBERS_INFO_0* pBuf=NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; PSID pEveryoneSID = NULL; DWORD dwEntries; DWORD dwTotal;
*pbInGroup = FALSE; //
// By default add everyone to the group
//
if(AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) ) { //
// Retrieve group member.
//
netErr = NetLocalGroupGetMembers( NULL, pszLocalGroup, 0, (LPBYTE *)&pBuf, MAX_PREFERRED_LENGTH, &dwEntries, &dwTotal, NULL );
if( NERR_Success == netErr ) { for(DWORD index=0; index < dwEntries; index++ ) { if(TRUE == EqualSid( pEveryoneSID, pBuf[index].lgrmi0_sid) ) { *pbInGroup = TRUE; break; }
if(NULL != pbUserSid && TRUE == EqualSid( pbUserSid, pBuf[index].lgrmi0_sid) ) { *pbInGroup = TRUE; break; } }
NetApiBufferFree( pBuf ); }
FreeSid( pEveryoneSID ); } else { netErr = GetLastError(); }
return netErr; }
BOOL IsLocalGroupExists( IN LPWSTR pszGroupName ) /*++
Routine Description:
Verify if local group exist on machine.
Parameter:
pszGroupName : Name of the group to be checked.
Returns:
TRUE/FALSE
--*/ { LOCALGROUP_INFO_1* pGroupInfo1; NET_API_STATUS netStatus; BOOL bGroupExists;
//
// Check to see if group exists
//
netStatus = NetLocalGroupGetInfo( NULL, pszGroupName, 1, (PBYTE *)&pGroupInfo1 );
if( NERR_Success == netStatus ) { NetApiBufferFree(pGroupInfo1); } else { SetLastError( netStatus ); }
return ( NERR_Success == netStatus ); }
//---------------------------------------------------------
DWORD CreateLocalGroup( IN LPWSTR pszGroupName, IN LPWSTR pszGroupDesc, IN BOOL bAddEveryone ) /*++
Routine Description:
Create a group on local machine.
Parameters:
pszGroupName : Group name. pszGroupDesc : Group desc. bAddEveryone : TRUE if add 'everyone' to the group, FALSE otherwise.
Returns: ERROR_SUCCESS or error code
--*/ { NET_API_STATUS netStatus; LOCALGROUP_INFO_1 GroupInfo; DWORD dwParmErr;
GroupInfo.lgrpi1_name = pszGroupName; GroupInfo.lgrpi1_comment = pszGroupDesc;
netStatus = NetLocalGroupAdd( NULL, 1, (LPBYTE)&GroupInfo, &dwParmErr );
if( NERR_Success == netStatus ) { if(FALSE == IsLocalGroupExists(pszGroupName)) { // We have big problem
netStatus = GetLastError(); } }
if( NERR_Success == netStatus && TRUE == bAddEveryone ) { LOCALGROUP_MEMBERS_INFO_0 gmember; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; PSID pEveryoneSID = NULL;
//
// add everyone to the group
//
if(AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) ) { gmember.lgrmi0_sid = pEveryoneSID;
bAddEveryone = NetLocalGroupAddMembers( NULL, pszGroupName, 0, (PBYTE)&gmember, 1 );
if( ERROR_MEMBER_IN_ALIAS == netStatus ) { // ignore this error
netStatus = NERR_Success; }
FreeSid( pEveryoneSID ); } }
return netStatus; }
//---------------------------------------------------------
DWORD RenameLocalAccount( IN LPWSTR pszOrgName, IN LPWSTR pszNewName ) /*++
Routine Description:
Parameters:
Returns:
ERROR_SUCCESS or error code.
--*/ { NET_API_STATUS err; USER_INFO_0 UserInfo;
UserInfo.usri0_name = pszNewName; err = NetUserSetInfo( NULL, pszOrgName, 0, (LPBYTE) &UserInfo, NULL );
return err; }
DWORD UpdateLocalAccountFullnameAndDesc( IN LPWSTR pszAccOrgName, IN LPWSTR pszAccFullName, IN LPWSTR pszAccDesc ) /*++
Routine Description:
Update account full name and description.
Parameters:
pszAccName : Account name. pszAccFullName : new account full name. pszAccDesc : new account description.
Returns:
ERROR_SUCCESS or error code
--*/ { LPBYTE pbServer = NULL; BYTE *pBuffer; NET_API_STATUS netErr = NERR_Success; DWORD parm_err;
netErr = NetUserGetInfo( NULL, pszAccOrgName, 3, &pBuffer );
if( NERR_Success == netErr ) { USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
lpui3->usri3_comment = pszAccDesc; lpui3->usri3_full_name = pszAccFullName;
netErr = NetUserSetInfo( NULL, pszAccOrgName, 3, (PBYTE)lpui3, &parm_err );
NetApiBufferFree(pBuffer); }
return netErr; }
DWORD IsLocalAccountEnabled( IN LPWSTR pszUserName, IN BOOL* pEnabled ) /*++
Routine Description:
Check if local account enabled
Parameters:
pszUserName : Name of user account. pEnabled : Return TRUE is account is enabled, FALSE otherwise.
Returns:
ERROR_SUCCESS or error code.
--*/ { DWORD dwResult; NET_API_STATUS err; LPBYTE pBuffer; USER_INFO_1 *pUserInfo;
err = NetUserGetInfo( NULL, pszUserName, 1, &pBuffer );
if( NERR_Success == err ) { pUserInfo = (USER_INFO_1 *)pBuffer;
if (pUserInfo != NULL) { if( pUserInfo->usri1_flags & UF_ACCOUNTDISABLE ) { *pEnabled = FALSE; } else { *pEnabled = TRUE; } }
NetApiBufferFree( pBuffer ); } else if( NERR_UserNotFound == err ) { *pEnabled = FALSE; //err = NERR_Success;
}
return err; }
//---------------------------------------------------------
DWORD EnableLocalAccount( IN LPWSTR pszUserName, IN BOOL bEnable ) /*++
Routine Description:
Routine to enable/disable a local account.
Parameters:
pszUserName : Name of user account. bEnable : TRUE if enabling account, FALSE if disabling account.
Returns:
ERROR_SUCCESS or error code.
--*/ { DWORD dwResult; NET_API_STATUS err; LPBYTE pBuffer; USER_INFO_1 *pUserInfo; BOOL bChangeAccStatus = TRUE;
err = NetUserGetInfo( NULL, pszUserName, 1, &pBuffer );
if( NERR_Success == err ) { pUserInfo = (USER_INFO_1 *)pBuffer;
if(pUserInfo != NULL) {
if( TRUE == bEnable && pUserInfo->usri1_flags & UF_ACCOUNTDISABLE ) { pUserInfo->usri1_flags &= ~UF_ACCOUNTDISABLE; } else if( FALSE == bEnable && !(pUserInfo->usri1_flags & UF_ACCOUNTDISABLE) ) { pUserInfo->usri1_flags |= UF_ACCOUNTDISABLE; } else { bChangeAccStatus = FALSE; }
if( TRUE == bChangeAccStatus ) { err = NetUserSetInfo( NULL, pszUserName, 1, pBuffer, &dwResult ); } }
NetApiBufferFree( pBuffer ); }
return err; }
//---------------------------------------------------------
BOOL IsPersonalOrProMachine() /*++
Routine Description:
Check if machine is PER or PRO sku.
Parameters:
None.
Return:
TRUE/FALSE --*/ { OSVERSIONINFOEX osVersionInfo; DWORDLONG dwlConditionMask = 0; BOOL bSuccess;
ZeroMemory( &osVersionInfo, sizeof(OSVERSIONINFOEX) );
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osVersionInfo.wProductType = VER_NT_SERVER;
VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL); bSuccess= VerifyVersionInfo( &osVersionInfo, VER_PRODUCT_TYPE, dwlConditionMask );
return !bSuccess; }
DWORD CreateLocalAccount( IN LPWSTR pszUserName, IN LPWSTR pszUserPwd, IN LPWSTR pszFullName, IN LPWSTR pszComment, IN LPWSTR pszGroup, IN LPWSTR pszScript, OUT BOOL* pbAccountExist ) /*++
Routine Description:
Create an user account on local machine.
Parameters:
pszUserName : Name of the user account. pszUserPwd : User account password. pszFullName : Account Full Name. pszComment : Account comment. pszGroup : Local group of the account. pbAccountExist ; Return TRUE if account already exists, FALSE otherwise.
Returns:
ERROR_SUCCESS or error code.
--*/ { LPBYTE pbServer = NULL; BYTE *pBuffer; NET_API_STATUS netErr = NERR_Success; DWORD parm_err; DWORD dwStatus;
netErr = NetUserGetInfo( NULL, pszUserName, 3, &pBuffer );
if( NERR_Success == netErr ) { //
// User account exists, if account is disabled,
// enable it and change password
//
USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
if( lpui3->usri3_flags & UF_ACCOUNTDISABLE || lpui3->usri3_flags & UF_LOCKOUT ) { // enable the account
lpui3->usri3_flags &= ~ ~UF_LOCKOUT;;
if( lpui3->usri3_flags & UF_ACCOUNTDISABLE ) { // we only reset password if account is disabled.
lpui3->usri3_flags &= ~ UF_ACCOUNTDISABLE; }
//lpui3->usri3_password = pszUserPwd;
// reset password if account is disabled.
lpui3->usri3_name = pszUserName; lpui3->usri3_comment = pszComment; lpui3->usri3_full_name = pszFullName; //lpui3->usri3_primary_group_id = dwGroupId;
netErr = NetUserSetInfo( NULL, pszUserName, 3, (PBYTE)lpui3, &parm_err ); }
*pbAccountExist = TRUE; NetApiBufferFree(pBuffer); } else if( NERR_UserNotFound == netErr ) { //
// Account does not exist, create and set it to our group
//
USER_INFO_1 UserInfo;
memset(&UserInfo, 0, sizeof(USER_INFO_1));
UserInfo.usri1_name = pszUserName; UserInfo.usri1_password = pszUserPwd; UserInfo.usri1_priv = USER_PRIV_USER; // see USER_INFO_1 for detail
UserInfo.usri1_comment = pszComment; UserInfo.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
netErr = NetUserAdd( NULL, 1, (PBYTE)&UserInfo, &parm_err );
*pbAccountExist = FALSE; }
return netErr; }
///////////////////////////////////////////////////////////////////////////////
DWORD ChangeLocalAccountPassword( IN LPWSTR pszAccName, IN LPWSTR pszOldPwd, IN LPWSTR pszNewPwd ) /*++
Routine Description:
Change password of a local account.
Parameters:
pszAccName : Name of user account. pszOldPwd : Old password. pszNewPwd : New password.
Returns:
ERROR_SUCCESS or error code.
Notes:
User NetUserChangePassword(), must have priviledge
--*/ { USER_INFO_1003 sUserInfo3; NET_API_STATUS netErr;
UNREFERENCED_PARAMETER( pszOldPwd );
sUserInfo3.usri1003_password = pszNewPwd; netErr = NetUserSetInfo( NULL, pszAccName, 1003, (BYTE *) &sUserInfo3, 0 );
return netErr; } ///////////////////////////////////////////////////////////////////////////////
DWORD RetrieveKeyFromLSA( IN PWCHAR pwszKeyName, OUT PBYTE * ppbKey, OUT DWORD * pcbKey ) /*++
Routine Description:
Retrieve private data previously stored with StoreKeyWithLSA().
Parameters:
pwszKeyName : Name of the key. ppbKey : Pointer to PBYTE to receive binary data. pcbKey : Size of binary data.
Returns:
ERROR_SUCCESS ERROR_INVALID_PARAMETER. ERROR_FILE_NOT_FOUND LSA return code
Note:
Memory is allocated using LocalAlloc()
--*/ { LSA_HANDLE PolicyHandle; UNICODE_STRING SecretKeyName; UNICODE_STRING *pSecretData; DWORD Status;
if( ( NULL == pwszKeyName ) || ( NULL == ppbKey ) || ( NULL == pcbKey ) ) { return( ERROR_INVALID_PARAMETER ); }
//
// setup the UNICODE_STRINGs for the call.
//
InitLsaString( &SecretKeyName, pwszKeyName );
Status = OpenPolicy( NULL, POLICY_GET_PRIVATE_INFORMATION, &PolicyHandle );
if( Status != ERROR_SUCCESS ) { return LsaNtStatusToWinError(Status); }
Status = LsaRetrievePrivateData( PolicyHandle, &SecretKeyName, &pSecretData );
LsaClose( PolicyHandle );
if( Status != ERROR_SUCCESS ) { return LsaNtStatusToWinError(Status); }
if(pSecretData->Length) { *ppbKey = ( LPBYTE )LocalAlloc( LPTR, pSecretData->Length );
if( *ppbKey ) { *pcbKey = pSecretData->Length; CopyMemory( *ppbKey, pSecretData->Buffer, pSecretData->Length ); Status = ERROR_SUCCESS; } else { Status = GetLastError(); } } else { Status = ERROR_FILE_NOT_FOUND; *pcbKey = 0; *ppbKey = NULL; }
ZeroMemory( pSecretData->Buffer, pSecretData->Length ); LsaFreeMemory( pSecretData );
return Status; }
///////////////////////////////////////////////////////////////////////////////
DWORD StoreKeyWithLSA( IN PWCHAR pwszKeyName, IN BYTE * pbKey, IN DWORD cbKey ) /*++
Routine Description:
Save private data to LSA.
Parameters:
pwszKeyName : Name of the key this data going to be stored under. pbKey : Binary data to be saved. cbKey : Size of binary data.
Returns:
ERROR_SUCCESS ERROR_INVALID_PARAMETER. LSA return code
--*/ { LSA_HANDLE PolicyHandle; UNICODE_STRING SecretKeyName; UNICODE_STRING SecretData; DWORD Status; if( ( NULL == pwszKeyName ) ) { return( ERROR_INVALID_PARAMETER ); }
//
// setup the UNICODE_STRINGs for the call.
//
InitLsaString( &SecretKeyName, pwszKeyName );
SecretData.Buffer = ( LPWSTR )pbKey; SecretData.Length = ( USHORT )cbKey; SecretData.MaximumLength = ( USHORT )cbKey;
Status = OpenPolicy( NULL, POLICY_CREATE_SECRET, &PolicyHandle );
if( Status != ERROR_SUCCESS ) { return LsaNtStatusToWinError(Status); }
Status = LsaStorePrivateData( PolicyHandle, &SecretKeyName, &SecretData );
LsaClose(PolicyHandle);
return LsaNtStatusToWinError(Status); }
///////////////////////////////////////////////////////////////////////////////
DWORD OpenPolicy( IN LPWSTR ServerName, IN DWORD DesiredAccess, OUT PLSA_HANDLE PolicyHandle ) /*++
Routine Description:
Create/return a LSA policy handle.
Parameters: ServerName : Name of server, refer to LsaOpenPolicy(). DesiredAccess : Desired access level, refer to LsaOpenPolicy(). PolicyHandle : Return PLSA_HANDLE.
Returns:
ERROR_SUCCESS or LSA error code
--*/ { LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_UNICODE_STRING ServerString; PLSA_UNICODE_STRING Server;
//
// Always initialize the object attributes to all zeroes.
//
ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
if( NULL != ServerName ) { //
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString( &ServerString, ServerName ); Server = &ServerString;
} else { Server = NULL; }
//
// Attempt to open the policy.
//
return( LsaOpenPolicy( Server, &ObjectAttributes, DesiredAccess, PolicyHandle ) ); }
///////////////////////////////////////////////////////////////////////////////
void InitLsaString( IN OUT PLSA_UNICODE_STRING LsaString, IN LPWSTR String ) /*++
Routine Description:
Initialize LSA unicode string.
Parameters:
LsaString : Pointer to LSA_UNICODE_STRING to be initialized. String : String to initialize LsaString.
Returns:
None.
Note:
Refer to LSA_UNICODE_STRING
--*/ { DWORD StringLength;
if( NULL == String ) { LsaString->Buffer = NULL; LsaString->Length = 0; LsaString->MaximumLength = 0; return; }
StringLength = lstrlenW( String ); LsaString->Buffer = String; LsaString->Length = ( USHORT ) StringLength * sizeof( WCHAR ); LsaString->MaximumLength=( USHORT )( StringLength + 1 ) * sizeof( WCHAR ); }
//-----------------------------------------------------
BOOL ValidatePassword( IN LPWSTR pszUserName, IN LPWSTR pszDomain, IN LPWSTR pszPassword ) /*++
Routine Description:
Validate user account password.
Parameters:
pszUserName : Name of user account. pszDomain : Domain name. pszPassword : Password to be verified.
Returns:
TRUE or FALSE.
Note:
To debug this code, you will need to run process as service in order for it to verify password. Refer to MSDN on LogonUser --*/ { HANDLE hToken; BOOL bSuccess;
//
// To debug this code, you will need to run process as service in order
// for it to verify password. Refer to MSDN on LogonUser
//
bSuccess = LogonUser( pszUserName, pszDomain, //_TEXT("."), //pszDomain,
pszPassword, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &hToken );
if( TRUE == bSuccess ) { CloseHandle( hToken ); } else { DWORD dwStatus = GetLastError();
DebugPrintf( _TEXT("ValidatePassword() failed with %d\n"), dwStatus );
SetLastError(dwStatus); }
return bSuccess; }
//---------------------------------------------------------------
BOOL GetTextualSid( IN PSID pSid, // binary Sid
IN OUT LPTSTR TextualSid, // buffer for Textual representation of Sid
IN OUT LPDWORD lpdwBufferLen // required/provided TextualSid buffersize
) /*++
Routine Description:
Conver a SID to string representation, code from MSDN
Parameters:
pSid : Pointer to SID to be converted to string. TextualSid : On input, pointer to buffer to received converted string, on output, converted SID in string form. lpdwBufferLen : On input, size of the buffer, on output, length of converted string or required buffer size in char.
Returns:
TRUE/FALSE, use GetLastError() to retrieve detail error code.
--*/ { PSID_IDENTIFIER_AUTHORITY psia; DWORD dwSubAuthorities; DWORD dwSidRev=SID_REVISION; DWORD dwCounter; DWORD dwSidSize;
// Validate the binary SID.
if(!IsValidSid(pSid)) { return FALSE; }
// Get the identifier authority value from the SID.
psia = GetSidIdentifierAuthority(pSid);
// Get the number of subauthorities in the SID.
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
// Compute the buffer length.
// S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
// Check input buffer length.
// If too small, indicate the proper size and set last error.
if (*lpdwBufferLen < dwSidSize) { *lpdwBufferLen = dwSidSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
// Add 'S' prefix and revision number to the string.
dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
// Add SID identifier authority to the string.
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) { dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), (USHORT)psia->Value[0], (USHORT)psia->Value[1], (USHORT)psia->Value[2], (USHORT)psia->Value[3], (USHORT)psia->Value[4], (USHORT)psia->Value[5]); } else { dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"), (ULONG)(psia->Value[5] ) + (ULONG)(psia->Value[4] << 8) + (ULONG)(psia->Value[3] << 16) + (ULONG)(psia->Value[2] << 24) ); }
// Add SID subauthorities to the string.
//
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) { dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter) ); }
return TRUE; }
#endif
long GetUserTSLogonIdEx( HANDLE hToken ) /*++
--*/ { BOOL Result; LONG SessionId = -1; ULONG ReturnLength;
#ifndef __WIN9XBUILD__
//
// Use the _HYDRA_ extension to GetTokenInformation to
// return the SessionId from the token.
//
Result = GetTokenInformation( hToken, TokenSessionId, &SessionId, sizeof(SessionId), &ReturnLength );
if( !Result ) {
DWORD dwStatus = GetLastError(); SessionId = -1;
}
#endif
return SessionId; }
long GetUserTSLogonId() /*++
Routine Description:
Return client TS Session ID.
Parameters:
None.
Returns:
Client's TS session ID or 0 if not on TS.
Note:
Must have impersonate user first.
--*/ { LONG lSessionId = -1;
#ifndef __WIN9XBUILD__
HANDLE hToken; BOOL bSuccess;
bSuccess = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, //TOKEN_ALL_ACCESS,
FALSE, &hToken );
if( TRUE == bSuccess ) { lSessionId = GetUserTSLogonIdEx(hToken); CloseHandle(hToken); }
#else
lSessionId = 0;
#endif
return lSessionId; }
//
//
////////////////////////////////////////////////////////////////
//
//
DWORD RegEnumSubKeys( IN HKEY hKey, IN LPCTSTR pszSubKey, IN RegEnumKeyCallback pFunc, IN HANDLE userData ) /*++
--*/ { DWORD dwStatus; HKEY hSubKey = NULL; int index;
LONG dwNumSubKeys; DWORD dwMaxSubKeyLength; DWORD dwSubKeyLength; LPTSTR pszSubKeyName = NULL;
DWORD dwMaxValueNameLen; LPTSTR pszValueName = NULL; DWORD dwValueNameLength;
if( NULL == hKey ) { dwStatus = ERROR_INVALID_PARAMETER; return dwStatus; }
dwStatus = RegOpenKeyEx( hKey, pszSubKey, 0, KEY_ALL_ACCESS, &hSubKey );
if(dwStatus != ERROR_SUCCESS) { // key does not exist
return dwStatus; }
//
// Query number of subkeys
//
dwStatus = RegQueryInfoKey( hSubKey, NULL, NULL, NULL, (DWORD *)&dwNumSubKeys, &dwMaxSubKeyLength, NULL, NULL, &dwMaxValueNameLen, NULL, NULL, NULL );
if(dwStatus != ERROR_SUCCESS) { goto cleanup; }
dwMaxValueNameLen++; pszValueName = (LPTSTR)LocalAlloc( LPTR, dwMaxValueNameLen * sizeof(TCHAR) ); if(pszValueName == NULL) { goto cleanup; }
if(dwNumSubKeys > 0) { // allocate buffer for subkeys.
dwMaxSubKeyLength++; pszSubKeyName = (LPTSTR)LocalAlloc( LPTR, dwMaxSubKeyLength * sizeof(TCHAR) ); if(pszSubKeyName == NULL) { dwStatus = ERROR_OUTOFMEMORY; goto cleanup; }
for(;dwStatus == ERROR_SUCCESS && dwNumSubKeys >= 0;) { // delete this subkey.
dwSubKeyLength = dwMaxSubKeyLength; memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
// retrieve subkey name
dwStatus = RegEnumKeyEx( hSubKey, (DWORD)--dwNumSubKeys, pszSubKeyName, &dwSubKeyLength, NULL, NULL, NULL, NULL );
if(dwStatus == ERROR_SUCCESS) { dwStatus = pFunc( hSubKey, pszSubKeyName, userData ); } }
if( ERROR_NO_MORE_ITEMS == dwStatus ) { dwStatus = ERROR_SUCCESS; } }
cleanup: // close the key before trying to delete it.
if(hSubKey != NULL) { RegCloseKey(hSubKey); }
if(pszValueName != NULL) { LocalFree(pszValueName); }
if(pszSubKeyName != NULL) { LocalFree(pszSubKeyName); }
return dwStatus; }
DWORD RegDelKey( IN HKEY hRegKey, IN LPCTSTR pszSubKey ) /*++
Abstract:
Recursively delete entire registry key.
Parameter:
hKey : Handle to a curently open key. pszSubKey : Pointer to NULL terminated string containing the key to be deleted.
Returns:
Error code from RegOpenKeyEx(), RegQueryInfoKey(), RegEnumKeyEx().
++*/ { DWORD dwStatus; HKEY hSubKey = NULL; int index;
DWORD dwNumSubKeys; DWORD dwMaxSubKeyLength; DWORD dwSubKeyLength; LPTSTR pszSubKeyName = NULL;
DWORD dwMaxValueNameLen; LPTSTR pszValueName = NULL; DWORD dwValueNameLength;
if( NULL == hRegKey ) { dwStatus = ERROR_INVALID_PARAMETER; return dwStatus; }
dwStatus = RegOpenKeyEx( hRegKey, pszSubKey, 0, KEY_ALL_ACCESS, &hSubKey );
if(dwStatus != ERROR_SUCCESS) { // key does not exist
return dwStatus; }
//
// Query number of subkeys
//
dwStatus = RegQueryInfoKey( hSubKey, NULL, NULL, NULL, &dwNumSubKeys, &dwMaxSubKeyLength, NULL, NULL, &dwMaxValueNameLen, NULL, NULL, NULL );
if(dwStatus != ERROR_SUCCESS) { goto cleanup; }
dwMaxValueNameLen++; pszValueName = (LPTSTR)LocalAlloc( LPTR, dwMaxValueNameLen * sizeof(TCHAR) ); if(pszValueName == NULL) { goto cleanup; }
if(dwNumSubKeys > 0) { // allocate buffer for subkeys.
dwMaxSubKeyLength++; pszSubKeyName = (LPTSTR)LocalAlloc( LPTR, dwMaxSubKeyLength * sizeof(TCHAR) ); if(pszSubKeyName == NULL) { dwStatus = ERROR_OUTOFMEMORY; goto cleanup; }
//for(index = 0; index < dwNumSubKeys; index++)
for(;dwStatus == ERROR_SUCCESS;) { // delete this subkey.
dwSubKeyLength = dwMaxSubKeyLength; memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
// retrieve subkey name
dwStatus = RegEnumKeyEx( hSubKey, (DWORD)0, pszSubKeyName, &dwSubKeyLength, NULL, NULL, NULL, NULL );
if(dwStatus == ERROR_SUCCESS) { dwStatus = RegDelKey( hSubKey, pszSubKeyName ); }
// ignore any error and continue on
} }
cleanup:
for(dwStatus = ERROR_SUCCESS; pszValueName != NULL && dwStatus == ERROR_SUCCESS;) { dwValueNameLength = dwMaxValueNameLen; memset(pszValueName, 0, dwMaxValueNameLen * sizeof(TCHAR));
dwStatus = RegEnumValue( hSubKey, 0, pszValueName, &dwValueNameLength, NULL, NULL, NULL, NULL );
if(dwStatus == ERROR_SUCCESS) { RegDeleteValue(hSubKey, pszValueName); } } // close the key before trying to delete it.
if(hSubKey != NULL) { RegCloseKey(hSubKey); }
// try to delete this key, will fail if any of the subkey
// failed to delete in loop
dwStatus = RegDeleteKey( hRegKey, pszSubKey );
if(pszValueName != NULL) { LocalFree(pszValueName); }
if(pszSubKeyName != NULL) { LocalFree(pszSubKeyName); }
return dwStatus; }
//---------------------------------------------------------------
DWORD GetUserSid( OUT PBYTE* ppbSid, OUT DWORD* pcbSid ) /*++
Routine Description:
Retrieve user's SID , must impersonate client first.
Parameters:
ppbSid : Pointer to PBYTE to receive user's SID. pcbSid : Pointer to DWORD to receive size of SID.
Returns:
ERROR_SUCCESS or error code.
Note:
Must have call ImpersonateClient(), funtion is NT specific, Win9X will return internal error.
--*/ { #ifndef __WIN9XBUILD__
BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS;
HANDLE hToken = NULL; DWORD dwSize = 0; TOKEN_USER* pToken = NULL;
*ppbSid = NULL; *pcbSid = 0;
//
// Open current process token
//
bSuccess = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken );
if( TRUE == bSuccess ) { //
// get user's token.
//
GetTokenInformation( hToken, TokenUser, NULL, 0, &dwSize );
pToken = (TOKEN_USER *)LocalAlloc( LPTR, dwSize ); if( NULL != pToken ) { bSuccess = GetTokenInformation( hToken, TokenUser, (LPVOID) pToken, dwSize, &dwSize );
if( TRUE == bSuccess ) { //
// GetLengthSid() return size of buffer require,
// must call IsValidSid() first
//
bSuccess = IsValidSid( pToken->User.Sid ); if( TRUE == bSuccess ) { *pcbSid = GetLengthSid( (PBYTE)pToken->User.Sid ); *ppbSid = (PBYTE)LocalAlloc(LPTR, *pcbSid); if( NULL != *ppbSid ) { bSuccess = CopySid( *pcbSid, *ppbSid, pToken->User.Sid ); } else // fail in LocalAlloc()
{ bSuccess = FALSE; } } // IsValidSid()
} // GetTokenInformation()
} else // LocalAlloc() fail
{ bSuccess = FALSE; } }
if( TRUE != bSuccess ) { dwStatus = GetLastError();
if( NULL != *ppbSid ) { LocalFree(*ppbSid); *ppbSid = NULL; *pcbSid = 0; } }
//
// Free resources...
//
if( NULL != pToken ) { LocalFree(pToken); }
if( NULL != hToken ) { CloseHandle(hToken); }
return dwStatus;
#else
return E_UNEXPECTED;
#endif
}
//----------------------------------------------------------------
HRESULT GetUserSidString( OUT CComBSTR& bstrSid ) /*++
Routine Description:
Retrieve user's SID in textual form, must impersonate client first.
Parameters:
bstrSID : Return users' SID in textual form.
Returns:
ERROR_SUCCESS or error code.
Note:
Must have call ImpersonateClient().
--*/ { #ifndef __WIN9XBUILD__
DWORD dwStatus; PBYTE pbSid = NULL; DWORD cbSid = 0; BOOL bSuccess = TRUE; LPTSTR pszTextualSid = NULL; DWORD dwTextualSid = 0;
dwStatus = GetUserSid( &pbSid, &cbSid ); if( ERROR_SUCCESS == dwStatus ) { bSuccess = GetTextualSid( pbSid, NULL, &dwTextualSid );
if( FALSE == bSuccess && ERROR_INSUFFICIENT_BUFFER == GetLastError() ) { pszTextualSid = (LPTSTR)LocalAlloc( LPTR, (dwTextualSid + 1) * sizeof(TCHAR) );
if( NULL != pszTextualSid ) { bSuccess = GetTextualSid( pbSid, pszTextualSid, &dwTextualSid );
if( TRUE == bSuccess ) { bstrSid = pszTextualSid; } } }
if( FALSE == bSuccess ) { dwStatus = GetLastError(); } }
if( NULL != pszTextualSid ) { LocalFree(pszTextualSid); }
if( NULL != pbSid ) { LocalFree(pbSid); }
return HRESULT_FROM_WIN32(dwStatus);
#else
bstrSid = WIN9X_USER_SID;
return S_OK;
#endif
}
BOOL FileExists( IN LPCTSTR FileName, OUT PWIN32_FIND_DATA FindData OPTIONAL )
/*++
Routine Description:
Determine if a file exists and is accessible. Errormode is set (and then restored) so the user will not see any pop-ups.
Arguments:
FileName - supplies full path of file to check for existance.
FindData - if specified, receives find data for the file.
Return Value:
TRUE if the file exists and is accessible. FALSE if not. GetLastError() returns extended error info.
--*/
{ WIN32_FIND_DATA findData; HANDLE FindHandle; DWORD Error;
FindHandle = FindFirstFile(FileName,&findData); if(FindHandle == INVALID_HANDLE_VALUE) { Error = GetLastError(); } else { FindClose(FindHandle); if(FindData) { *FindData = findData; } Error = NO_ERROR; }
SetLastError(Error); return (Error == NO_ERROR); }
BOOL AdjustPrivilege( PWSTR Privilege ) /*++
Routine Description:
This routine tries to adjust the priviliege of the current process.
Arguments:
Privilege - String with the name of the privilege to be adjusted.
Return Value:
Returns TRUE if the privilege could be adjusted. Returns FALSE, otherwise.
--*/ { HANDLE TokenHandle; LUID_AND_ATTRIBUTES LuidAndAttributes;
TOKEN_PRIVILEGES TokenPrivileges;
if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle ) ) { return( FALSE ); }
if( !LookupPrivilegeValue( NULL, Privilege, // (LPWSTR)SE_SECURITY_NAME,
&( LuidAndAttributes.Luid ) ) ) { return( FALSE ); }
LuidAndAttributes.Attributes = SE_PRIVILEGE_ENABLED; TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0] = LuidAndAttributes;
if( !AdjustTokenPrivileges( TokenHandle, FALSE, &TokenPrivileges, 0, NULL, NULL ) ) { return( FALSE ); }
if( GetLastError() != NO_ERROR ) { return( FALSE ); } return( TRUE ); }
|