|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cenumGroupCollection.cxx
//
// Contents: Windows NT 3.5 GroupCollection Enumeration Code
//
//
//
//
//
//
// History:
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
COMPUTER_GROUP_MEMBER CompMember;
//
// This assumes that addr is an LPBYTE type.
//
#define WORD_ALIGN_DOWN(addr) \
addr = ((LPBYTE)((DWORD_PTR)addr & ~1))
DWORD ComputerGrpMemberStrings[]=
{ FIELD_OFFSET(COMPUTER_GROUP_MEMBER, Parent), FIELD_OFFSET(COMPUTER_GROUP_MEMBER, Computer), FIELD_OFFSET(COMPUTER_GROUP_MEMBER, Domain), FIELD_OFFSET(COMPUTER_GROUP_MEMBER, Name), 0xFFFFFFFF };
DECLARE_INFOLEVEL(GrpUt) DECLARE_DEBUG(GrpUt) #define GrpUtDebugOut(x) GrpUtInlineDebugOut x
BOOL WinNTLocalGroupOpen( LPWSTR szDomainName, LPWSTR szComputerName, LPWSTR szGroupName, PHANDLE phGroup ) {
WCHAR szTempBuffer[MAX_PATH]; PINI_COMP_GROUP pIniCompGrp; HRESULT hr;
if (!phGroup) { return(FALSE); } pIniCompGrp = (PINI_COMP_GROUP)AllocADsMem( sizeof(INI_COMP_GROUP) ); if (!pIniCompGrp) { return(FALSE); }
hr = MakeUncName( szComputerName, szTempBuffer ); BAIL_ON_FAILURE(hr);
if (!(pIniCompGrp->szUncCompName = AllocADsStr(szTempBuffer))){ goto error; }
// to guard against the case of domainName == NULL for no
// workstation services
if (szDomainName != NULL) { if (!(pIniCompGrp->szDomainName = AllocADsStr(szDomainName))) { goto error; } }
if (!(pIniCompGrp->szComputerName = AllocADsStr(szComputerName))){ goto error; }
if (!(pIniCompGrp->szGroupName = AllocADsStr(szGroupName))){ goto error; }
*phGroup = (HANDLE)pIniCompGrp;
return(TRUE);
error: if (pIniCompGrp) { FreeIniCompGroup(pIniCompGrp); }
*phGroup = NULL;
return(FALSE);
}
BOOL WinNTLocalGroupEnum( HANDLE hGroup, DWORD dwRequested, LPBYTE * ppBuffer, PDWORD pdwReturned ) {
LPCOMPUTER_GROUP_MEMBER * ppGroupMembers = NULL; DWORD i = 0; BOOL dwRet = FALSE; DWORD dwReturned = 0; DWORD dwSize = 0; LPCOMPUTER_GROUP_MEMBER pBuffer = NULL; LPBYTE pEnd = NULL; DWORD dwError; BOOL fretVal = FALSE;
ppGroupMembers = (LPCOMPUTER_GROUP_MEMBER *)AllocADsMem( sizeof(LPCOMPUTER_GROUP_MEMBER)* dwRequested ); if (!ppGroupMembers) { return(FALSE); }
for (i = 0; i < dwRequested; i++) {
dwRet = WinNTLocalGroupGetObject( hGroup, &ppGroupMembers[dwReturned] ); if (!dwRet) {
dwError = GetLastError(); if (dwError == ERROR_INVALID_SID) { continue; }
//
// it was not because of a bad sid
// so break out, nothing more can be done
//
break;
}
dwReturned++;
}
dwRet = ComputeLocalGroupDataSize( ppGroupMembers, dwReturned, &dwSize );
pBuffer = (LPCOMPUTER_GROUP_MEMBER)AllocADsMem( dwSize );
if (pBuffer) {
fretVal = TRUE;
pEnd = (LPBYTE)((LPBYTE)(pBuffer) + dwSize);
for (i = 0; i < dwReturned; i++) {
pEnd = CopyIniCompGroupToCompGroup( ppGroupMembers[i], (LPBYTE)(pBuffer + i), pEnd ); } }
for (i = 0; i < dwReturned; i++ ) { FreeIntCompGroup(*(ppGroupMembers + i)); }
FreeADsMem(ppGroupMembers);
//
// Will correctl set to NULL if alloc failed.
//
*ppBuffer = (LPBYTE)pBuffer; *pdwReturned = fretVal ? dwReturned : 0;
if (!fretVal) { return(FALSE); }
if (dwReturned == dwRequested){ return(TRUE); }else { return(FALSE); } }
BOOL WinNTLocalGroupGetObject( HANDLE hGroup, LPCOMPUTER_GROUP_MEMBER * ppGroupMember ) {
BOOL dwRet = FALSE; PINI_COMP_GROUP pIniCompGrp = (PINI_COMP_GROUP)hGroup; NET_API_STATUS nasStatus = 0;
if ((!pIniCompGrp->_pBuffer) || (pIniCompGrp->_dwCurrentObject == pIniCompGrp->_dwObjectReturned)) {
if (pIniCompGrp->_bNoMore) {
//
// No more objects to return
//
return(FALSE); }
if (pIniCompGrp->_pBuffer) { NetApiBufferFree(pIniCompGrp->_pBuffer); pIniCompGrp->_pBuffer = NULL; }
pIniCompGrp->_dwObjectReturned = 0; pIniCompGrp->_dwCurrentObject = 0; pIniCompGrp->_dwTotalObjects = 0;
nasStatus = NetLocalGroupGetMembers( pIniCompGrp->szUncCompName, pIniCompGrp->szGroupName, 2, &pIniCompGrp->_pBuffer, MAX_PREFERRED_LENGTH, &pIniCompGrp->_dwObjectReturned, &pIniCompGrp->_dwTotalObjects, &pIniCompGrp->_dwResumeHandle ); if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)){ SetLastError(nasStatus); return(FALSE); }
if (nasStatus != ERROR_MORE_DATA) { pIniCompGrp->_bNoMore = TRUE; }
//
// If there are no more objects to return,
// return FALSE
//
if (!pIniCompGrp->_dwObjectReturned) { return(FALSE); }
}
while ( dwRet != TRUE && (pIniCompGrp->_dwCurrentObject < pIniCompGrp->_dwTotalObjects)) {
dwRet = BuildLocalGroupMember( hGroup, (LPBYTE)((LPLOCALGROUP_MEMBERS_INFO_2)pIniCompGrp->_pBuffer + pIniCompGrp->_dwCurrentObject), ppGroupMember );
if (dwRet == FALSE) { if (GetLastError() == ERROR_INVALID_SID) { pIniCompGrp->_dwCurrentObject++; continue; //
// proceed to the top of the while loop
//
} else goto error; } } //
// the while loop
//
if (dwRet == FALSE) goto error;
pIniCompGrp->_dwCurrentObject++;
return(TRUE);
error:
return(FALSE); }
BOOL WinNTLocalGroupClose( HANDLE hGroup ) {
PINI_COMP_GROUP pIniCompGrp = (PINI_COMP_GROUP)hGroup;
if (pIniCompGrp) { FreeIniCompGroup(pIniCompGrp); } return(TRUE); }
void FreeIniCompGroup( PINI_COMP_GROUP pIniCompGrp ) { if (pIniCompGrp->szDomainName) {
FreeADsStr(pIniCompGrp->szDomainName); }
if (pIniCompGrp->szComputerName) {
FreeADsStr(pIniCompGrp->szComputerName); }
if (pIniCompGrp->szGroupName) {
FreeADsStr(pIniCompGrp->szGroupName); }
if (pIniCompGrp->szUncCompName) {
FreeADsStr(pIniCompGrp->szUncCompName); }
if (pIniCompGrp->_pBuffer) {
NetApiBufferFree(pIniCompGrp->_pBuffer); }
if (pIniCompGrp) {
FreeADsMem(pIniCompGrp); }
return; }
void FreeIntCompGroup( LPCOMPUTER_GROUP_MEMBER pCompGroupMember ) { if (pCompGroupMember->Parent) {
FreeADsMem(pCompGroupMember->Parent);
}
if (pCompGroupMember->Computer) {
FreeADsStr(pCompGroupMember->Computer); }
if (pCompGroupMember->Domain) {
FreeADsStr(pCompGroupMember->Domain);
}
if (pCompGroupMember->Name) {
FreeADsStr(pCompGroupMember->Name); }
if (pCompGroupMember->Sid) {
FreeADsMem(pCompGroupMember->Sid); }
FreeADsMem(pCompGroupMember);
}
BOOL ComputeLocalGroupDataSize( LPCOMPUTER_GROUP_MEMBER * ppGroupMembers, DWORD dwReturned, PDWORD pdwSize ) {
DWORD i = 0; DWORD cb = 0; LPCOMPUTER_GROUP_MEMBER pMember = NULL;
for (i = 0; i < dwReturned; i++) {
pMember = *(ppGroupMembers + i);
cb += sizeof(COMPUTER_GROUP_MEMBER);
if (pMember->Parent) { cb += wcslen(pMember->Parent)*sizeof(WCHAR) + sizeof(WCHAR); }
if (pMember->Computer) { cb += wcslen(pMember->Computer)*sizeof(WCHAR) + sizeof(WCHAR); }
if (pMember->Domain) { cb += wcslen(pMember->Domain)*sizeof(WCHAR) + sizeof(WCHAR); }
if (pMember->Name) { cb += wcslen(pMember->Name)*sizeof(WCHAR) + sizeof(WCHAR); }
if (pMember->Sid) { cb += GetLengthSid(pMember->Sid); } }
*pdwSize = cb; return(TRUE); }
LPBYTE CopyIniCompGroupToCompGroup( LPCOMPUTER_GROUP_MEMBER pIntCompGrp, LPBYTE pExtCompGrp, LPBYTE pEnd ) { LPWSTR SourceStrings[sizeof(COMPUTER_GROUP_MEMBER)/sizeof(LPWSTR)]; LPWSTR *pSourceStrings=SourceStrings; LPCOMPUTER_GROUP_MEMBER pCompGrpMember = (LPCOMPUTER_GROUP_MEMBER)pExtCompGrp; DWORD dwSidLength = 0;
memset(SourceStrings, 0, sizeof(COMPUTER_GROUP_MEMBER)); *pSourceStrings++ = pIntCompGrp->Parent; *pSourceStrings++ = pIntCompGrp->Computer; *pSourceStrings++ = pIntCompGrp->Domain; *pSourceStrings++ = pIntCompGrp->Name;
pEnd = PackStrings( SourceStrings, pExtCompGrp, ComputerGrpMemberStrings, pEnd );
pCompGrpMember->Type = pIntCompGrp->Type; pCompGrpMember->ParentType = pIntCompGrp->ParentType;
if (pIntCompGrp->Sid) { dwSidLength = GetLengthSid(pIntCompGrp->Sid);
pEnd -= dwSidLength;
memcpy(pEnd, pIntCompGrp->Sid, dwSidLength ); pCompGrpMember->Sid = pEnd; }
return pEnd; }
BOOL BuildLocalGroupMember( HANDLE hGroup, LPBYTE lpBuffer, LPCOMPUTER_GROUP_MEMBER * ppGroupMember ) { LPINI_COMP_GROUP pGroup = (LPINI_COMP_GROUP)hGroup; LPCOMPUTER_GROUP_MEMBER pGroupMember = NULL; LPLOCALGROUP_MEMBERS_INFO_2 pGrpMem = (LPLOCALGROUP_MEMBERS_INFO_2)lpBuffer; WCHAR szADsParent[MAX_PATH]; LPWSTR pMemberName = NULL; LPWSTR pszSIDName = NULL; DWORD cblen = 0, dwLen = 0, dwLenDomAndName = 0; DWORD dwSidType = 0; DWORD dwSidLength = 0; BOOL fRet = FALSE; BOOL fError = FALSE;
pGroupMember = (LPCOMPUTER_GROUP_MEMBER)AllocADsMem( sizeof(COMPUTER_GROUP_MEMBER) ); if (!pGroupMember) {
goto error; }
dwSidType = pGrpMem->lgrmi2_sidusage;
pMemberName = wcschr(pGrpMem->lgrmi2_domainandname, L'\\');
cblen = wcslen(pGroup->szComputerName);
//
// Check to see if the lengthe of the domain name component in
// lgrmi2_domainandname and the comptuername are the same if not
// it cannot be a computer member object. We do this to catch the case
// where foo.foodom is computer name. foodom\user will incorrectly
// be identified as a local user rather than domain user
//
if (pMemberName) { *pMemberName = L'\0'; dwLenDomAndName = wcslen(pGrpMem->lgrmi2_domainandname); *pMemberName = L'\\'; } else { dwLenDomAndName = cblen; }
if ((dwLenDomAndName == cblen) && !_wcsnicmp(pGroup->szComputerName, pGrpMem->lgrmi2_domainandname, cblen)) {
//
// This is the local user case
//
if (pMemberName) {
pMemberName++; } else {
pMemberName = pGrpMem->lgrmi2_domainandname ; }
pGroupMember->Name = AllocADsStr(pMemberName); pGroupMember->Computer = AllocADsStr(pGroup->szComputerName); pGroupMember->Domain = AllocADsStr(pGroup->szDomainName);
if (pGroupMember->Domain != NULL) {
wsprintf( szADsParent, L"%s://%s/%s", szProviderName, pGroup->szDomainName, pGroup->szComputerName );
} else {
// Again we may have a null domain name for the case
// where there are no workstations services
wsprintf( szADsParent, L"%s://%s", szProviderName, pGroup->szComputerName ); }
pGroupMember->Parent = AllocADsStr(szADsParent); pGroupMember->ParentType = WINNT_COMPUTER_ID; //
// Need to look at SID to see if this is a local group
// in which case the sid will be alias.
//
if (dwSidType == SidTypeAlias) { pGroupMember->Type = WINNT_LOCALGROUP_ID; } else if (dwSidType == SidTypeUser) { pGroupMember->Type = WINNT_USER_ID; } else { //
// Unknown ??
//
SetLastError(ERROR_INVALID_SID); BAIL_ON_FAILURE(E_FAIL);
}
}else {
//
// This is the domain user, domain group case
//
pMemberName = wcschr(pGrpMem->lgrmi2_domainandname, L'\\');
if (pMemberName) {
*pMemberName = L'\0'; pMemberName++; pGroupMember->Domain = AllocADsStr(pGrpMem->lgrmi2_domainandname); pGroupMember->Computer = NULL;
wsprintf( szADsParent, L"%s://%s", szProviderName, pGrpMem->lgrmi2_domainandname ); } else {
//
// if name is well name like 'EveryOne' without the domain prefix,
// we end up with using the local computer name
//
pMemberName = pGrpMem->lgrmi2_domainandname ; pGroupMember->Domain = NULL; pGroupMember->Computer = AllocADsStr(L"") ;
wsprintf( szADsParent, L"WinNT:" ); }
pGroupMember->Name = AllocADsStr(pMemberName);
pGroupMember->Parent = AllocADsStr(szADsParent);
switch (dwSidType) { case SidTypeUser: pGroupMember->Type = WINNT_USER_ID; break;
case SidTypeGroup: case SidTypeWellKnownGroup : case SidTypeAlias : pGroupMember->Type = WINNT_GROUP_ID; break;
case SidTypeUnknown: case SidTypeDeletedAccount:
#if !defined(WIN95)
//
// In this case we want to use the stringized SID.
// We use functions in sddl.h.
//
fRet = ConvertSidToStringSidWrapper( pGrpMem->lgrmi2_sid, &pszSIDName );
if (!fRet || !pszSIDName) { //
// Not much we can do here
//
SetLastError(ERROR_INVALID_SID); fError = TRUE; } else { //
// We are always going to return just the SID.
//
if (pGroupMember->Name) { FreeADsStr(pGroupMember->Name); pGroupMember->Name = NULL; }
if (pGroupMember->Parent) { FreeADsStr(pGroupMember->Parent); pGroupMember->Parent = NULL; }
if (pGroupMember->Domain) { FreeADsStr(pGroupMember->Domain); pGroupMember->Domain = NULL; }
//
// Got be either user so default to user.
//
pGroupMember->Type = WINNT_USER_ID;
pGroupMember->Name = AllocADsStr(pszSIDName); pGroupMember->Parent = AllocADsStr(L"WinNT:"); if (!pGroupMember->Name || ! pGroupMember->Parent) { //
// Not enough mem - rather than ignore like we do
// in the rest of the places in this fn, will
// set the last error and hope we recover.
//
SetLastError(ERROR_INVALID_SID); fError = TRUE; } } #else
SetLastError(ERROR_INVALID_SID); fError = TRUE; #endif
if (pszSIDName) { LocalFree(pszSIDName); } if (fError) goto error; break;
default: SetLastError(ERROR_INVALID_SID); goto error; break;
}
//
// Need to special case this as we cannot have a domain
// name that is NULL.
//
if (dwSidType == SidTypeDeletedAccount || dwSidType == SidTypeUnknown) { pGroupMember->ParentType = WINNT_COMPUTER_ID; } else { pGroupMember->ParentType = WINNT_DOMAIN_ID; }
}
//
// Copy the SID
//
if (pGrpMem->lgrmi2_sid) {
//
// On NT4 for some reason GetLengthSID does not set lasterror to 0
//
SetLastError(NO_ERROR);
dwSidLength = GetLengthSid(pGrpMem->lgrmi2_sid);
//
// This is an extra check to make sure that we have the
// correct length.
//
if (GetLastError() != NO_ERROR) { SetLastError(ERROR_INVALID_SID); BAIL_ON_FAILURE(E_FAIL); }
pGroupMember->Sid = AllocADsMem(dwSidLength); if (!pGroupMember->Sid) { SetLastError(ERROR_OUTOFMEMORY); BAIL_ON_FAILURE(E_OUTOFMEMORY); }
memcpy(pGroupMember->Sid, pGrpMem->lgrmi2_sid, dwSidLength); }
*ppGroupMember = pGroupMember; return(TRUE);
error:
if (pGroupMember) {
FreeIntCompGroup(pGroupMember); }
*ppGroupMember = NULL; return(FALSE);
}
LPBYTE PackStrings( LPWSTR *pSource, LPBYTE pDest, DWORD *DestOffsets, LPBYTE pEnd ) { DWORD cbStr; WORD_ALIGN_DOWN(pEnd);
while (*DestOffsets != -1) { if (*pSource) { cbStr = wcslen(*pSource)*sizeof(WCHAR) + sizeof(WCHAR); pEnd -= cbStr; CopyMemory( pEnd, *pSource, cbStr); *(LPWSTR *)(pDest+*DestOffsets) = (LPWSTR)pEnd; } else { *(LPWSTR *)(pDest+*DestOffsets)=0; } pSource++; DestOffsets++; } return pEnd; }
|