Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1426 lines
32 KiB

  1. g// EmExtn.cpp : Defines the entry point for the DLL application.
  2. //
  3. #include "stdafx.h"
  4. #include <Psapi.h>
  5. #include <winsvc.h>
  6. #include <comsvcs.h>
  7. #include "Processes.h"
  8. #define SUCCESS 0
  9. DWORD
  10. InvalidCallback
  11. (
  12. /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc,
  13. /* [in] */ LPARAM lParam,
  14. /* [in] */ LONG nItemNum
  15. )
  16. {
  17. return( lpEnumSrvcsProc( INVALID_PID, NULL, NULL, NULL, lParam, nItemNum ) );
  18. }
  19. DWORD
  20. GetNumberOfRunningApps
  21. (
  22. /* [out] */ DWORD *pdwNumbApps
  23. )
  24. {
  25. DWORD dwLastRet = 0L;
  26. DWORD *pdwPIDs = NULL;
  27. DWORD dwBuffSize = 256L;
  28. UINT nIdx = 0;
  29. bool bIsService = false;
  30. do
  31. {
  32. //
  33. // This loop is used to get all the running PIDs
  34. // in the system. Because we do not know how many
  35. // processes are running, we dynamically increase
  36. // the array size. Limit = 256 DWORDs * 5
  37. //
  38. do {
  39. if(pdwPIDs != NULL){
  40. delete[] pdwPIDs;
  41. pdwPIDs = NULL;
  42. }
  43. dwBuffSize *= (nIdx + 1);
  44. pdwPIDs = new DWORD[dwBuffSize];
  45. if(pdwPIDs == NULL){
  46. dwLastRet = GetLastError();
  47. break;
  48. }
  49. dwLastRet = GetAllPids(
  50. pdwPIDs,
  51. dwBuffSize,
  52. &dwBuffSize
  53. );
  54. }
  55. while(dwLastRet == E_TOOMANY_PROCESSES);
  56. if( dwLastRet == 0 ){
  57. *pdwNumbApps = 0L;
  58. for(UINT i = 0; i < dwBuffSize; ++i)
  59. {
  60. IsService( pdwPIDs[i], &bIsService );
  61. if( bIsService != true ) *pdwNumbApps += 1;
  62. }
  63. }
  64. }
  65. while ( false );
  66. if(pdwPIDs != NULL) {
  67. delete[] pdwPIDs;
  68. pdwPIDs = NULL;
  69. }
  70. return dwLastRet;
  71. }
  72. DWORD
  73. GetAllPids
  74. (
  75. /* [out] */ DWORD adwProcIDs[],
  76. /* [in] */ DWORD dwBuffSize,
  77. /* [out] */ DWORD *pdwNumbProcs
  78. )
  79. {
  80. DWORD dwLastRet = 0L;
  81. _ASSERT(adwProcIDs != NULL);
  82. _ASSERT(dwBuffSize != 0L);
  83. _ASSERT(pdwNumbProcs != NULL);
  84. do
  85. {
  86. if( (adwProcIDs == NULL) ||
  87. (dwBuffSize == 0L) ||
  88. (pdwNumbProcs == 0L)) {
  89. dwLastRet = E_INVALIDARG;
  90. break;
  91. }
  92. //
  93. // Get the list of process identifiers.
  94. //
  95. dwLastRet = (DWORD)EnumProcesses(
  96. adwProcIDs,
  97. dwBuffSize,
  98. pdwNumbProcs);
  99. if(dwLastRet == 0L){
  100. dwLastRet = GetLastError();
  101. break;
  102. }
  103. //
  104. // If both of them are same, it means that
  105. // there may be more PIDs for which there
  106. // is no space..
  107. //
  108. if(dwBuffSize == *pdwNumbProcs){
  109. dwLastRet = ERROR_NOT_ENOUGH_MEMORY;
  110. break;
  111. }
  112. //
  113. // This will give us the number of PIDs
  114. //
  115. (*pdwNumbProcs) = ((*pdwNumbProcs) / sizeof(DWORD));
  116. dwLastRet = 0L;
  117. }
  118. while(FALSE);
  119. return dwLastRet;
  120. }
  121. DWORD
  122. GetNumberOfServices
  123. (
  124. /* [out] */ DWORD *pdwNumbSrvcs,
  125. /* [in] */ DWORD dwServiceType, /* = SERVICE_WIN32 */
  126. /* [in] */ DWORD dwServiceState /* = SERVICE_ACTIVE */
  127. )
  128. {
  129. _ASSERTE( pdwNumbSrvcs != NULL );
  130. DWORD dwLastRet = 0L;
  131. SC_HANDLE scm = NULL;
  132. LPENUM_SERVICE_STATUS status = NULL;
  133. DWORD cbBytesNeeded = 0L,
  134. dwNumbSvcs = 0L,
  135. dwResume = 0L;
  136. ENUM_SERVICE_STATUS aServices[1]; // a-mando, bug ID: 296023
  137. __try {
  138. if( pdwNumbSrvcs == NULL ) { dwLastRet = -1L; goto qGetNumberOfServices; }
  139. scm = OpenSCManager(
  140. NULL,
  141. NULL,
  142. SC_MANAGER_ENUMERATE_SERVICE
  143. );
  144. if( !scm ) { dwLastRet = GetLastError(); goto qGetNumberOfServices; }
  145. *pdwNumbSrvcs = 0L;
  146. if( EnumServicesStatus(
  147. scm,
  148. dwServiceType,
  149. dwServiceState,
  150. aServices, // a-mando, bug ID: 296023
  151. 0,
  152. &cbBytesNeeded,
  153. &dwNumbSvcs,
  154. &dwResume
  155. ) == false ) {
  156. dwLastRet = GetLastError();
  157. }
  158. if( dwLastRet != ERROR_MORE_DATA ) { goto qGetNumberOfServices;}
  159. //
  160. // Allocate space
  161. //
  162. status = (LPENUM_SERVICE_STATUS)LocalAlloc(
  163. LPTR,
  164. cbBytesNeeded
  165. );
  166. if( !status ) { dwLastRet = GetLastError(); goto qGetNumberOfServices; }
  167. //
  168. // Get the status records.
  169. //
  170. dwResume = 0;
  171. dwLastRet = EnumServicesStatus(
  172. scm,
  173. dwServiceType,
  174. dwServiceState,
  175. status,
  176. cbBytesNeeded,
  177. &cbBytesNeeded,
  178. &dwNumbSvcs,
  179. &dwResume
  180. );
  181. if (dwLastRet == 0) { dwLastRet = GetLastError(); goto qGetNumberOfServices; }
  182. *pdwNumbSrvcs = dwNumbSvcs;
  183. dwLastRet = SUCCESS;
  184. qGetNumberOfServices:
  185. if( scm ) CloseServiceHandle( scm );
  186. if( status ) LocalFree( status );
  187. }
  188. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  189. dwLastRet = GetLastError();
  190. if( scm ) CloseServiceHandle( scm );
  191. if( status ) LocalFree( status );
  192. _ASSERTE( false );
  193. }
  194. return dwLastRet;
  195. }
  196. DWORD
  197. GetNumberOfActiveServices
  198. (
  199. /* [out] */ DWORD *pdwNumbActiveSrvcs
  200. )
  201. {
  202. return GetNumberOfServices( pdwNumbActiveSrvcs );
  203. }
  204. DWORD
  205. GetNumberOfInactiveServices
  206. (
  207. /* [out] */ DWORD *pdwNumbInactiveSrvcs
  208. )
  209. {
  210. return GetNumberOfServices( pdwNumbInactiveSrvcs, SERVICE_WIN32, SERVICE_INACTIVE );
  211. }
  212. DWORD
  213. IsService
  214. (
  215. /* [in] */ UINT nPid,
  216. /* [out] */ bool *pbIsService,
  217. /* [out] */ LPTSTR lpszImagePath,
  218. /* [out] */ ULONG cchImagePath,
  219. /* [out] */ LPTSTR lpszServiceShortName,
  220. /* [in] */ ULONG cchServiceShortName,
  221. /* [out] */ LPTSTR lpszServiceDescription,
  222. /* [in] */ ULONG cchServiceDescription
  223. )
  224. {
  225. DWORD dwRet = 0L;
  226. OSVERSIONINFO osvi;
  227. ZeroMemory( (void *)&osvi, sizeof(OSVERSIONINFO) );
  228. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  229. if( !GetVersionEx (&osvi) ) {
  230. return (dwRet = GetLastError());
  231. }
  232. if( osvi.dwPlatformId & VER_PLATFORM_WIN32_NT ) {
  233. if( osvi.dwMajorVersion == 4 ) {
  234. // && osvi.dwMinorVersion == 0 ) { // we will not look for the minor version.
  235. IsService_NT4( nPid, pbIsService );
  236. }
  237. else if( osvi.dwMajorVersion == 5 ) {
  238. // && osvi.dwMinorVersion == 0 ) {
  239. IsService_NT5(
  240. nPid,
  241. pbIsService,
  242. lpszImagePath,
  243. cchImagePath,
  244. lpszServiceShortName,
  245. cchServiceShortName,
  246. lpszServiceDescription,
  247. cchServiceDescription
  248. );
  249. }
  250. }
  251. return dwRet;
  252. }
  253. DWORD
  254. IsService_NT5
  255. (
  256. /* [in] */ UINT nPid,
  257. /* [out] */ bool *pbIsService,
  258. /* [out] */ LPTSTR lpszImagePath,
  259. /* [out] */ ULONG cchImagePath,
  260. /* [out] */ LPTSTR lpszServiceShortName,
  261. /* [in] */ ULONG cchServiceShortName,
  262. /* [out] */ LPTSTR lpszServiceDescription,
  263. /* [in] */ ULONG cchServiceDescription
  264. )
  265. {
  266. _ASSERTE ( pbIsService != NULL );
  267. bool bIsService = false;
  268. DWORD dwLastRet = 0L;
  269. int i = 0;
  270. SC_HANDLE scm = NULL;
  271. ENUM_SERVICE_STATUS_PROCESS *status = NULL;
  272. DWORD numServices = 0L,
  273. sizeNeeded = 0L,
  274. resume = 0L;
  275. __try
  276. {
  277. if( pbIsService == NULL ) { dwLastRet = -1L; goto qIsService; }
  278. //
  279. // Open a connection to the SCM
  280. //
  281. scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
  282. if ( !scm ){ dwLastRet = GetLastError(); goto qIsService; }
  283. //
  284. // Get the number of bytes to allocate
  285. //
  286. resume = 0;
  287. if( EnumServicesStatusEx(
  288. scm,
  289. SC_ENUM_PROCESS_INFO,
  290. SERVICE_WIN32, // We won't debug drivers
  291. SERVICE_ACTIVE,
  292. 0,
  293. 0,
  294. &sizeNeeded,
  295. &numServices,
  296. &resume,
  297. NULL
  298. ) == 0 ) {
  299. dwLastRet = GetLastError();
  300. //
  301. // If it is any error other than this,
  302. // we won't continue..
  303. //
  304. if(dwLastRet != ERROR_MORE_DATA) goto qIsService;
  305. }
  306. //
  307. // Allocate space
  308. //
  309. status = (ENUM_SERVICE_STATUS_PROCESS *)LocalAlloc(
  310. LPTR,
  311. sizeNeeded
  312. );
  313. if( status == NULL ){ dwLastRet = GetLastError(); goto qIsService; }
  314. //
  315. // Get the status records.
  316. //
  317. resume = 0;
  318. if( EnumServicesStatusEx(
  319. scm,
  320. SC_ENUM_PROCESS_INFO,
  321. SERVICE_WIN32, // We won't debug drivers
  322. SERVICE_ACTIVE,
  323. (LPBYTE)status,
  324. sizeNeeded,
  325. &sizeNeeded,
  326. &numServices,
  327. &resume,
  328. NULL
  329. ) == 0 ) {
  330. dwLastRet = GetLastError(); goto qIsService;
  331. }
  332. *pbIsService = false;
  333. for (i = 0; i < (int)numServices; i++)
  334. {
  335. if( status[i].ServiceStatusProcess.dwProcessId == nPid ) {
  336. *pbIsService = true;
  337. if(lpszImagePath)
  338. { _tcsncpy( lpszImagePath, _T(""), cchImagePath ); }
  339. if(lpszServiceShortName)
  340. { _tcsncpy( lpszServiceShortName, status[i].lpServiceName, cchServiceShortName ); }
  341. if(lpszServiceDescription)
  342. { _tcsncpy( lpszServiceDescription, status[i].lpDisplayName, cchServiceDescription ); }
  343. break;
  344. }
  345. }
  346. dwLastRet = SUCCESS;
  347. qIsService:
  348. if( scm ) { CloseServiceHandle(scm); scm = NULL; }
  349. if( status ){ LocalFree(status); status = NULL; }
  350. }
  351. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  352. dwLastRet = GetLastError();
  353. if( scm ) { CloseServiceHandle( scm ); scm = NULL; }
  354. if( status ){ LocalFree(status); status = NULL; }
  355. _ASSERTE( false );
  356. }
  357. return dwLastRet;
  358. }
  359. DWORD
  360. GetServiceInfo
  361. (
  362. /* [in] */ UINT nPid,
  363. /* [out] */ LPTSTR lpszImagePath,
  364. /* [out] */ ULONG cchImagePath,
  365. /* [out] */ LPTSTR lpszServiceShortName,
  366. /* [in] */ ULONG cchServiceShortName,
  367. /* [out] */ LPTSTR lpszServiceDescription,
  368. /* [in] */ ULONG cchServiceDescription
  369. )
  370. {
  371. bool bIsService = false;
  372. return IsService(
  373. nPid,
  374. &bIsService,
  375. lpszImagePath,
  376. cchImagePath,
  377. lpszServiceShortName,
  378. cchServiceShortName,
  379. lpszServiceDescription,
  380. cchServiceDescription
  381. );
  382. }
  383. DWORD
  384. EnumRunningProcesses
  385. (
  386. /* [in] */ ENUMPROCSANDSERVICES lpEnumRunProc,
  387. /* [in] */ LPARAM lParam,
  388. /* [in] */ UINT nStartIndex
  389. )
  390. {
  391. // Nothing to do if this is NULL..
  392. _ASSERT(lpEnumRunProc != NULL);
  393. DWORD dwLastRet = 0L;
  394. DWORD dwBuffSize = 256L;
  395. DWORD *pdwPIDs = NULL;
  396. UINT nIdx = 0;
  397. UINT nItemNum = nStartIndex;
  398. bool bService = FALSE;
  399. TCHAR szShortName[_MAX_PATH] = _T("");
  400. TCHAR szImagePath[_MAX_PATH] = _T("");
  401. __try
  402. {
  403. if( !lpEnumRunProc ){ dwLastRet = E_INVALIDARG; goto qEnumRunningProcesses; }
  404. //
  405. // This loop is used to get all the running PIDs
  406. // in the system. Because we do not know how many
  407. // processes are running, we dynamically increase
  408. // the array size. Limit = 256 DWORDs * 5
  409. //
  410. do{
  411. if(pdwPIDs != NULL){
  412. delete[] pdwPIDs;
  413. pdwPIDs = NULL;
  414. }
  415. dwBuffSize *= (nIdx + 1);
  416. pdwPIDs = new DWORD[dwBuffSize];
  417. if(pdwPIDs == NULL){
  418. dwLastRet = GetLastError();
  419. break;
  420. }
  421. dwLastRet = GetAllPids(
  422. pdwPIDs,
  423. dwBuffSize,
  424. &dwBuffSize
  425. );
  426. }
  427. while(dwLastRet == E_TOOMANY_PROCESSES);
  428. //
  429. // There are more processes than we
  430. // can handle..
  431. //
  432. if( dwLastRet != E_TOOMANY_PROCESSES && dwLastRet != 0){ goto qEnumRunningProcesses; }
  433. //
  434. // If everything goes alright, call the Callback procedure
  435. // once for each PID (or till the procedure returns FALSE)
  436. // with the PID and the corresponding Image path..
  437. //
  438. nIdx = -1;
  439. while(++nIdx < dwBuffSize){
  440. dwLastRet = SUCCESS;
  441. IsService( pdwPIDs[nIdx], &bService );
  442. if( bService == true ) continue; // we won't add services into the list..
  443. // This may fail for some procs like the system process.
  444. if( GetImageNameFromPID( pdwPIDs[nIdx], szImagePath, _MAX_PATH )) {
  445. if(lpEnumRunProc(INVALID_PID, NULL, NULL, NULL, lParam, nItemNum++) == FALSE){
  446. dwLastRet = FALSE;
  447. goto qEnumRunningProcesses; // Stop when the Callback procedure returns FALSE.
  448. }
  449. }
  450. else {
  451. BSTR bstrDesc = _T("");
  452. if( IsPackage( szImagePath ) ) {
  453. GetPackageDescription( pdwPIDs[nIdx], bstrDesc );
  454. }
  455. if(lpEnumRunProc(pdwPIDs[nIdx], szImagePath, _T(""), bstrDesc, lParam, nItemNum++ ) == FALSE) {
  456. dwLastRet = FALSE;
  457. goto qEnumRunningProcesses; // Stop when the Callback procedure returns FALSE.
  458. }
  459. }
  460. }
  461. dwLastRet = SUCCESS;
  462. qEnumRunningProcesses:
  463. //
  464. // Clean up memory allocated for PIDs array.
  465. //
  466. if( pdwPIDs ) { delete[] pdwPIDs; pdwPIDs = NULL; }
  467. }
  468. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  469. dwLastRet = GetLastError();
  470. if( pdwPIDs ) { delete[] pdwPIDs; pdwPIDs = NULL; }
  471. _ASSERTE( false );
  472. }
  473. return dwLastRet;
  474. }
  475. BOOL
  476. IsPackage
  477. (
  478. IN LPTSTR lpszImageName
  479. )
  480. {
  481. _ASSERTE( lpszImageName != NULL );
  482. BOOL bRet = false;
  483. const DWORD cTemplates = 2;
  484. LPCTSTR szTemplate [cTemplates];
  485. __try
  486. {
  487. if( !lpszImageName ) { return (bRet = false); }
  488. _tcslwr( lpszImageName );
  489. szTemplate[0] = _T("dllhost.exe");
  490. szTemplate[1] = _T("mts.exe");
  491. for( int i = 0; i < cTemplates; i++ ) {
  492. if( _tcsstr( lpszImageName, szTemplate[i] ) != NULL ) {
  493. bRet = true;
  494. break;
  495. }
  496. }
  497. }
  498. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  499. bRet = false;
  500. _ASSERTE( false );
  501. }
  502. return bRet;
  503. }
  504. DWORD
  505. EnumRunningServices
  506. (
  507. /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc,
  508. /* [in] */ LPARAM lParam,
  509. /* [in] */ UINT nStartIndex
  510. )
  511. {
  512. return EnumServices( lpEnumSrvcsProc, lParam, SERVICE_ACTIVE, nStartIndex );
  513. }
  514. DWORD
  515. EnumStoppedServices
  516. (
  517. /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc,
  518. /* [in] */ LPARAM lParam,
  519. /* [in] */ UINT nStartIndex
  520. )
  521. {
  522. return EnumServices( lpEnumSrvcsProc, lParam, SERVICE_INACTIVE, nStartIndex );
  523. }
  524. DWORD
  525. EnumServices
  526. (
  527. /* [in] */ ENUMPROCSANDSERVICES lpEnumSrvcsProc,
  528. /* [in] */ LPARAM lParam,
  529. /* [in] */ DWORD dwSrvcState,
  530. /* [in] */ UINT nStartIndex
  531. )
  532. {
  533. _ASSERTE ( lpEnumSrvcsProc != NULL );
  534. bool bIsService = false;
  535. DWORD dwLastRet = 0L;
  536. int i = 0;
  537. SC_HANDLE scm = NULL,
  538. service = NULL;
  539. LPQUERY_SERVICE_CONFIG buffer = NULL;
  540. ENUM_SERVICE_STATUS_PROCESS *status = NULL;
  541. DWORD numServices = 0L,
  542. sizeNeeded = 0L,
  543. resume = 0L;
  544. UINT nItemNum = nStartIndex;
  545. __try
  546. {
  547. if( lpEnumSrvcsProc == NULL ) { dwLastRet = -1L; goto qEnumServices; }
  548. //
  549. // Open a connection to the SCM
  550. //
  551. scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
  552. if ( !scm ){ dwLastRet = GetLastError(); goto qEnumServices; }
  553. //
  554. // Get the number of bytes to allocate
  555. //
  556. resume = 0;
  557. if( EnumServicesStatusEx(
  558. scm,
  559. SC_ENUM_PROCESS_INFO,
  560. SERVICE_WIN32, // We won't debug drivers
  561. dwSrvcState,
  562. 0,
  563. 0,
  564. &sizeNeeded,
  565. &numServices,
  566. &resume,
  567. NULL
  568. ) == 0 ) {
  569. dwLastRet = GetLastError();
  570. //
  571. // If it is any error other than this,
  572. // we won't continue..
  573. //
  574. if(dwLastRet != ERROR_MORE_DATA) goto qEnumServices;
  575. }
  576. //
  577. // Allocate space
  578. //
  579. status = (ENUM_SERVICE_STATUS_PROCESS *)LocalAlloc(
  580. LPTR,
  581. sizeNeeded
  582. );
  583. if( status == NULL ){ dwLastRet = GetLastError(); goto qEnumServices; }
  584. //
  585. // Get the status records.
  586. //
  587. resume = 0;
  588. if( EnumServicesStatusEx(
  589. scm,
  590. SC_ENUM_PROCESS_INFO,
  591. SERVICE_WIN32, // We won't debug drivers
  592. dwSrvcState,
  593. (LPBYTE)status,
  594. sizeNeeded,
  595. &sizeNeeded,
  596. &numServices,
  597. &resume,
  598. NULL
  599. ) == 0 ) {
  600. dwLastRet = GetLastError(); goto qEnumServices;
  601. }
  602. for (i = 0; i < (int)numServices; i++)
  603. {
  604. if(service){
  605. CloseServiceHandle(service);
  606. service = NULL;
  607. }
  608. service = OpenService( scm,
  609. status[i].lpServiceName,
  610. SERVICE_QUERY_CONFIG
  611. );
  612. if (!service) {
  613. dwLastRet = GetLastError();
  614. InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ );
  615. continue;
  616. } //goto qEnumServices; }
  617. //
  618. // Find out how big the buffer needs to be
  619. //
  620. dwLastRet = QueryServiceConfig(
  621. service,
  622. 0,
  623. 0,
  624. &sizeNeeded
  625. );
  626. if(dwLastRet == 0){
  627. dwLastRet = GetLastError();
  628. //
  629. // If it is any error other than
  630. // this, we won't continue..
  631. //
  632. if(dwLastRet != ERROR_INSUFFICIENT_BUFFER) {
  633. InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ );
  634. continue;
  635. }
  636. }
  637. //
  638. // Allocate space for the buffer
  639. //
  640. buffer = (LPQUERY_SERVICE_CONFIG)
  641. LocalAlloc(
  642. LPTR,
  643. sizeNeeded
  644. );
  645. //
  646. // Get Buffer
  647. //
  648. dwLastRet = QueryServiceConfig(
  649. service,
  650. buffer,
  651. sizeNeeded,
  652. &sizeNeeded
  653. );
  654. if (dwLastRet == 0){
  655. dwLastRet = GetLastError();
  656. InvalidCallback( lpEnumSrvcsProc, lParam, nItemNum++ );
  657. continue;
  658. }
  659. _tcslwr(buffer->lpBinaryPathName);
  660. if(lpEnumSrvcsProc(
  661. status[i].ServiceStatusProcess.dwProcessId,
  662. buffer->lpBinaryPathName,
  663. status[i].lpServiceName,
  664. status[i].lpDisplayName,
  665. lParam,
  666. nItemNum++
  667. ) == FALSE) {
  668. dwLastRet = FALSE;
  669. goto qEnumServices; // Stop when the Callback procedure returns FALSE.
  670. }
  671. //
  672. // CleanUp
  673. //
  674. if(buffer != NULL){
  675. LocalFree(buffer);
  676. buffer = NULL;
  677. }
  678. }
  679. dwLastRet = SUCCESS;
  680. qEnumServices:
  681. if( scm ) { CloseServiceHandle(scm); scm = NULL; }
  682. if( status ){ LocalFree(status); status = NULL; }
  683. }
  684. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  685. dwLastRet = GetLastError();
  686. if( scm ) { CloseServiceHandle( scm ); scm = NULL; }
  687. if( status ){ LocalFree(status); status = NULL; }
  688. _ASSERTE( false );
  689. }
  690. return dwLastRet;
  691. }
  692. DWORD
  693. StartServiceAndGetPid
  694. (
  695. IN LPCTSTR lpszServiceShortName,
  696. OUT UINT *pnPid
  697. )
  698. {
  699. _ASSERTE(lpszServiceShortName != NULL);
  700. DWORD dwLastRet = 0L;
  701. DWORD dwBytesNeeded = 0L;
  702. SC_HANDLE scm = NULL,
  703. service = NULL;
  704. SERVICE_STATUS_PROCESS stInfo;
  705. do
  706. {
  707. //
  708. // Open a connection to the SCM
  709. //
  710. scm = OpenSCManager(0, 0, GENERIC_EXECUTE | STANDARD_RIGHTS_REQUIRED | SC_MANAGER_ENUMERATE_SERVICE);
  711. if (!scm){
  712. dwLastRet = GetLastError();
  713. break;
  714. }
  715. service = OpenService( scm, lpszServiceShortName, GENERIC_EXECUTE | STANDARD_RIGHTS_REQUIRED | SC_MANAGER_ENUMERATE_SERVICE );
  716. if (!service){
  717. dwLastRet = GetLastError();
  718. break;
  719. }
  720. if( StartService( service, 0L, NULL ) == 0 ) {
  721. dwLastRet = GetLastError();
  722. break;
  723. }
  724. if( QueryServiceStatusEx(
  725. service,
  726. SC_STATUS_PROCESS_INFO,
  727. (LPBYTE) &stInfo,
  728. sizeof stInfo,
  729. &dwBytesNeeded
  730. ) == 0 ) {
  731. dwLastRet = GetLastError();
  732. break;
  733. }
  734. //
  735. // Successful..
  736. //
  737. *pnPid = stInfo.dwProcessId;
  738. dwLastRet = 0L;
  739. }
  740. while(FALSE);
  741. if(scm){
  742. CloseServiceHandle(scm);
  743. scm = NULL;
  744. }
  745. if(service){
  746. CloseServiceHandle(service);
  747. service = NULL;
  748. }
  749. return dwLastRet;
  750. }
  751. BOOL
  752. IsImageRunning
  753. (
  754. /* [in] */ ULONG lPID
  755. )
  756. {
  757. bool bRet = FALSE;
  758. HANDLE hProcess = ::OpenProcess(
  759. PROCESS_QUERY_INFORMATION,
  760. FALSE,
  761. lPID
  762. );
  763. if(hProcess != NULL){
  764. CloseHandle(hProcess);
  765. bRet = TRUE;
  766. }
  767. return bRet;
  768. }
  769. DWORD
  770. GetImageNameFromPID
  771. (
  772. /* [in] */ ULONG lPID,
  773. /* [out] */ LPTSTR lpszImagePath,
  774. /* [in] */ DWORD dwBuffSize
  775. )
  776. {
  777. DWORD dwLastRet = S_OK;
  778. HANDLE hProcess = NULL;
  779. HMODULE hMod = NULL;
  780. DWORD cbNeeded = 0L;
  781. //
  782. // 0 is a valid PID..
  783. //
  784. // _ASSERT(lPID != 0L);
  785. _ASSERT(lpszImagePath != NULL);
  786. do
  787. {
  788. if( /*(lPID == 0L) ||*/
  789. (lpszImagePath == NULL) ){
  790. dwLastRet = E_INVALIDARG;
  791. break;
  792. }
  793. //
  794. // Get a handle to the process.
  795. //
  796. hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
  797. PROCESS_VM_READ,
  798. FALSE,
  799. lPID
  800. );
  801. if (hProcess == NULL){
  802. dwLastRet = GetLastError();
  803. break;
  804. }
  805. //
  806. // We do not want to enumerate all the modules in the
  807. // process, but only one..
  808. //
  809. dwLastRet = EnumProcessModules(
  810. hProcess,
  811. &hMod,
  812. sizeof(hMod),
  813. &cbNeeded
  814. );
  815. if(dwLastRet == NULL){
  816. dwLastRet = GetLastError();
  817. break;
  818. }
  819. //
  820. // Get the process name.
  821. //
  822. dwLastRet = GetModuleBaseName(
  823. hProcess,
  824. hMod,
  825. lpszImagePath,
  826. dwBuffSize
  827. );
  828. if(dwLastRet == NULL){
  829. dwLastRet = GetLastError();
  830. break;
  831. }
  832. //
  833. // We will store all the strings in
  834. // lower case..
  835. //
  836. _tcslwr(lpszImagePath);
  837. dwLastRet = SUCCESS;
  838. }while(FALSE);
  839. if(hProcess) CloseHandle(hProcess);
  840. return dwLastRet;
  841. }
  842. DWORD
  843. IsValidImage
  844. (
  845. /* [in] */ ULONG lPID,
  846. /* [in] */ LPCTSTR lpszImageName,
  847. /* [out] */ bool *pbValidImage
  848. )
  849. {
  850. _ASSERTE( lpszImageName != NULL );
  851. DWORD dwLastRet = 0L;
  852. TCHAR szImageName[_MAX_PATH+1] = _T("");
  853. __try
  854. {
  855. if( lpszImageName == NULL ) {
  856. return (dwLastRet = -1L);
  857. }
  858. *pbValidImage = false;
  859. dwLastRet = GetImageNameFromPID( lPID, szImageName, _MAX_PATH );
  860. if( dwLastRet != SUCCESS ) return dwLastRet;
  861. *pbValidImage = (_tcsicmp( szImageName, lpszImageName) == 0);
  862. }
  863. __except ( EXCEPTION_EXECUTE_HANDLER, 1 )
  864. {
  865. dwLastRet = GetLastError();
  866. _ASSERTE(false);
  867. }
  868. return dwLastRet;
  869. }
  870. DWORD
  871. IsValidProcess
  872. (
  873. /* [in] */ ULONG lPID,
  874. /* [in] */ LPCTSTR lpszImageName,
  875. /* [out] */ bool *pbValidImage
  876. )
  877. {
  878. return IsValidImage( lPID, lpszImageName, pbValidImage );
  879. }
  880. DWORD
  881. IsValidService
  882. (
  883. /* [in] */ ULONG lPID,
  884. /* [in] */ LPCTSTR lpszImageName,
  885. /* [out] */ bool *pbValidImage
  886. )
  887. {
  888. _ASSERTE( lpszImageName != NULL );
  889. DWORD dwLastRet = 0L;
  890. TCHAR szImageName[_MAX_PATH+1] = _T("");
  891. LPCTSTR lpszImage = NULL;
  892. __try
  893. {
  894. if( lpszImageName == NULL ) {
  895. return (dwLastRet = -1L);
  896. }
  897. lpszImage = _tcsrchr( lpszImageName, _T('\\') );
  898. if( !lpszImage ) { lpszImage = lpszImageName; }
  899. else { lpszImage += 1; }
  900. dwLastRet = IsValidImage( lPID, lpszImage, pbValidImage );
  901. }
  902. __except ( EXCEPTION_EXECUTE_HANDLER, 1 )
  903. {
  904. dwLastRet = GetLastError();
  905. _ASSERTE(false);
  906. }
  907. return dwLastRet;
  908. }
  909. DWORD
  910. GetProcessHandle
  911. (
  912. IN ULONG lPid,
  913. OUT HANDLE *phProcess
  914. )
  915. {
  916. DWORD dwLastRet = 0L;
  917. __try
  918. {
  919. //
  920. // Get a handle to the process.
  921. //
  922. dwLastRet = SUCCESS;
  923. *phProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
  924. PROCESS_VM_READ,
  925. FALSE,
  926. lPid
  927. );
  928. if (*phProcess == NULL){
  929. dwLastRet = GetLastError();
  930. }
  931. }
  932. __except ( EXCEPTION_EXECUTE_HANDLER, 1 )
  933. {
  934. dwLastRet = GetLastError();
  935. _ASSERTE(false);
  936. }
  937. return dwLastRet;
  938. }
  939. HRESULT
  940. GetPackageDescription
  941. (
  942. IN const long nPid,
  943. OUT BSTR &bstrDescription
  944. )
  945. {
  946. _ASSERTE( nPid != 0 );
  947. HRESULT hr = E_FAIL;
  948. IMtsGrp* pMtsGrp = NULL;
  949. IUnknown* pUnk = NULL;
  950. IMtsEvents* pEvents = NULL;
  951. long lPackages = 0;
  952. long lPID = 0;
  953. long lLp = 0;
  954. __try
  955. {
  956. if( !nPid ) { return (hr = E_INVALIDARG); }
  957. //Create the MTS Group object
  958. hr = CoInitialize( NULL );
  959. if( FAILED(hr) ) { goto qGetPackageDescription; }
  960. hr = CoCreateInstance (CLSID_MtsGrp, NULL, CLSCTX_ALL, IID_IMtsGrp, (void **)&pMtsGrp);
  961. if( FAILED(hr) ) { goto qGetPackageDescription; }
  962. hr = pMtsGrp->Refresh(); // its important to call this!
  963. if( FAILED(hr) ) { goto qGetPackageDescription; }
  964. hr = pMtsGrp->get_Count( &lPackages );
  965. if( FAILED(hr) ) { goto qGetPackageDescription; }
  966. for (lLp = 0; lLp < lPackages; lLp++)
  967. {
  968. hr = pMtsGrp->Item(lLp, &pUnk);
  969. if( FAILED(hr) ) { goto qGetPackageDescription; }
  970. hr = pUnk->QueryInterface(IID_IMtsEvents, (void **)&pEvents);
  971. if( FAILED(hr) || !pEvents ) { goto qGetPackageDescription; }
  972. if( pUnk ) { pUnk->Release(); pUnk = NULL; }
  973. hr = pEvents->GetProcessID( &lPID );
  974. if( FAILED(hr) ) { goto qGetPackageDescription; }
  975. if( lPID == nPid ) { // This is the package we are looking for..
  976. hr = pEvents->get_PackageName( &bstrDescription );
  977. if( FAILED(hr) ) { goto qGetPackageDescription; }
  978. break; // We got what we were looking for.
  979. }
  980. if( pEvents ) { pEvents->Release(); pEvents = NULL; }
  981. }
  982. hr = S_OK;
  983. qGetPackageDescription:
  984. if( pEvents ) { pEvents->Release(); pEvents = NULL; }
  985. if( pUnk ) { pUnk->Release(); pUnk = NULL; }
  986. if( pMtsGrp ) { pMtsGrp->Release(); pMtsGrp = NULL; }
  987. }
  988. __except ( EXCEPTION_EXECUTE_HANDLER, 1 )
  989. {
  990. if( pEvents ) { pEvents->Release(); pEvents = NULL; }
  991. if( pUnk ) { pUnk->Release(); pUnk = NULL; }
  992. if( pMtsGrp ) { pMtsGrp->Release(); pMtsGrp = NULL; }
  993. hr = E_UNEXPECTED;
  994. _ASSERTE(false);
  995. }
  996. return hr;
  997. }
  998. /*
  999. EnumServicesStatusEx(..) is not supported on NT 4.0.
  1000. <http://www.mvps.org/win32/security/is_svc.html>
  1001. */
  1002. HRESULT
  1003. IsService_NT4
  1004. (
  1005. IN UINT nPid,
  1006. OUT bool *pbIsService
  1007. )
  1008. {
  1009. _ASSERTE( nPid > 0 );
  1010. HRESULT hr = E_FAIL;
  1011. HANDLE hProcess = NULL;
  1012. HANDLE hProcessToken = NULL;
  1013. DWORD groupLength = 50;
  1014. PTOKEN_GROUPS groupInfo = NULL;
  1015. SID_IDENTIFIER_AUTHORITY siaNt = SECURITY_NT_AUTHORITY;
  1016. PSID pInteractiveSid = NULL;
  1017. PSID pServiceSid = NULL;
  1018. DWORD dwRet = NO_ERROR;
  1019. DWORD ndx;
  1020. bool isInteractive = FALSE,
  1021. isService = FALSE;
  1022. __try
  1023. {
  1024. if( nPid <= 0 ) { hr = E_INVALIDARG; goto qIsService; }
  1025. hr = GetProcessHandle( nPid, &hProcess );
  1026. if( FAILED(hr) ) { goto qIsService; }
  1027. // open the token
  1028. if( !::OpenProcessToken( hProcess, TOKEN_QUERY, &hProcessToken) ) {
  1029. hr = HRESULT_FROM_WIN32(GetLastError());
  1030. goto qIsService;
  1031. }
  1032. // allocate a buffer of default size
  1033. groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength);
  1034. if ( !groupInfo ) {
  1035. hr = HRESULT_FROM_WIN32( GetLastError() );
  1036. goto qIsService;
  1037. }
  1038. // try to get the info
  1039. if (!::GetTokenInformation(
  1040. hProcessToken,
  1041. TokenGroups,
  1042. groupInfo,
  1043. groupLength,
  1044. &groupLength
  1045. )
  1046. ) {
  1047. // if buffer was too small, allocate to proper size, otherwise error
  1048. if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1049. hr = HRESULT_FROM_WIN32( GetLastError() );
  1050. goto qIsService;
  1051. }
  1052. ::LocalFree(groupInfo);
  1053. groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength);
  1054. if (groupInfo == NULL) {
  1055. hr = HRESULT_FROM_WIN32( GetLastError() );
  1056. goto qIsService;
  1057. }
  1058. if (!GetTokenInformation(hProcessToken, TokenGroups,
  1059. groupInfo, groupLength, &groupLength)) {
  1060. hr = HRESULT_FROM_WIN32( GetLastError() );
  1061. goto qIsService;
  1062. }
  1063. }
  1064. //
  1065. // We now know the groups associated with this token. We want
  1066. // to look to see if the interactive group is active in the
  1067. // token, and if so, we know that this is an interactive process.
  1068. //
  1069. // We also look for the "service" SID, and if it's present,
  1070. // we know we're a service.
  1071. //
  1072. // The service SID will be present iff the service is running in a
  1073. // user account (and was invoked by the service controller).
  1074. //
  1075. // create comparison sids
  1076. if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_INTERACTIVE_RID,
  1077. 0, 0, 0, 0, 0, 0, 0, &pInteractiveSid)) {
  1078. hr = HRESULT_FROM_WIN32( GetLastError() );
  1079. goto qIsService;
  1080. }
  1081. if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_SERVICE_RID,
  1082. 0, 0, 0, 0, 0, 0, 0, &pServiceSid)) {
  1083. hr = HRESULT_FROM_WIN32( GetLastError() );
  1084. goto qIsService;
  1085. }
  1086. // reset flags
  1087. isInteractive = FALSE;
  1088. isService = FALSE;
  1089. // try to match sids
  1090. for (ndx = 0; ndx < groupInfo->GroupCount ; ndx += 1)
  1091. {
  1092. SID_AND_ATTRIBUTES sanda = groupInfo->Groups[ndx];
  1093. PSID pSid = sanda.Sid;
  1094. //
  1095. // Check to see if the group we're looking at is one of
  1096. // the two groups we're interested in.
  1097. //
  1098. if (::EqualSid(pSid, pInteractiveSid))
  1099. {
  1100. //
  1101. // This process has the Interactive SID in its
  1102. // token. This means that the process is running as
  1103. // a console process
  1104. //
  1105. isInteractive = TRUE;
  1106. isService = FALSE;
  1107. break;
  1108. }
  1109. else if (::EqualSid(pSid, pServiceSid))
  1110. {
  1111. //
  1112. // This process has the Service SID in its
  1113. // token. This means that the process is running as
  1114. // a service running in a user account ( not local system ).
  1115. //
  1116. isService = TRUE;
  1117. isInteractive = FALSE;
  1118. break;
  1119. }
  1120. }
  1121. if ( !( isService || isInteractive ) )
  1122. {
  1123. //
  1124. // Neither Interactive or Service was present in the current
  1125. // users token, This implies that the process is running as
  1126. // a service, most likely running as LocalSystem.
  1127. //
  1128. isService = TRUE;
  1129. }
  1130. qIsService:
  1131. if ( pServiceSid )
  1132. ::FreeSid( pServiceSid );
  1133. if ( pInteractiveSid )
  1134. ::FreeSid( pInteractiveSid );
  1135. if ( groupInfo )
  1136. ::LocalFree( groupInfo );
  1137. if ( hProcessToken )
  1138. ::CloseHandle( hProcessToken );
  1139. if( hProcess ) { CloseHandle( hProcess ); }
  1140. }
  1141. __except( EXCEPTION_EXECUTE_HANDLER, 1 )
  1142. {
  1143. hr = E_UNEXPECTED;
  1144. _ASSERTE(false);
  1145. }
  1146. //
  1147. // BUGBUG: If the function fails, we treat
  1148. // the process as an app
  1149. //
  1150. *pbIsService = isService;
  1151. return hr;
  1152. }