windows-nt/Source/XPSP1/NT/termsrv/remdsk/server/sessmgr/helper.cpp

2765 lines
61 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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 );
}