Example #1
0
static
DWORD
NetShareEnumParseArguments(
	int argc,
    char ** argv,
	IN OUT PNET_SHARE_COMMAND_INFO pCommandInfo
	)
{
	DWORD dwError = 0;

	if (!argv[3])
	{
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
	}

    dwError = LwMbsToWc16s(argv[3], &pCommandInfo->ShareEnumInfo.pwszServerName);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    return dwError;

error:

    NetShareFreeCommandInfo(pCommandInfo);

    goto cleanup;
}
Example #2
0
DWORD
NetExecFileQueryInfo(
    PCWSTR pwszServername,
    DWORD  dwFileId
    )
{
    NET_API_STATUS nStatus     = 0;
    DWORD          dwInfoLevel = 3;
    PBYTE          pBuffer     = NULL;
    PFILE_INFO_3   pFileInfo   = NULL;
    PSTR           pszPathname = NULL;
    PSTR           pszUsername = NULL;

    nStatus = NetFileGetInfoW(pwszServername, dwFileId, dwInfoLevel, &pBuffer);
    BAIL_ON_LTNET_ERROR(nStatus);

    pFileInfo = (PFILE_INFO_3)pBuffer;

    if (pFileInfo->fi3_path_name)
    {
        LW_SAFE_FREE_STRING(pszPathname);

        nStatus = LwWc16sToMbs(pFileInfo->fi3_path_name, &pszPathname);
        BAIL_ON_LTNET_ERROR(nStatus);
    }

    if (pFileInfo->fi3_username)
    {
        LW_SAFE_FREE_STRING(pszUsername);

        nStatus = LwWc16sToMbs(pFileInfo->fi3_username, &pszUsername);
        BAIL_ON_LTNET_ERROR(nStatus);
    }

    printf("\tId:              %u\n",     pFileInfo->fi3_idd);
    printf("\tPathname:        %s\n",     (pszPathname ? pszPathname : ""));
    printf("\tUsername:        %s\n",     (pszUsername ? pszUsername : ""));
    printf("\tNumber of locks: %u\n",     pFileInfo->fi3_num_locks);
    printf("\tPermissions:     0x%08x\n", pFileInfo->fi3_permissions);

cleanup:

    if (pBuffer)
    {
        NetApiBufferFree(pBuffer);
    }

    LW_SAFE_FREE_STRING(pszPathname);
    LW_SAFE_FREE_STRING(pszUsername);

    return nStatus;

error:

    fprintf(stderr, "Failed to get information on file [Id: %u].\n", dwFileId);

    goto cleanup;
}
Example #3
0
static
DWORD
MapSidToName(
    HANDLE hLsa,
    PSID pSid,
    PWSTR* ppwszName
    )
{
    DWORD dwError = 0;
    PSTR pszSid = NULL;
    LSA_QUERY_LIST QueryList;
    PLSA_SECURITY_OBJECT* ppObjects = NULL;

    dwError = LwNtStatusToWin32Error(
        RtlAllocateCStringFromSid(&pszSid, pSid));
    BAIL_ON_LTNET_ERROR(dwError);

    QueryList.ppszStrings = (PCSTR*) &pszSid;

    dwError = LsaFindObjects(
        hLsa,
        NULL,
        0,
        LSA_OBJECT_TYPE_UNDEFINED,
        LSA_QUERY_TYPE_BY_SID,
        1,
        QueryList,
        &ppObjects);
    BAIL_ON_LTNET_ERROR(dwError);

    if (ppObjects[0] == NULL)
    {
        dwError = LW_ERROR_NO_SUCH_OBJECT;
        BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwAllocateWc16sPrintfW(
        ppwszName,
        L"%s\\%s",
        ppObjects[0]->pszNetbiosDomainName,
        ppObjects[0]->pszSamAccountName);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    LsaFreeSecurityObjectList(1, ppObjects);

    LTNET_SAFE_FREE_STRING(pszSid);

    return dwError;

error:

    *ppwszName = NULL;

    goto cleanup;
}
Example #4
0
static
DWORD
NetShareSetinfoParseArguments(
    int argc,
    char ** argv,
    IN OUT PNET_SHARE_COMMAND_INFO pCommandInfo
    )
{
    DWORD dwError = 0;
    int indexShareSetInfoArg = 3;


    if (!argv[indexShareSetInfoArg])
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LTNET_ERROR(dwError);
    }

    if (!strncmp(argv[indexShareSetInfoArg], "\\\\", sizeof("\\\\")-1))
    {
        dwError = LwMbsToWc16s(argv[indexShareSetInfoArg]+sizeof("\\\\")-1,
                  &pCommandInfo->ShareAddOrSetInfo.pwszServerName);
        BAIL_ON_LTNET_ERROR(dwError);

        indexShareSetInfoArg++;
    }

    if (indexShareSetInfoArg > argc-1)
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwMbsToWc16s(argv[indexShareSetInfoArg],
            &pCommandInfo->ShareAddOrSetInfo.pwszShareName);
    BAIL_ON_LTNET_ERROR(dwError);

    // Process set-info options
    dwError = ParseShareAddOrSetinfoOptionArgs(argc, ++indexShareSetInfoArg, argv,
                                               pCommandInfo->dwControlCode,
                                               &pCommandInfo->ShareAddOrSetInfo);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    return dwError;

error:

    NetShareFreeCommandInfo(pCommandInfo);

    goto cleanup;

}
Example #5
0
static
DWORD
MapNameToSid(
    HANDLE hLsa,
    PCWSTR pwszName,
    PSID* ppSid
    )
{
    DWORD dwError = 0;
    PSTR pszName = NULL;
    LSA_QUERY_LIST QueryList;
    PLSA_SECURITY_OBJECT* ppObjects = NULL;

    dwError = LwWc16sToMbs(pwszName, &pszName);
    BAIL_ON_LTNET_ERROR(dwError);

    QueryList.ppszStrings = (PCSTR*) &pszName;

    dwError = LsaFindObjects(
        hLsa,
        NULL,
        0,
        LSA_OBJECT_TYPE_UNDEFINED,
        LSA_QUERY_TYPE_BY_NAME,
        1,
        QueryList,
        &ppObjects);
    BAIL_ON_LTNET_ERROR(dwError);

    if (ppObjects[0] == NULL)
    {
        dwError = LW_ERROR_NO_SUCH_OBJECT;
        BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwNetAllocateSidFromCString(ppSid, ppObjects[0]->pszObjectSid);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    LsaFreeSecurityObjectList(1, ppObjects);

    LTNET_SAFE_FREE_STRING(pszName);

    return dwError;

error:

    *ppSid = NULL;

    goto cleanup;
}
Example #6
0
DWORD
NetExecShareAdd(
    NET_SHARE_ADD_OR_SET_INFO_PARAMS ShareAddInfo
    )
{
    static const DWORD dwLevel = 502;

    DWORD dwError = 0;
    SHARE_INFO_502 shareInfo = {0};
    DWORD dwParmErr = 0;
    PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL;
    DWORD dwSecDescSize = 0;

    dwError = ConstructSecurityDescriptor(
    	ShareAddInfo.dwAllowUserCount,
    	ShareAddInfo.ppwszAllowUsers,
    	ShareAddInfo.dwDenyUserCount,
    	ShareAddInfo.ppwszDenyUsers,
    	ShareAddInfo.bReadOnly && !ShareAddInfo.bReadWrite,
        &pSecDesc,
        &dwSecDescSize);
    BAIL_ON_LTNET_ERROR(dwError);

    shareInfo.shi502_netname = ShareAddInfo.pwszShareName ? ShareAddInfo.pwszShareName : ShareAddInfo.pwszTarget;
    shareInfo.shi502_path = ShareAddInfo.pwszPath;

    shareInfo.shi502_type = 0; // SHARE_SERVICE_DISK_SHARE
    shareInfo.shi502_remark = ShareAddInfo.pwszComment;
    shareInfo.shi502_reserved = dwSecDescSize;
    shareInfo.shi502_security_descriptor = (PBYTE) pSecDesc;

    dwError = NetShareAddW(
    	ShareAddInfo.pwszServerName,
        dwLevel,
        (PBYTE)&shareInfo,
        &dwParmErr);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    LTNET_SAFE_FREE_MEMORY(pSecDesc);

    return dwError;

error:

    goto cleanup;
}
Example #7
0
static
DWORD
NetShareEnumParseArguments(
    int argc,
    char ** argv,
    IN OUT PNET_SHARE_COMMAND_INFO pCommandInfo
    )
{
    DWORD dwError = 0;

    if (!strncmp(argv[2], "\\\\", sizeof("\\\\")-1))
    {
        dwError = LwMbsToWc16s(argv[2]+sizeof("\\\\")-1,
                               &pCommandInfo->ShareEnumInfo.pwszServerName);
        BAIL_ON_LTNET_ERROR(dwError);
    }

cleanup:

    return dwError;

error:

    NetShareFreeCommandInfo(pCommandInfo);

    goto cleanup;
}
Example #8
0
static
DWORD
MapBuiltinSidToName(
    PWSTR *ppwszName,
    PSID pSid
    )
{
    DWORD dwError = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Sid;
    ULONG SidSize = sizeof(Sid.buffer);
    PWSTR pwszEveryone = NULL;

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinWorldSid,
            NULL,
            &Sid.sid,
            &SidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    if (RtlEqualSid(&Sid.sid, pSid))
    {
        dwError = LwNtStatusToWin32Error(
            RtlWC16StringAllocateFromCString(
                &pwszEveryone,
                "Everyone"));
        BAIL_ON_LTNET_ERROR(dwError);

    }

    *ppwszName = pwszEveryone;

cleanup:

    return dwError;

error:
    LwNetWC16StringFree(pwszEveryone);

    goto cleanup;
}
Example #9
0
static
DWORD
MapBuiltinNameToSid(
    PSID *ppSid,
    PCWSTR pwszName
    )
{
    DWORD dwError = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Sid;
    ULONG SidSize = sizeof(Sid.buffer);
    PWSTR pwszEveryone = NULL;

    dwError = LwNetWC16StringAllocateFromCString(
        &pwszEveryone,
        "Everyone");
    BAIL_ON_LTNET_ERROR(dwError);


    if (LwRtlWC16StringIsEqual(pwszName, pwszEveryone, FALSE))
    {
        dwError = LwNtStatusToWin32Error(
            RtlCreateWellKnownSid(
                WinWorldSid,
                NULL,
                &Sid.sid,
                &SidSize));
    }
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlDuplicateSid(ppSid, &Sid.sid));

cleanup:
    LwNetWC16StringFree(pwszEveryone);

    return dwError;

error:
    goto cleanup;
}
Example #10
0
DWORD
NetShare(
    int argc,
    char ** argv
    )
{
    DWORD dwError = 0;
    PNET_SHARE_COMMAND_INFO pCommandInfo = NULL;

    dwError = NetShareParseArguments(
                    argc,
                    argv,
                    &pCommandInfo
                    );
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = NetShareInitialize();
    BAIL_ON_LTNET_ERROR(dwError);

    switch (pCommandInfo->dwControlCode)
    {

        case NET_SHARE_ADD:

		dwError = NetExecShareAdd(pCommandInfo->ShareAddOrSetInfo);
		BAIL_ON_LTNET_ERROR(dwError);
		break;


        case NET_SHARE_DEL:
            dwError = NetExecShareDel(pCommandInfo->ShareDelInfo);
		BAIL_ON_LTNET_ERROR(dwError);
		break;

        case NET_SHARE_ENUM:

            dwError = NetExecShareEnum(pCommandInfo->ShareEnumInfo);
		BAIL_ON_LTNET_ERROR(dwError);
		break;

        case NET_SHARE_SETINFO:

            dwError = NetExecSetInfo(pCommandInfo->ShareAddOrSetInfo);
            BAIL_ON_LTNET_ERROR(dwError);
            break;

        default:
		break;
    }

cleanup:
    NetShareFreeCommandInfo(pCommandInfo);
    LTNET_SAFE_FREE_MEMORY(pCommandInfo);
    pCommandInfo = NULL;

    return dwError;

error:
    goto cleanup;
}
Example #11
0
DWORD
NetExecFileClose(
    PCWSTR pwszServername,
    DWORD  dwFileId
    )
{
    NET_API_STATUS nStatus = 0;

    nStatus = NetFileCloseW(pwszServername, dwFileId);
    BAIL_ON_LTNET_ERROR(nStatus);

cleanup:

    return nStatus;

error:

    fprintf(stderr, "Failed to close file [Id: %u].\n", dwFileId);

    goto cleanup;
}
Example #12
0
DWORD
NetExecShareDel(
    NET_SHARE_DEL_INFO_PARAMS ShareDelInfo
    )
{
    DWORD dwError = 0;

    dwError = NetShareDelW(
    	ShareDelInfo.pwszServerName,
        ShareDelInfo.pwszShareName,
        0);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    return dwError;

error:

    goto cleanup;
}
Example #13
0
DWORD
NetExecSessionLogoff(
    PWSTR pwszServername,   /* IN     OPTIONAL */
    PWSTR pwszUncClientname /* IN     OPTIONAL */
    )
{
    NET_API_STATUS nStatus = 0;
    PWSTR   pwszUsername = NULL;

    nStatus = NetSessionDelW(pwszServername, pwszUncClientname, pwszUsername);
    BAIL_ON_LTNET_ERROR(nStatus);

cleanup:

    return nStatus;

error:

    fprintf(stderr, "Failed to delete session.\n");

    goto cleanup;
}
Example #14
0
static
DWORD
DeconstructSecurityDescriptor(
    DWORD dwLength,
    PSECURITY_DESCRIPTOR_RELATIVE pRelative,
    PDWORD pdwAllowUserCount,
    PWSTR** pppwszAllowUsers,
    PDWORD pdwDenyUserCount,
    PWSTR** pppwszDenyUsers,
    PBOOLEAN pbReadOnly
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    DWORD dwError = 0;
    ULONG ulSize = 0;
    ULONG ulDaclSize = 0;
    ULONG ulSaclSize = 0;
    ULONG ulOwnerSize = 0;
    ULONG ulGroupSize = 0;
    PSID pOwner = NULL;
    PSID pGroup = NULL;
    PACL pSacl = NULL;
    PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL;
    PACL pDacl = NULL;
    ULONG ulIndex = 0;
    PVOID pAce = NULL;
    PACCESS_ALLOWED_ACE pAllow = NULL;
    PACCESS_DENIED_ACE pDeny = NULL;
    DWORD dwAllowUserCount = 0;
    PWSTR* ppwszAllowUsers = NULL;
    DWORD dwDenyUserCount = 0;
    PWSTR* ppwszDenyUsers = NULL;
    PSID pSid = NULL;
    PWSTR pwszUser = NULL;
    HANDLE hLsa = NULL;
    ACCESS_MASK leastMask = FILE_ALL_ACCESS;

    dwError = LsaOpenServer(&hLsa);
    BAIL_ON_LTNET_ERROR(dwError);

    status = RtlSelfRelativeToAbsoluteSD(
        pRelative,
        pAbsolute,
        &ulSize,
        pDacl,
        &ulDaclSize,
        pSacl,
        &ulSaclSize,
        pOwner,
        &ulOwnerSize,
        pGroup,
        &ulGroupSize);
    if (status != STATUS_BUFFER_TOO_SMALL)
    {
        dwError = LwNtStatusToWin32Error(status);
        BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwNetAllocateMemory(ulSize, OUT_PPVOID(&pAbsolute));
    BAIL_ON_LTNET_ERROR(dwError);

    if (ulDaclSize)
    {
        dwError = LwNetAllocateMemory(ulDaclSize, OUT_PPVOID(&pDacl));
        BAIL_ON_LTNET_ERROR(dwError);
    }

    if (ulSaclSize)
    {
        dwError = LwNetAllocateMemory(ulSaclSize, OUT_PPVOID(&pSacl));
        BAIL_ON_LTNET_ERROR(dwError);
    }

    if (ulOwnerSize)
    {
        dwError = LwNetAllocateMemory(ulOwnerSize, OUT_PPVOID(&pOwner));
        BAIL_ON_LTNET_ERROR(dwError);
    }

    if (ulGroupSize)
    {
        dwError = LwNetAllocateMemory(ulGroupSize, OUT_PPVOID(&pGroup));
        BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwNtStatusToWin32Error(
        RtlSelfRelativeToAbsoluteSD(
            pRelative,
            pAbsolute,
            &ulSize,
            pDacl,
            &ulDaclSize,
            pSacl,
            &ulSaclSize,
            pOwner,
            &ulOwnerSize,
            pGroup,
            &ulGroupSize));
    BAIL_ON_LTNET_ERROR(dwError);

    if (pDacl)
    {
        for (ulIndex = 0; ulIndex < RtlGetAclAceCount(pDacl); ulIndex++)
        {
            RtlGetAce(pDacl, ulIndex, &pAce);

            switch(((PACE_HEADER) pAce)->AceType)
            {
            case ACCESS_ALLOWED_ACE_TYPE:
                pAllow = pAce;
                pSid = (PSID) &pAllow->SidStart;

                if ((pAllow->Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ)
                {
                    dwError = MapSidToName(hLsa, pSid, &pwszUser);
                    if (dwError != LW_ERROR_SUCCESS)
                    {
                        dwError = MapBuiltinSidToName(&pwszUser, pSid);
                    }
                    BAIL_ON_LTNET_ERROR(dwError);

                    dwError = LwNetAppendStringArray(
                        &dwAllowUserCount,
                        &ppwszAllowUsers,
                        pwszUser);
                    BAIL_ON_LTNET_ERROR(dwError);

                    pwszUser = NULL;

                    leastMask &= pAllow->Mask;
                }
                break;
            case ACCESS_DENIED_ACE_TYPE:
                pDeny = pAce;
                pSid = (PSID) &pDeny->SidStart;

                if ((pDeny->Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ)
                {
                    dwError = MapSidToName(hLsa, pSid, &pwszUser);
                    if (dwError != LW_ERROR_SUCCESS)
                    {
                        dwError = MapBuiltinSidToName(&pwszUser, pSid);
                    }
                    BAIL_ON_LTNET_ERROR(dwError);

                    dwError = LwNetAppendStringArray(
                        &dwDenyUserCount,
                        &ppwszDenyUsers,
                        pwszUser);
                    BAIL_ON_LTNET_ERROR(dwError);

                    pwszUser = NULL;
                }
                break;
            default:
                break;
            }
        }
    }

    *pppwszAllowUsers = ppwszAllowUsers;
    *pdwAllowUserCount = dwAllowUserCount;
    *pppwszDenyUsers = ppwszDenyUsers;
    *pdwDenyUserCount = dwDenyUserCount;
    *pbReadOnly = !((leastMask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE);

cleanup:

    if (hLsa)
    {
        LsaCloseServer(hLsa);
    }

    LTNET_SAFE_FREE_MEMORY(pSacl);
    LTNET_SAFE_FREE_MEMORY(pOwner);
    LTNET_SAFE_FREE_MEMORY(pGroup);
    LTNET_SAFE_FREE_MEMORY(pwszUser);
    LTNET_SAFE_FREE_MEMORY(pDacl);
    LTNET_SAFE_FREE_MEMORY(pAbsolute);

    return dwError;

error:

    *pppwszAllowUsers = NULL;
    *pdwAllowUserCount = 0;
    *pppwszDenyUsers = NULL;
    *pdwDenyUserCount = 0;

    goto cleanup;
}
Example #15
0
static
DWORD
ConstructSecurityDescriptor(
    DWORD dwAllowUserCount,
    PWSTR* ppwszAllowUsers,
    DWORD dwDenyUserCount,
    PWSTR* ppwszDenyUsers,
    BOOLEAN bReadOnly,
    PSECURITY_DESCRIPTOR_RELATIVE* ppRelative,
    PDWORD pdwRelativeSize
    )
{
    DWORD dwError = 0;
    PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pRelative = NULL;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Owner;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Group;
    ULONG OwnerSidSize = sizeof(Owner.buffer);
    ULONG GroupSidSize = sizeof(Group.buffer);
    DWORD dwDaclSize = 0;
    PACL pDacl = NULL;
    DWORD dwIndex = 0;
    PSID pSid = NULL;
    ULONG ulRelativeSize = 0;
    HANDLE hLsa = NULL;
    ACCESS_MASK mask = bReadOnly ?
        (FILE_GENERIC_READ|FILE_GENERIC_EXECUTE) :
        FILE_ALL_ACCESS;

    dwError = LsaOpenServer(&hLsa);
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinBuiltinAdministratorsSid,
            NULL,
            &Owner.sid,
            &OwnerSidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinBuiltinPowerUsersSid,
            NULL,
            &Group.sid,
            &GroupSidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    dwDaclSize = ACL_HEADER_SIZE +
        dwAllowUserCount * (sizeof(ACCESS_ALLOWED_ACE) + SID_MAX_SIZE) +
        dwDenyUserCount * (sizeof(ACCESS_DENIED_ACE) + SID_MAX_SIZE) +
        RtlLengthSid(&Owner.sid) + RtlLengthSid(&Group.sid);

    dwError = LwNetAllocateMemory(
        dwDaclSize,
        OUT_PPVOID(&pDacl));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION));
    BAIL_ON_LTNET_ERROR(dwError);

    for (dwIndex = 0; dwIndex < dwDenyUserCount; dwIndex++)
    {
        dwError = MapNameToSid(hLsa, ppwszDenyUsers[dwIndex], &pSid);
        if (dwError != LW_ERROR_SUCCESS)
        {
            dwError = MapBuiltinNameToSid(&pSid, ppwszDenyUsers[dwIndex]);
        }

        BAIL_ON_LTNET_ERROR(dwError);

        dwError = LwNtStatusToWin32Error(
            RtlAddAccessDeniedAceEx(
                pDacl,
                ACL_REVISION,
                0,
                FILE_ALL_ACCESS,
                pSid));
        BAIL_ON_LTNET_ERROR(dwError);

        RTL_FREE(&pSid);
    }

    for (dwIndex = 0; dwIndex < dwAllowUserCount; dwIndex++)
    {
        dwError = MapNameToSid(hLsa, ppwszAllowUsers[dwIndex], &pSid);
        if (dwError != LW_ERROR_SUCCESS)
        {
            dwError = MapBuiltinNameToSid(&pSid, ppwszAllowUsers[dwIndex]);
        }
        BAIL_ON_LTNET_ERROR(dwError);

        dwError = LwNtStatusToWin32Error(
            RtlAddAccessAllowedAceEx(
                pDacl,
                ACL_REVISION,
                0,
                mask,
                pSid));
        BAIL_ON_LTNET_ERROR(dwError);

        RTL_FREE(&pSid);
    }

    dwError = LwNetAllocateMemory(
        SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE,
        OUT_PPVOID(&pAbsolute));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateSecurityDescriptorAbsolute(
            pAbsolute,
            SECURITY_DESCRIPTOR_REVISION));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetOwnerSecurityDescriptor(
            pAbsolute,
            &Owner.sid,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetGroupSecurityDescriptor(
            pAbsolute,
            &Group.sid,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetDaclSecurityDescriptor(
            pAbsolute,
            TRUE,
            pDacl,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    RtlAbsoluteToSelfRelativeSD(
        pAbsolute,
        NULL,
        &ulRelativeSize);

    dwError = LwNetAllocateMemory(ulRelativeSize, OUT_PPVOID(&pRelative));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlAbsoluteToSelfRelativeSD(
            pAbsolute,
            pRelative,
            &ulRelativeSize));
    BAIL_ON_LTNET_ERROR(dwError);

    *ppRelative = pRelative;
    *pdwRelativeSize = ulRelativeSize;

cleanup:

    if (hLsa)
    {
        LsaCloseServer(hLsa);
    }

    LTNET_SAFE_FREE_MEMORY(pSid);
    LTNET_SAFE_FREE_MEMORY(pDacl);
    LTNET_SAFE_FREE_MEMORY(pAbsolute);

    return dwError;

error:

    *ppRelative = NULL;
    *pdwRelativeSize = 0;

    LTNET_SAFE_FREE_MEMORY(pRelative);

    goto cleanup;
}
Example #16
0
DWORD
NetExecFileEnum(
    PCWSTR pwszServername
    )
{
    NET_API_STATUS nStatus  = 0;
    PWSTR pwszBasepath      = NULL;
    PWSTR pwszUsername      = NULL;
    DWORD dwInfoLevel       = 3;
    PBYTE pBuffer           = NULL;
    DWORD dwPrefmaxLen      = UINT32_MAX;
    DWORD dwEntriesRead     = 0;
    DWORD dwTotalEntries    = 0;
    DWORD dwResumeHandle    = 0;
    DWORD iFile             = 0;
    DWORD iFileCursor       = 0;
    PFILE_INFO_3 pFileCursor = NULL;
    PSTR  pszPathname       = NULL;
    PSTR  pszUsername       = NULL;
    BOOLEAN bContinue       = TRUE;

    do
    {
        if (pBuffer)
        {
            NetApiBufferFree(pBuffer);
            pBuffer = NULL;
        }

        bContinue = FALSE;
        nStatus = NetFileEnumW(
                        pwszServername,
                        pwszBasepath,
                        pwszUsername,
                        dwInfoLevel,
                        &pBuffer,
                        dwPrefmaxLen,
                        &dwEntriesRead,
                        &dwTotalEntries,
                        &dwResumeHandle);

        if (nStatus == ERROR_MORE_DATA)
        {
            bContinue = TRUE;
        }
        switch (nStatus)
        {
            case ERROR_SUCCESS:
            case ERROR_MORE_DATA:

                pFileCursor = (PFILE_INFO_3)pBuffer;

                for (iFile = 0; iFile < dwEntriesRead; iFile++, pFileCursor++)
                {
                    if (pFileCursor->fi3_path_name)
                    {
                        LW_SAFE_FREE_STRING(pszPathname);

                        nStatus = LwWc16sToMbs(
                                        pFileCursor->fi3_path_name,
                                        &pszPathname);
                        BAIL_ON_LTNET_ERROR(nStatus);
                    }

                    if (pFileCursor->fi3_username)
                    {
                        LW_SAFE_FREE_STRING(pszUsername);

                        nStatus = LwWc16sToMbs(
                                        pFileCursor->fi3_username,
                                        &pszUsername);
                        BAIL_ON_LTNET_ERROR(nStatus);
                    }

                    printf("File [%u]\n", ++iFileCursor);

                    printf("\tId:              %u\n", pFileCursor->fi3_idd);
                    printf("\tPathname:        %s\n",
                            (pszPathname ? pszPathname : ""));
                    printf("\tUsername:        %s\n",
                            (pszUsername ? pszUsername : ""));
                    printf("\tNumber of locks: %u\n",
                            pFileCursor->fi3_num_locks);
                    printf("\tPermissions:     0x%08x\n",
                            pFileCursor->fi3_permissions);
                }

                break;

            default:

                BAIL_ON_LTNET_ERROR(nStatus);

                break;
        }

    } while (bContinue);

    if (!iFileCursor)
    {
        printf("There are no entries in the list\n");
    }

cleanup:

    if (pBuffer)
    {
        NetApiBufferFree(pBuffer);
    }

    LW_SAFE_FREE_STRING(pszPathname);
    LW_SAFE_FREE_STRING(pszUsername);

    return nStatus;

error:

    fprintf(stderr, "Failed to enumerate files.\n");

    goto cleanup;
}
Example #17
0
DWORD
NetExecSetInfo(
    NET_SHARE_ADD_OR_SET_INFO_PARAMS ShareSetInfo
    )
{
    static const DWORD dwLevel = 502;

    DWORD dwError = 0;
    SHARE_INFO_502 newShareInfo = {0};
    PSHARE_INFO_502 pShareInfo = NULL;
    DWORD dwParmErr = 0;
    PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL;
    DWORD dwSecDescSize = 0;
    DWORD dwAllowUserCount = 0;
    PWSTR* ppwszAllowUsers = NULL;
    DWORD dwDenyUserCount = 0;
    PWSTR* ppwszDenyUsers = NULL;
    BOOLEAN bReadOnly = FALSE;

    dwError = NetShareGetInfoW(
        ShareSetInfo.pwszServerName,
        ShareSetInfo.pwszShareName,
        dwLevel,
        (PBYTE*)(&pShareInfo));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = DeconstructSecurityDescriptor(
        pShareInfo->shi502_reserved,
        (PSECURITY_DESCRIPTOR_RELATIVE) pShareInfo->shi502_security_descriptor,
        &dwAllowUserCount,
        &ppwszAllowUsers,
        &dwDenyUserCount,
        &ppwszDenyUsers,
        &bReadOnly);
    BAIL_ON_LTNET_ERROR(dwError);

    newShareInfo = *pShareInfo;

    if (ShareSetInfo.pwszShareName)
    {
        newShareInfo.shi502_netname = ShareSetInfo.pwszShareName;
    }

    if (ShareSetInfo.pwszComment)
    {
        newShareInfo.shi502_remark = ShareSetInfo.pwszComment;
    }

    if (ShareSetInfo.pwszPath)
    {
        newShareInfo.shi502_path = ShareSetInfo.pwszPath;
    }

    dwError = ConstructSecurityDescriptor(
        ShareSetInfo.dwAllowUserCount
        || ShareSetInfo.bClearAllow ? ShareSetInfo.dwAllowUserCount : dwAllowUserCount,
        ShareSetInfo.dwAllowUserCount || ShareSetInfo.bClearAllow ? ShareSetInfo.ppwszAllowUsers : ppwszAllowUsers,
        ShareSetInfo.dwDenyUserCount || ShareSetInfo.bClearDeny ? ShareSetInfo.dwDenyUserCount : dwDenyUserCount,
        ShareSetInfo.dwDenyUserCount || ShareSetInfo.bClearDeny ? ShareSetInfo.ppwszDenyUsers : ppwszDenyUsers,
        ShareSetInfo.bReadOnly || ShareSetInfo.bReadWrite ? (ShareSetInfo.bReadOnly && !ShareSetInfo.bReadWrite) : bReadOnly,
        &pSecDesc,
        &dwSecDescSize);
    BAIL_ON_LTNET_ERROR(dwError);

    newShareInfo.shi502_type = pShareInfo->shi502_type;
    newShareInfo.shi502_reserved = dwSecDescSize;
    newShareInfo.shi502_security_descriptor = (PBYTE) pSecDesc;

    dwError = NetShareSetInfoW(
        ShareSetInfo.pwszServerName,
        ShareSetInfo.pwszShareName,
        dwLevel,
        (PBYTE)&newShareInfo,
        &dwParmErr);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:

    if (pShareInfo)
    {
        LwNetFreeMemory(pShareInfo);
    }

    LwNetFreeWC16StringArray(dwAllowUserCount, ppwszAllowUsers);
    LwNetFreeWC16StringArray(dwDenyUserCount, ppwszDenyUsers);

    LTNET_SAFE_FREE_MEMORY(pSecDesc);

    return dwError;

error:

    goto cleanup;
}
Example #18
0
static
DWORD
NetShareAddParseArguments(
	int argc,
	char** argv,
	IN OUT PNET_SHARE_COMMAND_INFO pCommandInfo
	)
{
	DWORD dwError = 0;
	PCSTR pszPath =  NULL;
	size_t sShareNameLen = 0;
	int indexShareAddArg = 3;
	// Do not free
	PCSTR pszShareAddShareInfo = NULL;
	PSTR pszShareName = NULL;

	if (!argv[indexShareAddArg])
	{
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
	}

    if (!strncmp(argv[indexShareAddArg], "\\\\", sizeof("\\\\")-1))
    {
        dwError = LwMbsToWc16s(argv[indexShareAddArg]+sizeof("\\\\")-1,
                  &pCommandInfo->ShareAddOrSetInfo.pwszServerName);
        BAIL_ON_LTNET_ERROR(dwError);

        indexShareAddArg++;
    }

	if (indexShareAddArg > argc-1)
	{
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
	}

	pszShareAddShareInfo = argv[indexShareAddArg];

	pszPath = strchr(pszShareAddShareInfo, '=');
	if (LTNET_IS_NULL_OR_EMPTY_STR(pszPath))
	{
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
	}

    dwError = LwMbsToWc16s(pszPath+1, &pCommandInfo->ShareAddOrSetInfo.pwszPath);
    BAIL_ON_LTNET_ERROR(dwError);

    sShareNameLen = strlen(pszShareAddShareInfo)-strlen(pszPath);

    if (!sShareNameLen)
    {
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
    }

    dwError = LwNetAllocateMemory(sShareNameLen+1,
		                  (PVOID*)&pszShareName);
    BAIL_ON_LTNET_ERROR(dwError);

    memcpy(pszShareName, pszShareAddShareInfo, sShareNameLen);

    dwError = LwMbsToWc16s(pszShareName, &pCommandInfo->ShareAddOrSetInfo.pwszShareName);
    BAIL_ON_LTNET_ERROR(dwError);

    // Process add options
    dwError = ParseShareAddOrSetinfoOptionArgs(argc, ++indexShareAddArg, argv,
                                               pCommandInfo->dwControlCode,
                                               &pCommandInfo->ShareAddOrSetInfo);
    BAIL_ON_LTNET_ERROR(dwError);

cleanup:
    LTNET_SAFE_FREE_STRING(pszShareName);

    return dwError;

error:

    NetShareFreeCommandInfo(pCommandInfo);

    goto cleanup;
}
Example #19
0
DWORD
NetExecSessionEnum(
    PWSTR pwszServername,   /* IN              */
    PWSTR pwszClientname    /* IN     OPTIONAL */
    )
{
    NET_API_STATUS nStatus  = 0;
    PWSTR pwszUsername      = NULL;
    DWORD dwInfoLevel       = 2;
    PBYTE pBuffer           = NULL;
    DWORD dwPrefmaxLen      = UINT32_MAX;
    DWORD dwEntriesRead     = 0;
    DWORD dwTotalEntries    = 0;
    DWORD dwResumeHandle    = 0;
    DWORD iSession          = 0;
    DWORD iSessionCursor    = 0;
    PSESSION_INFO_2 pSessionCursor = NULL;
    PSTR  pszSessionname    = NULL;
    PSTR  pszUsername       = NULL;
    PSTR  pszClientType     = NULL;
    BOOLEAN bContinue       = FALSE;

    do
    {
        if (pBuffer)
        {
            NetApiBufferFree(pBuffer);
            pBuffer = NULL;
        }

        bContinue = FALSE;
        nStatus = NetSessionEnumW(
                        pwszServername,
                        pwszClientname,
                        pwszUsername,
                        dwInfoLevel,
                        &pBuffer,
                        dwPrefmaxLen,
                        &dwEntriesRead,
                        &dwTotalEntries,
                        &dwResumeHandle);

        if (nStatus == ERROR_MORE_DATA)
        {
            bContinue = TRUE;
        }
        switch (nStatus)
        {
            case ERROR_SUCCESS:
            case ERROR_MORE_DATA:

                pSessionCursor = (PSESSION_INFO_2)pBuffer;

                for (   iSession = 0;
                        iSession < dwEntriesRead;
                        iSession++, pSessionCursor++)
                {
                    if (pSessionCursor->sesi2_cname)
                    {
                        LW_SAFE_FREE_STRING(pszSessionname);

                        nStatus = LwWc16sToMbs(
                                        pSessionCursor->sesi2_cname,
                                        &pszSessionname);
                        BAIL_ON_LTNET_ERROR(nStatus);
                    }

                    if (pSessionCursor->sesi2_username)
                    {
                        LW_SAFE_FREE_STRING(pszUsername);

                        nStatus = LwWc16sToMbs(
                                        pSessionCursor->sesi2_username,
                                        &pszUsername);
                        BAIL_ON_LTNET_ERROR(nStatus);
                    }

                    if (pSessionCursor->sesi2_cltype_name)
                    {
                        LW_SAFE_FREE_STRING(pszClientType);

                        nStatus = LwWc16sToMbs(
                                        pSessionCursor->sesi2_cltype_name,
                                        &pszClientType);
                        BAIL_ON_LTNET_ERROR(nStatus);
                    }

                    printf("Session [%u]\n", ++iSessionCursor);

                    printf("\tComputer:        %s\n",
                            (pszSessionname ? pszSessionname : ""));
                    printf("\tUsername:        %s\n",
                            (pszUsername ? pszUsername : ""));
                    printf("\tClient type:     %s\n",
                            (pszClientType ? pszClientType : ""));
                    printf("\tNumber of opens: %u\n",
                            pSessionCursor->sesi2_num_opens);
                    printf("\tActive time:     %u\n",
                            pSessionCursor->sesi2_time);
                    printf("\tIdle time:       %u\n",
                            pSessionCursor->sesi2_idle_time);
                    printf("\tGuest login?     %s\n",
                            pSessionCursor->sesi2_user_flags & 0x1 ? "yes" : "no");
                    printf("\tEncryption?      %s\n\n",
                            pSessionCursor->sesi2_user_flags & 0x2 ? "yes" : "no");

                }

                break;

            default:

                BAIL_ON_LTNET_ERROR(nStatus);

                break;
        }

    } while (bContinue);

    if (!iSessionCursor)
    {
        printf("There are no entries in the list\n");
    }

cleanup:

    if (pBuffer)
    {
        NetApiBufferFree(pBuffer);
    }

    LW_SAFE_FREE_STRING(pszSessionname);
    LW_SAFE_FREE_STRING(pszUsername);
    LW_SAFE_FREE_STRING(pszClientType);

    return nStatus;

error:

    fprintf(stderr, "Failed to enumerate sessions.\n");

    goto cleanup;
}
Example #20
0
static
DWORD
ParseShareAddOrSetinfoOptionArgs(
    IN int argc,
    IN int indexStart,
    IN char** argv,
    IN NET_SHARE_CTRL_CODE dwCtrlCode,
    IN OUT PNET_SHARE_ADD_OR_SET_INFO_PARAMS pShareAddOrSetParams
    )
{
    DWORD dwError = 0;
    DWORD dwIndex = 0;
    PWSTR pwszArg = NULL;

    for (dwIndex = indexStart; dwIndex < argc; dwIndex++)
    {
        if (!strcmp(argv[dwIndex], "--allow"))
        {
            dwError = LwMbsToWc16s(argv[++dwIndex], &pwszArg);
            BAIL_ON_LTNET_ERROR(dwError);

            dwError = LwNetAppendStringArray(
                &pShareAddOrSetParams->dwAllowUserCount,
                &pShareAddOrSetParams->ppwszAllowUsers,
                pwszArg);
            BAIL_ON_LTNET_ERROR(dwError);

            pwszArg = NULL;
        }
        else if (!strcmp(argv[dwIndex], "--deny"))
        {
            dwError = LwMbsToWc16s(argv[++dwIndex], &pwszArg);
            BAIL_ON_LTNET_ERROR(dwError);

            dwError = LwNetAppendStringArray(
                &pShareAddOrSetParams->dwDenyUserCount,
                &pShareAddOrSetParams->ppwszDenyUsers,
                pwszArg);
            BAIL_ON_LTNET_ERROR(dwError);

            pwszArg = NULL;
        }
        else if (!strcmp(argv[dwIndex], "--comment"))
        {
            dwError = LwMbsToWc16s(argv[++dwIndex], &pShareAddOrSetParams->pwszComment);
            BAIL_ON_LTNET_ERROR(dwError);
        }
        else if (!strcmp(argv[dwIndex], "--read-only"))
        {
            pShareAddOrSetParams->bReadOnly = TRUE;
        }
        else if (!strcmp(argv[dwIndex], "--read-write"))
        {
            pShareAddOrSetParams->bReadWrite = TRUE;
        }
        else if (!strcmp(argv[dwIndex], "--clear-allow")
                && NET_SHARE_SETINFO == dwCtrlCode)
        {
            pShareAddOrSetParams->bClearAllow = TRUE;
        }
        else if (!strcmp(argv[dwIndex], "--clear-deny")
                && NET_SHARE_SETINFO == dwCtrlCode)
        {
            pShareAddOrSetParams->bClearDeny = TRUE;
        }
        else
        {
            dwError = LwMbsToWc16s(argv[dwIndex], &pShareAddOrSetParams->pwszTarget);
            BAIL_ON_LTNET_ERROR(dwError);
            break;
        }
    }

error:

    LTNET_SAFE_FREE_MEMORY(pwszArg);

    return dwError;
}
Example #21
0
static
DWORD
NetShareParseArguments(
    int argc,
	char ** argv,
	PNET_SHARE_COMMAND_INFO* ppCommandInfo
	)
{
	DWORD dwError = 0;
	PNET_SHARE_COMMAND_INFO pCommandInfo = NULL;

	if (argc < 2)
	{
		dwError = LW_ERROR_INTERNAL;
		BAIL_ON_LTNET_ERROR(dwError);
	}

    dwError = LwNetAllocateMemory(sizeof(*pCommandInfo),
		                       (PVOID*)&pCommandInfo);
    BAIL_ON_LTNET_ERROR(dwError);


    if (!argv[2])
    {
	pCommandInfo->dwControlCode = NET_SHARE_ENUM;
	goto cleanup;
    }

    if (!strcasecmp(argv[2], NET_SHARE_COMMAND_HELP))
    {
	NetShareShowUsage();
	goto cleanup;
    }
    else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_ADD))
	{
		pCommandInfo->dwControlCode = NET_SHARE_ADD;

		if (!argv[3])
		{
			dwError = LW_ERROR_INVALID_PARAMETER;
			BAIL_ON_LTNET_ERROR(dwError);
		}

		dwError = NetShareAddParseArguments(argc, argv, pCommandInfo);
		BAIL_ON_LTNET_ERROR(dwError);
	}
	else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_DEL))
	{
		pCommandInfo->dwControlCode = NET_SHARE_DEL;

		dwError = NetShareDelParseArguments(argc, argv, pCommandInfo);
		BAIL_ON_LTNET_ERROR(dwError);
	}
	else if (!strcasecmp(argv[2], "--server"))
    {
		pCommandInfo->dwControlCode = NET_SHARE_ENUM;

		dwError = NetShareEnumParseArguments(argc, argv, pCommandInfo);
		BAIL_ON_LTNET_ERROR(dwError);
    }
	else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_SETINFO))
	{
	    pCommandInfo->dwControlCode = NET_SHARE_SETINFO;

	    dwError = NetShareSetinfoParseArguments(argc, argv, pCommandInfo);
	    BAIL_ON_LTNET_ERROR(dwError);
	}
    else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_GETINFO))
    {
        pCommandInfo->dwControlCode = NET_SHARE_GETINFO;

        dwError = NetShareGetinfoParseArguments(argc, argv, pCommandInfo);
        BAIL_ON_LTNET_ERROR(dwError);
    }
	else
	{
		dwError = LW_ERROR_INVALID_PARAMETER;
		BAIL_ON_LTNET_ERROR(dwError);
	}

