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
01000
01001
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
01020
01021
01022 CommandMessage.CommandNumber = WorkQueueItem->
CommandNumber;
01023
ReplyMessage.ReturnedStatus = STATUS_SUCCESS;
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
switch (WorkQueueItem->
CommandParamsMemoryType) {
01034
01035
case SepRmImmediateMemory:
01036
01037
01038
01039
01040
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
01058
01059
01060
01061
01062
01063
if (WorkQueueItem->
CommandParamsLength <= LSA_MAXIMUM_COMMAND_PARAM_SIZE) {
01064
01065
01066
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
01083
01084
01085
01086
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
01113
01114
01115
01116
01117
01118
01119
break;
01120
01121 }
01122
01123 CommandMessage.CommandParamsMemoryType = SepRmLsaCustomSharedMemory;
01124 }
01125
01126
01127
01128
01129
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
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
01164
01165
01166
01167
Status = ZwRequestWaitReplyPort(
01168
SepRmState.
LsaCommandPortHandle,
01169 (PPORT_MESSAGE) &CommandMessage,
01170 (PPORT_MESSAGE) &ReplyMessage
01171 );
01172
01173
01174
01175
01176
01177
01178
if (
NT_SUCCESS(Status)) {
01179
01180
01181
01182
01183
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
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
01213
01214
01215
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
01237
01238
01239
01240
if ( ARGUMENT_PRESENT( WorkQueueItem->
CleanupFunction)) {
01241
01242 (WorkQueueItem->
CleanupFunction)(WorkQueueItem->
CleanupParameter);
01243 }
01244
01245
01246
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 }