Windows2003-3790/termsrv/winsta/client/lscore.c
2020-09-30 16:53:55 +02:00

830 lines
17 KiB
C

/*
* LsCore.c
*
* Author: BreenH
*
* Client side functions to call the licensing core RPC interface.
*/
/*
* Includes
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsta.h>
#include <license.h>
#include "lcrpc.h"
#include "rpcwire.h"
/*
* External Globals and Function Prototypes
*/
extern RTL_CRITICAL_SECTION WstHandleLock;
extern LPWSTR pszOptions;
extern LPWSTR pszProtocolSequence;
extern LPWSTR pszRemoteProtocolSequence;
RPC_STATUS
RpcWinStationBind(
LPWSTR pszUuid,
LPWSTR pszProtocolSequence,
LPWSTR pszNetworkAddress,
LPWSTR pszEndPoint,
LPWSTR pszOptions,
RPC_BINDING_HANDLE *pHandle
);
/*
* Internal Function Prototypes
*/
BOOLEAN
ConvertAnsiToUnicode(
LPWSTR *ppUnicodeString,
LPSTR pAnsiString
);
BOOLEAN
ConvertUnicodeToAnsi(
LPSTR *ppAnsiString,
LPWSTR pUnicodeString
);
BOOLEAN
ConvertPolicyInformationA2U(
LPLCPOLICYINFOGENERIC *ppPolicyInfoW,
LPLCPOLICYINFOGENERIC pPolicyInfoA
);
BOOLEAN
ConvertPolicyInformationU2A(
LPLCPOLICYINFOGENERIC *ppPolicyInfoA,
LPLCPOLICYINFOGENERIC pPolicyInfoW
);
BOOLEAN
LcRpcBindLocal(
VOID
);
/*
* Macros borrowed from winsta.c. RPC_HANDLE_NO_SERVER is not supported
* for the license core RPC calls. This means that no license core RPC call
* to the local machine will differentiate between "not a TS box" and "server
* not available".
*/
#define CheckLoaderLock() \
ASSERT(NtCurrentTeb()->ClientId.UniqueThread != \
((PRTL_CRITICAL_SECTION)(NtCurrentPeb()->LoaderLock))->OwningThread);
#define HANDLE_CURRENT_BINDING(hServer) \
CheckLoaderLock(); \
if (hServer == SERVERNAME_CURRENT) \
{ \
if (LCRPC_IfHandle == NULL) \
{ \
if (!LcRpcBindLocal()) \
{ \
return(FALSE); \
} \
} \
hServer = LCRPC_IfHandle; \
}
/*
* Function Implementations
*/
BOOLEAN
ConvertAnsiToUnicode(
LPWSTR *ppUnicodeString,
LPSTR pAnsiString
)
{
BOOLEAN fRet;
NTSTATUS Status;
ULONG cbAnsiString;
ULONG cbBytesWritten;
ULONG cbUnicodeString;
ASSERT(ppUnicodeString != NULL);
ASSERT(pAnsiString != NULL);
cbAnsiString = lstrlenA(pAnsiString);
Status = RtlMultiByteToUnicodeSize(
&cbUnicodeString,
pAnsiString,
cbAnsiString
);
if (Status == STATUS_SUCCESS)
{
cbUnicodeString += sizeof(WCHAR);
*ppUnicodeString = (LPWSTR)LocalAlloc(LPTR, cbUnicodeString);
if (*ppUnicodeString != NULL)
{
Status = RtlMultiByteToUnicodeN(
*ppUnicodeString,
cbUnicodeString,
&cbBytesWritten,
pAnsiString,
cbAnsiString
);
if (Status == STATUS_SUCCESS)
{
fRet = TRUE;
}
else
{
LocalFree(*ppUnicodeString);
*ppUnicodeString = NULL;
SetLastError(RtlNtStatusToDosError(Status));
fRet = FALSE;
}
}
else
{
SetLastError(ERROR_OUTOFMEMORY);
fRet = FALSE;
}
}
else
{
SetLastError(RtlNtStatusToDosError(Status));
fRet = FALSE;
}
return(fRet);
}
BOOLEAN
ConvertUnicodeToAnsi(
LPSTR *ppAnsiString,
LPWSTR pUnicodeString
)
{
BOOLEAN fRet;
NTSTATUS Status;
ULONG cbAnsiString;
ULONG cbBytesWritten;
ULONG cbUnicodeString;
ASSERT(ppAnsiString != NULL);
ASSERT(pUnicodeString != NULL);
cbUnicodeString = lstrlenW(pUnicodeString) * sizeof(WCHAR);
Status = RtlUnicodeToMultiByteSize(
&cbAnsiString,
pUnicodeString,
cbUnicodeString
);
if (Status == STATUS_SUCCESS)
{
cbAnsiString += sizeof(CHAR);
*ppAnsiString = (LPSTR)LocalAlloc(LPTR, cbAnsiString);
if (*ppAnsiString != NULL)
{
Status = RtlUnicodeToMultiByteN(
*ppAnsiString,
cbAnsiString,
&cbBytesWritten,
pUnicodeString,
cbUnicodeString
);
if (Status == STATUS_SUCCESS)
{
fRet = TRUE;
}
else
{
LocalFree(*ppAnsiString);
*ppAnsiString = NULL;
SetLastError(RtlNtStatusToDosError(Status));
fRet = FALSE;
}
}
else
{
SetLastError(ERROR_OUTOFMEMORY);
fRet = FALSE;
}
}
else
{
SetLastError(RtlNtStatusToDosError(Status));
fRet = FALSE;
}
return(fRet);
}
BOOLEAN
ConvertPolicyInformationA2U(
LPLCPOLICYINFOGENERIC *ppPolicyInfoW,
LPLCPOLICYINFOGENERIC pPolicyInfoA
)
{
BOOLEAN fRet;
ASSERT(ppPolicyInfoW != NULL);
ASSERT(pPolicyInfoA != NULL);
if (pPolicyInfoA->ulVersion == LCPOLICYINFOTYPE_V1)
{
LPLCPOLICYINFO_V1W *ppPolicyInfoV1W;
LPLCPOLICYINFO_V1A pPolicyInfoV1A;
ppPolicyInfoV1W = (LPLCPOLICYINFO_V1W*)ppPolicyInfoW;
pPolicyInfoV1A = (LPLCPOLICYINFO_V1A)pPolicyInfoA;
*ppPolicyInfoV1W = LocalAlloc(LPTR, sizeof(LPLCPOLICYINFO_V1W));
if (*ppPolicyInfoV1W != NULL)
{
(*ppPolicyInfoV1W)->ulVersion = LCPOLICYINFOTYPE_V1;
fRet = ConvertAnsiToUnicode(
&((*ppPolicyInfoV1W)->lpPolicyName),
pPolicyInfoV1A->lpPolicyName
);
if (fRet)
{
fRet = ConvertAnsiToUnicode(
&((*ppPolicyInfoV1W)->lpPolicyDescription),
pPolicyInfoV1A->lpPolicyDescription
);
}
if (fRet)
{
goto exit;
}
if ((*ppPolicyInfoV1W)->lpPolicyName != NULL)
{
LocalFree((*ppPolicyInfoV1W)->lpPolicyName);
}
if ((*ppPolicyInfoV1W)->lpPolicyDescription != NULL)
{
LocalFree((*ppPolicyInfoV1W)->lpPolicyDescription);
}
LocalFree(*ppPolicyInfoV1W);
*ppPolicyInfoV1W = NULL;
}
else
{
SetLastError(ERROR_OUTOFMEMORY);
fRet = FALSE;
}
}
else
{
SetLastError(ERROR_UNKNOWN_REVISION);
fRet = FALSE;
}
exit:
return(fRet);
}
BOOLEAN
ConvertPolicyInformationU2A(
LPLCPOLICYINFOGENERIC *ppPolicyInfoA,
LPLCPOLICYINFOGENERIC pPolicyInfoW
)
{
BOOLEAN fRet;
ASSERT(ppPolicyInfoA != NULL);
ASSERT(pPolicyInfoW != NULL);
if (pPolicyInfoW->ulVersion == LCPOLICYINFOTYPE_V1)
{
LPLCPOLICYINFO_V1A *ppPolicyInfoV1A;
LPLCPOLICYINFO_V1W pPolicyInfoV1W;
ppPolicyInfoV1A = (LPLCPOLICYINFO_V1A*)ppPolicyInfoA;
pPolicyInfoV1W = (LPLCPOLICYINFO_V1W)pPolicyInfoW;
*ppPolicyInfoV1A = LocalAlloc(LPTR, sizeof(LPLCPOLICYINFO_V1W));
if (*ppPolicyInfoV1A != NULL)
{
(*ppPolicyInfoV1A)->ulVersion = LCPOLICYINFOTYPE_V1;
fRet = ConvertUnicodeToAnsi(
&((*ppPolicyInfoV1A)->lpPolicyName),
pPolicyInfoV1W->lpPolicyName
);
if (fRet)
{
fRet = ConvertUnicodeToAnsi(
&((*ppPolicyInfoV1A)->lpPolicyDescription),
pPolicyInfoV1W->lpPolicyDescription
);
}
if (fRet)
{
goto exit;
}
if ((*ppPolicyInfoV1A)->lpPolicyName != NULL)
{
LocalFree((*ppPolicyInfoV1A)->lpPolicyName);
}
if ((*ppPolicyInfoV1A)->lpPolicyDescription != NULL)
{
LocalFree((*ppPolicyInfoV1A)->lpPolicyDescription);
}
LocalFree(*ppPolicyInfoV1A);
*ppPolicyInfoV1A = NULL;
}
else
{
SetLastError(ERROR_OUTOFMEMORY);
fRet = FALSE;
}
}
else
{
SetLastError(ERROR_UNKNOWN_REVISION);
fRet = FALSE;
}
exit:
return(fRet);
}
BOOLEAN
LcRpcBindLocal(
VOID
)
{
//
// Borrow the TSRPC handle critical section.
//
RtlEnterCriticalSection(&WstHandleLock);
if (LCRPC_IfHandle == NULL)
{
LCRPC_IfHandle = ServerLicensingOpenW(NULL);
if (LCRPC_IfHandle == NULL)
{
SetLastError(RPC_S_INVALID_BINDING);
RtlLeaveCriticalSection(&WstHandleLock);
return(FALSE);
}
}
RtlLeaveCriticalSection(&WstHandleLock);
return(TRUE);
}
HANDLE WINAPI
ServerLicensingOpenW(
LPWSTR pServerName
)
{
BOOLEAN fRet;
HANDLE hServer;
NTSTATUS Status;
RPC_STATUS RpcStatus;
RPC_BINDING_HANDLE RpcHandle;
if (pServerName == NULL)
{
if (!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)))
{
return(NULL);
}
RpcStatus = RpcWinStationBind(
LC_RPC_UUID,
pszProtocolSequence,
NULL,
LC_RPC_LRPC_EP,
pszOptions,
&RpcHandle
);
}
else
{
SetLastError(RPC_S_SERVER_UNAVAILABLE);
return(NULL);
}
if (RpcStatus != RPC_S_OK)
{
SetLastError(RPC_S_SERVER_UNAVAILABLE);
RpcBindingFree(&RpcHandle);
return(NULL);
}
__try
{
hServer = NULL;
fRet = RpcLicensingOpenServer(RpcHandle, &hServer, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
RpcBindingFree(&RpcHandle);
return(fRet ? hServer : NULL);
}
HANDLE WINAPI
ServerLicensingOpenA(
LPSTR pServerName
)
{
BOOLEAN fRet;
HANDLE hServer;
ULONG cchServerName;
if (pServerName == NULL)
{
return(ServerLicensingOpenW(NULL));
}
else
{
hServer = NULL;
SetLastError(RPC_S_SERVER_UNAVAILABLE);
}
return(hServer);
}
VOID WINAPI
ServerLicensingClose(
HANDLE hServer
)
{
//
// Don't try to close the define for the local server, and don't allow
// the auto-binding handle to be closed.
//
if ((hServer == SERVERNAME_CURRENT) || (hServer == LCRPC_IfHandle))
{
return;
}
__try
{
RpcLicensingCloseServer(&hServer);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
BOOLEAN WINAPI
ServerLicensingLoadPolicy(
HANDLE hServer,
ULONG ulPolicyId
)
{
BOOLEAN fRet;
NTSTATUS Status;
HANDLE_CURRENT_BINDING(hServer);
__try
{
fRet = RpcLicensingLoadPolicy(hServer, ulPolicyId, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
return(fRet);
}
BOOLEAN WINAPI
ServerLicensingUnloadPolicy(
HANDLE hServer,
ULONG ulPolicyId
)
{
BOOLEAN fRet;
NTSTATUS Status;
HANDLE_CURRENT_BINDING(hServer);
__try
{
fRet = RpcLicensingUnloadPolicy(hServer, ulPolicyId, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
return(fRet);
}
DWORD WINAPI
ServerLicensingSetPolicy(
HANDLE hServer,
ULONG ulPolicyId,
LPDWORD lpNewPolicyStatus
)
{
BOOLEAN fRet;
DWORD dwRet;
NTSTATUS Status;
NTSTATUS NewPolicyStatus;
HANDLE_CURRENT_BINDING(hServer);
if (lpNewPolicyStatus == NULL)
{
return(ERROR_INVALID_PARAMETER);
}
__try
{
Status = RpcLicensingSetPolicy(hServer, ulPolicyId, &NewPolicyStatus);
dwRet = RtlNtStatusToDosError(Status);
*lpNewPolicyStatus = RtlNtStatusToDosError(NewPolicyStatus);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dwRet = GetExceptionCode();
*lpNewPolicyStatus = ERROR_SUCCESS;
}
return(dwRet);
}
BOOLEAN WINAPI
ServerLicensingGetAvailablePolicyIds(
HANDLE hServer,
PULONG *ppulPolicyIds,
PULONG pcPolicies
)
{
BOOLEAN fRet;
NTSTATUS Status;
HANDLE_CURRENT_BINDING(hServer);
if ((ppulPolicyIds == NULL) || (pcPolicies == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
*pcPolicies = 0;
__try
{
fRet = RpcLicensingGetAvailablePolicyIds(hServer, ppulPolicyIds, pcPolicies, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
return(fRet);
}
BOOLEAN WINAPI
ServerLicensingGetPolicy(
HANDLE hServer,
PULONG pulPolicyId
)
{
BOOLEAN fRet;
NTSTATUS Status;
HANDLE_CURRENT_BINDING(hServer);
if (pulPolicyId == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
__try
{
fRet = RpcLicensingGetPolicy(hServer, pulPolicyId, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
return(fRet);
}
BOOLEAN WINAPI
ServerLicensingGetPolicyInformationW(
HANDLE hServer,
ULONG ulPolicyId,
PULONG pulVersion,
LPLCPOLICYINFOGENERIC *ppPolicyInfo
)
{
BOOLEAN fRet;
LPLCPOLICYINFOGENERIC pWire;
NTSTATUS Status;
ULONG cbPolicyInfo;
HANDLE_CURRENT_BINDING(hServer);
if ((ppPolicyInfo == NULL) || (pulVersion == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
*pulVersion = min(*pulVersion, LCPOLICYINFOTYPE_CURRENT);
pWire = NULL;
cbPolicyInfo = 0;
__try
{
fRet = RpcLicensingGetPolicyInformation(
hServer,
ulPolicyId,
pulVersion,
(PCHAR*)&pWire,
&cbPolicyInfo,
&Status
);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
if (fRet)
{
fRet = CopyPolicyInformationFromWire(ppPolicyInfo, pWire);
MIDL_user_free(pWire);
}
return(fRet);
}
BOOLEAN WINAPI
ServerLicensingGetPolicyInformationA(
HANDLE hServer,
ULONG ulPolicyId,
PULONG pulVersion,
LPLCPOLICYINFOGENERIC *ppPolicyInfo
)
{
BOOLEAN fRet;
LPLCPOLICYINFOGENERIC pPolicyInfoW;
NTSTATUS Status;
if (ppPolicyInfo == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
pPolicyInfoW = NULL;
fRet = ServerLicensingGetPolicyInformationW(
hServer,
ulPolicyId,
pulVersion,
&pPolicyInfoW
);
if (fRet)
{
fRet = ConvertPolicyInformationU2A(ppPolicyInfo, pPolicyInfoW);
ServerLicensingFreePolicyInformation(&pPolicyInfoW);
}
return(fRet);
}
VOID
ServerLicensingFreePolicyInformation(
LPLCPOLICYINFOGENERIC *ppPolicyInfo
)
{
if ((ppPolicyInfo != NULL) && (*ppPolicyInfo != NULL))
{
if ((*ppPolicyInfo)->ulVersion == LCPOLICYINFOTYPE_V1)
{
LPLCPOLICYINFO_V1 pPolicyInfoV1 = (LPLCPOLICYINFO_V1)(*ppPolicyInfo);
if (pPolicyInfoV1->lpPolicyName != NULL)
{
LocalFree(pPolicyInfoV1->lpPolicyName);
}
if (pPolicyInfoV1->lpPolicyDescription != NULL)
{
LocalFree(pPolicyInfoV1->lpPolicyDescription);
}
LocalFree(pPolicyInfoV1);
pPolicyInfoV1 = NULL;
}
}
}
BOOLEAN WINAPI
ServerLicensingDeactivateCurrentPolicy(
HANDLE hServer
)
{
BOOLEAN fRet;
NTSTATUS Status;
HANDLE_CURRENT_BINDING(hServer);
__try
{
fRet = RpcLicensingDeactivateCurrentPolicy(hServer, &Status);
if (!fRet)
{
SetLastError(RtlNtStatusToDosError(Status));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fRet = FALSE;
SetLastError(GetExceptionCode());
}
return(fRet);
}