513 lines
9.5 KiB
C
513 lines
9.5 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rpcstub.c
|
|
|
|
Abstract:
|
|
|
|
License Logging Service client stubs.
|
|
|
|
Author:
|
|
|
|
Arthur Hanson (arth) 06-Dec-1994
|
|
|
|
Environment: User mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
|
|
#include <string.h>
|
|
#include <zwapi.h>
|
|
#include <llsconst.h>
|
|
|
|
#include <debug.h>
|
|
#include "lsapi_c.h"
|
|
|
|
|
|
// #define API_TRACE 1
|
|
|
|
BOOLEAN LLSUp = FALSE;
|
|
|
|
#define MAX_EXPECTED_SID_LENGTH 72
|
|
|
|
LPTSTR pszStringBinding = NULL;
|
|
RTL_CRITICAL_SECTION LPCInitLock;
|
|
|
|
static HANDLE LpcPortHandle = NULL;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSReInitLPC( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service connects to the LLS server and initializes the LPC port.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The call completed successfully.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status = STATUS_SUCCESS;
|
|
LPTSTR pszUuid = NULL;
|
|
LPTSTR pszProtocolSequence = NULL;
|
|
LPTSTR pszNetworkAddress = NULL;
|
|
LPTSTR pszEndpoint = NULL;
|
|
LPTSTR pszOptions = NULL;
|
|
|
|
pszProtocolSequence = TEXT("ncalrpc");
|
|
pszEndpoint = TEXT(LLS_LPC_ENDPOINT);
|
|
pszNetworkAddress = NULL;
|
|
|
|
if (LLSUp) {
|
|
LLSUp = FALSE;
|
|
|
|
if (pszStringBinding != NULL) {
|
|
Status = RpcStringFree(&pszStringBinding);
|
|
pszStringBinding = NULL;
|
|
}
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
if (lsapirpc_handle != NULL) {
|
|
Status = RpcBindingFree(&lsapirpc_handle);
|
|
}
|
|
|
|
lsapirpc_handle = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
// Compose a string binding
|
|
Status = RpcStringBindingComposeW(pszUuid,
|
|
pszProtocolSequence,
|
|
pszNetworkAddress,
|
|
pszEndpoint,
|
|
pszOptions,
|
|
&pszStringBinding);
|
|
}
|
|
except (TRUE) {
|
|
Status = RpcExceptionCode();
|
|
}
|
|
|
|
if(Status) {
|
|
#if DBG
|
|
dprintf(TEXT("NTLSAPI RpcStringBindingComposeW Failed: 0x%lX\n"), Status);
|
|
#endif
|
|
if (pszStringBinding != NULL) {
|
|
RpcStringFree(&pszStringBinding);
|
|
pszStringBinding = NULL;
|
|
}
|
|
return I_RpcMapWin32Status(Status);
|
|
}
|
|
|
|
// Bind using the created string binding...
|
|
try {
|
|
Status = RpcBindingFromStringBindingW(pszStringBinding, &lsapirpc_handle);
|
|
}
|
|
except (TRUE) {
|
|
Status = RpcExceptionCode();
|
|
}
|
|
|
|
if(Status) {
|
|
#if DBG
|
|
dprintf(TEXT("NTLSAPI RpcBindingFromStringBindingW Failed: 0x%lX\n"), Status);
|
|
#endif
|
|
// lsapirpc_handle = NULL;
|
|
|
|
if (pszStringBinding != NULL) {
|
|
RpcStringFree(&pszStringBinding);
|
|
pszStringBinding = NULL;
|
|
}
|
|
|
|
return I_RpcMapWin32Status(Status);
|
|
}
|
|
|
|
LLSUp = TRUE;
|
|
|
|
return I_RpcMapWin32Status(Status);
|
|
|
|
} // LLSReInitLPC
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSInitLPC( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service connects to the LLS server and initializes the LPC port.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The call completed successfully.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
|
|
status = RtlInitializeCriticalSection(&LPCInitLock);
|
|
|
|
lsapirpc_handle = NULL;
|
|
|
|
return status;
|
|
|
|
} // LLSInitLPC
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSCloseLPC( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This closes the LPC port connection to the service.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The call completed successfully.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status = STATUS_SUCCESS, Status2 = STATUS_SUCCESS;
|
|
|
|
RtlEnterCriticalSection(&LPCInitLock);
|
|
LLSUp = FALSE;
|
|
|
|
if (pszStringBinding != NULL) {
|
|
Status = RpcStringFree(&pszStringBinding);
|
|
pszStringBinding = NULL;
|
|
}
|
|
|
|
if (lsapirpc_handle != NULL) {
|
|
Status2 = RpcBindingFree(&lsapirpc_handle);
|
|
}
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
Status = Status2;
|
|
|
|
lsapirpc_handle = NULL;
|
|
|
|
RtlLeaveCriticalSection(&LPCInitLock);
|
|
return Status;
|
|
|
|
} // LLSCloseLPC
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSLicenseRequest2 (
|
|
IN LPWSTR ProductName,
|
|
IN LPWSTR Version,
|
|
IN ULONG DataType,
|
|
IN BOOLEAN IsAdmin,
|
|
IN PVOID Data,
|
|
OUT PHANDLE LicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Arguments:
|
|
|
|
ProductName -
|
|
|
|
Version -
|
|
|
|
DataType -
|
|
|
|
IsAdmin -
|
|
|
|
Data -
|
|
|
|
LicenseHandle -
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR ProductID[MAX_PRODUCT_NAME_LENGTH + MAX_VERSION_LENGTH + 2];
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOL Close = FALSE;
|
|
ULONG VersionIndex;
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
LICENSE_HANDLE RpcLicenseHandle;
|
|
|
|
BOOL bActuallyConnect = TRUE;
|
|
|
|
//
|
|
// Get this out of the way in-case anything goes wrong
|
|
//
|
|
*LicenseHandle = NULL;
|
|
|
|
//
|
|
// If LicenseService isn't running (no LPC port) then just return
|
|
// dummy info - and let the user on.
|
|
//
|
|
RtlEnterCriticalSection(&LPCInitLock);
|
|
if (!LLSUp)
|
|
Status = LLSReInitLPC();
|
|
RtlLeaveCriticalSection(&LPCInitLock);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
return STATUS_SUCCESS;
|
|
|
|
if (((i = lstrlen(ProductName)) > MAX_PRODUCT_NAME_LENGTH) || (lstrlen(Version) > MAX_VERSION_LENGTH))
|
|
return STATUS_SUCCESS;
|
|
|
|
//
|
|
// Create productID - product name + version string.
|
|
//
|
|
lstrcpy(ProductID, ProductName);
|
|
lstrcat(ProductID, TEXT(" "));
|
|
lstrcat(ProductID, Version);
|
|
|
|
VersionIndex = i;
|
|
|
|
//
|
|
// Based on DataType figure out if we are doing a name or a SID
|
|
// and copy the data appropriatly
|
|
//
|
|
if (DataType == NT_LS_USER_NAME) {
|
|
Size = lstrlen((LPWSTR) Data);
|
|
if (Size > MAX_USER_NAME_LENGTH)
|
|
return STATUS_SUCCESS;
|
|
|
|
Size = (Size + 1) * sizeof(TCHAR);
|
|
}
|
|
|
|
if (DataType == NT_LS_USER_SID) {
|
|
//
|
|
// Friggin SID, so need to copy it manually.
|
|
// WARNING: This makes it dependent on the structure of the
|
|
// SID!!!
|
|
//
|
|
Size = RtlLengthSid( (PSID) Data);
|
|
|
|
if (Size > MAX_EXPECTED_SID_LENGTH)
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Call the Server.
|
|
//
|
|
try {
|
|
Status = LlsrLicenseRequestW(
|
|
&RpcLicenseHandle,
|
|
ProductID,
|
|
VersionIndex,
|
|
IsAdmin,
|
|
DataType,
|
|
Size,
|
|
(PBYTE) Data );
|
|
}
|
|
except (TRUE) {
|
|
#if DBG
|
|
Status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
if (Status != RPC_NT_SERVER_UNAVAILABLE) {
|
|
dprintf(TEXT("ERROR NTLSAPI.DLL: RPC Exception: 0x%lX\n"), Status);
|
|
// ASSERT(FALSE);
|
|
}
|
|
#endif
|
|
*LicenseHandle = NULL;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
bActuallyConnect = FALSE;
|
|
}
|
|
|
|
if (Close)
|
|
LLSCloseLPC();
|
|
|
|
// This is really a ULONG, we just treated it as a PVOID so
|
|
// RPC would treat is as a context handle
|
|
|
|
if(bActuallyConnect == TRUE)
|
|
*LicenseHandle = RpcLicenseHandle;
|
|
|
|
return Status;
|
|
|
|
} // LLSLicenseRequest
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSLicenseRequest (
|
|
IN LPWSTR ProductName,
|
|
IN LPWSTR Version,
|
|
IN ULONG DataType,
|
|
IN BOOLEAN IsAdmin,
|
|
IN PVOID Data,
|
|
OUT PULONG LicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Arguments:
|
|
|
|
ProductName -
|
|
|
|
Version -
|
|
|
|
DataType -
|
|
|
|
IsAdmin -
|
|
|
|
Data -
|
|
|
|
LicenseHandle -
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
--*/
|
|
{
|
|
HANDLE RealLicenseHandle;
|
|
NTSTATUS status;
|
|
|
|
if (sizeof(ULONG) == sizeof(HANDLE))
|
|
{
|
|
// Should still work on Win32
|
|
|
|
status = LLSLicenseRequest2(ProductName,Version,DataType,IsAdmin,Data,&RealLicenseHandle);
|
|
|
|
if (NULL != LicenseHandle)
|
|
*LicenseHandle = PtrToUlong(RealLicenseHandle);
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
if (NULL != LicenseHandle)
|
|
*LicenseHandle = (ULONG) 0xFFFFFFFF;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSLicenseFree2 (
|
|
IN HANDLE LicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Arguments:
|
|
|
|
LicenseHandle -
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Close = FALSE;
|
|
NTSTATUS Status;
|
|
LICENSE_HANDLE RpcLicenseHandle = (LICENSE_HANDLE) LicenseHandle;
|
|
|
|
//
|
|
// If LicenseService isn't running (no LPC port) then just return
|
|
// dummy info - and let the user on.
|
|
//
|
|
if (!LLSUp)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Call the Server.
|
|
//
|
|
try {
|
|
Status = LlsrLicenseFree( &RpcLicenseHandle );
|
|
}
|
|
except (TRUE) {
|
|
#if DBG
|
|
Status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
if (Status != RPC_NT_SERVER_UNAVAILABLE) {
|
|
dprintf(TEXT("ERROR NTLSAPI.DLL: RPC Exception: 0x%lX\n"), Status);
|
|
// ASSERT(FALSE);
|
|
}
|
|
#endif
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (Close)
|
|
LLSCloseLPC();
|
|
|
|
return Status;
|
|
} // LLSLicenseFree
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
NTSTATUS
|
|
LLSLicenseFree (
|
|
IN ULONG LicenseHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Arguments:
|
|
|
|
LicenseHandle -
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
|
|
--*/
|
|
{
|
|
if (sizeof(ULONG) == sizeof(HANDLE))
|
|
{
|
|
// Should still work on Win32
|
|
return LLSLicenseFree2(ULongToPtr(LicenseHandle));
|
|
}
|
|
else
|
|
{
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|