829 lines
19 KiB
C++
829 lines
19 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|