int
find_group_by_name_main(
    int argc,
    char* argv[]
    )
{
    DWORD dwError = 0;
    PSTR  pszGroupId = NULL;
    DWORD dwInfoLevel = 0;
    HANDLE hLsaConnection = (HANDLE)NULL;
    PVOID pGroupInfo = NULL;
    size_t dwErrorBufferSize = 0;
    BOOLEAN bPrintOrigError = TRUE;
    BOOLEAN bCountOnly = FALSE;
    LSA_FIND_FLAGS FindFlags = 0;

    dwError = ParseArgs(argc, argv, &pszGroupId, &FindFlags, &dwInfoLevel, &bCountOnly);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaOpenServer(&hLsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaFindGroupByName(
                    hLsaConnection,
                    pszGroupId,
                    FindFlags,
                    dwInfoLevel,
                    &pGroupInfo);
    BAIL_ON_LSA_ERROR(dwError);

    switch(dwInfoLevel)
    {
        case 0:
            PrintGroupInfo_0((PLSA_GROUP_INFO_0)pGroupInfo);
            break;
        case 1:
            PrintGroupInfo_1((PLSA_GROUP_INFO_1)pGroupInfo, bCountOnly);
            break;
        default:

            fprintf(stderr, "Error: Invalid group info level [%u]\n", dwInfoLevel);
            break;
    }

cleanup:

    if (pGroupInfo) {
       LsaFreeGroupInfo(dwInfoLevel, pGroupInfo);
    }

    if (hLsaConnection != (HANDLE)NULL) {
        LsaCloseServer(hLsaConnection);
    }

    LW_SAFE_FREE_STRING(pszGroupId);

    return (dwError);

error:

    dwError = MapErrorCode(dwError);

    dwErrorBufferSize = LwGetErrorString(dwError, NULL, 0);

    if (dwErrorBufferSize > 0)
    {
        DWORD dwError2 = 0;
        PSTR   pszErrorBuffer = NULL;

        dwError2 = LwAllocateMemory(
                    dwErrorBufferSize,
                    (PVOID*)&pszErrorBuffer);

        if (!dwError2)
        {
            DWORD dwLen = LwGetErrorString(dwError, pszErrorBuffer, dwErrorBufferSize);

            if ((dwLen == dwErrorBufferSize) && !LW_IS_NULL_OR_EMPTY_STR(pszErrorBuffer))
            {
                fprintf(stderr,
                        "Failed to locate group.  Error code %u (%s).\n%s\n",
                        dwError,
                        LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)),
                        pszErrorBuffer);
                bPrintOrigError = FALSE;
            }
        }

        LW_SAFE_FREE_STRING(pszErrorBuffer);
    }

    if (bPrintOrigError)
    {
        fprintf(stderr,
                "Failed to locate group.  Error code %u (%s).\n",
                dwError,
                LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)));
    }

    goto cleanup;
}
int
enum_groups_main(
    int argc,
    char* argv[]
    )
{
    DWORD dwError = 0;
    DWORD dwGroupInfoLevel = 0;
    DWORD dwBatchSize = 10;
    HANDLE hLsaConnection = (HANDLE)NULL;
    HANDLE hResume = (HANDLE)NULL;
    PVOID* ppGroupInfoList = NULL;
    DWORD  dwNumGroupsFound = 0;
    DWORD  dwTotalGroupsFound = 0;
    size_t dwErrorBufferSize = 0;
    BOOLEAN bPrintOrigError = FALSE;
    BOOLEAN bCheckGroupMembersOnline = FALSE;

    dwError = ParseArgs(argc, argv, &dwGroupInfoLevel, &dwBatchSize, &bCheckGroupMembersOnline);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaOpenServer(&hLsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaBeginEnumGroupsWithCheckOnlineOption(
                    hLsaConnection,
                    dwGroupInfoLevel,
                    dwBatchSize,
                    bCheckGroupMembersOnline,
                    0,
                    &hResume);
    BAIL_ON_LSA_ERROR(dwError);

    do
    {
        DWORD iGroup = 0;

        if (ppGroupInfoList) {
           LsaFreeGroupInfoList(dwGroupInfoLevel, ppGroupInfoList, dwNumGroupsFound);
           ppGroupInfoList = NULL;
        }

        dwError = LsaEnumGroups(
                    hLsaConnection,
                    hResume,
                    &dwNumGroupsFound,
                    &ppGroupInfoList);
        BAIL_ON_LSA_ERROR(dwError);

        if (!dwNumGroupsFound) {
            break;
        }

        dwTotalGroupsFound+=dwNumGroupsFound;

        for (iGroup = 0; iGroup < dwNumGroupsFound; iGroup++)
        {
            PVOID pGroupInfo = *(ppGroupInfoList + iGroup);

            switch(dwGroupInfoLevel)
            {
                case 0:
                    PrintGroupInfo_0((PLSA_GROUP_INFO_0)pGroupInfo);
                    break;
                case 1:
                    PrintGroupInfo_1((PLSA_GROUP_INFO_1)pGroupInfo);
                    break;
                default:

                    fprintf(stderr,
                            "Error: Invalid Group info level %u\n",
                            dwGroupInfoLevel);
                    break;
            }
        }
    } while (dwNumGroupsFound);

    fprintf(stdout, "TotalNumGroupsFound: %u\n", dwTotalGroupsFound);

cleanup:

    if (ppGroupInfoList) {
       LsaFreeGroupInfoList(dwGroupInfoLevel, ppGroupInfoList, dwNumGroupsFound);
    }

    if ((hResume != (HANDLE)NULL) &&
        (hLsaConnection != (HANDLE)NULL)) {
        LsaEndEnumGroups(hLsaConnection, hResume);
    }

    if (hLsaConnection != (HANDLE)NULL) {
        LsaCloseServer(hLsaConnection);
    }

    return (dwError);

error:

    dwError = MapErrorCode(dwError);

    dwErrorBufferSize = LwGetErrorString(dwError, NULL, 0);

    if (dwErrorBufferSize > 0)
    {
        DWORD dwError2 = 0;
        PSTR   pszErrorBuffer = NULL;

        dwError2 = LwAllocateMemory(
                    dwErrorBufferSize,
                    (PVOID*)&pszErrorBuffer);

        if (!dwError2)
        {
            DWORD dwLen = LwGetErrorString(dwError, pszErrorBuffer, dwErrorBufferSize);

            if ((dwLen == dwErrorBufferSize) && !LW_IS_NULL_OR_EMPTY_STR(pszErrorBuffer))
            {
                fprintf(stderr, "Failed to enumerate groups.  Error code %u (%s).\n"
                        "%s\n",
                        dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)),
                        pszErrorBuffer);
                bPrintOrigError = FALSE;
            }

            if (dwError == ERROR_INVALID_DATA)
            {
                fprintf(stderr, "The groups list has changed while enumerating. "
                        "Try again.\n");
            }
        }

        LW_SAFE_FREE_STRING(pszErrorBuffer);
    }

    if (bPrintOrigError)
    {
        fprintf(stderr, "Failed to enumerate groups.  Error code %u (%s).\n",
                dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)));
    }

    goto cleanup;
}
DWORD
TestEnumGroups(
    HANDLE hLsaConnection,
    PSTR pszGroup
    )
{
    DWORD dwError = 0;
    DWORD dwGroupInfoLevel = 0;
    DWORD dwBatchSize = 10;
    HANDLE hLsaConnection = (HANDLE)NULL;
    HANDLE hResume = (HANDLE)NULL;
    PVOID* ppGroupInfoList = NULL;
    DWORD  dwNumGroupsFound = 0;
    DWORD  dwTotalGroupsFound = 0;
    size_t dwErrorBufferSize = 0;
    BOOLEAN bPrintOrigError = FALSE;
    BOOLEAN bCheckGroupMembersOnline = FALSE;

dwError = LsaBeginEnumGroupsWithCheckOnlineOption(
                    hLsaConnection,
                    dwGroupInfoLevel,
                    dwBatchSize,
                    bCheckGroupMembersOnline,
                    0,
                    &hResume);
    BAIL_ON_LSA_ERROR(dwError);

    do
    {
        DWORD iGroup = 0;

        if (ppGroupInfoList) {
            LsaFreeGroupInfoList(dwGroupInfoLevel, ppGroupInfoList, dwNumGroupsFound);
            ppGroupInfoList = NULL;
        }

        dwError = LsaEnumGroups(
                    hLsaConnection,
                    hResume,
                    &dwNumGroupsFound,
                    &ppGroupInfoList);
        BAIL_ON_LSA_ERROR(dwError);

        if (!dwNumGroupsFound) {
            break;
        }

        dwTotalGroupsFound+=dwNumGroupsFound;
        
        for (iGroup = 0; iGroup < dwNumGroupsFound; iGroup++)
        {
            PVOID pGroupInfo = *(ppGroupInfoList + iGroup);
       
            switch(dwGroupInfoLevel)
            {
                case 0:
                    PrintGroupInfo_0((PLSA_GROUP_INFO_0)pGroupInfo);
                    break;
                case 1:
                    PrintGroupInfo_1((PLSA_GROUP_INFO_1)pGroupInfo);
                    break;
                default:
                    break;
            }
        }
    } while (dwNumGroupsFound);
}