Home Site Map Search Contact Us About Us About Us
Copyright © 2000
C++ Security

/***********************************************************************
 *       File : SecurityGate.cpp
 *
 *    Purpose : User and group security related functions with or 
 *              without MTS.
 *
 *   Revision : 1.0.0  08/03/1998  James Bischoff
 *              Initial release
 ***********************************************************************/

// SecurityGate.cpp : Implementation of CSecurityGate
#include "stdafx.h"
#include "SecurityObject.h"
#include "SecurityGate.h"

#include <ole2.h>
#include <stdio.h>
#include <mtx.h>
#include <lm.h>
#include <lmaccess.h>

#define MAXOUTPUTSTRINGLENGTH 1000
#define MAX_NAME 256
#define MAX_GROUPS 256

int TRACE = 0;

LPVOID AllocateTokenInfoBuffer( 
    HANDLE hToken, 
    TOKEN_INFORMATION_CLASS InfoClass, 
    DWORD *dwSize) 
{ 
    BOOL bRes; 
 
    *dwSize=0; 
    // 
    // Determine size of buffer needed 
    // 
 
    bRes = GetTokenInformation( 
        	hToken, 
        	InfoClass, 
        	NULL, 
        	*dwSize, 
		dwSize); 

    // 
    // Allocate a buffer for our token data 
    // 
    return(LocalAlloc(LPTR,*dwSize)); 
 
} 

BOOL FormatLastError(
	DWORD dwLastError, 
	LPSTR szOutputBuffer, 
	DWORD dwSizeofOutputBuffer) 	
{     
	DWORD dwRetFM;
	DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;  

	dwRetFM = FormatMessage(         
			dwFlags, 
			NULL, 
			dwLastError, 
			MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 
			szOutputBuffer, 
			dwSizeofOutputBuffer,         
			NULL); 
	
	// Get rid of the CR/LF for VB
	szOutputBuffer[dwRetFM - 2] = '\0';

	if (dwRetFM)  
		return TRUE; 
	else
		return FALSE;
} 

