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

adtlog.c File Reference

#include <nt.h>
#include <ntos.h>
#include <zwapi.h>
#include "sep.h"
#include "sertlp.h"
#include "adt.h"
#include "adtp.h"
#include "rmp.h"

Go to the source code of this file.

Functions

VOID SepAdtLogAuditRecord (IN PSE_ADT_PARAMETER_ARRAY AuditParameters)
VOID SepAuditFailed (VOID)
NTSTATUS SepAdtMarshallAuditRecord (IN PSE_ADT_PARAMETER_ARRAY AuditParameters, OUT PSE_ADT_PARAMETER_ARRAY *MarshalledAuditParameters, OUT PSEP_RM_LSA_MEMORY_TYPE RecordMemoryType)
VOID SepAdtSetAuditLogInformation (IN PPOLICY_AUDIT_LOG_INFO AuditLogInformation)
NTSTATUS SepAdtCopyToLsaSharedMemory (IN HANDLE LsaProcessHandle, IN PVOID Buffer, IN ULONG BufferLength, OUT PVOID *LsaBufferAddress)
BOOLEAN SepQueueWorkItem (IN PSEP_LSA_WORK_ITEM LsaWorkItem, IN BOOLEAN ForceQueue)
PSEP_LSA_WORK_ITEM SepDequeueWorkItem (VOID)


Function Documentation

NTSTATUS SepAdtCopyToLsaSharedMemory IN HANDLE  LsaProcessHandle,
IN PVOID  Buffer,
IN ULONG  BufferLength,
OUT PVOID *  LsaBufferAddress
 

Definition at line 504 of file adtlog.c.

References ASSERT, Buffer, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and Status.

Referenced by SepRmCallLsa().

00513 : 00514 00515 This function allocates memory shared with the LSA and optionally copies 00516 a given buffer to it. 00517 00518 Arguments: 00519 00520 LsaProcessHandle - Specifies a handle to the Lsa Process. 00521 00522 Buffer - Pointer to the buffer to be copied. 00523 00524 BufferLength - Length of buffer. 00525 00526 LsaBufferAddress - Receives the address of the buffer valid in the 00527 Lsa process context. 00528 00529 Return Value: 00530 00531 NTSTATUS - Standard Nt Result Code 00532 00533 Result codes returned by called routines. 00534 --*/ 00535 00536 { 00537 NTSTATUS Status, SecondaryStatus; 00538 PVOID OutputLsaBufferAddress = NULL; 00539 SIZE_T RegionSize = BufferLength; 00540 00541 PAGED_CODE(); 00542 00543 Status = ZwAllocateVirtualMemory( 00544 LsaProcessHandle, 00545 &OutputLsaBufferAddress, 00546 0, 00547 &RegionSize, 00548 MEM_COMMIT, 00549 PAGE_READWRITE 00550 ); 00551 00552 if (!NT_SUCCESS(Status)) { 00553 00554 goto CopyToLsaSharedMemoryError; 00555 } 00556 00557 Status = ZwWriteVirtualMemory( 00558 LsaProcessHandle, 00559 OutputLsaBufferAddress, 00560 Buffer, 00561 BufferLength, 00562 NULL 00563 ); 00564 00565 if (!NT_SUCCESS(Status)) { 00566 00567 goto CopyToLsaSharedMemoryError; 00568 } 00569 00570 *LsaBufferAddress = OutputLsaBufferAddress; 00571 return(Status); 00572 00573 CopyToLsaSharedMemoryError: 00574 00575 // 00576 // If we allocated memory, free it. 00577 // 00578 00579 if (OutputLsaBufferAddress != NULL) { 00580 00581 RegionSize = 0; 00582 00583 SecondaryStatus = ZwFreeVirtualMemory( 00584 LsaProcessHandle, 00585 &OutputLsaBufferAddress, 00586 &RegionSize, 00587 MEM_RELEASE 00588 ); 00589 00590 ASSERT(NT_SUCCESS(SecondaryStatus)); 00591 00592 OutputLsaBufferAddress = NULL; 00593 } 00594 00595 return(Status); 00596 }

VOID SepAdtLogAuditRecord IN PSE_ADT_PARAMETER_ARRAY  AuditParameters  ) 
 

Definition at line 52 of file adtlog.c.

