/*-------------------------------------------------------------------------
 *
 * security.c
 *    Microsoft Windows Win32 Security Support Functions
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  $PostgreSQL$
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

/*
 * Returns nonzero if the current user has administrative privileges,
 * or zero if not.
 */
int pgwin32_is_admin(void) {
	HANDLE AccessToken;
	UCHAR InfoBuffer[1024];
	PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer; 
	DWORD InfoBufferSize;
	PSID AdministratorsSid;
	PSID PowerUsersSid;
	SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY }; 
	UINT x;
	BOOL success;
	
	if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
		ereport(FATAL,
				(errmsg_internal("Failed to open process token: %i",(int)GetLastError())));

	if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,
							 1024, &InfoBufferSize))
		ereport(FATAL,
				(errmsg_internal("Failed to get token information: %i",(int)GetLastError())));

	CloseHandle(AccessToken);

	if(!AllocateAndInitializeSid(&NtAuthority, 2,
								 SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
								 0,&AdministratorsSid))
		ereport(FATAL,
				(errmsg_internal("Failed to get SID for Administrators group: %i",(int)GetLastError())));
	
	if (!AllocateAndInitializeSid(&NtAuthority, 2,
								  SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
								  0, &PowerUsersSid))
		ereport(FATAL,
				(errmsg_internal("Failed to get SID for PowerUsers group: %i",(int)GetLastError())));
	
	success = FALSE;
	
	for (x=0; x<Groups->GroupCount; x++)
	{
		if( EqualSid(AdministratorsSid, Groups->Groups[x].Sid) ||
			EqualSid(PowerUsersSid, Groups->Groups[x].Sid))
		{
			success = TRUE;
			break;
		}
	}
	
	FreeSid(AdministratorsSid);
	FreeSid(PowerUsersSid);
	return success;
}
