251 lines
6.3 KiB
C
251 lines
6.3 KiB
C
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1996, Microsoft Corporation
|
|
//
|
|
// File: dfsext.c
|
|
//
|
|
// Contents: Code to see if a path refers to a Dfs path.
|
|
//
|
|
// Classes: None
|
|
//
|
|
// Functions: IsThisADfsPath
|
|
//
|
|
// History: March 11, 1996 Milans created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <dfsfsctl.h>
|
|
#include <windows.h>
|
|
|
|
NTSTATUS
|
|
DfsFsctl(
|
|
IN HANDLE DfsHandle,
|
|
IN ULONG FsControlCode,
|
|
IN PVOID InputBuffer OPTIONAL,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer OPTIONAL,
|
|
IN ULONG OutputBufferLength);
|
|
|
|
NTSTATUS
|
|
DfsOpen(
|
|
IN OUT PHANDLE DfsHandle);
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: IsThisADfsPath, public
|
|
//
|
|
// Synopsis: Given a fully qualified UNC or Drive based path, this routine
|
|
// will identify if it is a Dfs path or not.
|
|
//
|
|
// Arguments: [pwszPath] -- The fully qualified path to test.
|
|
//
|
|
// [cwPath] -- Length, in WCHARs, of pwszPath. If this is 0,
|
|
// this routine will compute the length. If it is
|
|
// non-zero, it will assume that the length of pwszPath
|
|
// is cwPath WCHARs.
|
|
//
|
|
// Returns: TRUE if pwszPath is a Dfs path, FALSE otherwise.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
IsThisADfsPath(
|
|
IN LPCWSTR pwszPath,
|
|
IN DWORD cwPath OPTIONAL)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE hDfs;
|
|
BOOL fIsDfsPath = FALSE;
|
|
PDFS_IS_VALID_PREFIX_ARG pPrefixArg;
|
|
ULONG Size;
|
|
|
|
//
|
|
// We only accept UNC or drive letter paths
|
|
//
|
|
|
|
if (pwszPath == NULL)
|
|
return( FALSE );
|
|
|
|
if (cwPath == 0)
|
|
cwPath = wcslen( pwszPath );
|
|
|
|
if (cwPath < 2)
|
|
return( FALSE );
|
|
|
|
Status = DfsOpen( &hDfs );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
return( FALSE );
|
|
|
|
//
|
|
// From this point on, we must remember to close hDfs before returning.
|
|
//
|
|
|
|
if (pwszPath[0] == L'\\' && pwszPath[1] == L'\\') {
|
|
|
|
Size = sizeof(DFS_IS_VALID_PREFIX_ARG) +
|
|
cwPath * sizeof(WCHAR);
|
|
|
|
pPrefixArg = (PDFS_IS_VALID_PREFIX_ARG) LocalAlloc(0, Size);
|
|
|
|
if ( pPrefixArg ) {
|
|
|
|
//
|
|
// the InputBuffer must be in the structure of DFS_IS_VALID_PREFIX_ARG
|
|
//
|
|
|
|
pPrefixArg->CSCAgentCreate = FALSE;
|
|
pPrefixArg->RemoteNameLen = (SHORT)( (cwPath-1) * sizeof(WCHAR));
|
|
wcscpy(&pPrefixArg->RemoteName[0], pwszPath+1);
|
|
|
|
Status = DfsFsctl(
|
|
hDfs,
|
|
FSCTL_DFS_IS_VALID_PREFIX,
|
|
(PVOID) pPrefixArg, // &pwszPath[1],
|
|
Size, // (cwPath - 1) * sizeof(WCHAR),
|
|
NULL,
|
|
0);
|
|
|
|
LocalFree(pPrefixArg);
|
|
|
|
} else {
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
fIsDfsPath = TRUE;
|
|
|
|
} else if (pwszPath[1] == L':') {
|
|
|
|
//
|
|
// This is a drive based name. We'll fsctl to the driver to return
|
|
// the prefix for this drive, if it is indeed a Dfs drive.
|
|
//
|
|
|
|
Status = DfsFsctl(
|
|
hDfs,
|
|
FSCTL_DFS_IS_VALID_LOGICAL_ROOT,
|
|
(PVOID) &pwszPath[0],
|
|
sizeof(WCHAR),
|
|
NULL,
|
|
0);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
fIsDfsPath = TRUE;
|
|
|
|
}
|
|
|
|
NtClose( hDfs );
|
|
|
|
return( fIsDfsPath );
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsOpen, private
|
|
//
|
|
// Synopsis: Opens a handle to the Dfs driver for fsctl purposes.
|
|
//
|
|
// Arguments: [DfsHandle] -- On successful return, contains handle to the
|
|
// driver.
|
|
//
|
|
// Returns: NTSTATUS of attempt to open the Dfs driver.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsOpen(
|
|
IN OUT PHANDLE DfsHandle)
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
UNICODE_STRING name = {
|
|
sizeof(DFS_DRIVER_NAME)-sizeof(UNICODE_NULL),
|
|
sizeof(DFS_DRIVER_NAME)-sizeof(UNICODE_NULL),
|
|
DFS_DRIVER_NAME};
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
status = NtCreateFile(
|
|
DfsHandle,
|
|
SYNCHRONIZE,
|
|
&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);
|
|
|
|
if (NT_SUCCESS(status))
|
|
status = ioStatus.Status;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFsctl, public
|
|
//
|
|
// Synopsis: Fsctl's to the Dfs driver.
|
|
//
|
|
// Arguments: [DfsHandle] -- Handle to the Dfs driver, usually obtained by
|
|
// calling DfsOpen.
|
|
// [FsControlCode] -- The FSCTL code (see private\inc\dfsfsctl.h)
|
|
// [InputBuffer] -- InputBuffer to the fsctl.
|
|
// [InputBufferLength] -- Length, in BYTES, of InputBuffer
|
|
// [OutputBuffer] -- OutputBuffer to the fsctl.
|
|
// [OutputBufferLength] -- Length, in BYTES, of OutputBuffer
|
|
//
|
|
// Returns: NTSTATUS of Fsctl attempt.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsFsctl(
|
|
IN HANDLE DfsHandle,
|
|
IN ULONG FsControlCode,
|
|
IN PVOID InputBuffer OPTIONAL,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer OPTIONAL,
|
|
IN ULONG OutputBufferLength
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
|
|
status = NtFsControlFile(
|
|
DfsHandle,
|
|
NULL, // Event,
|
|
NULL, // ApcRoutine,
|
|
NULL, // ApcContext,
|
|
&ioStatus,
|
|
FsControlCode,
|
|
InputBuffer,
|
|
InputBufferLength,
|
|
OutputBuffer,
|
|
OutputBufferLength
|
|
);
|
|
|
|
if(NT_SUCCESS(status))
|
|
status = ioStatus.Status;
|
|
|
|
return status;
|
|
}
|
|
|
|
|