mirror of https://github.com/lianthony/NT4.0
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.
404 lines
10 KiB
404 lines
10 KiB
|
|
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Attach.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the routines for the NetWare
|
|
redirector to connect and disconnect from a server.
|
|
|
|
Author:
|
|
|
|
Colin Watson [ColinW] 10-Jan-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include <stdio.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
//#include "Procs.h"
|
|
|
|
|
|
#define DebugTrace(INDENT,LEVEL,X,Y) { \
|
|
printf(X,Y); \
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ExtractNextComponentName (
|
|
OUT PUNICODE_STRING Name,
|
|
IN PUNICODE_STRING Path
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine extracts a the "next" component from a path string.
|
|
|
|
It assumes that
|
|
|
|
Arguments:
|
|
|
|
Name - Returns a pointer to the component.
|
|
|
|
Path - Supplies a pointer to the backslash seperated pathname.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
register USHORT i; // Index into Name string.
|
|
|
|
if (Path->Length == 0) {
|
|
RtlInitUnicodeString(Name, NULL);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Initialize the extracted name to the name passed in skipping the
|
|
// leading backslash.
|
|
//
|
|
|
|
ASSERT(Path->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
|
|
|
|
Name->Buffer = Path->Buffer + 1;
|
|
Name->Length = Path->Length - sizeof(WCHAR);
|
|
Name->MaximumLength = Path->MaximumLength - sizeof(WCHAR);
|
|
|
|
//
|
|
// Scan forward finding the terminal "\" in the server name.
|
|
//
|
|
|
|
for (i=0;i<(USHORT)(Name->Length/sizeof(WCHAR));i++) {
|
|
|
|
if (Name->Buffer[i] == OBJ_NAME_PATH_SEPARATOR) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update the length and maximum length of the structure
|
|
// to match the new length.
|
|
//
|
|
|
|
Name->Length = Name->MaximumLength = (USHORT)(i*sizeof(WCHAR));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ExtractPathAndFileName (
|
|
IN PUNICODE_STRING EntryPath,
|
|
OUT PUNICODE_STRING PathString,
|
|
OUT PUNICODE_STRING FileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine cracks the entry path into two pieces, the path and the file
|
|
name component at the start of the name.
|
|
|
|
|
|
Arguments:
|
|
|
|
IN PUNICODE_STRING EntryPath - Supplies the path to disect.
|
|
OUT PUNICODE_STRING PathString - Returns the directory containing the file.
|
|
OUT PUNICODE_STRING FileName - Returns the file name specified.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - SUCCESS
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING Component;
|
|
UNICODE_STRING FilePath = *EntryPath;
|
|
|
|
// Strip trailing separators
|
|
while ( (FilePath.Length != 0) &&
|
|
FilePath.Buffer[(FilePath.Length-1)/sizeof(WCHAR)] ==
|
|
OBJ_NAME_PATH_SEPARATOR ) {
|
|
|
|
FilePath.Length -= sizeof(WCHAR);
|
|
FilePath.MaximumLength -= sizeof(WCHAR);
|
|
}
|
|
|
|
// PathString will become EntryPath minus FileName and trailing separators
|
|
*PathString = FilePath;
|
|
|
|
// Initialize FileName just incase there are no components at all.
|
|
RtlInitUnicodeString( FileName, NULL );
|
|
|
|
//
|
|
// Scan through the current file name to find the entire path
|
|
// up to (but not including) the last component in the path.
|
|
//
|
|
|
|
do {
|
|
|
|
//
|
|
// Extract the next component from the name.
|
|
//
|
|
|
|
ExtractNextComponentName(&Component, &FilePath);
|
|
|
|
//
|
|
// Bump the "remaining name" pointer by the length of this
|
|
// component
|
|
//
|
|
|
|
if (Component.Length != 0) {
|
|
|
|
FilePath.Length -= Component.Length+sizeof(WCHAR);
|
|
FilePath.MaximumLength -= Component.MaximumLength+sizeof(WCHAR);
|
|
FilePath.Buffer += (Component.Length/sizeof(WCHAR))+1;
|
|
|
|
*FileName = Component;
|
|
}
|
|
|
|
|
|
} while (Component.Length != 0);
|
|
|
|
//
|
|
// Take the name, subtract the last component of the name
|
|
// and concatenate the current path with the new path.
|
|
//
|
|
|
|
if ( FileName->Length != 0 ) {
|
|
|
|
//
|
|
// Set the path's name based on the original name, subtracting
|
|
// the length of the name portion (including the "\")
|
|
//
|
|
|
|
PathString->Length -= (FileName->Length + sizeof(WCHAR));
|
|
if ( PathString->Length != 0 ) {
|
|
PathString->MaximumLength -= (FileName->MaximumLength + sizeof(WCHAR));
|
|
} else{
|
|
RtlInitUnicodeString( PathString, NULL );
|
|
}
|
|
} else {
|
|
|
|
// There was no path or filename
|
|
|
|
RtlInitUnicodeString( PathString, NULL );
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CrackPath (
|
|
IN PUNICODE_STRING BaseName,
|
|
OUT PUNICODE_STRING DriveName,
|
|
OUT PUNICODE_STRING ServerName,
|
|
OUT PUNICODE_STRING VolumeName,
|
|
OUT PUNICODE_STRING PathName,
|
|
OUT PUNICODE_STRING FileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine extracts the relevant portions from BaseName to extract
|
|
the components of the user's string.
|
|
|
|
|
|
Arguments:
|
|
|
|
BaseName - Supplies the base user's path.
|
|
|
|
DriveName - Supplies a string to hold the drive specifier.
|
|
|
|
ServerName - Supplies a string to hold the remote server name.
|
|
|
|
VolumeName - Supplies a string to hold the volume name.
|
|
|
|
PathName - Supplies a string to hold the remaining part of the path.
|
|
|
|
FileName - Supplies a string to hold the final component of the path.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Status of operation
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING BaseCopy = *BaseName;
|
|
UNICODE_STRING ShareName;
|
|
|
|
RtlInitUnicodeString( DriveName, NULL);
|
|
RtlInitUnicodeString( ServerName, NULL);
|
|
RtlInitUnicodeString( VolumeName, NULL);
|
|
RtlInitUnicodeString( PathName, NULL);
|
|
RtlInitUnicodeString( FileName, NULL);
|
|
|
|
//
|
|
// If the name is "\", or empty, there is nothing to do.
|
|
//
|
|
|
|
if ( BaseName->Length <= sizeof( WCHAR ) ) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ExtractNextComponentName(ServerName, &BaseCopy);
|
|
|
|
//
|
|
// Skip over the server name.
|
|
//
|
|
|
|
BaseCopy.Buffer += (ServerName->Length / sizeof(WCHAR)) + 1;
|
|
BaseCopy.Length -= ServerName->Length + sizeof(WCHAR);
|
|
BaseCopy.MaximumLength -= ServerName->MaximumLength + sizeof(WCHAR);
|
|
|
|
if ((ServerName->Length == sizeof(L"X:") - sizeof(WCHAR) ) &&
|
|
(ServerName->Buffer[(ServerName->Length / sizeof(WCHAR)) - 1] == L':')) {
|
|
|
|
//
|
|
// The file name is of the form x:\server\volume\foo\bar
|
|
//
|
|
|
|
*DriveName = *ServerName;
|
|
|
|
RtlInitUnicodeString( ServerName, NULL );
|
|
ExtractNextComponentName(ServerName, &BaseCopy);
|
|
|
|
if ( ServerName->Length != 0 ) {
|
|
|
|
//
|
|
// Skip over the server name.
|
|
//
|
|
|
|
BaseCopy.Buffer += (ServerName->Length / sizeof(WCHAR)) + 1;
|
|
BaseCopy.Length -= ServerName->Length + sizeof(WCHAR);
|
|
BaseCopy.MaximumLength -= ServerName->MaximumLength + sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
if ( ServerName->Length != 0 ) {
|
|
|
|
//
|
|
// The file name is of the form \\server\volume\foo\bar
|
|
// Set volume name to server\volume.
|
|
//
|
|
|
|
ExtractNextComponentName( &ShareName, &BaseCopy);
|
|
|
|
//
|
|
// Set volume name = \server\share
|
|
//
|
|
|
|
VolumeName->Buffer = ServerName->Buffer - 1;
|
|
ASSERT( VolumeName->Buffer[0] == '\\' );
|
|
|
|
if ( ShareName.Length != 0 ) {
|
|
|
|
VolumeName->Length = ServerName->Length + ShareName.Length + 2 * sizeof( WCHAR );
|
|
|
|
BaseCopy.Buffer += ShareName.Length / sizeof(WCHAR) + 1;
|
|
BaseCopy.Length -= ShareName.Length + sizeof(WCHAR);
|
|
BaseCopy.MaximumLength -= ShareName.MaximumLength + sizeof(WCHAR);
|
|
|
|
} else {
|
|
|
|
VolumeName->Length = ServerName->Length + ShareName.Length + sizeof( WCHAR );
|
|
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
}
|
|
|
|
return ExtractPathAndFileName ( &BaseCopy, PathName, FileName );
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TestCrackPath (
|
|
IN PUNICODE_STRING BaseName
|
|
) {
|
|
NTSTATUS Status;
|
|
UNICODE_STRING DriveName;
|
|
UNICODE_STRING ServerName;
|
|
UNICODE_STRING VolumeName;
|
|
UNICODE_STRING PathName;
|
|
UNICODE_STRING FileName;
|
|
RtlInitUnicodeString( &DriveName, L"Error" );
|
|
RtlInitUnicodeString( &ServerName, L"Error" );
|
|
RtlInitUnicodeString( &PathName, L"Error" );
|
|
RtlInitUnicodeString( &FileName, L"Error" );
|
|
DebugTrace( 0, Dbg, "\nName = %Z\n", BaseName );
|
|
Status = CrackPath( BaseName, &DriveName, &ServerName, &VolumeName, &PathName, &FileName );
|
|
DebugTrace( 0, Dbg, " DriveName = %Z\n", &DriveName );
|
|
DebugTrace( 0, Dbg, " ServerName= %Z\n", &ServerName );
|
|
DebugTrace( 0, Dbg, " VolumeName= %Z\n", &VolumeName );
|
|
DebugTrace( 0, Dbg, " PathName = %Z\n", &PathName );
|
|
DebugTrace( 0, Dbg, " FileName = %Z\n", &FileName );
|
|
return Status;
|
|
|
|
}
|
|
int
|
|
_cdecl
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
UNICODE_STRING Name;
|
|
RtlInitUnicodeString( &Name, L"\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\Path\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\Path\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\Path\\Path2\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\x:\\Server\\Path\\Path2\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\Path\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\Path\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\Path\\Path2\\FileName" );
|
|
TestCrackPath( &Name );
|
|
RtlInitUnicodeString( &Name, L"\\Server\\Path\\Path2\\FileName\\" );
|
|
TestCrackPath( &Name );
|
|
return 0;
|
|
}
|