////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // Generates a message using "pid", "message" and "parameter" and sends it back to userland throught // a filter communication port. // Parameters : // _in_opt_ ULONG pid : Process ID from which the logs are produced. // _in_opt_ PWCHAR message : Message (function name most of the time). // _in_opt_ PWCHAR parameter : Function args. // Return value : // NTSTATUS : FltSendMessage return value. // Process : // - Retrieves the process name from the pid and saves the whole data into an ANSI string. // - Generates an ANSI string with the message, with the process name, pid, and function name, and the // - generic "parameter" parameter. The resulting output will basically follow this scheme: // "pid","proces_name","function_name","FAILED/SUCCESS(0/1)","return_value","number_of_arguments","argument1->value","argument2->value"... // - Uses the "mutex" mutex to avoid concurrency when using the FltSendMessage() function. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS sendLogs(ULONG pid, PWCHAR message, PWCHAR parameter) { NTSTATUS status = STATUS_SUCCESS; CHAR buf[MAXSIZE]; UNICODE_STRING processName; ULONG sizeBuf; LARGE_INTEGER timeout; timeout.QuadPart = -((LONGLONG)0.5*10*1000*1000); if(message == NULL) return STATUS_INVALID_PARAMETER; #ifdef DEBUG DbgPrint("SendLogs\n"); #endif processName.Length = 0; processName.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR); processName.Buffer = ExAllocatePoolWithTag(NonPagedPool, processName.MaximumLength, PROCNAME_TAG); if(!processName.Buffer) { KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout); KeReleaseMutex(&mutex, FALSE); return STATUS_NO_MEMORY; } status = getProcNameByPID(pid, &processName); if(!NT_SUCCESS(status)) { KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } status = RtlStringCbPrintfA(buf, MAXSIZE, "%d,%wZ,%ws,%ws\n", pid, &processName, message, parameter); if(!NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } status = RtlStringCbLengthA(buf, MAXSIZE, &sizeBuf); if(!NT_SUCCESS(status)) { KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); #ifdef DEBUG DbgPrint("\tmsg : %s\n", buf); #endif status = FltSendMessage(filter, &clientPort, buf, sizeBuf, NULL, 0, NULL); if(status == STATUS_TIMEOUT) DbgPrint("STATUS_TIMEOUT !!\n"); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); #ifdef DEBUG if(!NT_SUCCESS(status)) DbgPrint("return : 0x%08x\n", status); #endif DEBUG return status; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // Generates a message using "pid", "message" and "parameter" and sends it back to userland throught // a filter communication port. // Parameters : // _in_opt_ ULONG pid : Process ID from which the logs are produced. // _in_opt_ PWCHAR message : Message (function name most of the time). // _in_opt_ PWCHAR parameter : Function args. // Return value : // NTSTATUS : FltSendMessage return value. // Process : // - Retrieves the process name from the pid and saves the whole data into an ANSI string. // - Generates an ANSI string with the message, with the process name, pid, and function name, and the // - generic "parameter" parameter. The resulting output will basically follow this scheme: // "pid","process_name","function_name","FAILED/SUCCESS/BLOCKED(0/1/2)","return_value","number_of_arguments","argument1->value","argument2->value"... // - Uses the "mutex" mutex to avoid concurrency when using the FltSendMessage() function. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS sendLogs(ULONG pid, PWCHAR message, PWCHAR parameter) { NTSTATUS status = STATUS_SUCCESS; CHAR buf[MAXSIZE]; UNICODE_STRING processName; ULONG sizeBuf; if(message == NULL) return STATUS_INVALID_PARAMETER; processName.Length = 0; processName.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR); processName.Buffer = ExAllocatePoolWithTag(NonPagedPool, processName.MaximumLength, PROCNAME_TAG); if(!processName.Buffer) { DbgPrint("ProcessName.Buffer error\n"); KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL); KeReleaseMutex(&mutex, FALSE); return STATUS_NO_MEMORY; } status = getProcNameByPID(pid, &processName); if(!NT_SUCCESS(status)) { DbgPrint("getProcNameByPID() error\n"); KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } status = RtlStringCbPrintfA(buf, MAXSIZE, "%d,%wZ,%ws,%ws\n", pid, &processName, message, parameter); if(!NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { DbgPrint("RtlStringCbPrintfA() error\n"); KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } status = RtlStringCbLengthA(buf, MAXSIZE, &sizeBuf); if(!NT_SUCCESS(status)) { DbgPrint("RtlStringCbLengthA() error\n"); KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; } KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL); status = FltSendMessage(filter, &clientPort, buf, sizeBuf, NULL, 0, NULL); KeReleaseMutex(&mutex, FALSE); ExFreePool(processName.Buffer); return status; }