#include <windows.h>
#include <stdio.h>
#include <Sddl.h>

int
pgwin32_is_service(void)
{
	static int	_is_service = -1;
	BOOL		IsMember;
	PSID		ServiceSid;
	PSID		LocalSystemSid;
	LPTSTR      StringSid = NULL;
	SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };

	/* Only check the first time */
	if (_is_service != -1)
		return _is_service;

	/* First check for LocalSystem */
	if (!AllocateAndInitializeSid(&NtAuthority, 1,
		SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
		&LocalSystemSid))
	{
		fprintf(stderr, "could not get SID for local system account\n");
		return -1;
	}

	if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
	{
		fprintf(stderr, "could not check access token membership: error code %lu\n",
			GetLastError());
		FreeSid(LocalSystemSid);
		return -1;
	}
	ConvertSidToStringSid(LocalSystemSid, &StringSid);
	printf("local sid: %s\n", StringSid);
	FreeSid(LocalSystemSid);

	if (IsMember)
	{
		_is_service = 1;
		return _is_service;
	}

	/* Check for service group membership */
	if (!AllocateAndInitializeSid(&NtAuthority, 1,
		SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
		&ServiceSid))
	{
		fprintf(stderr, "could not get SID for service group: error code %lu\n",
			GetLastError());
		return -1;
	}

	if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
	{
		fprintf(stderr, "could not check access token membership: error code %lu\n",
			GetLastError());
		FreeSid(ServiceSid);
		return -1;
	}
	ConvertSidToStringSid(ServiceSid, &StringSid);
	printf("service sid: %s\n", StringSid);
	FreeSid(ServiceSid);
	LocalFree(StringSid);

	if (IsMember)
		_is_service = 1;
	else
		_is_service = 0;

	return _is_service;
}

int main() {
	printf(pgwin32_is_service() ? "service" : "not service");
	return 0;
}