BOOL GetUser(VARIANT *vDomain, VARIANT *vUser, VARIANT *vErrorMessage)
{

	// MTS
	IObjectContext* pIObjectContext = NULL;
	ISecurityProperty* pISecurityProperty = NULL;
	PSID pSid = NULL;

	// Misc
	DWORD dwSize;
	BOOL  bRes; 
	DWORD dwResult; 
	SID_NAME_USE SidType; 
	HRESULT hr;
	LPWSTR wcpTemp;

	// Handles
	HANDLE hProcess;
	HANDLE hToken; 
	
	// Various buffers
    	TOKEN_USER *pUserInfo; 
    	char lpName[MAX_NAME];     
	char lpDomain[MAX_NAME]; 
	char lpMessage[MAXOUTPUTSTRINGLENGTH * 2];
	char lpErrorMessage[MAXOUTPUTSTRINGLENGTH];

	// Set up variant parameters
	VariantClear(vDomain);
	vDomain->vt = VT_BSTR;
	VariantClear(vUser);
	vUser->vt = VT_BSTR;
	VariantClear(vErrorMessage);
	vErrorMessage->vt = VT_BSTR;
	BAY_AnsiToUnicode("",&wcpTemp);
	vErrorMessage->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	///////////////////////////////////////////////////////////////////
	// Get MTS context object
	///////////////////////////////////////////////////////////////////
	hr = GetObjectContext(&pIObjectContext);
	switch (hr)
	{
		case CONTEXT_E_NOCONTEXT:

			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////
			// Not running under MTS
			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////

			if (TRACE > 0)
				OutputDebugString("Success: GetObjectContext - Not running under MTS\n");

			///////////////////////////////////////////////////////////////////
			// Get the current process token
			///////////////////////////////////////////////////////////////////
			hProcess = GetCurrentProcess(); 
			if (hProcess == NULL)
			{
				sprintf(lpMessage,"SecurityGate - Error: GetCurrentProcess");
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				return FALSE;
			}
			else
				if (TRACE > 0)
					OutputDebugString("SecurityGate - Success: GetCurrentProcess\n");

			///////////////////////////////////////////////////////////////////
			// Open the current process token
			///////////////////////////////////////////////////////////////////
		   	bRes = OpenProcessToken(	
				hProcess, 
				TOKEN_QUERY, 
				&hToken);
			if (!bRes)
			{
				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: OpenProcessToken - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				CloseHandle(hProcess);
				return FALSE;
			}
			else
				if (TRACE > 0)
					OutputDebugString("SecurityGate - Success: OpenProcessToken\n");

			///////////////////////////////////////////////////////////////////
			// Allocate token buffer
			///////////////////////////////////////////////////////////////////
			dwSize = 0;
		    	pUserInfo = (TOKEN_USER *)AllocateTokenInfoBuffer(
							hToken,
							 TokenUser,
							 &dwSize);  
			if (!pUserInfo)
			{
				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: AllocateTokenInfoBuffer - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				CloseHandle(hProcess);
				CloseHandle(hToken);
				return FALSE;
			}
			else
				if (TRACE > 0)			
					OutputDebugString("SecurityGate - Success: AllocateTokenInfoBuffer\n");

			///////////////////////////////////////////////////////////////////
			// Get user token information
			///////////////////////////////////////////////////////////////////
			bRes = GetTokenInformation(
				hToken,
				TokenUser,
				pUserInfo,
				dwSize,
				&dwSize);				
			if (!bRes)      
			{
				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: GetTokenInformation - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				LocalFree(pUserInfo);			
				CloseHandle(hProcess);
				CloseHandle(hToken);
				return FALSE;
			}
			else
				if (TRACE > 0)			
					OutputDebugString("SecurityGate - Success: GetTokenInformation\n");

			///////////////////////////////////////////////////////////////////
			// Get domain and user
			///////////////////////////////////////////////////////////////////
			dwSize = MAX_NAME;
			if( !LookupAccountSid( 
					NULL,                      // lookup on local system 
					pUserInfo->User.Sid, 
					lpName,                    // buffer to receive name         
					&dwSize, 
					lpDomain,
					&dwSize,
					&SidType) )     
			{ 
			dwResult = GetLastError(); 
		        if( dwResult == ERROR_NONE_MAPPED ) 
				{
				    strcpy( lpName, "NONE_MAPPED" );          
					if (TRACE > 0)			
						OutputDebugString("SecurityGate - Success: LookupAccountSid - NONE_MAPPED\n");
				}
				else          
				{ 
					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: LookupAccountSid - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					LocalFree(pUserInfo);			
					CloseHandle(hProcess);
					CloseHandle(hToken);
					return FALSE;
				}     
			}  
			else
				if (TRACE > 0)			
					OutputDebugString("SecurityGate - Success: LookupAccountSid\n");

			///////////////////////////////////////////////////////////////////
			// Free up resources
			///////////////////////////////////////////////////////////////////
			LocalFree(pUserInfo);			
			CloseHandle(hProcess);
			CloseHandle(hToken);
			
			break;

			case S_OK:

			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////
			// Running under MTS
			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////
			if (TRACE > 0)
				OutputDebugString("SecurityGate - Success: GetObjectContext - Running under MTS\n");

			///////////////////////////////////////////////////////////////////
			// Get a reference to the ISecurityProperty interface.
			///////////////////////////////////////////////////////////////////
			pIObjectContext->QueryInterface(
								IID_ISecurityProperty,
								(void**)&pISecurityProperty);
			if (pISecurityProperty == NULL)
			{
				sprintf(lpMessage,"SecurityGate - Error: pIObjectContext->QueryInterface");
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				pIObjectContext->SetAbort();
				pIObjectContext->Release();
				return FALSE;
			}
			else
				if (TRACE > 0)
					OutputDebugString("SecurityGate - Success: pIObjectContext->QueryInterface\n");
		
			///////////////////////////////////////////////////////////////////
			// Obtain the original caller's security ID
			///////////////////////////////////////////////////////////////////
			hr = pISecurityProperty->GetOriginalCallerSID(&pSid);
			if (hr != S_OK)
			{
				sprintf(lpMessage,"SecurityGate - Error: pISecurityProperty->GetOriginalCallerSID");
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				pISecurityProperty->Release();
				pIObjectContext->SetAbort();
				pIObjectContext->Release();
				return FALSE;
			}
			else
				if (TRACE > 0)
					OutputDebugString("SecurityGate - Success: pISecurityProperty->GetOriginalCallerSID\n");

			///////////////////////////////////////////////////////////////////
			// Get domain and user
			///////////////////////////////////////////////////////////////////
			dwSize = MAX_NAME;
			if( !LookupAccountSid( 
					NULL,                      // lookup on local system 
					pSid,
					lpName,                    // buffer to recieve name         
					&dwSize, 
					lpDomain,
					&dwSize,
					&SidType) )     
			{ 
			dwResult = GetLastError(); 
		        if( dwResult == ERROR_NONE_MAPPED ) 
				{
				    strcpy( lpName, "NONE_MAPPED" );          
					if (TRACE > 0)			
						OutputDebugString("SecurityGate - Success: LookupAccountSid - NONE_MAPPED\n");
				}
				else          
				{ 
					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: LookupAccountSid - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					pISecurityProperty->ReleaseSID(pSid); 
					pISecurityProperty->Release();
					pIObjectContext->SetAbort();
					pIObjectContext->Release();
					return FALSE;
				}     
			}  
			else
				if (TRACE > 0)			
					OutputDebugString("SecurityGate - Success: LookupAccountSid\n");

			///////////////////////////////////////////////////////////////////
			// Free up resources
			///////////////////////////////////////////////////////////////////
			pISecurityProperty->ReleaseSID(pSid); 
			pISecurityProperty->Release();
			pIObjectContext->SetComplete();
			pIObjectContext->Release();

			break;

			default:

			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////
			// Unexpected error geting MTS context object
			///////////////////////////////////////////////////////////////////
			///////////////////////////////////////////////////////////////////

			sprintf(lpMessage,"SecurityGate - Error: GetObjectContext");
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}

			return FALSE;

			break;
	}

	if (TRACE > 0)
	{
		sprintf(lpMessage,"SecurityGate - Domain: %s\n", lpDomain);
	    	OutputDebugString(lpMessage);
	}
	BAY_AnsiToUnicode(lpDomain,&wcpTemp);
	vDomain->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	if (TRACE > 0)
	{
		sprintf(lpMessage,"SecurityGate - User: %s\n", lpName);
	    	OutputDebugString(lpMessage);
	}
	BAY_AnsiToUnicode(lpName,&wcpTemp);
	vUser->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Done\n");

	return TRUE;
}

