535 lines
12 KiB
C++
535 lines
12 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
|
//
|
|
// File: usrutils.cxx
|
|
//
|
|
// Contents: NetWare compatible UserCollection Enumeration Code
|
|
//
|
|
// History: 22-Mar-96 t-ptam (PatrickT) migrated from KrishnaG for NetWare
|
|
//----------------------------------------------------------------------------
|
|
#include "nwcompat.hxx"
|
|
#pragma hdrstop
|
|
|
|
USER_GROUP_ENTRY UserGroupEntry;
|
|
|
|
//
|
|
// This assumes that addr is an LPBYTE type.
|
|
//
|
|
|
|
#define WORD_ALIGN_DOWN(addr) \
|
|
addr = ((LPBYTE)((DWORD)addr & ~1))
|
|
|
|
DWORD UserGrpEntryStrings[]=
|
|
{
|
|
FIELD_OFFSET(USER_GROUP_ENTRY, Parent),
|
|
FIELD_OFFSET(USER_GROUP_ENTRY, Computer),
|
|
FIELD_OFFSET(USER_GROUP_ENTRY, Name),
|
|
0xFFFFFFFF
|
|
};
|
|
|
|
DECLARE_INFOLEVEL(UsrUt)
|
|
DECLARE_DEBUG(UsrUt)
|
|
#define UsrUtDebugOut(x) UsrUtInlineDebugOut x
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: NWCOMPATComputerUserOpen
|
|
//
|
|
// Synopsis: This function opens a handle to a INI_COMP_USER structure.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
NWCOMPATComputerUserOpen(
|
|
LPWSTR szComputerName,
|
|
LPWSTR szGroupName,
|
|
PHANDLE phUser
|
|
)
|
|
{
|
|
WCHAR szTempBuffer[MAX_PATH];
|
|
PINI_COMP_USER pIniCompUsr;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!phUser) {
|
|
return(FALSE);
|
|
}
|
|
|
|
pIniCompUsr = (PINI_COMP_USER)AllocADsMem(
|
|
sizeof(INI_COMP_USER)
|
|
);
|
|
if (!pIniCompUsr) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Fill structure's fields.
|
|
//
|
|
|
|
if (!(pIniCompUsr->szComputerName = AllocADsStr(szComputerName))){
|
|
goto error;
|
|
}
|
|
|
|
if (!(pIniCompUsr->szGroupName = AllocADsStr(szGroupName))){
|
|
goto error;
|
|
}
|
|
|
|
hr = NWApiGetBinderyHandle(
|
|
&pIniCompUsr->_hConn,
|
|
szComputerName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Return
|
|
//
|
|
|
|
*phUser = (HANDLE)pIniCompUsr;
|
|
|
|
return(TRUE);
|
|
|
|
|
|
error:
|
|
if (pIniCompUsr) {
|
|
FreeIniCompUser(pIniCompUsr);
|
|
}
|
|
|
|
*phUser = NULL;
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: NWCOMPATComputerUserEnum
|
|
//
|
|
// Synopsis: This function returns a buffer which contains all the binding
|
|
// informations for the requested number of objects without any
|
|
// references.
|
|
// It returns TRUE iff dwReturned = dwRequested.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
NWCOMPATComputerUserEnum(
|
|
HANDLE hUser,
|
|
DWORD dwRequested,
|
|
LPBYTE * ppBuffer,
|
|
PDWORD pdwReturned
|
|
)
|
|
{
|
|
LPUSER_GROUP_ENTRY * ppUserMembers = NULL;
|
|
DWORD i = 0;
|
|
BOOL dwRet = FALSE;
|
|
DWORD dwReturned = 0;
|
|
DWORD dwSize = 0;
|
|
LPUSER_GROUP_ENTRY pBuffer = NULL;
|
|
LPBYTE pEnd = NULL;
|
|
|
|
//
|
|
// Allocate buffer for the number of requested members.
|
|
//
|
|
|
|
ppUserMembers = (LPUSER_GROUP_ENTRY *)AllocADsMem(
|
|
sizeof(LPUSER_GROUP_ENTRY)* dwRequested
|
|
);
|
|
if (!ppUserMembers) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Fill in ppUserMembers one by one.
|
|
//
|
|
|
|
for (i = 0; i < dwRequested; i++) {
|
|
|
|
dwRet = NWCOMPATComputerUserGetObject(
|
|
hUser,
|
|
&ppUserMembers[i]
|
|
);
|
|
if (!dwRet) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwRet) {
|
|
dwReturned = i;
|
|
|
|
//
|
|
// Determine actual size of ppUserMembers[], ie. since each string in
|
|
// USER_GROUP_ENTRY have a different length, a buffer that is going
|
|
// to contain all the data without any references is unknown.
|
|
//
|
|
|
|
dwRet = ComputeComputerUserDataSize(
|
|
ppUserMembers,
|
|
dwReturned,
|
|
&dwSize
|
|
);
|
|
|
|
pBuffer = (LPUSER_GROUP_ENTRY)AllocADsMem(
|
|
dwSize
|
|
);
|
|
if (!pBuffer) {
|
|
goto error;
|
|
}
|
|
|
|
pEnd = (LPBYTE)((LPBYTE)(pBuffer) + dwSize);
|
|
|
|
//
|
|
// Put data into pBuffer, starting from the end.
|
|
//
|
|
|
|
for (i = 0; i < dwReturned; i++) {
|
|
|
|
pEnd = CopyIniCompUserToCompUser(
|
|
ppUserMembers[i],
|
|
(LPBYTE)(pBuffer + i),
|
|
pEnd
|
|
);
|
|
}
|
|
|
|
//
|
|
// Clean up.
|
|
//
|
|
|
|
for (i = 0; i < dwReturned; i++ ) {
|
|
FreeIntCompUser(*(ppUserMembers + i));
|
|
}
|
|
|
|
//
|
|
// Return values.
|
|
//
|
|
|
|
*ppBuffer = (LPBYTE)pBuffer;
|
|
*pdwReturned = dwReturned;
|
|
}
|
|
|
|
FreeADsMem(ppUserMembers);
|
|
|
|
if (dwReturned == dwRequested){
|
|
return(TRUE);
|
|
}else {
|
|
return(FALSE);
|
|
}
|
|
|
|
error:
|
|
|
|
for (i = 0; i < dwReturned; i++ ) {
|
|
FreeIntCompUser(*(ppUserMembers + i));
|
|
}
|
|
|
|
FreeADsMem(ppUserMembers);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: NWCOMPATComputerUserGetObject
|
|
//
|
|
// Synopsis: This function returns binding information of a user (group member)
|
|
// object one by one. In its first call, it builds a buffer that
|
|
// contains all the UserID of the group members. Then, and in
|
|
// subsequent calls, this UserID is translated into a user name.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
NWCOMPATComputerUserGetObject(
|
|
HANDLE hUser,
|
|
LPUSER_GROUP_ENTRY * ppUserMember
|
|
)
|
|
{
|
|
BOOL dwRet = FALSE;
|
|
DWORD dwGroupId = 0;
|
|
HRESULT hr = S_OK;
|
|
PINI_COMP_USER pIniCompUsr = (PINI_COMP_USER)hUser;
|
|
|
|
//
|
|
// Fill buffer with User ID. NetWare returns all UserID in one call.
|
|
//
|
|
|
|
if (!pIniCompUsr->_pBuffer) {
|
|
|
|
pIniCompUsr->_dwCurrentObject = 0;
|
|
|
|
hr = NWApiUserGetGroups(
|
|
pIniCompUsr->_hConn,
|
|
pIniCompUsr->szGroupName,
|
|
&(pIniCompUsr->_pBuffer)
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// Build one group member.
|
|
//
|
|
|
|
dwGroupId = *((LPDWORD)pIniCompUsr->_pBuffer + pIniCompUsr->_dwCurrentObject);
|
|
|
|
if (dwGroupId != 0x0000) {
|
|
|
|
dwRet = BuildComputerUserMember(
|
|
hUser,
|
|
dwGroupId,
|
|
ppUserMember
|
|
);
|
|
if (!dwRet) {
|
|
goto error;
|
|
}
|
|
|
|
pIniCompUsr->_dwCurrentObject++;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
error:
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: NWCOMPATComputerUserClose
|
|
//
|
|
// Synopsis: Wrapper of FreeIniCompUser.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
NWCOMPATComputerUserClose(
|
|
HANDLE hUser
|
|
)
|
|
{
|
|
PINI_COMP_USER pIniCompUsr = (PINI_COMP_USER)hUser;
|
|
|
|
if (pIniCompUsr) {
|
|
FreeIniCompUser(pIniCompUsr);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeIniCompUser
|
|
//
|
|
// Synopsis: Free an INI_COMP_USER structure.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
FreeIniCompUser(
|
|
PINI_COMP_USER pIniCompUsr
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pIniCompUsr) {
|
|
|
|
if (pIniCompUsr->szComputerName) {
|
|
FreeADsStr(pIniCompUsr->szComputerName);
|
|
}
|
|
|
|
if (pIniCompUsr->szGroupName) {
|
|
FreeADsStr(pIniCompUsr->szGroupName);
|
|
}
|
|
|
|
if (pIniCompUsr->_pBuffer) {
|
|
FreeADsMem(pIniCompUsr->_pBuffer);
|
|
}
|
|
|
|
if (pIniCompUsr->_hConn) {
|
|
hr = NWApiReleaseBinderyHandle(pIniCompUsr->_hConn);
|
|
}
|
|
|
|
FreeADsMem(pIniCompUsr);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeIntCompUser
|
|
//
|
|
// Synopsis: Free a USER_GROUP_ENTRY structure.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
FreeIntCompUser(
|
|
LPUSER_GROUP_ENTRY pCompUserMember
|
|
)
|
|
{
|
|
if (pCompUserMember) {
|
|
|
|
if (pCompUserMember->Parent) {
|
|
FreeADsStr(pCompUserMember->Parent);
|
|
}
|
|
|
|
if (pCompUserMember->Computer) {
|
|
FreeADsStr(pCompUserMember->Computer);
|
|
}
|
|
|
|
if (pCompUserMember->Name) {
|
|
FreeADsStr(pCompUserMember->Name);
|
|
}
|
|
|
|
FreeADsMem(pCompUserMember);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: ComputeComputerUserDataSize
|
|
//
|
|
// Synopsis: Calculate the size of a buffer that is going to store the data in
|
|
// ppUserMembers without any references.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
ComputeComputerUserDataSize(
|
|
LPUSER_GROUP_ENTRY * ppUserMembers,
|
|
DWORD dwReturned,
|
|
PDWORD pdwSize
|
|
)
|
|
{
|
|
|
|
DWORD i = 0;
|
|
DWORD cb = 0;
|
|
LPUSER_GROUP_ENTRY pMember = NULL;
|
|
|
|
for (i = 0; i < dwReturned; i++) {
|
|
|
|
pMember = *(ppUserMembers + i);
|
|
|
|
cb += sizeof(USER_GROUP_ENTRY);
|
|
|
|
if (pMember->Parent) {
|
|
cb += wcslen(pMember->Parent)*sizeof(WCHAR) + sizeof(WCHAR);
|
|
}
|
|
|
|
if (pMember->Computer) {
|
|
cb += wcslen(pMember->Computer)*sizeof(WCHAR) + sizeof(WCHAR);
|
|
}
|
|
|
|
if (pMember->Name) {
|
|
cb += wcslen(pMember->Name)*sizeof(WCHAR) + sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
*pdwSize = cb;
|
|
return(TRUE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyIniCompUserToCompUser
|
|
//
|
|
// Synopsis: Pack referenced data (string) into a buffer without any reference.
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
LPBYTE
|
|
CopyIniCompUserToCompUser(
|
|
LPUSER_GROUP_ENTRY pIntCompGrp,
|
|
LPBYTE pExtCompGrp,
|
|
LPBYTE pEnd
|
|
)
|
|
{
|
|
LPWSTR SourceStrings[sizeof(USER_GROUP_ENTRY)/sizeof(LPWSTR)];
|
|
LPWSTR *pSourceStrings = SourceStrings;
|
|
LPUSER_GROUP_ENTRY pCompGrpMember = (LPUSER_GROUP_ENTRY)pExtCompGrp;
|
|
|
|
memset(SourceStrings, 0, sizeof(USER_GROUP_ENTRY));
|
|
*pSourceStrings++ = pIntCompGrp->Parent;
|
|
*pSourceStrings++ = pIntCompGrp->Computer;
|
|
*pSourceStrings++ = pIntCompGrp->Name;
|
|
|
|
pEnd = PackStrings(
|
|
SourceStrings,
|
|
pExtCompGrp,
|
|
UserGrpEntryStrings,
|
|
pEnd
|
|
);
|
|
|
|
pCompGrpMember->Type = pIntCompGrp->Type;
|
|
|
|
return pEnd;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: BuildComputerUserMember
|
|
//
|
|
// Synopsis: Put binding information of a group member into ppUserMember.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
BuildComputerUserMember(
|
|
HANDLE hUser,
|
|
DWORD dwGroupId,
|
|
LPUSER_GROUP_ENTRY * ppUserMember
|
|
)
|
|
{
|
|
DWORD dwTempUserId = dwGroupId;
|
|
HRESULT hr = S_OK;
|
|
LPUSER_GROUP_ENTRY pUserMember = NULL;
|
|
LPINI_COMP_USER pUser = (LPINI_COMP_USER)hUser;
|
|
WCHAR szADsParent[MAX_PATH];
|
|
|
|
//
|
|
// Allocate one USER_GROUP_ENTRY.
|
|
//
|
|
|
|
pUserMember = (LPUSER_GROUP_ENTRY)AllocADsMem(
|
|
sizeof(USER_GROUP_ENTRY)
|
|
);
|
|
if (!pUserMember) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Fill structure's fields.
|
|
//
|
|
|
|
pUserMember->Type = NWCOMPAT_USER_ID;
|
|
|
|
wsprintf(
|
|
szADsParent,
|
|
L"%s://%s",
|
|
szProviderName,
|
|
pUser->szComputerName
|
|
);
|
|
pUserMember->Parent = AllocADsStr(szADsParent);
|
|
|
|
pUserMember->Computer = AllocADsStr(pUser->szComputerName);
|
|
|
|
hr = NWApiGetObjectName(
|
|
pUser->_hConn,
|
|
dwTempUserId,
|
|
&pUserMember->Name
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Return.
|
|
//
|
|
|
|
*ppUserMember = pUserMember;
|
|
return(TRUE);
|
|
|
|
error:
|
|
|
|
if (pUserMember) {
|
|
|
|
if (pUserMember->Parent)
|
|
FreeADsStr(pUserMember->Parent);
|
|
|
|
if (pUserMember->Computer)
|
|
FreeADsStr(pUserMember->Computer);
|
|
|
|
FreeADsMem(pUserMember);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|