References _SEP_LSA_WORK_ITEM::CleanupFunction, _SEP_LSA_WORK_ITEM::CommandNumber, _SEP_LSA_WORK_ITEM::CommandParams, _SEP_LSA_WORK_ITEM::CommandParamsLength, _SEP_LSA_WORK_ITEM::CommandParamsMemoryType, ExAllocatePoolWithTag, ExFreePool(), FALSE, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _SEP_LSA_WORK_ITEM::ReplyBuffer, _SEP_LSA_WORK_ITEM::ReplyBufferLength, SEP_LSA_WORK_ITEM, SepAdtMarshallAuditRecord(), SepAuditFailed(), SepAuditRecord, SepCrashOnAuditFail, SepQueueWorkItem(), Status, _SEP_LSA_WORK_ITEM::Tag, and TRUE.

Referenced by SeAuditHandleDuplication(), SeAuditProcessCreation(), SeAuditProcessExit(), SepAdtCloseObjectAuditAlarm(), SepAdtDeleteObjectAuditAlarm(), SepAdtGenerateDiscardAudit(), SepAdtHandleAuditAlarm(), SepAdtObjectReferenceAuditAlarm(), SepAdtOpenObjectAuditAlarm(), SepAdtOpenObjectForDeleteAuditAlarm(), SepAdtPrivilegedServiceAuditAlarm(), and SepAdtPrivilegeObjectAuditAlarm().

