diff options
Diffstat (limited to 'private/net/svcdlls/dfs/client/dfsstub.c')
-rw-r--r-- | private/net/svcdlls/dfs/client/dfsstub.c | 1194 |
1 files changed, 1194 insertions, 0 deletions
diff --git a/private/net/svcdlls/dfs/client/dfsstub.c b/private/net/svcdlls/dfs/client/dfsstub.c new file mode 100644 index 000000000..dc4290baa --- /dev/null +++ b/private/net/svcdlls/dfs/client/dfsstub.c @@ -0,0 +1,1194 @@ +//+---------------------------------------------------------------------------- +// +// Copyright (C) 1995, Microsoft Corporation +// +// File: dfsstub.c +// +// Contents: Stub file for the NetDfsXXX APIs. The stubs turn around and +// call the NetrDfsXXX APIs on the appropriate server. +// +// Classes: +// +// Functions: NetDfsEnum +// +// History: 01-10-96 Milans created +// +//----------------------------------------------------------------------------- + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#include <stdlib.h> +#include <lm.h> +#include <lmdfs.h> +#include <dfsp.h> +#include <netdfs.h> +#include "domain.h" + +#define IS_UNC_PATH(wsz, cw) \ + ((cw) > 2 && (wsz)[0] == L'\\' && (wsz)[1] == L'\\') + +#define IS_VALID_PREFIX(wsz, cw) \ + ((cw) > 1 && (wsz)[0] == L'\\' && (wsz)[1] != L'\\') + +#define IS_VALID_DFS_PATH(wsz, cw) \ + ((cw) > 0 && (wsz)[0] != L'\\') + +#define IS_VALID_STRING(wsz) \ + ((wsz) != NULL && (wsz)[0] != UNICODE_NULL) + +NET_API_STATUS +DfspGetDfsNameFromEntryPath( + LPWSTR wszEntryPath, + DWORD cwEntryPath, + LPWSTR *ppwszDfsName); + +NET_API_STATUS +DfspBindRpc( + IN LPWSTR DfsName, + OUT RPC_BINDING_HANDLE *BindingHandle); + +VOID +DfspFreeBinding( + RPC_BINDING_HANDLE BindingHandle); + +NET_API_STATUS +DfspVerifyBinding(); + +// +// The APIs are all single-threaded - only 1 can be outstanding at a time in +// any one process. The following critical section is used to gate the calls. +// The critical section is initialized at DLL Load time. +// + +CRITICAL_SECTION NetDfsApiCriticalSection; + +#define ENTER_NETDFS_API EnterCriticalSection( &NetDfsApiCriticalSection ); + +#define LEAVE_NETDFS_API LeaveCriticalSection( &NetDfsApiCriticalSection ); + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsAdd +// +// Synopsis: Creates a new volume, adds a replica to an existing volume, +// or creates a link to another Dfs. +// +// Arguments: [DfsEntryPath] -- Name of volume/link to create/add replica +// to. +// [ServerName] -- Name of server hosting the storage, or for +// link, name of Dfs root. +// [ShareName] -- Name of share hosting the storage. +// [Flags] -- Describes what is being added. +// +// Returns: [NERR_Success] -- Successfully completed operation. +// +// [ERROR_INVALID_PARAMETER] -- DfsEntryPath and/or ServerName +// and/or ShareName and/or Flags are incorrect. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for DfsName. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [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] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +NetDfsAdd( + IN LPWSTR DfsEntryPath, + IN LPWSTR ServerName, + IN LPWSTR ShareName, + IN LPWSTR Comment, + IN DWORD Flags) +{ + NET_API_STATUS dwErr; + DWORD cwDfsEntryPath; + LPWSTR pwszDfsName; + + // + // Validate the string arguments so RPC won't complain... + // + + if (!IS_VALID_STRING(ServerName) || + !IS_VALID_STRING(ShareName)) { + return( ERROR_INVALID_PARAMETER ); + } + + cwDfsEntryPath = wcslen(DfsEntryPath); + + if (!IS_UNC_PATH(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_PREFIX(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_DFS_PATH(DfsEntryPath, cwDfsEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + DfsEntryPath, + cwDfsEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + dwErr = DfspBindRpc(pwszDfsName, &netdfs_bhandle); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + dwErr = NetrDfsAdd( + DfsEntryPath, + ServerName, + ShareName, + Comment, + Flags); + + } RpcExcept(1) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsRemove +// +// Synopsis: Deletes a Dfs volume, removes a replica from an existing +// volume, or removes a link to another Dfs. +// +// Arguments: [DfsEntryPath] -- Name of volume/link to remove. +// [ServerName] -- Name of server hosting the storage. Must be +// NULL if removing Link. +// [ShareName] -- Name of share hosting the storage. Must be +// NULL if removing Link. +// +// Returns: [NERR_Success] -- Successfully completed operation. +// +// [ERROR_INVALID_PARAMETER] -- DfsEntryPath is incorrect. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for DfsName. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [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] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +NetDfsRemove( + IN LPWSTR DfsEntryPath, + IN LPWSTR ServerName, + IN LPWSTR ShareName) +{ + NET_API_STATUS dwErr; + DWORD cwDfsEntryPath; + LPWSTR pwszDfsName; + + // + // Validate the string arguments so RPC won't complain... + // + + cwDfsEntryPath = wcslen(DfsEntryPath); + + if (!IS_UNC_PATH(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_PREFIX(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_DFS_PATH(DfsEntryPath, cwDfsEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + DfsEntryPath, + cwDfsEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + dwErr = DfspBindRpc(pwszDfsName, &netdfs_bhandle); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + dwErr = NetrDfsRemove( + DfsEntryPath, + ServerName, + ShareName); + + } RpcExcept(1) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsSetInfo +// +// Synopsis: Sets the comment or state of a Dfs volume or Replica. +// +// Arguments: [DfsEntryPath] -- Path to the volume. Implicityly indicates +// which server or domain to connect to. +// [ServerName] -- Optional. If specified, only the state of +// the server supporting this volume is modified. +// [ShareName] -- Optional. If specified, only the state of +// this share on the specified server is modified. +// [Level] -- Must be 100 or 101 +// [Buffer] -- Pointer to DFS_INFO_100 or DFS_INFO_101 +// +// Returns: [NERR_Success] -- If successfully set info. +// +// [ERROR_INVALID_LEVEL] -- Level is not 100 or 101 +// +// [ERROR_INVALID_PARAMETER] -- Either DfsEntryPath is NULL, +// or ShareName is specified but ServerName is not, or +// Buffer is NULL. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for domain. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [NERR_DfsNoSuchVolume] -- No volume matches DfsEntryPath. +// +// [NERR_DfsNoSuchShare] -- The indicated ServerName/ShareName do +// not support this Dfs volume. +// +// [NERR_DfsInternalCorruption] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS NET_API_FUNCTION +NetDfsSetInfo( + IN LPWSTR DfsEntryPath, + IN LPWSTR ServerName OPTIONAL, + IN LPWSTR ShareName OPTIONAL, + IN DWORD Level, + IN LPBYTE Buffer) +{ + NET_API_STATUS dwErr; + LPWSTR pwszDfsName; + DWORD cwDfsEntryPath; + DFS_INFO_STRUCT DfsInfo; + + // + // Some elementary parameter checking to make sure we can proceed + // reasonably... + // + + if (Level != 100 && Level != 101) { + return( ERROR_INVALID_LEVEL ); + } + + cwDfsEntryPath = wcslen(DfsEntryPath); + + if (!IS_UNC_PATH(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_PREFIX(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_DFS_PATH(DfsEntryPath, cwDfsEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + if (!IS_VALID_STRING(ServerName) && IS_VALID_STRING(ShareName)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + DfsEntryPath, + cwDfsEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + // + // By now, we should have a valid pwszDfsName. Lets try to bind to it, + // and call the server. + // + + dwErr = DfspBindRpc( pwszDfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + DfsInfo.DfsInfo100 = (LPDFS_INFO_100) Buffer; + + dwErr = NetrDfsSetInfo( + DfsEntryPath, + ServerName, + ShareName, + Level, + &DfsInfo); + + } RpcExcept( 1 ) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsGetInfo +// +// Synopsis: Retrieves information about a particular Dfs volume. +// +// Arguments: [DfsEntryPath] -- Path to the volume. Implicitly indicates +// which server or domain to connect to. +// [ServerName] -- Optional. If specified, indicates the +// server supporting DfsEntryPath. +// [ShareName] -- Optional. If specified, indicates the share +// on ServerName for which info is desired. +// [Level] -- Indicates the level of info required. +// [Buffer] -- On successful return, will contain the buffer +// containing the required Info. This buffer should be +// freed using NetApiBufferFree. +// +// Returns: [NERR_Success] -- Info successfully returned. +// +// [ERROR_INVALID_LEVEL] -- Level is not 1,2,3,100, or 101 +// +// [ERROR_INVALID_PARAMETER] -- Either DfsEntryPath is NULL, +// or ShareName is specified but ServerName is NULL. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for domain. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [NERR_DfsNoSuchVolume] -- No volume matches DfsEntryPath. +// +// [NERR_DfsInternalCorruption] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS NET_API_FUNCTION +NetDfsGetInfo( + IN LPWSTR DfsEntryPath, + IN LPWSTR ServerName OPTIONAL, + IN LPWSTR ShareName OPTIONAL, + IN DWORD Level, + OUT LPBYTE* Buffer) +{ + NET_API_STATUS dwErr; + LPWSTR pwszDfsName; + DWORD cwDfsEntryPath; + DFS_INFO_STRUCT DfsInfo; + + // + // Some elementary parameter checking to make sure we can proceed + // reasonably... + // + + if (!(Level >= 1 && Level <= 3) && !(Level >= 100 && Level <= 101)) { + return( ERROR_INVALID_LEVEL ); + } + + cwDfsEntryPath = wcslen(DfsEntryPath); + + if (!IS_UNC_PATH(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_PREFIX(DfsEntryPath, cwDfsEntryPath) && + !IS_VALID_DFS_PATH(DfsEntryPath, cwDfsEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + if (!IS_VALID_STRING(ServerName) && IS_VALID_STRING(ShareName)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + DfsEntryPath, + cwDfsEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + // + // By now, we should have a valid pwszDfsName. Lets try to bind to it, + // and call the server. + // + + dwErr = DfspBindRpc( pwszDfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + DfsInfo.DfsInfo1 = NULL; + + dwErr = NetrDfsGetInfo( + DfsEntryPath, + ServerName, + ShareName, + Level, + &DfsInfo); + + if (dwErr == NERR_Success) { + + *Buffer = (LPBYTE) DfsInfo.DfsInfo1; + + } + + } RpcExcept( 1 ) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function +// +// Synopsis: Enumerates the Dfs volumes. +// +// Arguments: [DfsName] -- Name of server or domain whose Dfs is being +// enumerated. A leading \\ is optional. +// [Level] -- Indicates the level of info needed back. Valid +// Levels are 1,2, and 3. +// [PrefMaxLen] -- Preferred maximum length of return buffer. +// [Buffer] -- On successful return, contains an array of +// DFS_INFO_X. This buffer should be freed with a call +// to NetApiBufferFree. +// [EntriesRead] -- On successful return, contains the number +// of entries read (and therefore, size of the array in +// Buffer). +// [ResumeHandle] -- Must be 0 on first call. On subsequent calls +// the value returned by the immediately preceding call. +// +// Returns: [NERR_Success] -- Enum data successfully returned. +// +// [ERROR_INVALID_LEVEL] -- The Level specified in invalid. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for DfsName. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [ERROR_NO_MORE_ITEMS] -- No more volumes to be enumerated. +// +// [NERR_DfsInternalCorruption] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS NET_API_FUNCTION +NetDfsEnum( + IN LPWSTR DfsName, + IN DWORD Level, + IN DWORD PrefMaxLen, + OUT LPBYTE* Buffer, + OUT LPDWORD EntriesRead, + IN OUT LPDWORD ResumeHandle) +{ + NET_API_STATUS dwErr; + DFS_INFO_ENUM_STRUCT DfsEnum; + DFS_INFO_3_CONTAINER DfsInfo3Container; + + // + // Check the Level Parameter first, or RPC won't know how to marshal the + // arguments. + // + + if (Level != 1 && Level != 2 && Level != 3) { + return( ERROR_INVALID_LEVEL ); + } + + ENTER_NETDFS_API + + dwErr = DfspBindRpc( DfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + DfsInfo3Container.EntriesRead = 0; + DfsInfo3Container.Buffer = NULL; + + DfsEnum.Level = Level; + DfsEnum.DfsInfoContainer.DfsInfo3Container = &DfsInfo3Container; + + RpcTryExcept { + + dwErr = NetrDfsEnum( + Level, + PrefMaxLen, + &DfsEnum, + ResumeHandle); + + if (dwErr == NERR_Success) { + + *EntriesRead =DfsInfo3Container.EntriesRead; + + *Buffer = (LPBYTE) DfsInfo3Container.Buffer; + + } + + } RpcExcept( 1 ) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsMove +// +// Synopsis: Moves a dfs volume to a new place in the Dfs hierarchy. +// +// Arguments: [DfsEntryPath] -- Current path to the volume. +// [NewDfsEntryPath] -- Desired new path to the volume. +// +// Returns: [NERR_Success] -- Info successfully returned. +// +// [ERROR_INVALID_PARAMETER] -- Either DfsEntryPath or +// NewDfsEntryPath are not valid. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for domain. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [NERR_DfsNoSuchVolume] -- No volume matches DfsEntryPath. +// +// [NERR_DfsInternalCorruption] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +NetDfsMove( + IN LPWSTR DfsEntryPath, + IN LPWSTR NewDfsEntryPath) +{ + NET_API_STATUS dwErr; + DWORD cwEntryPath; + LPWSTR pwszDfsName; + + // + // Validate the input arguments... + // + + cwEntryPath = wcslen( NewDfsEntryPath ); + + if (!IS_UNC_PATH(NewDfsEntryPath, cwEntryPath) && + !IS_VALID_PREFIX(NewDfsEntryPath, cwEntryPath) && + !IS_VALID_DFS_PATH(NewDfsEntryPath, cwEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + cwEntryPath = wcslen( DfsEntryPath ); + + if (!IS_UNC_PATH(DfsEntryPath, cwEntryPath) && + !IS_VALID_PREFIX(DfsEntryPath, cwEntryPath) && + !IS_VALID_DFS_PATH(DfsEntryPath, cwEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + DfsEntryPath, + cwEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + // + // By now, we should have a valid pwszDfsName. Lets try to bind to it, + // and call the server. + // + + dwErr = DfspBindRpc( pwszDfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + dwErr = NetrDfsMove( DfsEntryPath, NewDfsEntryPath ); + + } RpcExcept(1) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsRename +// +// Synopsis: Renames a path that is along a Dfs Volume Entry Path +// +// Arguments: [Path] -- Current path. +// [NewPath] -- Desired new path. +// +// Returns: [NERR_Success] -- Info successfully returned. +// +// [ERROR_INVALID_PARAMETER] -- Either DfsEntryPath or +// NewDfsEntryPath are not valid. +// +// [ERROR_INVALID_NAME] -- Unable to locate server or domain. +// +// [ERROR_DCNotFound] -- Unable to locate DC for domain. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +// [NERR_DfsNoSuchVolume] -- No volume matches DfsEntryPath. +// +// [NERR_DfsInternalCorruption] -- Corruption of Dfs data +// encountered at the server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +NetDfsRename( + IN LPWSTR Path, + IN LPWSTR NewPath) +{ + NET_API_STATUS dwErr; + DWORD cwPath; + LPWSTR pwszDfsName; + + // + // Validate the input arguments... + // + + cwPath = wcslen( NewPath ); + + if (!IS_UNC_PATH(NewPath, cwPath) && + !IS_VALID_PREFIX(NewPath, cwPath) && + !IS_VALID_DFS_PATH(NewPath, cwPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + cwPath = wcslen( Path ); + + if (!IS_UNC_PATH(Path, cwPath) && + !IS_VALID_PREFIX(Path, cwPath) && + !IS_VALID_DFS_PATH(Path, cwPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + Path, + cwPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + // + // By now, we should have a valid pwszDfsName. Lets try to bind to it, + // and call the server. + // + + dwErr = DfspBindRpc( pwszDfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + dwErr = NetrDfsRename( Path, NewPath ); + + } RpcExcept(1) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: NetDfsManagerGetConfigInfo +// +// Synopsis: Given a DfsEntryPath and Guid of a local volume, this api +// remotes to the root server of the entry path and retrieves +// the config info from it. +// +// Arguments: [wszServer] -- Name of local machine +// [wszLocalVolumeEntryPath] -- Entry Path of local volume. +// [guidLocalVolume] -- Guid of local volume. +// [ppDfsmRelationInfo] -- On successful return, contains pointer +// to config info at the root server. Free using +// NetApiBufferFree. +// +// Returns: [NERR_Success] -- Info returned successfully. +// +// [ERROR_INVALID_PARAMETER] -- wszLocalVolumeEntryPath is +// invalid. +// +// [ERROR_INVALID_NAME] -- Unable to parse out server/domain name +// from wszLocalVolumeEntryPath +// +// [ERROR_DCNotFound] -- Unable to locate a DC for domain +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition +// +// [NERR_DfsNoSuchVolume] -- The root server did not recognize +// a volume with this guid/entrypath +// +// [NERR_DfsNoSuchServer] -- wszServer is not a valid server for +// wszLocalVolumeEntryPath +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +NetDfsManagerGetConfigInfo( + LPWSTR wszServer, + LPWSTR wszLocalVolumeEntryPath, + GUID guidLocalVolume, + LPDFSM_RELATION_INFO *ppDfsmRelationInfo) +{ + NET_API_STATUS dwErr; + LPWSTR pwszDfsName; + DWORD cwDfsEntryPath; + + // + // Some elementary parameter checking to make sure we can proceed + // reasonably... + // + + cwDfsEntryPath = wcslen(wszLocalVolumeEntryPath); + + if (!IS_UNC_PATH(wszLocalVolumeEntryPath, cwDfsEntryPath) && + !IS_VALID_PREFIX(wszLocalVolumeEntryPath, cwDfsEntryPath) && + !IS_VALID_DFS_PATH(wszLocalVolumeEntryPath, cwDfsEntryPath)) { + return( ERROR_INVALID_PARAMETER ); + } + + + ENTER_NETDFS_API + + dwErr = DfspGetDfsNameFromEntryPath( + wszLocalVolumeEntryPath, + cwDfsEntryPath, + &pwszDfsName); + + if (dwErr == NERR_Success) { + + // + // By now, we should have a valid pwszDfsName. Lets try to bind to it, + // and call the server. + // + + dwErr = DfspBindRpc( pwszDfsName, &netdfs_bhandle ); + + if (dwErr == NERR_Success) { + + RpcTryExcept { + + *ppDfsmRelationInfo = NULL; + + dwErr = NetrDfsManagerGetConfigInfo( + wszServer, + wszLocalVolumeEntryPath, + guidLocalVolume, + ppDfsmRelationInfo); + + } RpcExcept( 1 ) { + + dwErr = RpcExceptionCode(); + + } RpcEndExcept; + + DfspFreeBinding( netdfs_bhandle ); + + } + + free( pwszDfsName ); + + } + + LEAVE_NETDFS_API + + return( dwErr ); + +} + + +//+---------------------------------------------------------------------------- +// +// Function: DfspGetDfsNameFromEntryPath +// +// Synopsis: Given a DfsEntryPath, this routine returns the name of the +// Dfs Root. +// +// Arguments: [wszEntryPath] -- Pointer to EntryPath to parse. +// +// [cwEntryPath] -- Length in WCHAR of wszEntryPath. +// +// [ppwszDfsName] -- Name of Dfs root is returned here. Memory +// is allocated using malloc; caller resposible for +// freeing it. +// +// Returns: [NERR_Success] -- Successfully parsed out Dfs Root. +// +// [ERROR_INVALID_NAME] -- Unable to parse wszEntryPath. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for +// ppwszDfsName. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +DfspGetDfsNameFromEntryPath( + LPWSTR wszEntryPath, + DWORD cwEntryPath, + LPWSTR *ppwszDfsName) +{ + LPWSTR pwszDfsName, pwszFirst, pwszLast; + DWORD cwDfsName; + + if (IS_UNC_PATH(wszEntryPath, cwEntryPath)) { + + pwszFirst = &wszEntryPath[2]; + + } else if (IS_VALID_PREFIX(wszEntryPath, cwEntryPath)) { + + pwszFirst = &wszEntryPath[1]; + + } else if (IS_VALID_DFS_PATH(wszEntryPath, cwEntryPath)) { + + pwszFirst = &wszEntryPath[0]; + + } else { + + return( ERROR_INVALID_NAME ); + + } + + for (cwDfsName = 0, pwszLast = pwszFirst; + *pwszLast != UNICODE_NULL && *pwszLast != L'\\'; + pwszLast++, cwDfsName++) { + ; + } + + ++cwDfsName; + + pwszDfsName = malloc( cwDfsName * sizeof(WCHAR) ); + + if (pwszDfsName != NULL) { + + pwszDfsName[ cwDfsName - 1 ] = 0; + + for (cwDfsName--; cwDfsName > 0; cwDfsName--) { + + pwszDfsName[ cwDfsName - 1 ] = pwszFirst[ cwDfsName - 1 ]; + + } + + *ppwszDfsName = pwszDfsName; + + return( NERR_Success ); + + } else { + + return( ERROR_NOT_ENOUGH_MEMORY ); + + } + +} + + +//+---------------------------------------------------------------------------- +// +// Function: DfspBindRpc +// +// Synopsis: Given a server or domain name, this API will bind to the +// appropriate Dfs Manager service. +// +// Arguments: [DfsName] -- Name of domain or server. Leading \\ is optional +// +// [BindingHandle] -- On successful return, the binding handle +// is returned here. +// +// Returns: [NERR_Success] -- Binding handle successfull returned. +// +// [RPC_S_SERVER_NOT_AVAILABLE] -- Unable to bind to NetDfs +// interface on the named server or domain. +// +// [ERROR_INVALID_NAME] -- Unable to parse DfsName as a valid +// server or domain name. +// +// [ERROR_DCNotFound] -- Unable to locate DC for DfsName. +// +// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +DfspBindRpc( + IN LPWSTR DfsName, + OUT RPC_BINDING_HANDLE *BindingHandle) +{ + LPWSTR wszProtocolSeq = L"ncacn_np"; + LPWSTR wszEndPoint = L"\\pipe\\netdfs"; + LPWSTR pwszRpcBindingString = NULL; + LPWSTR pwszDCName = NULL; + NET_API_STATUS dwErr; + + // + // First, see if this is a domain name. + // + + dwErr = I_NetDfsIsThisADomainName( DfsName ); + + if (dwErr == ERROR_SUCCESS) { + + // + // Its a domain name. Get the PDC for the domain and try to bind to + // it. + // + + dwErr = NetGetDCName( NULL, DfsName, (LPBYTE *) &pwszDCName ); + + } else { + + // + // Lets see if this is a machine-based Dfs + // + + pwszDCName = DfsName; + + dwErr = ERROR_SUCCESS; + + } + + if (dwErr == ERROR_SUCCESS) { + + dwErr = RpcStringBindingCompose( + NULL, // Object UUID + wszProtocolSeq, // Protocol Sequence + pwszDCName, // Network Address + wszEndPoint, // RPC Endpoint + NULL, // RPC Options + &pwszRpcBindingString); // Returned binding string + + if (dwErr == RPC_S_OK) { + + dwErr = RpcBindingFromStringBinding( + pwszRpcBindingString, + BindingHandle); + + if (dwErr == RPC_S_OK) { + + dwErr = DfspVerifyBinding(); + + } else { + + dwErr = ERROR_INVALID_NAME; + + } + + } + + } + + if (pwszRpcBindingString != NULL) { + + RpcStringFree( &pwszRpcBindingString ); + + } + + if (pwszDCName != DfsName) { + + NetApiBufferFree( pwszDCName ); + + } + + if (dwErr == RPC_S_OUT_OF_MEMORY) { + dwErr = ERROR_NOT_ENOUGH_MEMORY; + } + + return( dwErr ); + +} + +//+---------------------------------------------------------------------------- +// +// Function: DfspFreeBinding +// +// Synopsis: Frees a binding created by DfspBindRpc +// +// Arguments: [BindingHandle] -- The handle to free. +// +// Returns: Nothing +// +//----------------------------------------------------------------------------- + +VOID +DfspFreeBinding( + RPC_BINDING_HANDLE BindingHandle) +{ + DWORD dwErr; + + dwErr = RpcBindingFree( BindingHandle ); + +} + +//+---------------------------------------------------------------------------- +// +// Function: DfspVerifyBinding +// +// Synopsis: Verifies that the binding can be used by doing a +// NetrDfsManagerGetVersion call on the binding. +// +// Arguments: None +// +// Returns: [NERR_Success] -- Server connnected to. +// +// [RPC_S_SERVER_UNAVAILABLE] -- The server is not available. +// +// Other RPC error from calling the remote server. +// +//----------------------------------------------------------------------------- + +NET_API_STATUS +DfspVerifyBinding() +{ + NET_API_STATUS status = NERR_Success; + DWORD Version; + + RpcTryExcept { + + Version = NetrDfsManagerGetVersion(); + + } RpcExcept(1) { + + status = RpcExceptionCode(); + + } RpcEndExcept; + + return( status ); + +} + |