mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
792 lines
19 KiB
792 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
aupckg.c
|
|
|
|
Abstract:
|
|
|
|
This module provides code that initializes authentication packages.
|
|
|
|
It also provides the dispatch code for LsaLookupPackage() and
|
|
LsaCallPackage().
|
|
|
|
Author:
|
|
|
|
Jim Kelly (JimK) 27-February-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "lsasrvp.h"
|
|
#include "ausrvp.h"
|
|
|
|
|
|
|
|
BOOLEAN
|
|
LsapPackageInitialize()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes data structures used to track authentication
|
|
packages and then makes a call to initialize each authentication package
|
|
we are configured to run with.
|
|
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN ReturnStatus;
|
|
|
|
//
|
|
// Initialize the private LSA services available to Microsoft
|
|
// authentication packages.
|
|
//
|
|
|
|
ReturnStatus = LsapAuMspInitialize();
|
|
|
|
|
|
//
|
|
// Initialize the dispatch table provided to authentication
|
|
// packages.
|
|
//
|
|
|
|
|
|
LsapPackageDispatchTable.CreateLogonSession = &LsapCreateLogonSession;
|
|
LsapPackageDispatchTable.DeleteLogonSession = &LsapDeleteLogonSession;
|
|
LsapPackageDispatchTable.AddCredential = &LsapAddCredential;
|
|
LsapPackageDispatchTable.GetCredentials = &LsapGetCredentials;
|
|
LsapPackageDispatchTable.DeleteCredential = &LsapDeleteCredential;
|
|
LsapPackageDispatchTable.AllocateLsaHeap = &LsapAllocateLsaHeap;
|
|
LsapPackageDispatchTable.FreeLsaHeap = &LsapFreeLsaHeap;
|
|
LsapPackageDispatchTable.AllocateClientBuffer = &LsapAllocateClientBuffer;
|
|
LsapPackageDispatchTable.FreeClientBuffer = &LsapFreeClientBuffer;
|
|
LsapPackageDispatchTable.CopyToClientBuffer = &LsapCopyToClientBuffer;
|
|
LsapPackageDispatchTable.CopyFromClientBuffer = &LsapCopyFromClientBuffer;
|
|
|
|
|
|
//
|
|
// Authentication packages are identified by a ULONG value.
|
|
// Each one is tracked in an array of authentication packages.
|
|
//
|
|
|
|
LsapPackageCount = 0;
|
|
LsapPackageArray = (PLSAP_PACKAGE_ARRAY)NULL;
|
|
|
|
|
|
//
|
|
// Load each configured authentication package
|
|
//
|
|
|
|
LsapConfigurePackages();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapConfigurePackage(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
RTL_QUERY_REGISTRY_TABLE LsapRegistryConfigurationTable[] = {
|
|
|
|
{LsapConfigurePackage, 0,
|
|
L"Authentication Packages",NULL,
|
|
REG_NONE, NULL, 0},
|
|
|
|
{NULL, 0,
|
|
NULL, NULL,
|
|
REG_NONE, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
NTSTATUS
|
|
LsapConfigurePackages()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retrieves configuration information regarding
|
|
which authentication packages are to be loaded and then
|
|
loads each package.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - Any errors are logged, but nothing happens to cause
|
|
initialization to fail.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
|
|
L"Lsa",
|
|
LsapRegistryConfigurationTable,
|
|
NULL,
|
|
NULL
|
|
);
|
|
#if DEVL
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
DbgPrint("LSA: Warning. Unable to read registry data - Status == %lx\n", Status);
|
|
}
|
|
#endif // DEVL
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
LsapConfigurePackage(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
)
|
|
{
|
|
UNICODE_STRING PackageName;
|
|
|
|
if (ValueType != REG_SZ) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
PackageName.Buffer = ValueData;
|
|
PackageName.Length = (USHORT)(ValueLength - sizeof( UNICODE_NULL ));
|
|
PackageName.MaximumLength = (USHORT)ValueLength;
|
|
return LsapAddPackage( &PackageName,
|
|
NULL, // Not yet supported
|
|
NULL // Not yet supported
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAddPackage(
|
|
IN PUNICODE_STRING PackageFileName,
|
|
IN PUNICODE_STRING DatabaseParameter,
|
|
IN PUNICODE_STRING ConfidentialityParameter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes an authentication package that we are
|
|
configured to run with. Each package is assigned a unique ID and
|
|
added to the list of authentication packages.
|
|
|
|
Note that authentication packages are never expected to exit.
|
|
|
|
|
|
Arguments:
|
|
|
|
PackageFileName - The name of the file that the authentication pacakge
|
|
DLL is in.
|
|
|
|
DatabaseParameter - The database source parameter value to pass to the
|
|
DLL. This enables the authentication package to locate its
|
|
package-specific database. The meaning and format of this string
|
|
are package-specific and opaque to the LSA.
|
|
|
|
ConfidentialityParameter - The confidentiality parameter to pass to the
|
|
DLL. This enables the authentication package to decrypt any
|
|
encrypted information in the authentication-package-specific
|
|
database. The meaning and format of this string are package-specific
|
|
and opaque to the LSA.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The package has been successfully added.
|
|
|
|
STATUS_QUOTA_EXCEEDED - An attempt to allocate heap space has failed.
|
|
The most probable cause is memory quota has been exceeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PLSAP_PACKAGE_CONTEXT NewPackage;
|
|
PLSAP_PACKAGE_ARRAY NewPackageArray;
|
|
ULONG i, NewArraySize, CurrentPackageCount;
|
|
|
|
|
|
|
|
//
|
|
// Allocate a new package context record.
|
|
//
|
|
|
|
NewPackage = (PLSAP_PACKAGE_CONTEXT)
|
|
LsapAllocateLsaHeap(
|
|
(ULONG)sizeof(LSAP_PACKAGE_CONTEXT)
|
|
);
|
|
if ( NewPackage == NULL ) {
|
|
return STATUS_QUOTA_EXCEEDED;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Most of the rest of this has to be done with exclusive access
|
|
// to the package count or the package array.
|
|
//
|
|
|
|
LsapAuLock();
|
|
|
|
|
|
//
|
|
// Extend the package array
|
|
//
|
|
|
|
CurrentPackageCount = LsapPackageCount;
|
|
LsapPackageCount += 1;
|
|
|
|
NewArraySize = (ULONG)sizeof(PVOID) * LsapPackageCount;
|
|
NewPackageArray = LsapAllocateLsaHeap( NewArraySize );
|
|
if ( NewPackageArray == NULL ) {
|
|
LsapPackageCount -= 1;
|
|
LsapAuUnlock();
|
|
LsapFreeLsaHeap( NewPackage );
|
|
return STATUS_QUOTA_EXCEEDED;
|
|
}
|
|
|
|
//
|
|
// Copy the old array into the new one.
|
|
//
|
|
|
|
for (i=0; i<CurrentPackageCount ; i++ ) {
|
|
NewPackageArray->Package[i] = LsapPackageArray->Package[i];
|
|
}
|
|
|
|
|
|
//
|
|
// Set the last array address
|
|
//
|
|
|
|
NewPackageArray->Package[LsapPackageCount-1] = NewPackage;
|
|
|
|
//
|
|
// Load the authentication package
|
|
//
|
|
|
|
Status = LsapLoadPackage( PackageFileName, NewPackage );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
|
|
LsapPackageCount -= 1;
|
|
LsapAuUnlock();
|
|
LsapFreeLsaHeap( NewPackage );
|
|
LsapFreeLsaHeap( NewPackageArray );
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Initialize the authentication package
|
|
//
|
|
|
|
Status = (NewPackage->PackageApi.LsapApInitializePackage) (
|
|
CurrentPackageCount,
|
|
&LsapPackageDispatchTable,
|
|
(PSTRING)DatabaseParameter,
|
|
(PSTRING)ConfidentialityParameter,
|
|
&NewPackage->Name
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
|
|
LsapPackageCount -= 1;
|
|
LsapAuUnlock();
|
|
DbgPrint("LSA: %wZ:Package failed to initialize\n", PackageFileName );
|
|
LsapFreeLsaHeap( NewPackage );
|
|
LsapFreeLsaHeap( NewPackageArray );
|
|
LsapUnloadPackage();
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// The package has been successfully loaded and initialized.
|
|
// Switch to the new package array.
|
|
//
|
|
|
|
if ( LsapPackageArray != NULL ) {
|
|
LsapFreeLsaHeap( LsapPackageArray );
|
|
}
|
|
LsapPackageArray = NewPackageArray;
|
|
|
|
|
|
LsapAuUnlock();
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapLoadPackage(
|
|
IN PUNICODE_STRING PackageFileName,
|
|
IN PLSAP_PACKAGE_CONTEXT NewPackage
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function loads an authentication package dll.
|
|
|
|
This function must be called with exclusive access to shared
|
|
authentication data (LsapAuLock() called).
|
|
|
|
Arguments:
|
|
|
|
PackageFileName - Name of the file that the authentication package
|
|
DLL resides in.
|
|
|
|
NewPackage - Pointer to the context record representing this new
|
|
authentication package. The dispatch table of this record will
|
|
be filled in upon successful loading of the authentication package.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The package has been successfully loaded.
|
|
|
|
|
|
Anything returned from LdrLoadDll() or LdrGetProcedureAddress().
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
NTSTATUS Status, IgnoreStatus, MsProcStatus;
|
|
PVOID ModuleHandle;
|
|
STRING ProcedureName;
|
|
PLSA_AP_MS_INITIALIZE MsInitialize;
|
|
NTSTATUS TmpStatus;
|
|
|
|
#if DBG
|
|
DbgPrint("LSA: Loading Authentication Package - %wZ\n", PackageFileName );
|
|
#endif //DBG
|
|
|
|
Status = LdrLoadDll(
|
|
NULL,
|
|
NULL,
|
|
PackageFileName,
|
|
&ModuleHandle
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
DbgPrint("LSA: Failed to load Authentication Package.\n" );
|
|
DbgPrint(" Status = 0x%lx\n");
|
|
return Status;
|
|
}
|
|
|
|
LsapAdtAuditPackageLoad( PackageFileName );
|
|
|
|
//
|
|
// Now get the address of each dispatch routine
|
|
//
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_INITIALIZE_PACKAGE );
|
|
Status = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApInitializePackage
|
|
);
|
|
}
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_CALL_PACKAGE );
|
|
Status = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApCallPackage
|
|
);
|
|
}
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_LOGON_TERMINATED );
|
|
Status = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApLogonTerminated
|
|
);
|
|
}
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_CALL_PACKAGE_UNTRUSTED );
|
|
IgnoreStatus = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApCallPackageUntrusted
|
|
);
|
|
}
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_LOGON_USER );
|
|
TmpStatus = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApLogonUser
|
|
);
|
|
|
|
if (!NT_SUCCESS( TmpStatus )) {
|
|
NewPackage->PackageApi.LsapApLogonUser = NULL;
|
|
}
|
|
}
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
//
|
|
// This procedure may or may not exist.
|
|
//
|
|
|
|
RtlInitString( &ProcedureName, LSA_AP_NAME_LOGON_USER_EX );
|
|
TmpStatus = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&NewPackage->PackageApi.LsapApLogonUserEx
|
|
);
|
|
|
|
if ( !NT_SUCCESS( TmpStatus ) ) {
|
|
NewPackage->PackageApi.LsapApLogonUserEx = NULL;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
|
|
if (NewPackage->PackageApi.LsapApLogonUser == NULL && NewPackage->PackageApi.LsapApLogonUserEx == NULL) {
|
|
Status = TmpStatus;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Microsoft authentication packages have one extra procedure, which
|
|
// will get called if available.
|
|
//
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
RtlInitString( &ProcedureName, LSAP_AP_NAME_MS_INITIALIZE );
|
|
MsProcStatus = LdrGetProcedureAddress(
|
|
ModuleHandle,
|
|
&ProcedureName,
|
|
0,
|
|
(PVOID *)&MsInitialize
|
|
);
|
|
|
|
if ( NT_SUCCESS(MsProcStatus) ) {
|
|
(MsInitialize)( &LsapPrivateLsaApi );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// if anything failed, unload the DLL.
|
|
//
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
IgnoreStatus = LdrUnloadDll( ModuleHandle );
|
|
}
|
|
|
|
return Status;
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapUnloadPackage()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function unloads an authentication package dll. This is expected
|
|
to be used only in the case where a package was successfully loaded,
|
|
but did not successfully initialize itself.
|
|
|
|
This function must be called with exclusive access to shared
|
|
authentication data (LsapAuLock() called).
|
|
|
|
Arguments:
|
|
|
|
TBS
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
LsapAuApiDispatchLookupPackage(
|
|
IN OUT PLSAP_CLIENT_REQUEST ClientRequest,
|
|
IN BOOLEAN TrustedClient
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the dispatch routine for LsaLookupPackage().
|
|
|
|
This function locates and returns the package ID of the specified
|
|
authentication package.
|
|
|
|
Arguments:
|
|
|
|
Request - Represents the client's LPC request message and context.
|
|
The request message contains a LSAP_LOOKUP_PACKAGE_ARGS message
|
|
block.
|
|
|
|
TrustedClient - Is this connection from a trusted client, one who has
|
|
TCB privilege.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
STATUS_NO_SUCH_PACKAGE - The specified authentication package is
|
|
unknown to the LSA.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PLSAP_LOOKUP_PACKAGE_ARGS Arguments;
|
|
ULONG i;
|
|
|
|
|
|
Arguments = &ClientRequest->Request->Arguments.LookupPackage;
|
|
|
|
|
|
LsapAuLock();
|
|
|
|
|
|
//
|
|
// Look at each loaded package for a name match
|
|
//
|
|
|
|
|
|
i = 0;
|
|
while ( i < LsapPackageCount ) {
|
|
|
|
if ( (LsapPackageArray->Package[i]->Name->Length ==
|
|
Arguments->PackageNameLength) &&
|
|
(_strnicmp (
|
|
LsapPackageArray->Package[i]->Name->Buffer,
|
|
Arguments->PackageName,
|
|
Arguments->PackageNameLength
|
|
) == 0 )
|
|
) {
|
|
|
|
Arguments->AuthenticationPackage = i;
|
|
|
|
LsapAuUnlock();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
i += 1;
|
|
}
|
|
|
|
LsapAuUnlock();
|
|
return STATUS_NO_SUCH_PACKAGE;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAuApiDispatchCallPackage(
|
|
IN OUT PLSAP_CLIENT_REQUEST ClientRequest,
|
|
IN BOOLEAN TrustedClient
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the dispatch routine for LsaCallPackage().
|
|
|
|
Arguments:
|
|
|
|
Request - Represents the client's LPC request message and context.
|
|
The request message contains a LSAP_CALL_PACKAGE_ARGS message
|
|
block.
|
|
|
|
TrustedClient - Is this connection from a trusted client, one who has
|
|
TCB privilege. For untrusted clients call the
|
|
LsapApCallPackageUntrusted API and for trusted clients call teh
|
|
LsapApCallPackage API.
|
|
|
|
|
|
Return Value:
|
|
|
|
In addition to the status values that an authentication package
|
|
might return, this routine will return the following:
|
|
|
|
STATUS_QUOTA_EXCEEDED - This error indicates that the call could
|
|
not be completed because the client does not have sufficient
|
|
quota to allocate the return buffer.
|
|
|
|
STATUS_NO_SUCH_PACKAGE - The specified authentication package is
|
|
unknown to the LSA.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
PLSAP_CALL_PACKAGE_ARGS Arguments;
|
|
PLSA_PACKAGE_TABLE PackageApi;
|
|
PVOID LocalProtocolSubmitBuffer; // Receives a copy of protocol submit buffer
|
|
|
|
|
|
Arguments = &ClientRequest->Request->Arguments.CallPackage;
|
|
|
|
|
|
//
|
|
// Get the address of the package to call
|
|
//
|
|
|
|
LsapAuLock();
|
|
|
|
if ( Arguments->AuthenticationPackage >= LsapPackageCount ) {
|
|
LsapAuUnlock();
|
|
return STATUS_NO_SUCH_PACKAGE;
|
|
}
|
|
|
|
PackageApi =
|
|
&LsapPackageArray->Package[Arguments->AuthenticationPackage]->PackageApi;
|
|
|
|
LsapAuUnlock();
|
|
|
|
|
|
//
|
|
// Fetch a copy of the profile buffer from the client's
|
|
// address space.
|
|
//
|
|
|
|
if (Arguments->SubmitBufferLength != 0) {
|
|
|
|
LocalProtocolSubmitBuffer =
|
|
LsapAllocateLsaHeap( Arguments->SubmitBufferLength );
|
|
|
|
Status = LsapCopyFromClientBuffer (
|
|
(PLSA_CLIENT_REQUEST)ClientRequest,
|
|
Arguments->SubmitBufferLength,
|
|
LocalProtocolSubmitBuffer,
|
|
Arguments->ProtocolSubmitBuffer
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
DbgPrint("LSA/CallPackage(): Failed to retrieve submit buffer %lx\n",Status);
|
|
return Status;
|
|
}
|
|
|
|
} else {
|
|
LocalProtocolSubmitBuffer = NULL;
|
|
}
|
|
|
|
ASSERT(ClientRequest->LogonProcessContext->CommPort != NULL);
|
|
|
|
|
|
//
|
|
// Now call the package. For trusted clients, call the normal
|
|
// CallPackage API. For untrusted clients, use the untrusted version.
|
|
//
|
|
|
|
if (TrustedClient) {
|
|
Status = (PackageApi->LsapApCallPackage)(
|
|
(PLSA_CLIENT_REQUEST)ClientRequest,
|
|
LocalProtocolSubmitBuffer,
|
|
Arguments->ProtocolSubmitBuffer,
|
|
Arguments->SubmitBufferLength,
|
|
&Arguments->ProtocolReturnBuffer,
|
|
&Arguments->ReturnBufferLength,
|
|
&Arguments->ProtocolStatus
|
|
);
|
|
|
|
} else if (PackageApi->LsapApCallPackageUntrusted != NULL) {
|
|
Status = (PackageApi->LsapApCallPackageUntrusted)(
|
|
(PLSA_CLIENT_REQUEST)ClientRequest,
|
|
LocalProtocolSubmitBuffer,
|
|
Arguments->ProtocolSubmitBuffer,
|
|
Arguments->SubmitBufferLength,
|
|
&Arguments->ProtocolReturnBuffer,
|
|
&Arguments->ReturnBufferLength,
|
|
&Arguments->ProtocolStatus
|
|
);
|
|
|
|
} else {
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
//
|
|
// Free the local copy of the protocol submit buffer
|
|
//
|
|
|
|
if (LocalProtocolSubmitBuffer != NULL) {
|
|
LsapFreeLsaHeap( LocalProtocolSubmitBuffer );
|
|
}
|
|
|
|
|
|
return Status;
|
|
|
|
}
|