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.
580 lines
15 KiB
580 lines
15 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1992.
|
|
//
|
|
// File: PathMisc.c
|
|
//
|
|
// Contents: methods to read information from the registry.
|
|
//
|
|
// History: udayh: created.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <lm.h>
|
|
#include <dfsheader.h>
|
|
#include <dfsmisc.h>
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsGetNetbiosName - Gets the netbios name of a machine
|
|
//
|
|
// Synopsis: DfsGetNetbiosName takes the name and returns 2 components
|
|
// of the name: the first is the name without the leading \\
|
|
// and upto the next "." or "\". The rest of the path (if any)
|
|
// is returned in the pRemaining argument.
|
|
//
|
|
// Arguments: pName - Input name
|
|
// pNetbiosName - the netbios name for the passed in name
|
|
// pRemaining - The rest of the name beyond the netbios name
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DfsGetNetbiosName(
|
|
PUNICODE_STRING pName,
|
|
PUNICODE_STRING pNetbiosName,
|
|
PUNICODE_STRING pRemaining )
|
|
{
|
|
|
|
USHORT i = 0, j;
|
|
|
|
RtlInitUnicodeString(pNetbiosName, NULL);
|
|
if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
|
|
|
|
for (; i < pName->Length/sizeof(WCHAR); i++) {
|
|
if (pName->Buffer[i] != UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
|
|
if ((pName->Buffer[j] == UNICODE_PATH_SEP) ||
|
|
(pName->Buffer[j] == L'.')) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j != i) {
|
|
pNetbiosName->Buffer = &pName->Buffer[i];
|
|
pNetbiosName->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pNetbiosName->MaximumLength = pNetbiosName->Length;
|
|
}
|
|
|
|
|
|
for (i = j; i < pName->Length/sizeof(WCHAR); i++) {
|
|
if ((pName->Buffer[i] != UNICODE_PATH_SEP) &&
|
|
(pName->Buffer[i] != L'.')) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
j = pName->Length/sizeof(WCHAR);
|
|
|
|
if ((pRemaining) && (j != i)) {
|
|
pRemaining->Buffer = &pName->Buffer[i];
|
|
pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pRemaining->MaximumLength = pRemaining->Length;
|
|
}
|
|
|
|
return NOTHING;
|
|
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsGetPathComponents - Breaks pathname into server, share,rest
|
|
//
|
|
// Synopsis: DfsGetPathComponents takes the name and returns 3 components
|
|
// of the name: the first (ServerName), the next (ShareName) and the// last (Remaining Name)
|
|
//
|
|
// Arguments: pName - Input name
|
|
// pServerName - The first path component
|
|
// pShareName - The second path component
|
|
// pRemaining - The rest of the path component
|
|
//
|
|
// Returns: STATUS: STATUS_INVALID_PARAMETER or Success
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
DFSSTATUS
|
|
DfsGetPathComponents(
|
|
PUNICODE_STRING pName,
|
|
PUNICODE_STRING pServerName,
|
|
PUNICODE_STRING pShareName,
|
|
PUNICODE_STRING pRemaining)
|
|
{
|
|
USHORT i = 0, j;
|
|
DFSSTATUS Status = ERROR_INVALID_PARAMETER;
|
|
|
|
RtlInitUnicodeString(pServerName, NULL);
|
|
if (pShareName) RtlInitUnicodeString(pShareName, NULL);
|
|
if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
|
|
|
|
for (; i < pName->Length/sizeof(WCHAR); i++) {
|
|
if ((pName->Buffer[i] != UNICODE_PATH_SEP) ||
|
|
(i >= 2))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
|
|
if (pName->Buffer[j] == UNICODE_PATH_SEP)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j > i) {
|
|
pServerName->Buffer = &pName->Buffer[i];
|
|
pServerName->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pServerName->MaximumLength = pServerName->Length;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
i = j + 1;
|
|
|
|
for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
|
|
if (pName->Buffer[j] == UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((pShareName) && (j > i)) {
|
|
pShareName->Buffer = &pName->Buffer[i];
|
|
pShareName->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pShareName->MaximumLength = pShareName->Length;
|
|
}
|
|
|
|
|
|
i = j + 1;
|
|
|
|
j = pName->Length/sizeof(WCHAR);
|
|
|
|
if ((pRemaining) && (j > i)) {
|
|
pRemaining->Buffer = &pName->Buffer[i];
|
|
pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pRemaining->MaximumLength = pRemaining->Length;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsGetFirstComponent - Gets the first part of the pathname
|
|
//
|
|
// Synopsis: DfsGetFirstComponent takes the name and returns 2 components
|
|
// of the name: the first is the first part of the pathname.
|
|
// The rest of the path is returned in the pRemaining argument.
|
|
//
|
|
// Arguments: pName - Input name
|
|
// pFirstName - First part of the name
|
|
// pRemaining - The rest of the name beyond the netbios name
|
|
//
|
|
// Returns: STATUS_INVALID_PARAMETER or SUCCESS
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
DfsGetFirstComponent(
|
|
PUNICODE_STRING pName,
|
|
PUNICODE_STRING pFirstName,
|
|
PUNICODE_STRING pRemaining)
|
|
{
|
|
USHORT i = 0, j;
|
|
DFSSTATUS Status = ERROR_INVALID_PARAMETER;
|
|
|
|
RtlInitUnicodeString(pFirstName, NULL);
|
|
if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
|
|
|
|
for (; i < pName->Length/sizeof(WCHAR); i++) {
|
|
if ((pName->Buffer[i] != UNICODE_PATH_SEP) ||
|
|
(i >= 2))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
|
|
if (pName->Buffer[j] == UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j > i) {
|
|
pFirstName->Buffer = &pName->Buffer[i];
|
|
pFirstName->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pFirstName->MaximumLength = pFirstName->Length;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
i = (j + 1);
|
|
|
|
j = pName->Length/sizeof(WCHAR);
|
|
|
|
if ((pRemaining) && (j > i)) {
|
|
pRemaining->Buffer = &pName->Buffer[i];
|
|
pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pRemaining->MaximumLength = pRemaining->Length;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsGetFirstComponent - Gets the first part of the pathname
|
|
//
|
|
// Synopsis: DfsGetFirstComponent takes the name and returns 2 components
|
|
// of the name: the first is the first part of the pathname.
|
|
// The rest of the path is returned in the pRemaining argument.
|
|
//
|
|
// Arguments: pName - Input name
|
|
// pFirstName - First part of the name
|
|
// pRemaining - The rest of the name beyond the netbios name
|
|
//
|
|
// Returns: STATUS_INVALID_PARAMETER or SUCCESS
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
DfsGetNextComponent(
|
|
PUNICODE_STRING pName,
|
|
PUNICODE_STRING pNextName,
|
|
PUNICODE_STRING pRemaining)
|
|
{
|
|
USHORT i = 0, j;
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
RtlInitUnicodeString(pNextName, NULL);
|
|
if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
|
|
|
|
for (; i < pName->Length/sizeof(WCHAR); i++) {
|
|
if (pName->Buffer[i] != UNICODE_PATH_SEP)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
|
|
if (pName->Buffer[j] == UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
pNextName->Buffer = &pName->Buffer[0];
|
|
pNextName->Length = (USHORT)((j) * sizeof(WCHAR));
|
|
pNextName->MaximumLength = pNextName->Length;
|
|
|
|
i = (j + 1);
|
|
|
|
j = pName->Length/sizeof(WCHAR);
|
|
|
|
if ((pRemaining) && (j > i)) {
|
|
pRemaining->Buffer = &pName->Buffer[i];
|
|
pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
|
|
pRemaining->MaximumLength = pRemaining->Length;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsGetSharePath
|
|
//
|
|
// Arguments: ServerName - the name of the server
|
|
// ShareName - the name of the share
|
|
// pPathName - the unicode string representing the NT name
|
|
// of the local path representing the share
|
|
//
|
|
// Returns: SUCCESS or error
|
|
//
|
|
// Description: This routine takes a servername and a sharename, and
|
|
// returns an NT pathname to the physical resource that is
|
|
// backing the share name.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
DfsGetSharePath(
|
|
IN LPWSTR ServerName,
|
|
IN LPWSTR ShareName,
|
|
OUT PUNICODE_STRING pPathName )
|
|
{
|
|
LPWSTR UseServerName = NULL;
|
|
ULONG InfoLevel = 2;
|
|
PSHARE_INFO_2 pShareInfo;
|
|
NET_API_STATUS NetStatus;
|
|
DFSSTATUS Status;
|
|
UNICODE_STRING NtSharePath;
|
|
|
|
if (IsEmptyString(ServerName) == FALSE)
|
|
{
|
|
UseServerName = ServerName;
|
|
}
|
|
|
|
NetStatus = NetShareGetInfo( UseServerName,
|
|
ShareName,
|
|
InfoLevel,
|
|
(LPBYTE *)&pShareInfo );
|
|
if (NetStatus != ERROR_SUCCESS)
|
|
{
|
|
Status = (DFSSTATUS)NetStatus;
|
|
return Status;
|
|
}
|
|
|
|
if( RtlDosPathNameToNtPathName_U(pShareInfo->shi2_path,
|
|
&NtSharePath,
|
|
NULL,
|
|
NULL ) == TRUE )
|
|
{
|
|
Status = DfsCreateUnicodeString( pPathName,
|
|
&NtSharePath );
|
|
|
|
RtlFreeUnicodeString( &NtSharePath );
|
|
}
|
|
else {
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
NetApiBufferFree( pShareInfo );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
ULONG
|
|
DfsSizeUncPath(
|
|
PUNICODE_STRING FirstComponent,
|
|
PUNICODE_STRING SecondComponent )
|
|
{
|
|
ULONG SizeRequired = 0;
|
|
|
|
SizeRequired += sizeof(UNICODE_PATH_SEP);
|
|
SizeRequired += sizeof(UNICODE_PATH_SEP);
|
|
SizeRequired += FirstComponent->Length;
|
|
SizeRequired += sizeof(UNICODE_PATH_SEP);
|
|
SizeRequired += SecondComponent->Length;
|
|
SizeRequired += sizeof(UNICODE_NULL);
|
|
|
|
return SizeRequired;
|
|
}
|
|
|
|
VOID
|
|
DfsCopyUncPath(
|
|
LPWSTR NewPath,
|
|
PUNICODE_STRING FirstComponent,
|
|
PUNICODE_STRING SecondComponent )
|
|
{
|
|
ULONG CurrentIndex = 0;
|
|
|
|
NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
|
|
NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
|
|
RtlCopyMemory(&NewPath[CurrentIndex],
|
|
FirstComponent->Buffer,
|
|
FirstComponent->Length );
|
|
CurrentIndex += (FirstComponent->Length / sizeof(WCHAR));
|
|
|
|
if (NewPath[CurrentIndex] != UNICODE_PATH_SEP &&
|
|
SecondComponent->Buffer[0] != UNICODE_PATH_SEP )
|
|
{
|
|
NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
|
|
}
|
|
RtlCopyMemory(&NewPath[CurrentIndex],
|
|
SecondComponent->Buffer,
|
|
SecondComponent->Length );
|
|
CurrentIndex += (SecondComponent->Length / sizeof(WCHAR));
|
|
|
|
NewPath[CurrentIndex] = UNICODE_NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// dfsdev: validate the next two functions. They appear to work,
|
|
// but we need to look into the boundary cases.
|
|
//
|
|
|
|
NTSTATUS
|
|
StripLastPathComponent(
|
|
PUNICODE_STRING pPath )
|
|
{
|
|
USHORT i = 0, j;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
if (pPath->Length == 0)
|
|
{
|
|
return Status;
|
|
}
|
|
for( i = (pPath->Length - 1)/ sizeof(WCHAR); i != 0; i--) {
|
|
if (pPath->Buffer[i] != UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j != 0; j--){
|
|
if (pPath->Buffer[j] == UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
pPath->Length = (j) * sizeof(WCHAR);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
AddNextPathComponent(
|
|
PUNICODE_STRING pPath )
|
|
{
|
|
USHORT i = 0, j;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
for( i = pPath->Length / sizeof(WCHAR); i < pPath->MaximumLength/sizeof(WCHAR); i++) {
|
|
if (pPath->Buffer[i] != UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < (pPath->MaximumLength -1)/sizeof(WCHAR); j++) {
|
|
if (pPath->Buffer[j] == UNICODE_PATH_SEP) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
pPath->Length = j * sizeof(WCHAR);
|
|
return Status;
|
|
}
|
|
|
|
void
|
|
StripTrailingSpacesFromPath(
|
|
LPWSTR pPath )
|
|
{
|
|
LPWSTR NewPath = NULL;
|
|
|
|
if(pPath)
|
|
{
|
|
|
|
NewPath = pPath + wcslen(pPath);
|
|
while (NewPath != pPath)
|
|
{
|
|
if( (NewPath[-1] != L' ' ) && (NewPath[-1] != L'\t' ))
|
|
{
|
|
break;
|
|
}
|
|
|
|
NewPath--;
|
|
}
|
|
|
|
*NewPath = L'\0' ;
|
|
}
|
|
}
|
|
|
|
LPWSTR
|
|
StripLeadingSpacesFromPath(
|
|
LPWSTR pPath )
|
|
{
|
|
LPWSTR NewPath = NULL;
|
|
|
|
NewPath = pPath + wcsspn( pPath, L" \t");
|
|
|
|
return NewPath;
|
|
}
|
|
|
|
LPWSTR
|
|
StripSpacesFromPath(
|
|
LPWSTR pPath )
|
|
{
|
|
LPWSTR NewPath = NULL;
|
|
|
|
NewPath = StripLeadingSpacesFromPath( pPath);
|
|
|
|
StripTrailingSpacesFromPath(NewPath );
|
|
|
|
return NewPath;
|
|
}
|
|
|
|
|
|
//
|
|
// This is a copy of the RtlInitUnicodeStringEx from rtl\string.c
|
|
// This is here because older systems (win2k) dont have this
|
|
// in their ntdll and causes us grief when our binaries are run
|
|
// on win2k.
|
|
//
|
|
NTSTATUS
|
|
DfsCopyOfRtlInitUnicodeStringEx(
|
|
OUT PUNICODE_STRING DestinationString,
|
|
IN PCWSTR SourceString OPTIONAL)
|
|
{
|
|
if (SourceString != NULL) {
|
|
SIZE_T Length = wcslen(SourceString);
|
|
|
|
// We are actually limited to 32765 characters since we want to store a meaningful
|
|
// MaximumLength also.
|
|
if (Length > (UNICODE_STRING_MAX_CHARS - 1)) {
|
|
return STATUS_NAME_TOO_LONG;
|
|
}
|
|
|
|
Length *= sizeof(WCHAR);
|
|
|
|
DestinationString->Length = (USHORT) Length;
|
|
DestinationString->MaximumLength = (USHORT) (Length + sizeof(WCHAR));
|
|
DestinationString->Buffer = (PWSTR) SourceString;
|
|
} else {
|
|
DestinationString->Length = 0;
|
|
DestinationString->MaximumLength = 0;
|
|
DestinationString->Buffer = NULL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
DfsRtlInitUnicodeStringEx(PUNICODE_STRING DestinationString,
|
|
PCWSTR SourceString)
|
|
{
|
|
DFSSTATUS DfsStatus = ERROR_SUCCESS;
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
|
|
NtStatus = DfsCopyOfRtlInitUnicodeStringEx(DestinationString, SourceString);
|
|
if(NtStatus != STATUS_SUCCESS)
|
|
{
|
|
DestinationString->Buffer = NULL;
|
|
DestinationString->Length = 0;
|
|
DestinationString->MaximumLength = 0;
|
|
DfsStatus = RtlNtStatusToDosError(NtStatus);
|
|
}
|
|
|
|
return DfsStatus;
|
|
}
|
|
|
|
|
|
|