NT4/private/ntos/mup/logroot.c
2020-09-30 17:12:29 +02:00

852 lines
26 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+----------------------------------------------------------------------------
//
// Copyright (C) 1992, Microsoft Corporation.
//
// File: logroot.c
//
// Contents: This module implements the logical root handling functions.
//
// Functions: DfsInitializeLogicalRoot -
// DfsDeleteLogicalRoot -
// DfspLogRootNameToPath -
//
// History: 14-June-1994 SudK Created (Most stuff moved from Dsinit.c)
//
//-----------------------------------------------------------------------------
#include "dfsprocs.h"
#include "creds.h"
#include "dnr.h"
#include "fcbsup.h"
#define Dbg DEBUG_TRACE_LOGROOT
NTSTATUS
DfsDefineDosDevice(
IN WCHAR Device,
IN PUNICODE_STRING Target);
NTSTATUS
DfsUndefineDosDevice(
IN WCHAR Device);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, DfsFindLogicalRoot )
#pragma alloc_text( PAGE, DfsInitializeLogicalRoot )
#pragma alloc_text( PAGE, DfsDeleteLogicalRoot )
#pragma alloc_text( PAGE, DfspLogRootNameToPath )
#pragma alloc_text( PAGE, DfsGetResourceFromVcb )
#pragma alloc_text( PAGE, DfsGetResourceFromCredentials )
#pragma alloc_text( PAGE, DfsLogicalRootExists )
#endif
//+-------------------------------------------------------------------------
//
// Function: DfsFindLogicalRoot, local
//
// Synopsis: DfsFindLogicalRoot takes as input a DS path name in
// the standard form (root:\file\path\name), looks up
// the DFS_VCB associated with the logical root, and returns
// a string pointing to beyond the logical root part
// of the input string.
//
// Arguments: [PrefixPath] -- Input path name
// [Vcb] -- Returns DFS_VCB which corresponds to logical root
// in PrefixPath
// [RemainingPath] -- Returns with portion of PrefixPath
// after the logical root name and colon
//
// Returns: NTSTATUS:
// STATUS_SUCCESS if Vcb found
// STATUS_OBJECT_PATH_SYNTAX_BAD - no logical root name
// STATUS_NO_SUCH_DEVICE - logical root name not found
//
//--------------------------------------------------------------------------
NTSTATUS
DfsFindLogicalRoot(
IN PUNICODE_STRING PrefixPath,
OUT PDFS_VCB *Vcb,
OUT PUNICODE_STRING RemainingPath
) {
PLIST_ENTRY Link;
unsigned int i;
NTSTATUS Status = STATUS_SUCCESS;
NETRESOURCE testnt;
DfsDbgTrace(+1, Dbg, "DfsFindLogicalRoot...\n", 0);
*RemainingPath = *PrefixPath;
for (i = 0; i < RemainingPath->Length/sizeof(WCHAR); i++) {
if ((RemainingPath->Buffer[i] == (WCHAR)':') ||
(RemainingPath->Buffer[i] == UNICODE_PATH_SEP))
break;
}
if ((i*sizeof(WCHAR) >= RemainingPath->Length) ||
(RemainingPath->Buffer[i] == UNICODE_PATH_SEP)) {
Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
DfsDbgTrace(-1, Dbg, "DfsFindLogicalRoot -> %08lx\n", Status);
return(Status);
}
RemainingPath->Length = i * sizeof (WCHAR);
//
// Search for the logical root in all known DFS_VCBs
//
ExAcquireResourceShared(&DfsData.Resource, TRUE);
for ( Link = DfsData.VcbQueue.Flink;
Link != &DfsData.VcbQueue;
Link = Link->Flink ) {
*Vcb = CONTAINING_RECORD( Link, DFS_VCB, VcbLinks );
if (RtlEqualString( (PSTRING)&(*Vcb)->LogicalRoot,
(PSTRING)RemainingPath, (BOOLEAN)TRUE) ) {
break;
}
}
if (Link == &DfsData.VcbQueue) {
Status = STATUS_NO_SUCH_DEVICE;
ExReleaseResource(&DfsData.Resource);
DfsDbgTrace(-1, Dbg, "DfsFindLogicalRoot -> %08lx\n", Status);
return(Status);
}
//
// Adjust remaining path to point beyond the logical root name
//
RemainingPath->Buffer = (WCHAR*)((char*) (RemainingPath->Buffer) +
RemainingPath->Length + sizeof (WCHAR) );
RemainingPath->Length = PrefixPath->Length -
(RemainingPath->Length + sizeof (WCHAR));
if (RemainingPath->Length <= 0 ||
RemainingPath->Buffer[0] != UNICODE_PATH_SEP) {
Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
ExReleaseResource(&DfsData.Resource);
DfsDbgTrace(-1, Dbg, "DfsFindLogicalRoot -> %08lx\n", Status);
return(Status);
}
ExReleaseResource(&DfsData.Resource);
DfsDbgTrace(-1, Dbg, "DfsFindLogicalRoot -> %08lx\n", Status);
return(Status);
}
//+-------------------------------------------------------------------------
//
// Function: DfsInitializeLogicalRoot, public
//
// Synopsis: Allocate and initialize storage for a logical root.
// This includes creating a device object and DFS_VCB for it.
//
// Effects: A logical root device object is created. A corresponding
// DFS_VCB is also created and linked into the list of known
// DFS_VCBs.
//
// Arguments: [Name] -- name of logical root.
// [Prefix] -- Prefix to be prepended to file names opened
// via the logical root being created before
// they can be resolved in the DFS name space.
// [Credentials] -- The credentials to use when accessing files
// via this logical root.
// [VcbFlags] -- To be OR'd into the VcbState field of the
// DFS_VCB of the newly created logical root device.
//
// Requires: DfsData must first be set up. Also an EXCLUSIVE LOCK on
// DfsData.Resource must be acquired.
//
// Returns: NTSTATUS - STATUS_SUCCESS unless there is some problem.
//
// History: 25 Jan 1992 alanw created
//
//--------------------------------------------------------------------------
NTSTATUS
DfsInitializeLogicalRoot(
IN LPCWSTR Name,
IN PUNICODE_STRING Prefix OPTIONAL,
IN PDFS_CREDENTIALS Credentials OPTIONAL,
IN USHORT VcbFlags
) {
UNICODE_STRING UnicodeString = DfsData.LogRootDevName;
UNICODE_STRING LogRootPrefix;
UNICODE_STRING RootName, RemainingPath;
PDFS_VCB Vcb;
WCHAR RootBuffer[MAX_LOGICAL_ROOT_LEN];
LPCWSTR pstr = Name;
PWSTR pdst;
PLOGICAL_ROOT_DEVICE_OBJECT DeviceObject = NULL;
NTSTATUS Status;
DfsDbgTrace(0, Dbg, "DfsInitializeLogicalRoot -> %ws\n", Name);
DfsDbgTrace(0, Dbg, "DfsInitializeLogicalRoot -> %wZ\n", Prefix);
//
// First, see if a logical root by the given name already exists
//
ASSERT(ARGUMENT_PRESENT(Name));
RootName.Buffer = RootBuffer;
RootName.MaximumLength = sizeof(RootBuffer);
Status = DfspLogRootNameToPath(Name, &RootName);
if (!NT_SUCCESS(Status)) {
return(Status);
}
Status = DfsFindLogicalRoot(&RootName, &Vcb, &RemainingPath);
ASSERT(Status != STATUS_OBJECT_PATH_SYNTAX_BAD);
if (Status != STATUS_NO_SUCH_DEVICE) {
return(STATUS_OBJECT_NAME_COLLISION);
}
//
// DfsData.LogRootDevName is initialized to be L"\Device\WinDfs\"
// Here, we tack on the name of the Logical root we are creating
// to the above string, so that the string becomes, for example,
// L"\Device\WinDfs\Root". Note that at this point, we are scribbling
// into the buffer belonging to DfsData.LogRootDevName, but this
// should be ok, since we are not changing the Length field of that
// Unicode string! BTW, we need a string of this form to create the
// device object.
//
pdst = &UnicodeString.Buffer[UnicodeString.Length/sizeof (WCHAR)];
while (*pstr != UNICODE_NULL) {
*pdst++ = *pstr++;
UnicodeString.Length += sizeof (WCHAR);
}
//
// Next, try to setup the Dos Device link
//
if (Prefix) {
Status = DfsDefineDosDevice( Name[0], &UnicodeString );
if (!NT_SUCCESS(Status)) {
return( Status );
}
}
//
// Before we initialize the Vcb, we need to allocate space for the
// Prefix. PagedPool should be fine here. We need to reallocate because
// we will store this permanently in the DFS_VCB.
//
if (Prefix && Prefix->Length > 0) {
LogRootPrefix.Length = Prefix->Length;
LogRootPrefix.MaximumLength = LogRootPrefix.Length + sizeof(WCHAR);
LogRootPrefix.Buffer =
ExAllocatePool(PagedPool, LogRootPrefix.MaximumLength);
if (LogRootPrefix.Buffer != NULL) {
RtlMoveMemory(LogRootPrefix.Buffer,
Prefix->Buffer,
Prefix->MaximumLength);
LogRootPrefix.Buffer[Prefix->Length/sizeof(WCHAR)] = UNICODE_NULL;
} else {
//
// Couldn't allocate memory! Ok to return with error code, since
// we haven't changed the state of the IO subsystem yet.
//
return(STATUS_INSUFFICIENT_RESOURCES);
}
} else {
RtlInitUnicodeString(&LogRootPrefix, NULL);
}
//
// Create the device object for the logical root.
//
Status = IoCreateDevice( DfsData.DriverObject,
sizeof( LOGICAL_ROOT_DEVICE_OBJECT ) -
sizeof( DEVICE_OBJECT ),
&UnicodeString,
FILE_DEVICE_DFS,
FILE_REMOTE_DEVICE,
FALSE,
(PDEVICE_OBJECT *) &DeviceObject );
if ( !NT_SUCCESS( Status ) ) {
if (LogRootPrefix.Buffer) {
ExFreePool(LogRootPrefix.Buffer);
}
if (Prefix) {
NTSTATUS DeleteStatus;
DeleteStatus = DfsUndefineDosDevice( Name[0] );
ASSERT(NT_SUCCESS(DeleteStatus));
}
return Status;
}
DeviceObject->DeviceObject.StackSize = 5;
DfsInitializeVcb ( NULL,
&DeviceObject->Vcb,
&LogRootPrefix,
Credentials,
(PDEVICE_OBJECT)DeviceObject );
DeviceObject->Vcb.VcbState |= VcbFlags;
//
// Save the logical root name in the DFS_VCB structure. Remember, above
// we had UnicodeString to be of the form L"\Device\WinDfs\org". Now,
// we adjust the buffer and length fields of UnicodeString so that
// the Buffer points to the beginning of the L"org"; Then, we allocate
// space for Vcb.LogicalRoot, and copy the name to it!
//
UnicodeString.Buffer =
&UnicodeString.Buffer[ DfsData.LogRootDevName.Length/sizeof (WCHAR) ];
UnicodeString.Length -= DfsData.LogRootDevName.Length;
UnicodeString.MaximumLength -= DfsData.LogRootDevName.Length;
DeviceObject->Vcb.LogicalRoot.Buffer = ExAllocatePool( PagedPool,
UnicodeString.Length );
DeviceObject->Vcb.LogicalRoot.Length =
DeviceObject->Vcb.LogicalRoot.MaximumLength =
UnicodeString.Length;
RtlMoveMemory( DeviceObject->Vcb.LogicalRoot.Buffer,
UnicodeString.Buffer, UnicodeString.Length );
//
// This is not documented anywhere, but calling IoCreateDevice has set
// the DO_DEVICE_INITIALIZING flag in DeviceObject->Flags. Normally,
// device objects are created only at driver init time, and IoLoadDriver
// will clear this bit for all device objects created at init time.
// Since in Dfs, we need to create and delete devices on the fly (ie,
// via FsCtl), we need to manually clear this bit.
//
DeviceObject->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
//+----------------------------------------------------------------------------
//
// Function: DfsDeleteLogicalRoot
//
// Synopsis: Removes a logical root if found and possible.
//
// Arguments: [Name] -- Name of the Logical Root
// [fForce] -- Whether to Forcibly delete logical root inspite of
// open files.
//
// Returns: STATUS_SUCCESS -- If successfully deleted logical root
//
// STATUS_NO_SUCH_DEVICE -- If there is no logical root to
// delete.
//
// STATUS_DEVICE_BUSY -- If fForce is false and there are open
// files via this logical root.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsDeleteLogicalRoot(
IN PWSTR Name,
IN BOOLEAN fForce
)
{
UNICODE_STRING RootName;
UNICODE_STRING RemainingPath;
WCHAR RootBuffer[MAX_LOGICAL_ROOT_LEN + 2];
PDFS_PKT_ENTRY PktEntry;
PDFS_VCB Vcb;
NTSTATUS Status;
PLOGICAL_ROOT_DEVICE_OBJECT DeviceObject;
BOOLEAN pktLocked;
//
// The 2 extra spots are for holding :\ to form a path out of a
// root name; ie, to go from root to a root:\ form.
//
DfsDbgTrace(0, Dbg, "DfsDeleteLogicalRoot -> %ws\n", Name);
DfsDbgTrace(0, Dbg, "DfsDeleteLogicalRoot -> %s\n", fForce ? "TRUE":"FALSE");
//
// First see if the logical root even exists.
//
ASSERT(ARGUMENT_PRESENT(Name));
RootName.Buffer = RootBuffer;
RootName.MaximumLength = sizeof(RootBuffer);
Status = DfspLogRootNameToPath(Name, &RootName);
if (!NT_SUCCESS(Status))
return(Status);
//
// Acquire Pkt and DfsData, wait till we do so.
//
PktAcquireExclusive(TRUE, &pktLocked);
ExAcquireResourceExclusive(&DfsData.Resource, TRUE);
Status = DfsFindLogicalRoot(&RootName, &Vcb, &RemainingPath);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
//
// Check to see if there are open files via this volume.
//
if (!fForce &&
((Vcb->DirectAccessOpenCount != 0) ||
(Vcb->OpenFileCount != 0))) {
Status = STATUS_DEVICE_BUSY;
goto Cleanup;
}
//
// Delete the credentials used by this connection
//
DfsDeleteCredentials( Vcb->Credentials );
//
// Get rid of the Dos Device
//
DfsUndefineDosDevice( Name[0] );
//
// Now, get rid of the Device itself. This is a bit tricky, because there
// might be files open on this device. So, we reference the device and
// call ObMakeTemporaryObject. This causes the object to be removed from
// the NT Object table, but, since atleast our reference is active,
// prevents the object from being freed. Then, we insert this object into
// our DeletedVcb list. The timer routine will periodically wake up and
// see if all references to this device have been released, at which
// point the device will be finally freed.
//
RemoveEntryList(&Vcb->VcbLinks);
InsertTailList( &DfsData.DeletedVcbQueue, &Vcb->VcbLinks );
DeviceObject = CONTAINING_RECORD( Vcb, LOGICAL_ROOT_DEVICE_OBJECT, Vcb);
ObReferenceObjectByPointer( DeviceObject, 0, NULL, KernelMode );
ObMakeTemporaryObject((PVOID) DeviceObject);
DeviceObject->DeviceObject.Flags &= ~DO_DEVICE_HAS_NAME;
Cleanup:
ExReleaseResource(&DfsData.Resource);
PktRelease();
return(Status);
}
//+----------------------------------------------------------------------------
//
// Function: DfspLogRootNameToPath
//
// Synopsis: Amazingly enough, all it does it takes a PWSTR, copies it into
// a Unicode string's buffer, and appends a \ to the tail of the
// buffer, thus making a path out of a Logical root name.
//
// Arguments: [Name] -- Name of logical root, like L"org"
// [RootName] -- Destination for L"org\\"
//
// Returns: STATUS_BUFFER_OVERFLOW, STATUS_SUCCESS
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspLogRootNameToPath(
IN LPCWSTR Name,
OUT PUNICODE_STRING RootName
)
{
unsigned short i, nMaxNameLen;
//
// The two extra spots are required to append a ":\" after the root name.
//
nMaxNameLen = (RootName->MaximumLength/sizeof(WCHAR)) - 2;
//
// Copy the name
//
for (i = 0; Name[i] != UNICODE_NULL && i < nMaxNameLen; i++) {
RootName->Buffer[i] = Name[i];
}
//
// Make sure entire name was copied before we ran out of space
//
if (Name[i] != UNICODE_NULL) {
//
// Someone sent in a name bigger than allowed.
//
return(STATUS_BUFFER_OVERFLOW);
}
//
// Append the ":\" to form a path
//
RootName->Length = i * sizeof(WCHAR);
return(RtlAppendUnicodeToString(RootName, L":\\"));
}
#define PackMem(buf, str, len, pulen) { \
ASSERT(*(pulen) >= (len)); \
RtlMoveMemory((buf) + *(pulen) - (len), (str), (len)); \
*(pulen) -= (len); \
}
//+----------------------------------------------------------------------------
//
// Function: DfsGetResourceFromVcb
//
// Synopsis: Given a DFS_VCB it constructs a NETRESOURCE struct into the buffer
// passed in. At the same time it uses the end of the buffer to
// fill in a string. If the buffer is insufficient in size the
// required size is returned in "pulen". If everything succeeds
// then the pulen arg is decremented to indicate remaining size
// of buffer.
//
// Arguments: [Vcb] -- The source DFS_VCB
// [ProviderName] -- Provider Name to stuff in the NETRESOURCE
// [BufBegin] -- Start of actual buffer for computing offsets
// [Buf] -- The NETRESOURCE structure to fill
// [BufSize] -- On entry, size of buf. On return, contains
// remaining size of buf.
//
// Returns: [STATUS_SUCCESS] -- Operation completed successfully.
// [STATUS_BUFFER_OVERFLOW] -- buf is not big enough.
//
// Notes: This routine fills in a NETRESOURCE structure starting at
// Buf. The strings in the NETRESOURCE are filled in starting
// from the *end* (ie, starting at Buf + *BufSize)
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsGetResourceFromVcb(
PDFS_VCB Vcb,
PUNICODE_STRING ProviderName,
PUCHAR BufBegin,
PUCHAR Buf,
PULONG BufSize
)
{
LPNETRESOURCE netResource;
ULONG sizeRequired = 0;
WCHAR localDrive[ 3 ];
sizeRequired = sizeof(NETRESOURCE) +
ProviderName->Length +
sizeof(UNICODE_NULL) +
3 * sizeof(WCHAR) + // lpLocalName D: etc.
sizeof(UNICODE_PATH_SEP) +
Vcb->LogRootPrefix.Length +
sizeof(UNICODE_NULL);
if (*BufSize < sizeRequired) {
*BufSize = sizeRequired;
return(STATUS_BUFFER_OVERFLOW);
}
//
// Buffer is big enough, fill in the NETRESOURCE structure
//
netResource = (LPNETRESOURCE) Buf;
Buf += sizeof(NETRESOURCE);
*BufSize -= sizeof(NETRESOURCE);
netResource->dwScope = RESOURCE_CONNECTED;
netResource->dwType = RESOURCETYPE_DISK;
netResource->dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
netResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
netResource->lpComment = NULL;
//
// Fill in the provider name
//
PackMem(Buf, L"", sizeof(L""), BufSize);
PackMem(Buf, ProviderName->Buffer, ProviderName->Length, BufSize);
netResource->lpProvider = (LPWSTR) (Buf + *BufSize - BufBegin);
//
// Fill in the local name next
//
localDrive[0] = Vcb->LogicalRoot.Buffer[0];
localDrive[1] = UNICODE_DRIVE_SEP;
localDrive[2] = UNICODE_NULL;
PackMem(Buf, localDrive, sizeof(localDrive), BufSize);
netResource->lpLocalName = (LPWSTR) (Buf + *BufSize - BufBegin);
//
// Fill in the remote name last
//
PackMem(Buf, L"", sizeof(L""), BufSize);
PackMem(Buf, Vcb->LogRootPrefix.Buffer, Vcb->LogRootPrefix.Length, BufSize);
PackMem(Buf, UNICODE_PATH_SEP_STR, sizeof(UNICODE_PATH_SEP), BufSize);
netResource->lpRemoteName = (LPWSTR) (Buf + *BufSize - BufBegin);
return(STATUS_SUCCESS);
}
//+----------------------------------------------------------------------------
//
// Function: DfsGetResourceFromCredentials
//
// Synopsis: Builds a NETRESOURCE structure for a device-less connection.
// The LPWSTR members of NETRESOURCE actually contain offsets
// from the BufBegin parameter.
//
// Arguments: [Creds] -- The source credentials
// [ProviderName] -- Provider Name to stuff in the NETRESOURCE
// [BufBegin] -- Start of actual buffer for computing offsets
// [Buf] -- The NETRESOURCE structure to fill
// [BufSize] -- On entry, size of buf. On return, contains
// remaining size of buf.
//
// Returns: [STATUS_SUCCESS] -- Operation completed successfully.
// [STATUS_BUFFER_OVERFLOW] -- buf is not big enough.
//
// Notes: This routine fills in a NETRESOURCE structure starting at
// Buf. The strings in the NETRESOURCE are filled in starting
// from the *end* (ie, starting at Buf + *BufSize)
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsGetResourceFromCredentials(
PDFS_CREDENTIALS Creds,
PUNICODE_STRING ProviderName,
PUCHAR BufBegin,
PUCHAR Buf,
PULONG BufSize)
{
LPNETRESOURCE netResource = (LPNETRESOURCE) Buf;
ULONG sizeRequired;
sizeRequired = sizeof(NETRESOURCE) +
ProviderName->Length +
sizeof(UNICODE_NULL) +
2 * sizeof(UNICODE_PATH_SEP) +
Creds->ServerName.Length +
sizeof(UNICODE_PATH_SEP) +
Creds->ShareName.Length +
sizeof(UNICODE_NULL);
if (*BufSize < sizeRequired) {
*BufSize = sizeRequired;
return(STATUS_BUFFER_OVERFLOW);
}
//
// Buffer is big enough, fill in the NETRESOURCE structure
//
Buf += sizeof(NETRESOURCE); // Start of string area
*BufSize -= sizeof(NETRESOURCE);
netResource->dwScope = RESOURCE_CONNECTED;
netResource->dwType = RESOURCETYPE_DISK;
netResource->dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
netResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
netResource->lpComment = NULL;
netResource->lpLocalName = NULL;
//
// Fill in the provider name
//
PackMem(Buf, L"", sizeof(L""), BufSize);
PackMem(Buf, ProviderName->Buffer, ProviderName->Length, BufSize);
netResource->lpProvider = (LPWSTR) (Buf + *BufSize - BufBegin);
//
// Fill in the remote name last
//
PackMem(Buf, L"", sizeof(L""), BufSize);
PackMem(Buf, Creds->ShareName.Buffer, Creds->ShareName.Length, BufSize);
PackMem(Buf, UNICODE_PATH_SEP_STR, sizeof(UNICODE_PATH_SEP), BufSize);
PackMem(Buf, Creds->ServerName.Buffer, Creds->ServerName.Length, BufSize);
PackMem(Buf, UNICODE_PATH_SEP_STR, sizeof(UNICODE_PATH_SEP), BufSize);
PackMem(Buf, UNICODE_PATH_SEP_STR, sizeof(UNICODE_PATH_SEP), BufSize);
netResource->lpRemoteName = (LPWSTR) (Buf + *BufSize - BufBegin);
return(STATUS_SUCCESS);
}
BOOLEAN
DfsLogicalRootExists(PWSTR pwszName)
{
UNICODE_STRING RootName;
UNICODE_STRING RemainingPath;
WCHAR RootBuffer[MAX_LOGICAL_ROOT_LEN + 2];
PDFS_VCB Vcb;
NTSTATUS Status;
ASSERT(ARGUMENT_PRESENT(pwszName));
RootName.Buffer = RootBuffer;
RootName.MaximumLength = sizeof(RootBuffer);
Status = DfspLogRootNameToPath(pwszName, &RootName);
if (!NT_SUCCESS(Status)) {
return(FALSE);
}
Status = DfsFindLogicalRoot(&RootName, &Vcb, &RemainingPath);
if (!NT_SUCCESS(Status)) {
//
// If this asserts, we need to fix the code above that creates the
// Logical Root name, or fix DfsFindLogicalRoot.
//
ASSERT(Status != STATUS_OBJECT_PATH_SYNTAX_BAD);
return(FALSE);
}
else {
return(TRUE);
}
}
//+----------------------------------------------------------------------------
//
// Function: DfsDefineDosDevice
//
// Synopsis: Creates a dos device to a logical root
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsDefineDosDevice(
IN WCHAR Device,
IN PUNICODE_STRING Target)
{
NTSTATUS status;
HANDLE device;
OBJECT_ATTRIBUTES ob;
UNICODE_STRING deviceName;
RtlInitUnicodeString( &deviceName, L"\\??\\X:" );
deviceName.Buffer[ deviceName.Length/sizeof(WCHAR) - 2] = Device;
InitializeObjectAttributes(
&ob,
&deviceName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
NULL);
status = ZwCreateSymbolicLinkObject(
&device,
SYMBOLIC_LINK_ALL_ACCESS,
&ob,
Target);
if (NT_SUCCESS(status))
ZwClose( device );
return( status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsUndefineDosDevice
//
// Synopsis: Undefines a dos device
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsUndefineDosDevice(
IN WCHAR Device)
{
NTSTATUS status;
HANDLE device;
OBJECT_ATTRIBUTES ob;
UNICODE_STRING deviceName;
RtlInitUnicodeString( &deviceName, L"\\??\\X:" );
deviceName.Buffer[ deviceName.Length/sizeof(WCHAR) - 2] = Device;
InitializeObjectAttributes(
&ob,
&deviceName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
NULL);
status = ZwOpenSymbolicLinkObject(
&device,
SYMBOLIC_LINK_QUERY | DELETE,
&ob);
if (NT_SUCCESS(status)) {
status = ZwMakeTemporaryObject( device );
ZwClose( device );
}
return( status );
}