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.
1094 lines
36 KiB
1094 lines
36 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
srvini.c
|
|
|
|
Abstract:
|
|
|
|
This is the initialization file for the Windows 32-bit Base Ini File
|
|
Mapping code. It loads the INI file mapping data from the registry and
|
|
places it in a data structure stored in the shared memory section that is
|
|
visible as read-only data to all Win32 applications.
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 10-Nov-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "basesrv.h"
|
|
|
|
PINIFILE_MAPPING BaseSrvIniFileMapping;
|
|
PINIFILE_MAPPING_TARGET BaseSrvMappingTargetHead;
|
|
|
|
NTSTATUS
|
|
BaseSrvSaveIniFileMapping(
|
|
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN HANDLE Key
|
|
);
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveFileNameMapping(
|
|
IN PUNICODE_STRING FileName,
|
|
OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
|
|
);
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveAppNameMapping(
|
|
IN OUT PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN PUNICODE_STRING ApplicationName OPTIONAL,
|
|
OUT PINIFILE_MAPPING_APPNAME *ReturnedAppNameMapping
|
|
);
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveVarNameMapping(
|
|
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN OUT PINIFILE_MAPPING_APPNAME AppNameMapping,
|
|
IN PUNICODE_STRING VariableName OPTIONAL,
|
|
IN PWSTR RegistryPath,
|
|
OUT PINIFILE_MAPPING_VARNAME *ReturnedVarNameMapping
|
|
);
|
|
|
|
PINIFILE_MAPPING_TARGET
|
|
BaseSrvSaveMappingTarget(
|
|
IN PWSTR RegistryPath,
|
|
OUT PULONG MappingFlags
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
BaseSrvInitializeIniFileMappings(
|
|
PBASE_STATIC_SERVER_DATA StaticServerData
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE IniFileMappingRoot;
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping, *pp;
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping;
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping;
|
|
UNICODE_STRING KeyName;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
WCHAR Buffer[ 512 ];
|
|
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
|
PKEY_BASIC_INFORMATION KeyInformation;
|
|
ULONG ResultLength;
|
|
HANDLE SubKeyHandle;
|
|
ULONG SubKeyIndex;
|
|
UNICODE_STRING ValueName;
|
|
UNICODE_STRING SubKeyName;
|
|
UNICODE_STRING WinIniFileName;
|
|
UNICODE_STRING NullString;
|
|
|
|
RtlInitUnicodeString( &WinIniFileName, L"win.ini" );
|
|
RtlInitUnicodeString( &NullString, NULL );
|
|
|
|
BaseSrvIniFileMapping = RtlAllocateHeap( BaseSrvSharedHeap,
|
|
MAKE_SHARED_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
|
|
sizeof( *BaseSrvIniFileMapping )
|
|
);
|
|
if (BaseSrvIniFileMapping == NULL) {
|
|
KdPrint(( "BASESRV: Unable to allocate memory in shared heap for IniFileMapping\n" ));
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
StaticServerData->IniFileMapping = BaseSrvIniFileMapping;
|
|
|
|
RtlInitUnicodeString( &KeyName,
|
|
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping"
|
|
);
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenKey( &IniFileMappingRoot,
|
|
GENERIC_READ,
|
|
&ObjectAttributes
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: Unable to open %wZ key - Status == %0x\n", &KeyName, Status ));
|
|
return Status;
|
|
}
|
|
|
|
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
|
|
RtlInitUnicodeString( &ValueName, NULL );
|
|
Status = NtQueryValueKey( IniFileMappingRoot,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
KeyValueInformation,
|
|
sizeof( Buffer ),
|
|
&ResultLength
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
if (BaseSrvSaveFileNameMapping( &NullString, &BaseSrvIniFileMapping->DefaultFileNameMapping )) {
|
|
if (BaseSrvSaveAppNameMapping( BaseSrvIniFileMapping->DefaultFileNameMapping, &NullString, &AppNameMapping )) {
|
|
if (BaseSrvSaveVarNameMapping( BaseSrvIniFileMapping->DefaultFileNameMapping,
|
|
AppNameMapping,
|
|
&NullString,
|
|
(PWSTR)(KeyValueInformation->Data),
|
|
&VarNameMapping
|
|
)
|
|
) {
|
|
VarNameMapping->MappingFlags |= INIFILE_MAPPING_APPEND_BASE_NAME |
|
|
INIFILE_MAPPING_APPEND_APPLICATION_NAME;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Enumerate node's children and load mappings for each one
|
|
//
|
|
|
|
pp = &BaseSrvIniFileMapping->FileNames;
|
|
*pp = NULL;
|
|
KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
|
|
for (SubKeyIndex = 0; TRUE; SubKeyIndex++) {
|
|
Status = NtEnumerateKey( IniFileMappingRoot,
|
|
SubKeyIndex,
|
|
KeyBasicInformation,
|
|
KeyInformation,
|
|
sizeof( Buffer ),
|
|
&ResultLength
|
|
);
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES) {
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
else
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: NtEnumerateKey failed - Status == %08lx\n", Status ));
|
|
break;
|
|
}
|
|
|
|
SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]);
|
|
SubKeyName.Length = (USHORT)KeyInformation->NameLength;
|
|
SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&SubKeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
IniFileMappingRoot,
|
|
NULL
|
|
);
|
|
|
|
Status = NtOpenKey( &SubKeyHandle,
|
|
GENERIC_READ,
|
|
&ObjectAttributes
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
if (!BaseSrvSaveFileNameMapping( &SubKeyName, &FileNameMapping )) {
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
else {
|
|
Status = BaseSrvSaveIniFileMapping( FileNameMapping, SubKeyHandle );
|
|
if (NT_SUCCESS( Status )) {
|
|
if (RtlEqualUnicodeString( &FileNameMapping->Name, &WinIniFileName, TRUE )) {
|
|
BaseSrvIniFileMapping->WinIniFileMapping = FileNameMapping;
|
|
}
|
|
|
|
*pp = FileNameMapping;
|
|
pp = &FileNameMapping->Next;
|
|
}
|
|
else {
|
|
KdPrint(( "BASESRV: Unable to load mappings for %wZ - Status == %x\n",
|
|
&FileNameMapping->Name, Status
|
|
));
|
|
RtlFreeHeap( BaseSrvSharedHeap, 0, FileNameMapping );
|
|
FileNameMapping = NULL;
|
|
}
|
|
}
|
|
NtClose( SubKeyHandle );
|
|
}
|
|
}
|
|
|
|
NtClose( IniFileMappingRoot );
|
|
|
|
//
|
|
// NT64: this function used to fall off the end without explicitly returning
|
|
// a value. from examining the object code generated, the returned
|
|
// value was typically the result of NtClose(), e.g. STATUS_SUCCESS.
|
|
//
|
|
// In order to get the compiler to stop complaining *and* to avoid
|
|
// changing existing functionality, I've made this return value
|
|
// explicit. However it is almost certainly the case that the
|
|
// intention was to return the value of Status.
|
|
//
|
|
// At any rate this should be reviewed by someone more familiar
|
|
// with the code.
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
BaseSrvSaveIniFileMapping(
|
|
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN HANDLE Key
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
WCHAR Buffer[ 512 ];
|
|
PKEY_BASIC_INFORMATION KeyInformation;
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping;
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping;
|
|
HANDLE SubKeyHandle;
|
|
ULONG SubKeyIndex;
|
|
UNICODE_STRING ValueName;
|
|
UNICODE_STRING SubKeyName;
|
|
UNICODE_STRING NullString;
|
|
ULONG ResultLength;
|
|
ULONG ValueIndex;
|
|
|
|
RtlInitUnicodeString( &NullString, NULL );
|
|
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
|
|
for (ValueIndex = 0; TRUE; ValueIndex++) {
|
|
Status = NtEnumerateValueKey( Key,
|
|
ValueIndex,
|
|
KeyValueFullInformation,
|
|
KeyValueInformation,
|
|
sizeof( Buffer ),
|
|
&ResultLength
|
|
);
|
|
if (Status == STATUS_NO_MORE_ENTRIES) {
|
|
break;
|
|
}
|
|
else
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: NtEnumerateValueKey failed - Status == %08lx\n", Status ));
|
|
break;
|
|
}
|
|
|
|
ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]);
|
|
ValueName.Length = (USHORT)KeyValueInformation->NameLength;
|
|
ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
|
|
if (KeyValueInformation->Type != REG_SZ) {
|
|
KdPrint(( "BASESRV: Ignoring %wZ mapping, invalid type == %u\n",
|
|
&ValueName, KeyValueInformation->Type
|
|
));
|
|
}
|
|
else
|
|
if (BaseSrvSaveAppNameMapping( FileNameMapping, &ValueName, &AppNameMapping )) {
|
|
if (BaseSrvSaveVarNameMapping( FileNameMapping,
|
|
AppNameMapping,
|
|
&NullString,
|
|
(PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset),
|
|
&VarNameMapping
|
|
)
|
|
) {
|
|
if (ValueName.Length == 0) {
|
|
VarNameMapping->MappingFlags |= INIFILE_MAPPING_APPEND_APPLICATION_NAME;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enumerate node's children and apply ourselves to each one
|
|
//
|
|
|
|
KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
|
|
for (SubKeyIndex = 0; TRUE; SubKeyIndex++) {
|
|
Status = NtEnumerateKey( Key,
|
|
SubKeyIndex,
|
|
KeyBasicInformation,
|
|
KeyInformation,
|
|
sizeof( Buffer ),
|
|
&ResultLength
|
|
);
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES) {
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
else
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: NtEnumerateKey failed - Status == %08lx\n", Status ));
|
|
break;
|
|
}
|
|
|
|
SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]);
|
|
SubKeyName.Length = (USHORT)KeyInformation->NameLength;
|
|
SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&SubKeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
Key,
|
|
NULL
|
|
);
|
|
|
|
Status = NtOpenKey( &SubKeyHandle,
|
|
GENERIC_READ,
|
|
&ObjectAttributes
|
|
);
|
|
if (NT_SUCCESS( Status ) &&
|
|
BaseSrvSaveAppNameMapping( FileNameMapping, &SubKeyName, &AppNameMapping )
|
|
) {
|
|
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
|
|
for (ValueIndex = 0; AppNameMapping != NULL; ValueIndex++) {
|
|
Status = NtEnumerateValueKey( SubKeyHandle,
|
|
ValueIndex,
|
|
KeyValueFullInformation,
|
|
KeyValueInformation,
|
|
sizeof( Buffer ),
|
|
&ResultLength
|
|
);
|
|
if (Status == STATUS_NO_MORE_ENTRIES) {
|
|
break;
|
|
}
|
|
else
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: NtEnumerateValueKey failed - Status == %08lx\n", Status ));
|
|
break;
|
|
}
|
|
|
|
ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]);
|
|
ValueName.Length = (USHORT)KeyValueInformation->NameLength;
|
|
ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
|
|
if (KeyValueInformation->Type != REG_SZ) {
|
|
KdPrint(( "BASESRV: Ignoring %wZ mapping, invalid type == %u\n",
|
|
&ValueName, KeyValueInformation->Type
|
|
));
|
|
}
|
|
else {
|
|
BaseSrvSaveVarNameMapping( FileNameMapping,
|
|
AppNameMapping,
|
|
&ValueName,
|
|
(PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset),
|
|
&VarNameMapping
|
|
);
|
|
}
|
|
}
|
|
|
|
NtClose( SubKeyHandle );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveFileNameMapping(
|
|
IN PUNICODE_STRING FileName,
|
|
OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
|
|
)
|
|
{
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping;
|
|
|
|
FileNameMapping = RtlAllocateHeap( BaseSrvSharedHeap,
|
|
MAKE_SHARED_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
|
|
sizeof( *FileNameMapping ) +
|
|
FileName->MaximumLength
|
|
);
|
|
if (FileNameMapping == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (FileName->Length != 0) {
|
|
FileNameMapping->Name.Buffer = (PWSTR)(FileNameMapping + 1);
|
|
FileNameMapping->Name.MaximumLength = FileName->MaximumLength;
|
|
RtlCopyUnicodeString( &FileNameMapping->Name, FileName );
|
|
}
|
|
|
|
*ReturnedFileNameMapping = FileNameMapping;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveAppNameMapping(
|
|
IN OUT PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN PUNICODE_STRING ApplicationName,
|
|
OUT PINIFILE_MAPPING_APPNAME *ReturnedAppNameMapping
|
|
)
|
|
{
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping, *pp;
|
|
|
|
if (ApplicationName->Length != 0) {
|
|
pp = &FileNameMapping->ApplicationNames;
|
|
while (AppNameMapping = *pp) {
|
|
if (RtlEqualUnicodeString( ApplicationName, &AppNameMapping->Name, TRUE )) {
|
|
break;
|
|
}
|
|
|
|
pp = &AppNameMapping->Next;
|
|
}
|
|
}
|
|
else {
|
|
pp = &FileNameMapping->DefaultAppNameMapping;
|
|
AppNameMapping = *pp;
|
|
}
|
|
|
|
if (AppNameMapping != NULL) {
|
|
KdPrint(( "BASESRV: Duplicate application name mapping [%ws] %ws\n",
|
|
&FileNameMapping->Name,
|
|
&AppNameMapping->Name
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
AppNameMapping = RtlAllocateHeap( BaseSrvSharedHeap,
|
|
MAKE_SHARED_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
|
|
sizeof( *AppNameMapping ) +
|
|
ApplicationName->MaximumLength
|
|
);
|
|
if (AppNameMapping == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (ApplicationName->Length != 0) {
|
|
AppNameMapping->Name.Buffer = (PWSTR)(AppNameMapping + 1);
|
|
AppNameMapping->Name.MaximumLength = ApplicationName->MaximumLength;
|
|
RtlCopyUnicodeString( &AppNameMapping->Name, ApplicationName );
|
|
}
|
|
|
|
*pp = AppNameMapping;
|
|
*ReturnedAppNameMapping = AppNameMapping;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvSaveVarNameMapping(
|
|
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
|
|
IN OUT PINIFILE_MAPPING_APPNAME AppNameMapping,
|
|
IN PUNICODE_STRING VariableName,
|
|
IN PWSTR RegistryPath,
|
|
OUT PINIFILE_MAPPING_VARNAME *ReturnedVarNameMapping
|
|
)
|
|
{
|
|
PINIFILE_MAPPING_TARGET MappingTarget;
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping, *pp;
|
|
ULONG MappingFlags;
|
|
|
|
if (VariableName->Length != 0) {
|
|
pp = &AppNameMapping->VariableNames;
|
|
while (VarNameMapping = *pp) {
|
|
if (RtlEqualUnicodeString( VariableName, &VarNameMapping->Name, TRUE )) {
|
|
break;
|
|
}
|
|
|
|
pp = &VarNameMapping->Next;
|
|
}
|
|
}
|
|
else {
|
|
pp = &AppNameMapping->DefaultVarNameMapping;
|
|
VarNameMapping = *pp;
|
|
}
|
|
|
|
if (VarNameMapping != NULL) {
|
|
KdPrint(( "BASESRV: Duplicate variable name mapping [%ws] %ws . %ws\n",
|
|
&FileNameMapping->Name,
|
|
&AppNameMapping->Name,
|
|
&VarNameMapping->Name
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
MappingTarget = BaseSrvSaveMappingTarget( RegistryPath, &MappingFlags );
|
|
if (MappingTarget == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
VarNameMapping = RtlAllocateHeap( BaseSrvSharedHeap,
|
|
MAKE_SHARED_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
|
|
sizeof( *VarNameMapping ) +
|
|
VariableName->MaximumLength
|
|
);
|
|
if (VarNameMapping == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
VarNameMapping->MappingFlags = MappingFlags;
|
|
VarNameMapping->MappingTarget = MappingTarget;
|
|
if (VariableName->Length != 0) {
|
|
VarNameMapping->Name.Buffer = (PWSTR)(VarNameMapping + 1);
|
|
VarNameMapping->Name.MaximumLength = VariableName->MaximumLength;
|
|
RtlCopyUnicodeString( &VarNameMapping->Name, VariableName );
|
|
}
|
|
|
|
*pp = VarNameMapping;
|
|
*ReturnedVarNameMapping = VarNameMapping;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PINIFILE_MAPPING_TARGET
|
|
BaseSrvSaveMappingTarget(
|
|
IN PWSTR RegistryPath,
|
|
OUT PULONG MappingFlags
|
|
)
|
|
{
|
|
BOOLEAN RelativePath;
|
|
UNICODE_STRING RegistryPathString;
|
|
PWSTR SaveRegistryPath;
|
|
PINIFILE_MAPPING_TARGET MappingTarget, *pp;
|
|
ULONG Flags;
|
|
|
|
Flags = 0;
|
|
SaveRegistryPath = RegistryPath;
|
|
while (TRUE) {
|
|
if (*RegistryPath == L'!') {
|
|
Flags |= INIFILE_MAPPING_WRITE_TO_INIFILE_TOO;
|
|
RegistryPath += 1;
|
|
}
|
|
else
|
|
if (*RegistryPath == L'#') {
|
|
Flags |= INIFILE_MAPPING_INIT_FROM_INIFILE;
|
|
RegistryPath += 1;
|
|
}
|
|
else
|
|
if (*RegistryPath == L'@') {
|
|
Flags |= INIFILE_MAPPING_READ_FROM_REGISTRY_ONLY;
|
|
RegistryPath += 1;
|
|
}
|
|
else
|
|
if (!_wcsnicmp( RegistryPath, L"USR:", 4 )) {
|
|
Flags |= INIFILE_MAPPING_USER_RELATIVE;
|
|
RegistryPath += 4;
|
|
break;
|
|
}
|
|
else
|
|
if (!_wcsnicmp( RegistryPath, L"SYS:", 4 )) {
|
|
Flags |= INIFILE_MAPPING_SOFTWARE_RELATIVE;
|
|
RegistryPath += 4;
|
|
break;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Flags & (INIFILE_MAPPING_USER_RELATIVE | INIFILE_MAPPING_SOFTWARE_RELATIVE)) {
|
|
RelativePath = TRUE;
|
|
}
|
|
else {
|
|
RelativePath = FALSE;
|
|
}
|
|
|
|
if ((RelativePath && *RegistryPath != OBJ_NAME_PATH_SEPARATOR) ||
|
|
(!RelativePath && *RegistryPath == OBJ_NAME_PATH_SEPARATOR)
|
|
) {
|
|
RtlInitUnicodeString( &RegistryPathString, RegistryPath );
|
|
}
|
|
else
|
|
if (!RelativePath && *RegistryPath == UNICODE_NULL) {
|
|
RtlInitUnicodeString( &RegistryPathString, NULL );
|
|
}
|
|
else {
|
|
KdPrint(( "BASESRV: Ignoring invalid mapping target - %ws\n",
|
|
SaveRegistryPath
|
|
));
|
|
return NULL;
|
|
}
|
|
|
|
pp = &BaseSrvMappingTargetHead;
|
|
while (MappingTarget = *pp) {
|
|
if (RtlEqualUnicodeString( &RegistryPathString, &MappingTarget->RegistryPath, TRUE )) {
|
|
*MappingFlags = Flags;
|
|
return MappingTarget;
|
|
}
|
|
|
|
pp = &MappingTarget->Next;
|
|
}
|
|
|
|
MappingTarget = RtlAllocateHeap( BaseSrvSharedHeap,
|
|
MAKE_SHARED_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
|
|
sizeof( *MappingTarget ) +
|
|
RegistryPathString.MaximumLength
|
|
);
|
|
if (MappingTarget != NULL) {
|
|
*MappingFlags = Flags;
|
|
*pp = MappingTarget;
|
|
if (RegistryPathString.Length != 0) {
|
|
MappingTarget->RegistryPath.Buffer = (PWSTR)(MappingTarget + 1);
|
|
MappingTarget->RegistryPath.Length = 0;
|
|
MappingTarget->RegistryPath.MaximumLength = RegistryPathString.MaximumLength;
|
|
RtlCopyUnicodeString( &MappingTarget->RegistryPath, &RegistryPathString );
|
|
}
|
|
}
|
|
else {
|
|
KdPrint(( "BASESRV: Unable to allocate memory for mapping target - %ws\n", RegistryPath ));
|
|
}
|
|
|
|
return MappingTarget;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvEqualVarNameMappings(
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping1,
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping2
|
|
)
|
|
{
|
|
if (VarNameMapping1 == NULL) {
|
|
if (VarNameMapping2 == NULL) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
if (VarNameMapping2 == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (RtlEqualUnicodeString( &VarNameMapping1->Name,
|
|
&VarNameMapping2->Name,
|
|
TRUE
|
|
) &&
|
|
VarNameMapping1->MappingFlags == VarNameMapping2->MappingFlags &&
|
|
VarNameMapping1->MappingTarget == VarNameMapping2->MappingTarget &&
|
|
BaseSrvEqualVarNameMappings( VarNameMapping1->Next,
|
|
VarNameMapping2->Next
|
|
)
|
|
) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvEqualAppNameMappings(
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping1,
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping2
|
|
)
|
|
{
|
|
if (AppNameMapping1 == NULL) {
|
|
if (AppNameMapping2 == NULL) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
if (AppNameMapping2 == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (RtlEqualUnicodeString( &AppNameMapping1->Name,
|
|
&AppNameMapping2->Name,
|
|
TRUE
|
|
) &&
|
|
BaseSrvEqualVarNameMappings( AppNameMapping1->VariableNames,
|
|
AppNameMapping2->VariableNames
|
|
) &&
|
|
BaseSrvEqualVarNameMappings( AppNameMapping1->DefaultVarNameMapping,
|
|
AppNameMapping2->DefaultVarNameMapping
|
|
) &&
|
|
BaseSrvEqualAppNameMappings( AppNameMapping1->Next,
|
|
AppNameMapping2->Next
|
|
)
|
|
) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
BaseSrvEqualFileMappings(
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping1,
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping2
|
|
)
|
|
{
|
|
if (RtlEqualUnicodeString( &FileNameMapping1->Name,
|
|
&FileNameMapping2->Name,
|
|
TRUE
|
|
) &&
|
|
BaseSrvEqualAppNameMappings( FileNameMapping1->ApplicationNames,
|
|
FileNameMapping2->ApplicationNames
|
|
) &&
|
|
BaseSrvEqualAppNameMappings( FileNameMapping1->DefaultAppNameMapping,
|
|
FileNameMapping2->DefaultAppNameMapping
|
|
)
|
|
) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
BaseSrvFreeVarNameMapping(
|
|
PINIFILE_MAPPING_VARNAME VarNameMapping
|
|
)
|
|
{
|
|
if (VarNameMapping != NULL) {
|
|
BaseSrvFreeVarNameMapping( VarNameMapping->Next );
|
|
RtlFreeHeap( BaseSrvSharedHeap, HEAP_NO_SERIALIZE, VarNameMapping );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
BaseSrvFreeAppNameMapping(
|
|
PINIFILE_MAPPING_APPNAME AppNameMapping
|
|
)
|
|
{
|
|
if (AppNameMapping != NULL) {
|
|
BaseSrvFreeVarNameMapping( AppNameMapping->VariableNames );
|
|
BaseSrvFreeVarNameMapping( AppNameMapping->DefaultVarNameMapping );
|
|
BaseSrvFreeAppNameMapping( AppNameMapping->Next );
|
|
RtlFreeHeap( BaseSrvSharedHeap, HEAP_NO_SERIALIZE, AppNameMapping );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
BaseSrvFreeFileMapping(
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping
|
|
)
|
|
{
|
|
if (FileNameMapping != NULL) {
|
|
BaseSrvFreeAppNameMapping( FileNameMapping->ApplicationNames );
|
|
BaseSrvFreeAppNameMapping( FileNameMapping->DefaultAppNameMapping );
|
|
RtlFreeHeap( BaseSrvSharedHeap, HEAP_NO_SERIALIZE, FileNameMapping );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
ULONG
|
|
BaseSrvRefreshIniFileMapping(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_REFRESHINIFILEMAPPING_MSG a = (PBASE_REFRESHINIFILEMAPPING_MSG)&m->u.ApiMessageData;
|
|
NTSTATUS Status;
|
|
HANDLE IniFileMappingRoot;
|
|
PINIFILE_MAPPING_FILENAME FileNameMapping, FileNameMapping1, *pp;
|
|
UNICODE_STRING KeyName;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE SubKeyHandle;
|
|
UNICODE_STRING WinIniFileName;
|
|
UNICODE_STRING NullString;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
if (!CsrValidateMessageBuffer(m, &a->IniFileName.Buffer, a->IniFileName.Length, sizeof(BYTE))) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RtlInitUnicodeString( &WinIniFileName, L"win.ini" );
|
|
RtlInitUnicodeString( &NullString, NULL );
|
|
|
|
RtlInitUnicodeString( &KeyName,
|
|
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping"
|
|
);
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenKey( &IniFileMappingRoot,
|
|
GENERIC_READ,
|
|
&ObjectAttributes
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
KdPrint(( "BASESRV: Unable to open %wZ key - Status == %0x\n", &KeyName, Status ));
|
|
return (ULONG)Status;
|
|
}
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&a->IniFileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
IniFileMappingRoot,
|
|
NULL
|
|
);
|
|
|
|
Status = NtOpenKey( &SubKeyHandle,
|
|
GENERIC_READ,
|
|
&ObjectAttributes
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
if (!BaseSrvSaveFileNameMapping( &a->IniFileName, &FileNameMapping )) {
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
else {
|
|
Status = BaseSrvSaveIniFileMapping( FileNameMapping, SubKeyHandle );
|
|
if (NT_SUCCESS( Status )) {
|
|
RtlLockHeap( BaseSrvSharedHeap );
|
|
try {
|
|
pp = &BaseSrvIniFileMapping->FileNames;
|
|
while (FileNameMapping1 = *pp) {
|
|
if (RtlEqualUnicodeString( &FileNameMapping1->Name, &a->IniFileName, TRUE )) {
|
|
if (BaseSrvEqualFileMappings( FileNameMapping, FileNameMapping1 )) {
|
|
//
|
|
// If old and new mappings the same, free up new and return
|
|
//
|
|
|
|
BaseSrvFreeFileMapping( FileNameMapping );
|
|
FileNameMapping = NULL;
|
|
}
|
|
else {
|
|
//
|
|
// Remove found mapping from list
|
|
//
|
|
|
|
*pp = FileNameMapping1->Next;
|
|
FileNameMapping1->Next = NULL;
|
|
}
|
|
break;
|
|
}
|
|
else {
|
|
pp = &FileNameMapping1->Next;
|
|
}
|
|
}
|
|
|
|
if (FileNameMapping != NULL) {
|
|
//
|
|
// Insert new (or different) mapping into list (at end if not found)
|
|
//
|
|
|
|
FileNameMapping->Next = *pp;
|
|
*pp = FileNameMapping;
|
|
}
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
RtlUnlockHeap( BaseSrvSharedHeap );
|
|
|
|
if (NT_SUCCESS( Status ) && FileNameMapping != NULL) {
|
|
if (RtlEqualUnicodeString( &FileNameMapping->Name, &WinIniFileName, TRUE )) {
|
|
BaseSrvIniFileMapping->WinIniFileMapping = FileNameMapping;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
KdPrint(( "BASESRV: Unable to load mappings for %wZ - Status == %x\n",
|
|
&FileNameMapping->Name, Status
|
|
));
|
|
RtlFreeHeap( BaseSrvSharedHeap, 0, FileNameMapping );
|
|
}
|
|
}
|
|
|
|
NtClose( SubKeyHandle );
|
|
}
|
|
|
|
NtClose( IniFileMappingRoot );
|
|
|
|
return (ULONG)Status;
|
|
ReplyStatus; // get rid of unreferenced parameter warning message
|
|
}
|
|
|
|
|
|
NTSTATUS NtCreateAdminsSid( PSID *ppAdminSid )
|
|
{
|
|
NTSTATUS Status;
|
|
PSID pSid;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
ASSERT(ppAdminSid != NULL);
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&SidAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*ppAdminSid = pSid;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS NtCreateSystemSid( PSID *ppSystemSid )
|
|
{
|
|
NTSTATUS Status;
|
|
PSID pSid;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
ASSERT(ppSystemSid != NULL);
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&SidAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*ppSystemSid = pSid;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
BOOL IsCallerAdminsOrSystem( VOID )
|
|
{
|
|
|
|
HANDLE ClientToken;
|
|
ULONG i;
|
|
ULONG RequiredLength=0;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PSID pAdminsSID=0;
|
|
PSID pSystemSID=0;
|
|
BOOL callerIsAdminsOrSystem = FALSE;
|
|
|
|
Status = NtCreateAdminsSid( &pAdminsSID );
|
|
if (!NT_SUCCESS(Status))
|
|
goto Error;
|
|
|
|
Status = NtCreateSystemSid( &pSystemSID );
|
|
if (!NT_SUCCESS(Status))
|
|
goto Error;
|
|
|
|
Status = NtOpenThreadToken(
|
|
NtCurrentThread(),
|
|
TOKEN_QUERY,
|
|
TRUE, // use the impersonation context
|
|
&ClientToken
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
goto Error;
|
|
|
|
// call it once to get the size of buffer we need from RequiredLength
|
|
Status = NtQueryInformationToken(
|
|
ClientToken,
|
|
TokenGroups,
|
|
NULL,
|
|
0,
|
|
&RequiredLength );
|
|
|
|
if (RequiredLength > 0)
|
|
{
|
|
PTOKEN_GROUPS TokenGroupInformation = NULL;
|
|
|
|
//
|
|
// Allocate enough memory
|
|
//
|
|
TokenGroupInformation = (PTOKEN_GROUPS) RtlAllocateHeap ( RtlProcessHeap(),
|
|
MAKE_TAG( TMP_TAG ), // what tag to use ???
|
|
RequiredLength );
|
|
|
|
if (NULL==TokenGroupInformation)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Query the Token for the group memberships
|
|
//
|
|
|
|
Status = NtQueryInformationToken(
|
|
ClientToken,
|
|
TokenGroups,
|
|
TokenGroupInformation,
|
|
RequiredLength,
|
|
&RequiredLength
|
|
);
|
|
|
|
for (i=0;i<TokenGroupInformation->GroupCount;i++)
|
|
{
|
|
if(RtlEqualSid(TokenGroupInformation->Groups[i].Sid, pAdminsSID ))
|
|
{
|
|
callerIsAdminsOrSystem= TRUE;
|
|
break;
|
|
}
|
|
else if (RtlEqualSid(TokenGroupInformation->Groups[i].Sid, pSystemSID ))
|
|
{
|
|
callerIsAdminsOrSystem= TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap( RtlProcessHeap(), 0, TokenGroupInformation );
|
|
|
|
}
|
|
|
|
Error:
|
|
if (pAdminsSID)
|
|
{
|
|
RtlFreeSid( pAdminsSID );
|
|
}
|
|
|
|
if (pSystemSID)
|
|
{
|
|
RtlFreeSid( pSystemSID );
|
|
}
|
|
|
|
return callerIsAdminsOrSystem;
|
|
|
|
}
|
|
|
|
|
|
ULONG
|
|
BaseSrvSetTermsrvAppInstallMode(IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOL RevertToSelfNeeded;
|
|
|
|
PBASE_SET_TERMSRVAPPINSTALLMODE b = (PBASE_SET_TERMSRVAPPINSTALLMODE)&m->u.ApiMessageData;
|
|
|
|
try {
|
|
|
|
RevertToSelfNeeded = CsrImpersonateClient( NULL ); // This stacks client contexts
|
|
|
|
if( RevertToSelfNeeded == FALSE ) {
|
|
Status = STATUS_BAD_IMPERSONATION_LEVEL;
|
|
leave;
|
|
}
|
|
else
|
|
{
|
|
if ( IsCallerAdminsOrSystem () )
|
|
{
|
|
if ( b->bState )
|
|
BaseSrvpStaticServerData->fTermsrvAppInstallMode = TRUE;
|
|
else
|
|
BaseSrvpStaticServerData->fTermsrvAppInstallMode = FALSE;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if ( RevertToSelfNeeded )
|
|
{
|
|
CsrRevertToSelf();
|
|
}
|
|
}
|
|
|
|
|
|
return( Status );
|
|
}
|