BOOL ValidateUser(VARIANT vUserDomain, VARIANT vUserName, VARIANT vGroupDomain, VARIANT vGroupName, VARIANT *vValidated, VARIANT *vErrorMessage)
{

	LPSTR cpUserDomain = NULL;
	LPSTR cpUserName = NULL;
	LPSTR cpGroupDomain = NULL;
	LPSTR cpGroupName = NULL;
	LPSTR cpTemp = NULL;
	LPWSTR wcpTemp = NULL;
	char lpMessage[MAXOUTPUTSTRINGLENGTH * 2];
	char lpErrorMessage[MAXOUTPUTSTRINGLENGTH];
	char lpBuffer[MAXOUTPUTSTRINGLENGTH];
	LPWSTR wcpDomainController = NULL;
	BOOL bResult = TRUE;
	BOOL bUseFreeOnBuffer = FALSE;

	
	// Net API
	LPGROUP_USERS_INFO_0 pBuf = NULL;  
	DWORD dwLevel = 0; 
   	DWORD dwPrefMaxLen = 0xFFFFFFFF;    
	DWORD dwEntriesRead = 0; 
    	DWORD dwTotalEntries = 0;    
	NET_API_STATUS nStatus; 
	LPGROUP_USERS_INFO_0 pTmpBuf = NULL; 
	DWORD i;       
	DWORD dwTotalCount = 0;  
	LPLOCALGROUP_USERS_INFO_0 pLocalBuf = NULL;
	DWORD dwFlags = LG_INCLUDE_INDIRECT;
	LPLOCALGROUP_USERS_INFO_0 pTmpLocalBuf = NULL;

	// Set up variant parameters
	VariantClear(vValidated);
	vValidated->vt = VT_BOOL;
	vValidated->boolVal = FALSE;
	VariantClear(vErrorMessage);
	vErrorMessage->vt = VT_BSTR;
	BAY_AnsiToUnicode("",&wcpTemp);
	vErrorMessage->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	///////////////////////////////////////////////////////////////////
	// Convert parameters to strings
	///////////////////////////////////////////////////////////////////
	if ((vUserDomain.vt == VT_BSTR) && 
		(SysStringLen(vUserDomain.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserDomain.bstrVal,&cpUserDomain);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Domain: %s\n", cpUserDomain);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserDomain not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;

	}

	if ((vUserName.vt == VT_BSTR) && 
		(SysStringLen(vUserName.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserName.bstrVal,&cpUserName);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Name: %s\n", cpUserName);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserName not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;
	}

	if ((vGroupDomain.vt == VT_BSTR) && 
		(SysStringLen(vGroupDomain.bstrVal)))
		BAY_UnicodeToAnsi(vGroupDomain.bstrVal,&cpGroupDomain);
	else
		BAY_UnicodeToAnsi(vUserDomain.bstrVal,&cpGroupDomain);
	if (TRACE > 0)
	{
		sprintf(lpMessage, "SecurityGate - Group Domain: %s\n", cpGroupDomain);
		OutputDebugString(lpMessage);
	}

	if ((vGroupName.vt == VT_BSTR) && 
		(SysStringLen(vGroupName.bstrVal)))
	{
		BAY_UnicodeToAnsi(vGroupName.bstrVal,&cpGroupName);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - Group Name: %s\n", cpGroupName);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: GroupName not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;
	}

	if (strstr(cpGroupDomain, "\\\\") == NULL)
	{
		///////////////////////////////////////////////////////////////////
		// Get a domain controller for group's domain
		///////////////////////////////////////////////////////////////////
		BAY_AnsiToUnicode(cpGroupDomain, &wcpTemp);
		nStatus = NetGetDCName(
				NULL,
				wcpTemp,  
				(LPBYTE *) &wcpDomainController);
		CoTaskMemFree(wcpTemp);

		if (nStatus != NERR_Success)
		{
			switch (nStatus)
			{
				case NERR_DCNotFound:

					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain controller not found - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;

				case ERROR_INVALID_NAME:

					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain not found - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;

				default:
	
					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Unexpected error - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;
			}
		}		
		else
		{
			if (TRACE > 0)
			{
				BAY_UnicodeToAnsi(wcpDomainController,&cpTemp);
				sprintf(lpMessage, "SecurityGate - Success: NetGetDCName - Domain Controller [%s]\n", cpTemp);
				OutputDebugString(lpMessage);
				CoTaskMemFree(cpTemp);
			}
		}

	}
	else
	{
		BAY_AnsiToUnicode(cpGroupDomain, &wcpDomainController);
		bUseFreeOnBuffer = TRUE;

		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - Use Server [%s]\n", cpGroupDomain);
			OutputDebugString(lpMessage);
		}
	}


	if (_stricmp(cpUserDomain, cpGroupDomain) == 0)
	{

		///////////////////////////////////////////////////////////////////
		// Check user's global groups
		///////////////////////////////////////////////////////////////////
		nStatus = NetUserGetGroups(
				wcpDomainController,                               
				vUserName.bstrVal, 
				dwLevel, 
				(LPBYTE*) &pBuf, 
	                    	dwPrefMaxLen, 
		                &dwEntriesRead, 
			        &dwTotalEntries);     

		switch (nStatus)
		{
			case NERR_Success:

				if (TRACE > 0)
				{
					sprintf(lpMessage, "SecurityGate - Success: NetUserGetGroups\n");
					OutputDebugString(lpMessage);
				}

				if ((pTmpBuf = pBuf) != NULL)       
				{ 	
					for (i = 0; i < dwEntriesRead; i++)          
					{ 
						if (pTmpBuf == NULL) 
						{ 
							sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - An access violation has occurred");
							BAY_AnsiToUnicode(lpMessage,&wcpTemp);
							vErrorMessage->bstrVal = SysAllocString(wcpTemp);
							CoTaskMemFree(wcpTemp);
							if (TRACE > 0)
							{
								OutputDebugString(lpMessage);
								OutputDebugString("\n");
							}	
							break;             
						}  
						if (_wcsicmp(pTmpBuf->grui0_name, vGroupName.bstrVal) == 0)
							vValidated->boolVal = TRUE;

						if (TRACE > 0)
						{
							BAY_UnicodeToAnsi(pTmpBuf->grui0_name,&cpTemp);
							sprintf(lpMessage, "SecurityGate - User Global Group Name: %s\n", cpTemp);
							OutputDebugString(lpMessage);
							CoTaskMemFree(cpTemp);
						}

						pTmpBuf++; 
						dwTotalCount++;          
					}       
				} 
		  	
				break;

			case NERR_UserNotFound:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - User not found - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}	
				bResult = FALSE;
				goto Cleanup;

				break;

			case NERR_InvalidComputer:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Invalid server - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				return FALSE;

				break;

			case ERROR_ACCESS_DENIED:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Premission denied - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				break;

			default:
	
				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Unexpected error - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				break;
		}
	}

	///////////////////////////////////////////////////////////////////
	// Check user's local groups
	///////////////////////////////////////////////////////////////////

	strcpy(lpBuffer, cpUserDomain);
	strcat(lpBuffer, "\\");
	strcat(lpBuffer, cpUserName);
	BAY_AnsiToUnicode(lpBuffer, &wcpTemp);

	nStatus = NetUserGetLocalGroups(
			wcpDomainController,                               
			wcpTemp, 
                    	dwLevel, 
			dwFlags,
			(LPBYTE*) &pLocalBuf, 
                    	dwPrefMaxLen, 
                    	&dwEntriesRead, 
                    	&dwTotalEntries);     

	CoTaskMemFree(wcpTemp);

	switch (nStatus)
	{
		case NERR_Success:

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Success: NetUserGetLocalGroups\n");
				OutputDebugString(lpMessage);
			}

			if ((pTmpLocalBuf = pLocalBuf) != NULL)       
			{ 
	
				for (i = 0; i < dwEntriesRead; i++)          
				{ 
					if (pTmpLocalBuf == NULL) 
					{ 
						sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - An access violation has occurred");
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}	

						break;             
					}  
					if (_wcsicmp(pTmpLocalBuf->lgrui0_name, vGroupName.bstrVal) == 0)
						vValidated->boolVal = TRUE;

					if (TRACE > 0)
					{
						BAY_UnicodeToAnsi(pTmpLocalBuf->lgrui0_name,&cpTemp);
						sprintf(lpMessage, "SecurityGate - User Local Group Name: %s\n", cpTemp);
						OutputDebugString(lpMessage);
						CoTaskMemFree(cpTemp);
					}

					pTmpLocalBuf++; 
					dwTotalCount++;          
				}       
			} 
	  	
			break;

		case NERR_UserNotFound:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - User not found - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case NERR_InvalidComputer:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Invalid server - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case ERROR_ACCESS_DENIED:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Premission denied - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		default:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Unexpected error - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;
	}

	///////////////////////////////////////////////////////////////////
	// Free up resources
	///////////////////////////////////////////////////////////////////
	Cleanup:

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Cleanup\n");

	if (cpUserDomain != NULL) 
		CoTaskMemFree(cpUserDomain);

	if (cpUserName != NULL) 
		CoTaskMemFree(cpUserName);

	if (cpGroupDomain != NULL) 
		CoTaskMemFree(cpGroupDomain);

	if (cpGroupName != NULL) 
		CoTaskMemFree(cpGroupName);

	if (wcpDomainController != NULL)
		if (bUseFreeOnBuffer)
			CoTaskMemFree(wcpDomainController);
		else
     		NetApiBufferFree(wcpDomainController); 

	if (pLocalBuf != NULL)
		NetApiBufferFree(pLocalBuf); 

	if (pBuf != NULL)
		NetApiBufferFree(pBuf); 

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Done\n");

	return bResult;

}


