test: rmmain.c File Reference

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

# rmmain.c File Reference

`#include <nt.h>`
`#include <ntlsa.h>`
`#include "sep.h"`
`#include <zwapi.h>`
`#include "rmp.h"`
`#include "adt.h"`
`#include "adtp.h"`

Go to the source code of this file.

## Functions

BOOLEAN | SeRmInitPhase1 ()
VOID | SepRmCommandServerThread (IN PVOID StartContext)
BOOLEAN | SepRmCommandServerThreadInit (VOID)
VOID | SepRmComponentTestCommandWrkr (IN PRM_COMMAND_MESSAGE CommandMessage, OUT PRM_REPLY_MESSAGE ReplyMessage)
VOID | SepRmSendCommandToLsaWrkr (IN PRM_COMMAND_MESSAGE CommandMessage, OUT PRM_REPLY_MESSAGE ReplyMessage)
NTSTATUS | SepRmCallLsa (PSEP_WORK_ITEM SepWorkItem)
BOOLEAN | SepRmInitPhase0 ()

## Variables

SEP_RM_COMMAND_WORKER | SepRmCommandDispatch []

## Function Documentation

NTSTATUS SepRmCallLsa | ( | PSEP_WORK_ITEM | SepWorkItem | ) |

Definition at line 907 of file rmmain.c.

References ASSERT, _SEP_LSA_WORK_ITEM::CleanupFunction, _SEP_LSA_WORK_ITEM::CleanupParameter, _SEP_LSA_WORK_ITEM::CommandNumber, _SEP_LSA_WORK_ITEM::CommandParams, _SEP_LSA_WORK_ITEM::CommandParamsLength, _SEP_LSA_WORK_ITEM::CommandParamsMemoryType, DbgPrint, ExFreePool(), KeAttachProcess(), KeDetachProcess(), _SEP_RM_STATE::LsaCommandPortHandle, _SEP_RM_STATE::LsaViewPortMemory, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _EPROCESS::Pcb, PSEP_WORK_ITEM, _SEP_LSA_WORK_ITEM::ReplyBuffer, _SEP_LSA_WORK_ITEM::ReplyBufferLength, ReplyMessage(), _SEP_RM_STATE::RmViewPortMemory, SEP_RM_LSA_SHARED_MEMORY_SIZE, SepAdtCopyToLsaSharedMemory(), SepDequeueWorkItem(), SepLsaHandle, SepLsaQueueLength, SepRmLsaCallProcess, SepRmState, SepWorkListHead, and Status.

