int pgwin32_is_service(void) { static int _is_service = -1; HANDLE hProcessToken = NULL; DWORD groupLength = 64; PTOKEN_GROUPS groupInfo; SID_IDENTIFIER_AUTHORITY siaNt = SECURITY_NT_AUTHORITY; PSID InteractiveSid = NULL; PSID ServiceSid = NULL; DWORD i; /* Only check the first time */ if (_is_service != -1) return _is_service; _is_service = 0; groupInfo = (PTOKEN_GROUPS) LocalAlloc(0, groupLength); if (groupInfo == NULL) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken)) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } if (!GetTokenInformation(hProcessToken, TokenGroups, groupInfo, groupLength, &groupLength)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } LocalFree(groupInfo); groupInfo = NULL; groupInfo = (PTOKEN_GROUPS) LocalAlloc(0, groupLength); if (groupInfo == NULL) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } if (!GetTokenInformation(hProcessToken, TokenGroups, groupInfo, groupLength, &groupLength)) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } } // // We now know the groups associated with this token. We want to look to see if // the interactive group is active in the token, and if so, we know that // this is an interactive process. // // We also look for the "service" SID, and if it's present, we know we're a service. // // The service SID will be present iff the service is running in a // user account (and was invoked by the service controller). // if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &InteractiveSid)) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &ServiceSid)) { fprintf(stderr, "could not get SID for local system account\n"); goto clean; } for (i = 0; i < groupInfo->GroupCount; i += 1) { SID_AND_ATTRIBUTES sanda = groupInfo->Groups[i]; PSID Sid = sanda.Sid; // // Check to see if the group we're looking at is one of // the 2 groups we're interested in. // if (EqualSid(Sid, InteractiveSid)) { // // This process has the Interactive SID in its // token. This means that the process is running as // an EXE. // goto clean; } else if (EqualSid(Sid, ServiceSid)) { // // This process has the Service SID in its // token. This means that the process is running as // a service running in a user account. // _is_service = 1; goto clean; } } // // Neither Interactive or Service was present in the current users token, // This implies that the process is running as a service, most likely // running as LocalSystem. // _is_service = 1; clean: if (InteractiveSid) FreeSid(InteractiveSid); if (ServiceSid) FreeSid(ServiceSid); if (groupInfo) LocalFree(groupInfo); if (hProcessToken) CloseHandle(hProcessToken); return _is_service; }