BOOL GetUserGroups(VARIANT vUserDomain, VARIANT vUserName, VARIANT vGroupDomain, VARIANT *vGlobalGroups, VARIANT *vLocalGroups, VARIANT *vErrorMessage)
{

	LPSTR cpUserDomain = NULL;
	LPSTR cpUserName = NULL;
	LPSTR cpGroupDomain = NULL;
	LPSTR cpTemp = NULL;
	LPWSTR wcpTemp = NULL;
	char lpMessage[MAXOUTPUTSTRINGLENGTH * 2];
	char lpErrorMessage[MAXOUTPUTSTRINGLENGTH];
	char lpBuffer[MAXOUTPUTSTRINGLENGTH];
	LPWSTR wcpDomainController = NULL;
	BOOL bResult = TRUE;
	BOOL bUseFreeOnBuffer = FALSE;
	
	// Net API
	LPGROUP_USERS_INFO_0 pBuf = NULL;  
	DWORD dwLevel = 0; 
    	DWORD dwPrefMaxLen = 0xFFFFFFFF;    
	DWORD dwEntriesRead = 0; 
    	DWORD dwTotalEntries = 0;    
	NET_API_STATUS nStatus; 
	LPGROUP_USERS_INFO_0 pTmpBuf = NULL; 
	DWORD i;       
	DWORD dwTotalCount = 0;  
	LPLOCALGROUP_USERS_INFO_0 pLocalBuf = NULL;
	DWORD dwFlags = LG_INCLUDE_INDIRECT;
	LPLOCALGROUP_USERS_INFO_0 pTmpLocalBuf = NULL;

	// Safe Array
	SAFEARRAY FAR* psaGlobalGroups;
	SAFEARRAYBOUND rgsaGlobalGroups[1];
	long alGlobalGroups[1];
	SAFEARRAY FAR* psaLocalGroups;
	SAFEARRAYBOUND rgsaLocalGroups[1];
	long alLocalGroups[1];
	VARIANT *pvTemp;

	// Set up variant parameters
	VariantClear(vErrorMessage);
	vErrorMessage->vt = VT_BSTR;
	BAY_AnsiToUnicode("",&wcpTemp);
	vErrorMessage->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	///////////////////////////////////////////////////////////////////
	// Convert parameters to strings
	///////////////////////////////////////////////////////////////////
	if ((vUserDomain.vt == VT_BSTR) && 
		(SysStringLen(vUserDomain.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserDomain.bstrVal,&cpUserDomain);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Domain: %s\n", cpUserDomain);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserDomain not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;

	}

	if ((vUserName.vt == VT_BSTR) && 
		(SysStringLen(vUserName.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserName.bstrVal,&cpUserName);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Name: %s\n", cpUserName);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserName not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;
	}

	if ((vGroupDomain.vt == VT_BSTR) && 
		(SysStringLen(vGroupDomain.bstrVal)))
		BAY_UnicodeToAnsi(vGroupDomain.bstrVal,&cpGroupDomain);
	else
		BAY_UnicodeToAnsi(vUserDomain.bstrVal,&cpGroupDomain);
	if (TRACE > 0)
	{
		sprintf(lpMessage, "SecurityGate - Group Domain: %s\n", cpGroupDomain);
		OutputDebugString(lpMessage);
	}


	if (strstr(cpUserDomain, "\\\\") == NULL)
	{
	
		///////////////////////////////////////////////////////////////////
		// Get a domain controller for users's domain
		///////////////////////////////////////////////////////////////////
		BAY_AnsiToUnicode(cpUserDomain, &wcpTemp);
		nStatus = NetGetDCName(
						NULL,
						wcpTemp,  
						(LPBYTE *) &wcpDomainController);
		CoTaskMemFree(wcpTemp);

		if (nStatus != NERR_Success)
		{
			switch (nStatus)
			{
				case NERR_DCNotFound:

					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain controller not found - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;

				case ERROR_INVALID_NAME:

					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain not found - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;

				default:

					FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
					sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Unexpected error - %s", lpErrorMessage);
					BAY_AnsiToUnicode(lpMessage,&wcpTemp);
					vErrorMessage->bstrVal = SysAllocString(wcpTemp);
					CoTaskMemFree(wcpTemp);
					if (TRACE > 0)
					{
						OutputDebugString(lpMessage);
						OutputDebugString("\n");
					}
					bResult = FALSE;
					goto Cleanup;

					break;
			}
		}
		else
		{
			if (TRACE > 0)
			{
				BAY_UnicodeToAnsi(wcpDomainController,&cpTemp);
				sprintf(lpMessage, "SecurityGate - Success: NetGetDCName - Domain Controller [%s]\n", cpTemp);
				OutputDebugString(lpMessage);
				CoTaskMemFree(cpTemp);
			}
		}
	}
	else
	{
		BAY_AnsiToUnicode(cpUserDomain, &wcpDomainController);
		bUseFreeOnBuffer = TRUE;

		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - Use Server [%s]\n", cpGroupDomain);
			OutputDebugString(lpMessage);
		}

	}

	///////////////////////////////////////////////////////////////////
	// Check user's global groups
	///////////////////////////////////////////////////////////////////
	nStatus = NetUserGetGroups(
			wcpDomainController,                               
			vUserName.bstrVal, 
			dwLevel, 
			(LPBYTE*) &pBuf, 
                    	dwPrefMaxLen, 
	                &dwEntriesRead, 
		        &dwTotalEntries);     

	switch (nStatus)
	{
		case NERR_Success:

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Success: NetUserGetGroups\n");
				OutputDebugString(lpMessage);
			}

			// Create the safearray
			VariantClear(vGlobalGroups);
			vGlobalGroups->vt = VT_ARRAY | VT_VARIANT;
			rgsaGlobalGroups[0].lLbound = 0;
			rgsaGlobalGroups[0].cElements = dwEntriesRead;
			psaGlobalGroups = SafeArrayCreate(VT_VARIANT, 1, rgsaGlobalGroups);
			if(psaGlobalGroups == NULL)
			{
				bResult = FALSE;
				goto Cleanup;
			}
			vGlobalGroups->parray = psaGlobalGroups;

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Success: SafeArrayCreate\n");
				OutputDebugString(lpMessage);
			}

			if ((pTmpBuf = pBuf) != NULL)       
			{ 	
				for (i = 0; i < dwEntriesRead; i++)          
				{ 
					if (pTmpBuf == NULL) 
					{ 
						sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - An access violation has occurred");
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}	
						break;             
					}  

					if (TRACE > 0)
					{
						BAY_UnicodeToAnsi(pTmpBuf->grui0_name,&cpTemp);
						sprintf(lpMessage, "SecurityGate - User Global Group Name: %s\n", cpTemp);
						OutputDebugString(lpMessage);
						CoTaskMemFree(cpTemp);
					}

					pvTemp = new VARIANT;
					if (pvTemp)
					{
						VariantInit(pvTemp);
						pvTemp->vt = VT_BSTR;
						pvTemp->bstrVal = SysAllocString(pTmpBuf->grui0_name);
						alGlobalGroups[0] = (long) i;
						SafeArrayPutElement(psaGlobalGroups, alGlobalGroups, pvTemp);
						VariantClear(pvTemp);
						delete pvTemp;
					}
					
					pTmpBuf++; 
					dwTotalCount++;          
				}       
			} 
		  	
			break;

		case NERR_UserNotFound:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - User not found - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}	
			bResult = FALSE;
			goto Cleanup;

			break;

		case NERR_InvalidComputer:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Invalid server - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			return FALSE;

			break;

		case ERROR_ACCESS_DENIED:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Premission denied - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		default:
	
			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetGroups - Unexpected error - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;
	}

	if (_stricmp(cpUserDomain, cpGroupDomain) != 0)
	{


		if (wcpDomainController != NULL)
			if (bUseFreeOnBuffer)
				CoTaskMemFree(wcpDomainController);
			else
		 		NetApiBufferFree(wcpDomainController); 
		wcpDomainController = NULL;

		if (strstr(cpGroupDomain, "\\\\") == NULL)
		{
			///////////////////////////////////////////////////////////////////
			// Get a domain controller for group's domain
			///////////////////////////////////////////////////////////////////
			BAY_AnsiToUnicode(cpGroupDomain, &wcpTemp);
			nStatus = NetGetDCName(
							NULL,
							wcpTemp,  
							(LPBYTE *) &wcpDomainController);
			CoTaskMemFree(wcpTemp);
			bUseFreeOnBuffer = FALSE;

			if (nStatus != NERR_Success)
			{
				switch (nStatus)
				{
					case NERR_DCNotFound:
	
						FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
						sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain controller not found - %s", lpErrorMessage);
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}
						bResult = FALSE;
						goto Cleanup;

						break;

					case ERROR_INVALID_NAME:

						FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
						sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain not found - %s", lpErrorMessage);
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}
						bResult = FALSE;
						goto Cleanup;

						break;

					default:
	
						FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
						sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Unexpected error - %s", lpErrorMessage);
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}
						bResult = FALSE;
						goto Cleanup;

						break;
				}
			}		
			else
			{
				if (TRACE > 0)
				{
					BAY_UnicodeToAnsi(wcpDomainController,&cpTemp);
					sprintf(lpMessage, "SecurityGate - Success: NetGetDCName - Domain Controller [%s]\n", cpTemp);
					OutputDebugString(lpMessage);
					CoTaskMemFree(cpTemp);
				}
			}

		}
		else
		{
			BAY_AnsiToUnicode(cpGroupDomain, &wcpDomainController);
			bUseFreeOnBuffer = TRUE;

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Use Server [%s]\n", cpGroupDomain);
				OutputDebugString(lpMessage);
			}

		}

	}
	
	///////////////////////////////////////////////////////////////////
	// Check user's local groups
	///////////////////////////////////////////////////////////////////
	if (strstr(cpUserDomain, "\\\\") == NULL)
		strcpy(lpBuffer, cpUserDomain);
	else
		strcpy(lpBuffer, cpUserDomain + 2);
	strcat(lpBuffer, "\\");

	strcat(lpBuffer, cpUserName);
	BAY_AnsiToUnicode(lpBuffer, &wcpTemp);

	nStatus = NetUserGetLocalGroups(
			wcpDomainController,                               
			wcpTemp, 
                    	dwLevel, 
			dwFlags,
                    	(LPBYTE*) &pLocalBuf, 
                    	dwPrefMaxLen, 
                    	&dwEntriesRead, 
                    	&dwTotalEntries);     

	CoTaskMemFree(wcpTemp);

	switch (nStatus)
	{
		case NERR_Success:

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Success: NetUserGetLocalGroups\n");
				OutputDebugString(lpMessage);
			}

			// Create the safearray
			VariantClear(vLocalGroups);
			vLocalGroups->vt = VT_ARRAY | VT_VARIANT;
			rgsaLocalGroups[0].lLbound = 0;
			rgsaLocalGroups[0].cElements = dwEntriesRead;
			psaLocalGroups = SafeArrayCreate(VT_VARIANT, 1, rgsaLocalGroups);
			if(psaLocalGroups == NULL)
			{
				bResult = FALSE;
				goto Cleanup;
			}
			vLocalGroups->parray = psaLocalGroups;

			if (TRACE > 0)
			{
				sprintf(lpMessage, "SecurityGate - Success: SafeArrayCreate\n");
				OutputDebugString(lpMessage);
			}
			
			if ((pTmpLocalBuf = pLocalBuf) != NULL)       
			{ 
	
				for (i = 0; i < dwEntriesRead; i++)          
				{ 
					if (pTmpLocalBuf == NULL) 
					{ 
						sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - An access violation has occurred");
						BAY_AnsiToUnicode(lpMessage,&wcpTemp);
						vErrorMessage->bstrVal = SysAllocString(wcpTemp);
						CoTaskMemFree(wcpTemp);
						if (TRACE > 0)
						{
							OutputDebugString(lpMessage);
							OutputDebugString("\n");
						}	

						break;             
					}  

					if (TRACE > 0)
					{
						BAY_UnicodeToAnsi(pTmpLocalBuf->lgrui0_name,&cpTemp);
						sprintf(lpMessage, "SecurityGate - User Local Group Name: %s\n", cpTemp);
						OutputDebugString(lpMessage);
						CoTaskMemFree(cpTemp);
					}

					pvTemp = new VARIANT;
					if (pvTemp)
					{
						VariantInit(pvTemp);
						pvTemp->vt = VT_BSTR;
						pvTemp->bstrVal = SysAllocString(pTmpLocalBuf->lgrui0_name);
						alLocalGroups[0] = (long) i;
						SafeArrayPutElement(psaLocalGroups, alLocalGroups, pvTemp);
						VariantClear(pvTemp);
						delete pvTemp;
					}

					pTmpLocalBuf++; 
					dwTotalCount++;          
				}       
			} 
	  	
			break;

		case NERR_UserNotFound:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - User not found - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case NERR_InvalidComputer:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Invalid server - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case ERROR_ACCESS_DENIED:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Premission denied - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		default:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetLocalGroups - Unexpected error - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;
	}

	///////////////////////////////////////////////////////////////////
	// Free up resources
	///////////////////////////////////////////////////////////////////
	Cleanup:

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Cleanup\n");

	if (cpUserDomain != NULL) 
		CoTaskMemFree(cpUserDomain);

	if (cpUserName != NULL) 
		CoTaskMemFree(cpUserName);

	if (cpGroupDomain != NULL) 
		CoTaskMemFree(cpGroupDomain);

	if (wcpDomainController != NULL)
		if (bUseFreeOnBuffer)
			CoTaskMemFree(wcpDomainController);
		else
     		NetApiBufferFree(wcpDomainController); 

	if (pLocalBuf != NULL)
		NetApiBufferFree(pLocalBuf); 

	if (pBuf != NULL)
		NetApiBufferFree(pBuf); 

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Done\n");

	return bResult;

}

