882 lines
20 KiB
C
882 lines
20 KiB
C
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
/*++
|
||
|
|
||
|
Copyright (c) 1990 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
nt_obj.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
1. Contains routines to access symbolic link objects
|
||
|
|
||
|
2. Contains routines to convert between the DOS and ARC Name space
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Sunil Pai (sunilp) 20-Nov-1991
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#define BUFFER_SIZE 1024
|
||
|
#define SYMLINKTYPE L"SymbolicLink"
|
||
|
#define ARCNAMEOBJDIR L"\\ArcName"
|
||
|
#define DOSDEVOBJDIR L"\\DosDevices"
|
||
|
|
||
|
BOOL
|
||
|
IsSymbolicLinkType(
|
||
|
IN PUNICODE_STRING Type
|
||
|
);
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
DosPathToNtPathWorker(
|
||
|
IN LPSTR DosPath,
|
||
|
OUT LPSTR NtPath
|
||
|
)
|
||
|
{
|
||
|
CHAR Drive[] = "\\DosDevices\\?:";
|
||
|
WCHAR NtNameDrive[MAX_PATH];
|
||
|
|
||
|
ANSI_STRING AnsiString;
|
||
|
|
||
|
UNICODE_STRING Drive_U, NtNameDrive_U;
|
||
|
ANSI_STRING NtNameDrive_A;
|
||
|
|
||
|
BOOL bStatus;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
//
|
||
|
// Validate the DOS Path passed in
|
||
|
//
|
||
|
|
||
|
if (lstrlen(DosPath) < 2 || DosPath[1] != ':') {
|
||
|
SetErrorText(IDS_ERROR_INVALIDDISK);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Extract the drive
|
||
|
//
|
||
|
|
||
|
Drive[12] = DosPath[0];
|
||
|
|
||
|
//
|
||
|
// Get Unicode string for the drive
|
||
|
//
|
||
|
|
||
|
RtlInitAnsiString(&AnsiString, Drive);
|
||
|
Status = RtlAnsiStringToUnicodeString(
|
||
|
&Drive_U,
|
||
|
&AnsiString,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the Nt Name for the Drive
|
||
|
//
|
||
|
|
||
|
NtNameDrive_U.Buffer = NtNameDrive;
|
||
|
NtNameDrive_U.Length = 0;
|
||
|
NtNameDrive_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Query symbolic link of the drive
|
||
|
//
|
||
|
|
||
|
bStatus = GetSymbolicLinkTarget(&Drive_U, &NtNameDrive_U);
|
||
|
RtlFreeUnicodeString(&Drive_U);
|
||
|
if (!bStatus) {
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the Unicode NtName for drive to ansi
|
||
|
//
|
||
|
|
||
|
Status = RtlUnicodeStringToAnsiString(
|
||
|
&NtNameDrive_A,
|
||
|
&NtNameDrive_U,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the drive to the output variable
|
||
|
//
|
||
|
|
||
|
NtNameDrive_A.Buffer[NtNameDrive_A.Length] = '\0'; //Null terminate
|
||
|
lstrcpy(NtPath, NtNameDrive_A.Buffer);
|
||
|
RtlFreeAnsiString(&NtNameDrive_A);
|
||
|
|
||
|
//
|
||
|
// concatenate the rest of the DosPath to this ArcPath
|
||
|
//
|
||
|
|
||
|
lstrcat(NtPath, DosPath+2);
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
NtPathToDosPathWorker(
|
||
|
IN LPSTR NtPath,
|
||
|
OUT LPSTR DosPath
|
||
|
)
|
||
|
{
|
||
|
CHAR Drive;
|
||
|
CHAR DriveStr[3] = "x:";
|
||
|
CHAR NtDevicePath[MAX_PATH];
|
||
|
unsigned MatchLen;
|
||
|
|
||
|
//
|
||
|
// Iterate through each potential drive letter.
|
||
|
//
|
||
|
for(Drive='A'; Drive<='Z'; Drive++) {
|
||
|
|
||
|
DriveStr[0] = Drive;
|
||
|
|
||
|
//
|
||
|
// Get the equivalent NT device path, if any.
|
||
|
//
|
||
|
if(DosPathToNtPathWorker(DriveStr,NtDevicePath)) {
|
||
|
|
||
|
MatchLen = lstrlen(NtDevicePath);
|
||
|
|
||
|
//
|
||
|
// If the NT Path we are trying to translate is a prefix
|
||
|
// of the NT path for the current drive, we've got a match.
|
||
|
//
|
||
|
if(!_strnicmp(NtDevicePath,NtPath,MatchLen)) {
|
||
|
|
||
|
lstrcpy(DosPath,DriveStr);
|
||
|
lstrcat(DosPath,NtPath+MatchLen);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Didn't find a drive letter that matches so there is no
|
||
|
// equivalent DOS path.
|
||
|
//
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
DosPathToArcPathWorker(
|
||
|
IN LPSTR DosPath,
|
||
|
OUT LPSTR ArcPath
|
||
|
)
|
||
|
{
|
||
|
CHAR Drive[] = "\\DosDevices\\?:";
|
||
|
WCHAR NtNameDrive[MAX_PATH];
|
||
|
WCHAR ArcNameDrive[MAX_PATH];
|
||
|
|
||
|
ANSI_STRING AnsiString;
|
||
|
|
||
|
UNICODE_STRING Drive_U, NtNameDrive_U, ObjDir_U, ArcNameDrive_U;
|
||
|
ANSI_STRING ArcNameDrive_A;
|
||
|
|
||
|
BOOL bStatus;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
//
|
||
|
// Validate the DOS Path passed in
|
||
|
//
|
||
|
|
||
|
if (lstrlen(DosPath) < 2 || DosPath[1] != ':') {
|
||
|
SetErrorText(IDS_ERROR_INVALIDDISK);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Extract the drive
|
||
|
//
|
||
|
|
||
|
Drive[12] = DosPath[0];
|
||
|
|
||
|
//
|
||
|
// Get Unicode string for the drive
|
||
|
//
|
||
|
|
||
|
RtlInitAnsiString(&AnsiString, Drive);
|
||
|
Status = RtlAnsiStringToUnicodeString(
|
||
|
&Drive_U,
|
||
|
&AnsiString,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the Nt Name for the Drive
|
||
|
//
|
||
|
|
||
|
NtNameDrive_U.Buffer = NtNameDrive;
|
||
|
NtNameDrive_U.Length = 0;
|
||
|
NtNameDrive_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the ArcName for the drive
|
||
|
//
|
||
|
|
||
|
ArcNameDrive_U.Buffer = ArcNameDrive;
|
||
|
ArcNameDrive_U.Length = 0;
|
||
|
ArcNameDrive_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the \\ArcName objdir name
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString(&ObjDir_U, ARCNAMEOBJDIR);
|
||
|
|
||
|
//
|
||
|
// Query symbolic link of the drive
|
||
|
//
|
||
|
|
||
|
bStatus = GetSymbolicLinkTarget(&Drive_U, &NtNameDrive_U);
|
||
|
RtlFreeUnicodeString(&Drive_U);
|
||
|
if (!bStatus) {
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find the object in the arcname directory
|
||
|
//
|
||
|
|
||
|
bStatus = GetSymbolicLinkSource(&ObjDir_U, &NtNameDrive_U, &ArcNameDrive_U);
|
||
|
if (!bStatus) {
|
||
|
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the Unicode ArcName for drive to ansi
|
||
|
//
|
||
|
|
||
|
Status = RtlUnicodeStringToAnsiString(
|
||
|
&ArcNameDrive_A,
|
||
|
&ArcNameDrive_U,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the drive to the output variable
|
||
|
//
|
||
|
|
||
|
ArcNameDrive_A.Buffer[ArcNameDrive_A.Length] = '\0'; //Null terminate
|
||
|
lstrcpy(ArcPath, ArcNameDrive_A.Buffer);
|
||
|
RtlFreeAnsiString(&ArcNameDrive_A);
|
||
|
|
||
|
//
|
||
|
// concatenate the rest of the DosPath to this ArcPath
|
||
|
//
|
||
|
|
||
|
lstrcat(ArcPath, DosPath+2);
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
ArcPathToDosPathWorker(
|
||
|
IN LPSTR ArcPath,
|
||
|
OUT LPSTR DosPath
|
||
|
)
|
||
|
{
|
||
|
CHAR ArcDir[] = "\\ArcName\\";
|
||
|
CHAR ArcFullPath[MAX_PATH];
|
||
|
SZ ArcDrive, FilePath;
|
||
|
|
||
|
CHAR ArcDriveObject[MAX_PATH];
|
||
|
WCHAR NtNameDrive[MAX_PATH];
|
||
|
WCHAR DosNameDrive[MAX_PATH];
|
||
|
|
||
|
|
||
|
ANSI_STRING AnsiString;
|
||
|
|
||
|
UNICODE_STRING Drive_U, NtNameDrive_U, ObjDir_U, DosNameDrive_U;
|
||
|
ANSI_STRING DosNameDrive_A;
|
||
|
|
||
|
BOOL bStatus;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
//
|
||
|
// Validate the Arc Path passed in
|
||
|
//
|
||
|
|
||
|
if (lstrlen(ArcPath) >= MAX_PATH) {
|
||
|
SetErrorText(IDS_ERROR_INVALIDDISK);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
// extract the arc drive and filename
|
||
|
|
||
|
lstrcpy (ArcFullPath, ArcPath);
|
||
|
ArcDrive = ArcFullPath;
|
||
|
FilePath = strchr (ArcFullPath, '\\');
|
||
|
if (FilePath != NULL) {
|
||
|
*FilePath = '\0';
|
||
|
FilePath++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Form the full spec for the ArcDrive object name
|
||
|
//
|
||
|
|
||
|
lstrcpy (ArcDriveObject, ArcDir);
|
||
|
lstrcat (ArcDriveObject, ArcDrive);
|
||
|
|
||
|
//
|
||
|
// Get Unicode string for the drive
|
||
|
//
|
||
|
|
||
|
RtlInitAnsiString(&AnsiString, ArcDriveObject);
|
||
|
Status = RtlAnsiStringToUnicodeString(
|
||
|
&Drive_U,
|
||
|
&AnsiString,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the Nt Name for the Drive
|
||
|
//
|
||
|
|
||
|
NtNameDrive_U.Buffer = NtNameDrive;
|
||
|
NtNameDrive_U.Length = 0;
|
||
|
NtNameDrive_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the ArcName for the drive
|
||
|
//
|
||
|
|
||
|
DosNameDrive_U.Buffer = DosNameDrive;
|
||
|
DosNameDrive_U.Length = 0;
|
||
|
DosNameDrive_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Initialise Unicode string to hold the \\DosDevices objdir name
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString(&ObjDir_U, DOSDEVOBJDIR);
|
||
|
|
||
|
//
|
||
|
// Query symbolic link of the drive
|
||
|
//
|
||
|
|
||
|
bStatus = GetSymbolicLinkTarget(&Drive_U, &NtNameDrive_U);
|
||
|
RtlFreeUnicodeString(&Drive_U);
|
||
|
if (!bStatus) {
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find the object in the dosdevices directory
|
||
|
//
|
||
|
|
||
|
bStatus = GetSymbolicLinkSource(&ObjDir_U, &NtNameDrive_U, &DosNameDrive_U);
|
||
|
if (!bStatus) {
|
||
|
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the Unicode ArcName for drive to ansi
|
||
|
//
|
||
|
|
||
|
Status = RtlUnicodeStringToAnsiString(
|
||
|
&DosNameDrive_A,
|
||
|
&DosNameDrive_U,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_RTLOOM);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the drive to the output variable
|
||
|
//
|
||
|
|
||
|
DosNameDrive_A.Buffer[DosNameDrive_A.Length] = '\0'; //Null terminate
|
||
|
lstrcpy(DosPath, DosNameDrive_A.Buffer);
|
||
|
RtlFreeAnsiString(&DosNameDrive_A);
|
||
|
|
||
|
//
|
||
|
// concatenate the rest of the DosPath to this ArcPath
|
||
|
//
|
||
|
if (FilePath != NULL) {
|
||
|
lstrcat (DosPath, "\\");
|
||
|
lstrcat (DosPath, FilePath);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsDriveExternalScsi(
|
||
|
IN LPSTR DosDrive,
|
||
|
OUT BOOL *IsExternal
|
||
|
)
|
||
|
{
|
||
|
CHAR ArcNameDrive[MAX_PATH];
|
||
|
BOOL bStatus;
|
||
|
|
||
|
//
|
||
|
// Set IsExternal to false
|
||
|
//
|
||
|
|
||
|
*IsExternal = FALSE;
|
||
|
|
||
|
//
|
||
|
// Query the ArcName for the DOS Drive
|
||
|
//
|
||
|
|
||
|
bStatus = DosPathToArcPathWorker(DosDrive, ArcNameDrive);
|
||
|
if (!bStatus) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find out if the Arcname first four letters are scsi
|
||
|
//
|
||
|
|
||
|
ArcNameDrive[4] = '\0'; // Only interested in first four letters
|
||
|
if(!lstrcmpi(ArcNameDrive, "scsi")) {
|
||
|
*IsExternal = TRUE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* OBJECT MANAGEMENT ROUTINES
|
||
|
*/
|
||
|
|
||
|
BOOL
|
||
|
GetSymbolicLinkSource(
|
||
|
IN PUNICODE_STRING pObjDir_U,
|
||
|
IN PUNICODE_STRING pTarget_U,
|
||
|
OUT PUNICODE_STRING pSource_U
|
||
|
)
|
||
|
{
|
||
|
PCHAR Buffer, FullNameObject, ObjectLink, SavedMatch;
|
||
|
UNICODE_STRING ObjName_U, ObjLink_U;
|
||
|
|
||
|
UNICODE_STRING SavedMatch_U;
|
||
|
BOOLEAN IsMatchSaved = FALSE;
|
||
|
|
||
|
OBJECT_ATTRIBUTES Attributes;
|
||
|
|
||
|
HANDLE DirectoryHandle;
|
||
|
ULONG Context = 0;
|
||
|
ULONG ReturnedLength;
|
||
|
BOOLEAN RestartScan = TRUE;
|
||
|
BOOLEAN ReturnSingleEntry = TRUE; //LATER change this to FALSE
|
||
|
|
||
|
POBJECT_DIRECTORY_INFORMATION DirInfo;
|
||
|
|
||
|
NTSTATUS Status;
|
||
|
BOOL bStatus;
|
||
|
|
||
|
//
|
||
|
// Open the object directory.
|
||
|
//
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&Attributes,
|
||
|
pObjDir_U,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
Status = NtOpenDirectoryObject(
|
||
|
&DirectoryHandle,
|
||
|
DIRECTORY_ALL_ACCESS,
|
||
|
&Attributes
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS( Status ) ) {
|
||
|
SetErrorText(IDS_ERROR_OBJDIROPEN);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Find the symbolic link objects in the directory and query them for
|
||
|
// a match with the string passed in
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Allocate a buffer to query the directory objects
|
||
|
//
|
||
|
if ((Buffer = SAlloc(BUFFER_SIZE)) == NULL) {
|
||
|
SetErrorText(IDS_ERROR_DLLOOM);
|
||
|
NtClose(DirectoryHandle);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Form a Unicode string object to hold the symbolic link objects found
|
||
|
// in the object directory
|
||
|
//
|
||
|
|
||
|
if ((FullNameObject = SAlloc(MAX_PATH * sizeof(WCHAR))) == NULL) {
|
||
|
SetErrorText(IDS_ERROR_DLLOOM);
|
||
|
SFree (Buffer);
|
||
|
NtClose (DirectoryHandle);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
ObjName_U.Buffer = (PWSTR)FullNameObject;
|
||
|
ObjName_U.Length = 0;
|
||
|
ObjName_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Form a Unicode string object to hold the symbolic link objects found
|
||
|
// in the object directory
|
||
|
//
|
||
|
|
||
|
if ((ObjectLink = SAlloc(MAX_PATH * sizeof(WCHAR))) == NULL) {
|
||
|
SetErrorText(IDS_ERROR_DLLOOM);
|
||
|
SFree (Buffer);
|
||
|
SFree (FullNameObject);
|
||
|
NtClose (DirectoryHandle);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
ObjLink_U.Buffer = (PWSTR)ObjectLink;
|
||
|
ObjLink_U.Length = 0;
|
||
|
ObjLink_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
|
||
|
if ((SavedMatch = SAlloc(MAX_PATH * sizeof(WCHAR))) == NULL) {
|
||
|
SetErrorText(IDS_ERROR_DLLOOM);
|
||
|
SFree (Buffer);
|
||
|
SFree (FullNameObject);
|
||
|
SFree (ObjectLink);
|
||
|
NtClose (DirectoryHandle);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
SavedMatch_U.Buffer = (PWSTR)SavedMatch;
|
||
|
SavedMatch_U.Length = 0;
|
||
|
SavedMatch_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
while (TRUE) {
|
||
|
//
|
||
|
// Clear the buffer
|
||
|
//
|
||
|
RtlZeroMemory( Buffer, BUFFER_SIZE);
|
||
|
|
||
|
//
|
||
|
// repeatedly Query the directory objects till done
|
||
|
//
|
||
|
|
||
|
Status = NtQueryDirectoryObject(
|
||
|
DirectoryHandle,
|
||
|
Buffer,
|
||
|
BUFFER_SIZE,
|
||
|
ReturnSingleEntry, // fetch more than one entry
|
||
|
RestartScan, // start rescan true on first go
|
||
|
&Context,
|
||
|
&ReturnedLength
|
||
|
);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check the Status of the operation.
|
||
|
//
|
||
|
|
||
|
if (!NT_SUCCESS(Status) && (Status != STATUS_MORE_ENTRIES)) {
|
||
|
if (Status == STATUS_NO_MORE_FILES || Status == STATUS_NO_MORE_ENTRIES) {
|
||
|
SetErrorText(IDS_ERROR_INVALIDDISK);
|
||
|
}
|
||
|
else {
|
||
|
SetErrorText(IDS_ERROR_OBJDIRREAD);
|
||
|
}
|
||
|
SFree(Buffer);
|
||
|
SFree(FullNameObject);
|
||
|
SFree(ObjectLink);
|
||
|
if(IsMatchSaved) {
|
||
|
RtlCopyUnicodeString (pSource_U, &SavedMatch_U);
|
||
|
SFree(SavedMatch);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
SFree(SavedMatch);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure that restart scan is false for next go
|
||
|
//
|
||
|
RestartScan = FALSE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// For every record in the buffer, see if the type of the object
|
||
|
// is a symbolic link
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Point to the first record in the buffer, we are guaranteed to have
|
||
|
// one otherwise Status would have been No More Files
|
||
|
//
|
||
|
|
||
|
DirInfo = (POBJECT_DIRECTORY_INFORMATION) Buffer;
|
||
|
|
||
|
while (TRUE) {
|
||
|
|
||
|
//
|
||
|
// Check if there is another record. If there isn't, break out of
|
||
|
// the loop now
|
||
|
//
|
||
|
|
||
|
if (DirInfo->Name.Length == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// See if the object type is a symbolic link
|
||
|
//
|
||
|
if (IsSymbolicLinkType(&(DirInfo->TypeName))) {
|
||
|
|
||
|
//
|
||
|
// get full pathname of object
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Check if we will overflow our buffer
|
||
|
//
|
||
|
if ((
|
||
|
pObjDir_U->Length +
|
||
|
sizeof(WCHAR) +
|
||
|
DirInfo->Name.Length +
|
||
|
sizeof(WCHAR)
|
||
|
) > ObjName_U.MaximumLength ) {
|
||
|
|
||
|
SetErrorText(IDS_ERROR_OBJNAMOVF);
|
||
|
SFree(Buffer);
|
||
|
SFree(FullNameObject);
|
||
|
SFree(ObjectLink);
|
||
|
|
||
|
if(IsMatchSaved) {
|
||
|
RtlCopyUnicodeString (pSource_U, &SavedMatch_U);
|
||
|
SFree(SavedMatch);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
SFree(SavedMatch);
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the current object name over the the buffer prefixing
|
||
|
// it with the \ArcName\ object directory name
|
||
|
//
|
||
|
|
||
|
RtlCopyUnicodeString ( &ObjName_U, pObjDir_U );
|
||
|
RtlAppendUnicodeToString ( &ObjName_U, L"\\" );
|
||
|
RtlAppendUnicodeStringToString ( &ObjName_U, &(DirInfo->Name));
|
||
|
|
||
|
//
|
||
|
// query the symbolic link target
|
||
|
//
|
||
|
|
||
|
ObjLink_U.Buffer = (PWSTR)ObjectLink;
|
||
|
ObjLink_U.Length = 0;
|
||
|
ObjLink_U.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||
|
|
||
|
bStatus = GetSymbolicLinkTarget (&ObjName_U, &ObjLink_U);
|
||
|
if (bStatus != TRUE) {
|
||
|
SFree(Buffer);
|
||
|
SFree(FullNameObject);
|
||
|
SFree(ObjectLink);
|
||
|
|
||
|
if(IsMatchSaved) {
|
||
|
RtlCopyUnicodeString (pSource_U, &SavedMatch_U);
|
||
|
SFree(SavedMatch);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
SFree(SavedMatch);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// see if it compares to the name we are looking for
|
||
|
//
|
||
|
|
||
|
if (RtlEqualUnicodeString (pTarget_U, &ObjLink_U, TRUE)) {
|
||
|
|
||
|
#if i386
|
||
|
UNICODE_STRING Multi_U;
|
||
|
|
||
|
RtlInitUnicodeString(&Multi_U,L"multi(");
|
||
|
if(RtlPrefixUnicodeString(&Multi_U,&DirInfo->Name,TRUE)) {
|
||
|
|
||
|
RtlCopyUnicodeString(&SavedMatch_U,&DirInfo->Name);
|
||
|
IsMatchSaved = TRUE;
|
||
|
|
||
|
} else // scsi, just return it. Favor scsi over multi.
|
||
|
#endif
|
||
|
{
|
||
|
RtlCopyUnicodeString (pSource_U, &(DirInfo->Name));
|
||
|
SFree(Buffer);
|
||
|
SFree(FullNameObject);
|
||
|
SFree(ObjectLink);
|
||
|
SFree(SavedMatch);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// There is another record so advance DirInfo to the next entry
|
||
|
//
|
||
|
|
||
|
DirInfo = (POBJECT_DIRECTORY_INFORMATION) (((PCHAR) DirInfo) +
|
||
|
sizeof( OBJECT_DIRECTORY_INFORMATION ) );
|
||
|
|
||
|
} // while
|
||
|
|
||
|
} // while
|
||
|
|
||
|
return ( FALSE );
|
||
|
|
||
|
} // getarcname
|
||
|
|
||
|
|
||
|
|
||
|
/* Checks to see if a given object type is a symbolic link type */
|
||
|
|
||
|
BOOL
|
||
|
IsSymbolicLinkType(
|
||
|
IN PUNICODE_STRING Type
|
||
|
)
|
||
|
{
|
||
|
UNICODE_STRING TypeName;
|
||
|
|
||
|
//
|
||
|
// Check the length of the string
|
||
|
//
|
||
|
if (Type->Length == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// compare it to the symbolic link type name
|
||
|
//
|
||
|
RtlInitUnicodeString(&TypeName, SYMLINKTYPE);
|
||
|
return (RtlEqualUnicodeString(Type, &TypeName, TRUE));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
GetSymbolicLinkTarget(
|
||
|
IN PUNICODE_STRING pSourceString_U,
|
||
|
IN OUT PUNICODE_STRING pDestString_U
|
||
|
)
|
||
|
{
|
||
|
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
OBJECT_ATTRIBUTES Attributes;
|
||
|
HANDLE ObjectHandle;
|
||
|
|
||
|
//
|
||
|
// Initialise the object attributes structure for the symbolic
|
||
|
// link object
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&Attributes,
|
||
|
pSourceString_U,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Open the symbolic link for link_query access
|
||
|
//
|
||
|
|
||
|
Status = NtOpenSymbolicLinkObject(
|
||
|
&ObjectHandle,
|
||
|
READ_CONTROL | SYMBOLIC_LINK_QUERY,
|
||
|
&Attributes
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_SYMLNKOPEN);
|
||
|
return ( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// query the symbolic link target
|
||
|
//
|
||
|
|
||
|
Status = NtQuerySymbolicLinkObject(
|
||
|
ObjectHandle,
|
||
|
pDestString_U,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
SetErrorText(IDS_ERROR_SYMLNKREAD);
|
||
|
NtClose(ObjectHandle);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// close the link object
|
||
|
//
|
||
|
|
||
|
NtClose(ObjectHandle);
|
||
|
|
||
|
//
|
||
|
// return the link target
|
||
|
//
|
||
|
return ( TRUE );
|
||
|
}
|