/* * LsCore.c * * Author: BreenH * * Client side functions to call the licensing core RPC interface. */ /* * Includes */ #include #include #include #include #include #include #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); }