windows-nt/Source/XPSP1/NT/base/tools/instaler/handler.c
2020-09-26 16:20:57 +08:00

2387 lines
78 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
handler.c
Abstract:
This module contains the individual API handler routines for the INSTALER program
Author:
Steve Wood (stevewo) 10-Aug-1994
Revision History:
--*/
#include "instaler.h"
#include <ntstatus.dbg>
BOOLEAN
HandleBreakpoint(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PBREAKPOINT_INFO Breakpoint
)
{
BOOLEAN Result;
API_SAVED_PARAMETERS SavedParameters;
UCHAR ApiIndex;
PBREAKPOINT_INFO ReturnBreakpoint;
Result = FALSE;
ApiIndex = Breakpoint->ApiIndex;
if (ApiInfo[ ApiIndex ].ModuleIndex < Thread->ModuleIndexCurrentlyIn) {
return TRUE;
}
DbgEvent( DBGEVENT, ( "Processing Breakpoint at %ws!%s\n",
Breakpoint->ModuleName,
Breakpoint->ProcedureName
)
);
if (!Breakpoint->SavedParametersValid) {
memset( &SavedParameters, 0, sizeof( SavedParameters ) );
Result = TRUE;
if (ExtractProcedureParameters( Process,
Thread,
(PVOID)&SavedParameters.ReturnAddress,
ApiInfo[ ApiIndex ].SizeOfParameters,
(PULONG)&SavedParameters.InputParameters
)
) {
if (ApiInfo[ ApiIndex ].EntryPointHandler == NULL ||
(ApiInfo[ ApiIndex ].EntryPointHandler)( Process,
Thread,
&SavedParameters
)
) {
if (SavedParameters.ReturnAddress == NULL) {
Result = FALSE;
}
else
if (CreateBreakpoint( SavedParameters.ReturnAddress,
Process,
Thread, // thread specific
ApiIndex,
&SavedParameters,
&ReturnBreakpoint
)
) {
ReturnBreakpoint->ModuleName = L"Return from";
ReturnBreakpoint->ProcedureName = Breakpoint->ProcedureName;
Thread->ModuleIndexCurrentlyIn = ApiInfo[ ApiIndex ].ModuleIndex;
SuspendAllButThisThread( Process, Thread );
}
}
}
#if DBG
TrimTemporaryBuffer();
#endif
}
else {
if (UndoReturnAddressBreakpoint( Process, Thread ) &&
ExtractProcedureReturnValue( Process,
Thread,
&Breakpoint->SavedParameters.ReturnValue,
ApiInfo[ ApiIndex ].SizeOfReturnValue
)
) {
Breakpoint->SavedParameters.ReturnValueValid = TRUE;
if (ApiInfo[ ApiIndex ].EntryPointHandler != NULL) {
(ApiInfo[ ApiIndex ].EntryPointHandler)( Process,
Thread,
&Breakpoint->SavedParameters
);
}
}
Thread->ModuleIndexCurrentlyIn = 0;
FreeSavedCallState( &Breakpoint->SavedParameters.SavedCallState );
DestroyBreakpoint( Breakpoint->Address, Process, Thread );
ResumeAllButThisThread( Process, Thread );
#if DBG
TrimTemporaryBuffer();
#endif
Result = FALSE;
}
return Result;
}
BOOLEAN
CreateSavedCallState(
PPROCESS_INFO Process,
PAPI_SAVED_CALL_STATE SavedCallState,
API_ACTION Action,
ULONG Type,
PWSTR FullName,
...
)
{
va_list arglist;
va_start( arglist, FullName );
SavedCallState->Action = Action;
SavedCallState->Type = Type;
SavedCallState->FullName = FullName;
switch (Action) {
case OpenPath:
SavedCallState->PathOpen.InheritHandle = va_arg( arglist, BOOLEAN );
SavedCallState->PathOpen.WriteAccessRequested = va_arg( arglist, BOOLEAN );
SavedCallState->PathOpen.ResultHandleAddress = va_arg( arglist, PHANDLE );
break;
case RenamePath:
SavedCallState->PathRename.NewName = va_arg( arglist, PWSTR );
SavedCallState->PathRename.ReplaceIfExists = va_arg( arglist, BOOLEAN );
break;
case DeletePath:
case QueryPath:
case SetValue:
case DeleteValue:
break;
case WriteIniValue:
SavedCallState->SetIniValue.SectionName = va_arg( arglist, PWSTR );
SavedCallState->SetIniValue.VariableName = va_arg( arglist, PWSTR );
SavedCallState->SetIniValue.VariableValue = va_arg( arglist, PWSTR );
break;
case WriteIniSection:
SavedCallState->SetIniSection.SectionName = va_arg( arglist, PWSTR );
SavedCallState->SetIniSection.SectionValue = va_arg( arglist, PWSTR );
break;
default:
return FALSE;
}
va_end( arglist );
return TRUE;
}
VOID
FreeSavedCallState(
PAPI_SAVED_CALL_STATE CallState
)
{
switch (CallState->Action) {
case WriteIniValue:
FreeMem( &CallState->SetIniValue.VariableValue );
break;
case WriteIniSection:
FreeMem( &CallState->SetIniSection.SectionValue );
break;
}
return;
}
BOOLEAN
CaptureObjectAttributes(
PPROCESS_INFO Process,
POBJECT_ATTRIBUTES ObjectAttributesAddress,
POBJECT_ATTRIBUTES ObjectAttributes,
PUNICODE_STRING ObjectName
)
{
if (ObjectAttributesAddress != NULL &&
ReadMemory( Process,
ObjectAttributesAddress,
ObjectAttributes,
sizeof( *ObjectAttributes ),
"object attributes"
) &&
ObjectAttributes->ObjectName != NULL &&
ReadMemory( Process,
ObjectAttributes->ObjectName,
ObjectName,
sizeof( *ObjectName ),
"object name string"
)
) {
return TRUE;
}
else {
return FALSE;
}
}
BOOLEAN
CaptureFullName(
PPROCESS_INFO Process,
ULONG Type,
HANDLE RootDirectory,
PWSTR Name,
ULONG Length,
PWSTR *ReturnedFullName
)
{
POPENHANDLE_INFO HandleInfo;
UNICODE_STRING FullName;
ULONG LengthOfName;
PWSTR s;
BOOLEAN Result;
*ReturnedFullName = NULL;
if (RootDirectory != NULL) {
HandleInfo = FindOpenHandle( Process,
RootDirectory,
Type
);
if (HandleInfo == NULL) {
//
// If handle not found then we dont care about this open
// as it is relative to a device that is not local.
//
return FALSE;
}
}
else {
HandleInfo = NULL;
}
LengthOfName = Length + sizeof( UNICODE_NULL );
if (HandleInfo != NULL) {
LengthOfName += HandleInfo->LengthOfName +
sizeof( OBJ_NAME_PATH_SEPARATOR );
}
FullName.Buffer = AllocMem( LengthOfName );
if (FullName.Buffer == NULL) {
return FALSE;
}
s = FullName.Buffer;
if (HandleInfo != NULL) {
RtlMoveMemory( s,
HandleInfo->Name,
HandleInfo->LengthOfName
);
s = &FullName.Buffer[ HandleInfo->LengthOfName / sizeof( WCHAR ) ];
if (s[-1] != OBJ_NAME_PATH_SEPARATOR) {
*s++ = OBJ_NAME_PATH_SEPARATOR;
}
}
if (!ReadMemory( Process,
Name,
s,
Length,
"object name buffer"
)
) {
FreeMem( &FullName.Buffer );
return FALSE;
}
s = &s[ Length / sizeof( WCHAR ) ];
*s = UNICODE_NULL;
FullName.Length = (PCHAR)s - (PCHAR)FullName.Buffer;
FullName.MaximumLength = (USHORT)(FullName.Length + sizeof( UNICODE_NULL ));
if (HandleInfo == NULL && Type == HANDLE_TYPE_FILE) {
Result = IsDriveLetterPath( &FullName );
}
else {
Result = TRUE;
}
*ReturnedFullName = AddName( &FullName );
FreeMem( &FullName.Buffer );
return Result;
}
BOOLEAN
CaptureOpenState(
PPROCESS_INFO Process,
PAPI_SAVED_PARAMETERS Parameters,
POBJECT_ATTRIBUTES ObjectAttributesAddress,
BOOLEAN WriteAccess,
PHANDLE ResultHandleAddress,
ULONG Type
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ObjectName;
PWSTR FullName;
BOOLEAN Result;
Result = FALSE;
if (CaptureObjectAttributes( Process,
ObjectAttributesAddress,
&ObjectAttributes,
&ObjectName
) &&
CaptureFullName( Process,
Type,
ObjectAttributes.RootDirectory,
ObjectName.Buffer,
ObjectName.Length,
&FullName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
OpenPath,
Type,
FullName,
(BOOLEAN)((ObjectAttributes.Attributes & OBJ_INHERIT) != 0),
WriteAccess,
ResultHandleAddress
)
) {
if (Type == HANDLE_TYPE_FILE) {
Result = CreateFileReference( FullName,
Parameters->SavedCallState.PathOpen.WriteAccessRequested,
(PFILE_REFERENCE *)&Parameters->SavedCallState.Reference
);
}
else {
Result = CreateKeyReference( FullName,
Parameters->SavedCallState.PathOpen.WriteAccessRequested,
(PKEY_REFERENCE *)&Parameters->SavedCallState.Reference
);
}
}
return Result;
}
BOOLEAN
CompleteOpenState(
PPROCESS_INFO Process,
PAPI_SAVED_PARAMETERS Parameters
)
{
PAPI_SAVED_CALL_STATE p = &Parameters->SavedCallState;
HANDLE Handle;
BOOLEAN CallSuccessful;
PFILE_REFERENCE FileReference;
PKEY_REFERENCE KeyReference;
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong ) &&
ReadMemory( Process,
p->PathOpen.ResultHandleAddress,
&Handle,
sizeof( Handle ),
"result handle"
) &&
AddOpenHandle( Process,
Handle,
p->Type,
p->FullName,
p->PathOpen.InheritHandle
)
) {
CallSuccessful = TRUE;
}
else {
CallSuccessful = FALSE;
}
IncrementOpenCount( p->FullName, CallSuccessful );
if (p->Type == HANDLE_TYPE_FILE) {
FileReference = (PFILE_REFERENCE)p->Reference;
CompleteFileReference( FileReference,
CallSuccessful,
FALSE,
NULL
);
}
else
if (p->Type == HANDLE_TYPE_KEY) {
KeyReference = (PKEY_REFERENCE)p->Reference;
CompleteKeyReference( (PKEY_REFERENCE)p->Reference,
CallSuccessful,
FALSE
);
}
return TRUE;
}
#if TRACE_ENABLED
ENUM_TYPE_NAMES FileAccessNames[] = {
FILE_READ_DATA, "FILE_READ_DATA",
FILE_READ_DATA, "FILE_READ_DATA",
FILE_WRITE_DATA, "FILE_WRITE_DATA",
FILE_APPEND_DATA, "FILE_APPEND_DATA",
FILE_READ_EA, "FILE_READ_EA",
FILE_WRITE_EA, "FILE_WRITE_EA",
FILE_EXECUTE, "FILE_EXECUTE",
FILE_DELETE_CHILD, "FILE_DELETE_CHILD",
FILE_READ_ATTRIBUTES, "FILE_READ_ATTRIBUTES",
FILE_WRITE_ATTRIBUTES, "FILE_WRITE_ATTRIBUTES",
DELETE, "DELETE",
READ_CONTROL, "READ_CONTROL",
WRITE_DAC, "WRITE_DAC",
WRITE_OWNER, "WRITE_OWNER",
SYNCHRONIZE, "SYNCHRONIZE",
GENERIC_READ, "GENERIC_READ",
GENERIC_WRITE, "GENERIC_WRITE",
GENERIC_EXECUTE, "GENERIC_EXECUTE",
GENERIC_ALL, "GENERIC_ALL",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES FileShareNames[] = {
FILE_SHARE_READ, "FILE_SHARE_READ",
FILE_SHARE_WRITE, "FILE_SHARE_WRITE",
FILE_SHARE_DELETE, "FILE_SHARE_DELETE",
0xFFFFFFFF, "FILE_SHARE_NONE"
};
ENUM_TYPE_NAMES FileCreateDispositionNames[] = {
FILE_SUPERSEDE, "FILE_SUPERSEDE",
FILE_OPEN, "FILE_OPEN",
FILE_CREATE, "FILE_CREATE",
FILE_OPEN_IF, "FILE_OPEN_IF",
FILE_OVERWRITE, "FILE_OVERWRITE",
FILE_OVERWRITE_IF, "FILE_OVERWRITE_IF",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES FileCreateOptionNames[] = {
FILE_DIRECTORY_FILE, "FILE_DIRECTORY_FILE",
FILE_WRITE_THROUGH, "FILE_WRITE_THROUGH",
FILE_SEQUENTIAL_ONLY, "FILE_SEQUENTIAL_ONLY",
FILE_NO_INTERMEDIATE_BUFFERING, "FILE_NO_INTERMEDIATE_BUFFERING",
FILE_SYNCHRONOUS_IO_ALERT, "FILE_SYNCHRONOUS_IO_ALERT",
FILE_SYNCHRONOUS_IO_NONALERT, "FILE_SYNCHRONOUS_IO_NONALERT",
FILE_NON_DIRECTORY_FILE, "FILE_NON_DIRECTORY_FILE",
FILE_CREATE_TREE_CONNECTION, "FILE_CREATE_TREE_CONNECTION",
FILE_COMPLETE_IF_OPLOCKED, "FILE_COMPLETE_IF_OPLOCKED",
FILE_NO_EA_KNOWLEDGE, "FILE_NO_EA_KNOWLEDGE",
FILE_RANDOM_ACCESS, "FILE_RANDOM_ACCESS",
FILE_DELETE_ON_CLOSE, "FILE_DELETE_ON_CLOSE",
FILE_OPEN_BY_FILE_ID, "FILE_OPEN_BY_FILE_ID",
FILE_OPEN_FOR_BACKUP_INTENT, "FILE_OPEN_FOR_BACKUP_INTENT",
FILE_NO_COMPRESSION, "FILE_NO_COMPRESSION",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES FileIoStatusInfoNames[] = {
FILE_SUPERSEDED, "FILE_SUPERSEDED",
FILE_OPENED, "FILE_OPENED",
FILE_CREATED, "FILE_CREATED",
FILE_OVERWRITTEN, "FILE_OVERWRITTEN",
FILE_EXISTS, "FILE_EXISTS",
FILE_DOES_NOT_EXIST, "FILE_DOES_NOT_EXIST",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES SetFileInfoClassNames[] = {
FileDirectoryInformation, "FileDirectoryInformation",
FileFullDirectoryInformation, "FileFullDirectoryInformation",
FileBothDirectoryInformation, "FileBothDirectoryInformation",
FileBasicInformation, "FileBasicInformation",
FileStandardInformation, "FileStandardInformation",
FileInternalInformation, "FileInternalInformation",
FileEaInformation, "FileEaInformation",
FileAccessInformation, "FileAccessInformation",
FileNameInformation, "FileNameInformation",
FileRenameInformation, "FileRenameInformation",
FileLinkInformation, "FileLinkInformation",
FileNamesInformation, "FileNamesInformation",
FileDispositionInformation, "FileDispositionInformation",
FilePositionInformation, "FilePositionInformation",
FileFullEaInformation, "FileFullEaInformation",
FileModeInformation, "FileModeInformation",
FileAlignmentInformation, "FileAlignmentInformation",
FileAllInformation, "FileAllInformation",
FileAllocationInformation, "FileAllocationInformation",
FileEndOfFileInformation, "FileEndOfFileInformation",
FileAlternateNameInformation, "FileAlternateNameInformation",
FileStreamInformation, "FileStreamInformation",
FilePipeInformation, "FilePipeInformation",
FilePipeLocalInformation, "FilePipeLocalInformation",
FilePipeRemoteInformation, "FilePipeRemoteInformation",
FileMailslotQueryInformation, "FileMailslotQueryInformation",
FileMailslotSetInformation, "FileMailslotSetInformation",
FileCompressionInformation, "FileCompressionInformation",
FileCompletionInformation, "FileCompletionInformation",
FileMoveClusterInformation, "FileMoveClusterInformation",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES KeyCreateOptionNames[] = {
REG_OPTION_VOLATILE, "REG_OPTION_VOLATILE",
REG_OPTION_CREATE_LINK, "REG_OPTION_CREATE_LINK",
REG_OPTION_BACKUP_RESTORE, "REG_OPTION_BACKUP_RESTORE",
0xFFFFFFFF, "%x"
};
ENUM_TYPE_NAMES KeyDispositionNames[] = {
REG_CREATED_NEW_KEY, "REG_CREATED_NEW_KEY",
REG_OPENED_EXISTING_KEY, "REG_OPENED_EXISTING_KEY",
0xFFFFFFFF, "%x"
};
#endif // TRACE_ENABLED
BOOLEAN
IsFileWriteAccessRequested(
ACCESS_MASK DesiredAccess,
ULONG CreateDisposition
)
{
if (DesiredAccess & (GENERIC_WRITE |
GENERIC_ALL |
DELETE |
FILE_WRITE_DATA |
FILE_APPEND_DATA
)
) {
return TRUE;
}
if (CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OPEN_IF) {
return TRUE;
}
return FALSE;
}
BOOLEAN
NtCreateFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PCREATEFILE_PARAMETERS p = &Parameters->InputParameters.CreateFile;
BOOLEAN Result;
if (!Parameters->ReturnValueValid) {
Result = CaptureOpenState( Process,
Parameters,
p->ObjectAttributes,
IsFileWriteAccessRequested( p->DesiredAccess, p->CreateDisposition ),
p->FileHandle,
HANDLE_TYPE_FILE
);
if (Result
// && Parameters->SavedCallState.PathOpen.WriteAccessRequested
) {
DbgEvent( CREATEEVENT, ( "NtCreateFile called:\n"
" Name: %ws\n"
" Access: %s\n"
" Share: %s\n"
" Create: %s\n"
" Options:%s\n",
Parameters->SavedCallState.FullName,
FormatEnumType( 0,
FileAccessNames,
p->DesiredAccess,
TRUE
),
FormatEnumType( 1,
FileShareNames,
p->ShareAccess,
TRUE
),
FormatEnumType( 2,
FileCreateDispositionNames,
p->CreateDisposition,
FALSE
),
FormatEnumType( 3,
FileCreateOptionNames,
p->CreateOptions,
TRUE
)
)
);
}
}
else {
Result = CompleteOpenState( Process,
Parameters
);
if (Result
// && Parameters->SavedCallState.PathOpen.WriteAccessRequested
) {
IO_STATUS_BLOCK IoStatusBlock;
ReadMemory( Process,
p->IoStatusBlock,
&IoStatusBlock,
sizeof( IoStatusBlock ),
"IoStatusBlock"
);
DbgEvent( CREATEEVENT, ( "*** Returned %s [%s %s]\n",
FormatEnumType( 0,
(PENUM_TYPE_NAMES)ntstatusSymbolicNames,
Parameters->ReturnValue.ReturnedLong,
FALSE
),
FormatEnumType( 1,
(PENUM_TYPE_NAMES)ntstatusSymbolicNames,
IoStatusBlock.Status,
FALSE
),
FormatEnumType( 2,
FileIoStatusInfoNames,
IoStatusBlock.Information,
FALSE
)
)
);
}
}
return Result;
}
BOOLEAN
NtOpenFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
POPENFILE_PARAMETERS p = &Parameters->InputParameters.OpenFile;
BOOLEAN Result;
if (!Parameters->ReturnValueValid) {
Result = CaptureOpenState( Process,
Parameters,
p->ObjectAttributes,
IsFileWriteAccessRequested( p->DesiredAccess, FILE_OPEN ),
p->FileHandle,
HANDLE_TYPE_FILE
);
if (Result
// && Parameters->SavedCallState.PathOpen.WriteAccessRequested
) {
DbgEvent( CREATEEVENT, ( "NtOpenFile called:\n"
" Name: %ws\n"
" Access: %s\n"
" Share: %s\n"
" Options:%s\n",
Parameters->SavedCallState.FullName,
FormatEnumType( 0,
FileAccessNames,
p->DesiredAccess,
TRUE
),
FormatEnumType( 1,
FileShareNames,
p->ShareAccess,
TRUE
),
FormatEnumType( 2,
FileCreateOptionNames,
p->OpenOptions,
TRUE
)
)
);
}
}
else {
Result = CompleteOpenState( Process,
Parameters
);
if (Result
// && Parameters->SavedCallState.PathOpen.WriteAccessRequested
) {
IO_STATUS_BLOCK IoStatusBlock;
ReadMemory( Process,
p->IoStatusBlock,
&IoStatusBlock,
sizeof( IoStatusBlock ),
"IoStatusBlock"
);
DbgEvent( CREATEEVENT, ( "*** Returned %s [%s %s]\n",
FormatEnumType( 0,
(PENUM_TYPE_NAMES)ntstatusSymbolicNames,
Parameters->ReturnValue.ReturnedLong,
FALSE
),
FormatEnumType( 1,
(PENUM_TYPE_NAMES)ntstatusSymbolicNames,
IoStatusBlock.Status,
FALSE
),
FormatEnumType( 2,
FileIoStatusInfoNames,
IoStatusBlock.Information,
FALSE
)
)
);
}
}
return Result;
}
BOOLEAN
NtDeleteFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PDELETEFILE_PARAMETERS p = &Parameters->InputParameters.DeleteFile;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ObjectName;
PWSTR FullName;
BOOLEAN Result, CallSuccessful;
PFILE_REFERENCE FileReference;
if (!Parameters->ReturnValueValid) {
if (CaptureObjectAttributes( Process,
p->ObjectAttributes,
&ObjectAttributes,
&ObjectName
) &&
CaptureFullName( Process,
HANDLE_TYPE_FILE,
ObjectAttributes.RootDirectory,
ObjectName.Buffer,
ObjectName.Length,
&FullName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
DeletePath,
HANDLE_TYPE_FILE,
FullName
)
) {
Result = CreateFileReference( FullName,
TRUE,
(PFILE_REFERENCE *)&Parameters->SavedCallState.Reference
);
}
else {
Result = FALSE;
}
return Result;
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
CallSuccessful = TRUE;
}
else {
CallSuccessful = FALSE;
}
FileReference = (PFILE_REFERENCE)Parameters->SavedCallState.Reference;
CompleteFileReference( FileReference,
CallSuccessful,
TRUE,
NULL
);
return TRUE;
}
}
#undef DeleteFile
BOOLEAN
NtSetInformationFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PSETINFORMATIONFILE_PARAMETERS p = &Parameters->InputParameters.SetInformationFile;
POPENHANDLE_INFO HandleInfo;
FILE_RENAME_INFORMATION RenameInformation;
FILE_DISPOSITION_INFORMATION DispositionInformation;
PWSTR NewName, OldName;
PFILE_REFERENCE OldFileReference;
PFILE_REFERENCE NewFileReference;
BOOLEAN Result, CallSuccessful;
HandleInfo = FindOpenHandle( Process,
p->FileHandle,
HANDLE_TYPE_FILE
);
if (HandleInfo == NULL) {
Result = FALSE;
}
else
if (p->FileInformationClass == FileRenameInformation) {
//
// Renaming an open file.
//
if (!Parameters->ReturnValueValid) {
if (ReadMemory( Process,
p->FileInformation,
&RenameInformation,
FIELD_OFFSET( FILE_RENAME_INFORMATION, FileName ),
"rename information"
) &&
CaptureFullName( Process,
HANDLE_TYPE_FILE,
RenameInformation.RootDirectory,
&((PFILE_RENAME_INFORMATION)(p->FileInformation))->FileName[ 0 ],
RenameInformation.FileNameLength,
&NewName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
RenamePath,
HANDLE_TYPE_FILE,
HandleInfo->Name,
NewName,
RenameInformation.ReplaceIfExists
)
) {
Result = CreateFileReference( NewName,
RenameInformation.ReplaceIfExists,
(PFILE_REFERENCE *)&Parameters->SavedCallState.Reference
);
}
else {
Result = FALSE;
}
}
else {
OldName = NULL;
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
CallSuccessful = TRUE;
OldFileReference = FindFileReference( HandleInfo->Name );
if (OldFileReference) {
OldName = OldFileReference->Name;
}
}
else {
CallSuccessful = FALSE;
OldFileReference = NULL;
}
NewFileReference = (PFILE_REFERENCE)Parameters->SavedCallState.Reference;
NewName = NewFileReference->Name;
CompleteFileReference( NewFileReference,
CallSuccessful,
(BOOLEAN)(!NewFileReference->Created),
OldFileReference
);
Result = TRUE;
}
}
else
if (p->FileInformationClass == FileDispositionInformation) {
//
// Marking an open file for delete.
//
if (!Parameters->ReturnValueValid) {
if (ReadMemory( Process,
p->FileInformation,
&DispositionInformation,
sizeof( DispositionInformation ),
"disposition information"
) &&
DispositionInformation.DeleteFile &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
DeletePath,
HANDLE_TYPE_FILE,
HandleInfo->Name
)
) {
Result = TRUE;
}
else {
Result = FALSE;
}
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
if (OldFileReference = FindFileReference( HandleInfo->Name )) {
if (OldFileReference->Created) {
LogEvent( INSTALER_EVENT_DELETE_TEMP_FILE,
2,
OldFileReference->DirectoryFile ? L"directory" : L"file",
OldFileReference->Name
);
DestroyFileReference( OldFileReference );
}
else {
OldFileReference->Deleted = TRUE;
LogEvent( INSTALER_EVENT_DELETE_FILE,
2,
OldFileReference->DirectoryFile ? L"directory" : L"file",
OldFileReference->Name
);
}
}
}
Result = TRUE;
}
}
else {
Result = FALSE;
}
return Result;
}
BOOLEAN
CaptureUnicodeString(
PPROCESS_INFO Process,
PUNICODE_STRING UnicodeStringAddress,
PWSTR *ReturnedString
)
{
UNICODE_STRING UnicodeString;
PWSTR s;
s = NULL;
if (ReadMemory( Process,
UnicodeStringAddress,
&UnicodeString,
sizeof( UnicodeString ),
"unicode string"
) &&
((s = AllocMem( UnicodeString.Length + sizeof( UNICODE_NULL ) )) != NULL) &&
ReadMemory( Process,
UnicodeString.Buffer,
s,
UnicodeString.Length,
"unicode string buffer"
)
) {
*ReturnedString = s;
return TRUE;
}
FreeMem( &s );
return FALSE;
}
BOOLEAN
NtQueryAttributesFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PQUERYATTRIBUTESFILE_PARAMETERS p = &Parameters->InputParameters.QueryAttributesFile;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ObjectName;
PWSTR FullName;
NTSTATUS Status;
BOOLEAN Result;
CHAR Buffer[ MAX_PATH ];
if (!Parameters->ReturnValueValid) {
FullName = NULL;
Result = FALSE;
if (CaptureObjectAttributes( Process,
p->ObjectAttributes,
&ObjectAttributes,
&ObjectName
) &&
CaptureFullName( Process,
HANDLE_TYPE_FILE,
ObjectAttributes.RootDirectory,
ObjectName.Buffer,
ObjectName.Length,
&FullName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
QueryPath,
HANDLE_TYPE_FILE,
FullName
)
) {
Result = CreateFileReference( FullName,
FALSE,
(PFILE_REFERENCE *)&Parameters->SavedCallState.Reference
);
}
else {
Result = FALSE;
}
return Result;
}
else {
FILE_BASIC_INFORMATION FileInformation;
ReadMemory( Process,
p->FileInformation,
&FileInformation,
sizeof( FileInformation ),
"FileInformation"
);
return TRUE;
}
}
BOOLEAN
NtQueryDirectoryFileHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PQUERYDIRECTORYFILE_PARAMETERS p = &Parameters->InputParameters.QueryDirectoryFile;
POPENHANDLE_INFO HandleInfo;
PWSTR FileName;
NTSTATUS Status;
BOOLEAN Result;
PULONG pNextEntryOffset;
ULONG NextEntryOffset;
ULONG EntriesReturned;
if (!Parameters->ReturnValueValid) {
FileName = NULL;
Result = FALSE;
if ((HandleInfo = FindOpenHandle( Process,
p->FileHandle,
HANDLE_TYPE_FILE
)
) != NULL &&
p->FileName != NULL &&
CaptureUnicodeString( Process,
p->FileName,
&FileName
)
) {
if (HandleInfo->RootDirectory &&
!wcscmp( FileName, L"*" ) || !wcscmp( FileName, L"*.*" )
) {
if (AskUserOnce) {
AskUserOnce = FALSE;
if (AskUser( MB_OKCANCEL,
INSTALER_ASKUSER_ROOTSCAN,
1,
HandleInfo->Name
) == IDCANCEL
) {
FailAllScansOfRootDirectories = TRUE;
}
}
Parameters->AbortCall = FailAllScansOfRootDirectories;
}
if (FileName) {
HandleInfo->QueryName = FileName;
}
}
return TRUE;
}
else {
if (Parameters->AbortCall) {
//
// If we get here, then user wanted to fail this call.
//
Status = STATUS_NO_MORE_FILES;
SetProcedureReturnValue( Process,
Thread,
&Status,
sizeof( Status )
);
return TRUE;
}
else {
if ((HandleInfo = FindOpenHandle( Process,
p->FileHandle,
HANDLE_TYPE_FILE
)
) != NULL
) {
//
// If successful, count entries returned
//
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
//
// Return buffer is a set of records, the first DWORD of each contains
// the offset to the next one or zero to indicate the end. Count them.
//
pNextEntryOffset = (PULONG)p->FileInformation;
EntriesReturned = 1;
while (ReadMemory( Process,
pNextEntryOffset,
&NextEntryOffset,
sizeof( NextEntryOffset ),
"DirectoryInformation"
) &&
NextEntryOffset != 0
) {
pNextEntryOffset = (PULONG)((PCHAR)pNextEntryOffset + NextEntryOffset);
EntriesReturned += 1;
}
LogEvent( INSTALER_EVENT_SCAN_DIRECTORY,
3,
HandleInfo->Name,
HandleInfo->QueryName ? HandleInfo->QueryName : L"*",
EntriesReturned
);
}
else {
FreeMem( &HandleInfo->QueryName );
}
}
}
return TRUE;
}
}
BOOLEAN
IsKeyWriteAccessRequested(
ACCESS_MASK DesiredAccess
)
{
if (DesiredAccess & (GENERIC_WRITE |
GENERIC_ALL |
DELETE |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY |
KEY_CREATE_LINK
)
) {
return TRUE;
}
return FALSE;
}
BOOLEAN
NtCreateKeyHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PCREATEKEY_PARAMETERS p = &Parameters->InputParameters.CreateKey;
BOOLEAN Result;
if (!Parameters->ReturnValueValid) {
Result = CaptureOpenState( Process,
Parameters,
p->ObjectAttributes,
IsKeyWriteAccessRequested( p->DesiredAccess ),
p->KeyHandle,
HANDLE_TYPE_KEY
);
}
else {
Result = CompleteOpenState( Process,
Parameters
);
}
return Result;
}
BOOLEAN
NtOpenKeyHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
POPENKEY_PARAMETERS p = &Parameters->InputParameters.OpenKey;
BOOLEAN Result;
if (!Parameters->ReturnValueValid) {
Result = CaptureOpenState( Process,
Parameters,
p->ObjectAttributes,
IsKeyWriteAccessRequested( p->DesiredAccess ),
p->KeyHandle,
HANDLE_TYPE_KEY
);
}
else {
Result = CompleteOpenState( Process,
Parameters
);
}
return Result;
}
BOOLEAN
NtDeleteKeyHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PDELETEKEY_PARAMETERS p = &Parameters->InputParameters.DeleteKey;
POPENHANDLE_INFO HandleInfo;
PKEY_REFERENCE OldKeyReference;
BOOLEAN Result;
//
// Marking an open key for delete.
//
HandleInfo = FindOpenHandle( Process,
p->KeyHandle,
HANDLE_TYPE_KEY
);
if (HandleInfo == NULL) {
Result = FALSE;
}
else
if (!Parameters->ReturnValueValid) {
if (CreateSavedCallState( Process,
&Parameters->SavedCallState,
DeletePath,
HANDLE_TYPE_KEY,
HandleInfo->Name
)
) {
Result = TRUE;
}
else {
Result = FALSE;
}
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
if (OldKeyReference = FindKeyReference( HandleInfo->Name )) {
if (OldKeyReference->Created) {
LogEvent( INSTALER_EVENT_DELETE_TEMP_KEY,
1,
OldKeyReference->Name
);
DestroyKeyReference( OldKeyReference );
}
else {
MarkKeyDeleted( OldKeyReference );
LogEvent( INSTALER_EVENT_DELETE_KEY,
1,
OldKeyReference->Name
);
}
}
}
Result = TRUE;
}
return Result;
}
BOOLEAN
CaptureValueName(
PPROCESS_INFO Process,
PUNICODE_STRING Name,
PWSTR *ReturnedValueName
)
{
UNICODE_STRING ValueName;
PWSTR s;
*ReturnedValueName = NULL;
if (Name == NULL ||
!ReadMemory( Process,
Name,
&ValueName,
sizeof( ValueName ),
"value name string"
)
) {
return FALSE;
}
s = AllocMem( ValueName.Length + sizeof( UNICODE_NULL ) );
if (s == NULL) {
return FALSE;
}
if (!ReadMemory( Process,
ValueName.Buffer,
s,
ValueName.Length,
"value name buffer"
)
) {
FreeMem( &s );
return FALSE;
}
s[ ValueName.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
ValueName.Buffer = s;
ValueName.MaximumLength = (USHORT)(ValueName.Length + sizeof( UNICODE_NULL ));
*ReturnedValueName = AddName( &ValueName );
FreeMem( &ValueName.Buffer );
return TRUE;
}
BOOLEAN
NtSetValueKeyHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PSETVALUEKEY_PARAMETERS p = &Parameters->InputParameters.SetValueKey;
POPENHANDLE_INFO HandleInfo;
PWSTR ValueName;
PKEY_REFERENCE KeyReference;
PVALUE_REFERENCE ValueReference;
BOOLEAN Result;
//
// Setting a value
//
HandleInfo = FindOpenHandle( Process,
p->KeyHandle,
HANDLE_TYPE_KEY
);
if (HandleInfo == NULL) {
Result = FALSE;
}
else
if (!Parameters->ReturnValueValid) {
if (CaptureValueName( Process,
p->ValueName,
&ValueName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
SetValue,
HANDLE_TYPE_KEY,
ValueName
)
) {
Result = TRUE;
}
else {
Result = FALSE;
}
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong ) &&
(KeyReference = FindKeyReference( HandleInfo->Name ))
) {
CreateValueReference( Process,
KeyReference,
Parameters->SavedCallState.FullName,
p->TitleIndex,
p->Type,
p->Data,
p->DataLength,
&ValueReference
);
if (ValueReference != NULL) {
LogEvent( INSTALER_EVENT_SET_KEY_VALUE,
2,
ValueReference->Name,
KeyReference->Name
);
}
}
Result = TRUE;
}
return Result;
}
BOOLEAN
NtDeleteValueKeyHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PDELETEVALUEKEY_PARAMETERS p = &Parameters->InputParameters.DeleteValueKey;
POPENHANDLE_INFO HandleInfo;
PWSTR ValueName;
PKEY_REFERENCE KeyReference;
PVALUE_REFERENCE ValueReference;
BOOLEAN Result;
//
// Marking a value for delete.
//
HandleInfo = FindOpenHandle( Process,
p->KeyHandle,
HANDLE_TYPE_KEY
);
if (HandleInfo == NULL) {
Result = FALSE;
}
else
if (!Parameters->ReturnValueValid) {
if (CaptureValueName( Process,
p->ValueName,
&ValueName
) &&
CreateSavedCallState( Process,
&Parameters->SavedCallState,
DeleteValue,
HANDLE_TYPE_KEY,
ValueName
)
) {
Result = TRUE;
}
else {
Result = FALSE;
}
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong ) &&
(KeyReference = FindKeyReference( HandleInfo->Name )) &&
(ValueReference = FindValueReference( KeyReference, Parameters->SavedCallState.FullName ))
) {
if (ValueReference->Created) {
LogEvent( INSTALER_EVENT_DELETE_KEY_TEMP_VALUE,
2,
ValueReference->Name,
KeyReference->Name
);
DestroyValueReference( ValueReference );
}
else {
ValueReference->Deleted = TRUE;
LogEvent( INSTALER_EVENT_DELETE_KEY_VALUE,
2,
ValueReference->Name,
KeyReference->Name
);
}
}
Result = TRUE;
}
return Result;
}
BOOLEAN
NtCloseHandleHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PCLOSEHANDLE_PARAMETERS p = &Parameters->InputParameters.CloseHandle;
POPENHANDLE_INFO HandleInfo;
PFILE_REFERENCE FileReference;
HandleInfo = FindOpenHandle( Process, p->Handle, (ULONG)-1 );
if (!Parameters->ReturnValueValid) {
if (HandleInfo != NULL) {
return TRUE;
}
else {
return FALSE;
}
}
else {
if (NT_SUCCESS( Parameters->ReturnValue.ReturnedLong )) {
if (HandleInfo != NULL &&
HandleInfo->Type == HANDLE_TYPE_FILE &&
(FileReference = FindFileReference( HandleInfo->Name )) != NULL &&
FileReference->WriteAccess &&
!FileReference->Created &&
!FileReference->DirectoryFile &&
IsNewFileSameAsBackup( FileReference )
) {
DestroyFileReference( FileReference );
FileReference = NULL;
}
DeleteOpenHandle( Process, p->Handle, (ULONG)-1 );
}
return TRUE;
}
}
UCHAR AnsiStringBuffer[ MAX_PATH+1 ];
WCHAR UnicodeStringBuffer[ MAX_PATH+1 ];
BOOLEAN
CaptureAnsiAsUnicode(
PPROCESS_INFO Process,
LPCSTR Address,
BOOLEAN DoubleNullTermination,
PWSTR *ReturnedName,
PWSTR *ReturnedData
)
{
NTSTATUS Status;
ULONG BytesRead;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
if (Address == NULL) {
if (ReturnedName != NULL) {
*ReturnedName = NULL;
}
else {
*ReturnedData = NULL;
}
return TRUE;
}
BytesRead = FillTemporaryBuffer( Process,
(PVOID)Address,
FALSE,
DoubleNullTermination
);
if (BytesRead != 0 && BytesRead < 0x7FFF) {
AnsiString.Buffer = TemporaryBuffer;
AnsiString.Length = (USHORT)BytesRead;
AnsiString.MaximumLength = (USHORT)BytesRead;
Status = RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, TRUE );
if (NT_SUCCESS( Status )) {
if (ReturnedName != NULL) {
*ReturnedName = AddName( &UnicodeString );
RtlFreeUnicodeString( &UnicodeString );
return TRUE;
}
else {
*ReturnedData = UnicodeString.Buffer;
return TRUE;
}
}
}
return FALSE;
}
BOOLEAN
CaptureUnicode(
PPROCESS_INFO Process,
LPCWSTR Address,
BOOLEAN DoubleNullTermination,
PWSTR *ReturnedName,
PWSTR *ReturnedData
)
{
ULONG BytesRead;
UNICODE_STRING UnicodeString;
if (Address == NULL) {
if (ReturnedName != NULL) {
*ReturnedName = NULL;
}
else {
*ReturnedData = NULL;
}
return TRUE;
}
BytesRead = FillTemporaryBuffer( Process,
(PVOID)Address,
TRUE,
DoubleNullTermination
);
if (BytesRead != 0 && (BytesRead & 1) == 0 && BytesRead <= 0xFFFC) {
if (ReturnedName != NULL) {
RtlInitUnicodeString( &UnicodeString, TemporaryBuffer );
*ReturnedName = AddName( &UnicodeString );
return TRUE;
}
else {
*ReturnedData = AllocMem( BytesRead + sizeof( UNICODE_NULL ) );
if (*ReturnedData != NULL) {
memmove( *ReturnedData, TemporaryBuffer, BytesRead );
return TRUE;
}
}
}
return FALSE;
}
BOOLEAN
GetVersionHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
DWORD dwVersion;
if (!Parameters->ReturnValueValid) {
if (AskUserOnce) {
AskUserOnce = FALSE;
if (AskUser( MB_OKCANCEL,
INSTALER_ASKUSER_GETVERSION,
0
) == IDCANCEL
) {
DefaultGetVersionToWin95 = TRUE;
}
else {
DefaultGetVersionToWin95 = FALSE;
}
}
LogEvent( INSTALER_EVENT_GETVERSION,
1,
DefaultGetVersionToWin95 ? L"Windows 95" : L"Windows NT"
);
Parameters->AbortCall = DefaultGetVersionToWin95;
return Parameters->AbortCall;
}
else {
dwVersion = 0xC0000004; // What Windows 95 returns
SetProcedureReturnValue( Process,
Thread,
&dwVersion,
sizeof( dwVersion )
);
return TRUE;
}
}
BOOLEAN
GetVersionExWHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PGETVERSIONEXW_PARAMETERS p = &Parameters->InputParameters.GetVersionExW;
OSVERSIONINFOW VersionInformation;
if (!Parameters->ReturnValueValid) {
if (AskUserOnce) {
AskUserOnce = FALSE;
if (AskUser( MB_OKCANCEL,
INSTALER_ASKUSER_GETVERSION,
0
) == IDCANCEL
) {
DefaultGetVersionToWin95 = TRUE;
}
else {
DefaultGetVersionToWin95 = FALSE;
}
}
Parameters->AbortCall = DefaultGetVersionToWin95;
return Parameters->AbortCall;
}
else {
memset( &VersionInformation, 0, sizeof( VersionInformation ) );
VersionInformation.dwMajorVersion = 4;
VersionInformation.dwBuildNumber = 0x3B6; // What Windows 95 returns
VersionInformation.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
WriteMemory( Process,
p->lpVersionInformation,
&VersionInformation,
sizeof( VersionInformation ),
"GetVersionExW"
);
return TRUE;
}
}
BOOLEAN
SetCurrentDirectoryAHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PSETCURRENTDIRECTORYA_PARAMETERS p = &Parameters->InputParameters.SetCurrentDirectoryA;
PWSTR PathName;
WCHAR PathBuffer[ MAX_PATH ];
if (!Parameters->ReturnValueValid) {
if (CaptureAnsiAsUnicode( Process, p->lpPathName, FALSE, NULL, &PathName ) && PathName != NULL) {
Parameters->CurrentDirectory = AllocMem( (wcslen( PathName ) + 1) * sizeof( WCHAR ) );
if (Parameters->CurrentDirectory != NULL) {
wcscpy( Parameters->CurrentDirectory, PathName );
return TRUE;
}
}
return FALSE;
}
else {
if (Parameters->ReturnValue.ReturnedBool != 0) {
if (SetCurrentDirectory( Parameters->CurrentDirectory ) &&
GetCurrentDirectory( MAX_PATH, PathBuffer )
) {
LogEvent( INSTALER_EVENT_SET_DIRECTORY,
1,
PathBuffer
);
}
}
FreeMem( &Parameters->CurrentDirectory );
return TRUE;
}
}
BOOLEAN
SetCurrentDirectoryWHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PSETCURRENTDIRECTORYW_PARAMETERS p = &Parameters->InputParameters.SetCurrentDirectoryW;
PWSTR PathName;
WCHAR PathBuffer[ MAX_PATH ];
if (!Parameters->ReturnValueValid) {
if (CaptureUnicode( Process, p->lpPathName, FALSE, NULL, &PathName ) && PathName != NULL) {
Parameters->CurrentDirectory = AllocMem( (wcslen( PathName ) + 1) * sizeof( WCHAR ) );
if (Parameters->CurrentDirectory != NULL) {
wcscpy( Parameters->CurrentDirectory, PathName );
return TRUE;
}
}
return FALSE;
}
else {
if (Parameters->ReturnValue.ReturnedBool != 0) {
if (SetCurrentDirectory( Parameters->CurrentDirectory ) &&
GetCurrentDirectory( MAX_PATH, PathBuffer )
) {
LogEvent( INSTALER_EVENT_SET_DIRECTORY,
1,
PathBuffer
);
}
}
FreeMem( &Parameters->CurrentDirectory );
return TRUE;
}
}
BOOLEAN
GetIniFilePath(
PWSTR IniFileName,
PWSTR *ReturnedIniFilePath
)
{
NTSTATUS Status;
UNICODE_STRING FileName, UnicodeString;
PWSTR FilePart;
DWORD n;
if (IniFileName == NULL) {
RtlInitUnicodeString( &FileName, L"win.ini" );
}
else {
RtlInitUnicodeString( &FileName, IniFileName );
}
if ((FileName.Length > sizeof( WCHAR ) &&
FileName.Buffer[ 1 ] == L':'
) ||
(FileName.Length != 0 &&
wcscspn( FileName.Buffer, L"\\/" ) != (FileName.Length / sizeof( WCHAR ))
)
) {
UnicodeString.MaximumLength = (USHORT)(MAX_PATH * sizeof( WCHAR ));
UnicodeString.Buffer = AllocMem( UnicodeString.MaximumLength );
if (UnicodeString.Buffer == NULL) {
Status = STATUS_NO_MEMORY;
}
else {
UnicodeString.Length = 0;
n = GetFullPathNameW( FileName.Buffer,
UnicodeString.MaximumLength / sizeof( WCHAR ),
UnicodeString.Buffer,
&FilePart
);
if (n > UnicodeString.MaximumLength) {
Status = STATUS_BUFFER_TOO_SMALL;
}
else {
UnicodeString.Length = (USHORT)(n * sizeof( WCHAR ));
Status = STATUS_SUCCESS;
}
}
}
else {
UnicodeString.Length = 0;
UnicodeString.MaximumLength = (USHORT)(WindowsDirectory.Length +
sizeof( WCHAR ) +
FileName.Length +
sizeof( UNICODE_NULL )
);
UnicodeString.Buffer = AllocMem( UnicodeString.MaximumLength );
if (UnicodeString.Buffer == NULL) {
Status = STATUS_NO_MEMORY;
}
else {
RtlCopyUnicodeString( &UnicodeString, &WindowsDirectory );
Status = RtlAppendUnicodeToString( &UnicodeString,
L"\\"
);
if (NT_SUCCESS( Status )) {
Status = RtlAppendUnicodeStringToString( &UnicodeString,
&FileName
);
}
}
}
if (IniFileName != NULL) {
FreeMem( &IniFileName );
}
if (NT_SUCCESS( Status )) {
*ReturnedIniFilePath = AddName( &UnicodeString );
FreeMem( &UnicodeString.Buffer );
return TRUE;
}
else {
FreeMem( &UnicodeString.Buffer );
return FALSE;
}
}
BOOLEAN
WritePrivateProfileStringEntry(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters,
PWSTR IniFilePath,
PWSTR SectionName,
PWSTR VariableName,
PWSTR VariableValue
)
{
if (CreateSavedCallState( Process,
&Parameters->SavedCallState,
WriteIniValue,
HANDLE_TYPE_NONE,
IniFilePath,
SectionName,
VariableName,
VariableValue
) &&
CreateIniFileReference( IniFilePath,
(PINI_FILE_REFERENCE *)&Parameters->SavedCallState.Reference
)
) {
return TRUE;
}
else {
FreeMem( &VariableValue );
return FALSE;
}
}
BOOLEAN
WritePrivateProfileStringExit(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PAPI_SAVED_CALL_STATE CallState;
PINI_FILE_REFERENCE IniFileReference;
PINI_SECTION_REFERENCE IniSectionReference;
PINI_VARIABLE_REFERENCE IniVariableReference;
if (Parameters->ReturnValue.ReturnedLong != 0) {
CallState = &Parameters->SavedCallState;
if (CallState->FullName == NULL &&
CallState->SetIniValue.SectionName == NULL &&
CallState->SetIniValue.VariableName == NULL
) {
//
// Ignore calls to flush INI cache
//
return FALSE;
}
IniFileReference = FindIniFileReference( CallState->FullName );
if (IniFileReference == NULL) {
return TRUE;
}
IniSectionReference = FindIniSectionReference( IniFileReference,
CallState->SetIniValue.SectionName,
(BOOLEAN)(CallState->SetIniValue.VariableName != NULL)
);
if (IniSectionReference == NULL) {
return TRUE;
}
if (CallState->SetIniValue.VariableName == NULL) {
IniSectionReference->Deleted = TRUE;
LogEvent( INSTALER_EVENT_INI_DELETE_SECTION,
2,
CallState->FullName,
CallState->SetIniValue.SectionName
);
} else {
IniVariableReference = FindIniVariableReference( IniSectionReference,
CallState->SetIniValue.VariableName,
(BOOLEAN)(CallState->SetIniValue.VariableValue != NULL)
);
if (IniVariableReference != NULL) {
if (CallState->SetIniValue.VariableValue != NULL) {
FreeMem( &IniVariableReference->Value );
IniVariableReference->Value = CallState->SetIniValue.VariableValue;
CallState->SetIniValue.VariableValue = NULL;
if (!IniVariableReference->Created) {
if (!wcscmp( IniVariableReference->Value,
IniVariableReference->OriginalValue
)
) {
FreeMem( &IniVariableReference->Value );
} else {
IniVariableReference->Modified = TRUE;
LogEvent( INSTALER_EVENT_INI_CHANGE,
5,
CallState->FullName,
CallState->SetIniValue.SectionName,
CallState->SetIniValue.VariableName,
IniVariableReference->Value,
IniVariableReference->OriginalValue
);
}
} else {
LogEvent( INSTALER_EVENT_INI_CREATE,
4,
CallState->FullName,
CallState->SetIniValue.SectionName,
CallState->SetIniValue.VariableName,
IniVariableReference->Value
);
}
} else if (!IniVariableReference->Created) {
IniVariableReference->Deleted = TRUE;
LogEvent( INSTALER_EVENT_INI_DELETE,
4,
CallState->FullName,
CallState->SetIniValue.SectionName,
CallState->SetIniValue.VariableName,
IniVariableReference->OriginalValue
);
} else {
DestroyIniVariableReference( IniVariableReference );
}
}
}
}
return TRUE;
}
BOOLEAN
WritePrivateProfileStringAHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PWRITEPRIVATEPROFILESTRINGA_PARAMETERS p = &Parameters->InputParameters.WritePrivateProfileStringA;
PWSTR SectionName, VariableName, FileName, VariableValue;
PWSTR IniFilePath;
if (!Parameters->ReturnValueValid) {
FileName = NULL;
VariableValue = NULL;
if (CaptureAnsiAsUnicode( Process, p->lpFileName, FALSE, NULL, &FileName ) &&
GetIniFilePath( FileName, &IniFilePath ) &&
CaptureAnsiAsUnicode( Process, p->lpAppName, FALSE, &SectionName, NULL ) &&
CaptureAnsiAsUnicode( Process, p->lpKeyName, FALSE, &VariableName, NULL ) &&
CaptureAnsiAsUnicode( Process, p->lpString, FALSE, NULL, &VariableValue )
) {
if (FileName != NULL || SectionName != NULL) {
return WritePrivateProfileStringEntry( Process,
Thread,
Parameters,
IniFilePath,
SectionName,
VariableName,
VariableValue
);
}
}
return TRUE;
}
else {
return WritePrivateProfileStringExit( Process,
Thread,
Parameters
);
}
}
BOOLEAN
WritePrivateProfileStringWHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PWRITEPRIVATEPROFILESTRINGW_PARAMETERS p = &Parameters->InputParameters.WritePrivateProfileStringW;
PWSTR SectionName, VariableName, FileName, VariableValue;
PWSTR IniFilePath;
if (!Parameters->ReturnValueValid) {
FileName = NULL;
IniFilePath = NULL;
SectionName = NULL;
VariableName = NULL;
VariableValue = NULL;
if (CaptureUnicode( Process, p->lpFileName, FALSE, NULL, &FileName ) &&
GetIniFilePath( FileName, &IniFilePath ) &&
CaptureUnicode( Process, p->lpAppName, FALSE, &SectionName, NULL ) &&
CaptureUnicode( Process, p->lpKeyName, FALSE, &VariableName, NULL ) &&
CaptureUnicode( Process, p->lpString, FALSE, NULL, &VariableValue )
) {
if (FileName != NULL || SectionName != NULL) {
return WritePrivateProfileStringEntry( Process,
Thread,
Parameters,
IniFilePath,
SectionName,
VariableName,
VariableValue );
}
}
return TRUE;
}
return WritePrivateProfileStringExit( Process,
Thread,
Parameters );
}
BOOLEAN
WritePrivateProfileSectionEntry(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters,
PWSTR IniFilePath,
PWSTR SectionName,
PWSTR SectionValue
)
{
if (CreateSavedCallState( Process,
&Parameters->SavedCallState,
WriteIniSection,
HANDLE_TYPE_NONE,
IniFilePath,
SectionName,
SectionValue )
&&
CreateIniFileReference( IniFilePath,
(PINI_FILE_REFERENCE *)&Parameters->SavedCallState.Reference )
) {
return TRUE;
}
FreeMem( &SectionValue );
return FALSE;
}
BOOLEAN
WritePrivateProfileSectionExit(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PAPI_SAVED_CALL_STATE CallState;
PINI_FILE_REFERENCE IniFileReference;
PINI_SECTION_REFERENCE IniSectionReference;
PINI_VARIABLE_REFERENCE IniVariableReference;
PWSTR VariableName, VariableValue;
UNICODE_STRING UnicodeString;
if (Parameters->ReturnValue.ReturnedLong != 0) {
CallState = &Parameters->SavedCallState;
IniFileReference = FindIniFileReference( CallState->FullName );
if (IniFileReference == NULL) {
return TRUE;
}
IniSectionReference = FindIniSectionReference( IniFileReference,
CallState->SetIniSection.SectionName,
(BOOLEAN)(CallState->SetIniSection.SectionValue != NULL) );
if (IniSectionReference == NULL) {
return TRUE;
}
if (CallState->SetIniSection.SectionValue == NULL) {
IniSectionReference->Deleted = TRUE;
} else {
VariableName = CallState->SetIniSection.SectionValue;
while (*VariableName) {
VariableValue = VariableName;
while (*VariableValue != UNICODE_NULL && *VariableValue != L'=') {
VariableValue += 1;
}
if (*VariableValue != L'=') {
break;
}
*VariableValue++ = UNICODE_NULL;
RtlInitUnicodeString( &UnicodeString, VariableName );
IniVariableReference = FindIniVariableReference( IniSectionReference,
AddName( &UnicodeString ),
(BOOLEAN)(*VariableValue != UNICODE_NULL)
);
if (IniVariableReference != NULL) {
if (*VariableValue != UNICODE_NULL) {
FreeMem( &IniVariableReference->Value );
IniVariableReference->Value = AllocMem( (wcslen( VariableValue ) + 1) * sizeof( WCHAR ) );
wcscpy( IniVariableReference->Value, VariableValue );
if (!IniVariableReference->Created) {
if (!wcscmp( IniVariableReference->Value,
IniVariableReference->OriginalValue
) )
{
FreeMem( &IniVariableReference->Value );
} else {
IniVariableReference->Modified = TRUE;
}
}
} else
if (!IniVariableReference->Created) {
IniVariableReference->Deleted = TRUE;
} else {
DestroyIniVariableReference( IniVariableReference );
}
}
VariableName = VariableValue;
while (*VariableName++ != UNICODE_NULL) {}
}
}
}
return TRUE;
}
BOOLEAN
WritePrivateProfileSectionAHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PWRITEPRIVATEPROFILESECTIONA_PARAMETERS p = &Parameters->InputParameters.WritePrivateProfileSectionA;
PWSTR SectionName, FileName, SectionValue;
PWSTR IniFilePath;
if (!Parameters->ReturnValueValid) {
FileName = NULL;
SectionValue = NULL;
if (CaptureAnsiAsUnicode( Process, p->lpFileName, FALSE, NULL, &FileName ) &&
GetIniFilePath( FileName, &IniFilePath ) &&
CaptureAnsiAsUnicode( Process, p->lpAppName, FALSE, &SectionName, NULL ) &&
CaptureAnsiAsUnicode( Process, p->lpString, TRUE, NULL, &SectionValue )
) {
return WritePrivateProfileSectionEntry( Process,
Thread,
Parameters,
IniFilePath,
SectionName,
SectionValue
);
}
return FALSE;
}
else {
return WritePrivateProfileSectionExit( Process,
Thread,
Parameters
);
}
}
BOOLEAN
WritePrivateProfileSectionWHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PWRITEPRIVATEPROFILESECTIONW_PARAMETERS p = &Parameters->InputParameters.WritePrivateProfileSectionW;
PWSTR SectionName, FileName, SectionValue;
PWSTR IniFilePath;
if (!Parameters->ReturnValueValid) {
FileName = NULL;
SectionValue = NULL;
if (CaptureUnicode( Process, p->lpFileName, FALSE, NULL, &FileName ) &&
GetIniFilePath( FileName, &IniFilePath ) &&
CaptureUnicode( Process, p->lpAppName, FALSE, &SectionName, NULL ) &&
CaptureUnicode( Process, p->lpString, TRUE, NULL, &SectionValue )
) {
return WritePrivateProfileSectionEntry( Process,
Thread,
Parameters,
IniFilePath,
SectionName,
SectionValue
);
}
return FALSE;
}
else {
return WritePrivateProfileSectionExit( Process,
Thread,
Parameters
);
}
}
BOOLEAN
RegConnectRegistryWHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PREGCONNECTREGISTRYW_PARAMETERS p = &Parameters->InputParameters.RegConnectRegistryW;
PWSTR MachineName;
LONG ErrorCode;
HKEY hKey;
if (!Parameters->ReturnValueValid) {
MachineName = NULL;
if (!CaptureUnicode( Process, p->lpMachineName, FALSE, NULL, &MachineName )) {
MachineName = L"Unknown";
}
if (AskUser( MB_OKCANCEL,
INSTALER_ASKUSER_REGCONNECT,
1,
MachineName
) == IDCANCEL
) {
FreeMem( &MachineName );
Parameters->AbortCall = TRUE;
return TRUE;
}
else {
FreeMem( &MachineName );
return FALSE;
}
}
else
if (Parameters->ReturnValue.ReturnedLong == 0) {
ErrorCode = ERROR_ACCESS_DENIED;
if (SetProcedureReturnValue( Process,
Thread,
&ErrorCode,
sizeof( ErrorCode )
)
) {
if (ReadMemory( Process,
p->phkResult,
&hKey,
sizeof( hKey ),
"phkResult"
)
) {
RegCloseKey( hKey );
hKey = NULL;
WriteMemory( Process,
p->phkResult,
&hKey,
sizeof( hKey ),
"phkResult"
);
}
}
}
return TRUE;
}
BOOLEAN
ExitWindowsExHandler(
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
PAPI_SAVED_PARAMETERS Parameters
)
{
PEXITWINDOWSEX_PARAMETERS p = &Parameters->InputParameters.ExitWindowsEx;
PWSTR MachineName;
LONG ErrorCode;
HKEY hKey;
if (!Parameters->ReturnValueValid) {
//
// About to shutdown, save .IML file
//
return TRUE;
}
else
if (!Parameters->ReturnValue.ReturnedBool) {
//
// Shutdown attempt failed, keep going
//
}
return TRUE;
}