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.
1291 lines
32 KiB
1291 lines
32 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
wow64log.c
|
|
|
|
Abstract:
|
|
|
|
Main entrypoints for wow64log.dll. To add a data type handler :
|
|
1- Define a LOGDATATYPE for the data to log in w64logp.h
|
|
2- Implement the data type handler using the standard interface
|
|
NTSTATUS
|
|
LogDataType(IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn);
|
|
3- Insert the handler into LogDataType[] below.
|
|
|
|
|
|
Author:
|
|
|
|
03-Oct-1999 SamerA
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "w64logp.h"
|
|
#include <cathelper.h>
|
|
|
|
extern API_CATEGORY Wow64ApiCategories[];
|
|
extern API_CATEGORY_MAPPING Wow64ApiCategoryMappings[];
|
|
|
|
extern
|
|
ULONG
|
|
GetApiCategoryTableSize(
|
|
void );
|
|
|
|
extern
|
|
PAPI_CATEGORY_MAPPING
|
|
FindApiInMappingTable(
|
|
IN PTHUNK_DEBUG_INFO DebugInfoEntry,
|
|
IN ULONG TableNumber);
|
|
|
|
|
|
|
|
|
|
/// Public
|
|
|
|
//
|
|
// Control logging flags
|
|
//
|
|
UINT_PTR Wow64LogFlags;
|
|
HANDLE Wow64LogFileHandle;
|
|
|
|
|
|
|
|
/// Private
|
|
|
|
//
|
|
// Hold an array of pointers to each system service DebugThunkInfo
|
|
//
|
|
PULONG_PTR *LogNtBase;
|
|
PULONG_PTR *LogWin32;
|
|
PULONG_PTR *LogConsole;
|
|
PULONG_PTR *LogBase;
|
|
|
|
//
|
|
// Hold an array of pointers to each system service api/category info
|
|
//
|
|
PULONG_PTR *ApiInfoNtBase;
|
|
PULONG_PTR *ApiInfoWin32;
|
|
PULONG_PTR *ApiInfoConsole;
|
|
PULONG_PTR *ApiInfoBase;
|
|
|
|
//
|
|
// NOTE : The order entries in this table should match the LOGTYPE enum in
|
|
// w64logp.h.
|
|
//
|
|
LOGDATATYPE LogDataType[] =
|
|
{
|
|
{LogTypeValue}, // TypeHex
|
|
{LogTypePULongInOut}, // TypePULongPtrInOut
|
|
{LogTypePULongOut}, // TypePULONGOut
|
|
{LogTypePULongOut}, // TypePHandleOut
|
|
{LogTypeUnicodeString}, // TypeUnicodeStringIn
|
|
{LogTypeObjectAttrbiutes}, // TypeObjectAttributesIn
|
|
{LogTypeIoStatusBlock}, // TypeIoStatusBlockOut
|
|
{LogTypePWStr}, // TypePwstrIn
|
|
{LogTypePRectIn}, // TypePRectIn
|
|
{LogTypePLargeIntegerIn}, // TypePLargeIntegerIn
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WOW64LOGAPI
|
|
NTSTATUS
|
|
Wow64LogInitialize(
|
|
VOID)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by wow64.dll to initialize wow64 logging
|
|
subsystem.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
ULONG NtBaseTableSize, Win32TableSize, ConsoleTableSize, BaseTableSize;
|
|
PULONG_PTR *Win32ThunkDebugInfo;
|
|
PULONG_PTR *ConsoleThunkDebugInfo;
|
|
UNICODE_STRING Log2Name;
|
|
PVOID Log2Handle = NULL;
|
|
NTSTATUS st;
|
|
|
|
//
|
|
// Initialize the logging file handle
|
|
//
|
|
Wow64LogFileHandle = INVALID_HANDLE_VALUE;
|
|
|
|
//
|
|
// Initialize the logging flags
|
|
//
|
|
LogInitializeFlags(&Wow64LogFlags);
|
|
WOW64LOGOUTPUT((LF_TRACE, "Wow64LogInitialize - Wow64LogFlags = %I64x\n", Wow64LogFlags));
|
|
|
|
//
|
|
// Load the Win32 logging DLL if available.
|
|
//
|
|
RtlInitUnicodeString(&Log2Name, L"wow64lg2.dll");
|
|
st = LdrLoadDll(NULL, NULL, &Log2Name, &Log2Handle);
|
|
if (NT_SUCCESS(st)) {
|
|
ANSI_STRING ExportName;
|
|
|
|
RtlInitAnsiString(&ExportName, "Win32ThunkDebugInfo");
|
|
st = LdrGetProcedureAddress(Log2Handle, &ExportName, 0, &(PVOID)Win32ThunkDebugInfo);
|
|
if (NT_SUCCESS(st)) {
|
|
RtlInitAnsiString(&ExportName, "ConsoleThunkDebugInfo");
|
|
st = LdrGetProcedureAddress(Log2Handle, &ExportName, 0, &(PVOID)ConsoleThunkDebugInfo);
|
|
}
|
|
}
|
|
if (!NT_SUCCESS(st)) {
|
|
Log2Handle = NULL;
|
|
Win32ThunkDebugInfo = NULL;
|
|
ConsoleThunkDebugInfo = NULL;
|
|
}
|
|
|
|
//
|
|
// Build pointers to the debug thunk info for each
|
|
// system service
|
|
//
|
|
|
|
NtBaseTableSize = GetThunkDebugTableSize(
|
|
(PTHUNK_DEBUG_INFO)NtThunkDebugInfo);
|
|
BaseTableSize = GetThunkDebugTableSize(
|
|
(PTHUNK_DEBUG_INFO)BaseThunkDebugInfo);
|
|
if (Log2Handle != NULL) {
|
|
Win32TableSize = GetThunkDebugTableSize(
|
|
(PTHUNK_DEBUG_INFO)Win32ThunkDebugInfo);
|
|
ConsoleTableSize = GetThunkDebugTableSize(
|
|
(PTHUNK_DEBUG_INFO)ConsoleThunkDebugInfo);
|
|
} else {
|
|
Win32TableSize = 0;
|
|
ConsoleTableSize = 0;
|
|
}
|
|
|
|
LogNtBase = (PULONG_PTR *)Wow64AllocateHeap((NtBaseTableSize + Win32TableSize + ConsoleTableSize + BaseTableSize) *
|
|
sizeof(PULONG_PTR) * 2 );
|
|
|
|
if (!LogNtBase)
|
|
{
|
|
WOW64LOGOUTPUT((LF_ERROR, "Wow64LogInitialize - Wow64AllocateHeap failed\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
LogWin32 = LogNtBase + NtBaseTableSize;
|
|
LogConsole = LogWin32 + Win32TableSize;
|
|
LogBase = LogConsole + ConsoleTableSize;
|
|
|
|
ApiInfoNtBase = LogBase + BaseTableSize;
|
|
ApiInfoWin32 = ApiInfoNtBase + NtBaseTableSize;
|
|
ApiInfoConsole = ApiInfoWin32 + Win32TableSize;
|
|
ApiInfoBase = ApiInfoConsole + ConsoleTableSize;
|
|
|
|
BuildDebugThunkInfo(WHNT32_INDEX,(PTHUNK_DEBUG_INFO)NtThunkDebugInfo,LogNtBase,ApiInfoNtBase);
|
|
BuildDebugThunkInfo(WHBASE_INDEX,(PTHUNK_DEBUG_INFO)BaseThunkDebugInfo,LogBase,ApiInfoBase);
|
|
if (Log2Handle) {
|
|
BuildDebugThunkInfo(WHWIN32_INDEX,(PTHUNK_DEBUG_INFO)Win32ThunkDebugInfo,LogWin32,ApiInfoWin32);
|
|
BuildDebugThunkInfo(WHCON_INDEX,(PTHUNK_DEBUG_INFO)ConsoleThunkDebugInfo,LogConsole,ApiInfoConsole);
|
|
} else
|
|
{
|
|
LogConsole = NULL;
|
|
LogWin32 = NULL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
WOW64LOGAPI
|
|
NTSTATUS
|
|
Wow64LogTerminate(
|
|
VOID)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by wow64.dll when the process is exiting.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
if (Wow64LogFileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
NtFlushBuffersFile(Wow64LogFileHandle, &IoStatusBlock);
|
|
NtClose(Wow64LogFileHandle);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogInitializeFlags(
|
|
IN OUT PUINT_PTR Flags)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the logging flags from the registry
|
|
|
|
Arguments:
|
|
|
|
Flags - Pointer to receive logging flags
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
HANDLE Key;
|
|
UNICODE_STRING KeyName, ValueName, ResultValue;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
WCHAR KeyValueBuffer[ 128 ];
|
|
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
|
ULONG ResultLength, RegFlags;
|
|
NTSTATUS NtStatus;
|
|
|
|
|
|
//
|
|
// Punch in the default
|
|
//
|
|
*Flags = LF_DEFAULT;
|
|
|
|
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
NtStatus = NtOpenKey(&Key, KEY_READ, &ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
RtlInitUnicodeString(&ValueName, L"WOW64LOGFLAGS");
|
|
NtStatus = NtQueryValueKey(Key,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
KeyValueInformation,
|
|
sizeof(KeyValueBuffer),
|
|
&ResultLength);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
if ((KeyValueInformation->Type == REG_DWORD) &&
|
|
(KeyValueInformation->DataLength == sizeof(DWORD)))
|
|
{
|
|
*Flags = *((PULONG)KeyValueInformation->Data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
ULONG
|
|
GetThunkDebugTableSize(
|
|
IN PTHUNK_DEBUG_INFO DebugInfoTable)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retreives the number of DebugThunkInfo entries
|
|
in the passed table.
|
|
|
|
Arguments:
|
|
|
|
DebugInfoTable - Pointer to services debug info
|
|
|
|
Return Value:
|
|
|
|
Number of entries
|
|
--*/
|
|
{
|
|
BOOLEAN InvalidArgumentPresent;
|
|
ULONG ArgIndex;
|
|
ULONG Count = 0;
|
|
|
|
while (DebugInfoTable && DebugInfoTable->ApiName)
|
|
{
|
|
//
|
|
// Walk the argument list to make sure there aren't any NULLs in them, which would
|
|
// terminate the table.
|
|
//
|
|
|
|
ArgIndex = 0;
|
|
InvalidArgumentPresent = FALSE;
|
|
while (ArgIndex < DebugInfoTable->NumberOfArg)
|
|
{
|
|
if (!ARGUMENT_PRESENT (DebugInfoTable->Arg[ArgIndex++].Name))
|
|
{
|
|
InvalidArgumentPresent = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (InvalidArgumentPresent == TRUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
DebugInfoTable = (PTHUNK_DEBUG_INFO)
|
|
&DebugInfoTable->Arg[DebugInfoTable->NumberOfArg];
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
BuildDebugThunkInfo(
|
|
IN ULONG TableNumber,
|
|
IN PTHUNK_DEBUG_INFO DebugInfoTable,
|
|
OUT PULONG_PTR *LogTable,
|
|
OUT PULONG_PTR *ApiInfoTable)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine fills a service-table-indexed with pointers
|
|
to the corresponding DebugThunkInfo
|
|
|
|
Arguments:
|
|
|
|
DebugInfoTable - Services debug info
|
|
LogTable - Table of pointers to fill
|
|
ApiInfoTable - Table of pointers to fill
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
BOOLEAN InvalidArgumentPresent;
|
|
ULONG ArgIndex;
|
|
ULONG i=0;
|
|
|
|
while (DebugInfoTable && DebugInfoTable->ApiName)
|
|
{
|
|
|
|
LogTable[i] = (PULONG_PTR) DebugInfoTable;
|
|
|
|
ApiInfoTable[i++] = (PULONG_PTR) FindApiInMappingTable(DebugInfoTable,TableNumber);
|
|
|
|
|
|
//
|
|
// Walk the argument list to make sure there aren't any NULLs in them, which would
|
|
// terminate the table.
|
|
//
|
|
|
|
ArgIndex = 0;
|
|
InvalidArgumentPresent = FALSE;
|
|
while (ArgIndex < DebugInfoTable->NumberOfArg)
|
|
{
|
|
if (!ARGUMENT_PRESENT (DebugInfoTable->Arg[ArgIndex++].Name))
|
|
{
|
|
InvalidArgumentPresent = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (InvalidArgumentPresent == TRUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
DebugInfoTable = (PTHUNK_DEBUG_INFO)
|
|
&DebugInfoTable->Arg[DebugInfoTable->NumberOfArg];
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogApiHeader(
|
|
PTHUNK_DEBUG_INFO ThunkDebugInfo,
|
|
PLOGINFO LogInfo,
|
|
BOOLEAN ServiceReturn,
|
|
ULONG_PTR ReturnResult,
|
|
ULONG_PTR ReturnAddress)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log the Thunked API header
|
|
|
|
Arguments:
|
|
|
|
ThunkDebugInfo - Pointer to service log info
|
|
LogInfo - Logging Info
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
ReturnResult - Result code returned from the API
|
|
ReturnAddress - Return address of for this thunked call
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
return LogFormat(LogInfo,
|
|
"wh%s: Ret=%lx-%lx: ",
|
|
ThunkDebugInfo->ApiName,
|
|
ReturnResult,
|
|
ReturnAddress);
|
|
}
|
|
|
|
return LogFormat(LogInfo,
|
|
"%8.8X-wh%s: ",
|
|
PtrToUlong(NtCurrentTeb()->ClientId.UniqueThread),
|
|
ThunkDebugInfo->ApiName);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogApiParameters(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN PULONG Stack32,
|
|
IN PTHUNK_DEBUG_INFO ThunkDebugInfo,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log the Thunked API Parameters
|
|
|
|
Arguments:
|
|
|
|
LogInfo - Output log buffer
|
|
Stack32 - Pointer to 32-bit arg stack
|
|
ThunkDebugInfo - Pointer to service log info for the API
|
|
ServiceReturn - TRUE if called after the Thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
UINT_PTR i=0;
|
|
|
|
//
|
|
// Loops thru the parameters
|
|
//
|
|
while (i < ThunkDebugInfo->NumberOfArg)
|
|
{
|
|
_try
|
|
{
|
|
LogDataType[ThunkDebugInfo->Arg[i].Type].Handler(
|
|
LogInfo,
|
|
Stack32[i],
|
|
ThunkDebugInfo->Arg[i].Name,
|
|
ServiceReturn);
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
//
|
|
// Log the bad parameters
|
|
//
|
|
LogFormat(LogInfo,
|
|
"%s=%lx-%ws ",
|
|
ThunkDebugInfo->Arg[i].Name,
|
|
Stack32[i],
|
|
L"(BAD)");
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogThunkApi(
|
|
IN PTHUNK_LOG_CONTEXT ThunkLogContext,
|
|
IN PTHUNK_DEBUG_INFO ThunkDebugInfo,
|
|
IN UINT_PTR LogFullInfo)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log the Thunked API
|
|
|
|
Arguments:
|
|
|
|
ThunkLogContext - Thunk API log context
|
|
ThunkDebugInfo - Pointer to service log info for the API
|
|
LogFullInfo - Flag whther to log all the API info or just the name
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus;
|
|
CHAR szBuf[ MAX_LOG_BUFFER ];
|
|
LOGINFO LogInfo;
|
|
PULONG Stack32 = ThunkLogContext->Stack32;
|
|
BOOLEAN ServiceReturn = ThunkLogContext->ServiceReturn;
|
|
|
|
//
|
|
// Initialize the log buffer
|
|
//
|
|
LogInfo.OutputBuffer = szBuf;
|
|
LogInfo.BufferSize = MAX_LOG_BUFFER - 1;
|
|
|
|
//
|
|
// Log API header
|
|
//
|
|
NtStatus = LogApiHeader(ThunkDebugInfo,
|
|
&LogInfo,
|
|
ServiceReturn,
|
|
ThunkLogContext->ReturnResult,
|
|
*(Stack32-1));
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
return NtStatus;
|
|
}
|
|
|
|
// Log Parameters
|
|
if (LogFullInfo)
|
|
{
|
|
NtStatus = LogApiParameters(&LogInfo,
|
|
Stack32,
|
|
ThunkDebugInfo,
|
|
ServiceReturn);
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
return NtStatus;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Do actual output
|
|
//
|
|
LogInfo.OutputBuffer[0] = '\0';
|
|
LogOut(szBuf, Wow64LogFlags);
|
|
LogOut("\r\n", Wow64LogFlags);
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
WOW64LOGAPI
|
|
NTSTATUS
|
|
Wow64LogSystemService(
|
|
IN PTHUNK_LOG_CONTEXT ThunkLogContext)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Logs information for the specified system service.
|
|
|
|
Arguments:
|
|
|
|
LogContext - Thunk API log context
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus;
|
|
PTHUNK_DEBUG_INFO ThunkDebugInfo;
|
|
ULONG_PTR TableNumber = ThunkLogContext->TableNumber;
|
|
ULONG_PTR ServiceNumber = ThunkLogContext->ServiceNumber;
|
|
UINT_PTR LogFullInfo;
|
|
PAPI_CATEGORY_MAPPING ApiCategoryMapping;
|
|
|
|
//
|
|
// Use try except !!
|
|
//
|
|
|
|
_try
|
|
{
|
|
switch(TableNumber)
|
|
{
|
|
case WHNT32_INDEX:
|
|
if (!LF_NTBASE_ENABLED(Wow64LogFlags))
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
LogFullInfo = (Wow64LogFlags & LF_NTBASE_FULL);
|
|
ThunkDebugInfo = (PTHUNK_DEBUG_INFO)LogNtBase[ServiceNumber];
|
|
ApiCategoryMapping = (PAPI_CATEGORY_MAPPING)(ApiInfoNtBase[ServiceNumber]);
|
|
|
|
if( LF_CATLOG_ENABLED(Wow64LogFlags) )
|
|
{
|
|
if(NULL == ApiCategoryMapping)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
{
|
|
// api enabled check
|
|
if( 0 == (ApiCategoryMapping->ApiFlags & APIFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// category enabled check
|
|
if( 0 == (Wow64ApiCategories[ApiCategoryMapping->ApiCategoryIndex].CategoryFlags & CATFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// log on fail check
|
|
if( APIFLAG_LOGONFAIL == (ApiCategoryMapping->ApiFlags & APIFLAG_LOGONFAIL) )
|
|
{
|
|
if( FALSE == ThunkLogContext->ServiceReturn )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if( NT_SUCCESS(ThunkLogContext->ReturnResult) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WHCON_INDEX:
|
|
if (!LF_NTCON_ENABLED(Wow64LogFlags) || LogConsole == NULL)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
LogFullInfo = (Wow64LogFlags & LF_NTCON_FULL);
|
|
ThunkDebugInfo = (PTHUNK_DEBUG_INFO)LogConsole[ServiceNumber];
|
|
ApiCategoryMapping = (PAPI_CATEGORY_MAPPING)(ApiInfoConsole[ServiceNumber]);
|
|
|
|
if( LF_CATLOG_ENABLED(Wow64LogFlags) )
|
|
{
|
|
if(NULL == ApiCategoryMapping)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
{
|
|
// api enabled check
|
|
if( 0 == (ApiCategoryMapping->ApiFlags & APIFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// category enabled check
|
|
if( 0 == (Wow64ApiCategories[ApiCategoryMapping->ApiCategoryIndex].CategoryFlags & CATFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// log on fail check
|
|
if( APIFLAG_LOGONFAIL == (ApiCategoryMapping->ApiFlags & APIFLAG_LOGONFAIL) )
|
|
{
|
|
if( FALSE == ThunkLogContext->ServiceReturn )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if( NT_SUCCESS(ThunkLogContext->ReturnResult) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WHWIN32_INDEX:
|
|
if (!LF_WIN32_ENABLED(Wow64LogFlags) || LogWin32 == NULL)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
LogFullInfo = (Wow64LogFlags & LF_WIN32_FULL);
|
|
ThunkDebugInfo = (PTHUNK_DEBUG_INFO)LogWin32[ServiceNumber];
|
|
ApiCategoryMapping = (PAPI_CATEGORY_MAPPING)(ApiInfoWin32[ServiceNumber]);
|
|
|
|
if( LF_CATLOG_ENABLED(Wow64LogFlags) )
|
|
{
|
|
if(NULL == ApiCategoryMapping)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
{
|
|
// api enabled check
|
|
if( 0 == (ApiCategoryMapping->ApiFlags & APIFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// category enabled check
|
|
if( 0 == (Wow64ApiCategories[ApiCategoryMapping->ApiCategoryIndex].CategoryFlags & CATFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// log on fail check
|
|
if( APIFLAG_LOGONFAIL == (ApiCategoryMapping->ApiFlags & APIFLAG_LOGONFAIL) )
|
|
{
|
|
if( FALSE == ThunkLogContext->ServiceReturn )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if( NT_SUCCESS(ThunkLogContext->ReturnResult) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WHBASE_INDEX:
|
|
if (!LF_BASE_ENABLED(Wow64LogFlags))
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
LogFullInfo = (Wow64LogFlags & LF_BASE_FULL);
|
|
ThunkDebugInfo = (PTHUNK_DEBUG_INFO)LogBase[ServiceNumber];
|
|
ApiCategoryMapping = (PAPI_CATEGORY_MAPPING)(ApiInfoBase[ServiceNumber]);
|
|
|
|
if( LF_CATLOG_ENABLED(Wow64LogFlags) )
|
|
{
|
|
if(NULL == ApiCategoryMapping)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
{
|
|
// api enabled check
|
|
if( 0 == (ApiCategoryMapping->ApiFlags & APIFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// category enabled check
|
|
if( 0 == (Wow64ApiCategories[ApiCategoryMapping->ApiCategoryIndex].CategoryFlags & CATFLAG_ENABLED) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// log on fail check
|
|
if( APIFLAG_LOGONFAIL == (ApiCategoryMapping->ApiFlags & APIFLAG_LOGONFAIL) )
|
|
{
|
|
if( FALSE == ThunkLogContext->ServiceReturn )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if( NT_SUCCESS(ThunkLogContext->ReturnResult) )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: // invalid service table
|
|
WOW64LOGOUTPUT((LF_ERROR, "Wow64LogSystemService: Not supported table number - %lx\n", TableNumber));
|
|
return STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
NtStatus = LogThunkApi(ThunkLogContext,
|
|
ThunkDebugInfo,
|
|
LogFullInfo);
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WOW64LOGOUTPUT((LF_EXCEPTION, "Wow64LogSystemService : Invalid Service ServiceTable = %lx, ServiceNumber = %lx. Status=%lx\n",
|
|
TableNumber, ServiceNumber, GetExceptionCode()));
|
|
NtStatus = GetExceptionCode();
|
|
}
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DATA TYPE LOGGING ROUTINES
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS
|
|
LogTypeValue(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as ULONG
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%lx ",
|
|
FieldName,
|
|
(ULONG)Data);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogTypeUnicodeString(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as UNICODE_STRING32
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
UNICODE_STRING32 *Name32;
|
|
PWCHAR Buffer = L" ";
|
|
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Name32 = (UNICODE_STRING32 *)Data;
|
|
if (Data > 0xffff)
|
|
{
|
|
if (Name32->Buffer)
|
|
{
|
|
Buffer = (PWCHAR)Name32->Buffer;
|
|
}
|
|
if (Name32->Length && Name32->Buffer > 0xffff) {
|
|
return LogFormat(LogInfo,
|
|
"%s=%ws ",
|
|
FieldName,
|
|
Buffer);
|
|
} else {
|
|
return LogFormat(LogInfo,
|
|
"%s={L=%x,M=%x,B=%x}",
|
|
FieldName,
|
|
Name32->Length,
|
|
Name32->MaximumLength,
|
|
Name32->Buffer);
|
|
}
|
|
}
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%x",
|
|
FieldName,
|
|
Name32);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LogTypePULongInOut(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as PULONG
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
return LogFormat(LogInfo,
|
|
"[%s-%lx]=%lx ",
|
|
FieldName,
|
|
(ULONG)Data,
|
|
((PULONG)Data ? *((PULONG)Data) : 0));
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogTypePULongOut(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as PULONG (Out field)
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
return LogFormat(LogInfo,
|
|
"[%s-%lx]=%lx ",
|
|
FieldName,
|
|
(PULONG)Data,
|
|
((PULONG)Data ? *(PULONG)Data : 0));
|
|
}
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%lx ",
|
|
FieldName,
|
|
(PULONG)Data);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LogTypeObjectAttrbiutes(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as POBJECT_ATTRIBUTES
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
NT32OBJECT_ATTRIBUTES *ObjA32;
|
|
UNICODE_STRING32 *ObjectName = NULL;
|
|
PWCHAR Buffer = L"";
|
|
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ObjA32 = (NT32OBJECT_ATTRIBUTES *)Data;
|
|
if (ObjA32)
|
|
{
|
|
ObjectName = (UNICODE_STRING32 *)ObjA32->ObjectName;
|
|
if (ObjectName)
|
|
{
|
|
if (ObjectName->Buffer)
|
|
{
|
|
Buffer = (PWCHAR)ObjectName->Buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%lx {N=%ws,A=%lx} ",
|
|
FieldName,
|
|
(PULONG)Data,
|
|
Buffer,
|
|
(ObjA32 ? ObjA32->Attributes : 0));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LogTypeIoStatusBlock(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as IO_STATUS_BLOCK
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
PIO_STATUS_BLOCK32 StatusBlock32 = (PIO_STATUS_BLOCK32)Data;
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s={S=%lx,I=%lx} ",
|
|
FieldName,
|
|
(PULONG)Data,
|
|
(StatusBlock32 ? StatusBlock32->Status : 0),
|
|
(StatusBlock32 ? StatusBlock32->Information : 0));
|
|
}
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%lx ",
|
|
FieldName,
|
|
(PULONG)Data);
|
|
}
|
|
|
|
NTSTATUS
|
|
LogTypePWStr(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as PWSTR
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
ULONG_PTR i;
|
|
WCHAR Buffer[ 14 ];
|
|
PWSTR String = (PWSTR) Data;
|
|
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Sometime this type is treated as a pointer
|
|
// to WCHARs without NULL terminating it, like
|
|
// how it's used in NtGdiExtTextOutW, so let's dump
|
|
// a minimal string
|
|
//
|
|
if (Data)
|
|
{
|
|
i = 0;
|
|
while((i < ((sizeof(Buffer) / sizeof(WCHAR)) - 4)) && (String[i]))
|
|
{
|
|
Buffer[i] = String[i];
|
|
i++;
|
|
}
|
|
|
|
if (i == ((sizeof(Buffer) / sizeof(WCHAR)) - 4))
|
|
{
|
|
Buffer[i++] = L'.';
|
|
Buffer[i++] = L'.';
|
|
Buffer[i++] = L'.';
|
|
}
|
|
Buffer[i++] = UNICODE_NULL;
|
|
}
|
|
|
|
|
|
return LogFormat(LogInfo,
|
|
"%s=%ws ",
|
|
FieldName,
|
|
(Data > 0xffff) ? Buffer : L"");
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogTypePRectIn(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as PWSTR
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (Data)
|
|
{
|
|
PRECT Rect = (PRECT)Data;
|
|
return LogFormat(LogInfo,
|
|
"%s={%lx,%lx,%lx,%lx} ",
|
|
FieldName,
|
|
Rect->left, Rect->top, Rect->right, Rect->bottom);
|
|
|
|
}
|
|
|
|
return LogTypeValue(LogInfo,
|
|
Data,
|
|
FieldName,
|
|
ServiceReturn);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LogTypePLargeIntegerIn(
|
|
IN OUT PLOGINFO LogInfo,
|
|
IN ULONG_PTR Data,
|
|
IN PSZ FieldName,
|
|
IN BOOLEAN ServiceReturn)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log Data as PLARGE_INTEGER
|
|
|
|
Arguments:
|
|
|
|
|
|
LogInfo - Output log buffer
|
|
Data - Value to log
|
|
FieldName - Descriptive name of value to log
|
|
ServiceReturn - TRUE if called after the thunk API has executed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
--*/
|
|
{
|
|
if (ServiceReturn)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (Data)
|
|
{
|
|
NT32ULARGE_INTEGER *ULargeInt = (NT32ULARGE_INTEGER *)Data;
|
|
return LogFormat(LogInfo,
|
|
"%s={H=%lx,L=%lx} ",
|
|
FieldName,
|
|
ULargeInt->HighPart, ULargeInt->LowPart);
|
|
|
|
}
|
|
|
|
return LogTypeValue(LogInfo,
|
|
Data,
|
|
FieldName,
|
|
ServiceReturn);
|
|
}
|