========== mswin32/S6_API-Base_Console #109607, from Rohan_Phillips, 9586 chars, 26-Sep-95 18:16:07 Comment to 109588. ---------- Subject: Am i a service? Fm: Rohan Phillips 72420,3522 To: Dick Beck 74260,3034 Dick, Try the code below. It's given to you with the notice that there is no support for it. Just something a friend wrote. /* @comm CService::CheckSIDs() determines whether the current process is executing as a console process or a service by enumerating the process token. If the process token contains a SECURITY_INTERACTIVE_RID SID, then the process is running as a console process. If the token contains a SECURITY_SERVICE_RID SID, then the process is running as a service in a user account. If neither of these cases are true, then the process is running as a service in the LOCAL_SYSTEM account. If the service is running under the LOCAL_SYSTEM account, it may have access to the desktop which is determined by checking the service's service_type for SERVICE_INTERACTIVE_PROCESS. If the service is interactive, a console is allocated and stdout and stderr redirected to it */ DWORD CService::CheckSIDs(void) { HANDLE hProcessToken = NULL; DWORD groupLength = 50; PTOKEN_GROUPS groupInfo = NULL; SID_IDENTIFIER_AUTHORITY siaNt = SECURITY_NT_AUTHORITY; PSID pInteractiveSid = NULL; PSID pServiceSid = NULL; DWORD dwRet = NO_ERROR; DWORD ndx; // open the token if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hProcessToken)) { dwRet = ::GetLastError(); goto closedown; } // allocate a buffer of default size groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength); if (groupInfo == NULL) { dwRet = ::GetLastError(); goto closedown; } // try to get the info if (!::GetTokenInformation(hProcessToken, TokenGroups, groupInfo, groupLength, &groupLength)) { // if buffer was too small, allocate to proper size, otherwise error if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) { dwRet = ::GetLastError(); goto closedown; } ::LocalFree(groupInfo); groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength); if (groupInfo == NULL) { dwRet = ::GetLastError(); goto closedown; } if (!GetTokenInformation(hProcessToken, TokenGroups, groupInfo, groupLength, &groupLength)) { dwRet = ::GetLastError(); goto closedown; } } // // 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). // // create comparison sids if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &pInteractiveSid)) { dwRet = ::GetLastError(); goto closedown; } if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pServiceSid)) { dwRet = ::GetLastError(); goto closedown; } // reset flags m_isInteractive = FALSE; m_isService = FALSE; // try to match sids for (ndx = 0; ndx < groupInfo->GroupCount ; ndx += 1) { SID_AND_ATTRIBUTES sanda = groupInfo->Groups[ndx]; PSID pSid = sanda.Sid; // // Check to see if the group we're looking at is one of // the two groups we're interested in. // if (::EqualSid(pSid, pInteractiveSid)) { // // This process has the Interactive SID in its // token. This means that the process is running as // a console process // m_isInteractive = TRUE; m_isService = FALSE; break; } else if (::EqualSid(pSid, pServiceSid)) { // // This process has the Service SID in its // token. This means that the process is running as // a service running in a user account ( not local system ). // m_isService = TRUE; m_isInteractive = FALSE; break; } } if ( !( m_isService || m_isInteractive ) ) { // // 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. // m_isService = TRUE; // determine if the local system service is interactive. We // do this y looking in the service's registry and checking // the Type value for the SERVICE_INTERACTIVE_PROCESS bit HKEY hkey = NULL; TCHAR szKey[256]; SPRINTF( szKey, TEXT("SYSTEM\\CurrentControlSet\\Services\\%s"), m_pServiceName ); if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkey ) == ERROR_SUCCESS ) { DWORD dwType = 0; DWORD dwSize = sizeof(DWORD); if ( RegQueryValueEx(hkey, TEXT("Type"), NULL, NULL, (LPBYTE) &dwType, &dwSize ) == ERROR_SUCCESS ) { if ( dwType & SERVICE_INTERACTIVE_PROCESS ) { m_isInteractive = TRUE; // service was given permission to interact with the // with the desktop, so allocate a console FreeConsole(); if ( AllocConsole() ) { // Now re-map the C Runtime STDIO handles int hCrt = ::_open_osfhandle((long) GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); *stdout = *(::_fdopen(hCrt, "w")); ::setvbuf(stdout, NULL, _IONBF, 0); *stderr = *(::_fdopen(hCrt, "w")); ::setvbuf(stderr, NULL, _IONBF, 0); } DWORD dwDebug = 0; DWORD dwDbgSize = sizeof(dwDebug); TCHAR szWindbgPath[256]; DWORD dwPathSize = sizeof(szWindbgPath); if ( ( RegQueryValueEx(hkey, TEXT("Debug"), NULL, NULL, (LPBYTE) &dwDebug, &dwDbgSize ) == ERROR_SUCCESS ) && ( RegQueryValueEx(hkey, TEXT("WindbgPath"), NULL, NULL, (LPBYTE) szWindbgPath, &dwPathSize ) == ERROR_SUCCESS ) ) { if( dwDebug ) // 1 if debug { PROCESS_INFORMATION pi; STARTUPINFO si; // startup info si.cb = sizeof( STARTUPINFO ); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwX = 0; si.dwY = 0; si.dwXSize = 0; si.dwYSize = 0; si.dwFlags = (DWORD) NULL; si.wShowWindow = SW_SHOWDEFAULT; si.cbReserved2 = 0; si.lpReserved2 = NULL; pi.hProcess = NULL; TCHAR szCmd[300]; _stprintf( szCmd, _T("%s -g -p 0x%x"), szWindbgPath, GetCurrentProcessId() ); //-- now create the windbg process if( CreateProcess( NULL, szCmd, (LPSECURITY_ATTRIBUTES) NULL, (LPSECURITY_ATTRIBUTES) NULL, TRUE, DETACHED_PROCESS, (LPVOID) NULL, (LPTSTR) NULL, &si, &pi ) ) { CloseHandle( pi.hThread ); CloseHandle( pi.hProcess ); } } } } } RegCloseKey( hkey ); } } closedown: if ( pServiceSid ) ::FreeSid( pServiceSid ); if ( pInteractiveSid ) ::FreeSid( pInteractiveSid ); if ( groupInfo ) ::LocalFree( groupInfo ); if ( hProcessToken ) ::CloseHandle( hProcessToken ); return dwRet; }