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.

764 lines
23 KiB

  1. /*******************************************************************************
  2. * process.c
  3. *
  4. * Published Terminal Server APIs
  5. *
  6. * - process routines
  7. *
  8. * Copyright 1998, Citrix Systems Inc.
  9. * Copyright (C) 1997-1999 Microsoft Corp.
  10. /******************************************************************************/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <ntddkbd.h>
  15. #include <ntddmou.h>
  16. #include <windows.h>
  17. #include <winbase.h>
  18. #include <winerror.h>
  19. #include <allproc.h>
  20. #if(WINVER >= 0x0500)
  21. #include <ntstatus.h>
  22. #include <winsta.h>
  23. #else
  24. #include <citrix\cxstatus.h>
  25. #include <citrix\winsta.h>
  26. #endif
  27. #include <utildll.h>
  28. #include <stdio.h>
  29. #include <stdarg.h>
  30. #include <wtsapi32.h>
  31. /*=============================================================================
  32. == External procedures defined
  33. =============================================================================*/
  34. BOOL WINAPI WTSEnumerateProcessesW( HANDLE, DWORD, DWORD, PWTS_PROCESS_INFOW *, DWORD * );
  35. BOOL WINAPI WTSEnumerateProcessesA( HANDLE, DWORD, DWORD, PWTS_PROCESS_INFOA *, DWORD * );
  36. BOOL WINAPI WTSTerminateProcess( HANDLE, DWORD, DWORD );
  37. /*=============================================================================
  38. == Procedures used
  39. =============================================================================*/
  40. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  41. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  42. /*=============================================================================
  43. * Internal function
  44. =============================================================================*/
  45. BOOL
  46. GetProcessSid(HANDLE Server,
  47. HANDLE hUniqueProcessId,
  48. LARGE_INTEGER ProcessStartTime,
  49. PBYTE * pProcessUserSid //Return the SID (allocated here..)
  50. );
  51. /*=======================================================================
  52. * Private structure definitions
  53. *=========================================================================*/
  54. typedef struct _SID_INFO {
  55. struct _SID_INFO * pNext;
  56. PBYTE pSid;
  57. } SID_INFO;
  58. /****************************************************************************
  59. *
  60. * WTSEnumerateProcessesW (UNICODE)
  61. *
  62. * Returns a list of Terminal Server Processes on the specified server
  63. *
  64. * ENTRY:
  65. * hServer (input)
  66. * Handle to a Terminal server (or WTS_CURRENT_SERVER)
  67. * Reserved (input)
  68. * Must be zero
  69. * Version (input)
  70. * Version of the enumeration request (must be 1)
  71. * ppProcessInfo (output)
  72. * Points to the address of a variable to receive the enumeration results,
  73. * which are returned as an array of WTS_PROCESS_INFO structures. The
  74. * buffer is allocated within this API and is disposed of using
  75. * WTSFreeMemory.
  76. * pCount (output)
  77. * Points to the address of a variable to receive the number of
  78. * WTS_PROCESS_INFO structures returned
  79. *
  80. * EXIT:
  81. *
  82. * TRUE -- The enumerate operation succeeded.
  83. *
  84. * FALSE -- The operation failed. Extended error status is available
  85. * using GetLastError.
  86. *
  87. ****************************************************************************/
  88. #if(WINVER >= 0x0500)
  89. BOOL
  90. WINAPI
  91. WTSEnumerateProcessesW(
  92. IN HANDLE hServer,
  93. IN DWORD Reserved,
  94. IN DWORD Version,
  95. OUT PWTS_PROCESS_INFOW * ppProcessInfo,
  96. OUT DWORD * pCount
  97. )
  98. {
  99. PBYTE pProcessBuffer = NULL;
  100. PTS_SYS_PROCESS_INFORMATION pProcessInfo;
  101. PCITRIX_PROCESS_INFORMATION pCitrixInfo;
  102. ULONG ProcessCount;
  103. ULONG Offset;
  104. ULONG DataLength;
  105. PWTS_PROCESS_INFOW pProcessW;
  106. PBYTE pProcessData;
  107. ULONG i;
  108. ULONG Length;
  109. PTS_ALL_PROCESSES_INFO ProcessArray = NULL;
  110. DWORD dwError;
  111. SID_INFO sidInfoHead; //The head of the Sid temp storage
  112. SID_INFO * pSidInfo; //Point to a list of temp storage for the
  113. //variable length SID
  114. sidInfoHead.pNext = NULL;
  115. sidInfoHead.pSid = NULL;
  116. pSidInfo = &sidInfoHead;
  117. /*
  118. * Validate parameters
  119. */
  120. if ( Reserved != 0 || Version != 1 ) {
  121. SetLastError( ERROR_INVALID_PARAMETER );
  122. goto badparam;
  123. }
  124. if (!ppProcessInfo || !pCount) {
  125. SetLastError( ERROR_INVALID_PARAMETER );
  126. goto badparam;
  127. }
  128. //
  129. // Try the new interface first (Windows 2000 server)
  130. //
  131. if (WinStationGetAllProcesses( hServer,
  132. GAP_LEVEL_BASIC,
  133. &ProcessCount,
  134. &ProcessArray) )
  135. {
  136. DataLength = 0;
  137. for (i=0; i<ProcessCount; i++)
  138. {
  139. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION)(ProcessArray[i].pTsProcessInfo);
  140. DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
  141. if (ProcessArray[i].pSid)
  142. {
  143. DataLength += GetLengthSid( ProcessArray[i].pSid );
  144. }
  145. }
  146. /*
  147. * Allocate user buffer
  148. */
  149. pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
  150. if ( pProcessW == NULL ) {
  151. SetLastError(ERROR_OUTOFMEMORY);
  152. goto GAPErrorReturn;
  153. }
  154. /*
  155. * Update user parameters
  156. */
  157. *ppProcessInfo = pProcessW;
  158. *pCount = ProcessCount;
  159. /*
  160. * Copy data to new buffer
  161. */
  162. pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
  163. for ( i=0; i < ProcessCount; i++ ) {
  164. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION)(ProcessArray[i].pTsProcessInfo);
  165. Length = pProcessInfo->ImageName.Length; // number of bytes
  166. pProcessW->pProcessName = (LPWSTR) pProcessData;
  167. memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
  168. *(pProcessData += Length) = (WCHAR)0;
  169. pProcessData += sizeof(WCHAR);
  170. pProcessW->ProcessId = (ULONG)(ULONG_PTR)pProcessInfo->UniqueProcessId;
  171. pProcessW->SessionId = pProcessInfo->SessionId;
  172. if (ProcessArray[i].pSid)
  173. {
  174. Length = GetLengthSid( ProcessArray[i].pSid );
  175. pProcessW->pUserSid = (LPWSTR) pProcessData;
  176. memcpy( pProcessData, ProcessArray[i].pSid, Length );
  177. pProcessData += Length;
  178. }
  179. pProcessW++;
  180. }
  181. //
  182. // Free ppProcessArray and all child pointers allocated by the client stub.
  183. //
  184. WinStationFreeGAPMemory(GAP_LEVEL_BASIC, ProcessArray, ProcessCount);
  185. }
  186. else // Maybe a TS 4.0 server ?
  187. {
  188. //
  189. // Check the return code indicating that the interface is not available.
  190. //
  191. dwError = GetLastError();
  192. if (dwError != RPC_S_PROCNUM_OUT_OF_RANGE)
  193. {
  194. goto badenum;
  195. }
  196. else
  197. {
  198. // It might be a TS4.0 server
  199. // Try the old interface
  200. //
  201. //
  202. // Enumerate Processes and check for an error
  203. //
  204. if ( !WinStationEnumerateProcesses( hServer, &pProcessBuffer ) ) {
  205. goto badenum;
  206. }
  207. //
  208. // Count the number of processes and total up the size of the data
  209. //
  210. ProcessCount = 0;
  211. DataLength = 0;
  212. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
  213. Offset = 0;
  214. do {
  215. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
  216. ProcessCount++;
  217. DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
  218. pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  219. (((PUCHAR)pProcessInfo) +
  220. SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
  221. (SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)pProcessInfo->NumberOfThreads));
  222. if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
  223. if ( pCitrixInfo->ProcessSid )
  224. DataLength += GetLengthSid( pCitrixInfo->ProcessSid );
  225. }
  226. Offset = pProcessInfo->NextEntryOffset;
  227. } while ( Offset != 0 );
  228. /*
  229. * Allocate user buffer
  230. */
  231. pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
  232. if ( pProcessW == NULL ) {
  233. SetLastError(ERROR_OUTOFMEMORY);
  234. goto badalloc;
  235. }
  236. /*
  237. * Update user parameters
  238. */
  239. *ppProcessInfo = pProcessW;
  240. *pCount = ProcessCount;
  241. /*
  242. * Copy data to new buffer
  243. */
  244. pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
  245. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
  246. Offset = 0;
  247. for ( i=0; i < ProcessCount; i++ ) {
  248. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
  249. Length = pProcessInfo->ImageName.Length; // number of bytes
  250. pProcessW->pProcessName = (LPWSTR) pProcessData;
  251. memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
  252. *(pProcessData += Length) = (WCHAR)0;
  253. pProcessData += sizeof(WCHAR);
  254. pProcessW->ProcessId = pProcessInfo->UniqueProcessId;
  255. /*
  256. * Point to the CITRIX_INFORMATION which follows the Threads
  257. */
  258. pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  259. (((PUCHAR)pProcessInfo) +
  260. SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
  261. (SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)pProcessInfo->NumberOfThreads));
  262. if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
  263. pProcessW->SessionId = pCitrixInfo->LogonId;
  264. if ( pCitrixInfo->ProcessSid ) {
  265. Length = GetLengthSid( pCitrixInfo->ProcessSid );
  266. pProcessW->pUserSid = (LPWSTR) pProcessData;
  267. memcpy( pProcessData, pCitrixInfo->ProcessSid, Length );
  268. pProcessData += Length;
  269. }
  270. } else {
  271. pProcessW->SessionId = (ULONG) -1;
  272. }
  273. pProcessW++;
  274. Offset = pProcessInfo->NextEntryOffset;
  275. }
  276. /*
  277. * Free original Process list buffer
  278. */
  279. WinStationFreeMemory( pProcessBuffer );
  280. }
  281. }
  282. return( TRUE );
  283. /*=============================================================================
  284. == Error return
  285. =============================================================================*/
  286. GAPErrorReturn:
  287. //
  288. // Free ppProcessArray and all child pointers allocated by the client stub.
  289. //
  290. WinStationFreeGAPMemory(GAP_LEVEL_BASIC, ProcessArray, ProcessCount);
  291. goto enderror;
  292. badalloc:
  293. WinStationFreeMemory( pProcessBuffer );
  294. badenum:
  295. badparam:
  296. enderror:
  297. if (ppProcessInfo) *ppProcessInfo = NULL;
  298. if (pCount) *pCount = 0;
  299. return( FALSE );
  300. }
  301. #else //#if(WINVER>=0x0500)
  302. BOOL
  303. WINAPI
  304. WTSEnumerateProcessesW(
  305. IN HANDLE hServer,
  306. IN DWORD Reserved,
  307. IN DWORD Version,
  308. OUT PWTS_PROCESS_INFOW * ppProcessInfo,
  309. OUT DWORD * pCount
  310. )
  311. {
  312. PBYTE pProcessBuffer;
  313. PTS_SYS_PROCESS_INFORMATION pProcessInfo;
  314. PCITRIX_PROCESS_INFORMATION pCitrixInfo;
  315. ULONG ProcessCount;
  316. ULONG Offset;
  317. ULONG DataLength;
  318. PWTS_PROCESS_INFOW pProcessW;
  319. PBYTE pProcessData;
  320. ULONG i;
  321. ULONG Length;
  322. /*
  323. * Validate parameters
  324. */
  325. if ( Reserved != 0 || Version != 1 ) {
  326. SetLastError( ERROR_INVALID_PARAMETER );
  327. goto badparam;
  328. }
  329. if (!ppProcessInfo || !pCount) {
  330. SetLastError( ERROR_INVALID_PARAMETER );
  331. goto badparam;
  332. }
  333. /*
  334. * Enumerate Processes and check for an error
  335. */
  336. if ( !WinStationEnumerateProcesses( hServer, &pProcessBuffer ) ) {
  337. goto badenum;
  338. }
  339. /*
  340. * Count the number of processes and total up the size of the data
  341. */
  342. ProcessCount = 0;
  343. DataLength = 0;
  344. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
  345. Offset = 0;
  346. do {
  347. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
  348. ProcessCount++;
  349. DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
  350. pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  351. ((PBYTE)pProcessInfo +
  352. sizeof(SYSTEM_PROCESS_INFORMATION) +
  353. (sizeof(SYSTEM_THREAD_INFORMATION) *
  354. pProcessInfo->NumberOfThreads));
  355. if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
  356. if ( pCitrixInfo->ProcessSid )
  357. DataLength += GetLengthSid( pCitrixInfo->ProcessSid );
  358. }
  359. Offset = pProcessInfo->NextEntryOffset;
  360. } while ( Offset != 0 );
  361. /*
  362. * Allocate user buffer
  363. */
  364. pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
  365. if ( pProcessW == NULL ) {
  366. SetLastError(ERROR_OUTOFMEMORY);
  367. goto badalloc;
  368. }
  369. /*
  370. * Update user parameters
  371. */
  372. *ppProcessInfo = pProcessW;
  373. *pCount = ProcessCount;
  374. /*
  375. * Copy data to new buffer
  376. */
  377. pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
  378. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
  379. Offset = 0;
  380. for ( i=0; i < ProcessCount; i++ ) {
  381. pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
  382. Length = pProcessInfo->ImageName.Length; // number of bytes
  383. pProcessW->pProcessName = (LPWSTR) pProcessData;
  384. memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
  385. *(pProcessData += Length) = (WCHAR)0;
  386. pProcessData += sizeof(WCHAR);
  387. pProcessW->ProcessId = (ULONG) pProcessInfo->UniqueProcessId;
  388. /*
  389. * Point to the CITRIX_INFORMATION which follows the Threads
  390. */
  391. pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  392. ((PBYTE)pProcessInfo +
  393. sizeof(SYSTEM_PROCESS_INFORMATION) +
  394. (sizeof(SYSTEM_THREAD_INFORMATION) *
  395. pProcessInfo->NumberOfThreads));
  396. if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
  397. pProcessW->SessionId = pCitrixInfo->LogonId;
  398. if ( pCitrixInfo->ProcessSid ) {
  399. Length = GetLengthSid( pCitrixInfo->ProcessSid );
  400. pProcessW->pUserSid = (LPWSTR) pProcessData;
  401. memcpy( pProcessData, pCitrixInfo->ProcessSid, Length );
  402. pProcessData += Length;
  403. }
  404. } else {
  405. pProcessW->SessionId = (ULONG) -1;
  406. }
  407. pProcessW++;
  408. Offset = pProcessInfo->NextEntryOffset;
  409. }
  410. /*
  411. * Free original Process list buffer
  412. */
  413. WinStationFreeMemory( pProcessBuffer );
  414. return( TRUE );
  415. /*=============================================================================
  416. == Error return
  417. =============================================================================*/
  418. badalloc:
  419. WinStationFreeMemory( pProcessBuffer );
  420. badenum:
  421. badparam:
  422. if (ppProcessInfo) *ppProcessInfo = NULL;
  423. if (pCount) *pCount = 0;
  424. return( FALSE );
  425. }
  426. #endif //#if(WINVER>=0x0500)
  427. /****************************************************************************
  428. *
  429. * WTSEnumerateProcessesA (ANSI stub)
  430. *
  431. * Returns a list of Terminal Server Processes on the specified server
  432. *
  433. * ENTRY:
  434. *
  435. * see WTSEnumerateProcessesW
  436. *
  437. * EXIT:
  438. *
  439. * TRUE -- The enumerate operation succeeded.
  440. *
  441. * FALSE -- The operation failed. Extended error status is available
  442. * using GetLastError.
  443. *
  444. ****************************************************************************/
  445. BOOL
  446. WINAPI
  447. WTSEnumerateProcessesA(
  448. IN HANDLE hServer,
  449. IN DWORD Reserved,
  450. IN DWORD Version,
  451. OUT PWTS_PROCESS_INFOA * ppProcessInfo,
  452. OUT DWORD * pCount
  453. )
  454. {
  455. PWTS_PROCESS_INFOW pProcessW;
  456. PWTS_PROCESS_INFOA pProcessA;
  457. PBYTE pProcessData;
  458. ULONG Length;
  459. ULONG DataLength; // number of bytes of name data
  460. ULONG NameCount;
  461. ULONG i;
  462. /*
  463. * Enumerate processes (UNICODE)
  464. */
  465. if ( !WTSEnumerateProcessesW( hServer,
  466. Reserved,
  467. Version,
  468. &pProcessW,
  469. &NameCount ) ) {
  470. goto badenum;
  471. }
  472. /*
  473. * Calculate the length of the name data
  474. */
  475. for ( i=0, DataLength=0; i < NameCount; i++ ) {
  476. DataLength += (wcslen(pProcessW[i].pProcessName) + 1);
  477. if ( pProcessW[i].pUserSid )
  478. DataLength += GetLengthSid( pProcessW[i].pUserSid );
  479. }
  480. /*
  481. * Allocate user buffer
  482. */
  483. pProcessA = LocalAlloc( LPTR, (NameCount * sizeof(WTS_PROCESS_INFOA)) + DataLength );
  484. if ( pProcessA == NULL )
  485. goto badalloc2;
  486. /*
  487. * Convert unicode process list to ansi
  488. */
  489. pProcessData = (PBYTE)pProcessA + (NameCount * sizeof(WTS_PROCESS_INFOA));
  490. for ( i=0; i < NameCount; i++ ) {
  491. pProcessA[i].SessionId = pProcessW[i].SessionId;
  492. pProcessA[i].ProcessId = pProcessW[i].ProcessId;
  493. Length = wcslen(pProcessW[i].pProcessName) + 1;
  494. pProcessA[i].pProcessName = pProcessData;
  495. UnicodeToAnsi( pProcessData, DataLength, pProcessW[i].pProcessName );
  496. DataLength -= Length;
  497. pProcessData += Length;
  498. if ( pProcessW[i].pUserSid ) {
  499. Length = GetLengthSid( pProcessW[i].pUserSid );
  500. pProcessA[i].pUserSid = pProcessData;
  501. memcpy( pProcessData, pProcessW[i].pUserSid, Length );
  502. DataLength -= Length;
  503. pProcessData += Length;
  504. }
  505. }
  506. /*
  507. * Free unicode process list buffer
  508. */
  509. LocalFree( pProcessW );
  510. /*
  511. * Update user parameters
  512. */
  513. if (ppProcessInfo) {
  514. *ppProcessInfo = pProcessA;
  515. } else {
  516. SetLastError(ERROR_INVALID_USER_BUFFER);
  517. return(FALSE);
  518. }
  519. if (pCount) {
  520. *pCount = NameCount;
  521. } else {
  522. SetLastError(ERROR_INVALID_USER_BUFFER);
  523. return(FALSE);
  524. }
  525. return( TRUE );
  526. /*=============================================================================
  527. == Error return
  528. =============================================================================*/
  529. badalloc2:
  530. LocalFree( pProcessW );
  531. badenum:
  532. // make sure the passed parameter buffer pointer is not NULL
  533. if (ppProcessInfo) *ppProcessInfo = NULL;
  534. if (pCount) *pCount = 0;
  535. return( FALSE );
  536. }
  537. /*******************************************************************************
  538. *
  539. * WTSTerminateProcess
  540. *
  541. * Terminate the specified process
  542. *
  543. * ENTRY:
  544. *
  545. * hServer (input)
  546. * handle to Terminal server
  547. * ProcessId (input)
  548. * process id of the process to terminate
  549. * ExitCode (input)
  550. * Termination status for each thread in the process
  551. *
  552. *
  553. * EXIT:
  554. *
  555. * TRUE -- The terminate operation succeeded.
  556. *
  557. * FALSE -- The operation failed. Extended error status is available
  558. * using GetLastError.
  559. *
  560. ******************************************************************************/
  561. BOOL WINAPI
  562. WTSTerminateProcess(
  563. HANDLE hServer,
  564. DWORD ProcessId,
  565. DWORD ExitCode
  566. )
  567. {
  568. return( WinStationTerminateProcess( hServer, ProcessId, ExitCode ) );
  569. }
  570. #if(WINVER >= 0x0500)
  571. //======================================================================//
  572. // Private functions //
  573. //======================================================================//
  574. BOOL
  575. GetProcessSid(HANDLE hServer,
  576. HANDLE hUniqueProcessId,
  577. LARGE_INTEGER ProcessStartTime,
  578. PBYTE * ppSid //Return the SID (allocated here..)
  579. )
  580. {
  581. DWORD dwSidSize;
  582. BYTE tmpSid[128]; //temp storage
  583. FILETIME startTime;
  584. dwSidSize = sizeof(tmpSid);
  585. *ppSid = NULL;
  586. //Convert the time format
  587. startTime.dwLowDateTime = ProcessStartTime.LowPart;
  588. startTime.dwHighDateTime = ProcessStartTime.HighPart;
  589. //-------------------------------------------//
  590. // Get the SID with the temp Sid storage //
  591. //-------------------------------------------//
  592. if (!WinStationGetProcessSid(hServer,
  593. (DWORD)(ULONG_PTR)hUniqueProcessId,
  594. startTime,
  595. (PBYTE)&tmpSid,
  596. &dwSidSize
  597. )) {
  598. //-------------------------------------------//
  599. // Sid is too big for the temp storage //
  600. //Get the size of the sid and do it again //
  601. //-------------------------------------------//
  602. NTSTATUS status;
  603. if ((status = GetLastError()) == STATUS_BUFFER_TOO_SMALL) {
  604. *ppSid = LocalAlloc(LPTR, dwSidSize);
  605. if (!*ppSid) {
  606. SetLastError(ERROR_OUTOFMEMORY);
  607. goto ErrorReturn;
  608. }
  609. } else if (dwSidSize == 0) {
  610. *ppSid = NULL;
  611. return TRUE;
  612. } else {
  613. SetLastError(status);
  614. goto ErrorReturn;
  615. }
  616. //-------------------------------------------//
  617. // Call the server again to get the SID
  618. //-------------------------------------------//
  619. if (!WinStationGetProcessSid(hServer,
  620. (DWORD)(ULONG_PTR)hUniqueProcessId,
  621. startTime,
  622. (PBYTE)ppSid,
  623. &dwSidSize
  624. )) {
  625. goto ErrorReturn;
  626. }
  627. } else {
  628. //-------------------------------------------//
  629. // Temp Sid is large enough //
  630. // Allocate the correct size and copy the //
  631. // Sid //
  632. //-------------------------------------------//
  633. *ppSid = LocalAlloc(LPTR, dwSidSize);
  634. if (*ppSid) {
  635. memcpy(*ppSid, tmpSid, dwSidSize);
  636. } else {
  637. SetLastError(ERROR_OUTOFMEMORY);
  638. goto ErrorReturn;
  639. }
  640. }
  641. return TRUE;
  642. ErrorReturn:
  643. if (*ppSid) {
  644. LocalFree(*ppSid);
  645. *ppSid = NULL;
  646. }
  647. return FALSE;
  648. }
  649. #endif //#if(WINVER >= 0x0500)