00058 : 00059 00060 This function manages the logging of Audit Records. It provides the 00061 single interface to the Audit Logging component from the Audit/Alarm 00062 generation routines. The function constructs an Audit Record in 00063 self-relative format from the information provided and appends it to 00064 the Audit Record Queue, a doubly-linked list of Audit Records awaiting 00065 output to the Audit Log. A dedicated thread reads this queue, writing 00066 Audit Records to the Audit Log and removing them from the Audit Queue. 00067 00068 Arguments: 00069 00070 AuditEventType - Specifies the type of the Audit Event described by 00071 the audit information provided. 00072 00073 AuditInformation - Pointer to buffer containing captured auditing 00074 information related to an Audit Event of type AuditEventType. 00075 00076 Return Value: 00077 00078 STATUS_SUCCESS 00079 STATUS_UNSUCCESSFUL - Audit record was not queued 00080 STATUS_INSUFFICIENT_RESOURCES - unable to allocate heap 00081 00082 --*/ 00083 00084 { 00085 NTSTATUS Status; 00086 PSEP_LSA_WORK_ITEM AuditWorkItem; 00087 00088 PAGED_CODE(); 00089 00090 AuditWorkItem = ExAllocatePoolWithTag( PagedPool, sizeof( SEP_LSA_WORK_ITEM ), 'iAeS' ); 00091 00092 if ( AuditWorkItem == NULL ) { 00093 00094 SepAuditFailed(); 00095 return; 00096 } 00097 00098 AuditWorkItem->Tag = SepAuditRecord; 00099 AuditWorkItem->CommandNumber = LsapWriteAuditMessageCommand; 00100 AuditWorkItem->ReplyBuffer = NULL; 00101 AuditWorkItem->ReplyBufferLength = 0; 00102 AuditWorkItem->CleanupFunction = NULL; 00103 00104 // 00105 // Build an Audit record in self-relative format from the supplied 00106 // Audit Information. 00107 // 00108 00109 Status = SepAdtMarshallAuditRecord( 00110 AuditParameters, 00111 (PSE_ADT_PARAMETER_ARRAY *) &AuditWorkItem->CommandParams.BaseAddress, 00112 &AuditWorkItem->CommandParamsMemoryType 00113 ); 00114 00115 if (NT_SUCCESS(Status)) { 00116 00117 // 00118 // Extract the length of the Audit Record. Store it as the length 00119 // of the Command Parameters buffer. 00120 // 00121 00122 AuditWorkItem->CommandParamsLength = 00123 ((PSE_ADT_PARAMETER_ARRAY) AuditWorkItem->CommandParams.BaseAddress)->Length; 00124 00125 // 00126 // If we're going to crash on a discarded audit, ignore the queue bounds 00127 // check and force the item onto the queue. 00128 // 00129 00130 if (!SepQueueWorkItem( AuditWorkItem, (BOOLEAN)(SepCrashOnAuditFail ? TRUE : FALSE) )) { 00131 00132 ExFreePool( AuditWorkItem->CommandParams.BaseAddress ); 00133 ExFreePool( AuditWorkItem ); 00134 00135 // 00136 // We failed to put the record on the queue. Take whatever action is 00137 // appropriate. 00138 // 00139 00140 SepAuditFailed(); 00141 } 00142 00143 } else { 00144 00145 ExFreePool( AuditWorkItem ); 00146 SepAuditFailed(); 00147 } 00148 }

NTSTATUS SepAdtMarshallAuditRecord IN PSE_ADT_PARAMETER_ARRAY  AuditParameters,
OUT PSE_ADT_PARAMETER_ARRAY *  MarshalledAuditParameters,
OUT PSEP_RM_LSA_MEMORY_TYPE  RecordMemoryType
 

Definition at line 264 of file adtlog.c.

References ASSERT, ExAllocatePoolWithTag, FALSE, NULL, PAGED_CODE, PagedPool, and SourceString.

Referenced by SepAdtLogAuditRecord().

00272 : 00273 00274 This routine will take an AuditParamters structure and create 00275 a new AuditParameters structure that is suitable for sending 00276 to LSA. It will be in self-relative form and allocated as 00277 a single chunk of memory. 00278 00279 Arguments: 00280 00281 00282 AuditParameters - A filled in set of AuditParameters to be marshalled. 00283 00284 MarshalledAuditParameters - Returns a pointer to a block of heap memory 00285 containing the passed AuditParameters in self-relative form suitable 00286 for passing to LSA. 00287 00288 00289 Return Value: 00290 00291 None. 00292 00293 --*/ 00294 00295 { 00296 ULONG i; 00297 ULONG TotalSize = sizeof( SE_ADT_PARAMETER_ARRAY ); 00298 PUNICODE_STRING TargetString; 00299 PCHAR Base; 00300 ULONG BaseIncr; 00301 00302 PAGED_CODE(); 00303 00304 // 00305 // Calculate the total size required for the passed AuditParameters 00306 // block. This calculation will probably be an overestimate of the 00307 // amount of space needed, because data smaller that 2 dwords will 00308 // be stored directly in the parameters structure, but their length 00309 // will be counted here anyway. The overestimate can't be more than 00310 // 24 dwords, and will never even approach that amount, so it isn't 00311 // worth the time it would take to avoid it. 00312 // 00313 00314 for (i=0; i<AuditParameters->ParameterCount; i++) { 00315 TotalSize += (ULONG)LongAlignSize(AuditParameters->Parameters[i].Length); 00316 } 00317 00318 // 00319 // Allocate a big enough block of memory to hold everything. 00320 // If it fails, quietly abort, since there isn't much else we 00321 // can do. 00322 // 00323 00324 *MarshalledAuditParameters = ExAllocatePoolWithTag( PagedPool, TotalSize, 'pAeS' ); 00325 00326 if (*MarshalledAuditParameters == NULL) { 00327 00328 *RecordMemoryType = SepRmNoMemory; 00329 return(STATUS_INSUFFICIENT_RESOURCES); 00330 } 00331 00332 *RecordMemoryType = SepRmPagedPoolMemory; 00333 00334 RtlCopyMemory ( 00335 *MarshalledAuditParameters, 00336 AuditParameters, 00337 sizeof( SE_ADT_PARAMETER_ARRAY ) 00338 ); 00339 00340 (*MarshalledAuditParameters)->Length = TotalSize; 00341 (*MarshalledAuditParameters)->Flags = SE_ADT_PARAMETERS_SELF_RELATIVE; 00342 00343 // 00344 // Start walking down the list of parameters and marshall them 00345 // into the target buffer. 00346 // 00347 00348 Base = (PCHAR) ((PCHAR)(*MarshalledAuditParameters) + sizeof( SE_ADT_PARAMETER_ARRAY )); 00349 00350 for (i=0; i<AuditParameters->ParameterCount; i++) { 00351 00352 00353 switch (AuditParameters->Parameters[i].Type) { 00354 case SeAdtParmTypeNone: 00355 case SeAdtParmTypeUlong: 00356 case SeAdtParmTypeLogonId: 00357 case SeAdtParmTypeNoLogonId: 00358 case SeAdtParmTypeAccessMask: 00359 { 00360 // 00361 // Nothing to do for this 00362 // 00363 00364 break; 00365 00366 } 00367 case SeAdtParmTypeString: 00368 case SeAdtParmTypeFileSpec: 00369 { 00370 PUNICODE_STRING SourceString; 00371 // 00372 // We must copy the body of the unicode string 00373 // and then copy the body of the string. Pointers 00374 // must be turned into offsets. 00375 00376 TargetString = (PUNICODE_STRING)Base; 00377 00378 SourceString = AuditParameters->Parameters[i].Address; 00379 00380 *TargetString = *SourceString; 00381 00382 // 00383 // Reset the data pointer in the output parameters to 00384 // 'point' to the new string structure. 00385 // 00386 00387 (*MarshalledAuditParameters)->Parameters[i].Address = Base - (ULONG_PTR)(*MarshalledAuditParameters); 00388 00389 Base += sizeof( UNICODE_STRING ); 00390 00391 RtlCopyMemory( Base, SourceString->Buffer, SourceString->Length ); 00392 00393 // 00394 // Make the string buffer in the target string point to where we 00395 // just copied the data. 00396 // 00397 00398 TargetString->Buffer = (PWSTR)(Base - (ULONG_PTR)(*MarshalledAuditParameters)); 00399 00400 BaseIncr = (ULONG)LongAlignSize(SourceString->Length); 00401 00402 Base += BaseIncr; 00403 00404 break; 00405 } 00406 00407 // 00408 // Handle types where we simply copy the buffer. 00409 // 00410 case SeAdtParmTypeSid: 00411 case SeAdtParmTypePrivs: 00412 case SeAdtParmTypeObjectTypes: 00413 { 00414 // 00415 // Copy the data into the output buffer 00416 // 00417 00418 RtlCopyMemory( Base, 00419 AuditParameters->Parameters[i].Address, 00420 AuditParameters->Parameters[i].Length ); 00421 00422 // 00423 // Reset the 'address' of the data to be its offset in the 00424 // buffer. 00425 // 00426 00427 (*MarshalledAuditParameters)->Parameters[i].Address = Base - (ULONG_PTR)(*MarshalledAuditParameters); 00428 00429 Base += (ULONG)LongAlignSize( AuditParameters->Parameters[i].Length ); 00430 00431 00432 break; 00433 } 00434 default: 00435 { 00436 // 00437 // We got passed junk, complain. 00438 // 00439 00440 ASSERT( FALSE ); 00441 break; 00442 } 00443 } 00444 } 00445 00446 return( STATUS_SUCCESS ); 00447 }

VOID SepAdtSetAuditLogInformation IN PPOLICY_AUDIT_LOG_INFO  AuditLogInformation  ) 
 

Definition at line 451 of file adtlog.c.

References PAGED_CODE, SepAdtLogInformation, SepRmAcquireDbWriteLock, and SepRmReleaseDbWriteLock.

Referenced by SepRmSetAuditLogWrkr().

00457 : 00458 00459 This function stores Audit Log Information in the Reference Monitor's 00460 in-memory database. This information contains parameters such as Audit 00461 Log size etc. It is the caller's responsibility to ensure that the 00462 supplied information is valid. 00463 00464 NOTE: After initialization, this function is only called by the LSA 00465 via a Reference Monitor command. This is a necessary restriction 00466 because the Audit Log Information stored in the LSA Database must 00467 remain in sync 00468 00469 Arguments: 00470 00471 AuditLogInformation - Pointer to Audit Log Information structure. 00472 00473 Return Value: 00474 00475 None. 00476 00477 --*/ 00478 00479 { 00480 PAGED_CODE(); 00481 00482 // 00483 // Acquire Reference Monitor Database write lock. 00484 // 00485 00486 SepRmAcquireDbWriteLock(); 00487 00488 // 00489 // Write the information 00490 // 00491 00492 SepAdtLogInformation = *AuditLogInformation; 00493 00494 // 00495 // Release Reference Monitor Database write lock 00496 // 00497 00498 SepRmReleaseDbWriteLock(); 00499 }

VOID SepAuditFailed VOID   ) 
 

Definition at line 153 of file adtlog.c.

References ASSERT, FALSE, KeBugCheck(), KeyName, L, NT_SUCCESS, NTSTATUS(), NULL, RtlInitUnicodeString(), SepCrashOnAuditFail, Status, and ValueName.

Referenced by SepAdtLogAuditRecord().

00159 : 00160 00161 Bugchecks the system due to a missed audit (optional requirement 00162 for C2 compliance). 00163 00164 Arguments: 00165 00166 None. 00167 00168 Return Value: 00169 00170 None. 00171 00172 --*/ 00173 00174 { 00175 NTSTATUS Status; 00176 OBJECT_ATTRIBUTES Obja; 00177 HANDLE KeyHandle; 00178 UNICODE_STRING KeyName; 00179 UNICODE_STRING ValueName; 00180 UCHAR NewValue; 00181 00182 ASSERT(sizeof(UCHAR) == sizeof(BOOLEAN)); 00183 00184 if (!SepCrashOnAuditFail) { 00185 return; 00186 } 00187 00188 // 00189 // Turn off flag in the registry that controls crashing on audit failure 00190 // 00191 00192 RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa"); 00193 00194 InitializeObjectAttributes( &Obja, 00195 &KeyName, 00196 OBJ_CASE_INSENSITIVE | 00197 OBJ_KERNEL_HANDLE, 00198 NULL, 00199 NULL 00200 ); 00201 do { 00202 00203 Status = ZwOpenKey( 00204 &KeyHandle, 00205 KEY_SET_VALUE, 00206 &Obja 00207 ); 00208 00209 } while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY)); 00210 00211 // 00212 // If the LSA key isn't there, he's got big problems. But don't crash. 00213 // 00214 00215 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { 00216 SepCrashOnAuditFail = FALSE; 00217 return; 00218 } 00219 00220 if (!NT_SUCCESS( Status )) { 00221 goto bugcheck; 00222 } 00223 00224 RtlInitUnicodeString( &ValueName, CRASH_ON_AUDIT_FAIL_VALUE ); 00225 00226 NewValue = LSAP_ALLOW_ADIMIN_LOGONS_ONLY; 00227 00228 do { 00229 00230 Status = ZwSetValueKey( KeyHandle, 00231 &ValueName, 00232 0, 00233 REG_NONE, 00234 &NewValue, 00235 sizeof(UCHAR) 00236 ); 00237 00238 } while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY)); 00239 ASSERT(NT_SUCCESS(Status)); 00240 00241 if (!NT_SUCCESS( Status )) { 00242 goto bugcheck; 00243 } 00244 00245 do { 00246 00247 Status = ZwFlushKey( KeyHandle ); 00248 00249 } while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY)); 00250 ASSERT(NT_SUCCESS(Status)); 00251 00252 // 00253 // go boom. 00254 // 00255 00256 bugcheck: 00257 00258 KeBugCheck(AUDIT_FAILURE); 00259 }

PSEP_LSA_WORK_ITEM SepDequeueWorkItem VOID   ) 
 

Definition at line 738 of file adtlog.c.

References DbgPrint, ExFreePool(), _SEP_LSA_WORK_ITEM::List, NULL, PAGED_CODE, SepAdtCurrentListLength, SepLockLsaQueue, SepLsaQueue, and SepUnlockLsaQueue.

Referenced by SepRmCallLsa().

00744 : 00745 00746 Removes the top element of the SepLsaQueue and returns the 00747 next element if there is one, NULL otherwise. 00748 00749 Arguments: 00750 00751 None. 00752 00753 Return Value: 00754 00755 A pointer to the next SEP_LSA_WORK_ITEM, or NULL. 00756 00757 --*/ 00758 00759 { 00760 PSEP_LSA_WORK_ITEM OldWorkQueueItem; 00761 00762 PAGED_CODE(); 00763 00764 SepLockLsaQueue(); 00765 00766 OldWorkQueueItem = (PSEP_LSA_WORK_ITEM)RemoveHeadList(&SepLsaQueue); 00767 OldWorkQueueItem->List.Flink = NULL; 00768 ExFreePool( OldWorkQueueItem ); 00769 00770 SepAdtCurrentListLength--; 00771 00772 #if 0 00773 DbgPrint("Removing item\n"); 00774 #endif 00775 00776 if (IsListEmpty( &SepLsaQueue )) { 00777 00778 SepUnlockLsaQueue(); 00779 return( NULL ); 00780 } 00781 00782 // 00783 // We know there's something on the queue now, so we 00784 // can unlock it. 00785 // 00786 00787 SepUnlockLsaQueue(); 00788 return((PSEP_LSA_WORK_ITEM)(&SepLsaQueue)->Flink); 00789 } }

BOOLEAN SepQueueWorkItem IN PSEP_LSA_WORK_ITEM  LsaWorkItem,
IN BOOLEAN  ForceQueue
 

Definition at line 600 of file adtlog.c.

References DbgPrint, DelayedWorkQueue, ExInitializeWorkItem, ExQueueWorkItem(), FALSE, PAGED_CODE, PWORKER_THREAD_ROUTINE, SepAdtCountEventsDiscarded, SepAdtCurrentListLength, SepAdtDiscardingAudits, SepAdtGenerateDiscardAudit(), SepAdtMaxListLength, SepAdtMinListLength, SepExWorkItem, SepLockLsaQueue, SepLsaQueue, SepRmCallLsa(), SepUnlockLsaQueue, TRUE, and _SEP_WORK_ITEM::WorkItem.

Referenced by SepAdtLogAuditRecord(), and SepInformLsaOfDeletedLogon().

00607 : 00608 00609 Puts the passed work item on the queue to be passed to LSA, 00610 and returns the state of the queue upon arrival. 00611 00612 Arguments: 00613 00614 LsaWorkItem - Pointer to the work item to be queued. 00615 00616 ForceQueue - Indicate that this item is not to be discarded 00617 due because of a full queue. 00618 00619 Return Value: 00620 00621 TRUE - The item was successfully queued. 00622 00623 FALSE - The item was not queued and must be discarded. 00624 00625 --*/ 00626 00627 { 00628 BOOLEAN rc = TRUE; 00629 BOOLEAN StartExThread = FALSE ; 00630 00631 PAGED_CODE(); 00632 00633 #if 0 00634 00635 DbgPrint("Queueing an audit\n"); 00636 00637 #endif 00638 00639 SepLockLsaQueue(); 00640 00641 if (SepAdtDiscardingAudits && !ForceQueue) { 00642 00643 if (SepAdtCurrentListLength < SepAdtMinListLength) { 00644 00645 // 00646 // We need to generate an audit saying how many audits we've 00647 // discarded. 00648 // 00649 // Since we have the mutex protecting the Audit queue, we don't 00650 // have to worry about anyone coming along and logging an 00651 // audit. But *we* can, since a mutex may be acquired recursively. 00652 // 00653 // Since we are so protected, turn off the SepAdtDiscardingAudits 00654 // flag here so that we don't come through this path again. 00655 // 00656 00657 SepAdtDiscardingAudits = FALSE; 00658 00659 SepAdtGenerateDiscardAudit(); 00660 #if 0 00661 DbgPrint("Auditing resumed\n"); 00662 #endif 00663 00664 // 00665 // We must assume that that worked, so clear the discard count. 00666 // 00667 00668 SepAdtCountEventsDiscarded = 0; 00669 00670 // 00671 // Our 'audits discarded' audit is now on the queue, 00672 // continue logging the one we started with. 00673 // 00674 00675 } else { 00676 00677 // 00678 // We are not yet below our low water mark. Toss 00679 // this audit and increment the discard count. 00680 // 00681 00682 SepAdtCountEventsDiscarded++; 00683 rc = FALSE; 00684 goto Exit; 00685 } 00686 } 00687 00688 if (SepAdtCurrentListLength < SepAdtMaxListLength || ForceQueue) { 00689 00690 InsertTailList(&SepLsaQueue, &LsaWorkItem->List); 00691 00692 if (++SepAdtCurrentListLength == 1) { 00693 00694 #if 0 00695 DbgPrint("Queueing a work item\n"); 00696 #endif 00697 00698 StartExThread = TRUE ; 00699 } 00700 00701 } else { 00702 00703 // 00704 // There is no room for this audit on the queue, 00705 // so change our state to 'discarding' and tell 00706 // the caller to toss this audit. 00707 // 00708 00709 SepAdtDiscardingAudits = TRUE; 00710 00711 #if 0 00712 DbgPrint("Starting to discard audits\n"); 00713 #endif 00714 00715 rc = FALSE; 00716 } 00717 00718 Exit: 00719 00720 SepUnlockLsaQueue(); 00721 00722 if ( StartExThread ) 00723 { 00724 ExInitializeWorkItem( &SepExWorkItem.WorkItem, 00725 (PWORKER_THREAD_ROUTINE) SepRmCallLsa, 00726 &SepExWorkItem 00727 ); 00728 00729 ExQueueWorkItem( &SepExWorkItem.WorkItem, DelayedWorkQueue ); 00730 } 00731 00732 return( rc ); 00733 }


Generated on Sat May 15 19:42:50 2004 for test by doxygen 1.3.7