Referenced by SepQueueWorkItem().

    00912                    :
    00913
    00914     This function sends a command to the LSA via the LSA Reference Monitor
    00915     Server Command LPC Port.  If the command has parameters, they will be
    00916     copied directly into a message structure and sent via LPC, therefore,
    00917     the supplied parameters may not contain any absolute pointers.  A caller
    00918     must remove pointers by "marshalling" them into the buffer CommandParams.
    00919
    00920     This function will create a queue of requests.  This is in order to allow
    00921     greater throughput for the majority if its callers.  If a thread enters
    00922     this routine and finds the queue empty, it is the responsibility of that
    00923     thread to service all requests that come in while it is working until the
    00924     queue is empty again.  Other threads that enter will simply hook their work
    00925     item onto the queue and exit.
    00926
    00927
    00928     To implement a new LSA command, do the following:
    00929     ================================================
    00930
    00931     (1)  If the command takes no parameters, just call this routine directly
    00932          and provide an LSA worker routine called Lsap<command>Wrkr.  See
    00933          file lsa\server\lsarm.c for examples
    00934
    00935     (2)  If the command takes parameters, provide a routine called
    00936          SepRmSend<command>Command that takes the parameters in unmarshalled
    00937          form and calls SepRmCallLsa() with the command id, marshalled
    00938          parameters, length  of marshalled parameters and pointer to
    00939          optional reply message.  The marshalled parameters are free format:
    00940          the only restriction is that there must be no absolute address
    00941          pointers.  These parameters are all placed in the passed LsaWorkItem
    00942          structure.
    00943
    00944     (3)  In file private\inc\ntrmlsa.h, append a command name  to the
    00945          enumerated type LSA_COMMAND_NUMBER defined in file
    00946          private\inc\ntrmlsa.h.  Change the #define for LsapMaximumCommand
    00947          to reference the new command.
    00948
    00949     (4)  Add the Lsap<command>Wrkr to the command dispatch table structure
    00950          LsapCommandDispatch[] in file lsarm.c.
    00951
    00952     (5)  Add function prototypes to lsap.h and sep.h.
    00953
    00954
    00955 Arguments:
    00956
    00957     LsaWorkItem - Supplies a pointer to an SE_LSA_WORK_ITEM containing the
    00958         information to be passed to LSA.  This structure will be freed
    00959         asynchronously by some invocation of this routine, not necessarily
    00960         in the current context.
    00961
    00962         !THIS PARAMETER MUST BE ALLOCATED OUT OF NONPAGED POOL!
    00963
    00964 Return Value:
    00965
    00966     NTSTATUS - Result Code.  This is either a result code returned from
    00967         trying to send the command/receive the reply, or a status code
    00968         from the command itself.
    00969
    00970 --*/
    00971
    00972 {
    00973     NTSTATUS Status = STATUS_SUCCESS;
    00974     LSA_COMMAND_MESSAGE CommandMessage;
    00975     LSA_REPLY_MESSAGE ReplyMessage;
    00976     PSEP_LSA_WORK_ITEM WorkQueueItem;
    00977     ULONG LocalListLength = 0;
    00978     SIZE_T RegionSize;
    00979     PVOID CopiedCommandParams = NULL;
    00980     PVOID LsaViewCopiedCommandParams = NULL;
    00981
    00982     PAGED_CODE();
    00983
    00984 #if 0
    00985   DbgPrint("Entering SepRmCallLsa\n");
    00986 #endif
    00987
    00988     WorkQueueItem = SepWorkListHead();
    00989
    00990     KeAttachProcess( &SepRmLsaCallProcess->Pcb );
    00991
    00992     while ( WorkQueueItem ) {
    00993
    00994 #if 0
    00995       DbgPrint("Got a work item from head of queue, processing\n");
    00996 #endif
    00997
    00998         //
    00999         // Construct a message for LPC.  First, fill in the message header
    01000         // fields for LPC, specifying the message type and data sizes for
    01001         // the outgoing CommandMessage and the incoming ReplyMessage.
    01002         //
    01003
    01004         CommandMessage.MessageHeader.u2.ZeroInit = 0;
    01005         CommandMessage.MessageHeader.u1.s1.TotalLength =
    01006             ((CSHORT) RM_COMMAND_MESSAGE_HEADER_SIZE +
    01007             (CSHORT) WorkQueueItem->CommandParamsLength);
    01008         CommandMessage.MessageHeader.u1.s1.DataLength =
    01009             CommandMessage.MessageHeader.u1.s1.TotalLength -
    01010             (CSHORT) sizeof(PORT_MESSAGE);
    01011
    01012         ReplyMessage.MessageHeader.u2.ZeroInit = 0;
    01013         ReplyMessage.MessageHeader.u1.s1.DataLength = (CSHORT) WorkQueueItem->ReplyBufferLength;
    01014         ReplyMessage.MessageHeader.u1.s1.TotalLength =
    01015             ReplyMessage.MessageHeader.u1.s1.DataLength +
    01016             (CSHORT) sizeof(PORT_MESSAGE);
    01017
    01018         //
    01019         // Next, fill in the header info needed by the LSA.
    01020         //
    01021
    01022         CommandMessage.CommandNumber = WorkQueueItem->CommandNumber;
    01023         ReplyMessage.ReturnedStatus = STATUS_SUCCESS;
    01024
    01025         //
    01026         // Set up the Command Parameters either in the LPC Command Message
    01027         // itself, in the preallocated Lsa shared memory block, or in a
    01028         // specially allocated block.  The parameters are either
    01029         // immediate (i.e. in the WorkQueueItem itself, or are in a buffer
    01030         // pointed to by the address in the WorkQueueItem.
    01031         //
    01032
    01033         switch (WorkQueueItem->CommandParamsMemoryType) {
    01034
    01035         case SepRmImmediateMemory:
    01036
    01037             //
    01038             // The Command Parameters are in the CommandParams buffer
    01039             // in the Work Queue Item.  Just copy them to the corresponding
    01040             // buffer in the CommandMessage buffer.
    01041             //
    01042
    01043             CommandMessage.CommandParamsMemoryType = SepRmImmediateMemory;
    01044
    01045             RtlCopyMemory(
    01046                 CommandMessage.CommandParams,
    01047                 &WorkQueueItem->CommandParams,
    01048                 WorkQueueItem->CommandParamsLength
    01049                 );
    01050
    01051             break;
    01052
    01053         case SepRmPagedPoolMemory:
    01054         case SepRmUnspecifiedMemory:
    01055
    01056             //
    01057             // The Command Parameters are contained in paged pool memory.
    01058             // Since this memory is is not accessible by the LSA, we must
    01059             // copy of them either to the LPC Command Message Block, or
    01060             // into LSA shared memory.
    01061             //
    01062
    01063             if (WorkQueueItem->CommandParamsLength <= LSA_MAXIMUM_COMMAND_PARAM_SIZE) {
    01064
    01065                 //
    01066                 // Parameters will fit into the LPC Command Message block.
    01067                 //
    01068
    01069                 CopiedCommandParams = CommandMessage.CommandParams;
    01070
    01071                 RtlCopyMemory(
    01072                     CopiedCommandParams,
    01073                     WorkQueueItem->CommandParams.BaseAddress,
    01074                     WorkQueueItem->CommandParamsLength
    01075                     );
    01076
    01077                 CommandMessage.CommandParamsMemoryType = SepRmImmediateMemory;
    01078
    01079             } else {
    01080
    01081                 //
    01082                 // Parameters too large for LPC Command Message block.
    01083                 // If possible, copy them to the preallocated Lsa Shared
    01084                 // Memory block.  If they are too large to fit, copy them
    01085                 // to an individually allocated chunk of Shared Virtual
    01086                 // Memory.
    01087                 //
    01088
    01089                 if (WorkQueueItem->CommandParamsLength <= SEP_RM_LSA_SHARED_MEMORY_SIZE) {
    01090
    01091                     RtlCopyMemory(
    01092                         SepRmState.RmViewPortMemory,
    01093                         WorkQueueItem->CommandParams.BaseAddress,
    01094                         WorkQueueItem->CommandParamsLength
    01095                         );
    01096
    01097                     LsaViewCopiedCommandParams = SepRmState.LsaViewPortMemory;
    01098                     CommandMessage.CommandParamsMemoryType = SepRmLsaCommandPortSharedMemory;
    01099
    01100                 } else {
    01101
    01102                     Status = SepAdtCopyToLsaSharedMemory(
    01103                                  SepLsaHandle,
    01104                                  WorkQueueItem->CommandParams.BaseAddress,
    01105                                  WorkQueueItem->CommandParamsLength,
    01106                                  &LsaViewCopiedCommandParams
    01107                                  );
    01108
    01109                     if (!NT_SUCCESS(Status)) {
    01110
    01111                         //
    01112                         // An error occurred, most likely in allocating
    01113                         // shared virtual memory.  For now, just ignore
    01114                         // the error and discard the Audit Record.  Later,
    01115                         // we may consider generating a warning record
    01116                         // indicating some records lost.
    01117                         //
    01118
    01119                         break;
    01120
    01121                     }
    01122
    01123                     CommandMessage.CommandParamsMemoryType = SepRmLsaCustomSharedMemory;
    01124                 }
    01125
    01126                 //
    01127                 // Buffer has been successfully copied to a shared Lsa
    01128                 // memory buffer.  Place the address of the buffer valid in
    01129                 // the LSA's process context in the Command Message.
    01130                 //
    01131
    01132                 *((PVOID *) CommandMessage.CommandParams) =
    01133                     LsaViewCopiedCommandParams;
    01134
    01135                 CommandMessage.MessageHeader.u1.s1.TotalLength =
    01136                     ((CSHORT) RM_COMMAND_MESSAGE_HEADER_SIZE +
    01137                     (CSHORT) sizeof( LsaViewCopiedCommandParams ));
    01138                 CommandMessage.MessageHeader.u1.s1.DataLength =
    01139                     CommandMessage.MessageHeader.u1.s1.TotalLength -
    01140                     (CSHORT) sizeof(PORT_MESSAGE);
    01141             }
    01142
    01143             //
    01144             // Free input command params buffer if Paged Pool.
    01145             //
    01146
    01147             if (WorkQueueItem->CommandParamsMemoryType == SepRmPagedPoolMemory) {
    01148
    01149                 ExFreePool( WorkQueueItem->CommandParams.BaseAddress );
    01150             }
    01151
    01152             break;
    01153
    01154         default:
    01155
    01156             Status = STATUS_INVALID_PARAMETER;
    01157             break;
    01158         }
    01159
    01160         if (NT_SUCCESS(Status)) {
    01161
    01162             //
    01163             // Send Message to the LSA via the LSA Server Command LPC Port.
    01164             // This must be done in the process in which the handle was created.
    01165             //
    01166
    01167             Status = ZwRequestWaitReplyPort(
    01168                          SepRmState.LsaCommandPortHandle,
    01169                          (PPORT_MESSAGE) &CommandMessage,
    01170                          (PPORT_MESSAGE) &ReplyMessage
    01171                          );
    01172
    01173             //
    01174             // If the command was successful, copy the data back to the output
    01175             // buffer.
    01176             //
    01177
    01178             if (NT_SUCCESS(Status)) {
    01179
    01180                 //
    01181                 // Move output from command (if any) to buffer.  Note that this
    01182                 // is done even if the command returns status, because some status
    01183                 // values are not errors.
    01184                 //
    01185
    01186                 if (ARGUMENT_PRESENT(WorkQueueItem->ReplyBuffer)) {
    01187
    01188                     RtlCopyMemory(
    01189                         WorkQueueItem->ReplyBuffer,
    01190                         ReplyMessage.ReplyBuffer,
    01191                         WorkQueueItem->ReplyBufferLength
    01192                         );
    01193                 }
    01194
    01195                 //
    01196                 // Return status from command.
    01197                 //
    01198
    01199                 Status = ReplyMessage.ReturnedStatus;
    01200
    01201                 if (!NT_SUCCESS(Status)) {
    01202                     KdPrint(("Security: Command sent from RM to LSA returned 0x%lx\n",
    01203                         Status));
    01204                 }
    01205
    01206             } else {
    01207
    01208                 KdPrint(("Security: Sending Command RM to LSA failed 0x%lx\n", Status));
    01209             }
    01210
    01211             //
    01212             // On return from the LPC call to the LSA, we expect the called
    01213             // LSA worker routine to have copied the Command Parameters
    01214             // buffer (if any).  If a custom shared memory boffer was allocated,
    01215             // free it now.
    01216             //
    01217
    01218             if (CommandMessage.CommandParamsMemoryType == SepRmLsaCustomSharedMemory) {
    01219
    01220                 RegionSize = 0;
    01221
    01222                 Status = ZwFreeVirtualMemory(
    01223                              SepLsaHandle,
    01224                              (PVOID *) &CommandMessage.CommandParams,
    01225                              &RegionSize,
    01226                              MEM_RELEASE
    01227                              );
    01228
    01229                 ASSERT(NT_SUCCESS(Status));
    01230             }
    01231
    01232         }
    01233
    01234
    01235         //
    01236         // Clean up.  We must call the cleanup functions on its parameter
    01237         // and then free the used WorkQueueItem itself.
    01238         //
    01239
    01240         if ( ARGUMENT_PRESENT( WorkQueueItem->CleanupFunction)) {
    01241
    01242             (WorkQueueItem->CleanupFunction)(WorkQueueItem->CleanupParameter);
    01243         }
    01244
    01245         //
    01246         // Determine if there is more work to do on this list
    01247         //
    01248
    01249         WorkQueueItem = SepDequeueWorkItem();
    01250 #if 0
    01251       if ( WorkQueueItem ) {
    01252             DbgPrint("Got another item from list, going back\n");
    01253       } else {
    01254           DbgPrint("List is empty, leaving\n");
    01255       }
    01256 #endif
    01257
    01258
    01259     }
    01260
    01261     KeDetachProcess();
    01262
    01263     if ( LocalListLength > SepLsaQueueLength ) {
    01264         SepLsaQueueLength = LocalListLength;
    01265     }
    01266
    01267     return Status;
    01268 }

