g// EmExtn.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include #include #include #include "Processes.h" #define SUCCESS 0 DWORD InvalidCallback ( /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc, /* [in] */ LPARAM lParam, /* [in] */ LONG nItemNum ) { return( lpEnumSrvcsProc( INVALID_PID, NULL, NULL, NULL, lParam, nItemNum ) ); } DWORD GetNumberOfRunningApps ( /* [out] */ DWORD *pdwNumbApps ) { DWORD dwLastRet = 0L; DWORD *pdwPIDs = NULL; DWORD dwBuffSize = 256L; UINT nIdx = 0; bool bIsService = false; do { // // This loop is used to get all the running PIDs // in the system. Because we do not know how many // processes are running, we dynamically increase // the array size. Limit = 256 DWORDs * 5 // do { if(pdwPIDs != NULL){ delete[] pdwPIDs; pdwPIDs = NULL; } dwBuffSize *= (nIdx + 1); pdwPIDs = new DWORD[dwBuffSize]; if(pdwPIDs == NULL){ dwLastRet = GetLastError(); break; } dwLastRet = GetAllPids( pdwPIDs, dwBuffSize, &dwBuffSize ); } while(dwLastRet == E_TOOMANY_PROCESSES); if( dwLastRet == 0 ){ *pdwNumbApps = 0L; for(UINT i = 0; i < dwBuffSize; ++i) { IsService( pdwPIDs[i], &bIsService ); if( bIsService != true ) *pdwNumbApps += 1; } } } while ( false ); if(pdwPIDs != NULL) { delete[] pdwPIDs; pdwPIDs = NULL; } return dwLastRet; } DWORD GetAllPids ( /* [out] */ DWORD adwProcIDs[], /* [in] */ DWORD dwBuffSize, /* [out] */ DWORD *pdwNumbProcs ) { DWORD dwLastRet = 0L; _ASSERT(adwProcIDs != NULL); _ASSERT(dwBuffSize != 0L); _ASSERT(pdwNumbProcs != NULL); do { if( (adwProcIDs == NULL) || (dwBuffSize == 0L) || (pdwNumbProcs == 0L)) { dwLastRet = E_INVALIDARG; break; } // // Get the list of process identifiers. // dwLastRet = (DWORD)EnumProcesses( adwProcIDs, dwBuffSize, pdwNumbProcs); if(dwLastRet == 0L){ dwLastRet = GetLastError(); break; } // // If both of them are same, it means that // there may be more PIDs for which there // is no space.. // if(dwBuffSize == *pdwNumbProcs){ dwLastRet = ERROR_NOT_ENOUGH_MEMORY; break; } // // This will give us the number of PIDs // (*pdwNumbProcs) = ((*pdwNumbProcs) / sizeof(DWORD)); dwLastRet = 0L; } while(FALSE); return dwLastRet; } DWORD GetNumberOfServices ( /* [out] */ DWORD *pdwNumbSrvcs, /* [in] */ DWORD dwServiceType, /* = SERVICE_WIN32 */ /* [in] */ DWORD dwServiceState /* = SERVICE_ACTIVE */ ) { _ASSERTE( pdwNumbSrvcs != NULL ); DWORD dwLastRet = 0L; SC_HANDLE scm = NULL; LPENUM_SERVICE_STATUS status = NULL; DWORD cbBytesNeeded = 0L, dwNumbSvcs = 0L, dwResume = 0L; ENUM_SERVICE_STATUS aServices[1]; // a-mando, bug ID: 296023 __try { if( pdwNumbSrvcs == NULL ) { dwLastRet = -1L; goto qGetNumberOfServices; } scm = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE ); if( !scm ) { dwLastRet = GetLastError(); goto qGetNumberOfServices; } *pdwNumbSrvcs = 0L; if( EnumServicesStatus( scm, dwServiceType, dwServiceState, aServices, // a-mando, bug ID: 296023 0, &cbBytesNeeded, &dwNumbSvcs, &dwResume ) == false ) { dwLastRet = GetLastError(); } if( dwLastRet != ERROR_MORE_DATA ) { goto qGetNumberOfServices;} // // Allocate space // status = (LPENUM_SERVICE_STATUS)LocalAlloc( LPTR, cbBytesNeeded ); if( !status ) { dwLastRet = GetLastError(); goto qGetNumberOfServices; } // // Get the status records. // dwResume = 0; dwLastRet = EnumServicesStatus( scm, dwServiceType, dwServiceState, status, cbBytesNeeded, &cbBytesNeeded, &dwNumbSvcs, &dwResume ); if (dwLastRet == 0) { dwLastRet = GetLastError(); goto qGetNumberOfServices; } *pdwNumbSrvcs = dwNumbSvcs; dwLastRet = SUCCESS; qGetNumberOfServices: if( scm ) CloseServiceHandle( scm ); if( status ) LocalFree( status ); } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); if( scm ) CloseServiceHandle( scm ); if( status ) LocalFree( status ); _ASSERTE( false ); } return dwLastRet; } DWORD GetNumberOfActiveServices ( /* [out] */ DWORD *pdwNumbActiveSrvcs ) { return GetNumberOfServices( pdwNumbActiveSrvcs ); } DWORD GetNumberOfInactiveServices ( /* [out] */ DWORD *pdwNumbInactiveSrvcs ) { return GetNumberOfServices( pdwNumbInactiveSrvcs, SERVICE_WIN32, SERVICE_INACTIVE ); } DWORD IsService ( /* [in] */ UINT nPid, /* [out] */ bool *pbIsService, /* [out] */ LPTSTR lpszImagePath, /* [out] */ ULONG cchImagePath, /* [out] */ LPTSTR lpszServiceShortName, /* [in] */ ULONG cchServiceShortName, /* [out] */ LPTSTR lpszServiceDescription, /* [in] */ ULONG cchServiceDescription ) { DWORD dwRet = 0L; OSVERSIONINFO osvi; ZeroMemory( (void *)&osvi, sizeof(OSVERSIONINFO) ); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if( !GetVersionEx (&osvi) ) { return (dwRet = GetLastError()); } if( osvi.dwPlatformId & VER_PLATFORM_WIN32_NT ) { if( osvi.dwMajorVersion == 4 ) { // && osvi.dwMinorVersion == 0 ) { // we will not look for the minor version. IsService_NT4( nPid, pbIsService ); } else if( osvi.dwMajorVersion == 5 ) { // && osvi.dwMinorVersion == 0 ) { IsService_NT5( nPid, pbIsService, lpszImagePath, cchImagePath, lpszServiceShortName, cchServiceShortName, lpszServiceDescription, cchServiceDescription ); } } return dwRet; } DWORD IsService_NT5 ( /* [in] */ UINT nPid, /* [out] */ bool *pbIsService, /* [out] */ LPTSTR lpszImagePath, /* [out] */ ULONG cchImagePath, /* [out] */ LPTSTR lpszServiceShortName, /* [in] */ ULONG cchServiceShortName, /* [out] */ LPTSTR lpszServiceDescription, /* [in] */ ULONG cchServiceDescription ) { _ASSERTE ( pbIsService != NULL ); bool bIsService = false; DWORD dwLastRet = 0L; int i = 0; SC_HANDLE scm = NULL; ENUM_SERVICE_STATUS_PROCESS *status = NULL; DWORD numServices = 0L, sizeNeeded = 0L, resume = 0L; __try { if( pbIsService == NULL ) { dwLastRet = -1L; goto qIsService; } // // Open a connection to the SCM // scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE); if ( !scm ){ dwLastRet = GetLastError(); goto qIsService; } // // Get the number of bytes to allocate // resume = 0; if( EnumServicesStatusEx( scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, // We won't debug drivers SERVICE_ACTIVE, 0, 0, &sizeNeeded, &numServices, &resume, NULL ) == 0 ) { dwLastRet = GetLastError(); // // If it is any error other than this, // we won't continue.. // if(dwLastRet != ERROR_MORE_DATA) goto qIsService; } // // Allocate space // status = (ENUM_SERVICE_STATUS_PROCESS *)LocalAlloc( LPTR, sizeNeeded ); if( status == NULL ){ dwLastRet = GetLastError(); goto qIsService; } // // Get the status records. // resume = 0; if( EnumServicesStatusEx( scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, // We won't debug drivers SERVICE_ACTIVE, (LPBYTE)status, sizeNeeded, &sizeNeeded, &numServices, &resume, NULL ) == 0 ) { dwLastRet = GetLastError(); goto qIsService; } *pbIsService = false; for (i = 0; i < (int)numServices; i++) { if( status[i].ServiceStatusProcess.dwProcessId == nPid ) { *pbIsService = true; if(lpszImagePath) { _tcsncpy( lpszImagePath, _T(""), cchImagePath ); } if(lpszServiceShortName) { _tcsncpy( lpszServiceShortName, status[i].lpServiceName, cchServiceShortName ); } if(lpszServiceDescription) { _tcsncpy( lpszServiceDescription, status[i].lpDisplayName, cchServiceDescription ); } break; } } dwLastRet = SUCCESS; qIsService: if( scm ) { CloseServiceHandle(scm); scm = NULL; } if( status ){ LocalFree(status); status = NULL; } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); if( scm ) { CloseServiceHandle( scm ); scm = NULL; } if( status ){ LocalFree(status); status = NULL; } _ASSERTE( false ); } return dwLastRet; } DWORD GetServiceInfo ( /* [in] */ UINT nPid, /* [out] */ LPTSTR lpszImagePath, /* [out] */ ULONG cchImagePath, /* [out] */ LPTSTR lpszServiceShortName, /* [in] */ ULONG cchServiceShortName, /* [out] */ LPTSTR lpszServiceDescription, /* [in] */ ULONG cchServiceDescription ) { bool bIsService = false; return IsService( nPid, &bIsService, lpszImagePath, cchImagePath, lpszServiceShortName, cchServiceShortName, lpszServiceDescription, cchServiceDescription ); } DWORD EnumRunningProcesses ( /* [in] */ ENUMPROCSANDSERVICES lpEnumRunProc, /* [in] */ LPARAM lParam, /* [in] */ UINT nStartIndex ) { // Nothing to do if this is NULL.. _ASSERT(lpEnumRunProc != NULL); DWORD dwLastRet = 0L; DWORD dwBuffSize = 256L; DWORD *pdwPIDs = NULL; UINT nIdx = 0; UINT nItemNum = nStartIndex; bool bService = FALSE; TCHAR szShortName[_MAX_PATH] = _T(""); TCHAR szImagePath[_MAX_PATH] = _T(""); __try { if( !lpEnumRunProc ){ dwLastRet = E_INVALIDARG; goto qEnumRunningProcesses; } // // This loop is used to get all the running PIDs // in the system. Because we do not know how many // processes are running, we dynamically increase // the array size. Limit = 256 DWORDs * 5 // do{ if(pdwPIDs != NULL){ delete[] pdwPIDs; pdwPIDs = NULL; } dwBuffSize *= (nIdx + 1); pdwPIDs = new DWORD[dwBuffSize]; if(pdwPIDs == NULL){ dwLastRet = GetLastError(); break; } dwLastRet = GetAllPids( pdwPIDs, dwBuffSize, &dwBuffSize ); } while(dwLastRet == E_TOOMANY_PROCESSES); // // There are more processes than we // can handle.. // if( dwLastRet != E_TOOMANY_PROCESSES && dwLastRet != 0){ goto qEnumRunningProcesses; } // // If everything goes alright, call the Callback procedure // once for each PID (or till the procedure returns FALSE) // with the PID and the corresponding Image path.. // nIdx = -1; while(++nIdx < dwBuffSize){ dwLastRet = SUCCESS; IsService( pdwPIDs[nIdx], &bService ); if( bService == true ) continue; // we won't add services into the list.. // This may fail for some procs like the system process. if( GetImageNameFromPID( pdwPIDs[nIdx], szImagePath, _MAX_PATH )) { if(lpEnumRunProc(INVALID_PID, NULL, NULL, NULL, lParam, nItemNum++) == FALSE){ dwLastRet = FALSE; goto qEnumRunningProcesses; // Stop when the Callback procedure returns FALSE. } } else { BSTR bstrDesc = _T(""); if( IsPackage( szImagePath ) ) { GetPackageDescription( pdwPIDs[nIdx], bstrDesc ); } if(lpEnumRunProc(pdwPIDs[nIdx], szImagePath, _T(""), bstrDesc, lParam, nItemNum++ ) == FALSE) { dwLastRet = FALSE; goto qEnumRunningProcesses; // Stop when the Callback procedure returns FALSE. } } } dwLastRet = SUCCESS; qEnumRunningProcesses: // // Clean up memory allocated for PIDs array. // if( pdwPIDs ) { delete[] pdwPIDs; pdwPIDs = NULL; } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); if( pdwPIDs ) { delete[] pdwPIDs; pdwPIDs = NULL; } _ASSERTE( false ); } return dwLastRet; } BOOL IsPackage ( IN LPTSTR lpszImageName ) { _ASSERTE( lpszImageName != NULL ); BOOL bRet = false; const DWORD cTemplates = 2; LPCTSTR szTemplate [cTemplates]; __try { if( !lpszImageName ) { return (bRet = false); } _tcslwr( lpszImageName ); szTemplate[0] = _T("dllhost.exe"); szTemplate[1] = _T("mts.exe"); for( int i = 0; i < cTemplates; i++ ) { if( _tcsstr( lpszImageName, szTemplate[i] ) != NULL ) { bRet = true; break; } } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { bRet = false; _ASSERTE( false ); } return bRet; } DWORD EnumRunningServices ( /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc, /* [in] */ LPARAM lParam, /* [in] */ UINT nStartIndex ) { return EnumServices( lpEnumSrvcsProc, lParam, SERVICE_ACTIVE, nStartIndex ); } DWORD EnumStoppedServices ( /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc, /* [in] */ LPARAM lParam, /* [in] */ UINT nStartIndex ) { return EnumServices( lpEnumSrvcsProc, lParam, SERVICE_INACTIVE, nStartIndex ); } DWORD EnumServices ( /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc, /* [in] */ LPARAM lParam, /* [in] */ DWORD dwSrvcState, /* [in] */ UINT nStartIndex ) { _ASSERTE ( lpEnumSrvcsProc != NULL ); bool bIsService = false; DWORD dwLastRet = 0L; int i = 0; SC_HANDLE scm = NULL, service = NULL; LPQUERY_SERVICE_CONFIG buffer = NULL; ENUM_SERVICE_STATUS_PROCESS *status = NULL; DWORD numServices = 0L, sizeNeeded = 0L, resume = 0L; UINT nItemNum = nStartIndex; __try { if( lpEnumSrvcsProc == NULL ) { dwLastRet = -1L; goto qEnumServices; } // // Open a connection to the SCM // scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE); if ( !scm ){ dwLastRet = GetLastError(); goto qEnumServices; } // // Get the number of bytes to allocate // resume = 0; if( EnumServicesStatusEx( scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, // We won't debug drivers dwSrvcState, 0, 0, &sizeNeeded, &numServices, &resume, NULL ) == 0 ) { dwLastRet = GetLastError(); // // If it is any error other than this, // we won't continue.. // if(dwLastRet != ERROR_MORE_DATA) goto qEnumServices; } // // Allocate space // status = (ENUM_SERVICE_STATUS_PROCESS *)LocalAlloc( LPTR, sizeNeeded ); if( status == NULL ){ dwLastRet = GetLastError(); goto qEnumServices; } // // Get the status records. // resume = 0; if( EnumServicesStatusEx( scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, // We won't debug drivers dwSrvcState, (LPBYTE)status, sizeNeeded, &sizeNeeded, &numServices, &resume, NULL ) == 0 ) { dwLastRet = GetLastError(); goto qEnumServices; } for (i = 0; i < (int)numServices; i++) { if(service){ CloseServiceHandle(service); service = NULL; } service = OpenService( scm, status[i].lpServiceName, SERVICE_QUERY_CONFIG ); if (!service) { dwLastRet = GetLastError(); InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ ); continue; } //goto qEnumServices; } // // Find out how big the buffer needs to be // dwLastRet = QueryServiceConfig( service, 0, 0, &sizeNeeded ); if(dwLastRet == 0){ dwLastRet = GetLastError(); // // If it is any error other than // this, we won't continue.. // if(dwLastRet != ERROR_INSUFFICIENT_BUFFER) { InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ ); continue; } } // // Allocate space for the buffer // buffer = (LPQUERY_SERVICE_CONFIG) LocalAlloc( LPTR, sizeNeeded ); // // Get Buffer // dwLastRet = QueryServiceConfig( service, buffer, sizeNeeded, &sizeNeeded ); if (dwLastRet == 0){ dwLastRet = GetLastError(); InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ ); continue; } _tcslwr(buffer->lpBinaryPathName); if(lpEnumSrvcsProc( status[i].ServiceStatusProcess.dwProcessId, buffer->lpBinaryPathName, status[i].lpServiceName, status[i].lpDisplayName, lParam, nItemNum++ ) == FALSE) { dwLastRet = FALSE; goto qEnumServices; // Stop when the Callback procedure returns FALSE. } // // CleanUp // if(buffer != NULL){ LocalFree(buffer); buffer = NULL; } } dwLastRet = SUCCESS; qEnumServices: if( scm ) { CloseServiceHandle(scm); scm = NULL; } if( status ){ LocalFree(status); status = NULL; } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); if( scm ) { CloseServiceHandle( scm ); scm = NULL; } if( status ){ LocalFree(status); status = NULL; } _ASSERTE( false ); } return dwLastRet; } DWORD StartServiceAndGetPid ( IN LPCTSTR lpszServiceShortName, OUT UINT *pnPid ) { _ASSERTE(lpszServiceShortName != NULL); DWORD dwLastRet = 0L; DWORD dwBytesNeeded = 0L; SC_HANDLE scm = NULL, service = NULL; SERVICE_STATUS_PROCESS stInfo; do { // // Open a connection to the SCM // scm = OpenSCManager(0, 0, GENERIC_EXECUTE | STANDARD_RIGHTS_REQUIRED | SC_MANAGER_ENUMERATE_SERVICE); if (!scm){ dwLastRet = GetLastError(); break; } service = OpenService( scm, lpszServiceShortName, GENERIC_EXECUTE | STANDARD_RIGHTS_REQUIRED | SC_MANAGER_ENUMERATE_SERVICE ); if (!service){ dwLastRet = GetLastError(); break; } if( StartService( service, 0L, NULL ) == 0 ) { dwLastRet = GetLastError(); break; } if( QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO, (LPBYTE) &stInfo, sizeof stInfo, &dwBytesNeeded ) == 0 ) { dwLastRet = GetLastError(); break; } // // Successful.. // *pnPid = stInfo.dwProcessId; dwLastRet = 0L; } while(FALSE); if(scm){ CloseServiceHandle(scm); scm = NULL; } if(service){ CloseServiceHandle(service); service = NULL; } return dwLastRet; } BOOL IsImageRunning ( /* [in] */ ULONG lPID ) { bool bRet = FALSE; HANDLE hProcess = ::OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, lPID ); if(hProcess != NULL){ CloseHandle(hProcess); bRet = TRUE; } return bRet; } DWORD GetImageNameFromPID ( /* [in] */ ULONG lPID, /* [out] */ LPTSTR lpszImagePath, /* [in] */ DWORD dwBuffSize ) { DWORD dwLastRet = S_OK; HANDLE hProcess = NULL; HMODULE hMod = NULL; DWORD cbNeeded = 0L; // // 0 is a valid PID.. // // _ASSERT(lPID != 0L); _ASSERT(lpszImagePath != NULL); do { if( /*(lPID == 0L) ||*/ (lpszImagePath == NULL) ){ dwLastRet = E_INVALIDARG; break; } // // Get a handle to the process. // hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lPID ); if (hProcess == NULL){ dwLastRet = GetLastError(); break; } // // We do not want to enumerate all the modules in the // process, but only one.. // dwLastRet = EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded ); if(dwLastRet == NULL){ dwLastRet = GetLastError(); break; } // // Get the process name. // dwLastRet = GetModuleBaseName( hProcess, hMod, lpszImagePath, dwBuffSize ); if(dwLastRet == NULL){ dwLastRet = GetLastError(); break; } // // We will store all the strings in // lower case.. // _tcslwr(lpszImagePath); dwLastRet = SUCCESS; }while(FALSE); if(hProcess) CloseHandle(hProcess); return dwLastRet; } DWORD IsValidImage ( /* [in] */ ULONG lPID, /* [in] */ LPCTSTR lpszImageName, /* [out] */ bool *pbValidImage ) { _ASSERTE( lpszImageName != NULL ); DWORD dwLastRet = 0L; TCHAR szImageName[_MAX_PATH+1] = _T(""); __try { if( lpszImageName == NULL ) { return (dwLastRet = -1L); } *pbValidImage = false; dwLastRet = GetImageNameFromPID( lPID, szImageName, _MAX_PATH ); if( dwLastRet != SUCCESS ) return dwLastRet; *pbValidImage = (_tcsicmp( szImageName, lpszImageName) == 0); } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); _ASSERTE(false); } return dwLastRet; } DWORD IsValidProcess ( /* [in] */ ULONG lPID, /* [in] */ LPCTSTR lpszImageName, /* [out] */ bool *pbValidImage ) { return IsValidImage( lPID, lpszImageName, pbValidImage ); } DWORD IsValidService ( /* [in] */ ULONG lPID, /* [in] */ LPCTSTR lpszImageName, /* [out] */ bool *pbValidImage ) { _ASSERTE( lpszImageName != NULL ); DWORD dwLastRet = 0L; TCHAR szImageName[_MAX_PATH+1] = _T(""); LPCTSTR lpszImage = NULL; __try { if( lpszImageName == NULL ) { return (dwLastRet = -1L); } lpszImage = _tcsrchr( lpszImageName, _T('\\') ); if( !lpszImage ) { lpszImage = lpszImageName; } else { lpszImage += 1; } dwLastRet = IsValidImage( lPID, lpszImage, pbValidImage ); } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); _ASSERTE(false); } return dwLastRet; } DWORD GetProcessHandle ( IN ULONG lPid, OUT HANDLE *phProcess ) { DWORD dwLastRet = 0L; __try { // // Get a handle to the process. // dwLastRet = SUCCESS; *phProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lPid ); if (*phProcess == NULL){ dwLastRet = GetLastError(); } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { dwLastRet = GetLastError(); _ASSERTE(false); } return dwLastRet; } HRESULT GetPackageDescription ( IN const long nPid, OUT BSTR &bstrDescription ) { _ASSERTE( nPid != 0 ); HRESULT hr = E_FAIL; IMtsGrp* pMtsGrp = NULL; IUnknown* pUnk = NULL; IMtsEvents* pEvents = NULL; long lPackages = 0; long lPID = 0; long lLp = 0; __try { if( !nPid ) { return (hr = E_INVALIDARG); } //Create the MTS Group object hr = CoInitialize( NULL ); if( FAILED(hr) ) { goto qGetPackageDescription; } hr = CoCreateInstance (CLSID_MtsGrp, NULL, CLSCTX_ALL, IID_IMtsGrp, (void **)&pMtsGrp); if( FAILED(hr) ) { goto qGetPackageDescription; } hr = pMtsGrp->Refresh(); // its important to call this! if( FAILED(hr) ) { goto qGetPackageDescription; } hr = pMtsGrp->get_Count( &lPackages ); if( FAILED(hr) ) { goto qGetPackageDescription; } for (lLp = 0; lLp < lPackages; lLp++) { hr = pMtsGrp->Item(lLp, &pUnk); if( FAILED(hr) ) { goto qGetPackageDescription; } hr = pUnk->QueryInterface(IID_IMtsEvents, (void **)&pEvents); if( FAILED(hr) || !pEvents ) { goto qGetPackageDescription; } if( pUnk ) { pUnk->Release(); pUnk = NULL; } hr = pEvents->GetProcessID( &lPID ); if( FAILED(hr) ) { goto qGetPackageDescription; } if( lPID == nPid ) { // This is the package we are looking for.. hr = pEvents->get_PackageName( &bstrDescription ); if( FAILED(hr) ) { goto qGetPackageDescription; } break; // We got what we were looking for. } if( pEvents ) { pEvents->Release(); pEvents = NULL; } } hr = S_OK; qGetPackageDescription: if( pEvents ) { pEvents->Release(); pEvents = NULL; } if( pUnk ) { pUnk->Release(); pUnk = NULL; } if( pMtsGrp ) { pMtsGrp->Release(); pMtsGrp = NULL; } } __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) { if( pEvents ) { pEvents->Release(); pEvents = NULL; } if( pUnk ) { pUnk->Release(); pUnk = NULL; } if( pMtsGrp ) { pMtsGrp->Release(); pMtsGrp = NULL; } hr = E_UNEXPECTED; _ASSERTE(false); } return hr; } /* EnumServicesStatusEx(..) is not supported on NT 4.0. */ HRESULT IsService_NT4 ( IN UINT nPid, OUT bool *pbIsService ) { _ASSERTE( nPid > 0 ); HRESULT hr = E_FAIL; HANDLE hProcess = NULL; 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; bool isInteractive = FALSE, isService = FALSE; __try { if( nPid <= 0 ) { hr = E_INVALIDARG; goto qIsService; } hr = GetProcessHandle( nPid, &hProcess ); if( FAILED(hr) ) { goto qIsService; } // open the token if( !::OpenProcessToken( hProcess, TOKEN_QUERY, &hProcessToken) ) { hr = HRESULT_FROM_WIN32(GetLastError()); goto qIsService; } // allocate a buffer of default size groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength); if ( !groupInfo ) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } // 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) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } ::LocalFree(groupInfo); groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength); if (groupInfo == NULL) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } if (!GetTokenInformation(hProcessToken, TokenGroups, groupInfo, groupLength, &groupLength)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } } // // 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)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pServiceSid)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto qIsService; } // reset flags isInteractive = FALSE; 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 // isInteractive = TRUE; 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 ). // isService = TRUE; isInteractive = FALSE; break; } } if ( !( isService || 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. // isService = TRUE; } qIsService: if ( pServiceSid ) ::FreeSid( pServiceSid ); if ( pInteractiveSid ) ::FreeSid( pInteractiveSid ); if ( groupInfo ) ::LocalFree( groupInfo ); if ( hProcessToken ) ::CloseHandle( hProcessToken ); if( hProcess ) { CloseHandle( hProcess ); } } __except( EXCEPTION_EXECUTE_HANDLER, 1 ) { hr = E_UNEXPECTED; _ASSERTE(false); } // // BUGBUG: If the function fails, we treat // the process as an app // *pbIsService = isService; return hr; }