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.
8430 lines
204 KiB
8430 lines
204 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rpc.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
Arthur Hanson (arth) 06-Jan-1995
|
|
|
|
Revision History:
|
|
|
|
Jeff Parham (jeffparh) 05-Dec-1995
|
|
o Added replication of certificate database and secure service list.
|
|
o Added Llsr API to support secure certificates.
|
|
o Added LLS_LICENSE_INFO_1 support to LlsrLicenseEnumW() and
|
|
LlsrLicenseAddW().
|
|
o Added LLS_PRODUCT_LICENSE_INFO_1 support to LlsrProductLicenseEnumW().
|
|
o Added save of all data files after receiving replicated data.
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <dsgetdc.h>
|
|
#include <malloc.h> // Added for SBS mods (bug# 505640). _wcsdup uses malloc
|
|
|
|
#include "llsapi.h"
|
|
#include "debug.h"
|
|
#include "llssrv.h"
|
|
#include "mapping.h"
|
|
#include "msvctbl.h"
|
|
#include "svctbl.h"
|
|
#include "perseat.h"
|
|
#include "purchase.h"
|
|
#include "server.h"
|
|
#include "ntlsapi.h"
|
|
|
|
#include "llsrpc_s.h"
|
|
#include "lsapi_s.h"
|
|
#include "llsdbg_s.h"
|
|
#include "repl.h"
|
|
#include "pack.h"
|
|
#include "registry.h"
|
|
#include "certdb.h"
|
|
#include "llsrtl.h"
|
|
|
|
#include <strsafe.h> //include last
|
|
|
|
|
|
#define LLS_SIG "LLSS"
|
|
#define LLS_SIG_SIZE 4
|
|
|
|
#define LLS_REPL_SIG "REPL"
|
|
#define LLS_REPL_SIG_SIZE 4
|
|
|
|
extern RTL_RESOURCE CertDbHeaderListLock;
|
|
|
|
#define LLS_POTENTIAL_ATTACK_THRESHHOLD 20
|
|
|
|
DWORD PotentialAttackCounter = 0;
|
|
|
|
typedef struct {
|
|
char Signature[LLS_SIG_SIZE];
|
|
PVOID *ProductUserEnumWRestartTable;
|
|
DWORD ProductUserEnumWRestartTableSize;
|
|
PVOID *UserEnumWRestartTable;
|
|
DWORD UserEnumWRestartTableSize;
|
|
TCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
|
|
} CLIENT_CONTEXT_TYPE, *PCLIENT_CONTEXT_TYPE;
|
|
|
|
typedef struct {
|
|
char Signature[LLS_REPL_SIG_SIZE];
|
|
TCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD ReplicationStart;
|
|
|
|
BOOL Active;
|
|
BOOL Replicated;
|
|
|
|
BOOL ServicesSent;
|
|
ULONG ServiceTableSize;
|
|
PREPL_SERVICE_RECORD Services;
|
|
|
|
BOOL ServersSent;
|
|
ULONG ServerTableSize;
|
|
PREPL_SERVER_RECORD Servers;
|
|
|
|
BOOL ServerServicesSent;
|
|
ULONG ServerServiceTableSize;
|
|
PREPL_SERVER_SERVICE_RECORD ServerServices;
|
|
|
|
BOOL UsersSent;
|
|
ULONG UserLevel;
|
|
ULONG UserTableSize;
|
|
LPVOID Users;
|
|
|
|
BOOL CertDbSent;
|
|
ULONG CertDbProductStringSize;
|
|
WCHAR * CertDbProductStrings;
|
|
ULONG CertDbNumHeaders;
|
|
PREPL_CERT_DB_CERTIFICATE_HEADER_0 CertDbHeaders;
|
|
ULONG CertDbNumClaims;
|
|
PREPL_CERT_DB_CERTIFICATE_CLAIM_0 CertDbClaims;
|
|
|
|
BOOL ProductSecuritySent;
|
|
ULONG ProductSecurityStringSize;
|
|
WCHAR * ProductSecurityStrings;
|
|
|
|
} REPL_CONTEXT_TYPE, *PREPL_CONTEXT_TYPE;
|
|
|
|
//
|
|
// This function is obtained from the April 1998 Knowledge Base
|
|
// Its purpose is to determine if the current user is an
|
|
// Administrator and therefore priveledged to change license
|
|
// settings.
|
|
//
|
|
// BOOL IsAdmin(void)
|
|
//
|
|
// returns TRUE if user is an admin
|
|
// FALSE if user is not an admin
|
|
//
|
|
|
|
#if 0
|
|
BOOL IsAdmin(void)
|
|
{
|
|
HANDLE hAccessToken;
|
|
UCHAR InfoBuffer[1024];
|
|
PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
|
|
DWORD dwInfoBufferSize;
|
|
PSID psidAdministrators;
|
|
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
|
|
UINT x;
|
|
BOOL bSuccess;
|
|
|
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
|
|
&hAccessToken )) {
|
|
if (GetLastError() != ERROR_NO_TOKEN)
|
|
return FALSE;
|
|
//
|
|
// retry against process token if no thread token exists
|
|
//
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
|
|
&hAccessToken))
|
|
return FALSE;
|
|
}
|
|
|
|
bSuccess = GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
|
|
1024, &dwInfoBufferSize);
|
|
|
|
CloseHandle(hAccessToken);
|
|
|
|
if (!bSuccess )
|
|
return FALSE;
|
|
|
|
if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&psidAdministrators))
|
|
return FALSE;
|
|
|
|
// assume that we don't find the admin SID.
|
|
bSuccess = FALSE;
|
|
|
|
for (x=0;x<ptgGroups->GroupCount;x++) {
|
|
if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) ) {
|
|
bSuccess = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
FreeSid(psidAdministrators);
|
|
return bSuccess;
|
|
}
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSRpcListen (
|
|
IN PVOID ThreadParameter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
ThreadParameter - Indicates how many active threads there currently
|
|
are.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status;
|
|
|
|
UNREFERENCED_PARAMETER(ThreadParameter);
|
|
|
|
Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, 0);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerListen Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // LLSRpcListen
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
VOID
|
|
LLSRpcInit()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status;
|
|
DWORD Ignore;
|
|
HANDLE Thread;
|
|
|
|
//
|
|
// Setup for LPC calls..
|
|
//
|
|
Status = RpcServerUseProtseqEp(TEXT("ncalrpc"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, TEXT(LLS_LPC_ENDPOINT), NULL);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerUseProtseq ncalrpc Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
// Named pipes as well
|
|
Status = RpcServerUseProtseqEp(TEXT("ncacn_np"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, TEXT(LLS_NP_ENDPOINT), NULL);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerUseProtseq ncacn_np Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
// register the interface for the UI RPC's
|
|
Status = RpcServerRegisterIf(llsrpc_ServerIfHandle, NULL, NULL);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerRegisterIf Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Now the interface for the Licensing RPC's
|
|
Status = RpcServerRegisterIf(lsapirpc_ServerIfHandle, NULL, NULL);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerRegisterIf2 Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#if DBG
|
|
//
|
|
// ... and if DEBUG then the debugging interface
|
|
//
|
|
Status = RpcServerRegisterIf(llsdbgrpc_ServerIfHandle, NULL, NULL);
|
|
if (Status) {
|
|
#if DBG
|
|
dprintf(TEXT("RpcServerRegisterIf (debug) Failed (0x%lx)\n"), Status);
|
|
#endif
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Create thread to listen for requests.
|
|
//
|
|
Thread = CreateThread(
|
|
NULL,
|
|
0L,
|
|
(LPTHREAD_START_ROUTINE) LLSRpcListen,
|
|
0L,
|
|
0L,
|
|
&Ignore
|
|
);
|
|
|
|
#if DBG
|
|
if (NULL == Thread) {
|
|
dprintf(TEXT("CreateThread Failed\n"));
|
|
}
|
|
#endif
|
|
|
|
if (NULL != Thread)
|
|
CloseHandle(Thread);
|
|
|
|
} // LLSRpcInit
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
VOID __RPC_USER LLS_HANDLE_rundown(
|
|
LLS_HANDLE Handle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCLIENT_CONTEXT_TYPE pClient;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LLS_HANDLE_rundown\n"));
|
|
#endif
|
|
|
|
pClient = (PCLIENT_CONTEXT_TYPE) Handle;
|
|
|
|
try
|
|
{
|
|
if (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (NULL != pClient->ProductUserEnumWRestartTable)
|
|
LocalFree(pClient->ProductUserEnumWRestartTable);
|
|
if (NULL != pClient->UserEnumWRestartTable)
|
|
LocalFree(pClient->UserEnumWRestartTable);
|
|
|
|
//
|
|
// Deallocate context.
|
|
//
|
|
|
|
midl_user_free(Handle);
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
}
|
|
|
|
} // LLS_HANDLE_rundown
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrConnect(
|
|
PLLS_HANDLE Handle,
|
|
LPTSTR Name
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
CLIENT_CONTEXT_TYPE *pClient;
|
|
RPC_STATUS Status = STATUS_SUCCESS;
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsConnect: %s\n"), Name);
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == Handle)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*Handle = NULL;
|
|
|
|
pClient = (CLIENT_CONTEXT_TYPE *) midl_user_allocate(sizeof(CLIENT_CONTEXT_TYPE));
|
|
|
|
if (NULL == pClient)
|
|
{
|
|
#if DBG
|
|
dprintf(TEXT("midl_user_allocate Failed\n"));
|
|
#endif
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrConnectExit;
|
|
}
|
|
|
|
if (Name != NULL)
|
|
{
|
|
if (lstrlen(Name) > MAX_COMPUTERNAME_LENGTH)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
midl_user_free(pClient);
|
|
goto LlsrConnectExit;
|
|
}
|
|
|
|
hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), Name);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else
|
|
{
|
|
hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), TEXT(""));
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
memcpy(pClient->Signature,LLS_SIG,LLS_SIG_SIZE);
|
|
|
|
pClient->ProductUserEnumWRestartTable = NULL;
|
|
pClient->ProductUserEnumWRestartTableSize = 0;
|
|
pClient->UserEnumWRestartTable = NULL;
|
|
pClient->UserEnumWRestartTableSize = 0;
|
|
|
|
*Handle = pClient;
|
|
|
|
LlsrConnectExit:
|
|
|
|
return Status;
|
|
} // LlsrConnect
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrClose(
|
|
LLS_HANDLE Handle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Obsolete - use LlsrCloseEx
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsClose\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
//
|
|
// Don't do anything; let rundown do cleanup
|
|
// We have no way of telling RPC system the handle can't be used
|
|
//
|
|
return STATUS_SUCCESS;
|
|
} // LlsrClose
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrCloseEx(
|
|
LLS_HANDLE * pHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsCloseEx\n"));
|
|
#endif
|
|
|
|
if ((pHandle != NULL) && (*pHandle != NULL))
|
|
{
|
|
LLS_HANDLE_rundown(*pHandle);
|
|
|
|
*pHandle = NULL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrCloseEx
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLicenseEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_LICENSE_ENUM_STRUCTW pLicenseInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
DWORD RecordSize;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLicenseEnumW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to scan list so get read access.
|
|
//
|
|
RtlAcquireResourceShared(&LicenseListLock, TRUE);
|
|
|
|
if ((NULL == pLicenseInfo) || (NULL == pTotalEntries))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Level = pLicenseInfo->Level;
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
if ( 0 == Level )
|
|
{
|
|
if (NULL == pLicenseInfo->LlsLicenseInfo.Level0)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecordSize = sizeof( LLS_LICENSE_INFO_0W );
|
|
}
|
|
else if ( 1 == Level )
|
|
{
|
|
if (NULL == pLicenseInfo->LlsLicenseInfo.Level1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecordSize = sizeof( LLS_LICENSE_INFO_1W );
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ( ( i < PurchaseListSize ) && ( BufSize < pPrefMaxLen ) )
|
|
{
|
|
if ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
|
|
{
|
|
BufSize += RecordSize;
|
|
EntriesRead++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen)
|
|
{
|
|
BufSize -= RecordSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
while ( i < PurchaseListSize )
|
|
{
|
|
if ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
|
|
{
|
|
TotalEntries++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
if (TotalEntries > EntriesRead)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrLicenseEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
while ((j < EntriesRead) && (i < PurchaseListSize))
|
|
{
|
|
if ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
|
|
{
|
|
if ( 0 == Level )
|
|
{
|
|
((PLLS_LICENSE_INFO_0W) BufPtr)[j].Product = PurchaseList[i].Service->ServiceName;
|
|
((PLLS_LICENSE_INFO_0W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
|
|
((PLLS_LICENSE_INFO_0W) BufPtr)[j].Date = PurchaseList[i].Date;
|
|
((PLLS_LICENSE_INFO_0W) BufPtr)[j].Admin = PurchaseList[i].Admin;
|
|
((PLLS_LICENSE_INFO_0W) BufPtr)[j].Comment = PurchaseList[i].Comment;
|
|
}
|
|
else
|
|
{
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Product = ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
|
|
? PurchaseList[i].Service->ServiceName
|
|
: PurchaseList[i].PerServerService->ServiceName;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Vendor = PurchaseList[i].Vendor;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].MaxQuantity = PurchaseList[i].MaxQuantity;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Date = PurchaseList[i].Date;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Admin = PurchaseList[i].Admin;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Comment = PurchaseList[i].Comment;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].AllowedModes = PurchaseList[i].AllowedModes;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].CertificateID = PurchaseList[i].CertificateID;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].Source = PurchaseList[i].Source;
|
|
((PLLS_LICENSE_INFO_1W) BufPtr)[j].ExpirationDate = PurchaseList[i].ExpirationDate;
|
|
memcpy( ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Secrets, PurchaseList[i].Secrets, LLS_NUM_SECRETS * sizeof( *PurchaseList[i].Secrets ) );
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
LlsrLicenseEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
|
|
if ( 0 == Level )
|
|
{
|
|
pLicenseInfo->LlsLicenseInfo.Level0->EntriesRead = EntriesRead;
|
|
pLicenseInfo->LlsLicenseInfo.Level0->Buffer = (PLLS_LICENSE_INFO_0W) BufPtr;
|
|
}
|
|
else
|
|
{
|
|
pLicenseInfo->LlsLicenseInfo.Level1->EntriesRead = EntriesRead;
|
|
pLicenseInfo->LlsLicenseInfo.Level1->Buffer = (PLLS_LICENSE_INFO_1W) BufPtr;
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrLicenseEnumW
|
|
|
|
void LlsrLicenseEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&LicenseListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLicenseEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_LICENSE_ENUM_STRUCTA LicenseInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLicenseEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(LicenseInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLicenseEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLicenseAddW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_LICENSE_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLicenseAddW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
#if 0
|
|
//
|
|
// Check that client is an administrator
|
|
//
|
|
rpcstat = RpcImpersonateClient(0);
|
|
if (rpcstat != RPC_S_OK)
|
|
{
|
|
//should handle dont_free in BufPtr
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
if (!IsAdmin())
|
|
{
|
|
RpcRevertToSelf();
|
|
//should handle dont_free in BufPtr
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
RpcRevertToSelf();
|
|
#endif
|
|
|
|
if ( 0 == Level )
|
|
{
|
|
if ( ( NULL == BufPtr )
|
|
|| ( NULL == BufPtr->LicenseInfo0.Product )
|
|
|| ( NULL == BufPtr->LicenseInfo0.Admin )
|
|
|| ( NULL == BufPtr->LicenseInfo0.Comment ) )
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = LicenseAdd( BufPtr->LicenseInfo0.Product,
|
|
TEXT("Microsoft"),
|
|
BufPtr->LicenseInfo0.Quantity,
|
|
0,
|
|
BufPtr->LicenseInfo0.Admin,
|
|
BufPtr->LicenseInfo0.Comment,
|
|
0,
|
|
LLS_LICENSE_MODE_ALLOW_PER_SEAT,
|
|
0,
|
|
TEXT("None"),
|
|
0,
|
|
NULL );
|
|
}
|
|
}
|
|
else if ( 1 == Level )
|
|
{
|
|
if ( ( NULL == BufPtr )
|
|
|| ( NULL == BufPtr->LicenseInfo1.Product )
|
|
|| ( NULL == BufPtr->LicenseInfo1.Admin )
|
|
|| ( NULL == BufPtr->LicenseInfo1.Comment )
|
|
|| ( 0 == BufPtr->LicenseInfo1.Quantity )
|
|
|| ( 0 == ( BufPtr->LicenseInfo1.AllowedModes
|
|
& ( LLS_LICENSE_MODE_ALLOW_PER_SERVER
|
|
| LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) ) )
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
// check to see if this certificate is already maxed out in the enterprise
|
|
BOOL bIsMaster = TRUE;
|
|
BOOL bMayInstall = TRUE;
|
|
HINSTANCE hDll = NULL;
|
|
PLLS_CONNECT_ENTERPRISE_W pLlsConnectEnterpriseW = NULL;
|
|
PLLS_CLOSE pLlsClose = NULL;
|
|
PLLS_CAPABILITY_IS_SUPPORTED pLlsCapabilityIsSupported = NULL;
|
|
PLLS_CERTIFICATE_CLAIM_ADD_CHECK_W pLlsCertificateClaimAddCheckW = NULL;
|
|
PLLS_CERTIFICATE_CLAIM_ADD_W pLlsCertificateClaimAddW = NULL;
|
|
PLLS_FREE_MEMORY pLlsFreeMemory = NULL;
|
|
LLS_HANDLE hEnterpriseLls = NULL;
|
|
TCHAR szComputerName[ 1 + MAX_COMPUTERNAME_LENGTH ];
|
|
|
|
szComputerName[0] = 0;
|
|
|
|
ConfigInfoUpdate(NULL,TRUE);
|
|
|
|
RtlEnterCriticalSection( &ConfigInfoLock );
|
|
bIsMaster = ConfigInfo.IsMaster;
|
|
if (ConfigInfo.ComputerName != NULL)
|
|
{
|
|
hr = StringCbCopy( szComputerName, sizeof(szComputerName), ConfigInfo.ComputerName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
RtlLeaveCriticalSection( &ConfigInfoLock );
|
|
|
|
if( !bIsMaster && ( 0 != BufPtr->LicenseInfo1.CertificateID ) )
|
|
{
|
|
// ask enterprise server if we can install this certfificate
|
|
hDll = LoadLibraryA( "LLSRPC.DLL" );
|
|
|
|
if ( NULL == hDll )
|
|
{
|
|
// LLSRPC.DLL should be available!
|
|
ASSERT( FALSE );
|
|
}
|
|
else
|
|
{
|
|
pLlsConnectEnterpriseW = (PLLS_CONNECT_ENTERPRISE_W ) GetProcAddress( hDll, "LlsConnectEnterpriseW" );
|
|
pLlsClose = (PLLS_CLOSE ) GetProcAddress( hDll, "LlsClose" );
|
|
pLlsCapabilityIsSupported = (PLLS_CAPABILITY_IS_SUPPORTED ) GetProcAddress( hDll, "LlsCapabilityIsSupported" );
|
|
pLlsCertificateClaimAddCheckW = (PLLS_CERTIFICATE_CLAIM_ADD_CHECK_W ) GetProcAddress( hDll, "LlsCertificateClaimAddCheckW" );
|
|
pLlsCertificateClaimAddW = (PLLS_CERTIFICATE_CLAIM_ADD_W ) GetProcAddress( hDll, "LlsCertificateClaimAddW" );
|
|
pLlsFreeMemory = (PLLS_FREE_MEMORY ) GetProcAddress( hDll, "LlsFreeMemory" );
|
|
|
|
if ( ( NULL == pLlsConnectEnterpriseW )
|
|
|| ( NULL == pLlsClose )
|
|
|| ( NULL == pLlsCapabilityIsSupported )
|
|
|| ( NULL == pLlsCertificateClaimAddCheckW )
|
|
|| ( NULL == pLlsCertificateClaimAddW )
|
|
|| ( NULL == pLlsFreeMemory ) )
|
|
{
|
|
// All of these functions should be exported!
|
|
ASSERT( FALSE );
|
|
}
|
|
else
|
|
{
|
|
PLLS_CONNECT_INFO_0 pConnectInfo;
|
|
|
|
Status = (*pLlsConnectEnterpriseW)( NULL, &hEnterpriseLls, 0, (LPBYTE *)&pConnectInfo );
|
|
|
|
if ( STATUS_SUCCESS == Status )
|
|
{
|
|
(*pLlsFreeMemory)( pConnectInfo );
|
|
|
|
if ( (*pLlsCapabilityIsSupported)( hEnterpriseLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
|
|
{
|
|
Status = (*pLlsCertificateClaimAddCheckW)( hEnterpriseLls, Level, (LPBYTE) BufPtr, &bMayInstall );
|
|
|
|
if ( STATUS_SUCCESS != Status )
|
|
{
|
|
bMayInstall = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !bMayInstall )
|
|
{
|
|
// denied!
|
|
Status = STATUS_ALREADY_COMMITTED;
|
|
}
|
|
else
|
|
{
|
|
// approved! (or an error occurred trying to get approval...)
|
|
Status = LicenseAdd( BufPtr->LicenseInfo1.Product,
|
|
BufPtr->LicenseInfo1.Vendor,
|
|
BufPtr->LicenseInfo1.Quantity,
|
|
BufPtr->LicenseInfo1.MaxQuantity,
|
|
BufPtr->LicenseInfo1.Admin,
|
|
BufPtr->LicenseInfo1.Comment,
|
|
0,
|
|
BufPtr->LicenseInfo1.AllowedModes,
|
|
BufPtr->LicenseInfo1.CertificateID,
|
|
BufPtr->LicenseInfo1.Source,
|
|
BufPtr->LicenseInfo1.ExpirationDate,
|
|
BufPtr->LicenseInfo1.Secrets );
|
|
|
|
if ( ( STATUS_SUCCESS == Status )
|
|
&& ( NULL != hEnterpriseLls )
|
|
&& ( (*pLlsCapabilityIsSupported)( hEnterpriseLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) ) )
|
|
{
|
|
// certificate successfully installed on this machine; register it
|
|
(*pLlsCertificateClaimAddW)( hEnterpriseLls, szComputerName, Level, (LPBYTE) BufPtr );
|
|
}
|
|
}
|
|
|
|
if ( NULL != hEnterpriseLls )
|
|
{
|
|
(*pLlsClose)( hEnterpriseLls );
|
|
}
|
|
|
|
if ( NULL != hDll )
|
|
{
|
|
FreeLibrary( hDll );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
|
|
if ( STATUS_SUCCESS == Status )
|
|
{
|
|
Status = LicenseListSave();
|
|
}
|
|
|
|
if (NULL != BufPtr)
|
|
{
|
|
// PNAMEW are declared as dont_free, we should free them
|
|
if (0 == Level)
|
|
{
|
|
if (NULL != BufPtr->LicenseInfo0.Product)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo0.Product);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo0.Admin)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo0.Admin);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo0.Comment)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo0.Comment);
|
|
}
|
|
}
|
|
|
|
if (1 == Level)
|
|
{
|
|
if (NULL != BufPtr->LicenseInfo1.Product)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo1.Product);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo1.Admin)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo1.Admin);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo1.Comment)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo1.Comment);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo1.Vendor)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo1.Vendor);
|
|
}
|
|
if (NULL != BufPtr->LicenseInfo1.Source)
|
|
{
|
|
MIDL_user_free(BufPtr->LicenseInfo1.Source);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrLicenseAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLicenseAddA(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_LICENSE_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLicenseAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLicenseAddA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_PRODUCT_ENUM_STRUCTW pProductInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to scan list so get read access.
|
|
//
|
|
RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == pProductInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pProductInfo->Level;
|
|
if (Level == 0)
|
|
{
|
|
if (NULL == pProductInfo->LlsProductInfo.Level0)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_PRODUCT_INFO_0W);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (NULL == pProductInfo->LlsProductInfo.Level1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_PRODUCT_INFO_1W);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ((i < MasterServiceListSize) && (BufSize < pPrefMaxLen)) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= RecSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (i < MasterServiceListSize)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
TotalEntries += (MasterServiceListSize - i);
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrProductEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
while ((j < EntriesRead) && (i < MasterServiceListSize)) {
|
|
if (Level == 0)
|
|
((PLLS_PRODUCT_INFO_0) BufPtr)[j].Product = MasterServiceList[i]->Name;
|
|
else {
|
|
((PLLS_PRODUCT_INFO_1) BufPtr)[j].Product = MasterServiceList[i]->Name;
|
|
((PLLS_PRODUCT_INFO_1) BufPtr)[j].Purchased = MasterServiceList[i]->Licenses;
|
|
((PLLS_PRODUCT_INFO_1) BufPtr)[j].InUse = MasterServiceList[i]->LicensesUsed;
|
|
((PLLS_PRODUCT_INFO_1) BufPtr)[j].ConcurrentTotal = MasterServiceList[i]->MaxSessionCount;
|
|
((PLLS_PRODUCT_INFO_1) BufPtr)[j].HighMark = MasterServiceList[i]->HighMark;
|
|
}
|
|
|
|
i++; j++;
|
|
}
|
|
|
|
LlsrProductEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
|
|
if (Level == 0) {
|
|
pProductInfo->LlsProductInfo.Level0->EntriesRead = EntriesRead;
|
|
pProductInfo->LlsProductInfo.Level0->Buffer = (PLLS_PRODUCT_INFO_0W) BufPtr;
|
|
} else {
|
|
pProductInfo->LlsProductInfo.Level1->EntriesRead = EntriesRead;
|
|
pProductInfo->LlsProductInfo.Level1->Buffer = (PLLS_PRODUCT_INFO_1W) BufPtr;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // LlsrProductEnumW
|
|
|
|
void LlsrProductEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&MasterServiceListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_PRODUCT_ENUM_STRUCTA ProductInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(ProductInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductAddW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR ProductFamily,
|
|
LPWSTR Product,
|
|
LPWSTR lpVersion
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PMASTER_SERVICE_RECORD Service;
|
|
DWORD Version;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductAddW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ((ProductFamily == NULL) || (Product == NULL) || (lpVersion == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
Version = VersionToDWORD(lpVersion);
|
|
RtlAcquireResourceExclusive(&MasterServiceListLock,TRUE);
|
|
Service = MasterServiceListAdd(ProductFamily, Product, Version);
|
|
RtlReleaseResource(&MasterServiceListLock);
|
|
|
|
if (Service == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrProductAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductAddA(
|
|
LLS_HANDLE Handle,
|
|
IN LPSTR ProductFamily,
|
|
IN LPSTR Product,
|
|
IN LPSTR Version
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(ProductFamily);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(Version);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductAddA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductUserEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Product,
|
|
PLLS_PRODUCT_USER_ENUM_STRUCTW pProductUserInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
PUSER_RECORD UserRec = NULL;
|
|
PVOID RestartKey = NULL, RestartKeySave = NULL;
|
|
PSVC_RECORD pService;
|
|
DWORD Flags;
|
|
ULONG j, AccessCount;
|
|
DWORD LastAccess;
|
|
PCLIENT_CONTEXT_TYPE pClient = NULL;
|
|
PVOID *pTableTmp;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductUserEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceShared(&UserListLock, TRUE);
|
|
|
|
if ((Product == NULL) || (NULL == pTotalEntries))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
if (pResumeHandle != NULL)
|
|
{
|
|
if (NULL == Handle)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
pClient = (PCLIENT_CONTEXT_TYPE) Handle;
|
|
|
|
try
|
|
{
|
|
if (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (*pResumeHandle != 0)
|
|
{
|
|
if ((NULL == pClient->ProductUserEnumWRestartTable)
|
|
|| (*pResumeHandle >= pClient->ProductUserEnumWRestartTableSize))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RestartKey = RestartKeySave = pClient->ProductUserEnumWRestartTable[(*pResumeHandle)-1];
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pProductUserInfo->Level;
|
|
if (Level == 0)
|
|
{
|
|
if (NULL == pProductUserInfo->LlsProductUserInfo.Level0)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_PRODUCT_USER_INFO_0);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (NULL == pProductUserInfo->LlsProductUserInfo.Level1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_PRODUCT_USER_INFO_1);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
if (lstrcmpi(Product, BackOfficeStr))
|
|
while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
|
|
if ( !(UserRec->Flags & LLS_FLAG_DELETED) ) {
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
pService = SvcListFind( Product, UserRec->Services, UserRec->ServiceTableSize );
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
|
|
if (pService != NULL) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
}
|
|
}
|
|
|
|
// Get next record
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
else
|
|
while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
|
|
if (UserRec->Mapping != NULL)
|
|
Flags = UserRec->Mapping->Flags;
|
|
else
|
|
Flags = UserRec->Flags;
|
|
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED))
|
|
if (Flags & LLS_FLAG_SUITE_USE) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
}
|
|
|
|
// Get next record
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= RecSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (UserRec != NULL)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
while (UserRec != NULL) {
|
|
TotalEntries++;
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
RestartKey = RestartKeySave;
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrProductUserEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
if (lstrcmpi(Product, BackOfficeStr))
|
|
while ((i < EntriesRead) && (UserRec != NULL)) {
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
pService = SvcListFind( Product, UserRec->Services, UserRec->ServiceTableSize );
|
|
if (pService != NULL) {
|
|
|
|
if (Level == 0)
|
|
((PLLS_PRODUCT_USER_INFO_0) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
|
|
else {
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].Flags = pService->Flags;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].LastUsed = pService->LastAccess;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].UsageCount = pService->AccessCount;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
}
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
else
|
|
while ((i < EntriesRead) && (UserRec != NULL)) {
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
|
|
if (UserRec->Mapping != NULL)
|
|
Flags = UserRec->Mapping->Flags;
|
|
else
|
|
Flags = UserRec->Flags;
|
|
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED))
|
|
if (Flags & LLS_FLAG_SUITE_USE) {
|
|
AccessCount = 0;
|
|
LastAccess = 0;
|
|
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
for (j = 0; j < UserRec->ServiceTableSize; j++) {
|
|
if (UserRec->Services[j].LastAccess > LastAccess)
|
|
LastAccess = UserRec->Services[j].LastAccess;
|
|
|
|
if (UserRec->Services[j].AccessCount > AccessCount)
|
|
AccessCount = UserRec->Services[j].AccessCount;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
if (Level == 0)
|
|
((PLLS_PRODUCT_USER_INFO_0) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
|
|
else {
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].Flags = UserRec->Flags;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].LastUsed = LastAccess;
|
|
((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].UsageCount = AccessCount;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
}
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
LlsrProductUserEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
{
|
|
try
|
|
{
|
|
if (NULL == pClient->ProductUserEnumWRestartTable)
|
|
{
|
|
pTableTmp = (PVOID *) LocalAlloc(LPTR,sizeof(PVOID));
|
|
} else
|
|
{
|
|
pTableTmp = (PVOID *) LocalReAlloc(pClient->ProductUserEnumWRestartTable,sizeof(PVOID) * (pClient->ProductUserEnumWRestartTableSize + 1),LHND);
|
|
}
|
|
|
|
if (NULL == pTableTmp)
|
|
{
|
|
if (BufPtr != NULL)
|
|
{
|
|
MIDL_user_free(BufPtr);
|
|
}
|
|
|
|
return STATUS_NO_MEMORY;
|
|
} else {
|
|
pClient->ProductUserEnumWRestartTable = pTableTmp;
|
|
}
|
|
|
|
pClient->ProductUserEnumWRestartTable[pClient->ProductUserEnumWRestartTableSize++] = RestartKey;
|
|
|
|
*pResumeHandle = pClient->ProductUserEnumWRestartTableSize;
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
return Status;
|
|
}
|
|
|
|
pProductUserInfo->LlsProductUserInfo.Level0->EntriesRead = EntriesRead;
|
|
pProductUserInfo->LlsProductUserInfo.Level0->Buffer = (PLLS_PRODUCT_USER_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
} // LlsrProductUserEnumW
|
|
|
|
void LlsrProductUserEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&UserListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductUserEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
PLLS_PRODUCT_USER_ENUM_STRUCTA ProductUserInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductUserEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(ProductUserInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductUserEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductServerEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPTSTR Product,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTW pProductServerInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j;
|
|
ULONG RestartKey = 0;
|
|
PSERVER_SERVICE_RECORD pSvc;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(pPrefMaxLen);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductServerEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceShared(&ServerListLock, TRUE);
|
|
|
|
if ((Product == NULL) || (NULL == pTotalEntries) || (NULL == pProductServerInfo))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
RestartKey = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pProductServerInfo->Level;
|
|
|
|
if (Level == 0)
|
|
{
|
|
if (pProductServerInfo->LlsServerProductInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_SERVER_PRODUCT_INFO_0);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (pProductServerInfo->LlsServerProductInfo.Level1 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_SERVER_PRODUCT_INFO_1);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
|
|
RtlAcquireResourceShared(&MasterServiceListLock,TRUE); // required for ServerServiceListFind
|
|
|
|
for (i = RestartKey; i < ServerListSize; i++) {
|
|
pSvc = ServerServiceListFind( Product, ServerList[i]->ServiceTableSize, ServerList[i]->Services );
|
|
|
|
if (pSvc != NULL) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
}
|
|
|
|
}
|
|
|
|
RtlReleaseResource(&MasterServiceListLock);
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrProductServerEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
j = 0;
|
|
|
|
RtlAcquireResourceShared(&MasterServiceListLock,TRUE); // required for ServerServiceListFind
|
|
for (i = RestartKey; i < ServerListSize; i++) {
|
|
pSvc = ServerServiceListFind( Product, ServerList[i]->ServiceTableSize, ServerList[i]->Services );
|
|
|
|
if (pSvc != NULL) {
|
|
|
|
if (Level == 0)
|
|
((PLLS_SERVER_PRODUCT_INFO_0) BufPtr)[j].Name = ServerList[i]->Name;
|
|
else {
|
|
((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].Name = ServerList[i]->Name;
|
|
((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].Flags = pSvc->Flags;
|
|
((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].MaxUses = pSvc->MaxSessionCount;
|
|
((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].MaxSetUses = pSvc->MaxSetSessionCount;
|
|
((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].HighMark = pSvc->HighMark;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
}
|
|
RtlReleaseResource(&MasterServiceListLock);
|
|
|
|
LlsrProductServerEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) RestartKey;
|
|
pProductServerInfo->LlsServerProductInfo.Level0->EntriesRead = EntriesRead;
|
|
pProductServerInfo->LlsServerProductInfo.Level0->Buffer = (PLLS_SERVER_PRODUCT_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
} // LlsrProductServerEnumW
|
|
|
|
void LlsrProductServerEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&ServerListLock);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductServerEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTA ProductServerInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductServerEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(ProductServerInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductServerEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductLicenseEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Product,
|
|
PLLS_PRODUCT_LICENSE_ENUM_STRUCTW pProductLicenseInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
DWORD RecordSize;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductLicenseEnumW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to scan list so get read access.
|
|
//
|
|
RtlAcquireResourceShared(&LicenseListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == pProductLicenseInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Level = pProductLicenseInfo->Level;
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
if ( 0 == Level )
|
|
{
|
|
if (NULL == pProductLicenseInfo->LlsProductLicenseInfo.Level0)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecordSize = sizeof( LLS_PRODUCT_LICENSE_INFO_0W );
|
|
}
|
|
else if ( 1 == Level )
|
|
{
|
|
if (NULL == pProductLicenseInfo->LlsProductLicenseInfo.Level1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecordSize = sizeof( LLS_PRODUCT_LICENSE_INFO_1W );
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ( ( i < PurchaseListSize ) && ( BufSize < pPrefMaxLen ) )
|
|
{
|
|
// level 0 enums return only per seat licenses for backwards compatibility
|
|
if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
|
|
&& !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
|
|
|| ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
|
|
&& !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
|
|
&& ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
|
|
{
|
|
BufSize += RecordSize;
|
|
EntriesRead++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen)
|
|
{
|
|
BufSize -= RecordSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
while ( i < PurchaseListSize )
|
|
{
|
|
if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
|
|
&& !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
|
|
|| ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
|
|
&& !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
|
|
&& ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
|
|
{
|
|
TotalEntries++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
if (TotalEntries > EntriesRead)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrLicenseEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
while ((j < EntriesRead) && (i < PurchaseListSize))
|
|
{
|
|
if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
|
|
&& !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
|
|
|| ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
|
|
&& !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
|
|
&& ( ( Level > 0 )
|
|
|| ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
|
|
{
|
|
if ( 0 == Level )
|
|
{
|
|
((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
|
|
((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Date = PurchaseList[i].Date;
|
|
((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Admin = PurchaseList[i].Admin;
|
|
((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Comment = PurchaseList[i].Comment;
|
|
}
|
|
else
|
|
{
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].MaxQuantity = PurchaseList[i].MaxQuantity;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Date = PurchaseList[i].Date;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Admin = PurchaseList[i].Admin;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Comment = PurchaseList[i].Comment;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].AllowedModes = PurchaseList[i].AllowedModes;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].CertificateID = PurchaseList[i].CertificateID;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Source = PurchaseList[i].Source;
|
|
((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].ExpirationDate = PurchaseList[i].ExpirationDate;
|
|
memcpy( ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Secrets, PurchaseList[i].Secrets, LLS_NUM_SECRETS * sizeof( *PurchaseList[i].Secrets ) );
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
LlsrLicenseEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
|
|
if ( 0 == Level )
|
|
{
|
|
pProductLicenseInfo->LlsProductLicenseInfo.Level0->EntriesRead = EntriesRead;
|
|
pProductLicenseInfo->LlsProductLicenseInfo.Level0->Buffer = (PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr;
|
|
}
|
|
else
|
|
{
|
|
pProductLicenseInfo->LlsProductLicenseInfo.Level1->EntriesRead = EntriesRead;
|
|
pProductLicenseInfo->LlsProductLicenseInfo.Level1->Buffer = (PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // LlsrProductLicenseEnumW
|
|
|
|
void LlsrProductLicenseEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&LicenseListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductLicenseEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
PLLS_PRODUCT_LICENSE_ENUM_STRUCTA ProductLicenseInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductLicenseEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(ProductLicenseInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
//swi, code review, why bother to validate input? It returns not supported anyway.
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductLicenseEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_USER_ENUM_STRUCTW pUserInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
pPrefMaxLen - Supplies the number of bytes of information to return
|
|
in the buffer. If this value is MAXULONG, all available information
|
|
will be returned.
|
|
|
|
pTotalEntries - Returns the total number of entries available. This value
|
|
is only valid if the return code is STATUS_SUCCESS or STATUS_MORE_ENTRIES.
|
|
|
|
pResumeHandle - Supplies a handle to resume the enumeration from where it
|
|
left off the last time through. Returns the resume handle if return
|
|
code is STATUS_MORE_ENTRIES.
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j;
|
|
PUSER_RECORD UserRec = NULL;
|
|
PVOID RestartKey = NULL,RestartKeySave = NULL;
|
|
ULONG StrSize;
|
|
LPTSTR ProductString = NULL;
|
|
PCLIENT_CONTEXT_TYPE pClient = NULL;
|
|
PVOID *pTableTmp;
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need AddEnum lock, but just shared UserListLock (as we just read
|
|
// the data).
|
|
//
|
|
RtlAcquireResourceShared(&UserListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == pUserInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
if (pResumeHandle != NULL)
|
|
{
|
|
pClient = (PCLIENT_CONTEXT_TYPE) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (*pResumeHandle != 0)
|
|
{
|
|
if ((NULL == pClient->UserEnumWRestartTable)
|
|
|| (*pResumeHandle > pClient->UserEnumWRestartTableSize))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RestartKey = RestartKeySave = pClient->UserEnumWRestartTable[(*pResumeHandle)-1];
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pUserInfo->Level;
|
|
if (Level == 0)
|
|
{
|
|
if (NULL == pUserInfo->LlsUserInfo.Level0)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_USER_INFO_0);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (NULL == pUserInfo->LlsUserInfo.Level1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_USER_INFO_1);
|
|
}
|
|
else if (Level == 2)
|
|
{
|
|
if (NULL == pUserInfo->LlsUserInfo.Level2)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RecSize = sizeof(LLS_USER_INFO_2);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
}
|
|
|
|
// Get next record
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= RecSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (UserRec != NULL)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
while (UserRec != NULL) {
|
|
TotalEntries++;
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
RestartKey = RestartKeySave;
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrUserEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
while ((i < EntriesRead) && (UserRec != NULL)) {
|
|
if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
|
|
|
|
if (Level == 0)
|
|
((PLLS_USER_INFO_0) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
|
|
else if (Level == 1) {
|
|
((PLLS_USER_INFO_1) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
|
|
|
|
if (UserRec->Mapping != NULL)
|
|
((PLLS_USER_INFO_1) BufPtr)[i].Group = UserRec->Mapping->Name;
|
|
else
|
|
((PLLS_USER_INFO_1) BufPtr)[i].Group = NULL;
|
|
|
|
((PLLS_USER_INFO_1) BufPtr)[i].Licensed = UserRec->LicensedProducts;
|
|
((PLLS_USER_INFO_1) BufPtr)[i].UnLicensed = UserRec->ServiceTableSize - UserRec->LicensedProducts;
|
|
|
|
((PLLS_USER_INFO_1) BufPtr)[i].Flags = UserRec->Flags;
|
|
} else {
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
|
|
|
|
if (UserRec->Mapping != NULL)
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Group = UserRec->Mapping->Name;
|
|
else
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Group = NULL;
|
|
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Licensed = UserRec->LicensedProducts;
|
|
((PLLS_USER_INFO_2) BufPtr)[i].UnLicensed = UserRec->ServiceTableSize - UserRec->LicensedProducts;
|
|
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Flags = UserRec->Flags;
|
|
|
|
//
|
|
// Walk product table and build up product string
|
|
//
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
StrSize = 0;
|
|
|
|
for (j = 0; j < UserRec->ServiceTableSize; j++)
|
|
StrSize += ((lstrlen(UserRec->Services[j].Service->Name) + 2) * sizeof(TCHAR));
|
|
|
|
if (StrSize != 0) {
|
|
ProductString = MIDL_user_allocate(StrSize);
|
|
if (ProductString != NULL) {
|
|
hr = StringCbCopy(ProductString, StrSize, TEXT(""));
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
for (j = 0; j < UserRec->ServiceTableSize; j++) {
|
|
if (j != 0)
|
|
{
|
|
hr = StringCbCat(ProductString, StrSize, TEXT(", "));
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
hr = StringCbCat(ProductString, StrSize, UserRec->Services[j].Service->Name);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Products = ProductString;
|
|
}
|
|
}
|
|
|
|
if ((StrSize == 0) || (ProductString == NULL)) {
|
|
ProductString = MIDL_user_allocate(2 * sizeof(TCHAR));
|
|
if (ProductString != NULL) {
|
|
hr = StringCchCopy(ProductString, 2, TEXT(""));
|
|
ASSERT(SUCCEEDED(hr));
|
|
((PLLS_USER_INFO_2) BufPtr)[i].Products = ProductString;
|
|
}
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
|
|
}
|
|
|
|
LlsrUserEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
|
|
#endif
|
|
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (NULL != pResumeHandle)
|
|
{
|
|
try
|
|
{
|
|
if (NULL == pClient->UserEnumWRestartTable)
|
|
{
|
|
pTableTmp = (PVOID *) LocalAlloc(LPTR,sizeof(PVOID));
|
|
} else
|
|
{
|
|
pTableTmp = (PVOID *) LocalReAlloc(pClient->UserEnumWRestartTable,sizeof(PVOID) * (pClient->UserEnumWRestartTableSize + 1),LHND);
|
|
}
|
|
|
|
if (NULL == pTableTmp)
|
|
{
|
|
if (BufPtr != NULL)
|
|
{
|
|
MIDL_user_free(BufPtr);
|
|
}
|
|
|
|
return STATUS_NO_MEMORY;
|
|
} else
|
|
{
|
|
pClient->UserEnumWRestartTable = pTableTmp;
|
|
}
|
|
|
|
pClient->UserEnumWRestartTable[pClient->UserEnumWRestartTableSize++] = RestartKey;
|
|
|
|
*pResumeHandle = pClient->UserEnumWRestartTableSize;
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
return Status;
|
|
}
|
|
|
|
pUserInfo->LlsUserInfo.Level0->EntriesRead = EntriesRead;
|
|
pUserInfo->LlsUserInfo.Level0->Buffer = (PLLS_USER_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
} // LlsrUserEnumW
|
|
|
|
void LlsrUserEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&UserListLock);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_USER_ENUM_STRUCTA UserInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(UserInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserInfoGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR User,
|
|
DWORD Level,
|
|
PLLS_USER_INFOW *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUSER_RECORD UserRec = NULL;
|
|
PLLS_USER_INFOW pUser = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserInfoGetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
|
|
if ((User == NULL) || (BufPtr == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*BufPtr = NULL;
|
|
|
|
if (Level != 1)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
UserRec = UserListFind(User);
|
|
|
|
if (UserRec != NULL) {
|
|
pUser = MIDL_user_allocate(sizeof(LLS_USER_INFOW));
|
|
if (pUser != NULL) {
|
|
pUser->UserInfo1.Name = (LPTSTR) UserRec->UserID;
|
|
|
|
if (UserRec->Mapping != NULL) {
|
|
pUser->UserInfo1.Mapping = UserRec->Mapping->Name;
|
|
pUser->UserInfo1.Licensed = UserRec->Mapping->Licenses;
|
|
pUser->UserInfo1.UnLicensed = 0;
|
|
} else {
|
|
pUser->UserInfo1.Mapping = NULL;
|
|
pUser->UserInfo1.Licensed = 1;
|
|
pUser->UserInfo1.UnLicensed = 0;
|
|
}
|
|
|
|
pUser->UserInfo1.Flags = UserRec->Flags;
|
|
}
|
|
}
|
|
|
|
if (UserRec == NULL)
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
if (pUser == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
*BufPtr = (PLLS_USER_INFOW) pUser;
|
|
return STATUS_SUCCESS;
|
|
} // LlsrUserInfoGetW
|
|
|
|
void LlsrUserInfoGetW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&UserListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserInfoGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR User,
|
|
DWORD Level,
|
|
PLLS_USER_INFOA *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserInfoGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(User);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (NULL == BufPtr)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*BufPtr = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserInfoGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserInfoSetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR User,
|
|
DWORD Level,
|
|
PLLS_USER_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PUSER_RECORD UserRec = NULL;
|
|
PLLS_USER_INFO_1 pUser;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserInfoSetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (Level != 1)
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
goto error;
|
|
}
|
|
|
|
if ((User == NULL) || (BufPtr == NULL))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
|
|
UserRec = UserListFind(User);
|
|
|
|
if (UserRec != NULL) {
|
|
pUser = (PLLS_USER_INFO_1) BufPtr;
|
|
|
|
//
|
|
// If in a mapping can't change SUITE_USE, since it is based on the
|
|
// License Group
|
|
//
|
|
if (UserRec->Mapping != NULL) {
|
|
RtlReleaseResource(&UserListLock);
|
|
Status = STATUS_MEMBER_IN_GROUP;
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// Reset SUITE_USE and turn off SUITE_AUTO
|
|
//
|
|
pUser->Flags &= LLS_FLAG_SUITE_USE;
|
|
UserRec->Flags &= ~LLS_FLAG_SUITE_USE;
|
|
UserRec->Flags |= pUser->Flags;
|
|
UserRec->Flags &= ~LLS_FLAG_SUITE_AUTO;
|
|
|
|
//
|
|
// Run though and clean up all old licenses
|
|
//
|
|
UserLicenseListFree( UserRec );
|
|
|
|
//
|
|
// Now assign new ones
|
|
//
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
SvcListLicenseUpdate( UserRec );
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
|
|
}
|
|
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if (UserRec == NULL)
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
else
|
|
Status = LLSDataSave();
|
|
|
|
error:
|
|
// note, some internal pointers are defined as dont_free, we should free them here
|
|
if (NULL != BufPtr)
|
|
{
|
|
pUser = (PLLS_USER_INFO_1) BufPtr;
|
|
if (NULL != pUser->Name)
|
|
{
|
|
MIDL_user_free(pUser->Name);
|
|
}
|
|
if (NULL != pUser->Group)
|
|
{
|
|
MIDL_user_free(pUser->Group);
|
|
}
|
|
}
|
|
return Status;
|
|
} // LlsrUserInfoSetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserInfoSetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR User,
|
|
DWORD Level,
|
|
PLLS_USER_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserInfoSetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(User);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserInfoSetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserDeleteW(
|
|
LLS_HANDLE Handle,
|
|
LPTSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PUSER_RECORD UserRec = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
if (User != NULL)
|
|
dprintf(TEXT("LLS TRACE: LlsUserDeleteW: %s\n"), User);
|
|
else
|
|
dprintf(TEXT("LLS TRACE: LlsUserDeleteW: <NULL>\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (User == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
|
|
UserRec = UserListFind(User);
|
|
|
|
if (UserRec != NULL) {
|
|
UserRec->Flags |= LLS_FLAG_DELETED;
|
|
UsersDeleted = TRUE;
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
SvcListLicenseFree(UserRec);
|
|
UserLicenseListFree(UserRec);
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
|
|
if (UserRec->Services != NULL)
|
|
LocalFree(UserRec->Services);
|
|
|
|
UserRec->Services = NULL;
|
|
UserRec->ServiceTableSize = 0;
|
|
}
|
|
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if (UserRec == NULL)
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
else
|
|
Status = LLSDataSave();
|
|
|
|
return Status;
|
|
|
|
} // LlsrUserDeleteW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserDeleteA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserDeleteA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(User);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserDeleteA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserProductEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR pUser,
|
|
PLLS_USER_PRODUCT_ENUM_STRUCTW pUserProductInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
PUSER_RECORD UserRec = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserProductEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to find the user-rec
|
|
//
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (pUser == NULL) || (NULL == pUserProductInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pUserProductInfo->Level;
|
|
if (Level == 0)
|
|
{
|
|
if (pUserProductInfo->LlsUserProductInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_USER_PRODUCT_INFO_0);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (pUserProductInfo->LlsUserProductInfo.Level1 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_USER_PRODUCT_INFO_1);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
UserRec = UserListFind(pUser);
|
|
if (UserRec == NULL) {
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
goto LlsrUserProductEnumWExit;
|
|
}
|
|
|
|
i = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
RtlEnterCriticalSection(&UserRec->ServiceTableLock);
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
while ((i < UserRec->ServiceTableSize) && (BufSize < pPrefMaxLen)) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= RecSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (i < UserRec->ServiceTableSize)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
TotalEntries += (UserRec->ServiceTableSize - i);
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
goto LlsrUserProductEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
j = 0;
|
|
i = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ((j < EntriesRead) && (i < UserRec->ServiceTableSize)) {
|
|
|
|
if (Level == 0)
|
|
((PLLS_USER_PRODUCT_INFO_0) BufPtr)[j].Product = UserRec->Services[i].Service->Name;
|
|
else {
|
|
((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].Product = UserRec->Services[i].Service->Name;
|
|
((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].Flags = UserRec->Services[i].Flags;
|
|
((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].LastUsed = UserRec->Services[i].LastAccess;
|
|
((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].UsageCount = UserRec->Services[i].AccessCount;
|
|
}
|
|
|
|
i++; j++;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
|
|
|
|
LlsrUserProductEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
pUserProductInfo->LlsUserProductInfo.Level0->EntriesRead = EntriesRead;
|
|
pUserProductInfo->LlsUserProductInfo.Level0->Buffer = (PLLS_USER_PRODUCT_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
} // LlsrUserProductEnumW
|
|
|
|
void LlsrUserProductEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&UserListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserProductEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR User,
|
|
PLLS_USER_PRODUCT_ENUM_STRUCTA UserProductInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserProductEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(User);
|
|
UNREFERENCED_PARAMETER(UserProductInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserProductEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserProductDeleteW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR User,
|
|
LPWSTR Product
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserProductDeleteW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ((User == NULL) || (Product == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
Status = SvcListDelete(User, Product);
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if ( STATUS_SUCCESS == Status )
|
|
{
|
|
// save modified data
|
|
Status = LLSDataSave();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrUserProductDeleteW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrUserProductDeleteA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR User,
|
|
LPSTR Product
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsUserProductDeleteA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(User);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrUserProductDeleteA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_MAPPING_ENUM_STRUCTW pMappingInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD Level;
|
|
ULONG RecSize;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to scan list so get read access.
|
|
//
|
|
RtlAcquireResourceShared(&MappingListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == pMappingInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
//
|
|
// Get size of each record based on info level. Only 0 and 1 supported.
|
|
//
|
|
Level = pMappingInfo->Level;
|
|
if (Level == 0)
|
|
{
|
|
if (pMappingInfo->LlsMappingInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_MAPPING_INFO_0W);
|
|
}
|
|
else if (Level == 1)
|
|
{
|
|
if (pMappingInfo->LlsMappingInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
RecSize = sizeof(LLS_MAPPING_INFO_1W);
|
|
}
|
|
else {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ((i < MappingListSize) && (BufSize < pPrefMaxLen)) {
|
|
BufSize += RecSize;
|
|
EntriesRead++;
|
|
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= RecSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (i < MappingListSize)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
TotalEntries += (MappingListSize - i);
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrMappingEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
j = 0;
|
|
while ((j < EntriesRead) && (i < MappingListSize)) {
|
|
if (Level == 0)
|
|
((PLLS_GROUP_INFO_0) BufPtr)[j].Name = MappingList[i]->Name;
|
|
else {
|
|
((PLLS_GROUP_INFO_1) BufPtr)[j].Name = MappingList[i]->Name;
|
|
((PLLS_GROUP_INFO_1) BufPtr)[j].Comment = MappingList[i]->Comment;
|
|
((PLLS_GROUP_INFO_1) BufPtr)[j].Licenses = MappingList[i]->Licenses;
|
|
}
|
|
|
|
i++; j++;
|
|
}
|
|
|
|
LlsrMappingEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
if (Level == 0) {
|
|
pMappingInfo->LlsMappingInfo.Level0->EntriesRead = EntriesRead;
|
|
pMappingInfo->LlsMappingInfo.Level0->Buffer = (PLLS_MAPPING_INFO_0W) BufPtr;
|
|
} else {
|
|
pMappingInfo->LlsMappingInfo.Level1->EntriesRead = EntriesRead;
|
|
pMappingInfo->LlsMappingInfo.Level1->Buffer = (PLLS_MAPPING_INFO_1W) BufPtr;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // LlsrMappingEnumW
|
|
|
|
void LlsrMappingEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&MappingListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_MAPPING_ENUM_STRUCTA MappingInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(MappingInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingInfoGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOW *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PMAPPING_RECORD pMapping = NULL;
|
|
PLLS_GROUP_INFO_1 pMap = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingInfoGetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceShared(&MappingListLock, TRUE);
|
|
|
|
if ((Mapping == NULL) || (BufPtr == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*BufPtr = NULL;
|
|
|
|
if (Level != 1)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
pMapping = MappingListFind(Mapping);
|
|
|
|
if (pMapping != NULL) {
|
|
pMap = MIDL_user_allocate(sizeof(LLS_GROUP_INFO_1));
|
|
if (pMap != NULL) {
|
|
pMap->Name = pMapping->Name;
|
|
pMap->Comment = pMapping->Comment;
|
|
pMap->Licenses = pMapping->Licenses;
|
|
}
|
|
}
|
|
|
|
if (pMapping == NULL)
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
if (pMap == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
*BufPtr = (PLLS_MAPPING_INFOW) pMap;
|
|
return STATUS_SUCCESS;
|
|
|
|
} // LlsrMappingInfoGetW
|
|
|
|
void LlsrMappingInfoGetW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&MappingListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingInfoGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOA *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingInfoGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (NULL == BufPtr)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*BufPtr = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingInfoGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingInfoSetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PMAPPING_RECORD pMapping = NULL;
|
|
PLLS_GROUP_INFO_1 pMap;
|
|
LPTSTR NewComment;
|
|
HRESULT hr;
|
|
size_t cch;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingInfoSetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (Level != 1)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
if ((Mapping == NULL) || (BufPtr == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
|
|
|
|
pMapping = MappingListFind(Mapping);
|
|
|
|
if (pMapping != NULL) {
|
|
pMap = (PLLS_GROUP_INFO_1) BufPtr;
|
|
|
|
//
|
|
// Check if comment has changed
|
|
//
|
|
if (pMap->Comment != NULL)
|
|
if (lstrcmp(pMap->Comment, pMapping->Comment)) {
|
|
cch = lstrlen(pMap->Comment) + 1;
|
|
NewComment = (LPTSTR) LocalAlloc(LPTR, cch * sizeof(TCHAR));
|
|
if (NewComment != NULL) {
|
|
LocalFree(pMapping->Comment);
|
|
pMapping->Comment = NewComment;
|
|
hr = StringCchCopy(pMapping->Comment, cch, pMap->Comment);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
|
|
if ( pMapping->Licenses != pMap->Licenses )
|
|
{
|
|
MappingLicenseListFree( pMapping );
|
|
pMapping->Licenses = pMap->Licenses;
|
|
MappingLicenseUpdate( pMapping, TRUE );
|
|
}
|
|
}
|
|
|
|
RtlReleaseResource(&MappingListLock);
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if (pMapping == NULL)
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
else
|
|
Status = MappingListSave();
|
|
|
|
return Status;
|
|
|
|
} // LlsrMappingInfoSetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingInfoSetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingInfoSetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingInfoSetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping,
|
|
PLLS_USER_ENUM_STRUCTW pMappingUserInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PMAPPING_RECORD pMapping;
|
|
DWORD Level;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// Need to scan list so get read access.
|
|
//
|
|
RtlAcquireResourceShared(&MappingListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == pMappingUserInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Level = pMappingUserInfo->Level;
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
if (Level != 0)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
if (pMappingUserInfo->LlsUserInfo.Level0 == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
pMapping = MappingListFind(Mapping);
|
|
if (pMapping == NULL) {
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
goto LlsrMappingUserEnumWExit;
|
|
}
|
|
|
|
//
|
|
// Calculate how many records will fit into PrefMaxLen buffer. This is
|
|
// the record size * # records + space for the string data. If MAX_ULONG
|
|
// is passed in then we return all records.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ((i < pMapping->NumMembers) && (BufSize < pPrefMaxLen)) {
|
|
BufSize += sizeof(LLS_USER_INFO_0);
|
|
EntriesRead++;
|
|
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
//
|
|
// If we overflowed the buffer then back up one record.
|
|
//
|
|
if (BufSize > pPrefMaxLen) {
|
|
BufSize -= sizeof(LLS_USER_INFO_0);
|
|
EntriesRead--;
|
|
}
|
|
|
|
if (i < pMapping->NumMembers)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
//
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
//
|
|
TotalEntries += (pMapping->NumMembers - i);
|
|
|
|
//
|
|
// Reset Enum to correct place.
|
|
//
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
//
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
//
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrMappingUserEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
//
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
//
|
|
while ((j < EntriesRead) && (i < pMapping->NumMembers)) {
|
|
((PLLS_USER_INFO_0) BufPtr)[j].Name = pMapping->Members[i];
|
|
i++; j++;
|
|
}
|
|
|
|
LlsrMappingUserEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
pMappingUserInfo->LlsUserInfo.Level0->EntriesRead = EntriesRead;
|
|
pMappingUserInfo->LlsUserInfo.Level0->Buffer = (PLLS_USER_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
|
|
} // LlsrMappingUserEnumW
|
|
|
|
void LlsrMappingUserEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&MappingListLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping,
|
|
PLLS_USER_ENUM_STRUCTA MappingUserInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
UNREFERENCED_PARAMETER(MappingUserInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingUserEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserAddW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping,
|
|
LPWSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PUSER_RECORD pUserRec;
|
|
PMAPPING_RECORD pMap;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ((Mapping == NULL) || (User == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
|
|
pMap = MappingUserListAdd( Mapping, User );
|
|
|
|
if (pMap == NULL)
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
else {
|
|
pUserRec = UserListFind(User);
|
|
|
|
if (pUserRec != NULL)
|
|
UserMappingAdd(pMap, pUserRec);
|
|
}
|
|
|
|
RtlReleaseResource(&MappingListLock);
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
Status = MappingListSave();
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
Status = LLSDataSave();
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // LlsrMappingUserAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserAddA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping,
|
|
LPSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
UNREFERENCED_PARAMETER(User);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingUserAddA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserDeleteW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping,
|
|
LPWSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PUSER_RECORD pUser;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserDeleteW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ((Mapping == NULL) || (User == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
|
|
Status = MappingUserListDelete(Mapping, User);
|
|
RtlReleaseResource(&MappingListLock);
|
|
|
|
RtlAcquireResourceExclusive(&UserListLock, TRUE);
|
|
pUser = UserListFind( User );
|
|
RtlReleaseResource(&UserListLock);
|
|
|
|
if (pUser != NULL) {
|
|
//
|
|
// if auto switch to BackOffice then turn BackOffice off
|
|
//
|
|
if (pUser->Flags & LLS_FLAG_SUITE_AUTO)
|
|
pUser->Flags &= ~ LLS_FLAG_SUITE_USE;
|
|
|
|
//
|
|
// Free up any licenses used by the user
|
|
//
|
|
RtlEnterCriticalSection(&pUser->ServiceTableLock);
|
|
SvcListLicenseFree( pUser );
|
|
pUser->Mapping = NULL;
|
|
|
|
//
|
|
// And claim any needed new-ones
|
|
//
|
|
SvcListLicenseUpdate( pUser );
|
|
RtlLeaveCriticalSection(&pUser->ServiceTableLock);
|
|
}
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
Status = MappingListSave();
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
Status = LLSDataSave();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrMappingUserDeleteW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingUserDeleteA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping,
|
|
LPSTR User
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingUserDeleteA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
UNREFERENCED_PARAMETER(User);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingUserDeleteA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingAddW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PMAPPING_RECORD pMap;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (Level != 1)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
if ((BufPtr == NULL) ||
|
|
(BufPtr->MappingInfo1.Name == NULL) ||
|
|
(BufPtr->MappingInfo1.Comment == NULL))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
|
|
|
|
pMap = MappingListAdd(BufPtr->MappingInfo1.Name,
|
|
BufPtr->MappingInfo1.Comment,
|
|
BufPtr->MappingInfo1.Licenses,
|
|
&Status);
|
|
|
|
RtlReleaseResource(&MappingListLock);
|
|
if (pMap == NULL)
|
|
{
|
|
if (STATUS_SUCCESS == Status)
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
Status = MappingListSave();
|
|
|
|
return Status;
|
|
} // LlsrMappingAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingAddA(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_MAPPING_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingAddA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingDeleteW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Mapping
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingDeleteW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (Mapping == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
|
|
Status = MappingListDelete(Mapping);
|
|
RtlReleaseResource(&MappingListLock);
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
Status = MappingListSave();
|
|
|
|
return Status;
|
|
} // LlsrMappingDeleteW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrMappingDeleteA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Mapping
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsMappingDeleteA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Mapping);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrMappingDeleteA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServerEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Server,
|
|
PLLS_SERVER_ENUM_STRUCTW pServerProductInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServerEnumW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Server);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(pPrefMaxLen);
|
|
UNREFERENCED_PARAMETER(pResumeHandle);
|
|
|
|
if (NULL == pTotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServerEnumW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServerEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Server,
|
|
PLLS_SERVER_ENUM_STRUCTA pServerProductInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServerEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Server);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServerEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServerProductEnumW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Server,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTW pServerProductInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServerProductEnumW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Server);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(pPrefMaxLen);
|
|
UNREFERENCED_PARAMETER(pResumeHandle);
|
|
|
|
if (NULL == pTotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServerProductEnumW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServerProductEnumA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Server,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTA pServerProductInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServerProductEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Server);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServerProductEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTW pServerProductInfo,
|
|
DWORD pPrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductEnumW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(pPrefMaxLen);
|
|
UNREFERENCED_PARAMETER(pResumeHandle);
|
|
|
|
if (NULL == pTotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductEnumW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_SERVER_PRODUCT_ENUM_STRUCTA pServerProductInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(pServerProductInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductInfoGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Product,
|
|
DWORD Level,
|
|
PLLS_SERVER_PRODUCT_INFOW *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductInfoGetW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (NULL == BufPtr)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*BufPtr = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductInfoGetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductInfoGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
DWORD Level,
|
|
PLLS_SERVER_PRODUCT_INFOA *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductInfoGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (NULL == BufPtr)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*BufPtr = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductInfoGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductInfoSetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR Product,
|
|
DWORD Level,
|
|
PLLS_SERVER_PRODUCT_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductInfoSetW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductInfoSetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrLocalProductInfoSetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
DWORD Level,
|
|
PLLS_SERVER_PRODUCT_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalProductInfoSetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrLocalProductInfoSetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServiceInfoGetW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_SERVICE_INFOW *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PLLS_SERVICE_INFO_0 pInfo;
|
|
FILETIME ftTimeStartedLocal;
|
|
LARGE_INTEGER llTimeStartedLocal;
|
|
LARGE_INTEGER llTimeStartedSystem;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServiceInfoGetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
// make sure the config info is up-to-date
|
|
ConfigInfoUpdate(NULL,FALSE);
|
|
|
|
RtlEnterCriticalSection(&ConfigInfoLock);
|
|
|
|
if (BufPtr == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*BufPtr = NULL;
|
|
|
|
if (Level != 0)
|
|
return STATUS_INVALID_LEVEL;
|
|
|
|
pInfo = (PLLS_SERVICE_INFO_0) MIDL_user_allocate(sizeof(LLS_SERVICE_INFO_0));
|
|
if (pInfo == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
pInfo->Version = ConfigInfo.Version;
|
|
pInfo->Mode = LLS_MODE_ENTERPRISE_SERVER;
|
|
pInfo->ReplicateTo = ConfigInfo.ReplicateTo;
|
|
pInfo->EnterpriseServer = ConfigInfo.EnterpriseServer;
|
|
pInfo->ReplicationType = ConfigInfo.ReplicationType;
|
|
pInfo->ReplicationTime = ConfigInfo.ReplicationTime;
|
|
pInfo->LastReplicated = ConfigInfo.LastReplicatedSeconds;
|
|
pInfo->UseEnterprise = ConfigInfo.UseEnterprise;
|
|
|
|
SystemTimeToFileTime( &ConfigInfo.Started, &ftTimeStartedLocal );
|
|
|
|
// convert time started (a local SYSTEMTIME) to a system time DWORD in seconds since 1980
|
|
llTimeStartedLocal.u.LowPart = ftTimeStartedLocal.dwLowDateTime;
|
|
llTimeStartedLocal.u.HighPart = ftTimeStartedLocal.dwHighDateTime;
|
|
|
|
RtlLocalTimeToSystemTime( &llTimeStartedLocal, &llTimeStartedSystem );
|
|
RtlTimeToSecondsSince1980( &llTimeStartedSystem, &pInfo->TimeStarted );
|
|
|
|
*BufPtr = (PLLS_SERVICE_INFOW) pInfo;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // LlsrServiceInfoGetW
|
|
|
|
void LlsrServiceInfoGetW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlLeaveCriticalSection(&ConfigInfoLock);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServiceInfoGetA(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_SERVICE_INFOA *BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServiceInfoGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (BufPtr == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
*BufPtr = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServiceInfoGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServiceInfoSetW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_SERVICE_INFOW BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PLLS_SERVICE_INFO_0W pInfo;
|
|
HKEY hKeyParameters;
|
|
LONG lError;
|
|
NTSTATUS Status = STATUS_NO_MEMORY;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServiceInfoSetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (BufPtr == NULL)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
if (Level != 0)
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
goto error;
|
|
}
|
|
|
|
pInfo = &(BufPtr->ServiceInfo0);
|
|
|
|
lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\LicenseService\\Parameters", 0, KEY_WRITE, &hKeyParameters );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
lError = RegSetValueExW( hKeyParameters, L"EnterpriseServer", 0, REG_SZ, (LPBYTE) pInfo->EnterpriseServer, sizeof( WCHAR ) * ( 1 + lstrlenW( pInfo->EnterpriseServer ) ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
lError = RegSetValueEx( hKeyParameters, L"ReplicationTime", 0, REG_DWORD, (LPBYTE) &pInfo->ReplicationTime, sizeof( pInfo->ReplicationTime ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
lError = RegSetValueEx( hKeyParameters, L"ReplicationType", 0, REG_DWORD, (LPBYTE) &pInfo->ReplicationType, sizeof( pInfo->ReplicationType ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
lError = RegSetValueEx( hKeyParameters, L"UseEnterprise", 0, REG_DWORD, (LPBYTE) &pInfo->UseEnterprise, sizeof( pInfo->UseEnterprise ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
ConfigInfoUpdate(NULL,TRUE);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey( hKeyParameters );
|
|
}
|
|
|
|
error:
|
|
if (NULL != BufPtr)
|
|
{
|
|
// note, some internal pointers are defined as dont_free, we should free them here
|
|
if (NULL != BufPtr->ServiceInfo0.ReplicateTo)
|
|
{
|
|
MIDL_user_free(BufPtr->ServiceInfo0.ReplicateTo);
|
|
}
|
|
if (NULL != BufPtr->ServiceInfo0.EnterpriseServer)
|
|
{
|
|
MIDL_user_free(BufPtr->ServiceInfo0.EnterpriseServer);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrServiceInfoSetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrServiceInfoSetA(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_SERVICE_INFOA BufPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsServiceInfoSetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(BufPtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrServiceInfoSetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Replication Functions
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
VOID __RPC_USER LLS_REPL_HANDLE_rundown(
|
|
LLS_REPL_HANDLE Handle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
LLS_REPL_HANDLE xHandle;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LLS_REPL_HANDLE_rundown\n"));
|
|
#endif
|
|
|
|
if (Handle == NULL)
|
|
return;
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if (pClient != NULL)
|
|
if (pClient->Active) {
|
|
xHandle = Handle;
|
|
LlsrReplClose(&xHandle);
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
} // LLS_REPL_HANDLE_rundown
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrReplConnect(
|
|
PLLS_REPL_HANDLE Handle,
|
|
LPTSTR Name
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplConnect: %s\n"), Name);
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == Handle)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*Handle = NULL;
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) midl_user_allocate(sizeof(REPL_CONTEXT_TYPE));
|
|
if (pClient == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
memcpy(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE);
|
|
|
|
if (Name != NULL)
|
|
lstrcpyn(pClient->Name, Name,MAX_COMPUTERNAME_LENGTH+1);
|
|
else
|
|
{
|
|
hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), TEXT(""));
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
pClient->Active = TRUE;
|
|
pClient->Replicated = FALSE;
|
|
|
|
pClient->ServicesSent = FALSE;
|
|
pClient->ServiceTableSize = 0;
|
|
pClient->Services = NULL;
|
|
|
|
pClient->ServersSent = FALSE;
|
|
pClient->ServerTableSize = 0;
|
|
pClient->Servers = NULL;
|
|
|
|
pClient->ServerServicesSent = FALSE;
|
|
pClient->ServerServiceTableSize = 0;
|
|
pClient->ServerServices = NULL;
|
|
|
|
pClient->UsersSent = FALSE;
|
|
pClient->UserLevel = 0;
|
|
pClient->UserTableSize = 0;
|
|
pClient->Users = NULL;
|
|
|
|
pClient->CertDbSent = FALSE;
|
|
pClient->CertDbProductStringSize = 0;
|
|
pClient->CertDbProductStrings = NULL;
|
|
pClient->CertDbNumHeaders = 0;
|
|
pClient->CertDbHeaders = NULL;
|
|
pClient->CertDbNumClaims = 0;
|
|
pClient->CertDbClaims = NULL;
|
|
|
|
pClient->ProductSecuritySent = FALSE;
|
|
pClient->ProductSecurityStringSize = 0;
|
|
pClient->ProductSecurityStrings = NULL;
|
|
|
|
*Handle = pClient;
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrReplConnect
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrReplClose(
|
|
LLS_REPL_HANDLE *pHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOL Replicated = TRUE;
|
|
LLS_REPL_HANDLE Handle = NULL;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
PSERVER_RECORD Server;
|
|
ULONG i;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplClose\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == pHandle)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//swi, code review, why we declare Handle here? It doesn't do anything in the code
|
|
Handle = *pHandle;
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
pClient->Active = FALSE;
|
|
|
|
//
|
|
// Check to see if we have all the information from the client - if we do
|
|
// then munge this information into our internal tables.
|
|
//
|
|
if (pClient->ServersSent && pClient->UsersSent && pClient->ServicesSent && pClient->ServerServicesSent) {
|
|
#if DBG
|
|
if (TraceFlags & TRACE_RPC)
|
|
dprintf(TEXT("LLS Replication - Munging Data\n"));
|
|
#endif
|
|
|
|
UnpackAll (
|
|
pClient->ServiceTableSize,
|
|
pClient->Services,
|
|
pClient->ServerTableSize,
|
|
pClient->Servers,
|
|
pClient->ServerServiceTableSize,
|
|
pClient->ServerServices,
|
|
pClient->UserLevel,
|
|
pClient->UserTableSize,
|
|
pClient->Users
|
|
);
|
|
|
|
if ( pClient->CertDbSent )
|
|
{
|
|
CertDbUnpack(
|
|
pClient->CertDbProductStringSize,
|
|
pClient->CertDbProductStrings,
|
|
pClient->CertDbNumHeaders,
|
|
pClient->CertDbHeaders,
|
|
pClient->CertDbNumClaims,
|
|
pClient->CertDbClaims,
|
|
TRUE );
|
|
}
|
|
|
|
if ( pClient->ProductSecuritySent )
|
|
{
|
|
ProductSecurityUnpack(
|
|
pClient->ProductSecurityStringSize,
|
|
pClient->ProductSecurityStrings );
|
|
}
|
|
} else
|
|
Replicated = FALSE;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//
|
|
// Replication Finished - clean up the context data.
|
|
//
|
|
#if DBG
|
|
if (TraceFlags & TRACE_RPC)
|
|
dprintf(TEXT("LLS Replication - Munging Finished\n"));
|
|
#endif
|
|
|
|
if (pClient->Servers != NULL) {
|
|
for (i = 0; i < pClient->ServerTableSize; i++)
|
|
MIDL_user_free(pClient->Servers[i].Name);
|
|
|
|
MIDL_user_free(pClient->Servers);
|
|
}
|
|
|
|
if (pClient->Services != NULL) {
|
|
for (i = 0; i < pClient->ServiceTableSize; i++) {
|
|
MIDL_user_free(pClient->Services[i].Name);
|
|
MIDL_user_free(pClient->Services[i].FamilyName);
|
|
}
|
|
|
|
MIDL_user_free(pClient->Services);
|
|
}
|
|
|
|
if (pClient->ServerServices != NULL)
|
|
MIDL_user_free(pClient->ServerServices);
|
|
|
|
if (pClient->Users != NULL) {
|
|
for (i = 0; i < pClient->UserTableSize; i++)
|
|
{
|
|
if ( 0 == pClient->UserLevel )
|
|
{
|
|
MIDL_user_free( ((PREPL_USER_RECORD_0) (pClient->Users))[i].Name );
|
|
}
|
|
else
|
|
{
|
|
ASSERT( 1 == pClient->UserLevel );
|
|
MIDL_user_free( ((PREPL_USER_RECORD_1) (pClient->Users))[i].Name );
|
|
}
|
|
}
|
|
|
|
MIDL_user_free(pClient->Users);
|
|
}
|
|
|
|
if (pClient->CertDbProductStrings != NULL)
|
|
{
|
|
MIDL_user_free(pClient->CertDbProductStrings);
|
|
}
|
|
|
|
if (pClient->CertDbHeaders != NULL)
|
|
{
|
|
MIDL_user_free(pClient->CertDbHeaders);
|
|
}
|
|
|
|
if (pClient->CertDbClaims != NULL)
|
|
{
|
|
MIDL_user_free(pClient->CertDbClaims);
|
|
}
|
|
|
|
if (pClient->ProductSecurityStrings != NULL)
|
|
{
|
|
MIDL_user_free(pClient->ProductSecurityStrings);
|
|
}
|
|
|
|
if (pClient->Replicated) {
|
|
if (Replicated) {
|
|
RtlAcquireResourceShared(&ServerListLock, TRUE);
|
|
Server = ServerListFind(pClient->Name);
|
|
RtlReleaseResource(&ServerListLock);
|
|
|
|
ASSERT(Server != NULL);
|
|
if (Server != NULL)
|
|
Server->LastReplicated = pClient->ReplicationStart;
|
|
}
|
|
|
|
RtlEnterCriticalSection(&ConfigInfoLock);
|
|
i = --ConfigInfo.NumReplicating;
|
|
RtlLeaveCriticalSection(&ConfigInfoLock);
|
|
|
|
if ( !i )
|
|
{
|
|
// no one's replicating; save all our data files
|
|
SaveAll();
|
|
}
|
|
}
|
|
|
|
MIDL_user_free(pClient);
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
//
|
|
// Let RPC know were done with it.
|
|
//
|
|
|
|
*pHandle = NULL;
|
|
|
|
return Status;
|
|
} // LlsrReplClose
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationRequestW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Version,
|
|
PREPL_REQUEST pRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
PSERVER_RECORD Server = NULL;
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC | TRACE_REPLICATION))
|
|
dprintf(TEXT("LLS TRACE: LlsReplicationRequestW: %s\n"), ((PCLIENT_CONTEXT_TYPE) Handle)->Name);
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (Version != REPL_VERSION) {
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
if (pRequest == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
ComputerName[0] = 0;
|
|
ASSERT(NULL != pRequest);
|
|
pRequest->EnterpriseServer[0] = 0;
|
|
|
|
//
|
|
// Check Enterprise server date from client to see if we need to update
|
|
// ours. Also, send back new one for the client.
|
|
//
|
|
RtlEnterCriticalSection(&ConfigInfoLock);
|
|
if (ConfigInfo.ComputerName != NULL)
|
|
{
|
|
hr = StringCbCopy(ComputerName, sizeof(ComputerName), ConfigInfo.ComputerName);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
#ifdef DISABLED_FOR_NT5
|
|
if (ConfigInfo.EnterpriseServerDate < pRequest->EnterpriseServerDate) {
|
|
if (lstrlen(pRequest->EnterpriseServer) != 0) {
|
|
//ConfigInfo.EnterpriseServer is hard code allocated in ConfigInfoInit as size of MAX_COMPUTERNAME_LENGTH + 3 chars. It seems lazy.
|
|
ASSERT(NULL != ConfigInfo.EnterpriseServer);
|
|
hr = StringCchCopy(ConfigInfo.EnterpriseServer, MAX_COMPUTERNAME_LENGTH + 3, pRequest->EnterpriseServer);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ConfigInfo.EnterpriseServerDate = pRequest->EnterpriseServerDate;
|
|
}
|
|
}
|
|
#endif // DISABLED_FOR_NT5
|
|
|
|
if (ConfigInfo.EnterpriseServer != NULL)
|
|
{
|
|
//ConfigInfo.EnterpriseServer is hard code allocated in ConfigInfoInit as size of MAX_COMPUTERNAME_LENGTH + 3 chars. It seems lazy.
|
|
hr = StringCchCopy(pRequest->EnterpriseServer, MAX_COMPUTERNAME_LENGTH + 3, ConfigInfo.EnterpriseServer);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
pRequest->EnterpriseServerDate = ConfigInfo.EnterpriseServerDate;
|
|
|
|
//
|
|
// Increment Repl Count
|
|
//
|
|
ConfigInfo.NumReplicating++;
|
|
RtlLeaveCriticalSection(&ConfigInfoLock);
|
|
|
|
//
|
|
// Find this server in our server list (add it if not there)
|
|
//
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
pClient->Replicated = TRUE;
|
|
RtlAcquireResourceExclusive(&ServerListLock, TRUE);
|
|
Server = ServerListAdd(pClient->Name, ComputerName);
|
|
RtlReleaseResource(&ServerListLock);
|
|
|
|
if (Server == NULL) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
pClient->ReplicationStart = pRequest->CurrentTime;
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
pRequest->LastReplicated = Server->LastReplicated;
|
|
return Status;
|
|
} // LlsrReplicationRequestW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationServerAddW(
|
|
LLS_HANDLE Handle,
|
|
ULONG NumRecords,
|
|
PREPL_SERVER_RECORD Servers
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
DWORD i;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplicationServerAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != Servers)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free(Servers[i].Name);
|
|
}
|
|
MIDL_user_free(Servers);
|
|
}
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->ServersSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != Servers)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free(Servers[i].Name);
|
|
}
|
|
MIDL_user_free(Servers);
|
|
}
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->ServersSent = TRUE;
|
|
pClient->ServerTableSize = NumRecords;
|
|
pClient->Servers = Servers;
|
|
|
|
//don't free Servers and it will be free in ReplClose
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrReplicationServerAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationServerServiceAddW(
|
|
LLS_HANDLE Handle,
|
|
ULONG NumRecords,
|
|
PREPL_SERVER_SERVICE_RECORD ServerServices
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplicationServerServiceAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != ServerServices)
|
|
{
|
|
MIDL_user_free(ServerServices);
|
|
}
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->ServerServicesSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != ServerServices)
|
|
{
|
|
MIDL_user_free(ServerServices);
|
|
}
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->ServerServicesSent = TRUE;
|
|
pClient->ServerServiceTableSize = NumRecords;
|
|
pClient->ServerServices = ServerServices;
|
|
|
|
//don't free and it will be free in ReplClose
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrReplicationServerServiceAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationServiceAddW(
|
|
LLS_HANDLE Handle,
|
|
ULONG NumRecords,
|
|
PREPL_SERVICE_RECORD Services
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
DWORD i;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplicationServiceAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != Services)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free(Services[i].Name);
|
|
MIDL_user_free(Services[i].FamilyName);
|
|
}
|
|
MIDL_user_free(Services);
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->ServicesSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != Services)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free(Services[i].Name);
|
|
MIDL_user_free(Services[i].FamilyName);
|
|
}
|
|
MIDL_user_free(Services);
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->ServicesSent = TRUE;
|
|
pClient->ServiceTableSize = NumRecords;
|
|
pClient->Services = Services;
|
|
|
|
// don't free and it will be free in ReplClose
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrReplicationServiceAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationUserAddW(
|
|
LLS_HANDLE Handle,
|
|
ULONG NumRecords,
|
|
PREPL_USER_RECORD_0 Users
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE *pClient;
|
|
DWORD i;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsReplicationUserAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != Users)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free( Users[i].Name );
|
|
}
|
|
MIDL_user_free(Users);
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->UsersSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != Users)
|
|
{
|
|
for (i = 0; i < NumRecords; i++)
|
|
{
|
|
MIDL_user_free( Users[i].Name );
|
|
}
|
|
MIDL_user_free(Users);
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->UsersSent = TRUE;
|
|
pClient->UserLevel = 0;
|
|
pClient->UserTableSize = NumRecords;
|
|
pClient->Users = Users;
|
|
|
|
// don't free Users and it will be free in ReplClose
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
return Status;
|
|
} // LlsrReplicationUserAddW
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Licensing Functions
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// Definitions from SVCTBL.C to fascilitate the SBS specific code below.
|
|
#define FILE_PRINT "FilePrint "
|
|
#define FILE_PRINT_BASE "FilePrint"
|
|
#define FILE_PRINT_VERSION_NDX ( 9 )
|
|
|
|
NTSTATUS
|
|
LlsrLicenseRequestW(
|
|
PLICENSE_HANDLE pLicenseHandle,
|
|
LPWSTR ProductID,
|
|
ULONG VersionIndex,
|
|
BOOLEAN IsAdmin,
|
|
ULONG DataType,
|
|
ULONG DataSize,
|
|
PBYTE Data
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Handle = 0xFFFFFFFFL;
|
|
PSID Sid = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(DataSize);
|
|
|
|
#if DBG
|
|
if ( TraceFlags & (TRACE_FUNCTION_TRACE) )
|
|
dprintf(TEXT("LLS TRACE: LlsrLicenseRequestW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
|
|
if ((NULL == pLicenseHandle) || (NULL == ProductID) || (NULL == Data) || (VersionIndex >= (ULONG)lstrlen(ProductID)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// SBS mods (bug# 505640), per server fix. Check database of user licenses to determine whether or not the specified user
|
|
// name already has a license. If it does, just bump the RefCount.
|
|
//
|
|
|
|
if (SBSPerServerHotfix) {
|
|
PPER_SERVER_USER_RECORD Walker;
|
|
|
|
LPWSTR UserName = NULL;
|
|
DWORD SidNameSize = 0;
|
|
LPWSTR DomainName = NULL;
|
|
DWORD DomainSize = 0;
|
|
SID_NAME_USE SidNameUse;
|
|
WCHAR FilePrintName[] = TEXT(FILE_PRINT);
|
|
|
|
if (DataType == NT_LS_USER_NAME) {
|
|
|
|
//
|
|
// If we get a request from a user name with a '$' in it, we're going to return a dummy license
|
|
// handle without actually consuming a session in the license server. We need to make sure
|
|
// that a check for this is always the very first one in the free path.
|
|
//
|
|
if (wcschr((LPWSTR)Data,L'$')) {
|
|
*pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(PER_SERVER_DUMMY_LICENSE);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// make sure we have a user name in the same form that we specified in the user list.
|
|
if (NULL == (UserName = wcschr((LPWSTR)Data,L'\\'))) {
|
|
UserName = (LPWSTR)Data;
|
|
} else {
|
|
UserName++;
|
|
}
|
|
|
|
//
|
|
// In the event of a bogus user account, LookupAccountName fails with ERROR_NONE_MAPPED.
|
|
// ERROR_INSUFFICIENT_BUFFER indicates that the account name exists, but that the buffer is too small.
|
|
// Hence, the following code is a simple existence check for the account name.
|
|
//
|
|
if (!LookupAccountName(NULL,
|
|
UserName,
|
|
NULL,
|
|
&SidNameSize,
|
|
NULL,
|
|
&DomainSize,
|
|
&SidNameUse)) {
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
*pLicenseHandle = NULL;
|
|
return LS_INSUFFICIENT_UNITS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Lookup the name again
|
|
if (NULL != (Sid = malloc(SidNameSize))) {
|
|
if (NULL != (DomainName = malloc(DomainSize*sizeof(WCHAR)))) {
|
|
if (!LookupAccountName(NULL,
|
|
UserName,
|
|
Sid,
|
|
&SidNameSize,
|
|
DomainName,
|
|
&DomainSize,
|
|
&SidNameUse)) {
|
|
free(DomainName);
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
free(DomainName);
|
|
|
|
} else {
|
|
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Verify and make a copy of the SID for later checks.
|
|
//
|
|
if (!IsValidSid((PSID)Data)) {
|
|
*pLicenseHandle = NULL;
|
|
return LS_INSUFFICIENT_UNITS;
|
|
}
|
|
|
|
SidNameSize = GetLengthSid((PSID)Data);
|
|
|
|
if (NULL == (Sid = malloc(SidNameSize))) {
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
}
|
|
|
|
if (!CopySid(SidNameSize,Sid,(PSID)Data)) {
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
}
|
|
|
|
if (!IsWellKnownSid(Sid,WinLocalSystemSid)) {
|
|
|
|
//
|
|
// In the event of a bogus user account, LookupAccountSid fails with ERROR_NONE_MAPPED.
|
|
// ERROR_INSUFFICIENT_BUFFER indicates that the account name exists, but that the buffer is too small.
|
|
// Hence, the following code is a simple existence check for the account name.
|
|
//
|
|
SidNameSize = 0;
|
|
if (!LookupAccountSid(NULL,
|
|
Sid,
|
|
NULL,
|
|
&SidNameSize,
|
|
NULL,
|
|
&DomainSize,
|
|
&SidNameUse)) {
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
*pLicenseHandle = NULL;
|
|
return LS_INSUFFICIENT_UNITS;
|
|
}
|
|
}
|
|
|
|
if (NULL != (UserName = malloc(SidNameSize*sizeof(WCHAR)))) {
|
|
if (NULL != (DomainName = malloc(DomainSize*sizeof(WCHAR)))) {
|
|
if (LookupAccountSid(NULL,
|
|
Sid,
|
|
UserName,
|
|
&SidNameSize,
|
|
DomainName,
|
|
&DomainSize,
|
|
&SidNameUse)) {
|
|
|
|
if (SidNameUse != SidTypeUser) {
|
|
free(UserName);
|
|
free(DomainName);
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_INSUFFICIENT_UNITS;
|
|
}
|
|
|
|
} else {
|
|
|
|
free(DomainName);
|
|
free(UserName);
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
|
|
free(DomainName);
|
|
|
|
} else {
|
|
|
|
free(Sid);
|
|
free(UserName);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
|
|
free(UserName);
|
|
|
|
} else {
|
|
|
|
free(Sid);
|
|
*pLicenseHandle = NULL;
|
|
return LS_UNKNOWN_STATUS;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
RtlEnterCriticalSection(&PerServerListLock);
|
|
// Walk our database and attempt to find an entry for the user/SID specified in the call.
|
|
for (Walker = PerServerList; Walker; Walker = Walker->Next) {
|
|
if (EqualSid(Sid,Walker->Sid)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we broke out of the loop early, we found a matching entry. Up the ReferenceCount and return.
|
|
if (Walker) {
|
|
Walker->RefCount++;
|
|
if (LLS_POTENTIAL_ATTACK_THRESHHOLD == Walker->RefCount) {
|
|
PotentialAttackCounter++;
|
|
}
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
*pLicenseHandle = (LICENSE_HANDLE)Walker;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// if we didn't find a record for the user, let the license server engine have the request and
|
|
// our code below will add a record. In order to better manage license enforcement, SBS always uses
|
|
// FilePrint CALs.
|
|
|
|
ProductID = (LPWSTR)FilePrintName;
|
|
VersionIndex = FILE_PRINT_VERSION_NDX;
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
}
|
|
|
|
//
|
|
// end SBS mods
|
|
//
|
|
|
|
Status = DispatchRequestLicense(DataType, Data, ProductID, VersionIndex, IsAdmin, &Handle);
|
|
|
|
//
|
|
// SBS mods (bug# 505640), per server fix, add acquired license to the user tracking database. The will function
|
|
// as expected for the end user in per seat mode as well, although some tracking information will be lost.
|
|
//
|
|
|
|
// ensure that we're on SBS and that the license acquisition succeeded. Also a sanity check on
|
|
// the input data (which should always succeed).
|
|
if (SBSPerServerHotfix && (Status == STATUS_SUCCESS) && Data) {
|
|
PPER_SERVER_USER_RECORD UserRecord = (PPER_SERVER_USER_RECORD)malloc(sizeof(PER_SERVER_USER_RECORD));
|
|
|
|
if (UserRecord) {
|
|
UserRecord->RefCount = 1;
|
|
UserRecord->ActualLicenseHandle = Handle + 1;
|
|
UserRecord->Next = NULL;
|
|
UserRecord->Sid = Sid;
|
|
|
|
// We have a valid user track record. Add it to the list.
|
|
RtlEnterCriticalSection(&PerServerListLock);
|
|
UserRecord->Next = PerServerList;
|
|
PerServerList = UserRecord;
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
|
|
// We've successfully added our record to the list. Return a pointer to the entry in the context
|
|
// field.
|
|
*pLicenseHandle = (LICENSE_HANDLE)UserRecord;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
//
|
|
// if we've gotten here it means there's been a problem allocating something. Fall through to the normal
|
|
// path so that the customer doesn't get penalized for this. Note this adds a little bit of work for us
|
|
// in the license free path, since we could in rare cases end up with a mix of typical license handles and
|
|
// pointers to our internal structures. We just have to do a check for pointer consistency in the free path.
|
|
//
|
|
}
|
|
|
|
//
|
|
// end SBS mods
|
|
//
|
|
|
|
// Can't allow Handle value of zero
|
|
*pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(Handle+1);
|
|
|
|
return Status;
|
|
} // LlsrLicenseRequestW
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLicenseFree(
|
|
PLICENSE_HANDLE pLicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
if ( TraceFlags & (TRACE_FUNCTION_TRACE) )
|
|
dprintf(TEXT("LLS TRACE: LlsrLicenseFree\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == pLicenseHandle)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
//
|
|
// SBS mods (bug# 505640), per server licensing hotfix free code.
|
|
//
|
|
|
|
if (SBSPerServerHotfix) {
|
|
PPER_SERVER_USER_RECORD Walker = NULL;
|
|
PPER_SERVER_USER_RECORD UserRecord = (PPER_SERVER_USER_RECORD)(*pLicenseHandle);
|
|
|
|
if (PtrToUlong(*pLicenseHandle) == PER_SERVER_DUMMY_LICENSE) {
|
|
*pLicenseHandle = NULL;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Because there are some rare cases where we may be mixing internal license handles and our hotfix track
|
|
// records, walk the list and make sure out handle is there.
|
|
//
|
|
RtlEnterCriticalSection(&PerServerListLock);
|
|
if (PerServerList == UserRecord) {
|
|
// stupid coder tricks: if UserRecord is the first on the list, point Walker at the list head
|
|
// for later possible removal. Since we only reference Next on Walker, this shouldn't present
|
|
// a problem.
|
|
Walker = (PPER_SERVER_USER_RECORD)&PerServerList;
|
|
} else {
|
|
for (Walker = PerServerList; Walker && Walker->Next != UserRecord; Walker = Walker->Next);
|
|
}
|
|
if (Walker) {
|
|
// we've found this entry on the list. Decrement the ref count and see whether it needs to go away.
|
|
if (!(--UserRecord->RefCount)) {
|
|
//ref count went to zero. Stop tracking this user and let the license engine free the license.
|
|
Walker->Next = UserRecord->Next;
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
// this next line should correctly free either a SID or a user name.
|
|
free(UserRecord->Sid);
|
|
*pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(UserRecord->ActualLicenseHandle);
|
|
free(UserRecord);
|
|
} else {
|
|
|
|
if (LLS_POTENTIAL_ATTACK_THRESHHOLD == UserRecord->RefCount) {
|
|
PotentialAttackCounter--;
|
|
}
|
|
|
|
// ref count still valid. Just return STATUS_SUCCESS on free call.
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
*pLicenseHandle = NULL;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
} else {
|
|
RtlLeaveCriticalSection(&PerServerListLock);
|
|
}
|
|
//
|
|
// if we get here, we need to let the license server engine actually free it's original handle, either
|
|
// because it wasn't on our list or the ref count (i.e., number of acquires) has been matched by a
|
|
// number of frees.
|
|
//
|
|
}
|
|
|
|
//
|
|
// end SBS mods
|
|
//
|
|
|
|
DispatchFreeLicense(PtrToUlong(*pLicenseHandle) - 1);
|
|
|
|
*pLicenseHandle = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrLicenseFree
|
|
|
|
void __RPC_USER LICENSE_HANDLE_rundown(
|
|
LICENSE_HANDLE LicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description: Called by RPC when client quits without calling
|
|
LlsrLicenseFree (i.e. when it crashes)
|
|
|
|
|
|
Arguments: LicenseHandle - Handle given to client
|
|
|
|
|
|
Return Value: none
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LICENSE_HANDLE_rundown\n"));
|
|
#endif
|
|
|
|
if (LicenseHandle != NULL)
|
|
{
|
|
DispatchFreeLicense(PtrToUlong(LicenseHandle) - 1);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#if DBG
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Debugging API's
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgTableDump(
|
|
DWORD Table
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
//
|
|
// FreeHandle is actually TableID
|
|
//
|
|
switch(Table) {
|
|
case SERVICE_TABLE_NUM:
|
|
ServiceListDebugDump();
|
|
break;
|
|
|
|
case USER_TABLE_NUM:
|
|
UserListDebugDump();
|
|
break;
|
|
|
|
case SID_TABLE_NUM:
|
|
SidListDebugDump();
|
|
break;
|
|
|
|
case LICENSE_TABLE_NUM:
|
|
LicenseListDebugDump();
|
|
break;
|
|
|
|
case ADD_CACHE_TABLE_NUM:
|
|
AddCacheDebugDump();
|
|
break;
|
|
|
|
case MASTER_SERVICE_TABLE_NUM:
|
|
MasterServiceListDebugDump();
|
|
break;
|
|
|
|
case SERVICE_FAMILY_TABLE_NUM:
|
|
MasterServiceRootDebugDump();
|
|
break;
|
|
|
|
case MAPPING_TABLE_NUM:
|
|
MappingListDebugDump();
|
|
break;
|
|
|
|
case SERVER_TABLE_NUM:
|
|
ServerListDebugDump();
|
|
break;
|
|
|
|
case SECURE_PRODUCT_TABLE_NUM:
|
|
ProductSecurityListDebugDump();
|
|
break;
|
|
|
|
case CERTIFICATE_TABLE_NUM:
|
|
CertDbDebugDump();
|
|
break;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgTableDump
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgTableInfoDump(
|
|
DWORD Table,
|
|
LPTSTR Item
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == Item)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch(Table) {
|
|
case SERVICE_TABLE_NUM:
|
|
ServiceListDebugInfoDump((PVOID) Item);
|
|
break;
|
|
|
|
case USER_TABLE_NUM:
|
|
UserListDebugInfoDump((PVOID) Item);
|
|
break;
|
|
|
|
// case SID_TABLE_NUM:
|
|
// SidListDebugInfoDump((PVOID) Item);
|
|
// break;
|
|
|
|
// case LICENSE_TABLE_NUM:
|
|
// LicenseListInfoDebugDump((PVOID) Item);
|
|
// break;
|
|
|
|
// case ADD_CACHE_TABLE_NUM:
|
|
// AddCacheDebugDump((PVOID) Item);
|
|
// break;
|
|
|
|
case MASTER_SERVICE_TABLE_NUM:
|
|
MasterServiceListDebugInfoDump((PVOID) Item);
|
|
break;
|
|
|
|
case SERVICE_FAMILY_TABLE_NUM:
|
|
MasterServiceRootDebugInfoDump((PVOID) Item);
|
|
break;
|
|
|
|
case MAPPING_TABLE_NUM:
|
|
MappingListDebugInfoDump((PVOID) Item);
|
|
break;
|
|
|
|
case SERVER_TABLE_NUM:
|
|
ServerListDebugInfoDump((PVOID) Item);
|
|
break;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgTableInfoDump
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgTableFlush(
|
|
DWORD Table
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(Table);
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgTableFlush
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgTraceSet(
|
|
DWORD Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
TraceFlags = Flags;
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgTraceSet
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgConfigDump(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
ConfigInfoDebugDump();
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgConfigDump
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgReplicationForce(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
NtSetEvent( ReplicationEvent, NULL );
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgReplicationForce
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgReplicationDeny(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgReplicationDeny
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgRegistryUpdateForce(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
ServiceListResynch();
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgRegistryUpdateForce
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrDbgDatabaseFlush(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
LLSDataSave();
|
|
return STATUS_SUCCESS;
|
|
} // LlsrDbgDatabaseFlush
|
|
|
|
|
|
|
|
#endif // #if DBG
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Extended RPC
|
|
|
|
NTSTATUS LlsrProductSecurityGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product,
|
|
LPBOOL pIsSecure
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the "security" of a product. A product is deemed secure iff
|
|
it requires a secure certificate. In such a case, licenses for the
|
|
product may not be entered via the Honesty ("enter the number of
|
|
licenses you purchased") method.
|
|
|
|
NOTE: Not yet implemented. Use LlsrProductSecurityGetW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPSTR)
|
|
The name of the product ("DisplayName") for which to receive the
|
|
security.
|
|
pIsSecure (LPBOOL)
|
|
On return, and if successful, indicates whether the product is
|
|
secure.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrProductSecurityGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
|
|
if (NULL == pIsSecure)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pIsSecure = FALSE;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductSecurityGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductSecurityGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR DisplayName,
|
|
LPBOOL pIsSecure
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the "security" of a product. A product is deemed secure iff
|
|
it requires a secure certificate. In such a case, licenses for the
|
|
product may not be entered via the Honesty ("enter the number of
|
|
licenses you purchased") method.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPWSTR)
|
|
The name of the product ("DisplayName") for which to receive the
|
|
security.
|
|
pIsSecure (LPBOOL)
|
|
On return, and if successful, indicates whether the product is
|
|
secure.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrProductSecurityGetW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == pIsSecure)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RtlAcquireResourceShared( &LocalServiceListLock, TRUE );
|
|
|
|
*pIsSecure = ServiceIsSecure( DisplayName );
|
|
|
|
RtlReleaseResource( &LocalServiceListLock );
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsrProductSecurityGetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductSecuritySetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR Product
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Flags the given product as secure. A product is deemed secure iff
|
|
it requires a secure certificate. In such a case, licenses for the
|
|
product may not be entered via the Honesty ("enter the number of
|
|
licenses you purchased") method.
|
|
|
|
This designation is not reversible and is propagated up the
|
|
replication tree.
|
|
|
|
NOTE: Not yet implemented. Use LlsrProductSecuritySetW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPSTR)
|
|
The name of the product ("DisplayName") for which to activate
|
|
security.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrProductSecuritySetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Product);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrProductSecuritySetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS LlsrProductSecuritySetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR DisplayName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Flags the given product as secure. A product is deemed secure iff
|
|
it requires a secure certificate. In such a case, licenses for the
|
|
product may not be entered via the Honesty ("enter the number of
|
|
licenses you purchased") method.
|
|
|
|
This designation is not reversible and is propagated up the
|
|
replication tree.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPWSTR)
|
|
The name of the product ("DisplayName") for which to activate
|
|
security.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrProductSecuritySetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == DisplayName)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
nt = ServiceSecuritySet( DisplayName );
|
|
|
|
return nt;
|
|
} // LlsrProductSecuritySetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrProductLicensesGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR DisplayName,
|
|
DWORD Mode,
|
|
LPDWORD pQuantity )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of licenses installed for use in the given mode.
|
|
|
|
NOTE: Not yet implemented. Use LlsrProductLicensesGetW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPSTR)
|
|
The name of the product for which to tally licenses.
|
|
Mode (DWORD)
|
|
Mode for which to tally licenses.
|
|
pQuantity (LPDWORD)
|
|
On return (and if successful), holds the total number of licenses
|
|
for use by the given product in the given license mode.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductLicensesGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(DisplayName);
|
|
UNREFERENCED_PARAMETER(Mode);
|
|
|
|
if (NULL == pQuantity)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pQuantity = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsProductLicensesGetA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrProductLicensesGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR DisplayName,
|
|
DWORD Mode,
|
|
LPDWORD pQuantity )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of licenses installed for use in the given mode.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
Product (LPWSTR)
|
|
The name of the product for which to tally licenses.
|
|
Mode (DWORD)
|
|
Mode for which to tally licenses.
|
|
pQuantity (LPDWORD)
|
|
On return (and if successful), holds the total number of licenses
|
|
for use by the given product in the given license mode.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsProductLicensesGetW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == pQuantity)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pQuantity = 0;
|
|
|
|
if ( !Mode || ServiceIsSecure( DisplayName ) )
|
|
{
|
|
// get limit from purchase list
|
|
*pQuantity = ProductLicensesGet( DisplayName, Mode );
|
|
}
|
|
else
|
|
{
|
|
DWORD i;
|
|
|
|
LocalServiceListUpdate();
|
|
LocalServerServiceListUpdate();
|
|
ServiceListResynch();
|
|
|
|
RtlAcquireResourceShared( &LocalServiceListLock, TRUE );
|
|
|
|
// get limit from concurrent limit setting from the registry
|
|
for ( i=0; i < LocalServiceListSize; i++ )
|
|
{
|
|
if ( !lstrcmpi( LocalServiceList[i]->DisplayName, DisplayName ) )
|
|
{
|
|
// get concurrent limit straight from the registry, not from LocalServiceList!
|
|
// (if the mode is set to per seat, the per server licenses in the
|
|
// LocalServiceList will always be 0!)
|
|
TCHAR szKeyName[ 512 ];
|
|
HKEY hKeyService;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
hr = StringCbPrintf( szKeyName, sizeof(szKeyName), TEXT("System\\CurrentControlSet\\Services\\LicenseInfo\\%s"), LocalServiceList[i]->Name );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// if error encountered, return STATUS_SUCCESS with *pQuantity = 0
|
|
if ( STATUS_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKeyService ) )
|
|
{
|
|
dwSize = sizeof( *pQuantity );
|
|
RegQueryValueEx( hKeyService, TEXT("ConcurrentLimit"), NULL, &dwType, (LPBYTE) pQuantity, &dwSize );
|
|
|
|
RegCloseKey( hKeyService );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
RtlReleaseResource( &LocalServiceListLock );
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} // LlsProductLicensesGetW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimEnumA(
|
|
LLS_HANDLE Handle,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOA LicensePtr,
|
|
PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA TargetInfo )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerates the servers on which a given secure certificate is installed.
|
|
This function is normally invoked when an attempt to add licenses from
|
|
a certificate is denied.
|
|
|
|
NOTE: Not yet implemented. Use LlsrCertificateClaimEnumW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOA)
|
|
Describes a license for which the certificate targets are requested.
|
|
TargetInfo (PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA)
|
|
Container in which to return the target information.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(LicenseLevel);
|
|
UNREFERENCED_PARAMETER(LicensePtr);
|
|
UNREFERENCED_PARAMETER(TargetInfo);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrCertificateClaimEnumA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimEnumW(
|
|
LLS_HANDLE Handle,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOW LicensePtr,
|
|
PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTW TargetInfo )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerates the servers on which a given secure certificate is installed.
|
|
This function is normally invoked when an attempt to add licenses from
|
|
a certificate is denied.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOW)
|
|
Describes a license for which the certificate targets are requested.
|
|
TargetInfo (PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA)
|
|
Container in which to return the target information.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceShared( &CertDbHeaderListLock, TRUE );
|
|
|
|
if ((NULL == TargetInfo) || (NULL == LicensePtr))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ( ( 1 != LicenseLevel ) || ( 0 != TargetInfo->Level ) )
|
|
{
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
if (TargetInfo->LlsCertificateClaimInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
nt = CertDbClaimsGet( (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1,
|
|
&TargetInfo->LlsCertificateClaimInfo.Level0->EntriesRead,
|
|
(PLLS_CERTIFICATE_CLAIM_INFO_0 *) &TargetInfo->LlsCertificateClaimInfo.Level0->Buffer );
|
|
|
|
if ( STATUS_SUCCESS != nt )
|
|
{
|
|
TargetInfo->LlsCertificateClaimInfo.Level0->EntriesRead = 0;
|
|
TargetInfo->LlsCertificateClaimInfo.Level0->Buffer = NULL;
|
|
}
|
|
|
|
|
|
return nt;
|
|
} // LlsrCertificateClaimEnumW
|
|
|
|
void LlsrCertificateClaimEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource( &CertDbHeaderListLock );
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimAddCheckA(
|
|
LLS_HANDLE Handle,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOA LicensePtr,
|
|
LPBOOL pbMayInstall )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that no more licenses from a given certificate are installed in
|
|
a licensing enterprise than are allowed by the certificate.
|
|
|
|
NOTE: Not yet implemented. Use LlsrCertificateClaimAddCheckW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOA)
|
|
Describes a license for which permission is requested.
|
|
pbMayInstall (LPBOOL)
|
|
On return (and if successful), indicates whether the certificate
|
|
may be legally installed.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddCheckA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(LicenseLevel);
|
|
UNREFERENCED_PARAMETER(LicensePtr);
|
|
|
|
if (NULL == pbMayInstall)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pbMayInstall = FALSE;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrCertificateClaimAddCheckA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimAddCheckW(
|
|
LLS_HANDLE Handle,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOW LicensePtr,
|
|
LPBOOL pbMayInstall )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that no more licenses from a given certificate are installed in
|
|
a licensing enterprise than are allowed by the certificate.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOW)
|
|
Describes a license for which permission is requested.
|
|
pbMayInstall (LPBOOL)
|
|
On return (and if successful), indicates whether the certificate
|
|
may be legally installed.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddCheckW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ((NULL == pbMayInstall) || (NULL == LicensePtr))
|
|
{
|
|
nt = STATUS_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
*pbMayInstall = FALSE;
|
|
|
|
if ( 1 != LicenseLevel )
|
|
{
|
|
nt = STATUS_INVALID_LEVEL;
|
|
goto error;
|
|
}
|
|
|
|
*pbMayInstall = CertDbClaimApprove( (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1 );
|
|
nt = STATUS_SUCCESS;
|
|
|
|
error:
|
|
if (NULL != LicensePtr)
|
|
{
|
|
// PNAMEW are declared as dont_free, we should free them
|
|
if (0 == LicenseLevel)
|
|
{
|
|
if (NULL != LicensePtr->LicenseInfo0.Product)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Product);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo0.Admin)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Admin);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo0.Comment)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Comment);
|
|
}
|
|
}
|
|
|
|
if (1 == LicenseLevel)
|
|
{
|
|
if (NULL != LicensePtr->LicenseInfo1.Product)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Product);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Admin)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Admin);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Comment)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Comment);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Vendor)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Vendor);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Source)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Source);
|
|
}
|
|
}
|
|
}
|
|
|
|
return nt;
|
|
} // LlsrCertificateClaimAddCheckW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimAddA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR ServerName,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOA LicensePtr )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Declare a number of licenses from a given certificate as being installed
|
|
on the target machine.
|
|
|
|
NOTE: Not yet implemented. Use LlsCertificateClaimAddW().
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle.
|
|
ServerName (LPWSTR)
|
|
Name of the server on which the licenses are installed.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOA)
|
|
Describes the installed license.
|
|
|
|
Return Value:
|
|
|
|
STATUS_NOT_SUPPORTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(ServerName);
|
|
UNREFERENCED_PARAMETER(LicenseLevel);
|
|
UNREFERENCED_PARAMETER(LicensePtr);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
} // LlsrCertificateClaimAddA
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrCertificateClaimAddW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR ServerName,
|
|
DWORD LicenseLevel,
|
|
PLLS_LICENSE_INFOW LicensePtr )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Declare a number of licenses from a given certificate as being installed
|
|
on the target machine.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_HANDLE)
|
|
An open LLS handle to the target license server.
|
|
ServerName (LPWSTR)
|
|
Name of the server on which the licenses are installed.
|
|
LicenseLevel (DWORD)
|
|
The level of the license structure pointed to by pLicenseInfo.
|
|
LicensePtr (PLLS_LICENSE_INFOW)
|
|
Describes the installed license.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or NTSTATUS error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( 1 != LicenseLevel )
|
|
{
|
|
nt = STATUS_INVALID_LEVEL;
|
|
goto error;
|
|
}
|
|
|
|
if (NULL == LicensePtr)
|
|
{
|
|
nt = STATUS_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
nt = CertDbClaimEnter( ServerName, (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1, FALSE, 0 );
|
|
|
|
if ( STATUS_SUCCESS == nt )
|
|
{
|
|
nt = CertDbSave();
|
|
}
|
|
|
|
error:
|
|
if (NULL != LicensePtr)
|
|
{
|
|
// PNAMEW are declared as dont_free, we should free them
|
|
if (0 == LicenseLevel)
|
|
{
|
|
if (NULL != LicensePtr->LicenseInfo0.Product)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Product);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo0.Admin)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Admin);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo0.Comment)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo0.Comment);
|
|
}
|
|
}
|
|
|
|
if (1 == LicenseLevel)
|
|
{
|
|
if (NULL != LicensePtr->LicenseInfo1.Product)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Product);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Admin)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Admin);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Comment)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Comment);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Vendor)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Vendor);
|
|
}
|
|
if (NULL != LicensePtr->LicenseInfo1.Source)
|
|
{
|
|
MIDL_user_free(LicensePtr->LicenseInfo1.Source);
|
|
}
|
|
}
|
|
}
|
|
|
|
return nt;
|
|
} // LlsrCertificateClaimAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationCertDbAddW(
|
|
LLS_REPL_HANDLE Handle,
|
|
DWORD Level,
|
|
REPL_CERTIFICATES Certificates )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called as an optional part of replication, this function receives
|
|
the contents of the remote certificate database.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_REPL_HANDLE)
|
|
An open replication handle.
|
|
Level (DWORD)
|
|
Level of replicated certificate information.
|
|
Certificates (REPL_CERTIFICATES)
|
|
Replicated certificate information.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_INVALID_LEVEL.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE * pClient;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrReplicationCertDbAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( ( 0 != Level )
|
|
|| ( ( NULL != Certificates )
|
|
&& ( ( 0 != Certificates->Level0.ClaimLevel )
|
|
|| ( 0 != Certificates->Level0.HeaderLevel ) ) ) )
|
|
{
|
|
nt = STATUS_INVALID_LEVEL;
|
|
}
|
|
else
|
|
{
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != Certificates)
|
|
{
|
|
if (NULL != Certificates->Level0.Strings)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.Strings);
|
|
}
|
|
|
|
if (NULL != Certificates->Level0.HeaderContainer.Level0.Headers)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.HeaderContainer.Level0.Headers);
|
|
}
|
|
|
|
if (NULL != Certificates->Level0.ClaimContainer.Level0.Claims)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.ClaimContainer.Level0.Claims);
|
|
}
|
|
MIDL_user_free( Certificates );
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->CertDbSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != Certificates)
|
|
{
|
|
if (NULL != Certificates->Level0.Strings)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.Strings);
|
|
}
|
|
|
|
if (NULL != Certificates->Level0.HeaderContainer.Level0.Headers)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.HeaderContainer.Level0.Headers);
|
|
}
|
|
|
|
if (NULL != Certificates->Level0.ClaimContainer.Level0.Claims)
|
|
{
|
|
MIDL_user_free(Certificates->Level0.ClaimContainer.Level0.Claims);
|
|
}
|
|
MIDL_user_free( Certificates );
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->CertDbSent = TRUE;
|
|
|
|
if ( NULL != Certificates )
|
|
{
|
|
pClient->CertDbProductStringSize = Certificates->Level0.StringSize;
|
|
pClient->CertDbProductStrings = Certificates->Level0.Strings;
|
|
pClient->CertDbNumHeaders = Certificates->Level0.HeaderContainer.Level0.NumHeaders;
|
|
pClient->CertDbHeaders = Certificates->Level0.HeaderContainer.Level0.Headers;
|
|
pClient->CertDbNumClaims = Certificates->Level0.ClaimContainer.Level0.NumClaims;
|
|
pClient->CertDbClaims = Certificates->Level0.ClaimContainer.Level0.Claims;
|
|
|
|
// free container only, rest of data will be free in ReplClose
|
|
MIDL_user_free( Certificates );
|
|
}
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
nt = GetExceptionCode();
|
|
}
|
|
}
|
|
|
|
return nt;
|
|
} // LlsrReplicationCertDbAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationProductSecurityAddW(
|
|
LLS_REPL_HANDLE Handle,
|
|
DWORD Level,
|
|
REPL_SECURE_PRODUCTS SecureProducts )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called as an optional part of replication, this function receives
|
|
the list of products which require secure certificates.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_REPL_HANDLE)
|
|
An open replication handle.
|
|
Level (DWORD)
|
|
Level of replicated secure product information.
|
|
SecureProducts (REPL_SECURE_PRODUCTS)
|
|
Replicated secure product information.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_INVALID_LEVEL.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE * pClient;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrReplicationProductSecurityAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( 0 != Level )
|
|
{
|
|
nt = STATUS_INVALID_LEVEL;
|
|
}
|
|
else
|
|
{
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != SecureProducts)
|
|
{
|
|
if (NULL != SecureProducts->Level0.Strings)
|
|
{
|
|
MIDL_user_free( SecureProducts->Level0.Strings );
|
|
}
|
|
MIDL_user_free( SecureProducts );
|
|
}
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->ProductSecuritySent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != SecureProducts)
|
|
{
|
|
if (NULL != SecureProducts->Level0.Strings)
|
|
{
|
|
MIDL_user_free( SecureProducts->Level0.Strings );
|
|
}
|
|
MIDL_user_free( SecureProducts );
|
|
}
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->ProductSecuritySent = TRUE;
|
|
|
|
if ( NULL != SecureProducts )
|
|
{
|
|
pClient->ProductSecurityStringSize = SecureProducts->Level0.StringSize;
|
|
pClient->ProductSecurityStrings = SecureProducts->Level0.Strings;
|
|
|
|
// free container only, rest of data will be free in ReplClose
|
|
MIDL_user_free( SecureProducts );
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
nt = GetExceptionCode();
|
|
}
|
|
}
|
|
|
|
return nt;
|
|
} // LlsrReplicationProductSecurityAddW
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LlsrReplicationUserAddExW(
|
|
LLS_REPL_HANDLE Handle,
|
|
DWORD Level,
|
|
REPL_USERS Users )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Replacement for LlsrReplicationUserAddW(). (This function, unlike its
|
|
counterpart, supports structure levels.) This function replicates the
|
|
user list.
|
|
|
|
Arguments:
|
|
|
|
Handle (LLS_REPL_HANDLE)
|
|
An open replication handle.
|
|
Level (DWORD)
|
|
Level of replicated user information.
|
|
Users (REPL_USERS)
|
|
Replicated user information.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_INVALID_LEVEL.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS nt = STATUS_SUCCESS;
|
|
REPL_CONTEXT_TYPE * pClient;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrReplicationUserAddExW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( ( 0 != Level ) && ( 1 != Level ) )
|
|
{
|
|
nt = STATUS_INVALID_LEVEL;
|
|
}
|
|
else
|
|
{
|
|
pClient = (REPL_CONTEXT_TYPE *) Handle;
|
|
|
|
try
|
|
{
|
|
if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
|
|
{
|
|
// free all data because it is dont_free
|
|
if (NULL != Users)
|
|
{
|
|
if (0 == Level )
|
|
{
|
|
if (NULL != Users->Level0.Users)
|
|
{
|
|
MIDL_user_free( Users->Level0.Users );
|
|
}
|
|
}
|
|
if (1 == Level )
|
|
{
|
|
if (NULL != Users->Level1.Users)
|
|
{
|
|
MIDL_user_free( Users->Level1.Users );
|
|
}
|
|
}
|
|
MIDL_user_free( Users );
|
|
}
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pClient->UsersSent)
|
|
{
|
|
// don't accept more than one Add
|
|
// free all data because it is dont_free
|
|
if (NULL != Users)
|
|
{
|
|
if (0 == Level )
|
|
{
|
|
if (NULL != Users->Level0.Users)
|
|
{
|
|
MIDL_user_free( Users->Level0.Users );
|
|
}
|
|
}
|
|
if (1 == Level )
|
|
{
|
|
if (NULL != Users->Level1.Users)
|
|
{
|
|
MIDL_user_free( Users->Level1.Users );
|
|
}
|
|
}
|
|
MIDL_user_free( Users );
|
|
}
|
|
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
}
|
|
|
|
pClient->UsersSent = TRUE;
|
|
pClient->UserLevel = Level;
|
|
|
|
if ( NULL != Users )
|
|
{
|
|
if ( 0 == Level )
|
|
{
|
|
pClient->UserTableSize = Users->Level0.NumUsers;
|
|
pClient->Users = Users->Level0.Users;
|
|
}
|
|
else
|
|
{
|
|
pClient->UserTableSize = Users->Level1.NumUsers;
|
|
pClient->Users = Users->Level1.Users;
|
|
}
|
|
|
|
// free container only, rest of data will be free in ReplClose
|
|
MIDL_user_free( Users );
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER ) {
|
|
nt = GetExceptionCode();
|
|
}
|
|
}
|
|
|
|
return nt;
|
|
} // LlsrReplicationUserAddExW
|
|
|
|
|
|
NTSTATUS
|
|
LlsrCapabilityGet(
|
|
LLS_HANDLE Handle,
|
|
DWORD cbCapabilities,
|
|
LPBYTE pbCapabilities )
|
|
{
|
|
static DWORD adwCapabilitiesSupported[] =
|
|
{
|
|
LLS_CAPABILITY_SECURE_CERTIFICATES,
|
|
LLS_CAPABILITY_REPLICATE_CERT_DB,
|
|
LLS_CAPABILITY_REPLICATE_PRODUCT_SECURITY,
|
|
LLS_CAPABILITY_REPLICATE_USERS_EX,
|
|
LLS_CAPABILITY_SERVICE_INFO_GETW,
|
|
LLS_CAPABILITY_LOCAL_SERVICE_API,
|
|
(DWORD) -1L
|
|
};
|
|
|
|
DWORD i;
|
|
DWORD dwCapByte;
|
|
DWORD dwCapBit;
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if (NULL == pbCapabilities)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
ZeroMemory( pbCapabilities, cbCapabilities );
|
|
|
|
for ( i=0; (DWORD) -1L != adwCapabilitiesSupported[ i ]; i++ )
|
|
{
|
|
dwCapByte = adwCapabilitiesSupported[ i ] / 8;
|
|
dwCapBit = adwCapabilitiesSupported[ i ] - 8 * dwCapByte;
|
|
|
|
if ( dwCapByte < cbCapabilities )
|
|
{
|
|
pbCapabilities[ dwCapByte ] |= ( 1 << dwCapBit );
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceEnumW(
|
|
LLS_HANDLE Handle,
|
|
PLLS_LOCAL_SERVICE_ENUM_STRUCTW LocalServiceInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD pTotalEntries,
|
|
LPDWORD pResumeHandle )
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PVOID BufPtr = NULL;
|
|
ULONG BufSize = 0;
|
|
ULONG EntriesRead = 0;
|
|
ULONG TotalEntries = 0;
|
|
ULONG i = 0;
|
|
ULONG j = 0;
|
|
const DWORD RecordSize = sizeof( LLS_LOCAL_SERVICE_INFO_0W );
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrLocalServiceEnumW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
// Need to scan list so get read access.
|
|
RtlAcquireResourceShared(&LocalServiceListLock, TRUE);
|
|
|
|
if ((NULL == pTotalEntries) || (NULL == LocalServiceInfo))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pTotalEntries = 0;
|
|
|
|
if ( 0 != LocalServiceInfo->Level )
|
|
{
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
if (LocalServiceInfo->LlsLocalServiceInfo.Level0 == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Calculate how many records will fit into PrefMaxLen buffer.
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
while ( ( i < LocalServiceListSize ) && ( BufSize < PrefMaxLen ) )
|
|
{
|
|
BufSize += RecordSize;
|
|
EntriesRead++;
|
|
i++;
|
|
}
|
|
|
|
TotalEntries = EntriesRead;
|
|
|
|
// If we overflowed the buffer then back up one record.
|
|
if (BufSize > PrefMaxLen)
|
|
{
|
|
BufSize -= RecordSize;
|
|
EntriesRead--;
|
|
}
|
|
|
|
// Now walk to the end of the list to see how many more records are still
|
|
// available.
|
|
TotalEntries += LocalServiceListSize - i;
|
|
|
|
if (TotalEntries > EntriesRead)
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
// Reset Enum to correct place.
|
|
i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
|
|
|
|
// We now know how many records will fit into the buffer, so allocate space
|
|
// and fix up pointers so we can copy the information.
|
|
BufPtr = MIDL_user_allocate(BufSize);
|
|
if (BufPtr == NULL)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto LlsrLocalServiceEnumWExit;
|
|
}
|
|
|
|
RtlZeroMemory((PVOID) BufPtr, BufSize);
|
|
|
|
// Buffers are all setup, so loop through records and copy the data.
|
|
while ((j < EntriesRead) && (i < LocalServiceListSize))
|
|
{
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].KeyName = LocalServiceList[i]->Name;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].DisplayName = LocalServiceList[i]->DisplayName;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].FamilyDisplayName = LocalServiceList[i]->FamilyDisplayName;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].Mode = LocalServiceList[i]->Mode;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].FlipAllow = LocalServiceList[i]->FlipAllow;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].ConcurrentLimit = LocalServiceList[i]->ConcurrentLimit;
|
|
((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].HighMark = LocalServiceList[i]->HighMark;
|
|
|
|
j++;
|
|
i++;
|
|
}
|
|
|
|
LlsrLocalServiceEnumWExit:
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
|
|
#endif
|
|
*pTotalEntries = TotalEntries;
|
|
|
|
if (pResumeHandle != NULL)
|
|
*pResumeHandle = (ULONG) i;
|
|
|
|
LocalServiceInfo->LlsLocalServiceInfo.Level0->EntriesRead = EntriesRead;
|
|
LocalServiceInfo->LlsLocalServiceInfo.Level0->Buffer = (PLLS_LOCAL_SERVICE_INFO_0W) BufPtr;
|
|
|
|
return Status;
|
|
}
|
|
|
|
void LlsrLocalServiceEnumW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&LocalServiceListLock);
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceEnumA(
|
|
LLS_HANDLE Handle,
|
|
PLLS_LOCAL_SERVICE_ENUM_STRUCTA LocalServiceInfo,
|
|
DWORD PrefMaxLen,
|
|
LPDWORD TotalEntries,
|
|
LPDWORD ResumeHandle )
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalServiceEnumA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(LocalServiceInfo);
|
|
UNREFERENCED_PARAMETER(PrefMaxLen);
|
|
UNREFERENCED_PARAMETER(ResumeHandle);
|
|
|
|
if (NULL == TotalEntries)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*TotalEntries = 0;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceAddW(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOW LocalServiceInfo )
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrLocalServiceAddW\n"));
|
|
#endif
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( 0 != Level )
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
}
|
|
else if ( ( NULL == LocalServiceInfo)
|
|
|| ( NULL == LocalServiceInfo->LocalServiceInfo0.KeyName )
|
|
|| ( NULL == LocalServiceInfo->LocalServiceInfo0.DisplayName )
|
|
|| ( NULL == LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName ) )
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
LONG lError;
|
|
HKEY hKeyLicenseInfo;
|
|
HKEY hKeyService;
|
|
DWORD dwDisposition;
|
|
|
|
lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_LICENSE, 0, KEY_WRITE, &hKeyLicenseInfo );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// create key
|
|
lError = RegCreateKeyEx( hKeyLicenseInfo, LocalServiceInfo->LocalServiceInfo0.KeyName, 0, NULL, 0, KEY_WRITE, NULL, &hKeyService, &dwDisposition );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// set DisplayName
|
|
lError = RegSetValueEx( hKeyService,
|
|
REG_VALUE_NAME,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE) LocalServiceInfo->LocalServiceInfo0.DisplayName,
|
|
( sizeof( *LocalServiceInfo->LocalServiceInfo0.DisplayName )
|
|
* ( 1 + lstrlen( LocalServiceInfo->LocalServiceInfo0.DisplayName ) ) ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// set FamilyDisplayName
|
|
lError = RegSetValueEx( hKeyService,
|
|
REG_VALUE_FAMILY,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE) LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName,
|
|
( sizeof( *LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName )
|
|
* ( 1 + lstrlen( LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName ) ) ) );
|
|
}
|
|
|
|
RegCloseKey( hKeyService );
|
|
}
|
|
|
|
RegCloseKey( hKeyLicenseInfo );
|
|
}
|
|
|
|
switch ( lError )
|
|
{
|
|
case ERROR_SUCCESS:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_PATH_NOT_FOUND:
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
break;
|
|
default:
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
if ( STATUS_SUCCESS == Status )
|
|
{
|
|
// set remaining items and update LocalServiceList
|
|
Status = LlsrLocalServiceInfoSetW( Handle, LocalServiceInfo->LocalServiceInfo0.KeyName, Level, LocalServiceInfo );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceAddA(
|
|
LLS_HANDLE Handle,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOA LocalServiceInfo )
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalServiceAddA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(LocalServiceInfo);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceInfoSetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR KeyName,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOW LocalServiceInfo )
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoSetW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
if ( 0 != Level )
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
}
|
|
else if (( NULL == KeyName ) || ( NULL == LocalServiceInfo ))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
LONG lError;
|
|
HKEY hKeyLicenseInfo;
|
|
HKEY hKeyService;
|
|
|
|
lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_LICENSE, 0, KEY_WRITE, &hKeyLicenseInfo );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
lError = RegOpenKeyEx( hKeyLicenseInfo, KeyName, 0, KEY_WRITE, &hKeyService );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// set Mode
|
|
lError = RegSetValueEx( hKeyService, REG_VALUE_MODE, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.Mode, sizeof( LocalServiceInfo->LocalServiceInfo0.Mode ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// set FlipAllow
|
|
lError = RegSetValueEx( hKeyService, REG_VALUE_FLIP, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.FlipAllow, sizeof( LocalServiceInfo->LocalServiceInfo0.FlipAllow ) );
|
|
|
|
if ( ERROR_SUCCESS == lError )
|
|
{
|
|
// set ConcurrentLimit
|
|
lError = RegSetValueEx( hKeyService, REG_VALUE_LIMIT, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.ConcurrentLimit, sizeof( LocalServiceInfo->LocalServiceInfo0.ConcurrentLimit ) );
|
|
}
|
|
}
|
|
|
|
RegCloseKey( hKeyService );
|
|
}
|
|
|
|
RegCloseKey( hKeyLicenseInfo );
|
|
}
|
|
|
|
switch ( lError )
|
|
{
|
|
case ERROR_SUCCESS:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_PATH_NOT_FOUND:
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
break;
|
|
default:
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
if ( STATUS_SUCCESS == Status )
|
|
{
|
|
LocalServiceListUpdate();
|
|
LocalServerServiceListUpdate();
|
|
ServiceListResynch();
|
|
}
|
|
}
|
|
|
|
if (NULL != LocalServiceInfo)
|
|
{
|
|
// note, some internal pointers are defined as dont_free, we should free them here
|
|
if (NULL != LocalServiceInfo->LocalServiceInfo0.KeyName)
|
|
{
|
|
MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.KeyName);
|
|
}
|
|
if (NULL != LocalServiceInfo->LocalServiceInfo0.DisplayName)
|
|
{
|
|
MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.DisplayName);
|
|
}
|
|
if (NULL != LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName)
|
|
{
|
|
MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName);
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceInfoSetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR KeyName,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOA LocalServiceInfo )
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoSetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(KeyName);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(LocalServiceInfo);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceInfoGetW(
|
|
LLS_HANDLE Handle,
|
|
LPWSTR KeyName,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOW * pLocalServiceInfo )
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsrLocalServiceInfoGetW\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
|
|
#if DELAY_INITIALIZATION
|
|
EnsureInitialized();
|
|
#endif
|
|
|
|
RtlAcquireResourceShared(&LocalServiceListLock, TRUE);
|
|
|
|
if (NULL == pLocalServiceInfo)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pLocalServiceInfo = NULL;
|
|
|
|
if ( 0 != Level )
|
|
{
|
|
Status = STATUS_INVALID_LEVEL;
|
|
}
|
|
else if ( NULL == KeyName )
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
PLOCAL_SERVICE_RECORD pRecord;
|
|
|
|
pRecord = LocalServiceListFind( KeyName );
|
|
|
|
if ( NULL == pRecord )
|
|
{
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
*pLocalServiceInfo = MIDL_user_allocate( sizeof( **pLocalServiceInfo ) );
|
|
|
|
if ( NULL == *pLocalServiceInfo )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.KeyName = pRecord->Name;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.DisplayName = pRecord->DisplayName;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.FamilyDisplayName = pRecord->FamilyDisplayName;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.Mode = pRecord->Mode;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.FlipAllow = pRecord->FlipAllow;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.ConcurrentLimit = pRecord->ConcurrentLimit;
|
|
(*pLocalServiceInfo)->LocalServiceInfo0.HighMark = pRecord->HighMark;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
void LlsrLocalServiceInfoGetW_notify_flag(
|
|
boolean fNotify
|
|
)
|
|
{
|
|
if (fNotify)
|
|
{
|
|
RtlReleaseResource(&LocalServiceListLock);
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
LlsrLocalServiceInfoGetA(
|
|
LLS_HANDLE Handle,
|
|
LPSTR KeyName,
|
|
DWORD Level,
|
|
PLLS_LOCAL_SERVICE_INFOA * pLocalServiceInfo )
|
|
{
|
|
#if DBG
|
|
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
|
|
dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoGetA\n"));
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(Handle);
|
|
UNREFERENCED_PARAMETER(KeyName);
|
|
UNREFERENCED_PARAMETER(Level);
|
|
|
|
if (NULL == pLocalServiceInfo)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pLocalServiceInfo = NULL;
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|