BOOL GetUserFullName(VARIANT vUserDomain, VARIANT vUserName, VARIANT *vUserFullName, VARIANT *vErrorMessage)
{

	LPSTR cpUserDomain = NULL;
	LPSTR cpUserName = NULL;
	LPSTR cpTemp = NULL;
	LPWSTR wcpTemp = NULL;
	char lpMessage[MAXOUTPUTSTRINGLENGTH * 2];
	char lpErrorMessage[MAXOUTPUTSTRINGLENGTH];
	LPWSTR wcpDomainController = NULL;
	BOOL bResult = TRUE;
	NET_API_STATUS nStatus; 
	struct _USER_INFO_2 *pUserBuf = NULL;

	// Set up variant parameters
	VariantClear(vErrorMessage);
	vErrorMessage->vt = VT_BSTR;
	BAY_AnsiToUnicode("",&wcpTemp);
	vErrorMessage->bstrVal = SysAllocString(wcpTemp);
	CoTaskMemFree(wcpTemp);

	///////////////////////////////////////////////////////////////////
	// Convert parameters to strings
	///////////////////////////////////////////////////////////////////
	if ((vUserDomain.vt == VT_BSTR) && 
		(SysStringLen(vUserDomain.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserDomain.bstrVal,&cpUserDomain);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Domain: %s\n", cpUserDomain);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserDomain not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;

	}

	if ((vUserName.vt == VT_BSTR) && 
		(SysStringLen(vUserName.bstrVal)))
	{
		BAY_UnicodeToAnsi(vUserName.bstrVal,&cpUserName);
		if (TRACE > 0)
		{
			sprintf(lpMessage, "SecurityGate - User Name: %s\n", cpUserName);
			OutputDebugString(lpMessage);
		}
	}
	else
	{
		sprintf(lpMessage,"SecurityGate - Error: UserName not present");
		BAY_AnsiToUnicode(lpMessage,&wcpTemp);
		vErrorMessage->bstrVal = SysAllocString(wcpTemp);
		CoTaskMemFree(wcpTemp);
		if (TRACE > 0)
		{
			OutputDebugString(lpMessage);
			OutputDebugString("\n");
		}
		bResult = FALSE;
		goto Cleanup;
	}


	///////////////////////////////////////////////////////////////////
	// Get a domain controller for users's domain
	///////////////////////////////////////////////////////////////////
	BAY_AnsiToUnicode(cpUserDomain, &wcpTemp);
	nStatus = NetGetDCName(
					NULL,
					wcpTemp,  
					(LPBYTE *) &wcpDomainController);
	CoTaskMemFree(wcpTemp);

	if (nStatus != NERR_Success)
	{
		switch (nStatus)
		{
			case NERR_DCNotFound:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain controller not found - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				break;

			case ERROR_INVALID_NAME:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Domain not found - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				break;

			default:

				FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
				sprintf(lpMessage,"SecurityGate - Error: NetGetDCName - Unexpected error - %s", lpErrorMessage);
				BAY_AnsiToUnicode(lpMessage,&wcpTemp);
				vErrorMessage->bstrVal = SysAllocString(wcpTemp);
				CoTaskMemFree(wcpTemp);
				if (TRACE > 0)
				{
					OutputDebugString(lpMessage);
					OutputDebugString("\n");
				}
				bResult = FALSE;
				goto Cleanup;

				break;
		}
	}
	else
	{
		if (TRACE > 0)
		{
			BAY_UnicodeToAnsi(wcpDomainController,&cpTemp);
			sprintf(lpMessage, "SecurityGate - Success: NetGetDCName - Domain Controller [%s]\n", cpTemp);
			OutputDebugString(lpMessage);
			CoTaskMemFree(cpTemp);
		}
	}

	///////////////////////////////////////////////////////////////////
	// Get a users's information
	///////////////////////////////////////////////////////////////////
	nStatus = NetUserGetInfo(
			wcpDomainController,                               
			vUserName.bstrVal, 
			2, 
                    	(LPBYTE*) &pUserBuf);     

	switch (nStatus)
	{
		case NERR_Success:

			if (TRACE > 0)
			{
			BAY_UnicodeToAnsi(pUserBuf->usri2_full_name,&cpTemp);
			sprintf(lpMessage, "SecurityGate - Success: NetUserGetInfo - User Full name [%s]\n", cpTemp);
			OutputDebugString(lpMessage);
			CoTaskMemFree(cpTemp);

			}

			vUserFullName->vt = VT_BSTR;
			vUserFullName->bstrVal = SysAllocString(pUserBuf->usri2_full_name);

			break;

		case NERR_UserNotFound:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetInfo - User not found - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case NERR_InvalidComputer:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetInfo - Invalid server - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		case ERROR_ACCESS_DENIED:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetInfo - Premission denied - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;

		default:

			FormatLastError(GetLastError(), lpErrorMessage, MAXOUTPUTSTRINGLENGTH); 		
			sprintf(lpMessage,"SecurityGate - Error: NetUserGetInfo - Unexpected error - %s", lpErrorMessage);
			BAY_AnsiToUnicode(lpMessage,&wcpTemp);
			vErrorMessage->bstrVal = SysAllocString(wcpTemp);
			CoTaskMemFree(wcpTemp);
			if (TRACE > 0)
			{
				OutputDebugString(lpMessage);
				OutputDebugString("\n");
			}
			bResult = FALSE;
			goto Cleanup;

			break;
	}

	///////////////////////////////////////////////////////////////////
	// Free up resources
	///////////////////////////////////////////////////////////////////
	Cleanup:

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Cleanup\n");

	if (cpUserDomain != NULL) 
		CoTaskMemFree(cpUserDomain);

	if (cpUserName != NULL) 
		CoTaskMemFree(cpUserName);

	if (wcpDomainController != NULL)
		NetApiBufferFree(wcpDomainController); 

	if (pUserBuf != NULL)
		NetApiBufferFree(pUserBuf); 

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Done\n");

	return bResult;

}
/////////////////////////////////////////////////////////////////////////////
// CSecurityGate


STDMETHODIMP CSecurityGate::GetDomainUser(VARIANT *vDomain, VARIANT *vUser, VARIANT *vErrorMessage, VARIANT *vResult)
{

	VariantClear(vResult);
	vResult->vt = VT_BOOL;
	vResult->boolVal = GetUser(
				vDomain, 
				vUser, 
				vErrorMessage);
	
		return S_OK;

}

STDMETHODIMP CSecurityGate::ValidateDomainUser(VARIANT vUserDomain, VARIANT vUserName, VARIANT vGroupDomain, VARIANT vGroupName, VARIANT *vValidated, VARIANT *vErrorMessage, VARIANT *vResult)
{
	
	VariantClear(vResult);
	vResult->vt = VT_BOOL;
	vResult->boolVal = ValidateUser( 
				vUserDomain, 
				vUserName, 
				vGroupDomain, 
				vGroupName, 
				vValidated, 
				vErrorMessage);

		return S_OK;

}

STDMETHODIMP CSecurityGate::SetTraceLevel(VARIANT vTrace)
{

	if (vTrace.vt == VT_I4)
		TRACE = vTrace.lVal;

	if (TRACE > 0)
		OutputDebugString("SecurityGate - Trace is now on\n");
	else
		OutputDebugString("SecurityGate - Trace is now off\n");

	return S_OK;

}

STDMETHODIMP CSecurityGate::GetDomainUserGroups(VARIANT vUserDomain, VARIANT vUserName, VARIANT vGroupDomain, VARIANT *vGlobalGroups, VARIANT *vLocalGroups, VARIANT *vErrorMessage, VARIANT *vResult)
{

	VariantClear(vResult);
	vResult->vt = VT_BOOL;
	vResult->boolVal = GetUserGroups( 
				vUserDomain, 
				vUserName, 
				vGroupDomain, 
				vGlobalGroups, 
				vLocalGroups, 
				vErrorMessage);

	return S_OK;

}

STDMETHODIMP CSecurityGate::GetDomainUserFullName(VARIANT vUserDomain, VARIANT vUserName, VARIANT *vUserFullName, VARIANT *vErrorMessage, VARIANT *vResult)
{

	VariantClear(vResult);
	vResult->vt = VT_BOOL;
	vResult->boolVal = GetUserFullName( 
				vUserDomain, 
				vUserName, 
				vUserFullName, 
				vErrorMessage);

	return S_OK;

}