VOID SepRmCommandServerThread | ( | IN PVOID | StartContext | ) |

Definition at line 309 of file rmmain.c.

References NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, ReplyMessage(), _SEP_RM_STATE::RmCommandPortHandle, SepRmCommandDispatch, SepRmCommandServerThreadInit(), SepRmState, and Status.

Referenced by SeRmInitPhase1().

    00315                    :
    00316
    00317     This function is executed indefinitely by a dedicated permanent thread
    00318     of the Sysinit Process, called the Reference Monitor Server Thread.
    00319     This thread updates Reference Monitor Global State Data by dispatching
    00320     commands sent from the LSA through the the Reference Monitor LPC Command
    00321     Port.  The following steps are repeated indefinitely:
    00322
    00323     o  Initialize RM Command receive and reply buffer headers
    00324     o  Perform remaining Reference Monitor initialization involving LSA
    00325     o  Wait for RM command sent from LSA, send reply to previous command
    00326        (if any)
    00327     o  Validate command
    00328     o  Dispatch to command worker routine to execute command.
    00329
    00330 Arguments:
    00331
    00332     None.
    00333
    00334 Return Value:
    00335
    00336     None.
    00337
    00338 --*/
    00339
    00340 {
    00341     NTSTATUS Status;
    00342     PRM_REPLY_MESSAGE Reply;
    00343     RM_COMMAND_MESSAGE CommandMessage;
    00344     RM_REPLY_MESSAGE ReplyMessage;
    00345
    00346     PAGED_CODE();
    00347
    00348     //
    00349     // Perform the rest of the Reference Monitor initialization, involving
    00350     // synchronization with the LSA or dependency on the LSA having run.
    00351     //
    00352
    00353     if (!SepRmCommandServerThreadInit()) {
    00354
    00355         KdPrint(("Security: Terminating Rm Command Server Thread\n"));
    00356         return;
    00357     }
    00358
    00359     //
    00360     // Initialize LPC port message header type and length fields for the
    00361     // received command message.
    00362     //
    00363
    00364     CommandMessage.MessageHeader.u2.ZeroInit = 0;
    00365     CommandMessage.MessageHeader.u1.s1.TotalLength =
    00366         (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    00367     CommandMessage.MessageHeader.u1.s1.DataLength =
    00368     CommandMessage.MessageHeader.u1.s1.TotalLength -
    00369         (CSHORT) sizeof(PORT_MESSAGE);
    00370
    00371     //
    00372     // Initialize the LPC port message header type and data sizes for
    00373     // for the reply message.
    00374     //
    00375
    00376     ReplyMessage.MessageHeader.u2.ZeroInit = 0;
    00377     ReplyMessage.MessageHeader.u1.s1.TotalLength =
    00378         (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    00379     ReplyMessage.MessageHeader.u1.s1.DataLength =
    00380     ReplyMessage.MessageHeader.u1.s1.TotalLength -
    00381         (CSHORT) sizeof(PORT_MESSAGE);
    00382
    00383     //
    00384     // First time through, there is no reply.
    00385     //
    00386
    00387     Reply = NULL;
    00388
    00389     //
    00390     // Now loop indefinitely, processing incoming Rm commands from the LSA.
    00391     //
    00392
    00393     for(;;) {
    00394
    00395         //
    00396         // Wait for Command, send reply to previous command (if any)
    00397         //
    00398
    00399         Status = ZwReplyWaitReceivePort(
    00400                     SepRmState.RmCommandPortHandle,
    00401                     NULL,
    00402                     (PPORT_MESSAGE) Reply,
    00403                     (PPORT_MESSAGE) &CommandMessage
    00404                     );
    00405
    00406         if (!NT_SUCCESS(Status)) {
    00407
    00408             //
    00409             // malicious user apps can try to connect to this port.  We will
    00410             // fail later, but if their thread vanishes, we'll get a failure
    00411             // here.  Ignore it:
    00412             //
    00413
    00414             if ( Status == STATUS_UNSUCCESSFUL )
    00415             {
    00416                 //
    00417                 // skip it:
    00418                 //
    00419
    00420                 Reply = NULL ;
    00421                 continue;
    00422             }
    00423
    00424             KdPrint(("Security: RM message receive from Lsa failed %lx\n",
    00425                 Status));
    00426
    00427         }
    00428
    00429         //
    00430         // Now dispatch to a routine to handle the command.  Allow
    00431         // command errors to occur without bringing system down just now.
    00432         //
    00433
    00434         if ( CommandMessage.MessageHeader.u2.s2.Type == LPC_REQUEST ) {
    00435             (*(SepRmCommandDispatch[CommandMessage.CommandNumber]))
    00436                 (&CommandMessage, &ReplyMessage);
    00437
    00438             //
    00439             // Initialize the client thread info and message id for the
    00440             // reply message.  First time through, the reply message structure
    00441             // is not used.
    00442             //
    00443
    00444             ReplyMessage.MessageHeader.ClientId =
    00445                 CommandMessage.MessageHeader.ClientId;
    00446             ReplyMessage.MessageHeader.MessageId =
    00447                 CommandMessage.MessageHeader.MessageId;
    00448
    00449             Reply = &ReplyMessage;
    00450
    00451         } else {
    00452
    00453             Reply = NULL;
    00454         }
    00455     }  // end_for
    00456
    00457     //
    00458     // Make compiler ferme la bouche
    00459     //
    00460
    00461     StartContext;
    00462 }

BOOLEAN SepRmCommandServerThreadInit | ( | VOID |  | ) |

Definition at line 466 of file rmmain.c.

References DynamicQos, FALSE, L, _SEP_RM_STATE::LsaCommandPortHandle, _SEP_RM_STATE::LsaCommandPortMemoryDelta, _SEP_RM_STATE::LsaCommandPortSectionHandle, _SEP_RM_STATE::LsaCommandPortSectionSize, _SEP_RM_STATE::LsaInitEventHandle, _SEP_RM_STATE::LsaViewPortMemory, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObjectAttributes, ObReferenceObject, PAGE_SIZE, PAGED_CODE, PsGetCurrentProcess, _SEP_RM_STATE::RmCommandPortHandle, _SEP_RM_STATE::RmViewPortMemory, RtlInitUnicodeString(), SepLsaHandle, SepRmLsaCallProcess, SepRmState, Status, and TRUE.

    00472                    :
    00473
    00474     This function performs initialization of the Reference Monitor Server
    00475     thread.  The following steps are performed.
    00476
    00477     o  Wait on the LSA signalling the event.  When the event is signalled,
    00478        the LSA has already created the LSA Command Server LPC Port
    00479     o  Close the LSA Init Event Handle.  The event is not used again.
    00480     o  Listen for the LSA to connect to the Port
    00481     o  Accept the connection.
    00482     o  Connect to the LSA Command Server LPC Port
    00483
    00484 Arguments:
    00485
    00486     None.
    00487
    00488 Return Value:
    00489
    00490 --*/
    00491
    00492 {
    00493     NTSTATUS Status;
    00494     UNICODE_STRING LsaCommandPortName;
    00495     PORT_MESSAGE ConnectionRequest;
    00496     SECURITY_QUALITY_OF_SERVICE DynamicQos;
    00497     OBJECT_ATTRIBUTES ObjectAttributes;
    00498     PORT_VIEW ClientView;
    00499     REMOTE_PORT_VIEW LsaClientView;
    00500     BOOLEAN BooleanStatus = TRUE;
    00501
    00502     PAGED_CODE();
    00503
    00504     //
    00505     // Save a pointer to our process so we can get back into this process
    00506     // to send commands to the LSA (using a handle to an LPC port created
    00507     // below).
    00508     //
    00509
    00510     SepRmLsaCallProcess = PsGetCurrentProcess();
    00511
    00512     ObReferenceObject(SepRmLsaCallProcess);
    00513
    00514     //
    00515     // Wait on the LSA signalling the event.  This means that the LSA
    00516     // has created its command port, not that LSA initialization is
    00517     // complete.
    00518     //
    00519
    00520     Status = ZwWaitForSingleObject(
    00521                  SepRmState.LsaInitEventHandle,
    00522                  FALSE,
    00523                  NULL);
    00524
    00525     if ( !NT_SUCCESS(Status) ) {
    00526
    00527         KdPrint(("Security Rm Init: Waiting for LSA Init Event failed 0x%lx\n", Status));
    00528         goto RmCommandServerThreadInitError;
    00529     }
    00530
    00531     //
    00532     // Close the LSA Init Event Handle.  The event is not used again.
    00533     //
    00534
    00535     ZwClose(SepRmState.LsaInitEventHandle);
    00536
    00537     //
    00538     // Listen for a connection to be made by the LSA to the Reference Monitor
    00539     // Command Port.  This connection will be made by the LSA process.
    00540     //
    00541
    00542     ConnectionRequest.u1.s1.TotalLength = sizeof(ConnectionRequest);
    00543     ConnectionRequest.u1.s1.DataLength = (CSHORT)0;
    00544     Status = ZwListenPort(
    00545                  SepRmState.RmCommandPortHandle,
    00546                  &ConnectionRequest
    00547                  );
    00548
    00549     if (!NT_SUCCESS(Status)) {
    00550
    00551         KdPrint(("Security Rm Init: Listen to Command Port failed 0x%lx\n",
    00552             Status));
    00553         goto RmCommandServerThreadInitError;
    00554     }
    00555
    00556     //
    00557     // Obtain a handle to the LSA process for use when auditing.
    00558     //
    00559
    00560     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
    00561
    00562     Status = ZwOpenProcess(
    00563                  &SepLsaHandle,
    00564                  PROCESS_VM_OPERATION | PROCESS_VM_WRITE,
    00565                  &ObjectAttributes,
    00566                  &ConnectionRequest.ClientId
    00567                  );
    00568
    00569     if (!NT_SUCCESS(Status)) {
    00570
    00571         KdPrint(("Security Rm Init: Open Listen to Command Port failed 0x%lx\n",
    00572             Status));
    00573         goto RmCommandServerThreadInitError;
    00574     }
    00575
    00576     //
    00577     // Accept the connection made by the LSA process.
    00578     //
    00579
    00580     LsaClientView.Length = sizeof(LsaClientView);
    00581
    00582     Status = ZwAcceptConnectPort(
    00583                  &SepRmState.RmCommandPortHandle,
    00584                  NULL,
    00585                  &ConnectionRequest,
    00586                  TRUE,
    00587                  NULL,
    00588                  &LsaClientView
    00589                  );
    00590
    00591     if (!NT_SUCCESS(Status)) {
    00592
    00593         KdPrint(("Security Rm Init: Accept Connect to Command Port failed 0x%lx\n",
    00594                 Status));
    00595
    00596         goto RmCommandServerThreadInitError;
    00597     }
    00598
    00599     //
    00600     // Complete the connection.
    00601     //
    00602
    00603     Status = ZwCompleteConnectPort(SepRmState.RmCommandPortHandle);
    00604
    00605     if (!NT_SUCCESS(Status)) {
    00606
    00607         KdPrint(("Security Rm Init: Complete Connect to Command Port failed 0x%lx\n",
    00608                 Status));
    00609         goto RmCommandServerThreadInitError;
    00610     }
    00611
    00612     //
    00613     // Set up the security quality of service parameters to use over the
    00614     // Lsa Command LPC port.  Use the most efficient (least overhead) - which
    00615     // is dynamic rather than static tracking.
    00616     //
    00617
    00618     DynamicQos.ImpersonationLevel = SecurityImpersonation;
    00619     DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    00620     DynamicQos.EffectiveOnly = TRUE;
    00621
    00622     //
    00623     // Create the section to be used as unnamed shared memory for
    00624     // communication between the RM and LSA.
    00625     //
    00626
    00627     SepRmState.LsaCommandPortSectionSize.LowPart = PAGE_SIZE;
    00628     SepRmState.LsaCommandPortSectionSize.HighPart = 0;
    00629
    00630     Status = ZwCreateSection(
    00631                  &SepRmState.LsaCommandPortSectionHandle,
    00632                  SECTION_ALL_ACCESS,
    00633                  NULL,                           // ObjectAttributes
    00634                  &SepRmState.LsaCommandPortSectionSize,
    00635                  PAGE_READWRITE,
    00636                  SEC_COMMIT,
    00637                  NULL                            // FileHandle
    00638                  );
    00639
    00640     if (!NT_SUCCESS(Status)) {
    00641
    00642         KdPrint(("Security Rm Init: Create Memory Section for LSA port failed: %X\n", Status));
    00643         goto RmCommandServerThreadInitError;
    00644     }
    00645
    00646     //
    00647     // Set up for a call to NtConnectPort and connect to the LSA port.
    00648     // This setup includes a description of the port memory section so that
    00649     // the LPC connection logic can make the section visible to both the
    00650     // client and server processes.
    00651     //
    00652
    00653     ClientView.Length = sizeof(ClientView);
    00654     ClientView.SectionHandle = SepRmState.LsaCommandPortSectionHandle;
    00655     ClientView.SectionOffset = 0;
    00656     ClientView.ViewSize = SepRmState.LsaCommandPortSectionSize.LowPart;
    00657     ClientView.ViewBase = 0;
    00658     ClientView.ViewRemoteBase = 0;
    00659
    00660     //
    00661     // Set up the security quality of service parameters to use over the
    00662     // port.  Use dynamic tracking so that XACTSRV will impersonate the
    00663     // user that we are impersonating when we call NtRequestWaitReplyPort.
    00664     // If we used static tracking, XACTSRV would impersonate the context
    00665     // when the connection is made.
    00666     //
    00667
    00668     DynamicQos.ImpersonationLevel = SecurityImpersonation;
    00669     DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    00670     DynamicQos.EffectiveOnly = TRUE;
    00671
    00672     //
    00673     // Connect to the Lsa Command LPC Port.  This port is used to send
    00674     // commands from the RM to the LSA.
    00675     //
    00676
    00677     RtlInitUnicodeString( &LsaCommandPortName, L"\\SeLsaCommandPort" );
    00678
    00679     Status = ZwConnectPort(
    00680                  &SepRmState.LsaCommandPortHandle,
    00681                  &LsaCommandPortName,
    00682                  &DynamicQos,
    00683                  &ClientView,
    00684                  NULL,                           // ServerView
    00685                  NULL,                           // MaxMessageLength
    00686                  NULL,                           // ConnectionInformation
    00687                  NULL                            // ConnectionInformationLength
    00688                  );
    00689
    00690     if (!NT_SUCCESS(Status)) {
    00691
    00692         KdPrint(("Security Rm Init: Connect to LSA Port failed 0x%lx\n", Status));
    00693         goto RmCommandServerThreadInitError;
    00694     }
    00695
    00696     //
    00697     // Store information about the section so that we can create pointers
    00698     // meaningful to LSA.
    00699     //
    00700
    00701     SepRmState.RmViewPortMemory = ClientView.ViewBase;
    00702     SepRmState.LsaCommandPortMemoryDelta =
    00703         (LONG)((ULONG_PTR)ClientView.ViewRemoteBase - (ULONG_PTR) ClientView.ViewBase );
    00704     SepRmState.LsaViewPortMemory = ClientView.ViewRemoteBase;
    00705
    00706 /* BugWarning - ScottBi - probably don't need the resource
    00707
    00708     //
    00709     // Create the resource serializing access to the port.  This
    00710     // resource prevents the port and the shared memory from being
    00711     // deleted while worker threads are processing requests.
    00712     //
    00713
    00714     if ( !SepRmState.LsaCommandPortResourceInitialized ) {
    00715
    00716         ExInitializeResource( &SepRmState.LsaCommandPortResource );
    00717         SepRmState.LsaCommandPortResourceInitialized = TRUE;
    00718     }
    00719
    00720     SepRmState.LsaCommandPortActive = TRUE;
    00721
    00722 */
    00723
    00724 RmCommandServerThreadInitFinish:
    00725
    00726     //
    00727     // Dont need this section handle any more, even if returning
    00728     // success.
    00729     //
    00730
    00731     if ( SepRmState.LsaCommandPortSectionHandle != NULL ) {
    00732
    00733        NtClose( SepRmState.LsaCommandPortSectionHandle );
    00734        SepRmState.LsaCommandPortSectionHandle = NULL;
    00735     }
    00736
    00737     //
    00738     // The Reference Monitor Thread has successfully initialized.
    00739     //
    00740
    00741     return BooleanStatus;
    00742
    00743 RmCommandServerThreadInitError:
    00744
    00745     if ( SepRmState.LsaCommandPortHandle != NULL ) {
    00746
    00747        NtClose( SepRmState.LsaCommandPortHandle );
    00748        SepRmState.LsaCommandPortHandle = NULL;
    00749     }
    00750
    00751     BooleanStatus = FALSE;
    00752     goto RmCommandServerThreadInitFinish;
    00753 }

VOID SepRmComponentTestCommandWrkr | ( | IN PRM_COMMAND_MESSAGE | CommandMessage,
|  | OUT PRM_REPLY_MESSAGE | ReplyMessage
| ) |

Definition at line 758 of file rmmain.c.

References ASSERT, PAGED_CODE, and ReplyMessage().

    00765                    :
    00766
    00767     BUGWARNING - Remove this command when other RM commands are implemented.
    00768              Until then, this command is the only way a CT can verify that
    00769              an RM command with parameters is sent correctly.
    00770
    00771     This function processes the Component Test RM command.
    00772     This is a temporary command that can be used to verify that the link
    00773     from RM to LSA is working.  This command verifies that the link
    00774     is working by receiving a ULONG parameter and verifying that it
    00775     has the expected value.
    00776
    00777 Arguments:
    00778
    00779     CommandMessage - Pointer to structure containing RM command message
    00780         information consisting of an LPC PORT_MESSAGE structure followed
    00781         by the command number (RmComponentTestCommand).  This command
    00782         currently has one parameter, a fixed ulong value.
    00783
    00784     ReplyMessage - Pointer to structure containing LSA reply message
    00785         information consisting of an LPC PORT_MESSAGE structure followed
    00786         by the command ReturnedStatus field in which a status code from the
    00787         command will be returned.
    00788
    00789 Return Value:
    00790
    00791     VOID
    00792
    00793 --*/
    00794
    00795 {
    00796     PAGED_CODE();
    00797
    00798     ReplyMessage->ReturnedStatus = STATUS_SUCCESS;
    00799
    00800     //
    00801     // Strict check that command is correct.
    00802     //
    00803
    00804     ASSERT( CommandMessage->CommandNumber == RmComponentTestCommand );
    00805
    00806     KdPrint(("Security: RM Component Test Command Received\n"));
    00807
    00808     //
    00809     // Verify that the parameter value passed is as expected.
    00810     //
    00811
    00812     if (*((ULONG *) CommandMessage->CommandParams) !=
    00813         RM_CT_COMMAND_PARAM_VALUE ) {
    00814
    00815         ReplyMessage->ReturnedStatus = STATUS_INVALID_PARAMETER;
    00816     }
    00817
    00818     return;
    00819 }

BOOLEAN SepRmInitPhase0 | ( |  | ) |

Definition at line 1275 of file rmmain.c.

References PAGED_CODE, and SepRmDbInitialization().

Referenced by SepInitializationPhase0().

    01280                    :
    01281
    01282     This function performs Reference Monitor Phase 0 initialization.
    01283     This includes initializing the reference monitor database to a state
    01284     which allows access validation routines to operate (always granting
    01285     access) prior to the main init of the Reference Monitor in Phase 1
    01286     initialization, without having to check if the RM is initialized.
    01287
    01288
    01289 Arguments:
    01290
    01291     None.
    01292
    01293 Return Value:
    01294
    01295    BOOLEAN - TRUE if successful, else FALSE
    01296
    01297 --*/
    01298
    01299 {
    01300
    01301     BOOLEAN CompletionStatus;
    01302
    01303     PAGED_CODE();
    01304
    01305     CompletionStatus = SepRmDbInitialization();
    01306
    01307     return CompletionStatus;
    01308 }
    }

VOID SepRmSendCommandToLsaWrkr | ( | IN PRM_COMMAND_MESSAGE | CommandMessage,
|  | OUT PRM_REPLY_MESSAGE | ReplyMessage
| ) |

Definition at line 824 of file rmmain.c.

References ASSERT, NULL, PAGED_CODE, and ReplyMessage().

    00831                    :
    00832
    00833     This function carries out the special Rm Send Command To Lsa Command.  This
    00834     command is used only by the ctlsarm component test which checks that
    00835     LSA to RM and RM to LSA communication via LPC is working.
    00836
    00837 Arguments:
    00838
    00839     CommandMessage - Pointer to structure containing RM command message
    00840         information consisting of an LPC PORT_MESSAGE structure followed
    00841         by the command number (RmDisableAuditCommand), followed by the
    00842         command parameters.  The parameters of this special command consists
    00843         of the Command Number of an LSA command and its parameters (if any).
    00844
    00845     ReplyMessage - Pointer to structure containing RM reply message
    00846         information consisting of an LPC PORT_MESSAGE structure followed
    00847         by the command ReturnedStatus field in which a status code from the
    00848         command will be returned.
    00849
    00850 Return Value:
    00851
    00852     VOID
    00853
    00854 --*/
    00855
    00856 {
    00857     //
    00858     // Obtain a pointer to the LSA command's params, and the size of the
    00859     // params in bytes.  If there are no params, set the pointer to NULL.
    00860     //
    00861
    00862     PVOID LsaCommandParams =
    00863         ((RM_SEND_COMMAND_TO_LSA_PARAMS *)
    00864         (CommandMessage->CommandParams))->LsaCommandParams;
    00865     ULONG LsaCommandParamsLength =
    00866         ((RM_SEND_COMMAND_TO_LSA_PARAMS *)
    00867         (CommandMessage->CommandParams))->LsaCommandParamsLength;
    00868
    00869     PAGED_CODE();
    00870
    00871     if (LsaCommandParamsLength == 0) {
    00872
    00873         LsaCommandParams = NULL;
    00874
    00875     }
    00876
    00877     //
    00878     // Strict check that command is correct one for this worker.
    00879     //
    00880
    00881     ASSERT( CommandMessage->CommandNumber == RmSendCommandToLsaCommand );
    00882
    00883     KdPrint(("Security: RM Send Command back to LSA Command Received\n"));
    00884
    00885     ReplyMessage->ReturnedStatus = STATUS_SUCCESS;
    00886
    00887 //    Status = SepRmCallLsa(
    00888 //                 ((RM_SEND_COMMAND_TO_LSA_PARAMS *)
    00889 //                    (CommandMessage->CommandParams))->LsaCommandNumber,
    00890 //                 LsaCommandParams,
    00891 //                 LsaCommandParamsLength,
    00892 //                 NULL,
    00893 //                 0,
    00894 //                 NULL,
    00895 //                 NULL
    00896 //                 );
    00897
    00898
    00899     return;
    00900
    00901 }

BOOLEAN SeRmInitPhase1 | ( |  | ) |

Definition at line 60 of file rmmain.c.

References ASSERT, ExAllocatePoolWithTag, ExFreePool(), FALSE, _SEP_RM_STATE::LsaInitEventHandle, NT_SUCCESS, NTSTATUS(), NULL, ObjectAttributes, PAGED_CODE, PagedPool, PsCreateSystemThread(), _SEP_RM_STATE::RmCommandPortHandle, RtlAddAccessAllowedAce(), RtlAnsiStringToUnicodeString(), RtlCreateAcl(), RtlCreateSecurityDescriptor(), RtlFreeUnicodeString(), RtlInitString(), SeLengthSid, SeLocalSystemSid, SEP_RM_CONNECT_INFO, SepAdtInitializeAuditingOptions(), SepAdtInitializeCrashOnFail(), SepAdtInitializePrivilegeAuditing(), SepRmCommandServerThread(), SepRmState, _SEP_RM_STATE::SepRmThreadHandle, Status, and TRUE.

    00065                    :
    00066
    00067     This function is called by Phase 1 System Initialization to initialize
    00068     the Security Reference Monitor.  Note that initialization of the
    00069     Reference Monitor Global State has already been performed in Phase 0
    00070     initialization to allow access validation routines to operate without
    00071     having to check that Reference Monitor Initialization is complete.
    00072
    00073     The steps listed below are performed in this routine.  The remainder
    00074     of Reference Monitor initialization requires the LSA subsystem to have run,
    00075     so that initialization is performed in a separate thread (the RM Command
    00076     Server Thread, see below), so that the present thread can create the
    00077     Session Manager which execs the LSA.
    00078
    00079     o Create the Reference Monitor Command LPC port.  The LSA subsystem sends
    00080       commands (e.g. turn on auditing) which change the Reference Monitor
    00081       Global State.
    00082     o Create an Event for use in synchronizing with the LSA subsystem.  The
    00083       LSA will signal the event when the portion of LSA initialization upon
    00084       with the Reference Monitor depends is complete.  The Reference Monitor
    00085       uses another LPC port, called the LSA Command Port to send commands
    00086       to the LSA, so the RM must know that this port has been created before
    00087       trying to connect to it.
    00088     o Create the Reference Monitor Command Server Thread.  This thread is
    00089       a permanent thread of the System Init process that fields the Reference
    00090       Monitor State Change commands described above.
    00091
    00092
    00093 Arguments:
    00094
    00095     None.
    00096
    00097 Return Value:
    00098
    00099     BOOLEAN - TRUE if Rm Initialization (Phase 1) succeeded, else FALSE
    00100
    00101 --*/
    00102
    00103 {
    00104     NTSTATUS Status;
    00105     STRING RmCommandPortName;
    00106     UNICODE_STRING UnicodeRmCommandPortName;
    00107     OBJECT_ATTRIBUTES ObjectAttributes;
    00108     STRING LsaInitEventName;
    00109     UNICODE_STRING UnicodeLsaInitEventName;
    00110     OBJECT_ATTRIBUTES LsaInitEventObjectAttributes;
    00111     SECURITY_DESCRIPTOR LsaInitEventSecurityDescriptor;
    00112     ULONG AclSize;
    00113
    00114     PAGED_CODE();
    00115
    00116     //
    00117     // Create an LPC port called the Reference Monitor Command Port.
    00118     // This will be used by the LSA to send commands to the Reference
    00119     // Monitor to update its state data.
    00120     //
    00121
    00122     RtlInitString( &RmCommandPortName, "\\SeRmCommandPort" );
    00123     Status = RtlAnsiStringToUnicodeString(
    00124                  &UnicodeRmCommandPortName,
    00125                  &RmCommandPortName,
    00126                  TRUE );  ASSERT( NT_SUCCESS(Status) );
    00127     InitializeObjectAttributes(
    00128         &ObjectAttributes,
    00129         &UnicodeRmCommandPortName,
    00130         0,
    00131         NULL,
    00132         NULL
    00133         );
    00134
    00135     Status = ZwCreatePort(
    00136                  &SepRmState.RmCommandPortHandle,
    00137                  &ObjectAttributes,
    00138                  sizeof(SEP_RM_CONNECT_INFO),
    00139                  sizeof(RM_COMMAND_MESSAGE),
    00140                  sizeof(RM_COMMAND_MESSAGE) * 32
    00141                  );
    00142     RtlFreeUnicodeString( &UnicodeRmCommandPortName );
    00143
    00144     if( !NT_SUCCESS(Status) ) {
    00145
    00146         KdPrint(("Security: Rm Create Command Port failed 0x%lx\n", Status));
    00147         return FALSE;
    00148     }
    00149
    00150     //
    00151     // Prepare to create an event for synchronizing with the LSA.
    00152     // First, build the Security Descriptor for the Init Event Object
    00153     //
    00154
    00155     Status = RtlCreateSecurityDescriptor(
    00156                  &LsaInitEventSecurityDescriptor,
    00157                  SECURITY_DESCRIPTOR_REVISION
    00158                  );
    00159
    00160     if (!NT_SUCCESS(Status)) {
    00161
    00162         KdPrint(("Security:  Creating Lsa Init Event Desc failed 0x%lx\n",
    00163                   Status));
    00164         return FALSE;
    00165     }
    00166
    00167     //
    00168     // Allocate a temporary buffer from the paged pool.  It is a fatal
    00169     // system error if the allocation fails since security cannot be
    00170     // enabled.
    00171     //
    00172
    00173     AclSize = sizeof(ACL) +
    00174               sizeof(ACCESS_ALLOWED_ACE) +
    00175               SeLengthSid(SeLocalSystemSid);
    00176     LsaInitEventSecurityDescriptor.Dacl =
    00177         ExAllocatePoolWithTag(PagedPool, AclSize, 'cAeS');
    00178
    00179     if (LsaInitEventSecurityDescriptor.Dacl == NULL) {
    00180
    00181         KdPrint(("Security LSA:  Insufficient resources to initialize\n"));
    00182         return FALSE;
    00183     }
    00184
    00185     //
    00186     // Now create the Discretionary ACL within the Security Descriptor
    00187     //
    00188
    00189     Status = RtlCreateAcl(
    00190                  LsaInitEventSecurityDescriptor.Dacl,
    00191                  AclSize,
    00192                  ACL_REVISION2
    00193                  );
    00194
    00195     if (!NT_SUCCESS(Status)) {
    00196
    00197         KdPrint(("Security:  Creating Lsa Init Event Dacl failed 0x%lx\n",
    00198                   Status));
    00199         return FALSE;
    00200     }
    00201
    00202     //
    00203     // Now add an ACE giving GENERIC_ALL access to the User ID
    00204     //
    00205
    00206     Status = RtlAddAccessAllowedAce(
    00207                  LsaInitEventSecurityDescriptor.Dacl,
    00208                  ACL_REVISION2,
    00209                  GENERIC_ALL,
    00210                  SeLocalSystemSid
    00211                  );
    00212
    00213     if (!NT_SUCCESS(Status)) {
    00214
    00215         KdPrint(("Security:  Adding Lsa Init Event ACE failed 0x%lx\n",
    00216                   Status));
    00217         return FALSE;
    00218     }
    00219
    00220     //
    00221     // Set up the Object Attributes for the Lsa Initialization Event
    00222     //
    00223
    00224     RtlInitString( &LsaInitEventName, "\\SeLsaInitEvent" );
    00225     Status = RtlAnsiStringToUnicodeString(
    00226                  &UnicodeLsaInitEventName,
    00227                  &LsaInitEventName,
    00228                  TRUE );  ASSERT( NT_SUCCESS(Status) );
    00229     InitializeObjectAttributes(
    00230         &LsaInitEventObjectAttributes,
    00231         &UnicodeLsaInitEventName,
    00232         0,
    00233         NULL,
    00234         &LsaInitEventSecurityDescriptor
    00235         );
    00236
    00237     //
    00238     // Create an event for use in synchronizing with the LSA.  The LSA will
    00239     // signal this event when LSA initialization has reached the point
    00240     // where the LSA's Reference Monitor Server Port has been created.
    00241     //
    00242
    00243     Status = ZwCreateEvent(
    00244                  &(SepRmState.LsaInitEventHandle),
    00245                  EVENT_MODIFY_STATE,
    00246                  &LsaInitEventObjectAttributes,
    00247                  NotificationEvent,
    00248                  FALSE);
    00249
    00250     RtlFreeUnicodeString( &UnicodeLsaInitEventName );
    00251
    00252     if (!NT_SUCCESS(Status)) {
    00253
    00254         KdPrint(("Security: LSA init event creation failed.0x%xl\n",
    00255             Status));
    00256         return FALSE;
    00257     }
    00258
    00259     //
    00260     // Deallocate the pool memory used for the Init Event DACL
    00261     //
    00262
    00263     ExFreePool( LsaInitEventSecurityDescriptor.Dacl );
    00264
    00265     //
    00266     // Create a permanent thread of the Sysinit Process, called the
    00267     // Reference Monitor Server Thread.  This thread is dedicated to
    00268     // receiving Reference Monitor commands and dispatching them.
    00269     //
    00270
    00271     Status = PsCreateSystemThread(
    00272                  &SepRmState.SepRmThreadHandle,
    00273                  THREAD_GET_CONTEXT |
    00274                  THREAD_SET_CONTEXT |
    00275                  THREAD_SET_INFORMATION,
    00276                  NULL,
    00277                  NULL,
    00278                  NULL,
    00279                  SepRmCommandServerThread,
    00280                  NULL
    00281                  );
    00282
    00283     if (!NT_SUCCESS(Status)) {
    00284
    00285         KdPrint(("Security: Rm Server Thread creation failed 0x%lx\n", Status));
    00286         return FALSE;
    00287     }
    00288
    00289     //
    00290     // Initialize data from the registry.  This must go here because all other
    00291     // Se initialization takes place before the registry is initialized.
    00292     //
    00293
    00294     SepAdtInitializeCrashOnFail();
    00295     SepAdtInitializePrivilegeAuditing();
    00296     SepAdtInitializeAuditingOptions();
    00297
    00298     //
    00299     // Reference Monitor initialization is successful if we get to here.
    00300     //
    00301
    00302     ZwClose( SepRmState.SepRmThreadHandle );
    00303     SepRmState.SepRmThreadHandle = NULL;
    00304     return TRUE;
    00305 }

## Variable Documentation

SEP_RM_COMMAND_WORKER SepRmCommandDispatch[]

Initial value:

     {
                              SepRmComponentTestCommandWrkr,
                              SepRmSetAuditEventWrkr,
                              SepRmSendCommandToLsaWrkr,
                              SepRmComponentTestCommandWrkr,
                              SepRmCreateLogonSessionWrkr,
                              SepRmDeleteLogonSessionWrkr
                              }

Definition at line 49 of file rmmain.c.

Referenced by SepRmCommandServerThread().