Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

smbtrsup.c File Reference

#include <ntsrv.h>
#include <smbtrace.h>
#include <smbtrsup.h>

Go to the source code of this file.

Classes

struct  _SMBTRACE_QUEUE_ENTRY
struct  _INSTANCE_DATA
struct  _TRACE_DEREFERENCE_ITEM

Defines

#define _SMBTRSUP_SYS_   1
#define TrPrint(x)
#define PAGED_CODE_CHECK()
#define ACQUIRE_SPIN_LOCK(a, b)   KeAcquireSpinLock(a, b)
#define RELEASE_SPIN_LOCK(a, b)   KeReleaseSpinLock(a, b)
#define LOCK_INC_ID(var)
#define LOCK_ZERO_ID(var)
#define ID(field)   (SmbTraceData[Component].field)
#define ACL_LENGTH
#define NUMBER_OF_BLOCKING_OBJECTS   4
#define INDEX_WAIT_TERMINATIONEVENT   0
#define INDEX_WAIT_APPTERMINATIONEVENT   1
#define INDEX_WAIT_NEEDMEMORYEVENT   2
#define INDEX_WAIT_QUEUESEMAPHORE   3
#define STATUS_WAIT_TERMINATIONEVENT   STATUS_WAIT_0
#define STATUS_WAIT_APPTERMINATIONEVENT   STATUS_WAIT_1
#define STATUS_WAIT_NEEDMEMORYEVENT   STATUS_WAIT_2
#define STATUS_WAIT_QUEUESEMAPHORE   STATUS_WAIT_3

Typedefs

typedef enum _SMBTRACE_STATE SMBTRACE_STATE
typedef _SMBTRACE_QUEUE_ENTRY SMBTRACE_QUEUE_ENTRY
typedef _SMBTRACE_QUEUE_ENTRYPSMBTRACE_QUEUE_ENTRY
typedef _INSTANCE_DATA INSTANCE_DATA
typedef _TRACE_DEREFERENCE_ITEM TRACE_DEREFERENCE_ITEM
typedef _TRACE_DEREFERENCE_ITEMPTRACE_DEREFERENCE_ITEM

Enumerations

enum  _SMBTRACE_STATE {
  TraceStopped, TraceStarting, TraceStartStopFile, TraceStartStopNull,
  TraceAppWaiting, TraceRunning, TraceStopping
}

Functions

