/*++ Copyright (c) 2000 Microsoft Corporation Module Name : tsnutl.c Abstract: Contains TS Notification DLL Utilities Author: TadB Revision History: --*/ #include #pragma hdrstop #include "tsnutl.h" #include "drdbg.h" // // For Tracing // extern DWORD GLOBAL_DEBUG_FLAGS; BOOL TSNUTL_IsProtocolRDP() /*++ Routine Description: Returns TRUE if the protocol is RDP for this Winstation Arguments: Return Value: TRUE if the protocol is RDP. --*/ { ULONG Length; BOOL bResult; WINSTATIONCLIENT ClientData; bResult = WinStationQueryInformation(SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationClient, &ClientData, sizeof(ClientData), &Length); if (bResult) { return ClientData.ProtocolType == PROTOCOL_RDP; } else { DBGMSG(DBG_ERROR, ("UMRDPPRN:WinStationQueryInformation returned false: %ld\n", GetLastError())); return FALSE; } } BOOL TSNUTL_FetchRegistryValue( IN HKEY regKey, IN LPWSTR regValueName, IN OUT PBYTE *buf ) /*++ Routine Description: Fetch a registry value. Arguments: regKey - Open reg key for value to fetch. regValueName - Name of registry value to fetch. buf - Location of fetched value. Return Value: TRUE if the value was successfully fetched. Otherwise, FALSE is returned and GetLastError returns the error code. --*/ { LONG sz; BOOL result = FALSE; LONG s; WCHAR tmp[1]; // // Get the size. // sz = 0; s = RegQueryValueEx(regKey, regValueName, NULL, NULL, (PBYTE)&tmp, &sz); // // Get the value. // if (s == ERROR_MORE_DATA) { // // Allocate the buf. // if (*buf != NULL) { PBYTE pTmp = REALLOCMEM(*buf, sz); if (pTmp != NULL) { *buf = pTmp; } else { FREEMEM(*buf); *buf = NULL; } } else { *buf = ALLOCMEM(sz); } // // Fetch the value. // if (*buf) { s = RegQueryValueEx( regKey, regValueName, NULL, NULL, *buf, &sz ); if (s != ERROR_SUCCESS) { DBGMSG(DBG_ERROR, ("TSNUTL: Can't fetch resource %s: %ld.\n", regValueName, GetLastError())); FREEMEM(*buf); *buf = NULL; } else { result = TRUE; } } else { DBGMSG(DBG_ERROR, ("TSNUTL: Can't allocate %ld bytes\n", sz)); } } return result; } BOOL TSNUTL_GetTextualSid( IN PSID pSid, IN OUT LPTSTR textualSid, IN OUT LPDWORD pSidSize ) /*++ Routine Description: Get a textual representation of a user SID. Arguments: pSid - Binary SID textualSid - buffer for Textual representaion of Sid pSidSize - required/provided textualSid buffersize Return Value: TRUE if the conversion was successful. Otherwise, FALSE is returned. GetLastError() can be used for retrieving extended error information. --*/ { PSID_IDENTIFIER_AUTHORITY psia; DWORD dwSubAuthorities; DWORD dwCounter; DWORD sidCopySize; PUCHAR pCount; BOOL result; // // Test if Sid passed in is valid // result = IsValidSid(pSid); // // Obtain SidIdentifierAuthority // if (result) { psia = GetSidIdentifierAuthority(pSid); result = GetLastError() == ERROR_SUCCESS; } // // Obtain sidsubauthority count // if (result) { pCount = GetSidSubAuthorityCount(pSid); result = GetLastError() == ERROR_SUCCESS; if (result) { dwSubAuthorities = *pCount; } } // // Compute approximate buffer length // if (result) { #if DBG WCHAR buf[MAX_PATH]; wsprintf(buf, TEXT("%lu"), SID_REVISION); ASSERT(wcslen(buf) <= 15); #endif // 'S-' + SID_REVISION + identifierauthority- + subauthorities- + NULL sidCopySize = (2 + 15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); } // // Check provided buffer length. // If not large enough, indicate proper size and setlasterror // if (result) { if(*pSidSize < sidCopySize) { *pSidSize = sidCopySize; SetLastError(ERROR_INSUFFICIENT_BUFFER); result = FALSE; } } // // Prepare S-SID_REVISION- // if (result) { sidCopySize = wsprintf(textualSid, TEXT("S-%lu-"), SID_REVISION ); } // // Prepare SidIdentifierAuthority // if (result) { if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) { sidCopySize += wsprintf(textualSid + sidCopySize, TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), (USHORT)psia->Value[0], (USHORT)psia->Value[1], (USHORT)psia->Value[2], (USHORT)psia->Value[3], (USHORT)psia->Value[4], (USHORT)psia->Value[5]); } else { sidCopySize += wsprintf(textualSid + sidCopySize, TEXT("%lu"), (ULONG)(psia->Value[5] ) + (ULONG)(psia->Value[4] << 8) + (ULONG)(psia->Value[3] << 16) + (ULONG)(psia->Value[2] << 24) ); } } // // Loop through SidSubAuthorities // if (result) { for(dwCounter = 0 ; result && (dwCounter < dwSubAuthorities) ; dwCounter++) { PDWORD ptr = GetSidSubAuthority(pSid, dwCounter); result = GetLastError() == ERROR_SUCCESS; if (result) { sidCopySize += wsprintf(textualSid + sidCopySize, TEXT("-%lu"), *ptr); } } } // // Tell the caller how many chars we provided, not including NULL // if (result) { *pSidSize = sidCopySize; } return result; } PSID TSNUTL_GetUserSid( IN HANDLE hTokenForLoggedOnUser ) { /*++ Routine Description: Allocates memory for psid and returns the psid for the current user The caller should call FREEMEM to free the memory. Arguments: Access Token for the User Return Value: if successful, returns the PSID else, returns NULL --*/ TOKEN_USER * ptu = NULL; BOOL bResult; PSID psid = NULL; DWORD defaultSize = sizeof(TOKEN_USER); DWORD Size; DWORD dwResult; ptu = (TOKEN_USER *)ALLOCMEM(defaultSize); if (ptu == NULL) { goto Cleanup; } bResult = GetTokenInformation( hTokenForLoggedOnUser, // Handle to Token TokenUser, // Token Information Class ptu, // Buffer for Token Information defaultSize, // Size of Buffer &Size); // Return length if (bResult == FALSE) { dwResult = GetLastError(); if (dwResult == ERROR_INSUFFICIENT_BUFFER) { // //Allocate required memory // FREEMEM(ptu); ptu = (TOKEN_USER *)ALLOCMEM(Size); if (ptu == NULL) { goto Cleanup; } else { defaultSize = Size; bResult = GetTokenInformation( hTokenForLoggedOnUser, TokenUser, ptu, defaultSize, &Size); if (bResult == FALSE) { //Still failed DBGMSG(DBG_ERROR, ("UMRDPDR:GetTokenInformation Failed, Error: %ld\n", GetLastError())); goto Cleanup; } } } else { DBGMSG(DBG_ERROR, ("UMRDPDR:GetTokenInformation Failed, Error: %ld\n", dwResult)); goto Cleanup; } } Size = GetLengthSid(ptu->User.Sid); // // Allocate memory. This will be freed by the caller. // psid = (PSID) ALLOCMEM(Size); if (psid != NULL) { // Make sure the allocation succeeded if (!CopySid(Size, psid, ptu->User.Sid)) { DBGMSG(DBG_ERROR, ("UMRDPDR:CopySid Failed, Error: %ld\n", GetLastError())); FREEMEM(psid); psid = NULL; goto Cleanup; } } Cleanup: if (ptu != NULL) FREEMEM(ptu); return psid; } #ifdef ENABLETHISWHENITISUSED PSID TSNUTL_GetLogonSessionSid( IN HANDLE hTokenForLoggedOnUser ) { /*++ Routine Description: Get a SID for a logon session. Arguments: Access Token for the User Return Value: if successful, returns the PSID else, returns NULL and GetLastError() can be used to get the error code. --*/ TOKEN_GROUPS * ptg = NULL; BOOL bResult; PSID psid = NULL; DWORD i; DWORD defaultSize = sizeof(TOKEN_GROUPS); DWORD size; DWORD dwResult = ERROR_SUCCESS; ptg = (TOKEN_GROUPS *)ALLOCMEM(defaultSize); if (ptg == NULL) { goto CLEANUPANDEXIT; } bResult = GetTokenInformation( hTokenForLoggedOnUser, // Handle to Token TokenGroups, // Token Information Class ptg, // Buffer for Token Information defaultSize, // Size of Buffer &size); // Return length if (bResult == FALSE) { dwResult = GetLastError(); if (dwResult == ERROR_INSUFFICIENT_BUFFER) { // //Allocate required memory // FREEMEM(ptg); ptg = (TOKEN_GROUPS *)ALLOCMEM(size); if (ptg == NULL) { dwResult = ERROR_OUTOFMEMORY; goto CLEANUPANDEXIT; } else { defaultSize = size; bResult = GetTokenInformation( hTokenForLoggedOnUser, TokenGroups, ptg, defaultSize, &size); if (bResult == FALSE) { //Still failed dwResult = GetLastError(); DBGMSG(DBG_ERROR, ("UMRDPDR:GetTokenInformation Failed, Error: %ld\n", GetLastError())); goto CLEANUPANDEXIT; } } } else { DBGMSG(DBG_ERROR, ("UMRDPDR:GetTokenInformation Failed, Error: %ld\n", dwResult)); goto CLEANUPANDEXIT; } } // // Iterate through the groups until we find the session SID. // for (i=0; iGroupCount; i++) { if (ptg->Groups[i].Attributes & SE_GROUP_LOGON_ID) { size = GetLengthSid(ptg->Groups[i].Sid); psid = (PSID)ALLOCMEM(size); if (psid != NULL) { // Make sure the allocation succeeded CopySid(size, psid, ptg->Groups[i].Sid); } break; } } CLEANUPANDEXIT: if (ptg != NULL) { FREEMEM(ptg); } SetLastError(dwResult); return psid; } #endif