cleanup:

    *ppCommandInfo = pCommandInfo;

    return dwError;

error:
    if (LW_ERROR_INVALID_PARAMETER == dwError)
    {
	NetShareShowUsage();
    }

    LTNET_SAFE_FREE_MEMORY(pCommandInfo);
    pCommandInfo = NULL;

    goto cleanup;
}
Example #22
0
int 
main(
    int argc,
    char ** argv
    )
{
	DWORD dwError = 0;
	NET_SUB_COMMAND dwSubCommand = NET_COMMAND_UNKNOWN;

	if (argc == 1)
	{
		NetCommandShow();
		return dwError;
	}

    dwError = NetMapSubCommand(
                    argv[1],
                    &dwSubCommand
                    );
    BAIL_ON_LTNET_ERROR(dwError);

    switch (dwSubCommand)
    {
        case NET_COMMAND_HELP:
            if (!argv[2])
            {
		NetShowUsage();
            }
            else
            {
		NetShowCommandUsage(argv[2]);
            }

        	break;

        case NET_COMMAND_SHARE:

            dwError = NetShare(argc, argv);

            break;

        case NET_COMMAND_SESSION:

            dwError = NetSession(argc, argv);

        	break;

        case NET_COMMAND_USER:
        	printf("net user\n");
        	break;

        case NET_COMMAND_VIEW:
        	printf("net view\n");
        	break;

        case NET_COMMAND_LOCALGROUP:
        	printf("net localgroup\n");
        	break;

        case NET_COMMAND_TIME:
		printf("net time\n");
		break;

        case NET_COMMAND_FILE:

            dwError = NetFile(argc, argv);

		break;

        case NET_COMMAND_UNKNOWN:
        default:
		NetShowUsage();
		break;
    }
    BAIL_ON_LTNET_ERROR(dwError);

 error:

     return dwError;
}
Example #23
0
DWORD
NetExecShareEnum(
    NET_SHARE_ENUM_INFO_PARAMS ShareEnumInfo
    )
{
    static const DWORD dwLevel = 2;
    static const DWORD dwMaxLen = 1024;

    DWORD dwError = 0;
    PSHARE_INFO_2 pShareInfo = NULL;
    DWORD dwNumShares = 0;
    DWORD dwTotalShares = 0;
    DWORD dwVisitedShares = 0;
    DWORD dwResume = 0;
    DWORD dwIndex = 0;

    PSTR* ppszShareName = NULL;
    PSTR* ppszSharePath = NULL;
    PSTR* ppszShareComment = NULL;
    DWORD dwShareNameLenMax = 0;
    DWORD dwSharePathLenMax = 0;
    DWORD dwShareCommentLenMax = 0;
    DWORD dwShareNameLen = 0;
    DWORD dwSharePathLen = 0;
    DWORD dwShareCommentLen = 0;

    do
    {
        dwError = NetShareEnumW(
            ShareEnumInfo.pwszServerName,
            dwLevel,
            (PBYTE*)&pShareInfo,
            dwMaxLen,
            &dwNumShares,
            &dwTotalShares,
            &dwResume);
        if (dwError == ERROR_MORE_DATA)
        {
            dwError = 0;
        }
        BAIL_ON_LTNET_ERROR(dwError);

        if (!ppszShareName)
        {
            dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszShareName);
            BAIL_ON_LTNET_ERROR(dwError);
        }

        if (!ppszSharePath)
        {
            dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszSharePath);
            BAIL_ON_LTNET_ERROR(dwError);
        }

        if (!ppszShareComment)
        {
            dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszShareComment);
            BAIL_ON_LTNET_ERROR(dwError);
        }

        for (dwIndex = 0; dwIndex < dwNumShares; dwIndex++)
        {
            dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_netname,
                                   &ppszShareName[dwIndex+dwVisitedShares]);
            BAIL_ON_LTNET_ERROR(dwError);

            dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_path,
                                   &ppszSharePath[dwIndex+dwVisitedShares]);
            BAIL_ON_LTNET_ERROR(dwError);

            if (pShareInfo[dwIndex].shi2_remark)
            {
                dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_remark,
                                       &ppszShareComment[dwIndex+dwVisitedShares]);
                BAIL_ON_LTNET_ERROR(dwError);
            }
        }

        if (pShareInfo)
        {
            NetApiBufferFree(pShareInfo);
            pShareInfo = NULL;
        }

        dwVisitedShares += dwNumShares;

    } while (dwVisitedShares < dwTotalShares);

    dwError = LwNetAllocateString(NET_SHARE_NAME_TITLE, &ppszShareName[dwTotalShares]);
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNetAllocateString(NET_SHARE_PATH_TITLE, &ppszSharePath[dwTotalShares]);
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNetAllocateString(NET_SHARE_COMMENT_TITLE, &ppszShareComment[dwTotalShares]);
    BAIL_ON_LTNET_ERROR(dwError);

    for (dwIndex = 0; dwIndex < dwTotalShares + 1; dwIndex++)
    {
        dwShareNameLen = strlen(ppszShareName[dwIndex]);
        if (dwShareNameLen>dwShareNameLenMax)
        {
            dwShareNameLenMax = dwShareNameLen;
        }

        dwSharePathLen = strlen(ppszSharePath[dwIndex]);
        if (dwSharePathLen>dwSharePathLenMax)
        {
            dwSharePathLenMax = dwSharePathLen;
        }

        if (ppszShareComment[dwIndex])
        {
            dwShareCommentLen = strlen(ppszShareComment[dwIndex]);
            if (dwShareCommentLen>dwShareCommentLenMax)
            {
            	dwShareCommentLenMax = dwShareCommentLen;
            }
        }
    }

    //print share enum header

    printf("  %s%*s",
           NET_SHARE_NAME_TITLE,
           (int) (strlen(NET_SHARE_NAME_TITLE)-dwShareNameLenMax),
           "");
    printf("  %s%*s",
           NET_SHARE_PATH_TITLE,
           (int) (strlen(NET_SHARE_PATH_TITLE)-dwSharePathLenMax),
           "");
    printf("  %s%*s\n",
           NET_SHARE_COMMENT_TITLE,
           (int) (strlen(NET_SHARE_COMMENT_TITLE)-dwShareCommentLenMax),
           "");

    for (dwIndex = 0; dwIndex < dwShareNameLenMax+dwSharePathLenMax+dwShareCommentLenMax+10; dwIndex++)
    	printf("%s", "-");

    printf("\n");


    for (dwIndex = 0; dwIndex < dwTotalShares; dwIndex++)
    {
        printf("  %s%*s",
               ppszShareName[dwIndex],
               (int) (strlen(ppszShareName[dwIndex])-dwShareNameLenMax),
               "");

        printf("  %s%*s",
               ppszSharePath[dwIndex],
               (int) (strlen(ppszSharePath[dwIndex])-dwSharePathLenMax),
               "");

        if (ppszShareComment[dwIndex])
        {
            printf("  %s%*s",
                   ppszShareComment[dwIndex],
                   (int) (strlen(ppszShareComment[dwIndex])-dwShareCommentLenMax),
                   "");
        }

        printf("\n");
    }

cleanup:

    if (ppszShareName)
    {
    	LwNetFreeStringArray(dwTotalShares, ppszShareName);
    }
    if (ppszSharePath)
    {
    	LwNetFreeStringArray(dwTotalShares, ppszSharePath);
    }
    if (ppszShareComment)
    {
    	LwNetFreeStringArray(dwTotalShares, ppszShareComment);
    }

    if (pShareInfo)
    {
    	NetApiBufferFree(pShareInfo);
        pShareInfo = NULL;
    }

    return dwError;

error:

    goto cleanup;
}