BOOLEAN SmbTraceReferenceHeap (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceDereferenceHeap (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceDisconnect (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceEmptyQueue (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceThreadEntry (IN PVOID Context)
NTSTATUS SmbTraceFreeMemory (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceToClient (IN PVOID Smb, IN CLONG SmbLength, IN PVOID SmbAddress, IN SMBTRACE_COMPONENT Component)
ULONG SmbTraceMdlLength (IN PMDL Mdl)
VOID SmbTraceCopyMdlContiguous (OUT PVOID Destination, IN PMDL Mdl, IN ULONG Length)
VOID SmbTraceDeferredDereferenceHeap (IN PVOID Context)
NTSTATUS SmbTraceInitialize (IN SMBTRACE_COMPONENT Component)
VOID SmbTraceTerminate (IN SMBTRACE_COMPONENT Component)
NTSTATUS SmbTraceStart (IN ULONG InputBufferLength, IN ULONG OutputBufferLength, IN OUT PVOID ConfigInOut, IN PFILE_OBJECT FileObject, IN SMBTRACE_COMPONENT Component)
NTSTATUS SmbTraceStop (IN PFILE_OBJECT FileObject OPTIONAL, IN SMBTRACE_COMPONENT Component)
VOID SmbTraceCompleteSrv (IN PMDL SmbMdl, IN PVOID Smb, IN CLONG SmbLength)
VOID SmbTraceCompleteRdr (IN PMDL SmbMdl, IN PVOID Smb, IN CLONG SmbLength)

Variables

INSTANCE_DATA SmbTraceData []
BOOLEAN SmbTraceActive [] = {FALSE, FALSE}
BOOLEAN SmbTraceTransitioning [] = {FALSE, FALSE}
HANDLE SmbTraceDiscardableCodeHandle = 0
HANDLE SmbTraceDiscardableDataHandle = 0


Define Documentation

#define _SMBTRSUP_SYS_   1
 

Definition at line 35 of file smbtrsup.c.

#define ACL_LENGTH
 

Value:

(ULONG)sizeof(ACL) + \ (ULONG)sizeof(ACCESS_ALLOWED_ACE) + \ sizeof(LUID) + \ 8

Referenced by SmbTraceStart().

#define ACQUIRE_SPIN_LOCK a,
 )     KeAcquireSpinLock(a, b)
 

Definition at line 84 of file smbtrsup.c.

Referenced by SmbTraceDereferenceHeap(), and SmbTraceReferenceHeap().

#define ID field   )     (SmbTraceData[Component].field)
 

Definition at line 151 of file smbtrsup.c.

Referenced by IopSetDefaultGateway(), IopTCPQueryInformationEx(), IopTCPSetInformationEx(), LoadBitmapA(), LoadCursorA(), LoadIconA(), LoadImageA(), SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceDereferenceHeap(), SmbTraceDisconnect(), SmbTraceEmptyQueue(), SmbTraceFreeMemory(), SmbTraceInitialize(), SmbTraceReferenceHeap(), SmbTraceStart(), SmbTraceStop(), SmbTraceTerminate(), SmbTraceThreadEntry(), SmbTraceToClient(), WOWFindResourceExWCover(), WOWLoadBitmapA(), and xxxContScroll().

#define INDEX_WAIT_APPTERMINATIONEVENT   1
 

Referenced by SmbTraceThreadEntry().

#define INDEX_WAIT_NEEDMEMORYEVENT   2
 

Referenced by SmbTraceThreadEntry().

#define INDEX_WAIT_QUEUESEMAPHORE   3
 

Referenced by SmbTraceThreadEntry().

#define INDEX_WAIT_TERMINATIONEVENT   0
 

Referenced by SmbTraceThreadEntry().

#define LOCK_INC_ID var   ) 
 

Value:

ExInterlockedAddUlong( (PULONG)&ID(var), \ 1, &ID(var##Interlock) )

Definition at line 91 of file smbtrsup.c.

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceThreadEntry(), and SmbTraceToClient().

#define LOCK_ZERO_ID var   ) 
 

Value:

{ \ ID(var) = 0; \ }

Definition at line 98 of file smbtrsup.c.

Referenced by SmbTraceToClient().

#define NUMBER_OF_BLOCKING_OBJECTS   4
 

Referenced by SmbTraceThreadEntry().

 
#define PAGED_CODE_CHECK  ) 
 

Definition at line 69 of file smbtrsup.c.

#define RELEASE_SPIN_LOCK a,
 )     KeReleaseSpinLock(a, b)
 

Definition at line 85 of file smbtrsup.c.

Referenced by SmbTraceDereferenceHeap(), and SmbTraceReferenceHeap().

#define STATUS_WAIT_APPTERMINATIONEVENT   STATUS_WAIT_1
 

Referenced by SmbTraceThreadEntry().

#define STATUS_WAIT_NEEDMEMORYEVENT   STATUS_WAIT_2
 

Referenced by SmbTraceThreadEntry().

#define STATUS_WAIT_QUEUESEMAPHORE   STATUS_WAIT_3
 

Referenced by SmbTraceThreadEntry().

#define STATUS_WAIT_TERMINATIONEVENT   STATUS_WAIT_0
 

Referenced by SmbTraceThreadEntry().

#define TrPrint  ) 
 

Definition at line 42 of file smbtrsup.c.

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceDereferenceHeap(), SmbTraceDisconnect(), SmbTraceFreeMemory(), SmbTraceReferenceHeap(), SmbTraceStart(), SmbTraceStop(), SmbTraceThreadEntry(), and SmbTraceToClient().


Typedef Documentation

typedef struct _INSTANCE_DATA INSTANCE_DATA
 

typedef struct _SMBTRACE_QUEUE_ENTRY * PSMBTRACE_QUEUE_ENTRY
 

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceEmptyQueue(), and SmbTraceThreadEntry().

typedef struct _TRACE_DEREFERENCE_ITEM * PTRACE_DEREFERENCE_ITEM
 

Referenced by SmbTraceDeferredDereferenceHeap(), and SmbTraceDereferenceHeap().

typedef struct _SMBTRACE_QUEUE_ENTRY SMBTRACE_QUEUE_ENTRY
 

typedef enum _SMBTRACE_STATE SMBTRACE_STATE
 

typedef struct _TRACE_DEREFERENCE_ITEM TRACE_DEREFERENCE_ITEM
 


Enumeration Type Documentation

enum _SMBTRACE_STATE
 

Enumeration values:
TraceStopped 
TraceStarting 
TraceStartStopFile 
TraceStartStopNull 
TraceAppWaiting 
TraceRunning 
TraceStopping 

Definition at line 109 of file smbtrsup.c.

00109 { 00110 TraceStopped, // not running 00111 TraceStarting, // preparing to run 00112 TraceStartStopFile, // starting, but want to shut down immediately 00113 // because the FileObject closed 00114 TraceStartStopNull, // starting, but want to shut down immediately 00115 // because a new fsctl came in 00116 TraceAppWaiting, // waiting for application to die 00117 TraceRunning, // processing SMBs 00118 TraceStopping // waiting for smbtrace thread to stop 00119 } SMBTRACE_STATE;


Function Documentation

VOID SmbTraceCompleteRdr IN PMDL  SmbMdl,
IN PVOID  Smb,
IN CLONG  SmbLength
 

Definition at line 1456 of file smbtrsup.c.

References ASSERT, _SMBTRACE_QUEUE_ENTRY::Buffer, _SMBTRACE_QUEUE_ENTRY::BufferNonPaged, DISPATCH_LEVEL, ExAllocatePoolWithTag, ExFreePool(), ExInterlockedInsertTailList(), FALSE, ID, KeAttachProcess(), KeDetachProcess(), KeInitializeEvent, KeReleaseSemaphore(), KernelMode, KeSetEvent(), KeWaitForSingleObject(), _SMBTRACE_QUEUE_ENTRY::ListEntry, LOCK_INC_ID, NonPagedPool, NULL, PsGetCurrentProcess, PSMBTRACE_QUEUE_ENTRY, RtlAllocateHeap, SEMAPHORE_INCREMENT, _SMBTRACE_QUEUE_ENTRY::SmbAddress, _SMBTRACE_QUEUE_ENTRY::SmbLength, SmbTraceActive, SmbTraceCopyMdlContiguous(), SmbTraceDereferenceHeap(), SmbTraceMdlLength(), SmbTraceReferenceHeap(), TraceRunning, TrPrint, TRUE, UserRequest, and _SMBTRACE_QUEUE_ENTRY::WaitEvent.

01464 : 01465 01466 Redirector version 01467 01468 Snapshot an SMB and export it to the SmbTrace application. How 01469 this happens is determined by which mode (fast or slow) SmbTracing 01470 was requested in, and which context (DPC, Fsp or Fsd) the current 01471 thread is executing in. 01472 01473 Fast mode: the SMB is copied into shared memory and an entry for it 01474 is queued to the redirector SmbTrace thread, which asynchronously 01475 passes SMBs to the app. (When in DPC, the SMB is copied to non-paged 01476 pool instead of shared memory, and the SmbTrace thread deals with 01477 moving it to shared memory later.) If there is insufficient memory 01478 for anything (SMB, queue entry, etc.) the SMB is lost. 01479 01480 Slow mode: identical to Fast mode except that this thread waits 01481 until the server SmbTrace thread signals that the app has finished 01482 processing the SMB. Because each thread waits until its SMB has 01483 been completely processed, there is much less chance of running 01484 out of any resources. If at DPC level, we behave exactly as in the 01485 fast mode case, because it would be a Bad Thing to block this thread 01486 at DPC level. 01487 01488 The SMB is either contained in SmbMdl, or at address Smb with length 01489 SmbLength. 01490 01491 Arguments: 01492 01493 SmbMdl - an Mdl containing the SMB. 01494 01495 Smb - a pointer to the SMB. 01496 01497 SmbLength - the length of the SMB. 01498 01499 Return Value: 01500 01501 None 01502 01503 --*/ 01504 01505 { 01506 PSMBTRACE_QUEUE_ENTRY queueEntry; 01507 PVOID buffer; 01508 BOOLEAN ProcessAttached = FALSE; 01509 BOOLEAN AtDpcLevel; 01510 SMBTRACE_COMPONENT Component = SMBTRACE_REDIRECTOR; 01511 KEVENT WaitEvent; 01512 01513 // 01514 // This routine is redirector specific. 01515 // 01516 01517 ASSERT( ID(TraceState) == TraceRunning ); 01518 ASSERT( SmbTraceActive[SMBTRACE_REDIRECTOR] ); 01519 01520 // 01521 // We want either an Mdl, or a pointer and a length, or occasionally, 01522 // a completely NULL response 01523 // 01524 01525 ASSERT( ( SmbMdl == NULL && Smb != NULL && SmbLength != 0 ) 01526 || ( SmbMdl != NULL && Smb == NULL && SmbLength == 0 ) 01527 || ( SmbMdl == NULL && Smb == NULL && SmbLength == 0 ) ); 01528 01529 // 01530 // Ensure that SmbTrace really is still active and hence, the 01531 // shared memory is still around. 01532 // 01533 01534 if ( SmbTraceReferenceHeap( Component ) == FALSE ) { 01535 return; 01536 } 01537 01538 // 01539 // To avoid multiple system calls, we find out once and for all. 01540 // 01541 01542 AtDpcLevel = (BOOLEAN)(KeGetCurrentIrql() >= DISPATCH_LEVEL); 01543 01544 // 01545 // If the SMB is currently in an MDL, we don't yet have the length, 01546 // which we need to know how much memory to allocate. 01547 // 01548 01549 if ( SmbMdl != NULL ) { 01550 SmbLength = SmbTraceMdlLength(SmbMdl); 01551 } 01552 01553 // 01554 // If we are in slow mode, then we wait after queuing the SMB 01555 // to the SmbTrace thread. If we are set for fast mode we 01556 // garbage collect in case of no memory. If we're at DPC level, 01557 // we store the SMB in non-paged pool. 01558 // 01559 01560 if ( ID(SingleSmbMode) ) { 01561 KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE ); 01562 } 01563 01564 // 01565 // allocate queue entry 01566 // 01567 01568 queueEntry = ExAllocatePoolWithTag( 01569 NonPagedPool, 01570 sizeof(SMBTRACE_QUEUE_ENTRY), 01571 'tbmS' 01572 ); 01573 01574 if ( queueEntry == NULL ) { 01575 // No free memory, this SMB is lost. Record its loss. 01576 LOCK_INC_ID(SmbsLost); 01577 SmbTraceDereferenceHeap( Component ); 01578 return; 01579 } 01580 01581 // 01582 // allocate buffer for SMB, in non-paged pool or shared heap as 01583 // appropriate 01584 // 01585 01586 if ( AtDpcLevel ) { 01587 01588 buffer = ExAllocatePoolWithTag( NonPagedPool, SmbLength, 'tbmS' ); 01589 queueEntry->BufferNonPaged = TRUE; 01590 01591 } else { 01592 01593 if ( PsGetCurrentProcess() != ID(FspProcess) ) { 01594 KeAttachProcess(ID(FspProcess)); 01595 ProcessAttached = TRUE; 01596 } 01597 01598 buffer = RtlAllocateHeap( ID(PortMemoryHeap), 0, SmbLength ); 01599 queueEntry->BufferNonPaged = FALSE; 01600 01601 } 01602 01603 if ( buffer == NULL ) { 01604 01605 if ( ProcessAttached ) { 01606 KeDetachProcess(); 01607 } 01608 01609 // No free memory, this SMB is lost. Record its loss. 01610 LOCK_INC_ID(SmbsLost); 01611 01612 if (!ID(SingleSmbMode)) { 01613 01614 // 01615 // If it was shared memory we ran out of, encourage 01616 // some garbage collection. 01617 // 01618 if ( !queueEntry->BufferNonPaged ) { 01619 KeSetEvent( &ID(NeedMemoryEvent), 0, FALSE ); 01620 } 01621 } 01622 01623 ExFreePool( queueEntry ); 01624 SmbTraceDereferenceHeap( Component ); 01625 return; 01626 } 01627 01628 // 01629 // Copy the SMB to shared or non-paged memory pointed to by the 01630 // queue entry, keeping in mind whether it's in an Mdl or contiguous 01631 // to begin with, and also preserving the address of the real SMB... 01632 // 01633 01634 if ( SmbMdl != NULL ) { 01635 SmbTraceCopyMdlContiguous( buffer, SmbMdl, SmbLength ); 01636 queueEntry->SmbAddress = SmbMdl; 01637 } else { 01638 RtlCopyMemory( buffer, Smb, SmbLength ); 01639 queueEntry->SmbAddress = Smb; 01640 } 01641 01642 if ( ProcessAttached ) { 01643 KeDetachProcess(); 01644 } 01645 01646 queueEntry->SmbLength = SmbLength; 01647 queueEntry->Buffer = buffer; 01648 01649 // 01650 // In slow mode, we want to wait until the SMB has been eaten, 01651 // in fast mode, we don't want to pass the address of the real 01652 // SMB along, since the SMB is long gone by the time it gets 01653 // decoded and printed. 01654 // 01655 01656 if ( ID(SingleSmbMode) && !AtDpcLevel ) { 01657 queueEntry->WaitEvent = &WaitEvent; 01658 } else { 01659 queueEntry->WaitEvent = NULL; 01660 queueEntry->SmbAddress = NULL; 01661 } 01662 01663 // 01664 // ...queue the entry to the SmbTrace thread... 01665 // 01666 01667 ExInterlockedInsertTailList( 01668 &ID(Queue), 01669 &queueEntry->ListEntry, 01670 &ID(QueueInterlock) 01671 ); 01672 01673 KeReleaseSemaphore( 01674 &ID(QueueSemaphore), 01675 SEMAPHORE_INCREMENT, 01676 1, 01677 FALSE 01678 ); 01679 01680 // 01681 // ...and wait for the SMB to be eaten, in slow mode. 01682 // 01683 01684 if ( ID(SingleSmbMode) && !AtDpcLevel ) { 01685 TrPrint(( "%s!SmbTraceCompleteRdr: Slow mode wait\n", ID(ComponentName) )); 01686 KeWaitForSingleObject( 01687 &WaitEvent, 01688 UserRequest, 01689 KernelMode, 01690 FALSE, 01691 NULL 01692 ); 01693 TrPrint(( "%s!SmbTraceCompleteRdr: Slow mode wait done\n", ID(ComponentName) )); 01694 } 01695 01696 SmbTraceDereferenceHeap( Component ); 01697 01698 return; 01699 01700 } // SmbTraceCompleteRdr

VOID SmbTraceCompleteSrv IN PMDL  SmbMdl,
IN PVOID  Smb,
IN CLONG  SmbLength
 

Definition at line 1242 of file smbtrsup.c.

References ASSERT, _SMBTRACE_QUEUE_ENTRY::Buffer, _SMBTRACE_QUEUE_ENTRY::BufferNonPaged, DISPATCH_LEVEL, ExAllocatePoolWithTag, ExFreePool(), ExInterlockedInsertTailList(), FALSE, ID, KeInitializeEvent, KeReleaseSemaphore(), KernelMode, KeSetEvent(), KeWaitForSingleObject(), _SMBTRACE_QUEUE_ENTRY::ListEntry, LOCK_INC_ID, NonPagedPool, NULL, PAGED_CODE, PsGetCurrentProcess, PSMBTRACE_QUEUE_ENTRY, RtlAllocateHeap, SEMAPHORE_INCREMENT, _SMBTRACE_QUEUE_ENTRY::SmbAddress, _SMBTRACE_QUEUE_ENTRY::SmbLength, SmbTraceActive, SmbTraceCopyMdlContiguous(), SmbTraceDereferenceHeap(), SmbTraceMdlLength(), SmbTraceReferenceHeap(), TraceRunning, TrPrint, UserRequest, and _SMBTRACE_QUEUE_ENTRY::WaitEvent.

01250 : 01251 01252 Server version. 01253 01254 Snapshot an SMB and export it to the SmbTrace application. How 01255 this happens is determined by which mode (fast or slow) SmbTracing 01256 was requested in. In the server, it is easy to guarantee that when 01257 tracing, a thread is always executing in the Fsp. 01258 01259 Fast mode: the SMB is copied into shared memory and an entry for it 01260 is queued to the server SmbTrace thread, which asynchronously 01261 passes SMBs to the app. If there is insufficient memory 01262 for anything (SMB, queue entry, etc.) the SMB is lost. 01263 01264 Slow mode: identical to Fast mode except that this thread waits 01265 until the server SmbTrace thread signals that the app has finished 01266 processing the SMB. Because each thread waits until its SMB has 01267 been completely processed, there is much less chance of running 01268 out of any resources. 01269 01270 The SMB is either contained in SmbMdl, or at address Smb with length 01271 SmbLength. 01272 01273 Arguments: 01274 01275 SmbMdl - an Mdl containing the SMB. 01276 01277 Smb - a pointer to the SMB. 01278 01279 SmbLength - the length of the SMB. 01280 01281 Return Value: 01282 01283 None 01284 01285 --*/ 01286 01287 { 01288 PSMBTRACE_QUEUE_ENTRY queueEntry; 01289 PVOID buffer; 01290 SMBTRACE_COMPONENT Component = SMBTRACE_SERVER; 01291 KEVENT WaitEvent; 01292 01293 PAGED_CODE(); 01294 01295 // 01296 // This routine is server specific. 01297 // 01298 01299 ASSERT( ID(TraceState) == TraceRunning ); 01300 ASSERT( SmbTraceActive[SMBTRACE_SERVER] ); 01301 01302 // 01303 // We want either an Mdl, or a pointer and a length, or occasionally, 01304 // a completely NULL response. 01305 // 01306 01307 ASSERT( ( SmbMdl == NULL && Smb != NULL && SmbLength != 0 ) 01308 || ( SmbMdl != NULL && Smb == NULL && SmbLength == 0 ) 01309 || ( SmbMdl == NULL && Smb == NULL && SmbLength == 0 ) ); 01310 01311 // 01312 // We've taken pains not to be at DPC level and to be in 01313 // the Fsp context too, for that matter. 01314 // 01315 01316 ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL); 01317 ASSERT( PsGetCurrentProcess() == ID(FspProcess) ); 01318 01319 // 01320 // Ensure that SmbTrace really is still active and hence, the 01321 // shared memory is still around. 01322 // 01323 01324 if ( SmbTraceReferenceHeap( Component ) == FALSE ) { 01325 return; 01326 } 01327 01328 // 01329 // If the SMB is currently in an MDL, we don't yet have the length, 01330 // which we need, to know how much memory to allocate. 01331 // 01332 01333 if ( SmbMdl != NULL ) { 01334 SmbLength = SmbTraceMdlLength(SmbMdl); 01335 } 01336 01337 // 01338 // If we are in slow mode, then we wait after queuing the SMB 01339 // to the SmbTrace thread. If we are set for fast mode we 01340 // garbage collect in case of no memory. 01341 // 01342 01343 if ( ID(SingleSmbMode) ) { 01344 KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE ); 01345 } 01346 01347 queueEntry = ExAllocatePoolWithTag( NonPagedPool, 01348 sizeof(SMBTRACE_QUEUE_ENTRY), 01349 'tbmS' 01350 ); 01351 01352 if ( queueEntry == NULL ) { 01353 // No free memory, this SMB is lost. Record its loss. 01354 LOCK_INC_ID(SmbsLost); 01355 SmbTraceDereferenceHeap( Component ); 01356 return; 01357 } 01358 01359 // 01360 // Allocate the required amount of memory in our heap 01361 // in the shared memory. 01362 // 01363 01364 buffer = RtlAllocateHeap( ID(PortMemoryHeap), 0, SmbLength ); 01365 01366 if ( buffer == NULL ) { 01367 // No free memory, this SMB is lost. Record its loss. 01368 // Very unlikely in slow mode. 01369 LOCK_INC_ID(SmbsLost); 01370 ExFreePool( queueEntry ); 01371 01372 if ( !ID(SingleSmbMode) ) { 01373 // 01374 // Encourage some garbage collection. 01375 // 01376 KeSetEvent( &ID(NeedMemoryEvent), 0, FALSE ); 01377 } 01378 01379 SmbTraceDereferenceHeap( Component ); 01380 return; 01381 } 01382 01383 // 01384 // Copy the SMB to shared memory pointed to by the queue entry, 01385 // keeping in mind whether it's in an Mdl or contiguous to begin 01386 // with, and also preserving the address of the real SMB... 01387 // 01388 01389 if ( SmbMdl != NULL ) { 01390 SmbTraceCopyMdlContiguous( buffer, SmbMdl, SmbLength ); 01391 queueEntry->SmbAddress = SmbMdl; 01392 } else { 01393 RtlCopyMemory( buffer, Smb, SmbLength ); 01394 queueEntry->SmbAddress = Smb; 01395 } 01396 01397 queueEntry->SmbLength = SmbLength; 01398 queueEntry->Buffer = buffer; 01399 queueEntry->BufferNonPaged = FALSE; 01400 01401 // 01402 // In slow mode, we want to wait until the SMB has been eaten, 01403 // in fast mode, we don't want to pass the address of the real 01404 // SMB along, since the SMB is long gone by the time it gets 01405 // decoded and printed. 01406 // 01407 01408 if ( ID(SingleSmbMode) ) { 01409 queueEntry->WaitEvent = &WaitEvent; 01410 } else { 01411 queueEntry->WaitEvent = NULL; 01412 queueEntry->SmbAddress = NULL; 01413 } 01414 01415 // 01416 // ...queue the entry to the SmbTrace thread... 01417 // 01418 01419 ExInterlockedInsertTailList( 01420 &ID(Queue), 01421 &queueEntry->ListEntry, 01422 &ID(QueueInterlock) 01423 ); 01424 01425 KeReleaseSemaphore( 01426 &ID(QueueSemaphore), 01427 SEMAPHORE_INCREMENT, 01428 1, 01429 FALSE 01430 ); 01431 01432 // 01433 // ...and wait for the SMB to be eaten, in slow mode. 01434 // 01435 01436 if ( ID(SingleSmbMode) ) { 01437 TrPrint(( "%s!SmbTraceCompleteSrv: Slow mode wait\n", ID(ComponentName) )); 01438 KeWaitForSingleObject( 01439 &WaitEvent, 01440 UserRequest, 01441 KernelMode, 01442 FALSE, 01443 NULL 01444 ); 01445 TrPrint(( "%s!SmbTraceCompleteSrv: Slow mode wait done\n", ID(ComponentName) )); 01446 } 01447 01448 SmbTraceDereferenceHeap( Component ); 01449 01450 return; 01451 01452 } // SmbTraceCompleteSrv

VOID SmbTraceCopyMdlContiguous OUT PVOID  Destination,
IN PMDL  Mdl,
IN ULONG  Length
 

Definition at line 2636 of file smbtrsup.c.

References ASSERT, MmGetMdlByteCount, MmGetSystemAddressForMdl, and NULL.

Referenced by SmbTraceCompleteRdr(), and SmbTraceCompleteSrv().

02644 : 02645 02646 Copy the data stored in Mdl into the contiguous memory at 02647 Destination. Length is present to keep the same interface 02648 as RtlCopyMemory. 02649 02650 Arguments: 02651 02652 Destination - a pointer to previously allocated memory into which 02653 the Mdl is to be copied. 02654 02655 Mdl - a pointer to an Mdl which is to be copied to Destination 02656 02657 Length - number of data bytes expected in Mdl 02658 02659 Return Value: 02660 02661 None 02662 02663 --*/ 02664 02665 { 02666 PCHAR Dest = Destination; 02667 02668 UNREFERENCED_PARAMETER(Length); 02669 02670 while (Mdl != NULL) { 02671 02672 RtlCopyMemory( 02673 Dest, 02674 MmGetSystemAddressForMdl(Mdl), 02675 MmGetMdlByteCount(Mdl) 02676 ); 02677 02678 Dest += MmGetMdlByteCount(Mdl); 02679 Mdl = Mdl->Next; 02680 } 02681 02682 ASSERT((ULONG)(Dest - (PCHAR)Destination) == Length); 02683 02684 return; 02685 02686 } // SmbTraceCopyMdlContiguous

VOID SmbTraceDeferredDereferenceHeap IN PVOID  Context  ) 
 

Definition at line 1760 of file smbtrsup.c.

References _TRACE_DEREFERENCE_ITEM::Component, ExFreePool(), PAGED_CODE, PTRACE_DEREFERENCE_ITEM, and SmbTraceDereferenceHeap().

Referenced by SmbTraceDereferenceHeap().

01765 : 01766 01767 If a caller dereferences a heap to 0 from DPC_LEVEL, this routine will 01768 be called in a system thread to complete the dereference at task time. 01769 01770 Arguments: 01771 01772 Component - Context from which we're called: server or redirector 01773 01774 Return Value: 01775 01776 None 01777 01778 --*/ 01779 01780 { 01781 PTRACE_DEREFERENCE_ITEM WorkItem = Context; 01782 SMBTRACE_COMPONENT Component = WorkItem->Component; 01783 01784 PAGED_CODE(); 01785 01786 ExFreePool(WorkItem); 01787 01788 SmbTraceDereferenceHeap(Component); 01789 01790 }

VOID SmbTraceDereferenceHeap IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 1794 of file smbtrsup.c.

References ACQUIRE_SPIN_LOCK, _TRACE_DEREFERENCE_ITEM::Component, DelayedWorkQueue, DISPATCH_LEVEL, ExAllocatePoolWithTag, ExInitializeWorkItem, ExQueueWorkItem(), ID, NonPagedPoolMustSucceed, PTRACE_DEREFERENCE_ITEM, RELEASE_SPIN_LOCK, SmbTraceDeferredDereferenceHeap(), SmbTraceDisconnect(), TrPrint, and _TRACE_DEREFERENCE_ITEM::WorkItem.

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceDeferredDereferenceHeap(), and SmbTraceThreadEntry().

01800 : 01801 01802 This routine dereferences the SmbTrace shared memory heap, 01803 disposing of it when the reference count is zero. 01804 01805 Arguments: 01806 01807 Component - Context from which we're called: server or redirector 01808 01809 Return Value: 01810 01811 None 01812 01813 --*/ 01814 01815 { 01816 ULONG oldCount; 01817 KIRQL OldIrql; 01818 01819 ACQUIRE_SPIN_LOCK( &ID(HeapReferenceCountLock), &OldIrql ); 01820 01821 if (ID(HeapReferenceCount) > 1) { 01822 ID(HeapReferenceCount) --; 01823 01824 TrPrint(( "%s!SmbTraceDereferenceHeap: Count now %lx\n", 01825 ID(ComponentName), 01826 ID(HeapReferenceCount) )); 01827 01828 RELEASE_SPIN_LOCK( &ID(HeapReferenceCountLock), OldIrql ); 01829 01830 return; 01831 } 01832 01833 RELEASE_SPIN_LOCK( &ID(HeapReferenceCountLock), OldIrql ); 01834 01835 // 01836 // If we are executing at DPC_LEVEL, we cannot dereference the heap 01837 // to 0. 01838 // 01839 01840 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) { 01841 PTRACE_DEREFERENCE_ITEM WorkItem; 01842 01843 WorkItem = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, sizeof(TRACE_DEREFERENCE_ITEM), 'tbmS'); 01844 01845 ExInitializeWorkItem(&WorkItem->WorkItem, SmbTraceDeferredDereferenceHeap, WorkItem); 01846 WorkItem->Component = Component; 01847 01848 ExQueueWorkItem(&WorkItem->WorkItem, DelayedWorkQueue); 01849 01850 return; 01851 01852 } 01853 01854 ACQUIRE_SPIN_LOCK( &ID(HeapReferenceCountLock), &OldIrql ); 01855 01856 oldCount = ID(HeapReferenceCount)--; 01857 01858 TrPrint(( "%s!SmbTraceDereferenceHeap: Count now %lx\n", 01859 ID(ComponentName), 01860 ID(HeapReferenceCount) )); 01861 01862 RELEASE_SPIN_LOCK( &ID(HeapReferenceCountLock), OldIrql ); 01863 01864 if ( oldCount == 1 ) { 01865 01866 // 01867 // Free the section, release the handles and such. 01868 // 01869 01870 SmbTraceDisconnect( Component ); 01871 } 01872 01873 return; 01874 01875 } // SmbTraceDereferenceHeap

VOID SmbTraceDisconnect IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 1879 of file smbtrsup.c.

References FALSE, ID, KeAttachProcess(), KeDetachProcess(), NULL, PAGED_CODE, PsGetCurrentProcess, RtlDestroyHeap(), TrPrint, and TRUE.

Referenced by SmbTraceDereferenceHeap(), and SmbTraceStart().

01885 : 01886 01887 This routine reverses all the effects of SmbTraceStart. Mostly, 01888 it just needs to close certain handles to do this. 01889 01890 Arguments: 01891 01892 Component - Context from which we're called: server or redirector 01893 01894 Return Value: 01895 01896 None - always works 01897 01898 --*/ 01899 01900 { 01901 BOOLEAN ProcessAttached = FALSE; 01902 01903 PAGED_CODE(); 01904 01905 if (PsGetCurrentProcess() != ID(FspProcess)) { 01906 KeAttachProcess(ID(FspProcess)); 01907 ProcessAttached = TRUE; 01908 01909 } 01910 01911 01912 if ( ID(DoneSmbEvent) != NULL ) { 01913 // Worker thread may be blocked on this, so we set it first 01914 TrPrint(( "%s!SmbTraceDisconnect: Signal DoneSmbEvent, handle %x, process %x.\n", 01915 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 01916 ZwSetEvent( ID(DoneSmbEvent), NULL ); 01917 01918 TrPrint(( "%s!SmbTraceDisconnect: Close DoneSmbEvent, handle %x, process %x.\n", 01919 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 01920 ZwClose( ID(DoneSmbEvent) ); 01921 ID(DoneSmbEvent) = NULL; 01922 } 01923 01924 if ( ID(NewSmbEvent) != NULL ) { 01925 ZwClose( ID(NewSmbEvent) ); 01926 ID(NewSmbEvent) = NULL; 01927 } 01928 01929 if ( ID(PortMemoryHeap) != NULL ) { 01930 RtlDestroyHeap( ID(PortMemoryHeap) ); 01931 ID(PortMemoryHeap) = NULL; 01932 } 01933 01934 if ( ID(SectionHandle) != NULL ) { 01935 ZwClose( ID(SectionHandle) ); 01936 ID(SectionHandle) = NULL; 01937 } 01938 01939 if (ProcessAttached) { 01940 KeDetachProcess(); 01941 } 01942 01943 return; 01944 01945 } // SmbTraceDisconnect

VOID SmbTraceEmptyQueue IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 1949 of file smbtrsup.c.

References ASSERT, _SMBTRACE_QUEUE_ENTRY::Buffer, _SMBTRACE_QUEUE_ENTRY::BufferNonPaged, ExFreePool(), ExInterlockedRemoveHeadList(), FALSE, ID, KeSetEvent(), NULL, PAGED_CODE, PSMBTRACE_QUEUE_ENTRY, TRUE, and _SMBTRACE_QUEUE_ENTRY::WaitEvent.

Referenced by SmbTraceThreadEntry().

01955 : 01956 01957 This routine empties the queue of unprocessed SMBs. 01958 01959 Arguments: 01960 01961 Component - Context from which we're called: server or redirector 01962 01963 Return Value: 01964 01965 None - always works 01966 01967 --*/ 01968 01969 { 01970 PLIST_ENTRY listEntry; 01971 PSMBTRACE_QUEUE_ENTRY queueEntry; 01972 01973 PAGED_CODE(); 01974 01975 while ( ( listEntry = ExInterlockedRemoveHeadList( 01976 &ID(Queue), 01977 &ID(QueueInterlock) 01978 ) 01979 ) != NULL 01980 ) { 01981 queueEntry = CONTAINING_RECORD( 01982 listEntry, 01983 SMBTRACE_QUEUE_ENTRY, 01984 ListEntry 01985 ); 01986 01987 // 01988 // If data for this entry is in non-paged pool, free it too. 01989 // This only ever happens in the redirector. 01990 // 01991 01992 if ( queueEntry->BufferNonPaged ) { 01993 01994 ASSERT( Component == SMBTRACE_REDIRECTOR ); 01995 01996 ExFreePool( queueEntry->Buffer ); 01997 } 01998 01999 // 02000 // If a worker thread is waiting on this event, let it go. 02001 // This only ever happens in slow mode. 02002 // 02003 02004 if ( queueEntry->WaitEvent != NULL ) { 02005 02006 ASSERT( ID(SingleSmbMode) == TRUE ); 02007 02008 KeSetEvent( queueEntry->WaitEvent, 0, FALSE ); 02009 } 02010 02011 ExFreePool( queueEntry ); 02012 } 02013 02014 return; 02015 02016 } // SmbTraceEmptyQueue

NTSTATUS SmbTraceFreeMemory IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 2355 of file smbtrsup.c.

References ID, L, PAGED_CODE, RtlFreeHeap, and TrPrint.

Referenced by SmbTraceThreadEntry().

02361 : 02362 02363 This procedure frees any memory that may have been allocated to an 02364 SMB that the client has already consumed. It does not alter table 02365 entries, except to record that the memory buffer has been cleared. 02366 This routinue is not espectally fast, it should not be called often, 02367 only when needed. 02368 02369 Arguments: 02370 02371 Component - Context from which we're called: server or redirector 02372 02373 Return Value: 02374 02375 NTSTATUS - result of operation. 02376 02377 --*/ 02378 02379 { 02380 PVOID buffer; 02381 PSMBTRACE_TABLE_ENTRY tableEntry; 02382 ULONG tableIndex; 02383 02384 PAGED_CODE(); 02385 02386 TrPrint(( "%s!SmbTraceFreeMemory: Called for garbage collection.\n", 02387 ID(ComponentName) )); 02388 02389 // 02390 // No free memory in the heap, perhaps we can free some by freeing 02391 // memory in old table entries. This is expensive for time. 02392 // 02393 02394 tableIndex = ID(TableHeader)->NextFree; 02395 02396 while( tableIndex != ID(TableHeader)->HighestConsumed ) { 02397 02398 tableEntry = ID(Table) + tableIndex; 02399 02400 // 02401 // Check if this table entry has been used but its memory has not 02402 // been freed yet. If so, free it. 02403 // 02404 02405 if ( tableEntry->BufferOffset != 0L ) { 02406 02407 buffer = (PVOID)( (ULONG_PTR)tableEntry->BufferOffset 02408 + (ULONG_PTR)ID(PortMemoryBase) ); 02409 02410 RtlFreeHeap( ID(PortMemoryHeap), 0, buffer); 02411 02412 tableEntry->BufferOffset = 0L; 02413 } 02414 02415 02416 tableIndex = (tableIndex + 1) % ID(TableSize); 02417 } 02418 02419 return( STATUS_SUCCESS ); 02420 02421 } // SmbTraceFreeMemory

NTSTATUS SmbTraceInitialize IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 438 of file smbtrsup.c.

References ERESOURCE, ExAllocatePoolWithTag, ExDeleteResource, ExFreePool(), ExInitializeResource, FALSE, ID, KeInitializeEvent, KeInitializeSpinLock(), NonPagedPool, NULL, PAGED_CODE, and TRUE.

00444 : 00445 00446 This routine initializes the SmbTrace component-specific instance 00447 globals. On first-ever invocation, it performs truly global 00448 initialization. 00449 00450 Arguments: 00451 00452 Component - Context from which we're called: server or redirector 00453 00454 Return Value: 00455 00456 NTSTATUS - Indicates failure if unable to allocate resources 00457 00458 --*/ 00459 00460 { 00461 PAGED_CODE(); 00462 00463 if ( ID(InstanceInitialized) == FALSE ) { 00464 // 00465 // Component specific initialization -- events and locks. 00466 // 00467 00468 KeInitializeEvent( &ID(ActiveEvent), NotificationEvent, FALSE); 00469 KeInitializeEvent( &ID(TerminatedEvent), NotificationEvent, FALSE); 00470 KeInitializeEvent( &ID(TerminationEvent), NotificationEvent, FALSE); 00471 KeInitializeEvent( &ID(AppTerminationEvent), NotificationEvent, FALSE); 00472 KeInitializeEvent( &ID(NeedMemoryEvent), NotificationEvent, FALSE); 00473 00474 KeInitializeSpinLock( &ID(SmbsLostInterlock) ); 00475 KeInitializeSpinLock( &ID(HeapReferenceCountLock) ); 00476 00477 ID(StateInterlock) = ExAllocatePoolWithTag( 00478 NonPagedPool, 00479 sizeof(ERESOURCE), 00480 'tbmS' 00481 ); 00482 if ( ID(StateInterlock) == NULL ) { 00483 return STATUS_INSUFFICIENT_RESOURCES; 00484 } 00485 ExInitializeResource( ID(StateInterlock) ); 00486 00487 ID(HeapInterlock) = ExAllocatePoolWithTag( 00488 NonPagedPool, 00489 sizeof(ERESOURCE), 00490 'tbmS' 00491 ); 00492 if ( ID(HeapInterlock) == NULL ) { 00493 ExDeleteResource( ID(StateInterlock) ); 00494 ExFreePool( ID(StateInterlock) ); 00495 ID(StateInterlock) = NULL; 00496 return STATUS_INSUFFICIENT_RESOURCES; 00497 } 00498 ExInitializeResource( ID(HeapInterlock) ); 00499 00500 ID(InstanceInitialized) = TRUE; 00501 } 00502 00503 return STATUS_SUCCESS; 00504 00505 } // SmbTraceInitialize

ULONG SmbTraceMdlLength IN PMDL  Mdl  ) 
 

Definition at line 2603 of file smbtrsup.c.

References MmGetMdlByteCount, and NULL.

Referenced by SmbTraceCompleteRdr(), and SmbTraceCompleteSrv().

02609 : 02610 02611 Determine the total number of bytes of data found in an Mdl. 02612 02613 Arguments: 02614 02615 Mdl - a pointer to an Mdl whose length is to be calculated 02616 02617 Return Value: 02618 02619 ULONG - total number of data bytes in Mdl 02620 02621 --*/ 02622 02623 { 02624 ULONG Bytes = 0; 02625 02626 while (Mdl != NULL) { 02627 Bytes += MmGetMdlByteCount(Mdl); 02628 Mdl = Mdl->Next; 02629 } 02630 02631 return Bytes; 02632 } // SmbTraceMdlLength

BOOLEAN SmbTraceReferenceHeap IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 1709 of file smbtrsup.c.

References ACQUIRE_SPIN_LOCK, ASSERT, FALSE, ID, RELEASE_SPIN_LOCK, TraceRunning, TrPrint, and TRUE.

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), and SmbTraceStart().

01715 : 01716 01717 This routine references the SmbTrace shared memory heap, 01718 ensuring it isn't disposed of while caller is using it. 01719 01720 Arguments: 01721 01722 Component - Context from which we're called: server or redirector 01723 01724 Return Value: 01725 01726 BOOLEAN - TRUE if SmbTrace is still active, and hence 01727 heap exists and was successfully referenced. 01728 FALSE otherwise. 01729 01730 --*/ 01731 01732 { 01733 BOOLEAN retval = TRUE; // assume we'll get it 01734 KIRQL OldIrql; 01735 01736 ACQUIRE_SPIN_LOCK( &ID(HeapReferenceCountLock), &OldIrql ); 01737 01738 if ( ID(TraceState) != TraceRunning ) { 01739 retval = FALSE; 01740 } else { 01741 ASSERT( ID(HeapReferenceCount) > 0 ); 01742 ID(HeapReferenceCount)++; 01743 TrPrint(( "%s!SmbTraceReferenceHeap: Count now %lx\n", 01744 ID(ComponentName), 01745 ID(HeapReferenceCount) )); 01746 } 01747 01748 RELEASE_SPIN_LOCK( &ID(HeapReferenceCountLock), OldIrql ); 01749 01750 return retval; 01751 01752 } // SmbTraceReferenceHeap

NTSTATUS SmbTraceStart IN ULONG  InputBufferLength,
IN ULONG  OutputBufferLength,
IN OUT PVOID  ConfigInOut,
IN PFILE_OBJECT  FileObject,
IN SMBTRACE_COMPONENT  Component
 

Definition at line 551 of file smbtrsup.c.

References ACL_LENGTH, ASSERT, Buffer, ExAcquireResourceExclusive, ExReleaseResource, FALSE, ID, KeResetEvent(), KernelMode, KeWaitForSingleObject(), L, MmLockPagableDataSection(), NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, PKSTART_ROUTINE, PsCreateSystemThread(), PsGetCurrentProcess, RtlAddAccessAllowedAce(), RtlAllocateHeap, RtlCreateAcl(), RtlCreateHeap(), RtlCreateSecurityDescriptor(), RtlInitUnicodeString(), RtlSetDaclSecurityDescriptor(), _SE_EXPORTS::SeAliasAdminsSid, SeExports, SmbTraceActive, SmbTraceData, SmbTraceDiscardableCodeHandle, SmbTraceDiscardableDataHandle, SmbTraceDisconnect(), SmbTraceReferenceHeap(), SmbTraceStop(), SmbTraceThreadEntry(), TraceRunning, TraceStarting, TraceStartStopFile, TraceStartStopNull, TraceStopped, TrPrint, TRUE, UserRequest, and VOID().

00561 : 00562 00563 This routine performs all the work necessary to connect the server/ 00564 redirector to SmbTrace. It creates the section of shared memory to 00565 be used, then creates the events needed. All these objects are then 00566 opened by the client (smbtrace) program. This code initializes the 00567 table, the heap stored in the section and table header. This routine 00568 must be called from an Fsp process. 00569 00570 Arguments: 00571 00572 InputBufferLength - Length of the ConfigInOut packet 00573 00574 OutputBufferLength - Length expected for the ConfigInOut packet returned 00575 00576 ConfigInOut - A structure that has configuration information. 00577 00578 FileObject - FileObject of the process requesting that SmbTrace be started, 00579 used to automatically shut down when the app dies. 00580 00581 Component - Context from which we're called: server or redirector 00582 00583 Return Value: 00584 00585 NTSTATUS - result of operation. 00586 00587 --*/ 00588 00589 // size of our one, particular, ACL 00590 #define ACL_LENGTH (ULONG)sizeof(ACL) + \ 00591 (ULONG)sizeof(ACCESS_ALLOWED_ACE) + \ 00592 sizeof(LUID) + \ 00593 8 00594 00595 { 00596 NTSTATUS status; 00597 UNICODE_STRING memoryNameU; 00598 00599 SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; 00600 UCHAR Buffer[ACL_LENGTH]; 00601 PACL AdminAcl = (PACL)(&Buffer[0]); 00602 SECURITY_DESCRIPTOR securityDescriptor; 00603 00604 UNICODE_STRING eventNameU; 00605 OBJECT_ATTRIBUTES objectAttributes; 00606 ULONG i; 00607 LARGE_INTEGER sectionSize; 00608 PSMBTRACE_CONFIG_PACKET_REQ ConfigPacket; 00609 PSMBTRACE_CONFIG_PACKET_RESP ConfigPacketResp; 00610 HANDLE threadHandle; 00611 00612 PAGED_CODE(); 00613 00614 ASSERT( ID(InstanceInitialized) ); 00615 00616 // 00617 // Validate the buffer lengths passed in. 00618 // 00619 00620 if ( ( InputBufferLength != sizeof( SMBTRACE_CONFIG_PACKET_REQ ) ) 00621 || ( OutputBufferLength != sizeof( SMBTRACE_CONFIG_PACKET_RESP ) ) 00622 ) { 00623 00624 TrPrint(( "%s!SmbTraceStart: config packet(s) of wrong size!\n", 00625 ID(ComponentName) )); 00626 00627 return STATUS_INFO_LENGTH_MISMATCH; 00628 00629 } 00630 00631 ExAcquireResourceExclusive( ID(StateInterlock), TRUE ); 00632 00633 if ( ID(TraceState) != TraceStopped ) { 00634 ExReleaseResource( ID(StateInterlock) ); 00635 return STATUS_INVALID_DEVICE_STATE; 00636 } 00637 00638 ASSERT(!SmbTraceActive[Component]); 00639 00640 ASSERT (SmbTraceDiscardableDataHandle == NULL); 00641 00642 ASSERT (SmbTraceDiscardableCodeHandle == NULL); 00643 00644 SmbTraceDiscardableCodeHandle = MmLockPagableCodeSection(SmbTraceReferenceHeap); 00645 00646 SmbTraceDiscardableDataHandle = MmLockPagableDataSection(SmbTraceData); 00647 00648 ID(TraceState) = TraceStarting; 00649 00650 // 00651 // Initialize global variables so that we know what to close on errexit 00652 // 00653 00654 ID(SectionHandle) = NULL; 00655 ID(PortMemoryHeap) = NULL; 00656 ID(NewSmbEvent) = NULL; 00657 ID(DoneSmbEvent) = NULL; 00658 00659 // 00660 // Caution! Both input and output packets are the same, we must 00661 // read all of the input before we write any output. 00662 // 00663 00664 ConfigPacket = (PSMBTRACE_CONFIG_PACKET_REQ) ConfigInOut; 00665 ConfigPacketResp = (PSMBTRACE_CONFIG_PACKET_RESP) ConfigInOut; 00666 00667 // 00668 // Set the mode of operation (read all values). 00669 // 00670 00671 ID(SingleSmbMode) = ConfigPacket->SingleSmbMode; 00672 ID(Verbosity) = ConfigPacket->Verbosity; 00673 ID(PortMemorySize) = ConfigPacket->BufferSize; 00674 ID(TableSize) = ConfigPacket->TableSize; 00675 00676 // 00677 // Create a security descriptor containing a discretionary Acl 00678 // allowing administrator access. This SD will be used to allow 00679 // Smbtrace access to the shared memory and the notification events. 00680 // 00681 00682 // Create Acl allowing administrator access using well-known Sid. 00683 00684 status = RtlCreateAcl( AdminAcl, ACL_LENGTH, ACL_REVISION2 ); 00685 if ( !NT_SUCCESS(status) ) { 00686 TrPrint(( 00687 "%s!SmbTraceStart: RtlCreateAcl failed: %X\n", 00688 ID(ComponentName), status )); 00689 goto errexit; 00690 } 00691 00692 status = RtlAddAccessAllowedAce( 00693 AdminAcl, 00694 ACL_REVISION2, 00695 GENERIC_ALL, 00696 SeExports->SeAliasAdminsSid 00697 ); 00698 if ( !NT_SUCCESS(status) ) { 00699 TrPrint(( 00700 "%s!SmbTraceStart: RtlAddAccessAllowedAce failed: %X\n", 00701 ID(ComponentName), status )); 00702 goto errexit; 00703 } 00704 00705 // Create SecurityDescriptor containing AdminAcl as a discrectionary ACL. 00706 00707 RtlCreateSecurityDescriptor( 00708 &securityDescriptor, 00709 SECURITY_DESCRIPTOR_REVISION1 00710 ); 00711 if ( !NT_SUCCESS(status) ) { 00712 TrPrint(( 00713 "%s!SmbTraceStart: RtlCreateSecurityDescriptor failed: %X\n", 00714 ID(ComponentName), status )); 00715 goto errexit; 00716 } 00717 00718 status = RtlSetDaclSecurityDescriptor( 00719 &securityDescriptor, 00720 TRUE, 00721 AdminAcl, 00722 FALSE 00723 ); 00724 if ( !NT_SUCCESS(status) ) { 00725 TrPrint(( 00726 "%s!SmbTraceStart: " 00727 "RtlSetDAclAllowedSecurityDescriptor failed: %X\n", 00728 ID(ComponentName), status )); 00729 goto errexit; 00730 } 00731 00732 // 00733 // Create the section to be used for communication between the 00734 // server/redirector and SmbTrace. 00735 // 00736 00737 // Define the object name. 00738 00739 RtlInitUnicodeString( &memoryNameU, ID(SharedMemoryName) ); 00740 00741 // Define the object information, including security descriptor and name. 00742 00743 InitializeObjectAttributes( 00744 &objectAttributes, 00745 &memoryNameU, 00746 OBJ_CASE_INSENSITIVE, 00747 NULL, 00748 &securityDescriptor 00749 ); 00750 00751 // Setup the section size. 00752 00753 sectionSize.QuadPart = ID(PortMemorySize); 00754 00755 // Create the named section of memory with all of our attributes. 00756 00757 status = ZwCreateSection( 00758 &ID(SectionHandle), 00759 SECTION_MAP_READ | SECTION_MAP_WRITE, 00760 &objectAttributes, 00761 &sectionSize, 00762 PAGE_READWRITE, 00763 SEC_RESERVE, 00764 NULL // file handle 00765 ); 00766 00767 if ( !NT_SUCCESS(status) ) { 00768 TrPrint(( "%s!SmbTraceStart: ZwCreateSection failed: %X\n", 00769 ID(ComponentName), status )); 00770 goto errexit; 00771 } 00772 00773 // Now, map it into our address space. 00774 00775 ID(PortMemoryBase) = NULL; 00776 00777 status = ZwMapViewOfSection( 00778 ID(SectionHandle), 00779 NtCurrentProcess(), 00780 &ID(PortMemoryBase), 00781 0, // zero bits (don't care) 00782 0, // commit size 00783 NULL, // SectionOffset 00784 &ID(PortMemorySize), // viewSize 00785 ViewUnmap, // inheritDisposition 00786 0L, // allocation type 00787 PAGE_READWRITE // protection 00788 ); 00789 00790 if ( !NT_SUCCESS(status) ) { 00791 TrPrint(( "%s!SmbTraceStart: NtMapViewOfSection failed: %X\n", 00792 ID(ComponentName), status )); 00793 goto errexit; 00794 } 00795 00796 // 00797 // Set up the shared section memory as a heap. 00798 // 00799 // *** Note that the HeapInterlock for the client instance is passed 00800 // to the heap manager to be used for serialization of 00801 // allocation and deallocation. It is necessary for the 00802 // resource to be allocated FROM NONPAGED POOL externally to the 00803 // heap manager, because if we let the heap manager allocate 00804 // the resource, if would allocate it from process virtual 00805 // memory. 00806 // 00807 00808 ID(PortMemoryHeap) = RtlCreateHeap( 00809 0, // Flags 00810 ID(PortMemoryBase), // HeapBase 00811 ID(PortMemorySize), // ReserveSize 00812 PAGE_SIZE, // CommitSize 00813 ID(HeapInterlock), // Lock 00814 0 // Reserved 00815 ); 00816 00817 // 00818 // Allocate and initialize the table and its header. 00819 // 00820 00821 ID(TableHeader) = RtlAllocateHeap( 00822 ID(PortMemoryHeap), 0, 00823 sizeof( SMBTRACE_TABLE_HEADER ) 00824 ); 00825 00826 ID(Table) = RtlAllocateHeap( 00827 ID(PortMemoryHeap), 0, 00828 sizeof( SMBTRACE_TABLE_ENTRY ) * ID(TableSize) 00829 ); 00830 00831 if ( (ID(TableHeader) == NULL) || (ID(Table) == NULL) ) { 00832 TrPrint(( 00833 "%s!SmbTraceStart: Not enough memory!\n", 00834 ID(ComponentName) )); 00835 00836 status = STATUS_NO_MEMORY; 00837 00838 goto errexit; 00839 } 00840 00841 // Initialize the values inside. 00842 00843 ID(TableHeader)->HighestConsumed = 0; 00844 ID(TableHeader)->NextFree = 1; 00845 ID(TableHeader)->ApplicationStop = FALSE; 00846 00847 for ( i = 0; i < ID(TableSize); i++) { 00848 ID(Table)[i].BufferOffset = 0L; 00849 ID(Table)[i].SmbLength = 0L; 00850 } 00851 00852 // 00853 // Create the required event handles. 00854 // 00855 00856 // Define the object information. 00857 00858 RtlInitUnicodeString( &eventNameU, ID(NewSmbEventName) ); 00859 00860 InitializeObjectAttributes( 00861 &objectAttributes, 00862 &eventNameU, 00863 OBJ_CASE_INSENSITIVE, 00864 NULL, 00865 &securityDescriptor 00866 ); 00867 00868 // Open the named object. 00869 00870 status = ZwCreateEvent( 00871 &ID(NewSmbEvent), 00872 EVENT_ALL_ACCESS, 00873 &objectAttributes, 00874 NotificationEvent, 00875 FALSE // initial state 00876 ); 00877 00878 if ( !NT_SUCCESS(status) ) { 00879 TrPrint(( "%s!SmbTraceStart: ZwCreateEvent (1st) failed: %X\n", 00880 ID(ComponentName), status )); 00881 00882 goto errexit; 00883 } 00884 00885 if ( ID(SingleSmbMode) ) { // this event may not be required. 00886 00887 // Define the object information. 00888 00889 RtlInitUnicodeString( &eventNameU, ID(DoneSmbEventName) ); 00890 00891 InitializeObjectAttributes( 00892 &objectAttributes, 00893 &eventNameU, 00894 OBJ_CASE_INSENSITIVE, 00895 NULL, 00896 &securityDescriptor 00897 ); 00898 00899 // Create the named object. 00900 00901 status = ZwCreateEvent( 00902 &ID(DoneSmbEvent), 00903 EVENT_ALL_ACCESS, 00904 &objectAttributes, 00905 NotificationEvent, 00906 FALSE // initial state 00907 ); 00908 00909 if ( !NT_SUCCESS(status) ) { 00910 TrPrint(( 00911 "%s!SmbTraceStart: NtCreateEvent (2nd) failed: %X\n", 00912 ID(ComponentName), status )); 00913 goto errexit; 00914 } 00915 TrPrint(( "%s!SmbTraceStart: DoneSmbEvent handle %x in process %x\n", 00916 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 00917 00918 } 00919 00920 // 00921 // Reset any events that may be in the wrong state from a previous run. 00922 // 00923 00924 KeResetEvent(&ID(TerminationEvent)); 00925 KeResetEvent(&ID(TerminatedEvent)); 00926 00927 // 00928 // Connection was successful, now start the SmbTrace thread. 00929 // 00930 00931 // 00932 // Create the SmbTrace thread and wait for it to finish 00933 // initializing (at which point SmbTraceActiveEvent is set) 00934 // 00935 00936 status = PsCreateSystemThread( 00937 &threadHandle, 00938 THREAD_ALL_ACCESS, 00939 NULL, 00940 NtCurrentProcess(), 00941 NULL, 00942 (PKSTART_ROUTINE) SmbTraceThreadEntry, 00943 (PVOID)Component 00944 ); 00945 00946 if ( !NT_SUCCESS(status) ) { 00947 00948 TrPrint(( 00949 "%s!SmbTraceStart: PsCreateSystemThread failed: %X\n", 00950 ID(ComponentName), status )); 00951 00952 goto errexit; 00953 } 00954 00955 // 00956 // Wait until SmbTraceThreadEntry has finished initializing 00957 // 00958 00959 (VOID)KeWaitForSingleObject( 00960 &ID(ActiveEvent), 00961 UserRequest, 00962 KernelMode, 00963 FALSE, 00964 NULL 00965 ); 00966 00967 // 00968 // Close the handle to the process so the object will be 00969 // destroyed when the thread dies. 00970 // 00971 00972 ZwClose( threadHandle ); 00973 00974 00975 // 00976 // Record who started SmbTrace so we can stop if he dies or otherwise 00977 // closes this handle to us. 00978 // 00979 00980 ID(StartersFileObject) = FileObject; 00981 00982 // 00983 // Record caller's process; which is always the appropriate Fsp 00984 // process. 00985 // 00986 00987 ID(FspProcess) = PsGetCurrentProcess(); 00988 00989 00990 // 00991 // Setup the response packet, since everything worked (write all values). 00992 // 00993 00994 ConfigPacketResp->HeaderOffset = (ULONG) 00995 ( (ULONG_PTR)ID(TableHeader) 00996 - (ULONG_PTR)ID(PortMemoryBase) ); 00997 00998 ConfigPacketResp->TableOffset = (ULONG) 00999 ( (ULONG_PTR)ID(Table) 01000 - (ULONG_PTR)ID(PortMemoryBase) ); 01001 01002 TrPrint(( "%s!SmbTraceStart: SmbTrace started.\n", ID(ComponentName) )); 01003 01004 ExReleaseResource( ID(StateInterlock) ); 01005 01006 // 01007 // if someone wanted it shut down while it was starting, shut it down 01008 // 01009 01010 switch ( ID(TraceState) ) { 01011 01012 case TraceStartStopFile : 01013 SmbTraceStop( ID(StartersFileObject), Component ); 01014 return STATUS_UNSUCCESSFUL; // app closed, so we should shut down 01015 break; 01016 01017 case TraceStartStopNull : 01018 SmbTraceStop( NULL, Component ); 01019 return STATUS_UNSUCCESSFUL; // someone requested a shut down 01020 break; 01021 01022 default : 01023 ID(TraceState) = TraceRunning; 01024 SmbTraceActive[Component] = TRUE; 01025 return STATUS_SUCCESS; 01026 } 01027 01028 errexit: 01029 01030 SmbTraceDisconnect( Component ); 01031 01032 ID(TraceState) = TraceStopped; 01033 01034 ExReleaseResource( ID(StateInterlock) ); 01035 01036 // 01037 // return original failure status code, not success of cleanup 01038 // 01039 01040 return status; 01041 01042 } // SmbTraceStart

NTSTATUS SmbTraceStop IN PFILE_OBJECT FileObject  OPTIONAL,
IN SMBTRACE_COMPONENT  Component
 

Definition at line 1050 of file smbtrsup.c.

References ASSERT, ExAcquireResourceExclusive, ExReleaseResource, FALSE, ID, KeAttachProcess(), KeDetachProcess(), KernelMode, KeSetEvent(), KeWaitForSingleObject(), MmUnlockPagableImageSection(), NULL, PAGED_CODE, PsGetCurrentProcess, SmbTraceActive, SmbTraceDiscardableCodeHandle, SmbTraceDiscardableDataHandle, TraceAppWaiting, TraceRunning, TraceStarting, TraceStartStopFile, TraceStartStopNull, TraceStopped, TraceStopping, TrPrint, TRUE, and UserRequest.

Referenced by SmbTraceStart().

01057 : 01058 01059 This routine stops tracing in the server/redirector. If no 01060 FileObject is provided, the SmbTrace application is stopped. 01061 If a FileObject is provided, SmbTrace is stopped if the 01062 FileObject refers to the one who started it. 01063 01064 Arguments: 01065 01066 FileObject - FileObject of a process that terminated. If it's the process 01067 that requested SmbTracing, we shut down automatically. 01068 01069 Component - Context from which we're called: server or redirector 01070 01071 Return Value: 01072 01073 NTSTATUS - result of operation. Possible results are: 01074 STATUS_SUCCESS - SmbTrace was stopped 01075 STATUS_UNSUCCESSFUL - SmbTrace was not stopped because the 01076 provided FileObject did not refer to the SmbTrace starter 01077 or because SmbTrace was not running. 01078 01079 --*/ 01080 01081 { 01082 PAGED_CODE(); 01083 01084 // 01085 // If we haven't been initialized, there's nothing to stop. (And no 01086 // resource to acquire!) 01087 // 01088 01089 if ( !ID(InstanceInitialized) ) { 01090 return STATUS_UNSUCCESSFUL; 01091 } 01092 01093 // 01094 // If it's not the FileObject that started SmbTrace, we don't care. 01095 // From then on, if ARGUMENT_PRESENT(FileObject) it's the right one. 01096 // 01097 01098 if ( ARGUMENT_PRESENT(FileObject) && 01099 FileObject != ID(StartersFileObject) 01100 ) { 01101 return STATUS_UNSUCCESSFUL; 01102 } 01103 01104 ExAcquireResourceExclusive( ID(StateInterlock), TRUE ); 01105 01106 // 01107 // Depending on the current state of SmbTrace and whether this is 01108 // a FileObject or unconditional shutdown request, we do different 01109 // things. It is always clear at this point, though, that 01110 // SmbTraceActive should be set to FALSE. 01111 // 01112 01113 SmbTraceActive[Component] = FALSE; 01114 01115 switch ( ID(TraceState) ) { 01116 case TraceStopped : 01117 case TraceStopping : 01118 case TraceStartStopFile : 01119 case TraceStartStopNull : 01120 01121 // if we're not running or already in a mode where we know we'll 01122 // soon be shut down, ignore the request. 01123 ExReleaseResource( ID(StateInterlock) ); 01124 return STATUS_UNSUCCESSFUL; 01125 break; 01126 01127 case TraceStarting : 01128 01129 // inform starting SmbTrace that it should shut down immediately 01130 // upon finishing initialization. It needs to know whether this 01131 // is a FileObject or unconditional shutdown request. 01132 01133 ID(TraceState) = ARGUMENT_PRESENT(FileObject) 01134 ? TraceStartStopFile 01135 : TraceStartStopNull; 01136 ExReleaseResource( ID(StateInterlock) ); 01137 return STATUS_SUCCESS; 01138 break; 01139 01140 case TraceAppWaiting : 01141 01142 // we're waiting for the application to die already, so ignore 01143 // new unconditional requests. But FileObject requests are 01144 // welcomed. We cause the SmbTrace thread to kill itself. 01145 if ( ARGUMENT_PRESENT(FileObject) ) { 01146 break; // thread kill code follows switch 01147 } else { 01148 ExReleaseResource( ID(StateInterlock) ); 01149 return STATUS_UNSUCCESSFUL; 01150 } 01151 break; 01152 01153 case TraceRunning : 01154 01155 // if it's a FileObject request, the app is dead, so we cause 01156 // the SmbTrace thread to kill itself. Otherwise, we need to 01157 // signal the app to stop and return. When the app is gone, we 01158 // will be called again; this time with a FileObject. 01159 01160 if ( ARGUMENT_PRESENT(FileObject) ) { 01161 break; // thread kill code follows switch 01162 } else { 01163 KeSetEvent( &ID(AppTerminationEvent), 2, FALSE ); 01164 ID(TraceState) = TraceAppWaiting; 01165 ExReleaseResource( ID(StateInterlock) ); 01166 return STATUS_SUCCESS; 01167 } 01168 01169 break; 01170 01171 default : 01172 ASSERT(!"SmbTraceStop: invalid TraceState"); 01173 break; 01174 } 01175 01176 // 01177 // We reach here from within the switch only in the case where 01178 // we actually want to kill the SmbTrace thread. Signal it to 01179 // wake up, and wait until it terminates. Signal DoneSmbEvent 01180 // in case it is currently waiting for the application to signal 01181 // it in slow mode. 01182 // 01183 01184 ID(StartersFileObject) = NULL; 01185 01186 if ( ID(SingleSmbMode)) { 01187 01188 BOOLEAN ProcessAttached = FALSE; 01189 01190 if (PsGetCurrentProcess() != ID(FspProcess)) { 01191 KeAttachProcess(ID(FspProcess)); 01192 ProcessAttached = TRUE; 01193 } 01194 01195 TrPrint(( "%s!SmbTraceStop: Signal DoneSmbEvent, handle %x, process %x.\n", 01196 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 01197 ZwSetEvent( ID(DoneSmbEvent), NULL ); 01198 01199 if (ProcessAttached) { 01200 KeDetachProcess(); 01201 } 01202 01203 } 01204 01205 TrPrint(( "%s!SmbTraceStop: Signal Termination Event.\n", ID(ComponentName) )); 01206 ID(TraceState) = TraceStopping; 01207 KeSetEvent( &ID(TerminationEvent), 2, FALSE ); 01208 01209 ExReleaseResource( ID(StateInterlock) ); 01210 01211 KeWaitForSingleObject( 01212 &ID(TerminatedEvent), 01213 UserRequest, 01214 KernelMode, 01215 FALSE, 01216 NULL 01217 ); 01218 01219 TrPrint(( "%s!SmbTraceStop: Terminated Event is set.\n", ID(ComponentName) )); 01220 ExAcquireResourceExclusive( ID(StateInterlock), TRUE ); 01221 01222 ID(TraceState) = TraceStopped; 01223 01224 ExReleaseResource( ID(StateInterlock) ); 01225 01226 TrPrint(( "%s!SmbTraceStop: SmbTrace stopped.\n", ID(ComponentName) )); 01227 01228 MmUnlockPagableImageSection(SmbTraceDiscardableCodeHandle); 01229 01230 SmbTraceDiscardableCodeHandle = NULL; 01231 01232 MmUnlockPagableImageSection(SmbTraceDiscardableDataHandle); 01233 01234 SmbTraceDiscardableDataHandle = NULL; 01235 01236 return STATUS_SUCCESS; 01237 01238 } // SmbTraceStop

VOID SmbTraceTerminate IN SMBTRACE_COMPONENT  Component  ) 
 

Definition at line 509 of file smbtrsup.c.

References ExDeleteResource, ExFreePool(), FALSE, ID, and PAGED_CODE.

00515 : 00516 00517 This routine cleans up the SmbTrace component-specific instance 00518 globals. It should be called by the component when the component 00519 is unloaded. 00520 00521 Arguments: 00522 00523 Component - Context from which we're called: server or redirector 00524 00525 Return Value: 00526 00527 None 00528 00529 --*/ 00530 00531 { 00532 PAGED_CODE(); 00533 00534 if ( ID(InstanceInitialized) ) { 00535 00536 ExDeleteResource( ID(StateInterlock) ); 00537 ExFreePool( ID(StateInterlock) ); 00538 00539 ExDeleteResource( ID(HeapInterlock) ); 00540 ExFreePool( ID(HeapInterlock) ); 00541 00542 ID(InstanceInitialized) = FALSE; 00543 } 00544 00545 return; 00546 00547 } // SmbTraceTerminate

VOID SmbTraceThreadEntry IN PVOID  Context  ) 
 

Definition at line 2020 of file smbtrsup.c.

References ASSERT, _SMBTRACE_QUEUE_ENTRY::Buffer, _SMBTRACE_QUEUE_ENTRY::BufferNonPaged, ExFreePool(), ExInterlockedRemoveHeadList(), FALSE, ID, INDEX_WAIT_APPTERMINATIONEVENT, INDEX_WAIT_NEEDMEMORYEVENT, INDEX_WAIT_QUEUESEMAPHORE, INDEX_WAIT_TERMINATIONEVENT, KeInitializeSemaphore(), KeInitializeSpinLock(), KeResetEvent(), KernelMode, KeSetEvent(), KeWaitForMultipleObjects(), L, LOCK_INC_ID, NT_SUCCESS, NTSTATUS(), NULL, NUMBER_OF_BLOCKING_OBJECTS, PAGED_CODE, PSMBTRACE_QUEUE_ENTRY, PsTerminateSystemThread(), RtlAllocateHeap, _SMBTRACE_QUEUE_ENTRY::SmbAddress, _SMBTRACE_QUEUE_ENTRY::SmbLength, SmbTraceDereferenceHeap(), SmbTraceEmptyQueue(), SmbTraceFreeMemory(), SmbTraceToClient(), STATUS_WAIT_APPTERMINATIONEVENT, STATUS_WAIT_NEEDMEMORYEVENT, STATUS_WAIT_QUEUESEMAPHORE, STATUS_WAIT_TERMINATIONEVENT, THREAD_WAIT_OBJECTS, TraceAppWaiting, TrPrint, TRUE, UserRequest, and _SMBTRACE_QUEUE_ENTRY::WaitEvent.

Referenced by SmbTraceStart().

02026 : 02027 02028 This routine is the entry point of the SmbTrace thread for the server/ 02029 redirector. It is started by SmbTraceStart. This thread loops 02030 continuously until the client SmbTrace dies or another SmbTrace sends 02031 an FsCtl to stop the trace. 02032 02033 Arguments: 02034 02035 Context - pointer to context block containing component from which 02036 we're called: server or redirector 02037 02038 Return Value: 02039 02040 None 02041 02042 --*/ 02043 02044 // we wait for termination, work-to-do and need-memory events 02045 #define NUMBER_OF_BLOCKING_OBJECTS 4 02046 02047 // keep these definitions in sync 02048 02049 #define INDEX_WAIT_TERMINATIONEVENT 0 02050 #define INDEX_WAIT_APPTERMINATIONEVENT 1 02051 #define INDEX_WAIT_NEEDMEMORYEVENT 2 02052 #define INDEX_WAIT_QUEUESEMAPHORE 3 02053 02054 #define STATUS_WAIT_TERMINATIONEVENT STATUS_WAIT_0 02055 #define STATUS_WAIT_APPTERMINATIONEVENT STATUS_WAIT_1 02056 #define STATUS_WAIT_NEEDMEMORYEVENT STATUS_WAIT_2 02057 #define STATUS_WAIT_QUEUESEMAPHORE STATUS_WAIT_3 02058 02059 { 02060 NTSTATUS status; 02061 PLIST_ENTRY listEntry; 02062 PSMBTRACE_QUEUE_ENTRY queueEntry; 02063 PVOID buffer; 02064 PVOID waitObjects[NUMBER_OF_BLOCKING_OBJECTS]; 02065 SMBTRACE_COMPONENT Component; 02066 BOOLEAN Looping; 02067 02068 #if NUMBER_OF_BLOCKING_OBJECTS > THREAD_WAIT_OBJECTS 02069 // 02070 // If we try to wait on too many objects, we need to allocate 02071 // our own wait blocks. 02072 // 02073 02074 KWAIT_BLOCK waitBlocks[NUMBER_OF_BLOCKING_OBJECTS]; 02075 #endif 02076 02077 PAGED_CODE(); 02078 02079 // 02080 // Context is really just the component 02081 // 02082 Component = (SMBTRACE_COMPONENT)(UINT_PTR)Context; 02083 02084 // 02085 // Initialize the queue. 02086 // 02087 02088 InitializeListHead( &ID(Queue) ); 02089 KeInitializeSpinLock( &ID(QueueInterlock) ); 02090 KeInitializeSemaphore( &ID(QueueSemaphore), 0, 0x7FFFFFFF ); 02091 02092 // 02093 // Set up the array of objects to wait on. We wait (in order) 02094 // for our termination event, the appliction termination event, 02095 // a no shared memory event or an SMB request to show up in the 02096 // SmbTrace queue. 02097 // 02098 02099 waitObjects[INDEX_WAIT_TERMINATIONEVENT] = &ID(TerminationEvent); 02100 waitObjects[INDEX_WAIT_APPTERMINATIONEVENT] = &ID(AppTerminationEvent); 02101 waitObjects[INDEX_WAIT_NEEDMEMORYEVENT] = &ID(NeedMemoryEvent); 02102 waitObjects[INDEX_WAIT_QUEUESEMAPHORE] = &ID(QueueSemaphore); 02103 02104 // 02105 // No SMBs have been lost yet, and this thread is the first user 02106 // of the shared memory. It's also a special user in that it gets 02107 // access before TraceState == TraceRunning, a requirement for all 02108 // subsequent referencers. 02109 // 02110 02111 ID(SmbsLost) = 0L; 02112 ID(HeapReferenceCount) = 1; 02113 02114 // 02115 // Signal to the FSP that we are ready to start capturing SMBs. 02116 // 02117 02118 KeSetEvent( &ID(ActiveEvent), 0, FALSE ); 02119 02120 // 02121 // Main loop, executed until the thread is terminated. 02122 // 02123 02124 TrPrint(( "%s!SmbTraceThread: Tracing started.\n", ID(ComponentName) )); 02125 02126 Looping = TRUE; 02127 while( Looping ) { 02128 02129 TrPrint(( "%s!SmbTraceThread: WaitForMultiple.\n", ID(ComponentName) )); 02130 status = KeWaitForMultipleObjects( 02131 NUMBER_OF_BLOCKING_OBJECTS, 02132 &waitObjects[0], 02133 WaitAny, 02134 UserRequest, 02135 KernelMode, 02136 FALSE, 02137 NULL, 02138 #if NUMBER_OF_BLOCKING_OBJECTS > THREAD_WAIT_OBJECTS 02139 &waitBlocks[0] 02140 #else 02141 NULL 02142 #endif 02143 ); 02144 02145 if ( !NT_SUCCESS(status) ) { 02146 TrPrint(( 02147 "%s!SmbTraceThreadEntry: KeWaitForMultipleObjectsfailed: %X\n", 02148 ID(ComponentName), status )); 02149 } else { 02150 TrPrint(( 02151 "%s!SmbTraceThreadEntry: %lx\n", 02152 ID(ComponentName), status )); 02153 } 02154 02155 switch( status ) { 02156 02157 case STATUS_WAIT_TERMINATIONEVENT: 02158 02159 // 02160 // Stop looping, and then proceed to clean up and die. 02161 // 02162 02163 Looping = FALSE; 02164 break; 02165 02166 case STATUS_WAIT_APPTERMINATIONEVENT: 02167 02168 // Turn off the event so we don't go in a tight loop 02169 KeResetEvent(&ID(AppTerminationEvent)); 02170 02171 // 02172 // Inform the app that it is time to die. The NULL SMB 02173 // sent here may not be the next to be processed by the 02174 // app, but the ApplicationStop bit will be detected 02175 // immediately. 02176 // 02177 02178 ID(TableHeader)->ApplicationStop = TRUE; 02179 SmbTraceToClient( NULL, 0, NULL, Component ); 02180 02181 break; 02182 02183 case STATUS_WAIT_NEEDMEMORYEVENT: 02184 02185 // Turn off the event so we don't go in a loop. 02186 KeResetEvent(&ID(NeedMemoryEvent)); 02187 // 02188 // Do a garbage collection, freeing all memory that is 02189 // allocated in the shared memory but that has been read 02190 // by the client. 02191 // 02192 02193 SmbTraceFreeMemory( Component ); 02194 02195 break; 02196 02197 case STATUS_WAIT_QUEUESEMAPHORE: 02198 02199 // 02200 // If any get through once we've gone into AppWaiting 02201 // state, don't bother sending them on, they're not 02202 // going to get processed. 02203 // 02204 02205 if ( ID(TraceState) == TraceAppWaiting ) { 02206 SmbTraceEmptyQueue( Component ); 02207 break; 02208 } 02209 02210 // 02211 // Remove the first element in the our queue. A 02212 // work item is represented by our header followed by 02213 // an SMB. We must free the entry after we are done 02214 // with it. 02215 // 02216 02217 listEntry = ExInterlockedRemoveHeadList( 02218 &ID(Queue), 02219 &ID(QueueInterlock) 02220 ); 02221 02222 if ( listEntry != NULL ) { 02223 02224 // 02225 // Get the address of the queue entry. 02226 // 02227 02228 queueEntry = CONTAINING_RECORD( 02229 listEntry, 02230 SMBTRACE_QUEUE_ENTRY, 02231 ListEntry 02232 ); 02233 02234 // 02235 // If the data is in non-paged pool, move it to shared 02236 // memory and free the non-paged pool before passing 02237 // the SMB to the client. Note that in this case, 02238 // there's no need to signal anyone. They ain't waiting. 02239 // 02240 02241 if ( queueEntry->BufferNonPaged ) { 02242 02243 // 02244 // Server never uses non-paged pool. 02245 // 02246 02247 ASSERT( Component != SMBTRACE_SERVER ); 02248 02249 buffer = RtlAllocateHeap( ID(PortMemoryHeap), 0, 02250 queueEntry->SmbLength ); 02251 02252 if ( buffer == NULL ) { 02253 02254 LOCK_INC_ID(SmbsLost); 02255 02256 ExFreePool( queueEntry->Buffer ); 02257 ExFreePool( queueEntry ); 02258 02259 break; 02260 02261 } 02262 02263 RtlCopyMemory( buffer, queueEntry->Buffer, 02264 queueEntry->SmbLength ); 02265 02266 ExFreePool( queueEntry->Buffer ); 02267 02268 // 02269 // Send it off. Because the original SMB is long 02270 // dead, we don't pass its real address along (not 02271 // that we have it, anyway.) 02272 // 02273 02274 ASSERT( queueEntry->SmbAddress == NULL ); 02275 02276 SmbTraceToClient( 02277 buffer, 02278 queueEntry->SmbLength, 02279 NULL, 02280 Component 02281 ); 02282 02283 } else { 02284 02285 // 02286 // Enter the SMB into the table and send it to the 02287 // client. Can block in slow mode. When it does so, we'll 02288 // signal the applicable thread. 02289 // 02290 02291 SmbTraceToClient( 02292 queueEntry->Buffer, 02293 queueEntry->SmbLength, 02294 queueEntry->SmbAddress, 02295 Component 02296 ); 02297 02298 if ( queueEntry->WaitEvent != NULL ) { 02299 KeSetEvent( queueEntry->WaitEvent, 0, FALSE ); 02300 } 02301 } 02302 02303 // 02304 // Now, we must free the queue entry. 02305 // 02306 02307 ExFreePool( queueEntry ); 02308 02309 } 02310 02311 break; 02312 02313 default: 02314 break; 02315 } 02316 02317 } 02318 02319 // 02320 // Clean up! 02321 // 02322 TrPrint(( "%s!SmbTraceThread: Tracing clean up.\n", ID(ComponentName) )); 02323 02324 SmbTraceDereferenceHeap( Component ); 02325 02326 SmbTraceEmptyQueue( Component ); 02327 02328 // 02329 // Signal to SmbTraceStop that we're dying. 02330 // 02331 02332 TrPrint(( "%s!SmbTraceThread: Tracing terminated.\n", ID(ComponentName) )); 02333 02334 KeSetEvent( &ID(TerminatedEvent), 0, FALSE ); 02335 02336 // 02337 // Kill this thread. 02338 // 02339 02340 status = PsTerminateSystemThread( STATUS_SUCCESS ); 02341 02342 // Shouldn't get here 02343 TrPrint(( 02344 "%s!SmbTraceThreadEntry: PsTerminateSystemThread() failed: %X\n", 02345 ID(ComponentName), status )); 02346 02347 } // SmbTraceThreadEntry

VOID SmbTraceToClient IN PVOID  Smb,
IN CLONG  SmbLength,
IN PVOID  SmbAddress,
IN SMBTRACE_COMPONENT  Component
 

Definition at line 2425 of file smbtrsup.c.

References ASSERT, FALSE, ID, KeResetEvent(), KernelMode, L, LOCK_INC_ID, LOCK_ZERO_ID, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, PsGetCurrentProcess, RtlFreeHeap, TraceRunning, and TrPrint.

Referenced by SmbTraceThreadEntry().

02434 : 02435 02436 Enter an SMB already found in shared memory into the table. Set 02437 an event for the client. If there is no table space, the SMB is 02438 not saved. If in slow mode, wait for the client to finish with 02439 and then free the memory occupied by the SMB. 02440 02441 Arguments: 02442 02443 Smb - a pointer to the SMB (which is ALREADY in shared memory). 02444 Can be NULL, indicating no new SMB is to be added, but the 02445 application is to be signalled anyway. 02446 02447 SmbLength - the length of the SMB. 02448 02449 SmbAddress - the address of the real SMB, not in shared memory. 02450 02451 Component - Context from which we're called: server or redirector 02452 02453 Return Value: 02454 02455 None 02456 02457 --*/ 02458 02459 { 02460 NTSTATUS status; 02461 PVOID buffer; 02462 PSMBTRACE_TABLE_ENTRY tableEntry; 02463 ULONG tableIndex; 02464 02465 PAGED_CODE(); 02466 02467 // 02468 // Reset DoneSmbEvent so we can determine when the request has been processed 02469 // 02470 02471 if ( ID(SingleSmbMode) ) { 02472 PKEVENT DoneEvent; 02473 02474 TrPrint(( "%s!SmbTraceToClient: Reset DoneSmbEvent, handle %x, process %x.\n", 02475 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 02476 02477 status = ObReferenceObjectByHandle( ID(DoneSmbEvent), 02478 EVENT_MODIFY_STATE, 02479 NULL, 02480 KernelMode, 02481 (PVOID *)&DoneEvent, 02482 NULL 02483 ); 02484 02485 ASSERT ( NT_SUCCESS(status) ); 02486 02487 KeResetEvent(DoneEvent); 02488 02489 ObDereferenceObject(DoneEvent); 02490 } 02491 02492 if (Smb != NULL) { 02493 02494 // 02495 // See if there is room in the table for a pointer to our SMB. 02496 // 02497 02498 if ( ID(TableHeader)->NextFree == ID(TableHeader)->HighestConsumed ) { 02499 // Tough luck. No memory in the table, this SMB is lost. 02500 LOCK_INC_ID( SmbsLost ); 02501 RtlFreeHeap( ID(PortMemoryHeap), 0, Smb ); 02502 return; 02503 } 02504 02505 tableIndex = ID(TableHeader)->NextFree; 02506 02507 tableEntry = ID(Table) + tableIndex; 02508 02509 // 02510 // Record the number of SMBs that were lost before this one and 02511 // (maybe) zero the count for the next one. 02512 // 02513 02514 tableEntry->NumberMissed = ID(SmbsLost); 02515 02516 if ( tableEntry->NumberMissed != 0 ) { 02517 LOCK_ZERO_ID(SmbsLost); 02518 } 02519 02520 // 02521 // Check if this table entry has been used but its memory has not 02522 // been freed yet. If so, free it. 02523 // 02524 if ( tableEntry->BufferOffset != 0L ) { 02525 02526 buffer = (PVOID)( (ULONG_PTR)tableEntry->BufferOffset 02527 + (ULONG_PTR)ID(PortMemoryBase) ); 02528 02529 RtlFreeHeap( ID(PortMemoryHeap), 0, buffer); 02530 tableEntry->BufferOffset = 0L; 02531 } 02532 02533 // 02534 // Record the location and size of this SMB in the table. 02535 // 02536 02537 tableEntry->BufferOffset = (ULONG)((ULONG_PTR)Smb - (ULONG_PTR)ID(PortMemoryBase)); 02538 tableEntry->SmbLength = SmbLength; 02539 02540 // 02541 // Record the real address of the actual SMB (i.e. not the shared 02542 // memory copy) if it's available. 02543 // 02544 02545 tableEntry->SmbAddress = SmbAddress; 02546 02547 // 02548 // Increment the Next Free counter. 02549 // 02550 02551 ID(TableHeader)->NextFree = (tableIndex + 1) % ID(TableSize); 02552 02553 } 02554 02555 02556 // 02557 // Unlock the client so it will process this new SMB. 02558 // 02559 02560 TrPrint(( "%s!SmbTraceToClient: Set NewSmbEvent.\n", ID(ComponentName) )); 02561 status = ZwSetEvent( ID(NewSmbEvent), NULL ); 02562 02563 // 02564 // When stopping the trace we set TraceState to TraceStopping and then 02565 // DoneSmbEvent. This prevents this routine from blocking indefinitely 02566 // because it Resets DoneSmbEvent processes the Smb and then checks TraceState 02567 // before blocking. 02568 // 02569 if (( ID(SingleSmbMode) ) && 02570 ( ID(TraceState) == TraceRunning )) { 02571 02572 // 02573 // Wait for the app to acknowledge that the SMB has been 02574 // processed. 02575 // 02576 02577 TrPrint(( "%s!SmbTraceToClient: Waiting for DoneSmbEvent, handle %x, process %x.\n", 02578 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 02579 status = ZwWaitForSingleObject( 02580 ID(DoneSmbEvent), 02581 FALSE, 02582 NULL 02583 ); 02584 02585 TrPrint(( "%s!SmbTraceToClient: DoneSmbEvent is set, handle %x, process %x.\n", 02586 ID(ComponentName), ID(DoneSmbEvent), PsGetCurrentProcess())); 02587 ASSERT( NT_SUCCESS(status) ); 02588 02589 if (Smb != NULL) { 02590 02591 tableEntry->BufferOffset = 0L; 02592 RtlFreeHeap( ID(PortMemoryHeap), 0, Smb); 02593 } 02594 02595 } 02596 02597 return; 02598 02599 } // SmbTraceToClient


Variable Documentation

BOOLEAN SmbTraceActive[] = {FALSE, FALSE}
 

Definition at line 333 of file smbtrsup.c.

Referenced by SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceStart(), and SmbTraceStop().

INSTANCE_DATA SmbTraceData[]
 

Definition at line 278 of file smbtrsup.c.

Referenced by SmbTraceStart().

HANDLE SmbTraceDiscardableCodeHandle = 0
 

Definition at line 337 of file smbtrsup.c.

Referenced by SmbTraceStart(), and SmbTraceStop().

HANDLE SmbTraceDiscardableDataHandle = 0
 

Definition at line 340 of file smbtrsup.c.

Referenced by SmbTraceStart(), and SmbTraceStop().

BOOLEAN SmbTraceTransitioning[] = {FALSE, FALSE}
 

Definition at line 334 of file smbtrsup.c.


Generated on Sat May 15 19:45:39 2004 for test by doxygen 1.3.7