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.
500 lines
12 KiB
500 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
tsnutl.c
|
|
|
|
Abstract:
|
|
|
|
Contains TS Notification DLL Utilities
|
|
|
|
Author:
|
|
|
|
TadB
|
|
|
|
Revision History:
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#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; i<ptg->GroupCount; 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
|
|
|
|
|
|
|