/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * net_localgroupenum.c * * Abstract: * * Remote Procedure Call (RPC) Client Interface * * NetLocalGroupEnum function * * Authors: Rafal Szczesniak (rafal@likewise.com) */ #include "includes.h" NET_API_STATUS NetLocalGroupEnum( PCWSTR pwszHostname, DWORD dwLevel, PVOID *ppBuffer, DWORD dwMaxBufferSize, PDWORD pdwNumEntries, PDWORD pdwTotalNumEntries, PDWORD pdwResume ) { const DWORD dwAccountFlags = 0; const DWORD dwAliasAccessFlags = ALIAS_ACCESS_LOOKUP_INFO; const WORD wInfoLevel = ALIAS_INFO_ALL; NTSTATUS status = STATUS_SUCCESS; WINERR err = ERROR_SUCCESS; DWORD dwResume = 0; NetConn *pConn = NULL; handle_t hSamrBinding = NULL; DOMAIN_HANDLE hDomain = NULL; DOMAIN_HANDLE hBtinDomain = NULL; DWORD dwSamrResume = 0; PWSTR *ppwszDomainAliases = NULL; PDWORD pdwDomainRids = NULL; DWORD dwNumDomainEntries = 0; DWORD dwTotalNumDomainEntries = 0; PWSTR *ppwszBtinDomainAliases = NULL; PDWORD pdwBtinDomainRids = NULL; DWORD dwNumBtinDomainEntries = 0; DWORD dwTotalNumBtinDomainEntries = 0; DWORD dwTotalNumEntries = 0; DWORD dwNumEntries = 0; DWORD i = 0; PDWORD pdwRids = NULL; PWSTR *ppwszAliases = NULL; ACCOUNT_HANDLE hAlias = NULL; AliasInfo *pSamrAliasInfo = NULL; AliasInfoAll **ppAliasInfo = NULL; DWORD dwInfoLevelSize = 0; PVOID pSourceBuffer = NULL; DWORD dwSize = 0; DWORD dwTotalSize = 0; DWORD dwSpaceAvailable = 0; PVOID pBuffer = NULL; PVOID pBufferCursor = NULL; PIO_CREDS pCreds = NULL; BAIL_ON_INVALID_PTR(ppBuffer); BAIL_ON_INVALID_PTR(pdwNumEntries); BAIL_ON_INVALID_PTR(pdwTotalNumEntries); BAIL_ON_INVALID_PTR(pdwResume); switch (dwLevel) { case 0: dwInfoLevelSize = sizeof(LOCALGROUP_INFO_0); break; case 1: dwInfoLevelSize = sizeof(LOCALGROUP_INFO_1); break; default: err = ERROR_INVALID_LEVEL; BAIL_ON_WINERR_ERROR(err); } dwResume = *pdwResume; status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NTSTATUS_ERROR(status); status = NetConnectSamr(&pConn, pwszHostname, 0, 0, pCreds); BAIL_ON_NTSTATUS_ERROR(status); hSamrBinding = pConn->samr.bind; hDomain = pConn->samr.hDomain; hBtinDomain = pConn->samr.hBtinDomain; do { status = SamrEnumDomainAliases(hSamrBinding, hDomain, &dwSamrResume, dwAccountFlags, &ppwszDomainAliases, &pdwDomainRids, &dwNumDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NTSTATUS_ERROR(status); } if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); ppwszDomainAliases = NULL; } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); pdwDomainRids = NULL; } dwTotalNumDomainEntries += dwNumDomainEntries; dwNumDomainEntries = 0; } while (status == STATUS_MORE_ENTRIES); dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hBtinDomain, &dwSamrResume, dwAccountFlags, &ppwszBtinDomainAliases, &pdwBtinDomainRids, &dwNumBtinDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NTSTATUS_ERROR(status); } if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); ppwszBtinDomainAliases = NULL; } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); pdwBtinDomainRids = NULL; } dwTotalNumBtinDomainEntries += dwNumBtinDomainEntries; dwNumBtinDomainEntries = 0; } while (status == STATUS_MORE_ENTRIES); dwTotalNumEntries = dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries; status = NetAllocateMemory((void**)&pdwRids, sizeof(pdwRids[0]) * dwTotalNumEntries, NULL); BAIL_ON_NTSTATUS_ERROR(status); status = NetAllocateMemory((void**)&ppwszAliases, sizeof(ppwszAliases[0]) * dwTotalNumEntries, NULL); BAIL_ON_NTSTATUS_ERROR(status); status = NetAllocateMemory((void**)&ppAliasInfo, sizeof(ppAliasInfo[0]) * dwTotalNumEntries, NULL); BAIL_ON_NTSTATUS_ERROR(status); dwTotalNumDomainEntries = 0; dwTotalNumBtinDomainEntries = 0; dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hDomain, &dwSamrResume, dwAccountFlags, &ppwszDomainAliases, &pdwDomainRids, &dwNumDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NTSTATUS_ERROR(status); } for (i = 0; i < dwNumDomainEntries; i++) { err = LwAllocateWc16String(&ppwszAliases[dwTotalNumDomainEntries + i], ppwszDomainAliases[i]); BAIL_ON_WINERR_ERROR(err); pdwRids[dwTotalNumDomainEntries + i] = pdwDomainRids[i]; } dwTotalNumDomainEntries += dwNumDomainEntries; dwNumDomainEntries = 0; if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); ppwszDomainAliases = NULL; } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); pdwDomainRids = NULL; } } while (status == STATUS_MORE_ENTRIES); dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hBtinDomain, &dwSamrResume, dwAccountFlags, &ppwszBtinDomainAliases, &pdwBtinDomainRids, &dwNumBtinDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NTSTATUS_ERROR(status); } for (i = 0; i < dwNumBtinDomainEntries; i++) { err = LwAllocateWc16String(&ppwszAliases[dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries + i], ppwszBtinDomainAliases[i]); BAIL_ON_WINERR_ERROR(err); pdwRids[dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries + i] = pdwBtinDomainRids[i]; } dwTotalNumBtinDomainEntries += dwNumBtinDomainEntries; dwNumBtinDomainEntries = 0; if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); ppwszBtinDomainAliases = NULL; } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); pdwBtinDomainRids = NULL; } } while (status == STATUS_MORE_ENTRIES); for (i = dwResume; i < dwTotalNumEntries; i++) { if (dwLevel == 0) { pSourceBuffer = ppwszAliases[i]; } else { DOMAIN_HANDLE hDom = NULL; DWORD dwRid = 0; hDom = (i < dwTotalNumDomainEntries) ? hDomain : hBtinDomain; dwRid = pdwRids[i]; status = SamrOpenAlias(hSamrBinding, hDom, dwAliasAccessFlags, dwRid, &hAlias); BAIL_ON_NTSTATUS_ERROR(status); status = SamrQueryAliasInfo(hSamrBinding, hAlias, wInfoLevel, &pSamrAliasInfo); BAIL_ON_NTSTATUS_ERROR(status); ppAliasInfo[i - dwResume] = &pSamrAliasInfo->all; pSourceBuffer = &pSamrAliasInfo->all; status = SamrClose(hSamrBinding, hAlias); BAIL_ON_NTSTATUS_ERROR(status); } dwSize = 0; err = NetAllocateLocalGroupInfo(NULL, NULL, dwLevel, pSourceBuffer, &dwSize); BAIL_ON_WINERR_ERROR(err); dwTotalSize += dwSize; dwNumEntries++; if (dwTotalSize > dwMaxBufferSize) { dwTotalSize -= dwSize; dwNumEntries--; break; } } if (dwTotalNumEntries > 0 && dwNumEntries == 0) { err = ERROR_INSUFFICIENT_BUFFER; BAIL_ON_WINERR_ERROR(err); } if (dwTotalSize) { status = NetAllocateMemory((void**)&pBuffer, dwTotalSize, NULL); BAIL_ON_NTSTATUS_ERROR(status); } dwSize = 0; pBufferCursor = pBuffer; dwSpaceAvailable = dwTotalSize; for (i = 0; i < dwNumEntries; i++) { if (dwLevel == 0) { pSourceBuffer = ppwszAliases[dwResume + i]; } else { pSourceBuffer = ppAliasInfo[i]; } pBufferCursor = pBuffer + (i * dwInfoLevelSize); err = NetAllocateLocalGroupInfo(pBufferCursor, &dwSpaceAvailable, dwLevel, pSourceBuffer, &dwSize); BAIL_ON_WINERR_ERROR(err); } if (dwResume + dwNumEntries < dwTotalNumEntries) { err = ERROR_MORE_DATA; } *ppBuffer = pBuffer; *pdwNumEntries = dwNumEntries; *pdwTotalNumEntries = dwTotalNumEntries; *pdwResume = dwResume + dwNumEntries; cleanup: if (pdwRids) { NetFreeMemory(pdwRids); } if (ppwszAliases) { for (i = 0; i < dwTotalNumEntries; i++) { LW_SAFE_FREE_MEMORY(ppwszAliases[i]); } NetFreeMemory(ppwszAliases); } if (ppAliasInfo) { for (i = 0; i < dwNumEntries; i++) { if (ppAliasInfo[i]) { SamrFreeMemory((void*)ppAliasInfo[i]); } } NetFreeMemory(ppAliasInfo); } if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); } if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); } if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && status != STATUS_SUCCESS) { err = NtStatusToWin32Error(status); } return err; error: if (pBuffer) { NetFreeMemory(pBuffer); } *ppBuffer = NULL; *pdwNumEntries = 0; *pdwTotalNumEntries = 0; *pdwResume = 0; goto cleanup; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */