415 lines
9.9 KiB
C
415 lines
9.9 KiB
C
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <shellapi.h>
|
|
#include "dfsadmin.h"
|
|
|
|
DFSSTATUS
|
|
AddRootToPrefixTable(
|
|
struct _DFS_PREFIX_TABLE **ppTable,
|
|
PROOT_DEF pRoot );
|
|
|
|
PLINK_DEF
|
|
CreateNewLinkEntry(
|
|
LPWSTR LinkName );
|
|
|
|
PTARGET_DEF
|
|
CreateNewTargetEntry(
|
|
LPWSTR ServerName,
|
|
LPWSTR ShareName,
|
|
ULONG State );
|
|
|
|
PLINK_DEF
|
|
GetLinkEntry(
|
|
struct _DFS_PREFIX_TABLE *pTable,
|
|
LPWSTR NameString );
|
|
|
|
PTARGET_DEF
|
|
GetTargetEntry(
|
|
PLINK_DEF pLink,
|
|
LPWSTR ServerName,
|
|
LPWSTR ShareName );
|
|
|
|
PLINK_DEF
|
|
MergeLinkInfo(
|
|
PDFS_INFO_4 pBuf,
|
|
struct _DFS_PREFIX_TABLE *pPrefixTable );
|
|
|
|
|
|
|
|
|
|
DFSSTATUS
|
|
DfsMerge (
|
|
PROOT_DEF pRoot,
|
|
LPWSTR NameSpace )
|
|
{
|
|
LPBYTE pBuffer = NULL;
|
|
DWORD ResumeHandle = 0;
|
|
DWORD EntriesRead = 0;
|
|
DWORD PrefMaxLen = -1;
|
|
DWORD Level = 4;
|
|
DFSSTATUS Status;
|
|
NTSTATUS NtStatus;
|
|
PDFS_INFO_4 pCurrentBuffer;
|
|
DWORD i;
|
|
|
|
PLINK_DEF pGrownLinks = NULL, pLink;
|
|
struct _DFS_PREFIX_TABLE *pPrefixTable;
|
|
|
|
|
|
Status = AddRootToPrefixTable( &pPrefixTable,
|
|
pRoot );
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
printf("DfsVerify: create prefix table failed %x\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
if (DebugOut)
|
|
{
|
|
fwprintf(DebugOut, L"Contacting %wS for enumeration \n", NameSpace);
|
|
}
|
|
|
|
Status = NetDfsEnum( NameSpace,
|
|
Level,
|
|
PrefMaxLen,
|
|
&pBuffer,
|
|
&EntriesRead,
|
|
&ResumeHandle);
|
|
|
|
if (DebugOut)
|
|
{
|
|
fwprintf(DebugOut, L"Enumeration for %wS is complete %d entries\n",
|
|
NameSpace,
|
|
EntriesRead);
|
|
}
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
printf("Export: cannot enum %wS: error %x\n", NameSpace, Status);
|
|
return Status;
|
|
}
|
|
|
|
pCurrentBuffer = (PDFS_INFO_4)pBuffer;
|
|
|
|
NtStatus = DfsPrefixTableAcquireWriteLock( pPrefixTable);
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
printf("Unable to take prefix table lock, %x\n", NtStatus);
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < EntriesRead; i++)
|
|
{
|
|
pLink = MergeLinkInfo( pCurrentBuffer,
|
|
pPrefixTable);
|
|
if (pLink != NULL)
|
|
{
|
|
if (pGrownLinks == NULL)
|
|
{
|
|
pGrownLinks = pRoot->pLinks;
|
|
}
|
|
NEXT_LINK_OBJECT(pLink) = pGrownLinks;
|
|
pGrownLinks = pLink;
|
|
}
|
|
|
|
pCurrentBuffer++;
|
|
}
|
|
DfsPrefixTableReleaseLock(pPrefixTable);
|
|
if (pGrownLinks != NULL)
|
|
{
|
|
pRoot->pLinks = pGrownLinks;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
PTARGET_DEF
|
|
CreateNewTargetEntry(
|
|
LPWSTR ServerName,
|
|
LPWSTR ShareName,
|
|
ULONG State )
|
|
{
|
|
DFSSTATUS Status;
|
|
UNICODE_STRING TargetName;
|
|
PTARGET_DEF pTarget;
|
|
|
|
Status = DfsCreateUnicodePathString( &TargetName,
|
|
2, // unc path: 2 leading sep.
|
|
ServerName,
|
|
ShareName );
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
pTarget = CreateTargetDef(IN_NAMESPACE, TargetName.Buffer, State);
|
|
|
|
DfsFreeUnicodeString(&TargetName);
|
|
}
|
|
|
|
return pTarget;
|
|
}
|
|
|
|
PLINK_DEF
|
|
CreateNewLinkEntry(
|
|
LPWSTR LinkName )
|
|
{
|
|
PLINK_DEF pLink;
|
|
|
|
pLink = CreateLinkDef(IN_NAMESPACE, LinkName, NULL);
|
|
|
|
return pLink;
|
|
}
|
|
|
|
|
|
VOID
|
|
UpdateLinkEntry(
|
|
PLINK_DEF pLink,
|
|
ULONG State,
|
|
ULONG Timeout,
|
|
LPWSTR Comment )
|
|
{
|
|
if (State != 0)
|
|
{
|
|
AddObjectStateValue(&pLink->BaseObject, State);
|
|
}
|
|
if (Timeout != 0)
|
|
{
|
|
AddObjectTimeoutValue(&pLink->BaseObject, Timeout);
|
|
}
|
|
if (Comment != NULL)
|
|
{
|
|
AddObjectComment(&pLink->BaseObject, Comment);
|
|
}
|
|
}
|
|
|
|
DFSSTATUS
|
|
AddRootToPrefixTable(
|
|
struct _DFS_PREFIX_TABLE **ppTable,
|
|
PROOT_DEF pRoot )
|
|
{
|
|
struct _DFS_PREFIX_TABLE *pTable = NULL;
|
|
NTSTATUS NtStatus;
|
|
PLINK_DEF pLink;
|
|
UNICODE_STRING LinkName;
|
|
ULONG Links = 0;
|
|
|
|
NtStatus = DfsInitializePrefixTable( &pTable,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
return NtStatus;
|
|
}
|
|
|
|
NtStatus = DfsPrefixTableAcquireWriteLock( pTable);
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
printf("Unable to take prefix table lock, %x\n", NtStatus);
|
|
return NtStatus;
|
|
}
|
|
for (pLink = pRoot->pLinks; pLink != NULL; pLink = NEXT_LINK_OBJECT(pLink))
|
|
{
|
|
RtlInitUnicodeString(&LinkName, pLink->LinkObjectName);
|
|
NtStatus = DfsInsertInPrefixTableLocked( pTable,
|
|
&LinkName,
|
|
(PVOID)(pLink) );
|
|
if (NtStatus == STATUS_SUCCESS)
|
|
{
|
|
pLink->LinkObjectFlags |= IN_TABLE;
|
|
}
|
|
else {
|
|
printf(" AddRootToPrefixTable: Link %wZ, Status 0x%x\n, Links %d",
|
|
&LinkName, NtStatus, Links);
|
|
|
|
break;
|
|
}
|
|
Links++;
|
|
}
|
|
DfsPrefixTableReleaseLock(pTable);
|
|
*ppTable = pTable;
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
DeletePrefixTable(
|
|
struct _DFS_PREFIX_TABLE *pTable,
|
|
PROOT_DEF pRoot )
|
|
{
|
|
PLINK_DEF pLink;
|
|
NTSTATUS NtStatus;
|
|
UNICODE_STRING LinkName;
|
|
|
|
|
|
NtStatus = DfsPrefixTableAcquireWriteLock( pTable);
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
printf("Unable to take prefix table lock, %x\n", NtStatus);
|
|
return NtStatus;
|
|
}
|
|
for (pLink = pRoot->pLinks; pLink != NULL; pLink = NEXT_LINK_OBJECT(pLink))
|
|
{
|
|
if ((pLink->LinkObjectFlags & IN_TABLE) == TRUE)
|
|
{
|
|
RtlInitUnicodeString(&LinkName, pLink->LinkObjectName);
|
|
NtStatus = DfsRemoveFromPrefixTableLocked( pTable,
|
|
&LinkName,
|
|
(PVOID)(pLink) );
|
|
if (NtStatus == STATUS_SUCCESS)
|
|
{
|
|
pLink->LinkObjectFlags &= ~IN_TABLE;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DfsPrefixTableReleaseLock(pTable);
|
|
DfsDereferencePrefixTable( pTable );
|
|
|
|
return NtStatus;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLINK_DEF
|
|
GetLinkEntry(
|
|
struct _DFS_PREFIX_TABLE *pTable,
|
|
LPWSTR NameString )
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING Name;
|
|
UNICODE_STRING Suffix;
|
|
PLINK_DEF pLink;
|
|
|
|
RtlInitUnicodeString( &Name, NameString );
|
|
|
|
Status = DfsFindUnicodePrefixLocked( pTable,
|
|
&Name,
|
|
&Suffix,
|
|
&pLink,
|
|
NULL );
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
return pLink;
|
|
}
|
|
|
|
if (Status != STATUS_OBJECT_PATH_NOT_FOUND)
|
|
{
|
|
printf("GetLinkEntry: unexpected status %x\n", Status);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
PTARGET_DEF
|
|
GetTargetEntry(
|
|
PLINK_DEF pLink,
|
|
LPWSTR ServerName,
|
|
LPWSTR ShareName )
|
|
{
|
|
PTARGET_DEF pTarget, pReturn = NULL;
|
|
UNICODE_STRING TargetName;
|
|
DFSSTATUS Status;
|
|
|
|
Status = DfsCreateUnicodePathString( &TargetName,
|
|
2, // unc path: 2 leading sep.
|
|
ServerName,
|
|
ShareName );
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
printf("GetTargetEntry: failed to create string\n");
|
|
return NULL;
|
|
}
|
|
|
|
for (pTarget = pLink->LinkObjectTargets; pTarget != NULL; pTarget = pTarget->NextTarget)
|
|
{
|
|
if (_wcsicmp(TargetName.Buffer, pTarget->Name) == 0)
|
|
{
|
|
pReturn = pTarget;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
DfsFreeUnicodeString(&TargetName);
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
|
|
PLINK_DEF
|
|
MergeLinkInfo(
|
|
PDFS_INFO_4 pBuf,
|
|
struct _DFS_PREFIX_TABLE *pPrefixTable )
|
|
{
|
|
PLINK_DEF pLink, pReturn = NULL;
|
|
DWORD i;
|
|
PDFS_STORAGE_INFO pStorage;
|
|
UNICODE_STRING LinkName, ServerName, ShareName, Remains;
|
|
DFSSTATUS Status;
|
|
PTARGET_DEF pTargetList = NULL, pTarget;
|
|
|
|
RtlInitUnicodeString( &LinkName, pBuf->EntryPath);
|
|
Status = DfsGetPathComponents(&LinkName,
|
|
&ServerName,
|
|
&ShareName,
|
|
&Remains);
|
|
|
|
if (Remains.Length == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
if ((pLink = GetLinkEntry(pPrefixTable,
|
|
Remains.Buffer)) == NULL)
|
|
{
|
|
pLink = CreateNewLinkEntry(Remains.Buffer);
|
|
UpdateLinkEntry( pLink, pBuf->State, pBuf->Timeout, pBuf->Comment);
|
|
pReturn = pLink;
|
|
}
|
|
|
|
SetObjectInNameSpace(pLink);
|
|
for(i = 0, pStorage = pBuf->Storage;
|
|
i < pBuf->NumberOfStorages;
|
|
i++, pStorage = pBuf->Storage+i) {
|
|
|
|
if ((pTarget = GetTargetEntry(pLink,
|
|
pStorage->ServerName,
|
|
pStorage->ShareName)) == NULL)
|
|
{
|
|
pTarget = CreateNewTargetEntry(pStorage->ServerName,
|
|
pStorage->ShareName,
|
|
pStorage->State);
|
|
if (pTargetList == NULL)
|
|
{
|
|
pTargetList = pLink->LinkObjectTargets;
|
|
}
|
|
|
|
pTarget->NextTarget = pTargetList;
|
|
pTargetList = pTarget;
|
|
}
|
|
SetInNameSpace(pTarget);
|
|
}
|
|
if (pTargetList != NULL)
|
|
{
|
|
pLink->LinkObjectTargets = pTargetList;
|
|
}
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
|