2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "AFSCommon.h"
38 AFSDbgLogMsg( IN ULONG Subsystem,
44 NTSTATUS ntStatus = STATUS_SUCCESS;
46 ULONG ulBytesWritten = 0;
47 BOOLEAN bReleaseLock = FALSE;
48 char *pCurrentTrace = NULL;
53 if( AFSDbgBuffer == NULL)
56 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
60 (Subsystem & AFSTraceComponent) == 0)
64 // Not tracing this subsystem
67 try_return( ntStatus);
71 Level > AFSTraceLevel)
75 // Not tracing this level
78 try_return( ntStatus);
81 AFSAcquireExcl( &AFSDbgLogLock,
87 // Check again under lock
90 if( AFSDbgBuffer == NULL)
93 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
96 if( AFSDbgLogRemainingLength < 255)
99 AFSDbgLogRemainingLength = AFSDbgBufferLength;
101 AFSDbgCurrentBuffer = AFSDbgBuffer;
103 SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED);
106 pCurrentTrace = AFSDbgCurrentBuffer;
108 RtlStringCchPrintfA( AFSDbgCurrentBuffer,
113 AFSDbgCurrentBuffer += 9;
115 AFSDbgLogRemainingLength -= 9;
117 va_start( va_args, Format);
119 ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer,
120 AFSDbgLogRemainingLength,
124 if( ntStatus == STATUS_BUFFER_OVERFLOW)
127 RtlZeroMemory( AFSDbgCurrentBuffer,
128 AFSDbgLogRemainingLength);
130 AFSDbgLogRemainingLength = AFSDbgBufferLength;
132 AFSDbgCurrentBuffer = AFSDbgBuffer;
134 SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED);
136 pCurrentTrace = AFSDbgCurrentBuffer;
138 RtlStringCchPrintfA( AFSDbgCurrentBuffer,
143 AFSDbgCurrentBuffer += 9;
145 AFSDbgLogRemainingLength -= 9;
147 ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer,
148 AFSDbgLogRemainingLength,
153 if( NT_SUCCESS( ntStatus))
156 RtlStringCbLengthA( AFSDbgCurrentBuffer,
157 AFSDbgLogRemainingLength,
158 (size_t *)&ulBytesWritten);
160 AFSDbgCurrentBuffer += ulBytesWritten;
162 AFSDbgLogRemainingLength -= ulBytesWritten;
167 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_TRACE_TO_DEBUGGER) &&
168 pCurrentTrace != NULL)
171 DbgPrint( pCurrentTrace);
179 AFSReleaseResource( &AFSDbgLogLock);
187 AFSInitializeDbgLog()
190 NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
192 AFSAcquireExcl( &AFSDbgLogLock,
195 if( AFSDbgBufferLength > 0)
198 AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool,
200 AFS_GENERIC_MEMORY_19_TAG);
202 if( AFSDbgBuffer != NULL)
205 AFSDbgCurrentBuffer = AFSDbgBuffer;
207 AFSDbgLogRemainingLength = AFSDbgBufferLength;
209 ntStatus = STATUS_SUCCESS;
211 InterlockedCompareExchangePointer( (PVOID *)&AFSDebugTraceFnc,
212 (void *)AFSDbgLogMsg,
217 AFSReleaseResource( &AFSDbgLogLock);
219 if( NT_SUCCESS( ntStatus))
221 AFSTagInitialLogEntry();
231 NTSTATUS ntStatus = STATUS_SUCCESS;
233 AFSAcquireExcl( &AFSDbgLogLock,
236 if( AFSDbgBuffer != NULL)
239 ExFreePool( AFSDbgBuffer);
244 AFSDbgCurrentBuffer = NULL;
246 AFSDbgLogRemainingLength = 0;
248 AFSReleaseResource( &AFSDbgLogLock);
254 AFSConfigureTrace( IN AFSTraceConfigCB *TraceInfo)
257 NTSTATUS ntStatus = STATUS_SUCCESS;
258 UNICODE_STRING uniString;
263 AFSAcquireExcl( &AFSDbgLogLock,
266 if( TraceInfo->TraceLevel == AFSTraceLevel &&
267 TraceInfo->TraceBufferLength == AFSDbgBufferLength &&
268 TraceInfo->Subsystem == AFSTraceComponent &&
269 TraceInfo->DebugFlags == AFSDebugFlags)
276 try_return( ntStatus);
280 // Go update the registry with the new entries
283 if( TraceInfo->TraceLevel != (ULONG)-1 &&
284 TraceInfo->TraceLevel != AFSTraceLevel)
287 AFSTraceLevel = TraceInfo->TraceLevel;
289 RtlInitUnicodeString( &uniString,
290 AFS_REG_TRACE_LEVEL);
292 ntStatus = AFSUpdateRegistryParameter( &uniString,
294 &TraceInfo->TraceLevel,
297 if( !NT_SUCCESS( ntStatus))
300 DbgPrint("AFSConfigureTrace Failed to set debug level in registry Status %08lX\n", ntStatus);
304 if( TraceInfo->Subsystem != (ULONG)-1 &&
305 TraceInfo->Subsystem != AFSTraceComponent)
308 AFSTraceComponent = TraceInfo->Subsystem;
310 RtlInitUnicodeString( &uniString,
311 AFS_REG_TRACE_SUBSYSTEM);
313 ntStatus = AFSUpdateRegistryParameter( &uniString,
315 &TraceInfo->Subsystem,
318 if( !NT_SUCCESS( ntStatus))
321 DbgPrint("AFSConfigureTrace Failed to set debug subsystem in registry Status %08lX\n", ntStatus);
325 if( TraceInfo->DebugFlags != (ULONG)-1 &&
326 TraceInfo->DebugFlags != AFSDebugFlags)
329 AFSDebugFlags = TraceInfo->DebugFlags;
331 RtlInitUnicodeString( &uniString,
332 AFS_REG_DEBUG_FLAGS);
334 ntStatus = AFSUpdateRegistryParameter( &uniString,
336 &TraceInfo->DebugFlags,
339 if( !NT_SUCCESS( ntStatus))
342 DbgPrint("AFSConfigureTrace Failed to set debug flags in registry Status %08lX\n", ntStatus);
346 if( TraceInfo->TraceBufferLength != (ULONG)-1 &&
347 TraceInfo->TraceBufferLength != AFSDbgBufferLength)
350 RtlInitUnicodeString( &uniString,
351 AFS_REG_TRACE_BUFFER_LENGTH);
353 ntStatus = AFSUpdateRegistryParameter( &uniString,
355 &TraceInfo->TraceBufferLength,
358 if( !NT_SUCCESS( ntStatus))
361 DbgPrint("AFSConfigureTrace Failed to set debug buffer length in registry Status %08lX\n", ntStatus);
364 AFSDbgBufferLength = TraceInfo->TraceBufferLength * 1024;
366 ClearFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED);
368 if( AFSDbgBuffer != NULL)
371 ExFreePool( AFSDbgBuffer);
375 AFSDbgCurrentBuffer = NULL;
377 AFSDbgLogRemainingLength = 0;
380 if( AFSDbgBufferLength > 0)
383 AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool,
385 AFS_GENERIC_MEMORY_20_TAG);
387 if( AFSDbgBuffer == NULL)
390 AFSDbgBufferLength = 0;
392 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
395 InterlockedCompareExchangePointer( (PVOID *)&AFSDebugTraceFnc,
396 (void *)AFSDbgLogMsg,
399 AFSDbgCurrentBuffer = AFSDbgBuffer;
401 AFSDbgLogRemainingLength = AFSDbgBufferLength;
403 AFSTagInitialLogEntry();
407 InterlockedCompareExchangePointer( (PVOID *)&AFSDebugTraceFnc,
409 (void *)AFSDbgLogMsg);
412 AFSConfigLibraryDebug();
417 AFSReleaseResource( &AFSDbgLogLock);
424 AFSGetTraceConfig( OUT AFSTraceConfigCB *TraceInfo)
426 NTSTATUS ntStatus = STATUS_SUCCESS;
431 AFSAcquireExcl( &AFSDbgLogLock,
434 TraceInfo->TraceLevel = AFSTraceLevel;
436 TraceInfo->TraceBufferLength = AFSDbgBufferLength;
438 TraceInfo->Subsystem = AFSTraceComponent;
440 TraceInfo->DebugFlags = AFSDebugFlags;
442 AFSReleaseResource( &AFSDbgLogLock);
449 AFSGetTraceBuffer( IN ULONG TraceBufferLength,
450 OUT void *TraceBuffer,
451 OUT ULONG_PTR *CopiedLength)
454 NTSTATUS ntStatus = STATUS_SUCCESS;
455 ULONG ulCopyLength = 0;
456 char *pCurrentLocation = NULL;
461 AFSAcquireShared( &AFSDbgLogLock,
464 if( TraceBufferLength < AFSDbgBufferLength)
467 try_return( ntStatus = STATUS_INVALID_PARAMETER);
471 // If we have wrapped then copy in the remaining portion
474 pCurrentLocation = (char *)TraceBuffer;
478 if( BooleanFlagOn( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED))
481 ulCopyLength = AFSDbgLogRemainingLength;
483 RtlCopyMemory( pCurrentLocation,
487 pCurrentLocation[ 0] = '0'; // The buffer is NULL terminated ...
489 pCurrentLocation += ulCopyLength;
491 *CopiedLength = ulCopyLength;
494 ulCopyLength = AFSDbgBufferLength - AFSDbgLogRemainingLength;
496 if( ulCopyLength > 0)
499 RtlCopyMemory( pCurrentLocation,
503 *CopiedLength += ulCopyLength;
508 AFSReleaseResource( &AFSDbgLogLock);
515 AFSTagInitialLogEntry()
518 LARGE_INTEGER liTime, liLocalTime;
519 TIME_FIELDS timeFields;
521 KeQuerySystemTime( &liTime);
523 ExSystemTimeToLocalTime( &liTime,
526 RtlTimeToTimeFields( &liLocalTime,
531 "AFS Log Initialized %d-%d-%d %d:%d Level %d Subsystems %08lX\n",
547 NTSTATUS ntStatus = STATUS_SUCCESS;
548 HANDLE hDirectory = NULL;
549 OBJECT_ATTRIBUTES stObjectAttribs;
550 IO_STATUS_BLOCK stIoStatus;
551 LARGE_INTEGER liTime, liLocalTime;
552 TIME_FIELDS timeFields;
553 ULONG ulBytesWritten = 0;
554 HANDLE hDumpFile = NULL;
555 ULONG ulBytesProcessed, ulCopyLength;
556 LARGE_INTEGER liOffset;
557 ULONG ulDumpLength = 0;
558 BOOLEAN bSetEvent = FALSE;
563 AFSAcquireShared( &AFSDbgLogLock,
566 ulDumpLength = AFSDbgBufferLength - AFSDbgLogRemainingLength;
568 AFSReleaseResource( &AFSDbgLogLock);
570 if( AFSDumpFileLocation.Length == 0 ||
571 AFSDumpFileLocation.Buffer == NULL ||
572 AFSDbgBufferLength == 0 ||
574 AFSDumpFileName.MaximumLength == 0 ||
575 AFSDumpFileName.Buffer == NULL ||
576 AFSDumpBuffer == NULL)
578 try_return( ntStatus);
582 // Go open the cache file
585 InitializeObjectAttributes( &stObjectAttribs,
586 &AFSDumpFileLocation,
587 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
591 ntStatus = ZwCreateFile( &hDirectory,
592 GENERIC_READ | GENERIC_WRITE,
597 FILE_SHARE_READ | FILE_SHARE_WRITE,
599 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
603 if( !NT_SUCCESS( ntStatus))
606 try_return( ntStatus);
609 ntStatus = KeWaitForSingleObject( &AFSDumpFileEvent,
615 if( !NT_SUCCESS( ntStatus))
618 try_return( ntStatus);
623 AFSDumpFileName.Length = 0;
625 RtlZeroMemory( AFSDumpFileName.Buffer,
626 AFSDumpFileName.MaximumLength);
628 KeQuerySystemTime( &liTime);
630 ExSystemTimeToLocalTime( &liTime,
633 RtlTimeToTimeFields( &liLocalTime,
636 ntStatus = RtlStringCchPrintfW( AFSDumpFileName.Buffer,
637 AFSDumpFileName.MaximumLength/sizeof( WCHAR),
638 L"AFSDumpFile %d.%d.%d %d.%d.%d.log",
646 if( !NT_SUCCESS( ntStatus))
648 try_return( ntStatus);
651 RtlStringCbLengthW( AFSDumpFileName.Buffer,
652 AFSDumpFileName.MaximumLength,
653 (size_t *)&ulBytesWritten);
655 AFSDumpFileName.Length = (USHORT)ulBytesWritten;
657 InitializeObjectAttributes( &stObjectAttribs,
659 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
663 ntStatus = ZwCreateFile( &hDumpFile,
664 GENERIC_READ | GENERIC_WRITE,
669 FILE_SHARE_READ | FILE_SHARE_WRITE,
671 FILE_SYNCHRONOUS_IO_NONALERT,
675 if( !NT_SUCCESS( ntStatus))
677 try_return( ntStatus);
681 // Write out the trace buffer
684 liOffset.QuadPart = 0;
686 ulBytesProcessed = 0;
688 while( ulBytesProcessed < ulDumpLength)
691 ulCopyLength = AFSDumpBufferLength;
693 if( ulCopyLength > ulDumpLength - ulBytesProcessed)
695 ulCopyLength = ulDumpLength - ulBytesProcessed;
698 RtlCopyMemory( AFSDumpBuffer,
699 (void *)((char *)AFSDbgBuffer + ulBytesProcessed),
702 ntStatus = ZwWriteFile( hDumpFile,
712 if( !NT_SUCCESS( ntStatus))
717 liOffset.QuadPart += ulCopyLength;
719 ulBytesProcessed += ulCopyLength;
724 if( hDumpFile != NULL)
729 if( hDirectory != NULL)
731 ZwClose( hDirectory);
736 KeSetEvent( &AFSDumpFileEvent,
746 AFSInitializeDumpFile()
749 NTSTATUS ntStatus = STATUS_SUCCESS;
754 KeInitializeEvent( &AFSDumpFileEvent,
755 SynchronizationEvent,
758 AFSDumpFileName.Length = 0;
759 AFSDumpFileName.Buffer = NULL;
760 AFSDumpFileName.MaximumLength = PAGE_SIZE;
762 AFSDumpFileName.Buffer = (WCHAR *)ExAllocatePoolWithTag( PagedPool,
763 AFSDumpFileName.MaximumLength,
764 AFS_GENERIC_MEMORY_28_TAG);
766 if( AFSDumpFileName.Buffer == NULL)
768 AFSDumpFileName.MaximumLength = 0;
770 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
773 AFSDumpBufferLength = 64 * 1024;
775 AFSDumpBuffer = ExAllocatePoolWithTag( PagedPool,
777 AFS_GENERIC_MEMORY_28_TAG);
779 if( AFSDumpBuffer == NULL)
782 ExFreePool( AFSDumpFileName.Buffer);
784 AFSDumpFileName.Buffer = NULL;
785 AFSDumpFileName.MaximumLength = 0;
787 AFSDumpBufferLength = 0;
789 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);