5394 lines
134 KiB
C++
5394 lines
134 KiB
C++
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Copyright (C) 1995, Microsoft Corporation
|
|||
|
//
|
|||
|
// File: dfsmsrv.cxx
|
|||
|
//
|
|||
|
// Contents: The server side stubs for the Dfs Manager Admin RPC interface
|
|||
|
//
|
|||
|
// Classes:
|
|||
|
//
|
|||
|
// Functions: GetDfsVolumeFromPath --
|
|||
|
// AddReplica --
|
|||
|
// RemoveReplica --
|
|||
|
// Delete --
|
|||
|
// SetComment --
|
|||
|
// GetInfo --
|
|||
|
// Move --
|
|||
|
// Rename --
|
|||
|
// CreateChild --
|
|||
|
// GetReplicaSetID --
|
|||
|
// SetReplicaSetID --
|
|||
|
// ChangeStorageID --
|
|||
|
// SetReplicaState --
|
|||
|
// SetVolumeState --
|
|||
|
//
|
|||
|
// History: 12-27-95 Milans Created.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
//#include <ntos.h>
|
|||
|
//#include <ntrtl.h>
|
|||
|
//#include <nturtl.h>
|
|||
|
//#include <dfsfsctl.h>
|
|||
|
//#include <windows.h>
|
|||
|
|
|||
|
|
|||
|
#include <headers.hxx>
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
extern "C" {
|
|||
|
#include "dfspriv.h" // For I_NetDfsXXX calls
|
|||
|
#include <dfsmsrv.h>
|
|||
|
#include <srvfsctl.h>
|
|||
|
#include <icanon.h>
|
|||
|
#include <validc.h>
|
|||
|
#include <winldap.h>
|
|||
|
#include <dsrole.h>
|
|||
|
}
|
|||
|
|
|||
|
extern "C" {
|
|||
|
|
|||
|
DWORD
|
|||
|
DfsGetFtServersFromDs(
|
|||
|
IN PVOID pLDAP OPTIONAL,
|
|||
|
IN LPWSTR wszDomainName OPTIONAL,
|
|||
|
IN LPWSTR wszDfsName,
|
|||
|
OUT LPWSTR **List
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
NetrDfsEnum200(
|
|||
|
IN DWORD Level,
|
|||
|
IN DWORD PrefMaxLen,
|
|||
|
IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
|
|||
|
IN OUT LPDWORD ResumeHandle
|
|||
|
);
|
|||
|
|
|||
|
#include "cdfsvol.hxx"
|
|||
|
#include "jnpt.hxx"
|
|||
|
#include "security.hxx"
|
|||
|
#include "registry.hxx"
|
|||
|
#include "setup.hxx"
|
|||
|
#include "ftsup.hxx"
|
|||
|
#include "dfsmwml.h"
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
DfspGetOneEnumInfo(
|
|||
|
DWORD i,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray,
|
|||
|
LPDWORD InfoSize,
|
|||
|
LPDWORD ResumeHandle);
|
|||
|
|
|||
|
DWORD
|
|||
|
DfspGetOneEnumInfoEx(
|
|||
|
PDFS_VOLUME_LIST pDfsVolList,
|
|||
|
DWORD i,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray,
|
|||
|
LPDWORD InfoSize);
|
|||
|
|
|||
|
VOID
|
|||
|
DfspFreeOneEnumInfo(
|
|||
|
DWORD i,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray);
|
|||
|
|
|||
|
DWORD
|
|||
|
DfspAllocateRelationInfo(
|
|||
|
PDFS_PKT_RELATION_INFO pDfsRelationInfo,
|
|||
|
LPDFSM_RELATION_INFO *ppRelationInfo);
|
|||
|
|
|||
|
DWORD
|
|||
|
DfsManagerRemoveServiceForced(
|
|||
|
LPWSTR wszServerName,
|
|||
|
LPWSTR wszDCName,
|
|||
|
LPWSTR wszFtDfsName);
|
|||
|
|
|||
|
DWORD
|
|||
|
InitializeDfsManager(void);
|
|||
|
|
|||
|
VOID
|
|||
|
GetDebugSwitches();
|
|||
|
|
|||
|
VOID
|
|||
|
GetConfigSwitches();
|
|||
|
|
|||
|
extern HANDLE hSyncEvent;
|
|||
|
extern ULONG DcLockIntervalInMs;
|
|||
|
extern PLDAP pLdapConnection;
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NormalizeEntryPath
|
|||
|
//
|
|||
|
// Synopsis: Normalizes an EntryPath argument to a prefix.
|
|||
|
//
|
|||
|
// Arguments: [pwszEntryPath] -- The entry path to normalize.
|
|||
|
//
|
|||
|
// Returns: If pwszEntryPath is a UNC path, this routine returns
|
|||
|
// &pwszEntryPath[1]; if pwszEntryPath starts with a backslash,
|
|||
|
// this routine returns pwszEntryPath. In all other cases, this
|
|||
|
// routine returns NULL.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
LPWSTR
|
|||
|
NormalizeEntryPath(
|
|||
|
IN LPWSTR pwszEntryPath)
|
|||
|
{
|
|||
|
LPWSTR pwszEntryPathCanon;
|
|||
|
DWORD Type = 0;
|
|||
|
DWORD dwErr;
|
|||
|
ULONG Size = wcslen(pwszEntryPath) + 1;
|
|||
|
WCHAR *wCp;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NormalizeEntryPath(%ws)\n", pwszEntryPath);
|
|||
|
#endif
|
|||
|
|
|||
|
if (pwszEntryPath == NULL)
|
|||
|
return( NULL );
|
|||
|
|
|||
|
if (wcslen(pwszEntryPath) < 2)
|
|||
|
return( NULL );
|
|||
|
|
|||
|
if (pwszEntryPath[0] != UNICODE_PATH_SEP)
|
|||
|
return( NULL );
|
|||
|
|
|||
|
pwszEntryPathCanon = new WCHAR [ Size ];
|
|||
|
|
|||
|
if (pwszEntryPathCanon == NULL)
|
|||
|
return( NULL );
|
|||
|
|
|||
|
dwErr = I_NetPathCanonicalize(
|
|||
|
NULL,
|
|||
|
pwszEntryPath,
|
|||
|
pwszEntryPathCanon,
|
|||
|
Size * sizeof(WCHAR),
|
|||
|
NULL,
|
|||
|
&Type,
|
|||
|
0);
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NormalizeEntryPath:pwszEntryPathCanon:%ws)\n", pwszEntryPathCanon);
|
|||
|
#endif
|
|||
|
|
|||
|
if (dwErr != 0 || (Type != ITYPE_UNC && Type != (ITYPE_PATH | ITYPE_ABSOLUTE))) {
|
|||
|
|
|||
|
delete [] pwszEntryPathCanon;
|
|||
|
return( NULL );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_SERVER) {
|
|||
|
|
|||
|
if (pwszDfsRootName == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
wcscpy(pwszEntryPath, UNICODE_PATH_SEP_STR);
|
|||
|
wcscat(pwszEntryPath, pwszDfsRootName);
|
|||
|
|
|||
|
if (pwszEntryPathCanon[1] == UNICODE_PATH_SEP) {
|
|||
|
wCp = wcschr(&pwszEntryPathCanon[2], UNICODE_PATH_SEP);
|
|||
|
} else {
|
|||
|
wCp = wcschr(&pwszEntryPathCanon[1], UNICODE_PATH_SEP);
|
|||
|
}
|
|||
|
|
|||
|
if(wCp == NULL) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
wcscat(pwszEntryPath, wCp);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
if (pwszEntryPathCanon[1] == UNICODE_PATH_SEP) {
|
|||
|
wcscpy(pwszEntryPath, &pwszEntryPathCanon[1]);
|
|||
|
} else {
|
|||
|
wcscpy(pwszEntryPath, pwszEntryPathCanon);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
delete [] pwszEntryPathCanon;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NormalizeEntryPath returning %ws\n", pwszEntryPath);
|
|||
|
#endif
|
|||
|
|
|||
|
return( pwszEntryPath );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: FormFTDfsEntryPath
|
|||
|
//
|
|||
|
// Synopsis: When the NetDfsXXX APIs are used to administer an FTDfs, the
|
|||
|
// entry path passed in is of the form \servername\sharename\p
|
|||
|
// These first two components must be massaged to the form
|
|||
|
// \domainname\ftdfsname\p
|
|||
|
//
|
|||
|
// Arguments: [pwszEntryPath] -- The entry path to massage
|
|||
|
//
|
|||
|
// Returns: If successfully massaged the entry path, returns a pointer to
|
|||
|
// the newly allocated FTDfs entry path, else NULL
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
LPWSTR
|
|||
|
FormFTDfsEntryPath(
|
|||
|
IN LPWSTR pwszEntryPath)
|
|||
|
{
|
|||
|
LPWSTR pwszFTDfsPath;
|
|||
|
LPWSTR pwszRestOfPath;
|
|||
|
|
|||
|
if (pwszDomainName == NULL || pwszDfsRootName == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
if (pwszEntryPath[0] == UNICODE_PATH_SEP &&
|
|||
|
pwszEntryPath[1] == UNICODE_PATH_SEP) {
|
|||
|
pwszEntryPath++;
|
|||
|
}
|
|||
|
|
|||
|
pwszFTDfsPath = new WCHAR [
|
|||
|
wcslen(pwszEntryPath) +
|
|||
|
wcslen(UNICODE_PATH_SEP_STR) +
|
|||
|
wcslen(pwszDomainName) +
|
|||
|
wcslen(UNICODE_PATH_SEP_STR) +
|
|||
|
wcslen(pwszDfsRootName) ];
|
|||
|
|
|||
|
if (pwszFTDfsPath != NULL) {
|
|||
|
|
|||
|
wcscpy(pwszFTDfsPath, UNICODE_PATH_SEP_STR);
|
|||
|
wcscat(pwszFTDfsPath, pwszDomainName);
|
|||
|
wcscat(pwszFTDfsPath, UNICODE_PATH_SEP_STR);
|
|||
|
wcscat(pwszFTDfsPath, pwszDfsRootName);
|
|||
|
|
|||
|
//
|
|||
|
// Skip past the first three backslashes of the input parameter
|
|||
|
//
|
|||
|
|
|||
|
if (pwszEntryPath[0] != UNICODE_PATH_SEP)
|
|||
|
return NULL;
|
|||
|
|
|||
|
pwszRestOfPath = wcschr( &pwszEntryPath[1], UNICODE_PATH_SEP );
|
|||
|
|
|||
|
if (pwszRestOfPath == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
pwszRestOfPath = wcschr( &pwszRestOfPath[1], UNICODE_PATH_SEP );
|
|||
|
|
|||
|
if (pwszRestOfPath != NULL)
|
|||
|
wcscat(pwszFTDfsPath, pwszRestOfPath );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("FormFTDfsEntryPath(%ws->%ws)\n", pwszEntryPath, pwszFTDfsPath);
|
|||
|
#endif
|
|||
|
|
|||
|
return( pwszFTDfsPath );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: FormStdDfsEntryPath
|
|||
|
//
|
|||
|
// Synopsis: When the NetDfsXXX APIs are used to administer an StdDfs, the
|
|||
|
// entry path passed in may be of the form \somename\dfsname.
|
|||
|
// The first component must be normalized if possible
|
|||
|
// to the computer name.
|
|||
|
//
|
|||
|
// Arguments: [pwszEntryPath] -- The entry path to normalize
|
|||
|
//
|
|||
|
// Returns: If successfully normalized the entry path, returns a pointer to
|
|||
|
// the newly allocated entry path, else NULL
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
LPWSTR
|
|||
|
FormStdDfsEntryPath(
|
|||
|
IN LPWSTR pwszEntryPath)
|
|||
|
{
|
|||
|
LPWSTR pwszStdDfsPath;
|
|||
|
LPWSTR pwszRestOfPath;
|
|||
|
|
|||
|
if (pwszComputerName == NULL || pwszDfsRootName == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
if (pwszEntryPath[0] == UNICODE_PATH_SEP &&
|
|||
|
pwszEntryPath[1] == UNICODE_PATH_SEP) {
|
|||
|
pwszEntryPath++;
|
|||
|
}
|
|||
|
|
|||
|
pwszStdDfsPath = new WCHAR [
|
|||
|
wcslen(pwszEntryPath) +
|
|||
|
wcslen(UNICODE_PATH_SEP_STR) +
|
|||
|
wcslen(pwszComputerName) ];
|
|||
|
|
|||
|
if (pwszStdDfsPath != NULL) {
|
|||
|
|
|||
|
wcscpy(pwszStdDfsPath, UNICODE_PATH_SEP_STR);
|
|||
|
wcscat(pwszStdDfsPath, pwszComputerName);
|
|||
|
|
|||
|
//
|
|||
|
// Skip past the first two backslashes of the input parameter
|
|||
|
//
|
|||
|
|
|||
|
ASSERT(pwszEntryPath[0] == UNICODE_PATH_SEP);
|
|||
|
|
|||
|
pwszRestOfPath = wcschr( &pwszEntryPath[1], UNICODE_PATH_SEP );
|
|||
|
|
|||
|
if (pwszRestOfPath != NULL)
|
|||
|
wcscat(pwszStdDfsPath, pwszRestOfPath );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("FormStdDfsEntryPath(%ws->%ws)\n", pwszEntryPath, pwszStdDfsPath);
|
|||
|
#endif
|
|||
|
|
|||
|
return( pwszStdDfsPath );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetDfsVolumeFromPath
|
|||
|
//
|
|||
|
// Synopsis: Given a volume EntryPath, returns a CDfsVolume for that
|
|||
|
// volume.
|
|||
|
//
|
|||
|
// Arguments: [pwszEntryPath] -- EntryPath for which CDfsVolume is
|
|||
|
// desired.
|
|||
|
// [fExactMatch] -- If TRUE, this call will succeed only if
|
|||
|
// a volume object's EntryPath exactly matches
|
|||
|
// pwszEntryPath.
|
|||
|
// [ppCDfsVolume] -- On successful return, contains pointer to
|
|||
|
// newly allocated CDfsVolume for the EntryPath.
|
|||
|
//
|
|||
|
// Returns: [S_OK] -- Successfully returning new CDfsVolume.
|
|||
|
//
|
|||
|
// [E_OUTOFMEMORY] -- Out of memory creating new object.
|
|||
|
//
|
|||
|
// [DFS_E_NO_SUCH_VOLUME] -- Unable to find volume with
|
|||
|
// given EntryPath.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
GetDfsVolumeFromPath(
|
|||
|
LPWSTR pwszEntryPath,
|
|||
|
BOOLEAN fExactMatch,
|
|||
|
CDfsVolume **ppCDfsVolume)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
CDfsVolume *pCDfsVolume = NULL;
|
|||
|
LPWSTR pwszVolumeObject = NULL;
|
|||
|
|
|||
|
dwErr = GetVolObjForPath( pwszEntryPath, fExactMatch, &pwszVolumeObject );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
pCDfsVolume = new CDfsVolume();
|
|||
|
|
|||
|
if (pCDfsVolume != NULL) {
|
|||
|
|
|||
|
dwErr = pCDfsVolume->Load( pwszVolumeObject, 0 );
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
pCDfsVolume->Release();
|
|||
|
|
|||
|
pCDfsVolume = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
delete [] pwszVolumeObject;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*ppCDfsVolume = pCDfsVolume;
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsManagerGetVersion
|
|||
|
//
|
|||
|
// Synopsis: Returns the version of this server side implementation.
|
|||
|
//
|
|||
|
// Arguments: None.
|
|||
|
//
|
|||
|
// Returns: The version number.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
NetrDfsManagerGetVersion()
|
|||
|
{
|
|||
|
DWORD Version = 2;
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetVersion_Start, LOGNOTHING);
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsGetVersion()\n");
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetVersion_End, LOGULONG(Version));
|
|||
|
return( Version );
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsAdd (Obsolete)
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsAdd(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN LPWSTR Comment,
|
|||
|
IN DWORD Flags)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAdd_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
}
|
|||
|
else if (ulDfsManagerType == DFS_MANAGER_FTDFS){
|
|||
|
status = ERROR_NOT_SUPPORTED;
|
|||
|
}
|
|||
|
else {
|
|||
|
status = NetrDfsAdd2(
|
|||
|
DfsEntryPath,
|
|||
|
NULL,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
Comment,
|
|||
|
Flags,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAdd_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsAdd2
|
|||
|
//
|
|||
|
// Synopsis: Adds a volume/replica/link to this Dfs.
|
|||
|
//
|
|||
|
// Arguments: [DfsEntryPath] -- Entry Path of volume/link to be created, or
|
|||
|
// to which a replica should be added.
|
|||
|
// [DcName] -- Name of Dc to use
|
|||
|
// [ServerName] -- Name of server backing the volume.
|
|||
|
// [ShareName] -- Name of share on ServerName backing the volume.
|
|||
|
// [Comment] -- Comment associated with this volume, only used
|
|||
|
// when DFS_ADD_VOLUME is specified.
|
|||
|
// [Flags] -- If DFS_ADD_VOLUME, a new volume will be created.
|
|||
|
// If DFS_ADD_LINK, a new link to another Dfs will be
|
|||
|
// create. If 0, a replica will be added.
|
|||
|
// [ppRootList] -- On success, returns a list of roots that need to be
|
|||
|
// informed of the change in the DS object
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to a
|
|||
|
// existing Dfs volume.
|
|||
|
//
|
|||
|
// [NERR_DfsVolumeAlreadyExists] -- DFS_ADD_VOLUME was specified
|
|||
|
// and a volume with DfsEntryPath already exists.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- An internal database
|
|||
|
// corruption was encountered while executing this
|
|||
|
// operation.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsAdd2(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN LPWSTR Comment,
|
|||
|
IN DWORD Flags,
|
|||
|
IN PDFSM_ROOT_LIST *ppRootList)
|
|||
|
{
|
|||
|
NET_API_STATUS status = NERR_Success;
|
|||
|
CDfsVolume *pDfsVol = NULL;
|
|||
|
DFS_REPLICA_INFO replInfo;
|
|||
|
DWORD dwVersion;
|
|||
|
DWORD dwVolType;
|
|||
|
DWORD shareType = 0;
|
|||
|
DWORD dwErr;
|
|||
|
LPWSTR realShareName;
|
|||
|
BOOLEAN modifiedShareName = FALSE;
|
|||
|
LPDFS_SITELIST_INFO pSiteInfo;
|
|||
|
LPWSTR OrgDfsEntryPath = DfsEntryPath;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsAdd2(%ws,%ws,%ws,%ws,%ws,%d,0x%x)\n",
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
Comment,
|
|||
|
Flags,
|
|||
|
ppRootList);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAdd2_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if ( (Flags & ~(DFS_ADD_VOLUME | DFS_RESTORE_VOLUME)) != 0) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath == NULL || DfsEntryPath[0] != UNICODE_PATH_SEP){
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
#if 0 // Broken for DNS names
|
|||
|
DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
|
|||
|
#endif
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint(" 0:DfsEntryPath=[%ws]\n", DfsEntryPath);
|
|||
|
DbgPrint(" 0:ServerName=[%ws]\n", ServerName);
|
|||
|
DbgPrint(" 0:ShareName=[%ws]\n", ShareName);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEntryPath != NULL) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
|
|||
|
else if (ulDfsManagerType == DFS_MANAGER_SERVER)
|
|||
|
DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
|
|||
|
|
|||
|
if (DfsEntryPath == NULL) {
|
|||
|
status = ERROR_OUTOFMEMORY;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint(" 1:ServerName=[%ws]\n", ServerName);
|
|||
|
DbgPrint(" 1:ShareName=[%ws]\n", ShareName);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEntryPath == NULL ||
|
|||
|
ServerName == NULL ||
|
|||
|
ShareName == NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != NULL && DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL ||
|
|||
|
ShareName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
if (DcName != NULL)
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
LdapIncrementBlob();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We next determine whether this is going to be an interdomain link or
|
|||
|
// not. While doing so, we'll also check for certain cases of cyclical
|
|||
|
// references.
|
|||
|
//
|
|||
|
|
|||
|
if (I_NetDfsIsThisADomainName(ServerName) == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS &&
|
|||
|
pwszDfsRootName != NULL &&
|
|||
|
(_wcsicmp( ServerName, pwszDfsRootName) == 0)){
|
|||
|
status = NERR_DfsCyclicalName;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsAdd2_Error1,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
}
|
|||
|
else
|
|||
|
dwVolType = DFS_VOL_TYPE_REFERRAL_SVC | DFS_VOL_TYPE_INTER_DFS;
|
|||
|
|
|||
|
} else if (Flags & DFS_RESTORE_VOLUME) {
|
|||
|
|
|||
|
dwVolType = DFS_VOL_TYPE_DFS;
|
|||
|
|
|||
|
shareType = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Server name passed in is a real server. See if what kind of share
|
|||
|
// we are talking about.
|
|||
|
//
|
|||
|
|
|||
|
PSHARE_INFO_1005 shi1005;
|
|||
|
|
|||
|
realShareName = wcschr(ShareName, UNICODE_PATH_SEP);
|
|||
|
|
|||
|
if (realShareName != NULL) {
|
|||
|
*realShareName = UNICODE_NULL;
|
|||
|
modifiedShareName = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
status = NetShareGetInfo(
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
1005,
|
|||
|
(PBYTE *) &shi1005);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, NetrDfsAdd2_Error_NetShareGetInfo,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
if (modifiedShareName)
|
|||
|
*realShareName = UNICODE_PATH_SEP;
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
shareType = shi1005->shi1005_flags;
|
|||
|
|
|||
|
NetApiBufferFree( shi1005 );
|
|||
|
}
|
|||
|
|
|||
|
if (status != NERR_NetNameNotFound)
|
|||
|
status = NERR_Success;
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
if (shareType & SHI1005_FLAGS_DFS_ROOT) {
|
|||
|
|
|||
|
//
|
|||
|
// If this is a server based Dfs, make sure we are not creating
|
|||
|
// a cyclical link to our root share. Since there is only one
|
|||
|
// share per server that can be a Dfs Root, it is sufficient to
|
|||
|
// see if the machine names match.
|
|||
|
//
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_SERVER &&
|
|||
|
pwszDfsRootName != NULL &&
|
|||
|
(_wcsicmp( ServerName, pwszDfsRootName) == 0)) {
|
|||
|
status = NERR_DfsCyclicalName;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsAdd2_Error2,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
}
|
|||
|
else
|
|||
|
dwVolType = DFS_VOL_TYPE_REFERRAL_SVC |
|
|||
|
DFS_VOL_TYPE_INTER_DFS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwVolType = DFS_VOL_TYPE_DFS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Great, the parameters look semi-reasonable, lets do the work.
|
|||
|
//
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
if ((Flags & DFS_ADD_VOLUME) == 0) {
|
|||
|
|
|||
|
status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Add volume or link case, so we don't want an exact match.
|
|||
|
// Note that if the Dfs Volume returned does indeed match exactly,
|
|||
|
// its ok, because the subsequent CreateChild operation will fail.
|
|||
|
//
|
|||
|
|
|||
|
status = GetDfsVolumeFromPath( DfsEntryPath, FALSE, &pDfsVol );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
|
|||
|
pDfsVol = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Create a DFS_REPLICA_INFO struct for this server-share...
|
|||
|
//
|
|||
|
|
|||
|
ZeroMemory( &replInfo, sizeof(replInfo) );
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint(" 2:ServerName=[%ws]\n", ServerName);
|
|||
|
DbgPrint(" 2:ShareName=[%ws]\n", ShareName);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
replInfo.ulReplicaType = DFS_STORAGE_TYPE_NONDFS;
|
|||
|
replInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
|
|||
|
replInfo.pwszServerName = ServerName;
|
|||
|
replInfo.pwszShareName = ShareName;
|
|||
|
|
|||
|
//
|
|||
|
// and carry out the Add operation.
|
|||
|
//
|
|||
|
|
|||
|
if ((Flags & DFS_ADD_VOLUME) != 0) {
|
|||
|
|
|||
|
status = pDfsVol->CreateChild(
|
|||
|
DfsEntryPath,
|
|||
|
dwVolType,
|
|||
|
&replInfo,
|
|||
|
Comment,
|
|||
|
DFS_NORMAL_FORCE);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = pDfsVol->AddReplica( &replInfo, 0 );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
//
|
|||
|
// Find out the list of covered sites
|
|||
|
// Note we use dwErr as the return code,
|
|||
|
// because we don't care if this fails - a downlevel
|
|||
|
// server won't respond.
|
|||
|
//
|
|||
|
|
|||
|
pSiteInfo = NULL;
|
|||
|
|
|||
|
dwErr = I_NetDfsManagerReportSiteInfo(
|
|||
|
ServerName,
|
|||
|
&pSiteInfo);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR, NetrDfsAdd2_Error_I_NetDfsManagerReportSiteInfo,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
//
|
|||
|
// Create a SiteTable object with those sites
|
|||
|
//
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (pSiteInfo->cSites > 0) {
|
|||
|
|
|||
|
//
|
|||
|
// AddRef the site table, then put the site info in, then
|
|||
|
// Release it. This will cause it to be written to the
|
|||
|
// appropriate store (ldap or registry).
|
|||
|
//
|
|||
|
|
|||
|
pDfsmSites->AddRef();
|
|||
|
|
|||
|
pDfsmSites->AddOrUpdateSiteInfo(
|
|||
|
ServerName,
|
|||
|
pSiteInfo->cSites,
|
|||
|
&pSiteInfo->Site[0]);
|
|||
|
pDfsmSites->Release();
|
|||
|
}
|
|||
|
|
|||
|
NetApiBufferFree(pSiteInfo);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This writes the dfs-link info back
|
|||
|
// to
|
|||
|
// (1) the registry if stddfs
|
|||
|
// or
|
|||
|
// (2) the in-memory unmarshalled pkt blob which
|
|||
|
// will still need to go to the DS.
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsVol != NULL) {
|
|||
|
pDfsVol->Release();
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
// if we can't write to the DS we get an error
|
|||
|
// but don't mask any previous errors...
|
|||
|
NET_API_STATUS NewStatus;
|
|||
|
NewStatus = LdapDecrementBlob();
|
|||
|
if(status == NERR_Success){
|
|||
|
status = NewStatus;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Create list of roots to redirect to this DC
|
|||
|
//
|
|||
|
|
|||
|
if (status == NERR_Success &&
|
|||
|
DcName != NULL &&
|
|||
|
ulDfsManagerType == DFS_MANAGER_FTDFS
|
|||
|
) {
|
|||
|
DfspCreateRootList(
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ppRootList);
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsAdd2 returning %d\n", status);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAdd2_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsAddFtRoot
|
|||
|
//
|
|||
|
// Synopsis: Creates a new FtDfs, or joins a Server into an FtDfs at the root
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server backing the volume.
|
|||
|
// [DcName] -- DC to use
|
|||
|
// [RootShare] -- Name of share on ServerName backing the volume.
|
|||
|
// [FtDfsName] -- The Name of the FtDfs to create/join
|
|||
|
// [Comment] -- Comment associated with this root.
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
// [ppRootList] -- On success, returns a list of roots that need to be
|
|||
|
// informed of the change in the DS object
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- An internal database
|
|||
|
// corruption was encountered while executing this
|
|||
|
// operation.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsAddFtRoot(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR RootShare,
|
|||
|
IN LPWSTR FtDfsName,
|
|||
|
IN LPWSTR Comment,
|
|||
|
IN LPWSTR ConfigDN,
|
|||
|
IN BOOLEAN NewFtDfs,
|
|||
|
IN DWORD Flags,
|
|||
|
IN PDFSM_ROOT_LIST *ppRootList)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
ULONG i;
|
|||
|
WCHAR wszFullObjectName[MAX_PATH];
|
|||
|
WCHAR wszComputerName[MAX_PATH];
|
|||
|
WCHAR wszDomainName[MAX_PATH];
|
|||
|
HKEY hkey;
|
|||
|
DFS_NAME_CONVENTION NameType;
|
|||
|
PDFSM_ROOT_LIST pRootList = NULL;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsAddFtRoot(%ws,%ws,%ws,%ws,%ws,%ws,0x%x,0x%x)\n",
|
|||
|
ServerName,
|
|||
|
DcName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
Comment,
|
|||
|
ConfigDN,
|
|||
|
NewFtDfs,
|
|||
|
Flags);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddFtRoot_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(FtDfsName)
|
|||
|
LOGWSTR(ConfigDN));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (
|
|||
|
ServerName == NULL ||
|
|||
|
DcName == NULL ||
|
|||
|
RootShare == NULL ||
|
|||
|
FtDfsName == NULL ||
|
|||
|
Comment == NULL ||
|
|||
|
ConfigDN == NULL
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (
|
|||
|
ServerName[0] == UNICODE_NULL ||
|
|||
|
DcName[0] == UNICODE_NULL ||
|
|||
|
RootShare[0] == UNICODE_NULL ||
|
|||
|
FtDfsName[0] == UNICODE_NULL ||
|
|||
|
ConfigDN[0] == UNICODE_NULL
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get our computer and domain names
|
|||
|
//
|
|||
|
NameType = DFS_NAMETYPE_DNS;
|
|||
|
dwErr = GetDomAndComputerName( wszDomainName, wszComputerName, &NameType);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS){
|
|||
|
goto cleanup;
|
|||
|
//return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Ensure the syntax of FtDfsName is reasonable
|
|||
|
//
|
|||
|
|
|||
|
if( wcslen( FtDfsName ) > NNLEN ||
|
|||
|
wcscspn( FtDfsName, ILLEGAL_NAME_CHARS_STR ) != wcslen( FtDfsName ) ) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_NAME;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Already a root?
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
LdapIncrementBlob();
|
|||
|
|
|||
|
//
|
|||
|
// Update pKT (blob) attribute
|
|||
|
//
|
|||
|
|
|||
|
dwErr = SetupFtDfs(
|
|||
|
wszComputerName,
|
|||
|
wszDomainName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
Comment,
|
|||
|
ConfigDN,
|
|||
|
NewFtDfs,
|
|||
|
Flags);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("SetupFtDfs() returned %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Reset dfs
|
|||
|
//
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmInitLocalPartitions();
|
|||
|
InitializeDfsManager();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Something went wrong - remove all the stuff we set up
|
|||
|
//
|
|||
|
|
|||
|
if (*ppRootList != NULL) {
|
|||
|
pRootList = *ppRootList;
|
|||
|
for (i = 0; i< pRootList->cEntries; i++)
|
|||
|
if (pRootList->Entry[i].ServerShare != NULL)
|
|||
|
MIDL_user_free(pRootList->Entry[i].ServerShare);
|
|||
|
MIDL_user_free(pRootList);
|
|||
|
*ppRootList = NULL;
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(wszFullObjectName, LDAP_VOLUMES_DIR);
|
|||
|
wcscat(wszFullObjectName, DOMAIN_ROOT_VOL);
|
|||
|
|
|||
|
DfsManagerRemoveService(
|
|||
|
wszFullObjectName,
|
|||
|
wszComputerName);
|
|||
|
|
|||
|
|
|||
|
if (*ppRootList != NULL) {
|
|||
|
pRootList = *ppRootList;
|
|||
|
for (i = 0; i < pRootList->cEntries; i++)
|
|||
|
if (pRootList->Entry[i].ServerShare != NULL)
|
|||
|
MIDL_user_free(pRootList->Entry[i].ServerShare);
|
|||
|
MIDL_user_free(pRootList);
|
|||
|
*ppRootList = NULL;
|
|||
|
}
|
|||
|
|
|||
|
DfsRemoveRoot();
|
|||
|
DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER);
|
|||
|
|
|||
|
//
|
|||
|
// Tell dfs.sys to discard all state
|
|||
|
//
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
{
|
|||
|
// don't mask the previous errors!!!!
|
|||
|
DWORD dwErr2;
|
|||
|
dwErr2 = LdapDecrementBlob();
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
dwErr = dwErr2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Everything went okay.
|
|||
|
// Update remoteServerName attribute
|
|||
|
//
|
|||
|
|
|||
|
dwErr = DfspCreateFtDfsDsObj(
|
|||
|
wszComputerName,
|
|||
|
DcName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
ppRootList);
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfspCreateFtDfsDsObj() returned %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
dwErr = ERROR_ALREADY_EXISTS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsAddFtRoot returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddFtRoot_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(FtDfsName)
|
|||
|
LOGWSTR(ConfigDN));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsGetDcAddress
|
|||
|
//
|
|||
|
// Synopsis: Gets the DC to go to so that we can create an FtDfs object for
|
|||
|
// this server.
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server backing the volume.
|
|||
|
// [DcName] -- Dc to use
|
|||
|
// [IsRoot] -- TRUE if this server is a Dfs root, FALSE otherwise
|
|||
|
// [Timeout] -- Timeout, in sec, that the server will stay with this DC
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- An internal database
|
|||
|
// corruption was encountered while executing this
|
|||
|
// operation.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsGetDcAddress(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN OUT LPWSTR *DcName,
|
|||
|
IN OUT BOOLEAN *IsRoot,
|
|||
|
IN OUT ULONG *Timeout)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
HKEY hkey;
|
|||
|
WCHAR *wszDCName;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsGetDcAddress(%ws)\n", ServerName);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsGetDcAddress_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (
|
|||
|
ServerName == NULL ||
|
|||
|
DcName == NULL ||
|
|||
|
IsRoot == NULL ||
|
|||
|
Timeout == NULL
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in root flag
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
*IsRoot = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
*IsRoot = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("IsRoot=%ws\n", *IsRoot == TRUE ? L"TRUE" : L"FALSE");
|
|||
|
#endif
|
|||
|
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
if (pwszDSMachineName == NULL) {
|
|||
|
|
|||
|
dwErr = GetDcName( NULL, 1, &wszDCName );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
DfsManagerSetDcName(&wszDCName[2]);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
*DcName = (LPWSTR) MIDL_user_allocate((wcslen(pwszDSMachineName)+1) * sizeof(WCHAR));
|
|||
|
if (*DcName != NULL) {
|
|||
|
wcscpy(*DcName,pwszDSMachineName);
|
|||
|
} else {
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*Timeout = DcLockIntervalInMs / 1000;
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsGetDcAddress returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsGetDcAddress_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(*DcName)
|
|||
|
LOGBOOLEAN(*IsRoot)
|
|||
|
LOGULONG(*Timeout)
|
|||
|
);
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsSetDcAddress
|
|||
|
//
|
|||
|
// Synopsis: Sets the DC to go to for the dfs blob
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server backing the volume.
|
|||
|
// [DcName] -- Dc to use
|
|||
|
// [Timeout] -- Time, in sec, to stay with that DC
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsSetDcAddress(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN ULONG Timeout,
|
|||
|
IN DWORD Flags)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsSetDcAddress(%ws,%ws,%d,0x%x)\n",
|
|||
|
ServerName,
|
|||
|
DcName,
|
|||
|
Timeout,
|
|||
|
Flags);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsSetDcAddress_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName == NULL || DcName == NULL) {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL || DcName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
|
|||
|
if ((Flags & NET_DFS_SETDC_TIMEOUT) != 0) {
|
|||
|
DcLockIntervalInMs = Timeout * 1000;
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
if (Flags & NET_DFS_SETDC_INITPKT) {
|
|||
|
SetEvent(hSyncEvent);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsSetDcAddress returning SUCCESS\n");
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsSetDcAddress_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName));
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsFlushFtTable
|
|||
|
//
|
|||
|
// Synopsis: Flushes an FtDfs entry from the FtDfs cache
|
|||
|
//
|
|||
|
// Arguments: [DcName] -- Dc to use
|
|||
|
// [FtDfsName] -- Name of FtDfs
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsFlushFtTable(
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR FtDfsName)
|
|||
|
{
|
|||
|
ULONG Size;
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
NTSTATUS Status;
|
|||
|
PDFS_DELETE_SPECIAL_INFO_ARG pSpcDelArg;
|
|||
|
OBJECT_ATTRIBUTES objectAttributes;
|
|||
|
IO_STATUS_BLOCK IoStatus;
|
|||
|
HANDLE dfsHandle = NULL;
|
|||
|
UNICODE_STRING SrvName;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsFlushFtTable_Start,
|
|||
|
LOGSTATUS(Status)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(FtDfsName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
Status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (DcName == NULL || FtDfsName == NULL) {
|
|||
|
|
|||
|
Status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (DcName[0] == UNICODE_NULL || FtDfsName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
Status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
Size = sizeof(DFS_DELETE_SPECIAL_INFO_ARG) +
|
|||
|
wcslen(FtDfsName) * sizeof(WCHAR);
|
|||
|
|
|||
|
pSpcDelArg = (PDFS_DELETE_SPECIAL_INFO_ARG) malloc(Size);
|
|||
|
|
|||
|
if (pSpcDelArg != NULL) {
|
|||
|
|
|||
|
WCHAR *wCp;
|
|||
|
|
|||
|
RtlZeroMemory(pSpcDelArg, Size);
|
|||
|
|
|||
|
wCp = (WCHAR *)((PCHAR)pSpcDelArg + sizeof(DFS_DELETE_SPECIAL_INFO_ARG));
|
|||
|
pSpcDelArg->SpecialName.Buffer = (PWCHAR)sizeof(DFS_DELETE_SPECIAL_INFO_ARG);
|
|||
|
pSpcDelArg->SpecialName.Length = wcslen(FtDfsName) * sizeof(WCHAR);
|
|||
|
pSpcDelArg->SpecialName.MaximumLength = pSpcDelArg->SpecialName.Length;
|
|||
|
RtlCopyMemory(wCp, FtDfsName, pSpcDelArg->SpecialName.Length);
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
RtlInitUnicodeString(&SrvName, DFS_SERVER_NAME);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&objectAttributes,
|
|||
|
&SrvName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
Status = NtCreateFile(
|
|||
|
&dfsHandle,
|
|||
|
SYNCHRONIZE | FILE_WRITE_DATA,
|
|||
|
&objectAttributes,
|
|||
|
&IoStatus,
|
|||
|
NULL,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|||
|
FILE_OPEN_IF,
|
|||
|
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
|
|||
|
NULL,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(Status, ALL_ERROR, NetrDfsFlushFtTable_Error_NtCreateFile,
|
|||
|
LOGSTATUS(Status)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(FtDfsName));
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
NtFsControlFile(
|
|||
|
dfsHandle,
|
|||
|
NULL, // Event,
|
|||
|
NULL, // ApcRoutine,
|
|||
|
NULL, // ApcContext,
|
|||
|
&IoStatus,
|
|||
|
FSCTL_DFS_DELETE_FTDFS_INFO,
|
|||
|
pSpcDelArg,
|
|||
|
Size,
|
|||
|
NULL,
|
|||
|
0);
|
|||
|
|
|||
|
NtClose(dfsHandle);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
free(pSpcDelArg);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
dwErr = ERROR_NOT_FOUND;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsFlushFtTable_Start,
|
|||
|
LOGSTATUS(Status)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(FtDfsName));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsAddStdRoot
|
|||
|
//
|
|||
|
// Synopsis: Creates a new Std Dfs
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server backing the volume.
|
|||
|
// [RootShare] -- Name of share on ServerName backing the volume.
|
|||
|
// [Comment] -- Comment associated with this root.
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- An internal database
|
|||
|
// corruption was encountered while executing this
|
|||
|
// operation.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsAddStdRoot(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR RootShare,
|
|||
|
IN LPWSTR Comment,
|
|||
|
IN DWORD Flags)
|
|||
|
{
|
|||
|
WCHAR wszComputerName[MAX_PATH+1];
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
HKEY hkey;
|
|||
|
DFS_NAME_CONVENTION NameType;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRoot_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName == NULL || RootShare == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL || RootShare[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get our computer name
|
|||
|
//
|
|||
|
NameType = DFS_NAMETYPE_EITHER;
|
|||
|
// NameType = DFS_NAMETYPE_NETBIOS;
|
|||
|
dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS){
|
|||
|
goto cleanup;
|
|||
|
//return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Already a root?
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
dwErr = SetupStdDfs(
|
|||
|
wszComputerName,
|
|||
|
RootShare,
|
|||
|
Comment,
|
|||
|
Flags,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Reset dfs
|
|||
|
//
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmInitLocalPartitions();
|
|||
|
InitializeDfsManager();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
dwErr = ERROR_ALREADY_EXISTS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRoot_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsAddStdRootForced
|
|||
|
//
|
|||
|
// Synopsis: Creates a new Std Dfs
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server backing the volume.
|
|||
|
// [RootShare] -- Name of share on ServerName backing the volume.
|
|||
|
// [Comment] -- Comment associated with this root.
|
|||
|
// [Share] -- drive:\dir behind the share
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- An internal database
|
|||
|
// corruption was encountered while executing this
|
|||
|
// operation.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsAddStdRootForced(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR RootShare,
|
|||
|
IN LPWSTR Comment,
|
|||
|
IN LPWSTR Share)
|
|||
|
{
|
|||
|
WCHAR wszComputerName[MAX_PATH+1];
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
HKEY hkey;
|
|||
|
DFS_NAME_CONVENTION NameType;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRootForced_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(Share));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName == NULL || RootShare == NULL || Share == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL || RootShare[0] == UNICODE_NULL || Share[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get our computer name
|
|||
|
//
|
|||
|
NameType = DFS_NAMETYPE_EITHER;
|
|||
|
dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS){
|
|||
|
goto cleanup;
|
|||
|
//return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Already a root?
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
dwErr = SetupStdDfs(
|
|||
|
wszComputerName,
|
|||
|
RootShare,
|
|||
|
Comment,
|
|||
|
1,
|
|||
|
Share);
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Reset dfs
|
|||
|
//
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmInitLocalPartitions();
|
|||
|
InitializeDfsManager();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
dwErr = ERROR_ALREADY_EXISTS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsAddStdRootForced_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(Share));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsRemove (Obsolete)
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsRemove(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemove_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS){
|
|||
|
status = ERROR_NOT_SUPPORTED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
status = NetrDfsRemove2(
|
|||
|
DfsEntryPath,
|
|||
|
NULL,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
NULL);
|
|||
|
goto cleanup;
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemove_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsRemove2
|
|||
|
//
|
|||
|
// Synopsis: Deletes a volume/replica/link from the Dfs.
|
|||
|
//
|
|||
|
// Arguments: [DfsEntryPath] -- Entry path of the volume to operate on.
|
|||
|
// [DcName] -- Name of Dc to use
|
|||
|
// [ServerName] -- If specified, indicates the replica of the
|
|||
|
// volume to operate on.
|
|||
|
// [ShareName] -- If specified, indicates the share on the
|
|||
|
// server to operate on.
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
// [ppRootList] -- On success, returns a list of roots that need to be
|
|||
|
// informed of the change in the DS object
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation successful.
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to
|
|||
|
// a valid entry path.
|
|||
|
//
|
|||
|
// [NERR_DfsNotALeafVolume] -- Unable to delete the volume
|
|||
|
// because it is not a leaf volume.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal database corruption
|
|||
|
// encountered while executing operation.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- One of the input parameters is
|
|||
|
// incorrect.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsRemove2(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN PDFSM_ROOT_LIST *ppRootList)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
CDfsVolume *pDfsVol = NULL;
|
|||
|
DFS_REPLICA_INFO replInfo;
|
|||
|
BOOLEAN fRemoveReplica = FALSE;
|
|||
|
LPWSTR OrgDfsEntryPath = DfsEntryPath;
|
|||
|
DWORD dwErr;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsRemove2(%ws,%ws,%ws,%ws,0x%x)\n",
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
ppRootList);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemove2_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()){
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
#if 0 // Broken for DNS names
|
|||
|
DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEntryPath != NULL) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
|
|||
|
else if (ulDfsManagerType == DFS_MANAGER_SERVER)
|
|||
|
DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
|
|||
|
|
|||
|
if (DfsEntryPath == NULL){
|
|||
|
status = ERROR_OUTOFMEMORY;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath == NULL) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If ServerName is present, it must be valid.
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName != NULL && ServerName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If ShareName is present, it must be valid.
|
|||
|
//
|
|||
|
|
|||
|
if (ShareName != NULL && ShareName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If ShareName is present, ServerName must be present.
|
|||
|
//
|
|||
|
|
|||
|
if (ShareName != NULL && ServerName == NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Great, the parameters look semi-reasonable, lets do the work.
|
|||
|
//
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
if (DcName != NULL)
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
LdapIncrementBlob();
|
|||
|
}
|
|||
|
|
|||
|
ZeroMemory( &replInfo, sizeof(replInfo) );
|
|||
|
|
|||
|
status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
|
|||
|
pDfsVol = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS && ServerName != NULL && ShareName != NULL) {
|
|||
|
|
|||
|
LPWSTR pwszShare;
|
|||
|
|
|||
|
replInfo.ulReplicaState = 0;
|
|||
|
replInfo.ulReplicaType = 0;
|
|||
|
replInfo.pwszServerName = ServerName;
|
|||
|
replInfo.pwszShareName = ShareName;
|
|||
|
|
|||
|
fRemoveReplica = TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// See whether we should delete a replica or the volume
|
|||
|
//
|
|||
|
|
|||
|
if (fRemoveReplica) {
|
|||
|
|
|||
|
status = pDfsVol->RemoveReplica( &replInfo, DFS_OVERRIDE_FORCE );
|
|||
|
|
|||
|
if (status == NERR_DfsCantRemoveLastServerShare) {
|
|||
|
|
|||
|
status = pDfsVol->Delete( DFS_OVERRIDE_FORCE );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = pDfsVol->Delete( DFS_OVERRIDE_FORCE );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (pDfsVol != NULL) {
|
|||
|
pDfsVol->Release();
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Create list of roots to redirect to this DC
|
|||
|
//
|
|||
|
|
|||
|
if (status == NERR_Success &&
|
|||
|
DcName != NULL &&
|
|||
|
ulDfsManagerType == DFS_MANAGER_FTDFS
|
|||
|
) {
|
|||
|
DfspCreateRootList(
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ppRootList);
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsRemove2 returning %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemove2_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsRemoveFtRoot
|
|||
|
//
|
|||
|
// Synopsis: Deletes a root from an FtDfs.
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- The server to remove.
|
|||
|
// [DcName] -- DC to use
|
|||
|
// [RootShare] -- The Root share hosting the Dfs/FtDfs
|
|||
|
// [FtDfsName] -- The FtDfs to remove the root from.
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
// [ppRootList] -- On success, returns a list of roots that need to be
|
|||
|
// informed of the change in the DS object
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation successful.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal database corruption
|
|||
|
// encountered while executing operation.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- One of the input parameters is
|
|||
|
// incorrect.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsRemoveFtRoot(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR RootShare,
|
|||
|
IN LPWSTR FtDfsName,
|
|||
|
IN DWORD Flags,
|
|||
|
IN PDFSM_ROOT_LIST *ppRootList)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
DWORD dwErr2 = ERROR_SUCCESS;
|
|||
|
DWORD cbData;
|
|||
|
DWORD dwType;
|
|||
|
HKEY hkey;
|
|||
|
WCHAR wszRootShare[MAX_PATH];
|
|||
|
WCHAR wszFTDfs[MAX_PATH];
|
|||
|
WCHAR wszFullObjectName[MAX_PATH];
|
|||
|
WCHAR wszComputerName[MAX_PATH];
|
|||
|
DFS_NAME_CONVENTION NameType;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsRemoveFtRoot(%ws,%ws,%ws,%ws,0x%x)\n",
|
|||
|
ServerName,
|
|||
|
DcName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
Flags);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemoveFtRoot_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(FtDfsName));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (
|
|||
|
ServerName == NULL ||
|
|||
|
DcName == NULL ||
|
|||
|
RootShare == NULL ||
|
|||
|
FtDfsName == NULL
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (
|
|||
|
ServerName[0] == UNICODE_NULL ||
|
|||
|
DcName[0] == UNICODE_NULL ||
|
|||
|
RootShare[0] == UNICODE_NULL ||
|
|||
|
FtDfsName[0] == UNICODE_NULL
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get our computer name
|
|||
|
//
|
|||
|
NameType = DFS_NAMETYPE_DNS;
|
|||
|
dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS){
|
|||
|
goto cleanup;
|
|||
|
//return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ((Flags & DFS_FORCE_REMOVE) == 0) {
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Update remoteServerName attribute
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
dwErr = DfspRemoveFtDfsDsObj(
|
|||
|
wszComputerName,
|
|||
|
DcName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
ppRootList);
|
|||
|
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
LdapIncrementBlob();
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
|
|||
|
//
|
|||
|
// We need to be a root to remove a root...
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check RootName and FtDfsName
|
|||
|
//
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
cbData = sizeof(wszRootShare);
|
|||
|
|
|||
|
dwErr = RegQueryValueEx(
|
|||
|
hkey,
|
|||
|
ROOT_SHARE_VALUE_NAME,
|
|||
|
NULL,
|
|||
|
&dwType,
|
|||
|
(PBYTE) wszRootShare,
|
|||
|
&cbData);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS ||
|
|||
|
dwType != REG_SZ ||
|
|||
|
_wcsicmp(wszRootShare, RootShare) != 0
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
hkey = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
cbData = sizeof(wszFTDfs);
|
|||
|
|
|||
|
dwErr = RegQueryValueEx(
|
|||
|
hkey,
|
|||
|
FTDFS_VALUE_NAME,
|
|||
|
NULL,
|
|||
|
&dwType,
|
|||
|
(PBYTE) wszFTDfs,
|
|||
|
&cbData);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS ||
|
|||
|
dwType != REG_SZ ||
|
|||
|
_wcsicmp(wszFTDfs, FtDfsName) != 0
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update pKT (blob) attribute
|
|||
|
//
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
wcscpy(wszFullObjectName, LDAP_VOLUMES_DIR);
|
|||
|
wcscat(wszFullObjectName, DOMAIN_ROOT_VOL);
|
|||
|
|
|||
|
dwErr = DfsManagerRemoveService(
|
|||
|
wszFullObjectName,
|
|||
|
wszComputerName);
|
|||
|
|
|||
|
if (dwErr == NERR_DfsCantRemoveLastServerShare) {
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
dwErr = DfsRemoveRoot();
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Reinit the service, back to non-ldap
|
|||
|
//
|
|||
|
|
|||
|
DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER);
|
|||
|
|
|||
|
//
|
|||
|
// Tell dfs.sys to discard all state
|
|||
|
//
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
hkey = NULL;
|
|||
|
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (hkey != NULL) {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
dwErr2 = LdapDecrementBlob();
|
|||
|
// don't mask more important errors.
|
|||
|
if(dwErr == ERROR_SUCCESS) {
|
|||
|
dwErr = dwErr2;
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// We're forcefully removing a root. We'd better be a DC!!
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Update remoteServerName attribute
|
|||
|
//
|
|||
|
|
|||
|
dwErr = DfspRemoveFtDfsDsObj(
|
|||
|
ServerName,
|
|||
|
DcName,
|
|||
|
RootShare,
|
|||
|
FtDfsName,
|
|||
|
ppRootList);
|
|||
|
|
|||
|
//
|
|||
|
// Update pKT (blob) attribute
|
|||
|
//
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
dwErr = DfsManagerRemoveServiceForced(
|
|||
|
ServerName,
|
|||
|
DcName,
|
|||
|
FtDfsName);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsRemoveFtRoot returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemoveFtRoot_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(RootShare)
|
|||
|
LOGWSTR(FtDfsName));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsRemoveStdRoot
|
|||
|
//
|
|||
|
// Synopsis: Deletes a Dfs root
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- The server to remove.
|
|||
|
// [RootShare] -- The Root share hosting the Dfs/FtDfs
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation successful.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal database corruption
|
|||
|
// encountered while executing operation.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- One of the input parameters is
|
|||
|
// incorrect.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsRemoveStdRoot(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR RootShare,
|
|||
|
IN DWORD Flags)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
DWORD cbData;
|
|||
|
DWORD dwType;
|
|||
|
HKEY hkey;
|
|||
|
WCHAR wszRootShare[MAX_PATH];
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemoveStdRoot_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input arguments...
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (RootShare == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (RootShare[0] == UNICODE_NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// We need to be a root to remove a root...
|
|||
|
//
|
|||
|
|
|||
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|||
|
|
|||
|
//
|
|||
|
// Check RootName
|
|||
|
//
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
cbData = sizeof(wszRootShare);
|
|||
|
|
|||
|
dwErr = RegQueryValueEx(
|
|||
|
hkey,
|
|||
|
ROOT_SHARE_VALUE_NAME,
|
|||
|
NULL,
|
|||
|
&dwType,
|
|||
|
(PBYTE) wszRootShare,
|
|||
|
&cbData);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS ||
|
|||
|
dwType != REG_SZ ||
|
|||
|
_wcsicmp(wszRootShare, RootShare) != 0
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
hkey = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Remove registry stuff (DfsHost and volumes)
|
|||
|
//
|
|||
|
|
|||
|
dwErr = DfsRemoveRoot();
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Reinit the service
|
|||
|
//
|
|||
|
|
|||
|
DfsReInitGlobals(pwszComputerName, DFS_MANAGER_SERVER);
|
|||
|
|
|||
|
//
|
|||
|
// Tell dfs.sys to discard all state
|
|||
|
//
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
hkey = NULL;
|
|||
|
|
|||
|
DfsmStopDfs();
|
|||
|
DfsmResetPkt();
|
|||
|
DfsmStartDfs();
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (hkey != NULL) {
|
|||
|
|
|||
|
RegCloseKey(hkey);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRemoveStdRoot_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(RootShare));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsSetInfo (Obsolete)
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsSetInfo(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN DWORD Level,
|
|||
|
IN LPDFS_INFO_STRUCT DfsInfo)
|
|||
|
{
|
|||
|
if (!AccessCheckRpcClient())
|
|||
|
return( ERROR_ACCESS_DENIED );
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
return( ERROR_NOT_SUPPORTED );
|
|||
|
|
|||
|
return NetrDfsSetInfo2(
|
|||
|
DfsEntryPath,
|
|||
|
NULL,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
Level,
|
|||
|
DfsInfo,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsSetInfo2
|
|||
|
//
|
|||
|
// Synopsis: Sets the comment, volume state, or replica state.
|
|||
|
//
|
|||
|
// Arguments: [DfsEntryPath] -- Entry Path of the volume for which info is
|
|||
|
// to be set.
|
|||
|
// [ServerName] -- If specified, the name of the server whose
|
|||
|
// state is to be set.
|
|||
|
// [ShareName] -- If specified, the name of the share on
|
|||
|
// ServerName whose state is to be set.
|
|||
|
// [Level] -- Level of DfsInfo
|
|||
|
// [DfsInfo] -- The actual Dfs info.
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation completed successfully.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_LEVEL] -- Level != 100 , 101, or 102
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- DfsEntryPath invalid, or
|
|||
|
// ShareName specified without ServerName.
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchVolume] -- DfsEntryPath does not correspond to
|
|||
|
// a valid Dfs volume.
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchShare] -- The indicated ServerName/ShareName do
|
|||
|
// not support this Dfs volume.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal database corruption
|
|||
|
// encountered while executing operation.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsSetInfo2(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR DcName,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN DWORD Level,
|
|||
|
IN LPDFS_INFO_STRUCT DfsInfo,
|
|||
|
IN PDFSM_ROOT_LIST *ppRootList)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
NET_API_STATUS netStatus;
|
|||
|
CDfsVolume *pDfsVol = NULL;
|
|||
|
LPWSTR pwszShare = NULL;
|
|||
|
BOOLEAN fSetReplicaState;
|
|||
|
LPWSTR OrgDfsEntryPath = DfsEntryPath;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsSetInfo2_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint("NetrDfsSetInfo2(%ws,%ws,%ws,%ws,%d,0x%x\n",
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
Level,
|
|||
|
ppRootList);
|
|||
|
if (Level == 100) {
|
|||
|
DbgPrint(",Comment=%ws)\n", DfsInfo->DfsInfo100->Comment);
|
|||
|
} else if (Level == 101) {
|
|||
|
DbgPrint(",State=0x%x)\n", DfsInfo->DfsInfo101->State);
|
|||
|
} else if (Level == 102) {
|
|||
|
DbgPrint(",Timeout=0x%x)\n", DfsInfo->DfsInfo102->Timeout);
|
|||
|
} else {
|
|||
|
DbgPrint(")\n");
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input parameters...
|
|||
|
//
|
|||
|
|
|||
|
#if 0 // Broken for DNS names
|
|||
|
DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEntryPath != NULL) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
|
|||
|
else if (ulDfsManagerType == DFS_MANAGER_SERVER)
|
|||
|
DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
|
|||
|
|
|||
|
if (DfsEntryPath == NULL){
|
|||
|
status = ERROR_OUTOFMEMORY;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath == NULL) {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (DfsInfo == NULL || DfsInfo->DfsInfo100 == NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (!(Level >= 100 && Level <= 102)) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_LEVEL;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
if (DcName != NULL)
|
|||
|
DfsManagerSetDcName(DcName);
|
|||
|
LdapIncrementBlob();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Try to get the Dfs Volume for DfsEntryPath
|
|||
|
//
|
|||
|
|
|||
|
status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the right thing based on Level...
|
|||
|
//
|
|||
|
|
|||
|
if (Level == 100) {
|
|||
|
|
|||
|
//
|
|||
|
// Set the volume Comment
|
|||
|
//
|
|||
|
|
|||
|
if (DfsInfo->DfsInfo100->Comment != NULL)
|
|||
|
status = pDfsVol->SetComment(DfsInfo->DfsInfo100->Comment);
|
|||
|
else
|
|||
|
status = pDfsVol->SetComment(L"");
|
|||
|
|
|||
|
} else if (Level == 101) {
|
|||
|
|
|||
|
//
|
|||
|
// Set the volume state
|
|||
|
//
|
|||
|
|
|||
|
if (ServerName == NULL && ShareName == NULL) {
|
|||
|
|
|||
|
fSetReplicaState = FALSE;
|
|||
|
|
|||
|
} else if (ServerName != NULL && ServerName[0] != UNICODE_NULL &&
|
|||
|
ShareName != NULL && ShareName[0] != UNICODE_NULL) {
|
|||
|
|
|||
|
fSetReplicaState = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsSetInfo2_Error1,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
}
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (fSetReplicaState) {
|
|||
|
|
|||
|
status = pDfsVol->SetReplicaState(
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
DfsInfo->DfsInfo101->State);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = pDfsVol->SetVolumeState(DfsInfo->DfsInfo101->State);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (pwszShare != NULL) {
|
|||
|
|
|||
|
delete [] pwszShare;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else if (Level == 102) {
|
|||
|
|
|||
|
//
|
|||
|
// Set the volume timeout
|
|||
|
//
|
|||
|
|
|||
|
status = pDfsVol->SetVolumeTimeout(DfsInfo->DfsInfo102->Timeout);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (pDfsVol != NULL) {
|
|||
|
pDfsVol->Release();
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Create list of roots to redirect to this DC
|
|||
|
//
|
|||
|
|
|||
|
if (status == NERR_Success &&
|
|||
|
DcName != NULL &&
|
|||
|
ulDfsManagerType == DFS_MANAGER_FTDFS
|
|||
|
) {
|
|||
|
DfspCreateRootList(
|
|||
|
DfsEntryPath,
|
|||
|
DcName,
|
|||
|
ppRootList);
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsSetInfo2 returning %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsSetInfo2_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(OrgDfsEntryPath)
|
|||
|
LOGWSTR(DcName)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsGetInfo
|
|||
|
//
|
|||
|
// Synopsis: Server side implementation of the NetDfsGetInfo.
|
|||
|
//
|
|||
|
// Arguments: [DfsEntryPath] -- Entry Path of volume for which info is
|
|||
|
// requested.
|
|||
|
//
|
|||
|
// [ServerName] -- Name of server which supports this volume
|
|||
|
// and for which info is requested.
|
|||
|
//
|
|||
|
// [ShareName] -- Name of share on ServerName which supports this
|
|||
|
// volume.
|
|||
|
//
|
|||
|
// [Level] -- Level of Info requested.
|
|||
|
//
|
|||
|
// [DfsInfo] -- On successful return, contains a pointer to the
|
|||
|
// requested DFS_INFO_x struct.
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- If successfully returned requested info.
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchVolume] -- If DfsEntryPath does not
|
|||
|
// corresponds to a valid volume.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Corruption encountered in
|
|||
|
// internal database.
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for
|
|||
|
// info.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- DfsInfo was NULL on entry, or
|
|||
|
// ShareName specified without ServerName, or
|
|||
|
// DfsEntryPath was NULL on entry.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_LEVEL] -- Level != 1,2,3,4, or 100
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsGetInfo(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN LPWSTR ShareName,
|
|||
|
IN DWORD Level,
|
|||
|
OUT LPDFS_INFO_STRUCT DfsInfo)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
LPDFS_INFO_3 pInfo;
|
|||
|
CDfsVolume *pDfsVol;
|
|||
|
DWORD cbInfo;
|
|||
|
LPWSTR OrgDfsEntryPath = DfsEntryPath;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsGetInfo_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsGetInfo(%ws,%ws,%ws,%d)\n",
|
|||
|
DfsEntryPath,
|
|||
|
ServerName,
|
|||
|
ShareName,
|
|||
|
Level);
|
|||
|
#endif
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsGetInfo(L=%d)\n", Level));
|
|||
|
|
|||
|
//
|
|||
|
// Validate the input parameters...
|
|||
|
//
|
|||
|
|
|||
|
#if 0 // Broken for DNS names
|
|||
|
DfsEntryPath = NormalizeEntryPath( DfsEntryPath );
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEntryPath != NULL) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
DfsEntryPath = FormFTDfsEntryPath(DfsEntryPath);
|
|||
|
else if (ulDfsManagerType == DFS_MANAGER_SERVER)
|
|||
|
DfsEntryPath = FormStdDfsEntryPath(DfsEntryPath);
|
|||
|
|
|||
|
if (DfsEntryPath == NULL) {
|
|||
|
status = ERROR_OUTOFMEMORY;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (DfsEntryPath == NULL) {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (DfsInfo == NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (!(Level >= 1 && Level <= 4) && Level != 100) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_LEVEL;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (ServerName == NULL && ShareName != NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now, get the info...
|
|||
|
//
|
|||
|
|
|||
|
if (Level <= 3) {
|
|||
|
|
|||
|
pInfo = (LPDFS_INFO_3) MIDL_user_allocate(sizeof(DFS_INFO_3));
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
pInfo = (LPDFS_INFO_3) MIDL_user_allocate(sizeof(DFS_INFO_4));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (pInfo == NULL) {
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
LdapIncrementBlob();
|
|||
|
|
|||
|
status = GetDfsVolumeFromPath( DfsEntryPath, TRUE, &pDfsVol );
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
status = pDfsVol->GetNetInfo(Level, pInfo, &cbInfo );
|
|||
|
|
|||
|
pDfsVol->Release();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
DfsInfo->DfsInfo3 = pInfo;
|
|||
|
|
|||
|
} else if (status != NERR_DfsNoSuchVolume) {
|
|||
|
|
|||
|
status = NERR_DfsInternalCorruption;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
NET_API_STATUS TempStatus;
|
|||
|
TempStatus = LdapDecrementBlob();
|
|||
|
// only mask the status if we haven't already seen an error.
|
|||
|
if(status == ERROR_SUCCESS) {
|
|||
|
status = TempStatus;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
if (DfsEntryPath != OrgDfsEntryPath) {
|
|||
|
delete [] DfsEntryPath;
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsGetInfo returning %d\n", status);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsGetInfo_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(ServerName)
|
|||
|
LOGWSTR(ShareName));
|
|||
|
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsEnum
|
|||
|
//
|
|||
|
// Synopsis: The server side implementation of the NetDfsEnum public API
|
|||
|
//
|
|||
|
// Arguments: [Level] -- The level of info struct desired.
|
|||
|
// [PrefMaxLen] -- Preferred maximum length of output buffer.
|
|||
|
// 0xffffffff means no limit.
|
|||
|
// [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
|
|||
|
// structs will be returned.
|
|||
|
// [ResumeHandle] -- If 0, the enumeration will begin from the
|
|||
|
// start. On return, the resume handle will be an opaque
|
|||
|
// cookie that can be passed in on subsequent calls to
|
|||
|
// resume the enumeration.
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Successfully retrieved info.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal Dfs database is
|
|||
|
// corrupt.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
|
|||
|
// NULL on entry.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_LEVEL] -- If Level != 1,2, 4 or 200
|
|||
|
//
|
|||
|
// [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
|
|||
|
// on *ResumeHandle value.
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
|
|||
|
// condition while constructing info.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsEnum(
|
|||
|
IN DWORD Level,
|
|||
|
IN DWORD PrefMaxLen,
|
|||
|
IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
|
|||
|
IN OUT LPDWORD ResumeHandle)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
DWORD i, cEntriesToRead, cbInfoSize, cbOneInfoSize, cbTotalSize;
|
|||
|
LPBYTE pBuffer;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsEnum_Start,
|
|||
|
LOGSTATUS(status));
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsEnum(L=%d)\n", Level));
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum(%d,0x%x)\n",
|
|||
|
Level,
|
|||
|
PrefMaxLen);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Out parameters before we die...
|
|||
|
//
|
|||
|
|
|||
|
if (DfsEnum == NULL ||
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container == NULL ||
|
|||
|
ResumeHandle == NULL) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum returning ERROR_INVALID_PARAMETER\n");
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
ERROR_INVALID_PARAMETER,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Info Level...
|
|||
|
//
|
|||
|
if (!(Level >= 1 && Level <= 4) && Level != 200) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum returning ERROR_INVALID_LEVEL\n");
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
ERROR_INVALID_LEVEL,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
status = ERROR_INVALID_LEVEL;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
LdapIncrementBlob();
|
|||
|
|
|||
|
//
|
|||
|
// Handle level 200 as a special case
|
|||
|
//
|
|||
|
|
|||
|
if (Level == 200) {
|
|||
|
|
|||
|
status = NetrDfsEnum200(
|
|||
|
Level,
|
|||
|
PrefMaxLen,
|
|||
|
DfsEnum,
|
|||
|
ResumeHandle);
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint("NetrDfsEnum200 returned %d\n", status);
|
|||
|
DbgPrint("NetrDfsEnum returning %d\n", status);
|
|||
|
}
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
status,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
//return( status );
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check the ResumeHandle...
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsmStorageDirectory == NULL ||
|
|||
|
(*ResumeHandle) >= pDfsmStorageDirectory->GetNumEntries()) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum returning ERROR_NO_MORE_ITEMS\n");
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
ERROR_NO_MORE_ITEMS,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
status = ERROR_NO_MORE_ITEMS;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
switch (Level) {
|
|||
|
case 1:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_1);
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_2);
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_3);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_4);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
status = ERROR_INVALID_LEVEL;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (PrefMaxLen == ~0) {
|
|||
|
|
|||
|
cEntriesToRead = pDfsmStorageDirectory->GetNumEntries();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
cEntriesToRead = min( pDfsmStorageDirectory->GetNumEntries(),
|
|||
|
PrefMaxLen / cbInfoSize );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum: cEntriesToRead = %d\n", cEntriesToRead);
|
|||
|
#endif
|
|||
|
|
|||
|
pBuffer = (LPBYTE) MIDL_user_allocate( cEntriesToRead * cbInfoSize );
|
|||
|
|
|||
|
if (pBuffer == NULL) {
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum returning ERROR_NOT_ENOUGH_MEMORY\n");
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
ERROR_NOT_ENOUGH_MEMORY,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now, we sit in a loop and get the info
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0, cbTotalSize = 0, status = NERR_Success;
|
|||
|
(i < cEntriesToRead) &&
|
|||
|
(cbTotalSize < PrefMaxLen);
|
|||
|
i++) {
|
|||
|
|
|||
|
status = DfspGetOneEnumInfo(
|
|||
|
i,
|
|||
|
Level,
|
|||
|
pBuffer,
|
|||
|
&cbOneInfoSize,
|
|||
|
ResumeHandle);
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfspGetOneEnumInfo returned %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
if (status == ERROR_NO_MORE_ITEMS || status != NERR_Success)
|
|||
|
break;
|
|||
|
|
|||
|
cbTotalSize += (cbInfoSize + cbOneInfoSize);
|
|||
|
|
|||
|
cbOneInfoSize = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == NERR_Success || status == ERROR_NO_MORE_ITEMS) {
|
|||
|
|
|||
|
DfsEnum->Level = Level;
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = i;
|
|||
|
|
|||
|
if (i > 0) {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer =
|
|||
|
(LPDFS_INFO_1) pBuffer;
|
|||
|
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
|
|||
|
|
|||
|
MIDL_user_free( pBuffer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
for (; i > 0; i--) {
|
|||
|
|
|||
|
DfspFreeOneEnumInfo(i-1, Level, pBuffer);
|
|||
|
|
|||
|
//
|
|||
|
// 333596. Fix memory leak.
|
|||
|
//
|
|||
|
MIDL_user_free( pBuffer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS)
|
|||
|
status = LdapDecrementBlob();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum returning %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUM,
|
|||
|
status,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsEnum_End,
|
|||
|
LOGSTATUS(status));
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsEnum200
|
|||
|
//
|
|||
|
// Synopsis: Handles level 200 for NetrDfsEnum, server-side implementation
|
|||
|
//
|
|||
|
// Arguments: [Level] -- The level of info struct desired.
|
|||
|
// [PrefMaxLen] -- Preferred maximum length of output buffer.
|
|||
|
// 0xffffffff means no limit.
|
|||
|
// [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
|
|||
|
// structs will be returned.
|
|||
|
// [ResumeHandle] -- If 0, the enumeration will begin from the
|
|||
|
// start. On return, the resume handle will be an opaque
|
|||
|
// cookie that can be passed in on subsequent calls to
|
|||
|
// resume the enumeration.
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Successfully retrieved info.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal Dfs database is
|
|||
|
// corrupt.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
|
|||
|
// NULL on entry.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_LEVEL] -- If Level != 200
|
|||
|
//
|
|||
|
// [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
|
|||
|
// on *ResumeHandle value.
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
|
|||
|
// condition while constructing info.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
NET_API_STATUS
|
|||
|
NetrDfsEnum200(
|
|||
|
IN DWORD Level,
|
|||
|
IN DWORD PrefMaxLen,
|
|||
|
IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
|
|||
|
IN OUT LPDWORD ResumeHandle)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_SUCCESS;
|
|||
|
ULONG i;
|
|||
|
ULONG cEntriesToRead;
|
|||
|
ULONG cEntriesRead;
|
|||
|
ULONG cbInfoSize;
|
|||
|
ULONG cbThisInfoSize;
|
|||
|
ULONG cbTotalSize;
|
|||
|
ULONG cList;
|
|||
|
LPWSTR *List = NULL;
|
|||
|
PDFS_INFO_200 pDfsInfo200;
|
|||
|
PBYTE pBuffer;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum200(%d,%d)\n", Level, PrefMaxLen);
|
|||
|
#endif
|
|||
|
|
|||
|
if (Level != 200) {
|
|||
|
status = ERROR_INVALID_LEVEL;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error1, LOGSTATUS(status));
|
|||
|
goto AllDone;
|
|||
|
}
|
|||
|
|
|||
|
if (pwszDomainName == NULL) {
|
|||
|
status = ERROR_DOMAIN_CONTROLLER_NOT_FOUND;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error2, LOGSTATUS(status));
|
|||
|
goto AllDone;
|
|||
|
}
|
|||
|
|
|||
|
cbInfoSize = sizeof(DFS_INFO_200);
|
|||
|
|
|||
|
//
|
|||
|
// Get the list of FtDfs roots in the domain
|
|||
|
//
|
|||
|
status = DfsGetFtServersFromDs(
|
|||
|
NULL,
|
|||
|
pwszDomainName,
|
|||
|
NULL,
|
|||
|
&List);
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "DfsGetFtServersFromDs returned %d\n", status));
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
goto AllDone;
|
|||
|
|
|||
|
if (List == NULL) {
|
|||
|
status = ERROR_NO_MORE_ITEMS;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error3, LOGSTATUS(status));
|
|||
|
goto AllDone;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build the results array
|
|||
|
//
|
|||
|
if (status == NOERROR) {
|
|||
|
|
|||
|
status = NERR_Success;
|
|||
|
|
|||
|
//
|
|||
|
// Count # entries returned
|
|||
|
//
|
|||
|
for (cList = 0; List[cList]; cList++) {
|
|||
|
NOTHING;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
DbgPrint("List has %d items\n", cList);
|
|||
|
for (i = 0; i < cList; i++)
|
|||
|
DbgPrint("%d: %ws\n", i, List[i]);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (*ResumeHandle >= cList) {
|
|||
|
status = ERROR_NO_MORE_ITEMS;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error4, LOGSTATUS(status));
|
|||
|
goto AllDone;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Size & allocate the results array
|
|||
|
//
|
|||
|
if (PrefMaxLen == ~0) {
|
|||
|
|
|||
|
cEntriesToRead = cList;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
cEntriesToRead = min(cList, PrefMaxLen / cbInfoSize);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pBuffer = (LPBYTE) MIDL_user_allocate(cEntriesToRead * cbInfoSize);
|
|||
|
|
|||
|
if (pBuffer == NULL) {
|
|||
|
|
|||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error5, LOGSTATUS(status));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Load the results array, starting at the resume handle
|
|||
|
//
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
pDfsInfo200 = (LPDFS_INFO_200)pBuffer;
|
|||
|
cbTotalSize = cEntriesRead = 0;
|
|||
|
|
|||
|
for (i = *ResumeHandle; (i < cEntriesToRead) && (status == NERR_Success); i++) {
|
|||
|
|
|||
|
cbThisInfoSize = (wcslen(List[i]) + 1) * sizeof(WCHAR);
|
|||
|
|
|||
|
//
|
|||
|
// Quit if this element would cause us to exceed PrefmaxLen
|
|||
|
//
|
|||
|
if (cbTotalSize + cbInfoSize + cbThisInfoSize > PrefMaxLen) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pDfsInfo200->FtDfsName = (LPWSTR) MIDL_user_allocate(cbThisInfoSize);
|
|||
|
|
|||
|
if (pDfsInfo200 != NULL) {
|
|||
|
|
|||
|
wcscpy(pDfsInfo200->FtDfsName, List[i]);
|
|||
|
cbTotalSize += cbInfoSize + cbThisInfoSize;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
DFSM_TRACE_HIGH(ERROR, NetrDfsEnum200_Error6, LOGSTATUS(status));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pDfsInfo200++;
|
|||
|
cEntriesRead++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*ResumeHandle = i;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
|
|||
|
//
|
|||
|
// Everything worked
|
|||
|
//
|
|||
|
|
|||
|
DfsEnum->Level = Level;
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = cEntriesRead;
|
|||
|
|
|||
|
if (cEntriesRead > 0) {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = (LPDFS_INFO_1) pBuffer;
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
|
|||
|
|
|||
|
MIDL_user_free( pBuffer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// We're going to return an error, so free all the MIDL_user_allocate's
|
|||
|
// we made to hold FtDfsName's
|
|||
|
//
|
|||
|
for (i = cEntriesRead; i > 0; i--) {
|
|||
|
|
|||
|
pDfsInfo200 = (LPDFS_INFO_200) (pBuffer + (i-1) * sizeof(DFS_INFO_200));
|
|||
|
|
|||
|
if (pDfsInfo200->FtDfsName != NULL) {
|
|||
|
|
|||
|
MIDL_user_free(pDfsInfo200->FtDfsName);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
MIDL_user_free( pBuffer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NetApiBufferFree( List );
|
|||
|
|
|||
|
AllDone:
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum200 returning %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsEnumEx
|
|||
|
//
|
|||
|
// Synopsis: The DC implementation of the NetDfsEnum public API
|
|||
|
//
|
|||
|
// Arguments: [DfsName] -- The Dfs to enumerate (\\domainname\ftdfsname)
|
|||
|
// [Level] -- The level of info struct desired.
|
|||
|
// [PrefMaxLen] -- Preferred maximum length of output buffer.
|
|||
|
// 0xffffffff means no limit.
|
|||
|
// [DfsEnum] -- DFS_INFO_ENUM_STRUCT pointer where the info
|
|||
|
// structs will be returned.
|
|||
|
// [ResumeHandle] -- If 0, the enumeration will begin from the
|
|||
|
// start. On return, the resume handle will be an opaque
|
|||
|
// cookie that can be passed in on subsequent calls to
|
|||
|
// resume the enumeration.
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Successfully retrieved info.
|
|||
|
//
|
|||
|
// [NERR_DfsInternalCorruption] -- Internal Dfs database is
|
|||
|
// corrupt.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_PARAMETER] -- DfsEnum or ResumeHandle were
|
|||
|
// NULL on entry.
|
|||
|
//
|
|||
|
// [ERROR_INVALID_LEVEL] -- If Level != 1,2, 4 or 200
|
|||
|
//
|
|||
|
// [ERROR_NO_MORE_ITEMS] -- If nothing more to enumerate based
|
|||
|
// on *ResumeHandle value.
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- If we hit an out of memory
|
|||
|
// condition while constructing info.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsEnumEx(
|
|||
|
IN LPWSTR DfsName,
|
|||
|
IN DWORD Level,
|
|||
|
IN DWORD PrefMaxLen,
|
|||
|
IN OUT LPDFS_INFO_ENUM_STRUCT DfsEnum,
|
|||
|
IN OUT LPDWORD ResumeHandle)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
DFS_VOLUME_LIST DfsVolList;
|
|||
|
ULONG cbBlob = 0;
|
|||
|
BYTE *pBlob = NULL;
|
|||
|
LPWSTR wszFtDfsName;
|
|||
|
|
|||
|
DWORD i;
|
|||
|
DWORD cEntriesToRead;
|
|||
|
DWORD cbInfoSize;
|
|||
|
DWORD cbOneInfoSize;
|
|||
|
DWORD cbTotalSize;
|
|||
|
LPBYTE pBuffer;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsEnumEx_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(DfsName));
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsEnumEx(%ws,%d)\n", DfsName, Level));
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnumEx(%ws,%d,0x%x)\n",
|
|||
|
DfsName,
|
|||
|
Level,
|
|||
|
PrefMaxLen);
|
|||
|
#endif
|
|||
|
|
|||
|
RtlZeroMemory(&DfsVolList, sizeof(DFS_VOLUME_LIST));
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Out parameters
|
|||
|
//
|
|||
|
|
|||
|
if (DfsEnum == NULL
|
|||
|
||
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container == NULL
|
|||
|
||
|
|||
|
ResumeHandle == NULL
|
|||
|
) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnumEx returning ERROR_INVALID_PARAMETER\n");
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUMEX,
|
|||
|
ERROR_INVALID_PARAMETER,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Info Level...
|
|||
|
//
|
|||
|
if (!(Level >= 1 && Level <= 4) && Level != 200) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnumEx returning ERROR_INVALID_LEVEL\n");
|
|||
|
#endif
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUMEX,
|
|||
|
ERROR_INVALID_LEVEL,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
dwErr = ERROR_INVALID_LEVEL;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Handle level 200 as a special case
|
|||
|
//
|
|||
|
|
|||
|
if (Level == 200) {
|
|||
|
|
|||
|
dwErr = NetrDfsEnum200(
|
|||
|
Level,
|
|||
|
PrefMaxLen,
|
|||
|
DfsEnum,
|
|||
|
ResumeHandle);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnum200 returned %d\n", dwErr);
|
|||
|
#endif
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
for (wszFtDfsName = DfsName;
|
|||
|
*wszFtDfsName != UNICODE_PATH_SEP && *wszFtDfsName != UNICODE_NULL;
|
|||
|
wszFtDfsName++) {
|
|||
|
NOTHING;
|
|||
|
}
|
|||
|
|
|||
|
if (*wszFtDfsName != UNICODE_PATH_SEP) {
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
wszFtDfsName++;
|
|||
|
|
|||
|
if (*wszFtDfsName == UNICODE_NULL) {
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get blob from Ds
|
|||
|
//
|
|||
|
dwErr = DfsGetDsBlob(
|
|||
|
wszFtDfsName,
|
|||
|
pwszComputerName,
|
|||
|
&cbBlob,
|
|||
|
&pBlob);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
//
|
|||
|
// Unserialize it
|
|||
|
//
|
|||
|
dwErr = DfsGetVolList(
|
|||
|
cbBlob,
|
|||
|
pBlob,
|
|||
|
&DfsVolList);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DfsDumpVolList(&DfsVolList);
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check the ResumeHandle...
|
|||
|
//
|
|||
|
|
|||
|
if ((*ResumeHandle) >= DfsVolList.VolCount) {
|
|||
|
|
|||
|
dwErr = ERROR_NO_MORE_ITEMS;
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
switch (Level) {
|
|||
|
case 1:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_1);
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_2);
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_3);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
cbInfoSize = sizeof(DFS_INFO_4);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ASSERT(FALSE && "Invalid Info Level");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (PrefMaxLen == ~0) {
|
|||
|
|
|||
|
cEntriesToRead = DfsVolList.VolCount;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
cEntriesToRead = min(DfsVolList.VolCount, PrefMaxLen/cbInfoSize);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnumEx: cEntriesToRead = %d\n", cEntriesToRead);
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
pBuffer = (LPBYTE) MIDL_user_allocate( cEntriesToRead * cbInfoSize );
|
|||
|
|
|||
|
if (pBuffer == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now, we sit in a loop and get the info
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0, cbTotalSize = 0, dwErr = ERROR_SUCCESS;
|
|||
|
(i < cEntriesToRead) && (cbTotalSize < PrefMaxLen);
|
|||
|
i++
|
|||
|
) {
|
|||
|
|
|||
|
dwErr = DfspGetOneEnumInfoEx(
|
|||
|
&DfsVolList,
|
|||
|
i,
|
|||
|
Level,
|
|||
|
pBuffer,
|
|||
|
&cbOneInfoSize);
|
|||
|
|
|||
|
if (dwErr == ERROR_NO_MORE_ITEMS || dwErr != ERROR_SUCCESS)
|
|||
|
break;
|
|||
|
|
|||
|
cbTotalSize += cbInfoSize + cbOneInfoSize;
|
|||
|
cbOneInfoSize = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS || dwErr == ERROR_NO_MORE_ITEMS) {
|
|||
|
|
|||
|
DfsEnum->Level = Level;
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead = cEntriesToRead;
|
|||
|
|
|||
|
if (i > 0) {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = (LPDFS_INFO_1) pBuffer;
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer = NULL;
|
|||
|
MIDL_user_free( pBuffer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
for (; i > 0; i--) {
|
|||
|
|
|||
|
DfspFreeOneEnumInfo(i-1, Level, pBuffer);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Cleanup:
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
if (pBlob != NULL)
|
|||
|
free(pBlob);
|
|||
|
|
|||
|
if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL)
|
|||
|
DfsFreeVolList(&DfsVolList);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000) {
|
|||
|
DbgPrint("===============\n");
|
|||
|
DbgPrint("Level: %d\n", DfsEnum->Level);
|
|||
|
DbgPrint("EntriesRead=%d\n", DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead);
|
|||
|
for (i = 0; i < DfsEnum->DfsInfoContainer.DfsInfo1Container->EntriesRead; i++) {
|
|||
|
if (Level == 1) {
|
|||
|
DbgPrint("Entry %d: %ws\n",
|
|||
|
i+1,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo1Container->Buffer[i].EntryPath);
|
|||
|
} else if (Level == 3) {
|
|||
|
DbgPrint("Entry %d: %ws\n",
|
|||
|
i+1,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].EntryPath);
|
|||
|
}
|
|||
|
if (Level == 3) {
|
|||
|
ULONG j;
|
|||
|
DbgPrint("\tComment: [%ws]\n",
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Comment,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].State,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].NumberOfStorages);
|
|||
|
for (j = 0;
|
|||
|
j < DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].NumberOfStorages;
|
|||
|
j++
|
|||
|
) {
|
|||
|
DbgPrint("\t\t[0x%x][\\\\%ws\\%ws]\n",
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].State,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].ServerName,
|
|||
|
DfsEnum->DfsInfoContainer.DfsInfo3Container->Buffer[i].Storage[j].ShareName);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
DbgPrint("===============\n");
|
|||
|
}
|
|||
|
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsEnumEx returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
if (DfsEventLog > 1) {
|
|||
|
LogWriteMessage(
|
|||
|
NET_DFS_ENUMEX,
|
|||
|
dwErr,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsEnumEx_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(DfsName));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsMove
|
|||
|
//
|
|||
|
// Synopsis: Moves a leaf volume to a different parent.
|
|||
|
//
|
|||
|
// Arguments: [DfsEntryPath] -- Current entry path of Dfs volume.
|
|||
|
//
|
|||
|
// [NewEntryPath] -- New entry path of Dfs volume.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsMove(
|
|||
|
IN LPWSTR DfsEntryPath,
|
|||
|
IN LPWSTR NewDfsEntryPath)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_NOT_SUPPORTED;
|
|||
|
CDfsVolume *pDfsVol = NULL;
|
|||
|
LPWSTR OrgDfsEntryPath = DfsEntryPath;
|
|||
|
LPWSTR OrgNewDfsEntryPath = NewDfsEntryPath;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsMove_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(NewDfsEntryPath));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient())
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsMove_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(DfsEntryPath)
|
|||
|
LOGWSTR(NewDfsEntryPath));
|
|||
|
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsRename
|
|||
|
//
|
|||
|
// Synopsis: Moves a leaf volume to a different parent.
|
|||
|
//
|
|||
|
// Arguments: [Path] -- Current path along the entry path of a Dfs volume.
|
|||
|
//
|
|||
|
// [NewPath] -- New path for current path.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsRename(
|
|||
|
IN LPWSTR Path,
|
|||
|
IN LPWSTR NewPath)
|
|||
|
{
|
|||
|
NET_API_STATUS status = ERROR_NOT_SUPPORTED;
|
|||
|
CDfsVolume *pDfsVol;
|
|||
|
LPWSTR OrgPath = Path;
|
|||
|
LPWSTR OrgNewPath = NewPath;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRename_Start,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(Path)
|
|||
|
LOGWSTR(NewPath));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient())
|
|||
|
status = ERROR_ACCESS_DENIED;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsRename_End,
|
|||
|
LOGSTATUS(status)
|
|||
|
LOGWSTR(Path)
|
|||
|
LOGWSTR(NewPath));
|
|||
|
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsManagerGetConfigInfo
|
|||
|
//
|
|||
|
// Synopsis: RPC Interface method that returns the config info for a
|
|||
|
// Dfs volume for a given server
|
|||
|
//
|
|||
|
// Arguments: [wszServer] -- Name of server requesting the info. This
|
|||
|
// server is assumed to be requesting the info for
|
|||
|
// verification of its local volume knowledge.
|
|||
|
// [wszLocalVolumeEntryPath] -- Entry path of local volume.
|
|||
|
// [idLocalVolume] -- The guid of the local volume.
|
|||
|
// [ppRelationInfo] -- The relation info is allocated and
|
|||
|
// returned here.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully returning relation info
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchVolume] -- Did not find LocalVolumeEntryPath
|
|||
|
//
|
|||
|
// [NERR_DfsNoSuchShare] -- The server name passed in does not
|
|||
|
// support this local volume.
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for info.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" DWORD
|
|||
|
NetrDfsManagerGetConfigInfo(
|
|||
|
IN LPWSTR wszServer,
|
|||
|
IN LPWSTR wszLocalVolumeEntryPath,
|
|||
|
IN GUID idLocalVolume,
|
|||
|
OUT LPDFSM_RELATION_INFO *ppRelationInfo)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
DFS_PKT_ENTRY_ID EntryId;
|
|||
|
DFS_PKT_RELATION_INFO DfsRelationInfo;
|
|||
|
CDfsVolume *pDfsVol;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsManagerGetConfigInfo(%ws,%ws)\n",
|
|||
|
wszServer,
|
|||
|
wszLocalVolumeEntryPath);
|
|||
|
#endif
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetConfigInfo_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(wszServer)
|
|||
|
LOGWSTR(wszLocalVolumeEntryPath));
|
|||
|
|
|||
|
if (ppRelationInfo == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
EntryId.Uid = idLocalVolume;
|
|||
|
|
|||
|
RtlInitUnicodeString( &EntryId.Prefix, wszLocalVolumeEntryPath );
|
|||
|
|
|||
|
EntryId.ShortPrefix.Length = EntryId.ShortPrefix.MaximumLength = 0;
|
|||
|
EntryId.ShortPrefix.Buffer = NULL;
|
|||
|
|
|||
|
dwErr = GetPktCacheRelationInfo( &EntryId, &DfsRelationInfo );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Well, we have the relation info, see if this server is a valid
|
|||
|
// server for this volume.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = GetDfsVolumeFromPath( wszLocalVolumeEntryPath, TRUE, &pDfsVol );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if ( pDfsVol->IsValidService(wszServer) ) {
|
|||
|
|
|||
|
dwErr = DfspAllocateRelationInfo(
|
|||
|
&DfsRelationInfo,
|
|||
|
ppRelationInfo );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = NERR_DfsNoSuchShare;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pDfsVol->Release();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = NERR_DfsNoSuchVolume;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DeallocateCacheRelationInfo( DfsRelationInfo );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = NERR_DfsInternalError;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsManagerGetConfigInfo returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerGetConfigInfo_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(wszServer)
|
|||
|
LOGWSTR(wszLocalVolumeEntryPath));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsManagerSendSiteInfo
|
|||
|
//
|
|||
|
// Synopsis: RPC Interface method that reports the site information for a
|
|||
|
// Dfs storage server.
|
|||
|
//
|
|||
|
// Arguments: [wszServer] -- Name of server sending the info.
|
|||
|
// [pSiteInfo] -- The site info is here.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfull
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for info.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" DWORD
|
|||
|
NetrDfsManagerSendSiteInfo(
|
|||
|
IN LPWSTR wszServer,
|
|||
|
IN LPDFS_SITELIST_INFO pSiteInfo)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerSendSiteInfo_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(wszServer));
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
//
|
|||
|
// Update the Site table
|
|||
|
//
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "NetrDfsGetInfo()\n", 0));
|
|||
|
|
|||
|
pDfsmSites->AddRef();
|
|||
|
dwErr = pDfsmSites->AddOrUpdateSiteInfo(
|
|||
|
wszServer,
|
|||
|
pSiteInfo->cSites,
|
|||
|
&pSiteInfo->Site[0]);
|
|||
|
pDfsmSites->Release();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
cleanup:
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerSendSiteInfo_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(wszServer));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: NetrDfsManagerInitialize
|
|||
|
//
|
|||
|
// Synopsis: Reinitializes the service
|
|||
|
//
|
|||
|
// Arguments: [ServerName] -- Name of server
|
|||
|
// [Flags] -- Flags for the operation
|
|||
|
//
|
|||
|
// Returns: [NERR_Success] -- Operation succeeded.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory condition.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" NET_API_STATUS
|
|||
|
NetrDfsManagerInitialize(
|
|||
|
IN LPWSTR ServerName,
|
|||
|
IN DWORD Flags)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerInitialize_Start,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName));
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsManagerInitialize(%ws,%d)\n",
|
|||
|
ServerName,
|
|||
|
Flags);
|
|||
|
#endif
|
|||
|
|
|||
|
if (!AccessCheckRpcClient()) {
|
|||
|
dwErr = ERROR_ACCESS_DENIED;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ENTER_DFSM_OPERATION;
|
|||
|
|
|||
|
#if DBG
|
|||
|
GetDebugSwitches();
|
|||
|
#endif
|
|||
|
GetConfigSwitches();
|
|||
|
|
|||
|
//
|
|||
|
// If we are a DomDfs, simply doing the LdapIncrementBlob will
|
|||
|
// be enough. If the DS blob has changed, then we will note that
|
|||
|
// and fully reinitialize everything.
|
|||
|
//
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
LdapIncrementBlob();
|
|||
|
dwErr = LdapDecrementBlob();
|
|||
|
} else {
|
|||
|
if (pDfsmStorageDirectory != NULL)
|
|||
|
delete pDfsmStorageDirectory;
|
|||
|
if (pDfsmSites != NULL)
|
|||
|
delete pDfsmSites;
|
|||
|
pDfsmSites = new CSites(LDAP_VOLUMES_DIR SITE_ROOT, &dwErr);
|
|||
|
pDfsmStorageDirectory = new CStorageDirectory( &dwErr );
|
|||
|
DfsmMarkStalePktEntries();
|
|||
|
InitializeDfsManager();
|
|||
|
DfsmFlushStalePktEntries();
|
|||
|
}
|
|||
|
|
|||
|
DfsmPktFlushCache();
|
|||
|
|
|||
|
EXIT_DFSM_OPERATION;
|
|||
|
|
|||
|
dwErr = NERR_Success;
|
|||
|
cleanup:
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("NetrDfsManagerInitialize returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
DFSM_TRACE_NORM(EVENT, NetrDfsManagerInitialize_End,
|
|||
|
LOGSTATUS(dwErr)
|
|||
|
LOGWSTR(ServerName));
|
|||
|
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfspGetOneEnumInfo
|
|||
|
//
|
|||
|
// Synopsis: Helper routine to read one info dfs info into an enum array.
|
|||
|
//
|
|||
|
// Arguments: [i] -- Index of the array element to fill.
|
|||
|
// [Level] -- Info Level to fill with.
|
|||
|
// [InfoArray] -- The array to use; only the ith member will be
|
|||
|
// filled.
|
|||
|
// [InfoSize] -- On successful return, size in bytes of info.
|
|||
|
// [ResumeHandle] -- Handle to indicate the information to fill.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
DfspGetOneEnumInfo(
|
|||
|
DWORD i,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray,
|
|||
|
LPDWORD InfoSize,
|
|||
|
LPDWORD ResumeHandle)
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
LPWSTR wszObject;
|
|||
|
CDfsVolume *pDfsVolume;
|
|||
|
LPDFS_INFO_3 pDfsInfo;
|
|||
|
|
|||
|
//
|
|||
|
// Get the object name for the object indicated in ResumeHandle. i == 0
|
|||
|
// means that this is the first time this function is being called for
|
|||
|
// this enum, so we are forced to get object name by index. If i > 0, then
|
|||
|
// we can get the object name by using the "get next" capability of
|
|||
|
// CStorageDirectory::GetObjectByIndex.
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsmStorageDirectory == NULL) {
|
|||
|
|
|||
|
return(ERROR_NO_MORE_ITEMS);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == 0) {
|
|||
|
|
|||
|
status = pDfsmStorageDirectory->GetObjectByIndex(*ResumeHandle, &wszObject);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = pDfsmStorageDirectory->GetObjectByIndex((DWORD)~0, &wszObject);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
return( status );
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfspGetOneEnumInfo(%d,%d)\n", i, Level);
|
|||
|
#endif
|
|||
|
|
|||
|
pDfsVolume = new CDfsVolume();
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint(" pDfsVolume = 0x%x\n", pDfsVolume);
|
|||
|
#endif
|
|||
|
|
|||
|
if (pDfsVolume != NULL) {
|
|||
|
|
|||
|
status = pDfsVolume->Load(wszObject, 0);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint(" pDfsVolume->Load returned %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
switch (Level) {
|
|||
|
case 1:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_1));
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_2));
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_3));
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_4));
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ASSERT( FALSE && "Invalid Info Level" );
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
status = pDfsVolume->GetNetInfo(Level, pDfsInfo, InfoSize);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint(" pDfsVolume->GetNetInfo returned %d\n", status);
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pDfsVolume->Release();
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
(*ResumeHandle)++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = NERR_DfsInternalCorruption;
|
|||
|
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspGetOneEnumInfo_Error1, LOGSTATUS(status));
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspGetOneEnumInfo_Error2, LOGSTATUS(status));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
delete [] wszObject;
|
|||
|
|
|||
|
return( status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfspGetOneEnumInfoEx
|
|||
|
//
|
|||
|
// Synopsis: Helper routine to read one info dfs info into an enum array.
|
|||
|
//
|
|||
|
// Arguments: [pDfsVolList] pointer to DFS_VOLUME_LIST to use
|
|||
|
// [i] -- Index of the array element to fill.
|
|||
|
// [Level] -- Info Level to fill with.
|
|||
|
// [InfoArray] -- The array to use; only the ith member will be
|
|||
|
// filled.
|
|||
|
// [InfoSize] -- On successful return, size in bytes of info.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
DfspGetOneEnumInfoEx(
|
|||
|
PDFS_VOLUME_LIST pDfsVolList,
|
|||
|
DWORD i,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray,
|
|||
|
LPDWORD InfoSize)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
LPWSTR wszObject;
|
|||
|
LPDFS_INFO_3 pDfsInfo;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfspGetOneEnumInfoEx(%d,%d)\n", i, Level);
|
|||
|
#endif
|
|||
|
|
|||
|
if (pDfsVolList == NULL || i >= pDfsVolList->VolCount) {
|
|||
|
|
|||
|
dwErr = ERROR_NO_MORE_ITEMS;
|
|||
|
goto AllDone;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
switch (Level) {
|
|||
|
case 1:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_1));
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_2));
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_3));
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + i * sizeof(DFS_INFO_4));
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
// 447489. fix prefix bug.
|
|||
|
return ERROR_INVALID_LEVEL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
dwErr = GetNetInfoEx(&pDfsVolList->Volumes[i], Level, pDfsInfo, InfoSize);
|
|||
|
|
|||
|
AllDone:
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfspGetOneEnumInfoEx returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfspFreeOneEnumInfo
|
|||
|
//
|
|||
|
// Synopsis: Worker routine to free one DFS_INFO_x struct as allocated
|
|||
|
// by DfspGetOneEnumInfo. Useful for cleanup in case of error.
|
|||
|
//
|
|||
|
// Arguments: [Idx] -- Index of the array element to free.
|
|||
|
// [Level] -- Level of info to free.
|
|||
|
// [InfoArray] -- The array to use; only the members of the ith
|
|||
|
// element will be freed.
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
DfspFreeOneEnumInfo(
|
|||
|
DWORD Idx,
|
|||
|
DWORD Level,
|
|||
|
LPBYTE InfoArray)
|
|||
|
{
|
|||
|
LPDFS_INFO_3 pDfsInfo;
|
|||
|
LPDFS_INFO_4 pDfsInfo4;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
switch (Level) {
|
|||
|
case 1:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_1));
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_2));
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
pDfsInfo = (LPDFS_INFO_3) (InfoArray + Idx * sizeof(DFS_INFO_3));
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
pDfsInfo4 = (LPDFS_INFO_4) (InfoArray + Idx * sizeof(DFS_INFO_4));
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//
|
|||
|
// 447480. prefix bug. return if unknown level.
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (Level == 4) {
|
|||
|
|
|||
|
if (pDfsInfo4->EntryPath != NULL) {
|
|||
|
MIDL_user_free(pDfsInfo4->EntryPath);
|
|||
|
}
|
|||
|
|
|||
|
if (pDfsInfo4->Comment != NULL) {
|
|||
|
MIDL_user_free(pDfsInfo4->Comment);
|
|||
|
}
|
|||
|
|
|||
|
if (pDfsInfo4->Storage != NULL) {
|
|||
|
|
|||
|
for (i = 0; i < pDfsInfo4->NumberOfStorages; i++) {
|
|||
|
|
|||
|
if (pDfsInfo4->Storage[i].ServerName != NULL)
|
|||
|
MIDL_user_free(pDfsInfo4->Storage[i].ServerName);
|
|||
|
|
|||
|
if (pDfsInfo4->Storage[i].ShareName != NULL)
|
|||
|
MIDL_user_free(pDfsInfo4->Storage[i].ShareName);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
MIDL_user_free(pDfsInfo4->Storage);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup the Level 1 stuff.
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsInfo->EntryPath != NULL)
|
|||
|
MIDL_user_free(pDfsInfo->EntryPath);
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup the Level 2 stuff if needed.
|
|||
|
//
|
|||
|
|
|||
|
if (Level > 1 && pDfsInfo->Comment != NULL)
|
|||
|
MIDL_user_free(pDfsInfo->Comment);
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup the Level 3 stuff if needed.
|
|||
|
//
|
|||
|
|
|||
|
if (Level > 2 && pDfsInfo->Storage != NULL) {
|
|||
|
|
|||
|
for (i = 0; i < pDfsInfo->NumberOfStorages; i++) {
|
|||
|
|
|||
|
if (pDfsInfo->Storage[i].ServerName != NULL)
|
|||
|
MIDL_user_free(pDfsInfo->Storage[i].ServerName);
|
|||
|
|
|||
|
if (pDfsInfo->Storage[i].ShareName != NULL)
|
|||
|
MIDL_user_free(pDfsInfo->Storage[i].ShareName);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
MIDL_user_free(pDfsInfo->Storage);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsManagerCreateVolumeObject
|
|||
|
//
|
|||
|
// Synopsis: Bootstrap routine to create a volume object directly (ie,
|
|||
|
// without having to call DfsCreateChildVolume on a parent
|
|||
|
// volume)
|
|||
|
//
|
|||
|
// Arguments: [pwszObjectName] -- Name of the volume object.
|
|||
|
// [pwszPrefix] -- Entry Path of dfs volume.
|
|||
|
// [pwszServer] -- Name of server supporting dfs volume.
|
|||
|
// [pwszShare] -- Name of share on server supporting dfs volume.
|
|||
|
// [pwszComment] -- Comment for dfs volume.
|
|||
|
// [guidVolume] -- Id of dfs volume.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" DWORD
|
|||
|
DfsManagerCreateVolumeObject(
|
|||
|
IN LPWSTR pwszObjectName,
|
|||
|
IN LPWSTR pwszPrefix,
|
|||
|
IN LPWSTR pwszServer,
|
|||
|
IN LPWSTR pwszShare,
|
|||
|
IN LPWSTR pwszComment,
|
|||
|
IN GUID *guidVolume)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
DWORD dwStatus;
|
|||
|
CDfsVolume *pCDfsVolume;
|
|||
|
DFS_REPLICA_INFO replicaInfo;
|
|||
|
LPDFS_SITELIST_INFO pSiteInfo;
|
|||
|
|
|||
|
pCDfsVolume = new CDfsVolume();
|
|||
|
|
|||
|
if (pCDfsVolume != NULL) {
|
|||
|
|
|||
|
replicaInfo.ulReplicaType = DFS_STORAGE_TYPE_DFS;
|
|||
|
replicaInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
|
|||
|
replicaInfo.pwszServerName = pwszServer;
|
|||
|
replicaInfo.pwszShareName = pwszShare;
|
|||
|
|
|||
|
dwErr = pCDfsVolume->CreateObject(
|
|||
|
pwszObjectName,
|
|||
|
pwszPrefix,
|
|||
|
DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC,
|
|||
|
&replicaInfo,
|
|||
|
pwszComment,
|
|||
|
guidVolume);
|
|||
|
|
|||
|
//
|
|||
|
// Create the site table object in the DS or registry
|
|||
|
//
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
|
|||
|
dwErr = LdapCreateObject(
|
|||
|
LDAP_VOLUMES_DIR SITE_ROOT);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// registry stuff instead
|
|||
|
|
|||
|
dwErr = RegCreateObject(
|
|||
|
VOLUMES_DIR SITE_ROOT);
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Find out the list of covered sites
|
|||
|
// We continue even if this fails (standalone, no TCP/IP)
|
|||
|
//
|
|||
|
pSiteInfo = NULL;
|
|||
|
|
|||
|
dwStatus = I_NetDfsManagerReportSiteInfo(
|
|||
|
pwszServer,
|
|||
|
&pSiteInfo);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(dwStatus, ALL_ERROR, DfsManagerCreateVolumeObject_Error_I_NetDfsManagerReportSiteInfo,
|
|||
|
LOGSTATUS(dwStatus)
|
|||
|
LOGWSTR(pwszObjectName)
|
|||
|
LOGWSTR(pwszPrefix)
|
|||
|
LOGWSTR(pwszServer)
|
|||
|
LOGWSTR(pwszShare));
|
|||
|
//
|
|||
|
// Create a SiteTable object with those sites
|
|||
|
//
|
|||
|
|
|||
|
if (dwStatus == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (pSiteInfo->cSites > 0) {
|
|||
|
|
|||
|
//
|
|||
|
// AddRef the site table, then put the site info in, then
|
|||
|
// Release it. This will cause it to be written to the
|
|||
|
// appropriate store (ldap or registry).
|
|||
|
//
|
|||
|
|
|||
|
pDfsmSites->AddRef();
|
|||
|
|
|||
|
pDfsmSites->AddOrUpdateSiteInfo(
|
|||
|
pwszServer,
|
|||
|
pSiteInfo->cSites,
|
|||
|
&pSiteInfo->Site[0]);
|
|||
|
|
|||
|
pDfsmSites->Release();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NetApiBufferFree(pSiteInfo);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pCDfsVolume->Release();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsManagerSetDcName
|
|||
|
//
|
|||
|
// Synopsis: Sets the DC we should first attempt to connect to.
|
|||
|
//
|
|||
|
// Arguments: [pwszDCName] -- Name of the DC
|
|||
|
//
|
|||
|
// Returns: ERROR_SUCCESS
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" DWORD
|
|||
|
DfsManagerSetDcName(
|
|||
|
IN LPWSTR pwszDCName)
|
|||
|
{
|
|||
|
if (pwszDSMachineName != NULL) {
|
|||
|
if (wcscmp(pwszDSMachineName, pwszDCName) != 0) {
|
|||
|
wcscpy(wszDSMachineName, pwszDCName);
|
|||
|
pwszDSMachineName = wszDSMachineName;
|
|||
|
if (pLdapConnection != NULL) {
|
|||
|
if (DfsSvcLdap)
|
|||
|
DbgPrint("DfsManagerSetDcName:ldap_unbind()\n");
|
|||
|
ldap_unbind(pLdapConnection);
|
|||
|
pLdapConnection = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
wcscpy(wszDSMachineName, pwszDCName);
|
|||
|
pwszDSMachineName = wszDSMachineName;
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsManagerAddService
|
|||
|
//
|
|||
|
// Synopsis: Bootstrap routine for adding a service to an existing volume
|
|||
|
// object. Used to set up additional root servers in an FTDfs
|
|||
|
// setup.
|
|||
|
//
|
|||
|
// Arguments: [pwszFullObjectName] -- Name of the volume object.
|
|||
|
// [pwszServer] -- Name of server to add.
|
|||
|
// [pwszShare] -- Name of share.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
extern "C" DWORD
|
|||
|
DfsManagerAddService(
|
|||
|
IN LPWSTR pwszFullObjectName,
|
|||
|
IN LPWSTR pwszServer,
|
|||
|
IN LPWSTR pwszShare,
|
|||
|
OUT GUID *guidVolume)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
DWORD dwStatus;
|
|||
|
CDfsVolume *pCDfsVolume;
|
|||
|
DFS_REPLICA_INFO replicaInfo;
|
|||
|
LPDFS_SITELIST_INFO pSiteInfo;
|
|||
|
|
|||
|
pCDfsVolume = new CDfsVolume();
|
|||
|
|
|||
|
if (pCDfsVolume != NULL) {
|
|||
|
|
|||
|
dwErr = pCDfsVolume->Load( pwszFullObjectName, 0 );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
replicaInfo.ulReplicaType = DFS_STORAGE_TYPE_DFS;
|
|||
|
replicaInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
|
|||
|
replicaInfo.pwszServerName = pwszServer;
|
|||
|
replicaInfo.pwszShareName = pwszShare;
|
|||
|
|
|||
|
dwErr = pCDfsVolume->AddReplicaToObj( &replicaInfo );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
pCDfsVolume->GetObjectID( guidVolume );
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Find out the list of covered sites
|
|||
|
// We continue even if this fails (standalone, no TCP/IP)
|
|||
|
//
|
|||
|
pSiteInfo = NULL;
|
|||
|
|
|||
|
dwStatus = I_NetDfsManagerReportSiteInfo(
|
|||
|
pwszServer,
|
|||
|
&pSiteInfo);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(dwStatus, ALL_ERROR, DfsManagerAddService_Error_I_NetDfsManagerReportSiteInfo,
|
|||
|
LOGSTATUS(dwStatus)
|
|||
|
LOGWSTR(pwszFullObjectName)
|
|||
|
LOGWSTR(pwszServer)
|
|||
|
LOGWSTR(pwszShare));
|
|||
|
//
|
|||
|
// Create a SiteTable object with those sites
|
|||
|
//
|
|||
|
|
|||
|
if (dwStatus == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (pSiteInfo->cSites > 0) {
|
|||
|
|
|||
|
//
|
|||
|
// AddRef the site table, then put the site info in, then
|
|||
|
// Release it. This will cause it to be written to the
|
|||
|
// appropriate store (ldap or registry).
|
|||
|
//
|
|||
|
|
|||
|
pDfsmSites->AddRef();
|
|||
|
|
|||
|
pDfsmSites->AddOrUpdateSiteInfo(
|
|||
|
pwszServer,
|
|||
|
pSiteInfo->cSites,
|
|||
|
&pSiteInfo->Site[0]);
|
|||
|
|
|||
|
pDfsmSites->Release();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NetApiBufferFree(pSiteInfo);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pCDfsVolume->Release();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsManagerRemoveService
|
|||
|
//
|
|||
|
// Synopsis: Bootstrap routine for removing a service from an existing
|
|||
|
// volume object. Used to remove root servers in an FTDfs
|
|||
|
// setup.
|
|||
|
//
|
|||
|
// Arguments: [pwszFullObjectName] -- Name of the volume object.
|
|||
|
// [pwszServer] -- Name of server to remove.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
DfsManagerRemoveService(
|
|||
|
IN LPWSTR pwszFullObjectName,
|
|||
|
IN LPWSTR pwszServer)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
CDfsVolume *pCDfsVolume;
|
|||
|
|
|||
|
pCDfsVolume = new CDfsVolume();
|
|||
|
|
|||
|
if (pCDfsVolume != NULL) {
|
|||
|
|
|||
|
dwErr = pCDfsVolume->Load( pwszFullObjectName, 0 );
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
dwErr = pCDfsVolume->RemoveReplicaFromObj( pwszServer );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pCDfsVolume->Release();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsManagerRemoveServiceForced
|
|||
|
//
|
|||
|
// Synopsis: Routine for removing a service from an existing
|
|||
|
// volume object in the DS. Used to remove root servers in an FTDfs
|
|||
|
// setup, even if the server is not up.
|
|||
|
//
|
|||
|
// Arguments: [wszServerName] -- Name of server to remove
|
|||
|
// [wszDCName] -- Name of DC to use
|
|||
|
// [wszFtDfsName] -- Name of the FtDfs
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
DfsManagerRemoveServiceForced(
|
|||
|
LPWSTR wszServerName,
|
|||
|
LPWSTR wszDCName,
|
|||
|
LPWSTR wszFtDfsName)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
DFS_VOLUME_LIST DfsVolList;
|
|||
|
ULONG cbBlob = 0;
|
|||
|
BYTE *pBlob = NULL;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfsManagerRemoveServiceForced(%ws,%ws,%ws)\n",
|
|||
|
wszServerName,
|
|||
|
wszDCName,
|
|||
|
wszFtDfsName);
|
|||
|
#endif
|
|||
|
|
|||
|
RtlZeroMemory(&DfsVolList, sizeof(DFS_VOLUME_LIST));
|
|||
|
|
|||
|
//
|
|||
|
// Get blob from Ds
|
|||
|
//
|
|||
|
dwErr = DfsGetDsBlob(
|
|||
|
wszFtDfsName,
|
|||
|
wszDCName,
|
|||
|
&cbBlob,
|
|||
|
&pBlob);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
//
|
|||
|
// Unserialize it
|
|||
|
//
|
|||
|
dwErr = DfsGetVolList(
|
|||
|
cbBlob,
|
|||
|
pBlob,
|
|||
|
&DfsVolList);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
//
|
|||
|
// Free the blob
|
|||
|
//
|
|||
|
free(pBlob);
|
|||
|
pBlob = NULL;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DfsDumpVolList(&DfsVolList);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Remove the root/server/machine
|
|||
|
//
|
|||
|
dwErr = DfsRemoveRootReplica(&DfsVolList, wszServerName);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DfsDumpVolList(&DfsVolList);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Serialize it
|
|||
|
//
|
|||
|
dwErr = DfsPutVolList(
|
|||
|
&cbBlob,
|
|||
|
&pBlob,
|
|||
|
&DfsVolList);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
goto Cleanup;
|
|||
|
|
|||
|
//
|
|||
|
// Update the DS
|
|||
|
//
|
|||
|
dwErr = DfsPutDsBlob(
|
|||
|
wszFtDfsName,
|
|||
|
wszDCName,
|
|||
|
cbBlob,
|
|||
|
pBlob);
|
|||
|
|
|||
|
//
|
|||
|
// Free the volume list we created
|
|||
|
//
|
|||
|
DfsFreeVolList(&DfsVolList);
|
|||
|
|
|||
|
Cleanup:
|
|||
|
if (pBlob != NULL)
|
|||
|
free(pBlob);
|
|||
|
|
|||
|
if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL)
|
|||
|
DfsFreeVolList(&DfsVolList);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("DfsManagerRemoveServiceForced returning %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfspAllocateRelationInfo
|
|||
|
//
|
|||
|
// Synopsis: Allocates and fills a RPC compliant DFSM_RELATION_INFO struct
|
|||
|
//
|
|||
|
// Arguments: [pDfsRelationInfo] -- The DFS_PKT_RELATION_INFO to use as a
|
|||
|
// the source.
|
|||
|
// [ppRelationInfo] -- On successful return, pointer to allocated
|
|||
|
// DFSM_RELATION_INFO.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully returning RelationInfo
|
|||
|
//
|
|||
|
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate RelationInfo
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
DfspAllocateRelationInfo(
|
|||
|
IN PDFS_PKT_RELATION_INFO pDfsRelationInfo,
|
|||
|
OUT LPDFSM_RELATION_INFO *ppRelationInfo)
|
|||
|
{
|
|||
|
LPDFSM_RELATION_INFO pRelationInfo;
|
|||
|
DWORD i, cbSize, dwErr;
|
|||
|
LPDFSM_ENTRY_ID pEntryId;
|
|||
|
LPWSTR pwszEntryPath;
|
|||
|
|
|||
|
cbSize = sizeof(DFSM_RELATION_INFO);
|
|||
|
|
|||
|
for (i = 0; i < pDfsRelationInfo->SubordinateIdCount; i++) {
|
|||
|
|
|||
|
cbSize += sizeof(DFSM_ENTRY_ID) +
|
|||
|
pDfsRelationInfo->SubordinateIdList[i].Prefix.Length +
|
|||
|
sizeof(UNICODE_NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pRelationInfo = (LPDFSM_RELATION_INFO) MIDL_user_allocate( cbSize );
|
|||
|
|
|||
|
if (pRelationInfo != NULL) {
|
|||
|
|
|||
|
pRelationInfo->cSubordinates = pDfsRelationInfo->SubordinateIdCount;
|
|||
|
|
|||
|
pEntryId = &pRelationInfo->eid[0];
|
|||
|
|
|||
|
pwszEntryPath = (LPWSTR)
|
|||
|
(((PBYTE) pRelationInfo) +
|
|||
|
sizeof(DFSM_RELATION_INFO) +
|
|||
|
(pDfsRelationInfo->SubordinateIdCount
|
|||
|
* sizeof(DFSM_ENTRY_ID)));
|
|||
|
|
|||
|
for (i = 0;
|
|||
|
i < pDfsRelationInfo->SubordinateIdCount;
|
|||
|
i++, pEntryId++) {
|
|||
|
|
|||
|
pEntryId->idSubordinate =
|
|||
|
pDfsRelationInfo->SubordinateIdList[i].Uid;
|
|||
|
|
|||
|
pEntryId->wszSubordinate = pwszEntryPath;
|
|||
|
|
|||
|
CopyMemory(
|
|||
|
pwszEntryPath,
|
|||
|
pDfsRelationInfo->SubordinateIdList[i].Prefix.Buffer,
|
|||
|
pDfsRelationInfo->SubordinateIdList[i].Prefix.Length);
|
|||
|
|
|||
|
pwszEntryPath +=
|
|||
|
pDfsRelationInfo->SubordinateIdList[i].Prefix.Length /
|
|||
|
sizeof(WCHAR);
|
|||
|
|
|||
|
*pwszEntryPath = UNICODE_NULL;
|
|||
|
|
|||
|
pwszEntryPath++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*ppRelationInfo = pRelationInfo;
|
|||
|
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetDomAndComputerName
|
|||
|
//
|
|||
|
// Synopsis: Retrieves the domain and computer name of the local machine
|
|||
|
//
|
|||
|
// Arguments: [wszDomain] -- On successful return, contains name of domain.
|
|||
|
// If this parameter is NULL on entry, the domain name is
|
|||
|
// not returned.
|
|||
|
//
|
|||
|
// [wszComputer] -- On successful return, contains name of
|
|||
|
// computer. If this parameter is NULL on entry, the
|
|||
|
// computer name is not returned.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully returning names.
|
|||
|
//
|
|||
|
// Win32 Error from calling NetWkstaGetInfo
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
GetDomAndComputerName(
|
|||
|
LPWSTR wszDomain OPTIONAL,
|
|||
|
LPWSTR wszComputer OPTIONAL,
|
|||
|
PDFS_NAME_CONVENTION pNameType)
|
|||
|
{
|
|||
|
DWORD dwErrNetBios = ERROR_SUCCESS;
|
|||
|
DWORD dwErrDns = ERROR_SUCCESS;
|
|||
|
PWKSTA_INFO_100 wkstaInfo = NULL;
|
|||
|
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL;
|
|||
|
DWORD Idx = 0;
|
|||
|
DFS_NAME_CONVENTION NameType = *pNameType;
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("GetDomAndComputerName(0x%x,0x%x,%ws)\n",
|
|||
|
wszDomain,
|
|||
|
wszComputer,
|
|||
|
NameType == DFS_NAMETYPE_NETBIOS ? L"DFS_NAMETYPE_NETBIOS" :
|
|||
|
NameType == DFS_NAMETYPE_DNS ? L"DFS_NAMETYPE_DNS" :
|
|||
|
L"DFS_NAMETYPE_EITHER");
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Force Netbios only unless DfsDnsConfig != 0
|
|||
|
//
|
|||
|
if (DfsDnsConfig == 0) {
|
|||
|
NameType = DFS_NAMETYPE_NETBIOS;
|
|||
|
}
|
|||
|
|
|||
|
if (NameType == DFS_NAMETYPE_NETBIOS || NameType == DFS_NAMETYPE_EITHER) {
|
|||
|
|
|||
|
dwErrNetBios = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo );
|
|||
|
|
|||
|
if (dwErrNetBios == ERROR_SUCCESS) {
|
|||
|
|
|||
|
if (wszDomain)
|
|||
|
wcscpy(wszDomain, wkstaInfo->wki100_langroup);
|
|||
|
|
|||
|
if (wszComputer)
|
|||
|
wcscpy(wszComputer, wkstaInfo->wki100_computername);
|
|||
|
|
|||
|
NetApiBufferFree( wkstaInfo );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErrNetBios == ERROR_SUCCESS)
|
|||
|
*pNameType = DFS_NAMETYPE_NETBIOS;
|
|||
|
|
|||
|
if (NameType == DFS_NAMETYPE_NETBIOS) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("GetDomAndComputerName:NETBIOS:%ws,%ws\n", wszDomain, wszComputer);
|
|||
|
#endif
|
|||
|
return dwErrNetBios;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (NameType == DFS_NAMETYPE_DNS || NameType == DFS_NAMETYPE_EITHER) {
|
|||
|
|
|||
|
if (wszDomain) {
|
|||
|
//
|
|||
|
// Get our machine name and type/role.
|
|||
|
//
|
|||
|
dwErrDns = DsRoleGetPrimaryDomainInformation(
|
|||
|
NULL,
|
|||
|
DsRolePrimaryDomainInfoBasic,
|
|||
|
(PBYTE *)&pPrimaryDomainInfo);
|
|||
|
|
|||
|
if (dwErrDns == ERROR_SUCCESS) {
|
|||
|
if (pPrimaryDomainInfo->DomainNameDns != NULL) {
|
|||
|
if (wcslen(pPrimaryDomainInfo->DomainNameDns) < MAX_PATH) {
|
|||
|
wcscpy(wszDomain, pPrimaryDomainInfo->DomainNameDns);
|
|||
|
} else {
|
|||
|
dwErrDns = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (pPrimaryDomainInfo != NULL) {
|
|||
|
DsRoleFreeMemory(pPrimaryDomainInfo);
|
|||
|
pPrimaryDomainInfo = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (wszComputer && dwErrDns == ERROR_SUCCESS) {
|
|||
|
Idx = MAX_PATH;
|
|||
|
if (!GetComputerNameEx(
|
|||
|
ComputerNameDnsFullyQualified,
|
|||
|
wszComputer,
|
|||
|
&Idx))
|
|||
|
dwErrDns = GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
if (dwErrDns == ERROR_SUCCESS)
|
|||
|
*pNameType = DFS_NAMETYPE_DNS;
|
|||
|
|
|||
|
if (NameType == DFS_NAMETYPE_DNS) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("GetDomAndComputerName:DNS:%ws,%ws\n", wszDomain, wszComputer);
|
|||
|
#endif
|
|||
|
return dwErrDns;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// NameType must be DFS_NAMETYPE_EITHER
|
|||
|
//
|
|||
|
|
|||
|
if (*pNameType == DFS_NAMETYPE_DNS) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("GetDomAndComputerName:EITHER(DNS)%ws,%ws\n", wszDomain, wszComputer);
|
|||
|
#endif
|
|||
|
return dwErrDns;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("GetDomAndComputerName:EITHER(NETBIOS)%ws,%ws\n", wszDomain, wszComputer);
|
|||
|
#endif
|
|||
|
|
|||
|
return dwErrNetBios;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// ====================================================================
|
|||
|
// MIDL allocate and free
|
|||
|
// ====================================================================
|
|||
|
|
|||
|
PVOID
|
|||
|
MIDL_user_allocate(size_t len)
|
|||
|
{
|
|||
|
return malloc(len);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
MIDL_user_free(void * ptr)
|
|||
|
{
|
|||
|
free(ptr);
|
|||
|
}
|