static void VMToolsLog(const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer _data) { LogHandler *data = _data; if (SHOULD_LOG(level, data)) { gchar *msg; data = data->inherited ? gDefaultData : data; msg = VMToolsLogFormat(message, domain, level, data); if (data->logger != NULL) { data->logger->logfn(domain, level, msg, data->logger); } else if (gErrorData->logger != NULL) { gErrorData->logger->logfn(domain, level, msg, gErrorData->logger); } g_free(msg); } if (IS_FATAL(level)) { VMToolsLogPanic(); } }
static void VMToolsLog(const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer _data) { LogHandler *data = _data; if (SHOULD_LOG(level, data)) { LogEntry *entry; data = data->inherited ? gDefaultData : data; entry = g_malloc0(sizeof(LogEntry)); if (entry) { entry->domain = domain ? g_strdup(domain) : NULL; if (domain && !entry->domain) { VMToolsLogPanic(); } entry->handler = data; entry->level = level; } if (gLogIOSuspended && data->needsFileIO) { if (gMaxCacheEntries == 0) { /* No way to log at this point, drop it */ VMToolsFreeLogEntry(entry); gDroppedLogCount++; goto exit; } entry->msg = VMToolsLogFormat(message, domain, level, data, TRUE); /* * Cache the log message */ if (!gCachedLogs) { /* * If gMaxCacheEntries > 1K, start with 1/4th size * to avoid frequent allocations */ gCachedLogs = g_ptr_array_sized_new(gMaxCacheEntries < 1024 ? gMaxCacheEntries : gMaxCacheEntries/4); if (!gCachedLogs) { VMToolsLogPanic(); } /* * Some builds use glib version 2.16.4 which does not * support g_ptr_array_set_free_func function */ } /* * We don't expect logging to be suspended for a long time, * so we can avoid putting a cap on cache size. However, we * still have a default cap of 4K messages, just to be safe. */ if (gCachedLogs->len < gMaxCacheEntries) { g_ptr_array_add(gCachedLogs, entry); } else { /* * Cache is full, drop the oldest log message. This is not * very efficient but we don't expect this to be a common * case anyway. */ LogEntry *oldest = g_ptr_array_remove_index(gCachedLogs, 0); VMToolsFreeLogEntry(oldest); gDroppedLogCount++; g_ptr_array_add(gCachedLogs, entry); } } else { entry->msg = VMToolsLogFormat(message, domain, level, data, FALSE); VMToolsLogMsg(entry, NULL); } } exit: if (IS_FATAL(level)) { VMToolsLogPanic(); } }
VOID SpyLogIrpCompletion ( __in PIRP Irp, __inout PRECORD_LIST RecordList ) /*++ Routine Description: Records the Irp necessary information according to LoggingFlags in RecordList. For any activity on the Irp path of a device being logged, this function should get called twice: once on the IRPs originating path and once on the IRPs completion path. Arguments: Irp - The Irp that contains the information we want to record. LoggingFlags - The flags that say what to log. RecordList - The PRECORD_LIST in which the Irp information is stored. Return Value: None. --*/ { PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_OBJECT deviceObject = pIrpStack->DeviceObject; PRECORD_IRP pRecordIrp; // // Process the log record // if (SHOULD_LOG( deviceObject )) { pRecordIrp = &RecordList->LogRecord.Record.RecordIrp; // // Record the information we use for a completion Irp. // pRecordIrp->ReturnStatus = Irp->IoStatus.Status; pRecordIrp->ReturnInformation = Irp->IoStatus.Information; KeQuerySystemTime(&pRecordIrp->CompletionTime); // // Add RecordList to our gOutputBufferList so that it gets up to // the user // SpyLog( RecordList ); } else { if (RecordList) { // // Context is set with a RECORD_LIST, but we are no longer // logging so free this record. // SpyFreeRecord( RecordList ); } } switch (pIrpStack->MajorFunction) { case IRP_MJ_CREATE: // // If the operation failed remove the name from the cache because // it is stale // if (!NT_SUCCESS(Irp->IoStatus.Status) && (pIrpStack->FileObject != NULL)) { SpyNameDelete(pIrpStack->FileObject); } break; case IRP_MJ_CLOSE: // // Always remove the name on close // SpyNameDelete(pIrpStack->FileObject); break; case IRP_MJ_SET_INFORMATION: // // If the operation was successful and it was a rename, always // remove the name. They can re-get it next time. // if (NT_SUCCESS(Irp->IoStatus.Status) && (FileRenameInformation == pIrpStack->Parameters.SetFile.FileInformationClass)) { SpyNameDelete(pIrpStack->FileObject); } break; } }