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.

287 lines
8.0 KiB

  1. /*******************************************************************************
  2. *
  3. * procs.cpp
  4. *
  5. * implementation of ProcEnumerateProcesses function
  6. *
  7. * copyright notice: Copyright 1997, Citrix Systems Inc.
  8. * Copyright (c) 1998 - 1999 Microsoft Corporation
  9. *
  10. * $Author: BillG $ Don Messerli
  11. *
  12. * $Log: X:\NT\PRIVATE\UTILS\CITRIX\WINUTILS\WINADMIN\VCS\PROCS.CPP $
  13. *
  14. * Rev 1.1 02 Dec 1997 16:30:10 BillG
  15. * alpha update
  16. *
  17. * Rev 1.0 30 Jul 1997 17:12:02 butchd
  18. * Initial revision.
  19. *
  20. *******************************************************************************/
  21. #ifndef UNICODE
  22. #define UNICODE
  23. #endif
  24. //#ifndef _X86_
  25. //#define _X86_
  26. //#endif
  27. #include <nt.h>
  28. #include <ntrtl.h>
  29. #include <nturtl.h>
  30. #include <ntcsrsrv.h>
  31. #include <ntlsa.h>
  32. #include <ntsam.h>
  33. #include <windows.h>
  34. #include <lmaccess.h>
  35. #include <lmserver.h>
  36. #include <lmwksta.h>
  37. #include <lmapibuf.h>
  38. #include <winsta.h>
  39. #include <procs.h>
  40. #define MAX_PROCESSNAME 18
  41. VOID
  42. FetchProcessIDAndImageName(PTS_SYS_PROCESS_INFORMATION ProcessInfo,
  43. PULONG pPID,
  44. LPTSTR pImageName)
  45. {
  46. int i;
  47. TCHAR ImageName[MAX_PROCESSNAME+1];
  48. //
  49. // Set the PID.
  50. //
  51. *pPID = (ULONG)(ULONG_PTR)(ProcessInfo->UniqueProcessId);
  52. //
  53. // Fetch and convert counted UNICODE string into a NULL
  54. // terminated UNICODE string.
  55. //
  56. if( !ProcessInfo->ImageName.Length == 0 )
  57. {
  58. wcsncpy( ImageName,
  59. ProcessInfo->ImageName.Buffer,
  60. min(MAX_PROCESSNAME, ProcessInfo->ImageName.Length/2));
  61. }
  62. ImageName[min(MAX_PROCESSNAME, ProcessInfo->ImageName.Length/2)] = 0;
  63. /*
  64. * We're UNICODE: simply copy the converted ImageName buffer
  65. * into the m_PLObject->m_ImageName field.
  66. */
  67. lstrcpy(pImageName, ImageName);
  68. _wcslwr(pImageName);
  69. }
  70. /*******************************************************************************
  71. *
  72. * EnumerateProcesses - WinFrame helper function
  73. *
  74. * Enumerate all processes in system, passing back one with each call to this
  75. * routine.
  76. *
  77. *
  78. * ENTRY:
  79. * hServer:
  80. * handle of the aimed server
  81. * pEnumToken
  82. * pointer to the current token
  83. * pImageName (output)
  84. * Points to a buffer to store process name in. NOTE: this buffer is expected
  85. * to be at least MAX_PROCESSNAME+1 characters in size.
  86. * pLogonId (output)
  87. * Points to variable to store process LogonId in.
  88. * pPID (output)
  89. * Points to variable to store process PID in.
  90. * ppSID (output)
  91. * Points to a pointer which is set to point to the process' SID on exit.
  92. *
  93. * EXIT:
  94. * TRUE - information for the next process in the system has been placed into
  95. * the referenced PLObject and pSID variables.
  96. * FALSE - if the enumeration is done, GetLastError() will contain the
  97. * ERROR_NO_MORE_ITEMS error code. If another (true error) is
  98. * encountered, that code will be set.
  99. *
  100. ******************************************************************************/
  101. BOOL WINAPI
  102. ProcEnumerateProcesses( HANDLE hServer,
  103. PENUMTOKEN pEnumToken,
  104. LPTSTR pImageName,
  105. PULONG pLogonId,
  106. PULONG pPID,
  107. PSID *ppSID )
  108. {
  109. int i;
  110. PTS_SYS_PROCESS_INFORMATION ProcessInfo;
  111. PCITRIX_PROCESS_INFORMATION CitrixInfo;
  112. if ((pEnumToken == NULL)
  113. || (pImageName == NULL)
  114. || (pLogonId == NULL)
  115. || (pPID == NULL)
  116. || (ppSID == NULL)
  117. )
  118. {
  119. return FALSE;
  120. }
  121. /*
  122. * Check for done with enumeration.
  123. */
  124. if ( pEnumToken->Current == (ULONG)-1 ) {
  125. SetLastError(ERROR_NO_MORE_ITEMS);
  126. if (pEnumToken->bGAP == TRUE) // we used the GAP (GetAllProcesses) interface
  127. {
  128. //
  129. // Free ProcessArray and all child pointers allocated by the client stub.
  130. //
  131. WinStationFreeGAPMemory(GAP_LEVEL_BASIC,
  132. pEnumToken->ProcessArray,
  133. pEnumToken->NumberOfProcesses);
  134. pEnumToken->ProcessArray = NULL;
  135. pEnumToken->NumberOfProcesses = 0;
  136. return(FALSE);
  137. }
  138. else // we used the old Hydra 4 interface
  139. {
  140. WinStationFreeMemory(pEnumToken->pProcessBuffer);
  141. pEnumToken->pProcessBuffer = NULL;
  142. return(FALSE);
  143. }
  144. }
  145. /*
  146. * Check for beginning enumeration.
  147. */
  148. if ( pEnumToken->Current == 0 ) {
  149. //
  150. // Try the new interface first (NT5 server ?)
  151. //
  152. if (WinStationGetAllProcesses( hServer,
  153. GAP_LEVEL_BASIC,
  154. &(pEnumToken->NumberOfProcesses),
  155. (PVOID *)&(pEnumToken->ProcessArray) ) )
  156. {
  157. pEnumToken->bGAP = TRUE;
  158. }
  159. else
  160. {
  161. //
  162. // Check the return code indicating that the interface is not available.
  163. //
  164. DWORD dwError = GetLastError();
  165. if (dwError != RPC_S_PROCNUM_OUT_OF_RANGE)
  166. {
  167. pEnumToken->pProcessBuffer = NULL;
  168. return(FALSE);
  169. }
  170. else // maybe a Hydra 4 server ?
  171. {
  172. if ( WinStationEnumerateProcesses( hServer,
  173. (PVOID *)&(pEnumToken->pProcessBuffer)))
  174. {
  175. pEnumToken->bGAP = FALSE;
  176. }
  177. else
  178. {
  179. DWORD error = GetLastError();
  180. if(pEnumToken->pProcessBuffer != NULL)
  181. {
  182. WinStationFreeMemory(pEnumToken->pProcessBuffer);
  183. pEnumToken->pProcessBuffer = NULL;
  184. }
  185. return(FALSE);
  186. }
  187. }
  188. }
  189. }
  190. if (pEnumToken->bGAP == TRUE)
  191. {
  192. ProcessInfo = (PTS_SYS_PROCESS_INFORMATION)((pEnumToken->ProcessArray)[pEnumToken->Current].pTsProcessInfo);
  193. FetchProcessIDAndImageName(ProcessInfo,pPID,pImageName);
  194. //
  195. // Set the SessionId
  196. //
  197. *pLogonId = ProcessInfo->SessionId;
  198. //
  199. // set the SID
  200. //
  201. *ppSID = (pEnumToken->ProcessArray)[pEnumToken->Current].pSid;
  202. (pEnumToken->Current)++;
  203. if ( (pEnumToken->Current) >= (pEnumToken->NumberOfProcesses) )
  204. {
  205. pEnumToken->Current = (ULONG)-1; // sets the end of enumeration
  206. }
  207. }
  208. else
  209. {
  210. /*
  211. * Parse and store the next process' information.
  212. */
  213. ProcessInfo = (PTS_SYS_PROCESS_INFORMATION)
  214. &(((PUCHAR)(pEnumToken->pProcessBuffer))[pEnumToken->Current]);
  215. FetchProcessIDAndImageName(ProcessInfo,pPID,pImageName);
  216. /*
  217. * Point to the CITRIX_INFORMATION which follows the Threads
  218. */
  219. CitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  220. (((PUCHAR)ProcessInfo) +
  221. SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
  222. (SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)ProcessInfo->NumberOfThreads));
  223. /*
  224. * Fetch the LogonId and point to this SID for the primary
  225. * thread to use (copy).
  226. */
  227. if( CitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
  228. *pLogonId = CitrixInfo->LogonId;
  229. *ppSID = CitrixInfo->ProcessSid;
  230. } else {
  231. *pLogonId = (ULONG)(-1);
  232. *ppSID = NULL;
  233. }
  234. /*
  235. * Increment the total offset count for next call. If this is the
  236. * last process, set the offset to -1 so that next call will indicate
  237. * the end of the enumeration.
  238. */
  239. if ( ProcessInfo->NextEntryOffset != 0 )
  240. (pEnumToken->Current) += ProcessInfo->NextEntryOffset;
  241. else
  242. pEnumToken->Current = (ULONG)-1;
  243. }
  244. return(TRUE);
  245. } // end EnumerateProcesses