You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
747 lines
22 KiB
747 lines
22 KiB
//--------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1999, Microsoft Corporation
|
|
//
|
|
// File: misc.cxx
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#define UNICODE 1
|
|
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <shellapi.h>
|
|
#include <dfsprefix.h>
|
|
#include <winldap.h>
|
|
#include <dsgetdc.h>
|
|
#include <lm.h>
|
|
#include <lmdfs.h>
|
|
#include <dfsfsctl.h>
|
|
}
|
|
#include <DfsServerLibrary.hxx>
|
|
#include <DfsRegStrings.hxx>
|
|
#include "struct.hxx"
|
|
#include "flush.hxx"
|
|
#include "misc.hxx"
|
|
#include "messages.h"
|
|
|
|
#include <strsafe.h>
|
|
|
|
#include <dfsutil.hxx>
|
|
#include <DfsBlobInfo.hxx>
|
|
|
|
#include "dfspathname.hxx"
|
|
|
|
DFSSTATUS
|
|
GetWin2kStandaloneMetadata (
|
|
IN HKEY DfsMetadataKey,
|
|
IN LPWSTR RelativeName,
|
|
IN LPWSTR RegistryValueNameString,
|
|
OUT PDFS_NAME_INFORMATION pNameInfo);
|
|
|
|
|
|
DFSSTATUS
|
|
SetWin2kStandaloneMetadata (
|
|
IN HKEY DfsMetadataKey,
|
|
IN LPWSTR RelativeName,
|
|
IN LPWSTR RegistryValueNameString,
|
|
IN PVOID pData,
|
|
IN ULONG DataSize );
|
|
|
|
DFSSTATUS
|
|
GetDfsRegistryKey( IN LPWSTR MachineName,
|
|
IN LPWSTR LocationString,
|
|
BOOLEAN WritePermission,
|
|
OUT BOOLEAN *pMachineContacted,
|
|
OUT PHKEY pDfsRegKey );
|
|
DFSSTATUS
|
|
GetRootPhysicalShare(
|
|
HKEY RootKey,
|
|
PUNICODE_STRING pRootPhysicalShare );
|
|
|
|
|
|
|
|
DFSSTATUS
|
|
GetRootPhysicalShare(
|
|
HKEY RootKey,
|
|
PUNICODE_STRING pRootPhysicalShare )
|
|
{
|
|
DFSSTATUS Status;
|
|
ULONG DataSize, DataType;
|
|
LPWSTR DfsRootShare = NULL;
|
|
|
|
Status = RegQueryInfoKey( RootKey, // Key
|
|
NULL, // Class string
|
|
NULL, // Size of class string
|
|
NULL, // Reserved
|
|
NULL, // # of subkeys
|
|
NULL, // max size of subkey name
|
|
NULL, // max size of class name
|
|
NULL, // # of values
|
|
NULL, // max size of value name
|
|
&DataSize, // max size of value data,
|
|
NULL, // security descriptor
|
|
NULL ); // Last write time
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DfsRootShare = (LPWSTR) new BYTE [DataSize];
|
|
if ( DfsRootShare == NULL )
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else
|
|
{
|
|
Status = RegQueryValueEx( RootKey,
|
|
DFS_REG_ROOT_SHARE_VALUE,
|
|
NULL,
|
|
&DataType,
|
|
(LPBYTE)DfsRootShare,
|
|
&DataSize );
|
|
}
|
|
}
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
if (DataType == REG_SZ)
|
|
{
|
|
RtlInitUnicodeString( pRootPhysicalShare, DfsRootShare );
|
|
}
|
|
else {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
if (DfsRootShare != NULL)
|
|
{
|
|
delete [] DfsRootShare;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
DFSSTATUS
|
|
GetDfsRegistryKey( IN LPWSTR MachineName,
|
|
IN LPWSTR LocationString,
|
|
BOOLEAN WritePermission,
|
|
OUT BOOLEAN *pMachineContacted,
|
|
OUT PHKEY pDfsRegKey )
|
|
{
|
|
DFSSTATUS Status;
|
|
HKEY RootKey;
|
|
BOOLEAN Contacted = FALSE;
|
|
LPWSTR UseMachineName = NULL;
|
|
REGSAM DesiredAccess = KEY_READ;
|
|
|
|
if (WritePermission == TRUE)
|
|
{
|
|
DesiredAccess |= KEY_WRITE;
|
|
}
|
|
|
|
if (IsEmptyString(MachineName) == FALSE) {
|
|
UseMachineName = MachineName;
|
|
}
|
|
|
|
Status = RegConnectRegistry( UseMachineName,
|
|
HKEY_LOCAL_MACHINE,
|
|
&RootKey );
|
|
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
Contacted = TRUE;
|
|
|
|
Status = RegOpenKeyEx( RootKey,
|
|
LocationString,
|
|
0,
|
|
DesiredAccess,
|
|
pDfsRegKey );
|
|
|
|
//
|
|
// There appears to be a bug in the registry code. When
|
|
// we connect to the local machine, the key that is returned
|
|
// in the RegConnectRegistry is HKEY_LOCAL_MACHINE. If we
|
|
// then attempt to close it here, it affects other threads
|
|
// that are using this code: they get STATUS_INVALID_HANDLE
|
|
// in some cases. So, dont close the key if it is
|
|
// HKEY_LOCAL_MACHINE.
|
|
//
|
|
|
|
if (RootKey != HKEY_LOCAL_MACHINE)
|
|
{
|
|
RegCloseKey( RootKey );
|
|
}
|
|
}
|
|
|
|
if (pMachineContacted != NULL)
|
|
{
|
|
*pMachineContacted = Contacted;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
DFSSTATUS
|
|
CreateNameInformationBlob(
|
|
IN PDFS_NAME_INFORMATION pDfsNameInfo,
|
|
OUT PVOID *ppBlob,
|
|
OUT PULONG pDataSize )
|
|
{
|
|
PVOID pBlob = NULL;
|
|
PVOID pUseBlob = NULL;
|
|
ULONG BlobSize = 0;
|
|
ULONG UseBlobSize = 0;
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
BlobSize = PackSizeNameInformation( pDfsNameInfo );
|
|
|
|
pBlob = (PVOID) new BYTE[BlobSize];
|
|
if (pBlob == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pUseBlob = pBlob;
|
|
UseBlobSize = BlobSize;
|
|
|
|
// Pack the name information into the binary stream allocated.
|
|
//
|
|
Status = PackSetStandaloneNameInformation( pDfsNameInfo,
|
|
&pUseBlob,
|
|
&UseBlobSize );
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
delete [] pBlob;
|
|
pBlob = NULL;
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
*ppBlob = pBlob;
|
|
*pDataSize = BlobSize - UseBlobSize;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
DFSSTATUS
|
|
DfsSetWin2kStdNameInfo(
|
|
HKEY DomainRootKey,
|
|
LPWSTR LinkName,
|
|
PDFS_NAME_INFORMATION pNameInfo)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
PVOID pBlob = NULL;
|
|
ULONG BlobSize = 0;
|
|
|
|
|
|
Status = CreateNameInformationBlob( pNameInfo,
|
|
&pBlob,
|
|
&BlobSize );
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
DebugInformation((L"Error 0x%x creating registry blob with NameInfo\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
Status = SetWin2kStandaloneMetadata( DomainRootKey,
|
|
LinkName, // Can be NULL for roots
|
|
L"ID",
|
|
pBlob,
|
|
BlobSize );
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DebugInformation((L"Successfully wrote changes to the Windows2000 standalone root\n"));
|
|
}
|
|
else
|
|
{
|
|
DebugInformation((L"Error 0x%x writing changes to the Windows2000 standalone root\n", Status));
|
|
}
|
|
}
|
|
|
|
delete [] pBlob;
|
|
|
|
return Status;
|
|
}
|
|
|
|
#if 0
|
|
DFSSTATUS
|
|
DfsGetWin2kStdReplicaInfo(
|
|
LPWSTR MachineName,
|
|
PDFS_REPLICA_LIST_INFORMATION pReplicaInfo)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
HKEY VolumesKey = NULL;
|
|
BOOLEAN MachineContacted = FALSE;
|
|
PVOID pBlob = NULL;
|
|
ULONG BlobSize = 0;
|
|
|
|
Status = GetDfsRegistryKey (MachineName,
|
|
DFS_REG_OLD_HOST_LOCATION,
|
|
FALSE,
|
|
&MachineContacted,
|
|
&VolumesKey );
|
|
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Status = GetWin2kStandaloneMetadata( VolumesKey,
|
|
DFS_REG_OLD_STANDALONE_CHILD,
|
|
L"Svc",
|
|
&pBlob,
|
|
&BlobSize );
|
|
RegCloseKey( VolumesKey );
|
|
|
|
RtlZeroMemory (pReplicaInfo, sizeof(DFS_REPLICA_LIST_INFORMATION));
|
|
|
|
Status = PackGetULong( &pReplicaInfo->ReplicaCount,
|
|
&pBlob,
|
|
&BlobSize );
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
pReplicaInfo->pReplicas = new DFS_REPLICA_INFORMATION[ pReplicaInfo->ReplicaCount];
|
|
if ( pReplicaInfo->pReplicas != NULL )
|
|
{
|
|
Status = PackGetReplicaInformation( pReplicaInfo,
|
|
&pBlob,
|
|
&BlobSize );
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DumpReplicaInformation( pReplicaInfo );
|
|
delete [] pReplicaInfo->pReplicas;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
|
|
DFSSTATUS
|
|
DfsGetWin2kStdLinkNameInfo(
|
|
HKEY DomainRootKey,
|
|
PUNICODE_STRING pLinkName,
|
|
PBOOLEAN pLinkFound,
|
|
LPWSTR *pChildGuidName,
|
|
PDFS_NAME_INFORMATION pNameInfo)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
ULONG ChildNum = 0;
|
|
DWORD CchMaxName = 0;
|
|
DWORD CchChildName = 0;
|
|
LPWSTR ChildName = NULL;
|
|
|
|
*pLinkFound = FALSE;
|
|
|
|
//
|
|
// First find the length of the longest subkey
|
|
// and allocate a buffer big enough for it.
|
|
//
|
|
Status = RegQueryInfoKey( DomainRootKey, // Key
|
|
NULL, // Class string
|
|
NULL, // Size of class string
|
|
NULL, // Reserved
|
|
NULL, // # of subkeys
|
|
&CchMaxName, // max size of subkey name in TCHARs
|
|
NULL, // max size of class name
|
|
NULL, // # of values
|
|
NULL, // max size of value name
|
|
NULL, // max size of value data,
|
|
NULL, // security descriptor
|
|
NULL ); // Last write time
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
// Space for the NULL terminator.
|
|
CchMaxName++;
|
|
|
|
ChildName = (LPWSTR) new WCHAR [CchMaxName];
|
|
if (ChildName == NULL)
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// For each child, get the child name.
|
|
//
|
|
|
|
CchChildName = CchMaxName;
|
|
|
|
Status = RegEnumKeyEx( DomainRootKey,
|
|
ChildNum,
|
|
ChildName,
|
|
&CchChildName,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
ChildNum++;
|
|
|
|
//
|
|
// Read in the child link and see if that's the link we need.
|
|
//
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
UNICODE_STRING PrefixName;
|
|
|
|
Status = GetWin2kStandaloneMetadata( DomainRootKey,
|
|
ChildName,
|
|
L"ID",
|
|
pNameInfo);
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DumpNameInformation( pNameInfo );
|
|
|
|
// Skip the leading '\'s if any.
|
|
PrefixName = pNameInfo->Prefix;
|
|
while (PrefixName.Buffer[0] == UNICODE_PATH_SEP)
|
|
{
|
|
PrefixName.Buffer++;
|
|
PrefixName.Length -= sizeof(WCHAR);
|
|
}
|
|
|
|
if (RtlCompareUnicodeString( &PrefixName, pLinkName, TRUE ) == 0)
|
|
{
|
|
*pLinkFound = TRUE;
|
|
*pChildGuidName = ChildName;
|
|
Status = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Go on to the next link
|
|
DebugInformation((L"Found W2k Link %wZ, doesn't match %wZ\n", &PrefixName, pLinkName));
|
|
}
|
|
}
|
|
}
|
|
|
|
} while ( Status == ERROR_SUCCESS );
|
|
|
|
if (*pLinkFound == FALSE)
|
|
{
|
|
delete [] ChildName;
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
DFSSTATUS
|
|
DfsGetWin2kStdNameInfo(
|
|
HKEY VolumesKey,
|
|
HKEY DomainRootKey,
|
|
PUNICODE_STRING pShareName,
|
|
PDFS_NAME_INFORMATION pNameInfo)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
UNICODE_STRING W2kRootName;
|
|
|
|
|
|
// Look at DfsHost\volumes-> RootShare key to get at the root name.
|
|
Status = GetRootPhysicalShare( VolumesKey, &W2kRootName );
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
// We need to find a matching share. Win2k has only one root.
|
|
if (RtlCompareUnicodeString( &W2kRootName, pShareName, TRUE ) == 0)
|
|
{
|
|
Status = GetWin2kStandaloneMetadata( DomainRootKey,
|
|
NULL,
|
|
L"ID",
|
|
pNameInfo);
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
DebugInformation((L"Found W2k root %wZ, doesn't match %wZ\n", &W2kRootName, pShareName));
|
|
}
|
|
|
|
delete [] W2kRootName.Buffer;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
GetWin2kStandaloneMetadata (
|
|
IN HKEY DfsMetadataKey,
|
|
IN LPWSTR RelativeName,
|
|
IN LPWSTR RegistryValueNameString,
|
|
OUT PDFS_NAME_INFORMATION pNameInfo)
|
|
{
|
|
|
|
HKEY NewKey = NULL;
|
|
HKEY UseKey = NULL;
|
|
PVOID pDataBuffer = NULL;
|
|
ULONG DataSize, DataType;
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// If a relative name was passed in, we need to open a subkey under the
|
|
// passed in key. Otherwise, we already have a key open to the information
|
|
// of interest.
|
|
//
|
|
if ( RelativeName != NULL )
|
|
{
|
|
Status = RegOpenKeyEx( DfsMetadataKey,
|
|
RelativeName,
|
|
0,
|
|
KEY_READ,
|
|
&NewKey );
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
UseKey = NewKey;
|
|
}
|
|
else
|
|
{
|
|
//DFS_TRACE_HIGH( REFERRAL_SERVER, "registry store, GetMetadata-RegOpenKeyEx %ws status=%d\n", RelativeName, Status);
|
|
}
|
|
} else
|
|
{
|
|
UseKey = DfsMetadataKey;
|
|
}
|
|
|
|
//
|
|
// Get the largest size of any value under the key of interest, so we know
|
|
// how much we need to allocate in the worst case.
|
|
// (If a subkey has 3 values, this returns the maximum memory size required
|
|
// to read any one of the values.)
|
|
//
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
Status = RegQueryInfoKey( UseKey, // Key
|
|
NULL, // Class string
|
|
NULL, // Size of class string
|
|
NULL, // Reserved
|
|
NULL, // # of subkeys
|
|
NULL, // max size of subkey name
|
|
NULL, // max size of class name
|
|
NULL, // # of values
|
|
NULL, // max size of value name
|
|
&DataSize, // max size of value data,
|
|
NULL, // security descriptor
|
|
NULL ); // Last write time
|
|
}
|
|
|
|
//
|
|
// We have the required size now: allocate a buffer for that size and
|
|
// read the value we are interested in.
|
|
//
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
pDataBuffer = new BYTE [DataSize];
|
|
|
|
if ( pDataBuffer == NULL )
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
Status = RegQueryValueEx( UseKey,
|
|
RegistryValueNameString, // eg. "ID"
|
|
NULL,
|
|
&DataType,
|
|
(LPBYTE)pDataBuffer,
|
|
&DataSize );
|
|
//
|
|
// If the format of data is not a certain type (usually binary type for DFS)
|
|
// we have bogus data.
|
|
//
|
|
if ( (Status == ERROR_SUCCESS) && (DataType != DFS_REGISTRY_DATA_TYPE) )
|
|
{
|
|
Status = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we are successful in reading the value, pass the allcoated buffer and
|
|
// size back to caller. Otherwise, free up the allocate buffer and return
|
|
// error status to the caller.
|
|
//
|
|
if ( Status == ERROR_SUCCESS )
|
|
{
|
|
Status = PackGetStandaloneNameInformation( pNameInfo, &pDataBuffer, &DataSize );
|
|
}
|
|
|
|
if ( pDataBuffer != NULL )
|
|
{
|
|
delete [] pDataBuffer;
|
|
pDataBuffer = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// If we did open a new key, it is time to close it now.
|
|
//
|
|
if ( NewKey != NULL )
|
|
RegCloseKey(NewKey);
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
SetWin2kStandaloneMetadata (
|
|
IN HKEY DomainRootKey,
|
|
IN LPWSTR RelativeName,
|
|
IN LPWSTR RegistryValueNameString,
|
|
IN PVOID pData,
|
|
IN ULONG DataSize )
|
|
{
|
|
HKEY UseKey = DomainRootKey;
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// If a relative name was passed in, we need to open a subkey under the
|
|
// passed in key. Otherwise, we already have a key open to the information
|
|
// of interest.
|
|
//
|
|
if (RelativeName)
|
|
{
|
|
Status = RegOpenKeyEx( DomainRootKey,
|
|
RelativeName,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&UseKey );
|
|
|
|
}
|
|
|
|
//
|
|
// Store the value against the passed in value string
|
|
//
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
Status = RegSetValueEx( UseKey,
|
|
RegistryValueNameString,
|
|
NULL,
|
|
DFS_REGISTRY_DATA_TYPE,
|
|
(LPBYTE)pData,
|
|
DataSize );
|
|
|
|
if (UseKey != DomainRootKey)
|
|
RegCloseKey(UseKey);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Look at the Win2k standalone location on the remote
|
|
// machine to see if it has a matching root. If this is a
|
|
// set operation, the Type info will be changed. Else this
|
|
// returns existing Type attribute in NameInformation.
|
|
//
|
|
DFSSTATUS
|
|
DfsExtendedWin2kRootAttributes(
|
|
DfsPathName *Namespace,
|
|
PULONG pAttr,
|
|
BOOLEAN Set)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
DFS_NAME_INFORMATION NameInfo;
|
|
BOOLEAN PathFound = FALSE;
|
|
LPWSTR ChildGuidName = NULL;
|
|
HKEY VolumesKey = NULL;
|
|
HKEY DomainRootKey = NULL;
|
|
|
|
// Open DfsHost\volumes
|
|
Status = GetDfsRegistryKey (Namespace->GetServerString(),
|
|
DFS_REG_OLD_HOST_LOCATION,
|
|
TRUE, // RW
|
|
NULL,
|
|
&VolumesKey );
|
|
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
return Status;
|
|
}
|
|
|
|
Status = RegOpenKeyEx( VolumesKey,
|
|
DFS_REG_OLD_STANDALONE_CHILD, // 'domainroot',
|
|
0,
|
|
KEY_READ|KEY_WRITE,
|
|
&DomainRootKey );
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey( VolumesKey );
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
return Status;
|
|
}
|
|
|
|
do {
|
|
DebugInformation((L"Attempting to get Windows2000 standalone root information for %wZ\n",
|
|
Namespace->GetPathCountedString()));
|
|
Status = DfsGetWin2kStdNameInfo( VolumesKey,
|
|
DomainRootKey,
|
|
Namespace->GetShareCountedString(),
|
|
&NameInfo );
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
//DumpNameInformation( &NameInfo );
|
|
|
|
// We've matched the root name so far. See if we need to find the link component.
|
|
if (!IsEmptyUnicodeString( Namespace->GetRemainingCountedString() ))
|
|
{
|
|
Status = DfsGetWin2kStdLinkNameInfo( DomainRootKey,
|
|
Namespace->GetFolderCountedString(),
|
|
&PathFound,
|
|
&ChildGuidName,
|
|
&NameInfo );
|
|
if (!PathFound)
|
|
{
|
|
Status = ERROR_PATH_NOT_FOUND;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Set)
|
|
{
|
|
*pAttr = NameInfo.Type & PKT_ENTRY_TYPE_EXTENDED_ATTRIBUTES;
|
|
}
|
|
else
|
|
{
|
|
NameInfo.Type &= ~PKT_ENTRY_TYPE_EXTENDED_ATTRIBUTES;
|
|
NameInfo.Type |= *pAttr;
|
|
|
|
//DebugInformation((L"New name information type flags will be 0x%x\n", NameInfo.Type));
|
|
Status = DfsSetWin2kStdNameInfo( DomainRootKey,
|
|
ChildGuidName, // NULL for roots
|
|
&NameInfo );
|
|
}
|
|
} while (FALSE);
|
|
|
|
RegCloseKey( DomainRootKey );
|
|
RegCloseKey( VolumesKey );
|
|
return Status;
|
|
}
|
|
|