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.

814 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. apiinit.c
  5. Abstract:
  6. Initialization for Cluster API component (CLUSAPI) of the
  7. NT Cluster Service
  8. Author:
  9. John Vert (jvert) 7-Feb-1996
  10. Revision History:
  11. --*/
  12. #include "apip.h"
  13. #include "aclapi.h"
  14. #include "stdio.h"
  15. #include <psapi.h>
  16. extern LPWSTR g_pszServicesPath;
  17. extern DWORD g_dwServicesPid;
  18. API_INIT_STATE ApiState=ApiStateUninitialized;
  19. const DWORD NO_USER_SID = 0;
  20. const DWORD USER_SID_GRANTED = 1;
  21. const DWORD USER_SID_DENIED = 2;
  22. //forward declarations
  23. DWORD
  24. ApipGetLocalCallerInfo(
  25. IN handle_t hIDL,
  26. IN OUT OPTIONAL LPDWORD pdwCheckPid,
  27. IN OPTIONAL LPCWSTR pszModuleName,
  28. OUT BOOL *pbLocal,
  29. OUT OPTIONAL BOOL *pbMatchedPid,
  30. OUT OPTIONAL BOOL *pbMatchedModule,
  31. OUT OPTIONAL BOOL *pbLocalSystemAccount
  32. );
  33. RPC_STATUS
  34. ApipConnectCallback(
  35. IN RPC_IF_ID * Interface,
  36. IN void * Context
  37. )
  38. /*++
  39. Routine Description:
  40. RPC callback for authenticating connecting clients of CLUSAPI
  41. Arguments:
  42. Interface - Supplies the UUID and version of the interface.
  43. Context - Supplies a server binding handle representing the client
  44. Return Value:
  45. RPC_S_OK if the user is granted permission.
  46. RPC_S_ACCESS_DENIED if the user is denied permission.
  47. Win32 error code otherwise
  48. --*/
  49. {
  50. PSECURITY_DESCRIPTOR pSD = NULL;
  51. DWORD BufferSize=0;
  52. DWORD Size=0;
  53. DWORD Status;
  54. HANDLE ClientToken = NULL;
  55. PRIVILEGE_SET psPrivileges;
  56. DWORD PrivSize = sizeof(psPrivileges);
  57. DWORD GrantedAccess;
  58. DWORD AccessStatus;
  59. DWORD dwMask = CLUSAPI_ALL_ACCESS;
  60. GENERIC_MAPPING gmMap;
  61. DWORD dwStatus = 0;
  62. BOOL bReturn = FALSE;
  63. BOOL bACRtn = FALSE;
  64. DWORD dwUserPermStatus;
  65. RPC_STATUS RpcStatus;
  66. BOOL bRevertToSelfRequired = FALSE;
  67. BOOL bLocal, bMatchedPid, bMatchedModule, bLocalSystemAccount;
  68. //check if services is calling the cluster service for
  69. //services calls the interface only for eventlog propagation
  70. //if so, avoid the security checks
  71. // Get the process id
  72. Status = ApipGetLocalCallerInfo(Context,
  73. &g_dwServicesPid,
  74. g_dwServicesPid ? NULL : g_pszServicesPath, //perform the module name match the first time
  75. &bLocal,
  76. &bMatchedPid,
  77. &bMatchedModule,
  78. g_dwServicesPid ? &bLocalSystemAccount : NULL);//perform the local system account check if it is the first time
  79. if (Status != ERROR_SUCCESS)
  80. {
  81. ClRtlLogPrint(LOG_NOISE, "[API] ApipGetLocalCallerInfo failed with %1!u!.\n",
  82. Status);
  83. return RPC_S_ACCESS_DENIED;
  84. }
  85. if (Status == ERROR_SUCCESS)
  86. {
  87. //if the caller is local and if it matches the pid or if it matches
  88. //the module and is in local system account, allow access
  89. if ((bLocal) &&
  90. (bMatchedPid || (bMatchedModule && bLocalSystemAccount)))
  91. {
  92. return(RPC_S_OK);
  93. }
  94. }
  95. //
  96. // The authentication we do here is to retrieve the Security value
  97. // from the cluster registry, impersonate the client, and call
  98. // AccessCheck.
  99. //
  100. Status = DmQueryString(DmClusterParametersKey,
  101. CLUSREG_NAME_CLUS_SD,
  102. REG_BINARY,
  103. (LPWSTR *) &pSD,
  104. &BufferSize,
  105. &Size);
  106. if (Status != ERROR_SUCCESS) {
  107. PSECURITY_DESCRIPTOR psd4;
  108. ClRtlLogPrint(LOG_NOISE, "[API] Did not find Security Descriptor key in the cluster DB.\n");
  109. Status = DmQueryString(DmClusterParametersKey,
  110. CLUSREG_NAME_CLUS_SECURITY,
  111. REG_BINARY,
  112. (LPWSTR *) &psd4,
  113. &BufferSize,
  114. &Size);
  115. if (Status == ERROR_SUCCESS) {
  116. pSD = ClRtlConvertClusterSDToNT5Format(psd4);
  117. LocalFree(psd4);
  118. }
  119. else {
  120. DWORD dwSDLen;
  121. ClRtlLogPrint(LOG_NOISE, "[API] Did not find Security key in the cluster DB.\n");
  122. Status = ClRtlBuildDefaultClusterSD(NULL, &pSD, &dwSDLen);
  123. if (SUCCEEDED(Status)) {
  124. ClRtlLogPrint(LOG_NOISE, "[API] Successfully built default cluster SD.\n");
  125. }
  126. else {
  127. ClRtlLogPrint(LOG_NOISE,
  128. "[API] Did not successfully build default cluster SD. Error = 0x%1!.8x!\n",
  129. Status);
  130. Status = RPC_S_ACCESS_DENIED;
  131. goto FnExit;
  132. }
  133. }
  134. }
  135. if (!IsValidSecurityDescriptor(pSD)) {
  136. ClRtlLogPrint(LOG_ERROR, "[API] SD is not valid!\n");
  137. ClRtlExamineSD(pSD, "[API]");
  138. Status = RPC_S_ACCESS_DENIED;
  139. goto FnExit;
  140. }
  141. RpcStatus = RpcImpersonateClient(Context);
  142. if (RpcStatus != RPC_S_OK) {
  143. Status = RpcStatus;
  144. ClRtlLogPrint(LOG_NOISE, "[API] RpcImpersonateClient() failed. Status = 0x%1!.8x!\n", Status);
  145. goto FnExit;
  146. }
  147. bRevertToSelfRequired = TRUE;
  148. if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &ClientToken)) {
  149. Status = GetLastError();
  150. ClRtlLogPrint(LOG_NOISE, "[API] OpenThreadToken() failed. Status = 0x%1!.8x!\n", Status);
  151. goto FnExit;
  152. }
  153. gmMap.GenericRead = CLUSAPI_READ_ACCESS;
  154. gmMap.GenericWrite = CLUSAPI_CHANGE_ACCESS;
  155. gmMap.GenericExecute = CLUSAPI_READ_ACCESS | CLUSAPI_CHANGE_ACCESS;
  156. gmMap.GenericAll = CLUSAPI_ALL_ACCESS;
  157. MapGenericMask(&dwMask, &gmMap);
  158. bACRtn = AccessCheck(pSD, ClientToken, dwMask, &gmMap, &psPrivileges, &PrivSize, &dwStatus, &bReturn);
  159. if (bACRtn && bReturn) {
  160. Status = RPC_S_OK;
  161. } else {
  162. DWORD dwSDLen;
  163. ClRtlLogPrint(LOG_NOISE,
  164. "[API] User denied access. GetLastError() = 0x%1!.8x!; dwStatus = 0x%2!.8x!. Trying the default SD...\n",
  165. GetLastError(),
  166. dwStatus);
  167. Status = RPC_S_ACCESS_DENIED;
  168. ClRtlLogPrint(LOG_NOISE, "[API] Dump access mask.\n");
  169. ClRtlExamineMask(dwMask, "[API]");
  170. ClRtlLogPrint(LOG_NOISE, "[API] Dump the SD that failed...\n" );
  171. ClRtlExamineSD(pSD, "[API]");
  172. ClRtlLogPrint(LOG_NOISE, "[API] Dump the ClientToken that failed...\n" );
  173. ClRtlExamineClientToken(ClientToken, "[API]");
  174. if (pSD) {
  175. LocalFree(pSD);
  176. pSD = NULL;
  177. }
  178. Status = ClRtlBuildDefaultClusterSD(NULL, &pSD, &dwSDLen);
  179. if (SUCCEEDED(Status)) {
  180. ClRtlLogPrint(LOG_NOISE, "[API] Successfully built default cluster SD.\n");
  181. bACRtn = AccessCheck(pSD, ClientToken, dwMask, &gmMap, &psPrivileges, &PrivSize, &dwStatus, &bReturn);
  182. if (bACRtn && bReturn) {
  183. ClRtlLogPrint(LOG_NOISE, "[API] User granted access using default cluster SD.\n");
  184. Status = RPC_S_OK;
  185. } else {
  186. ClRtlLogPrint(LOG_NOISE,
  187. "[API] User denied access using default cluster SD. GetLastError() = 0x%1!.8x!; dwStatus = 0x%2!.8x!.\n",
  188. GetLastError(),
  189. dwStatus);
  190. Status = RPC_S_ACCESS_DENIED;
  191. }
  192. }
  193. else {
  194. ClRtlLogPrint(LOG_NOISE,
  195. "[API] Did not successfully build default cluster SD. Error = 0x%1!.8x!\n",
  196. Status);
  197. Status = RPC_S_ACCESS_DENIED;
  198. }
  199. }
  200. FnExit:
  201. if (bRevertToSelfRequired) {
  202. RpcRevertToSelf();
  203. }
  204. if (ClientToken) {
  205. CloseHandle(ClientToken);
  206. }
  207. if (pSD) {
  208. LocalFree(pSD);
  209. }
  210. return(Status);
  211. }
  212. DWORD
  213. ApiInitialize(
  214. VOID
  215. )
  216. /*++
  217. Routine Description:
  218. Performs one-time initialization of the API data structures.
  219. Arguments:
  220. None.
  221. Return Value:
  222. ERROR_SUCCESS if successful
  223. Win32 error code otherwise.
  224. --*/
  225. {
  226. ClRtlLogPrint(LOG_NOISE, "[API] Initializing\n");
  227. CL_ASSERT(ApiState == ApiStateUninitialized);
  228. //
  229. // Initialize global data.
  230. //
  231. InitializeListHead(&NotifyListHead);
  232. InitializeCriticalSection(&NotifyListLock);
  233. ApiState = ApiStateOffline;
  234. return(ERROR_SUCCESS);
  235. }
  236. DWORD
  237. ApiOnlineReadOnly(
  238. VOID
  239. )
  240. /*++
  241. Routine Description:
  242. Brings up a limited set of APIs - currently OpenResource/read-only
  243. registry APIs. Only LPC connections are enabled.
  244. Arguments:
  245. None.
  246. Return Value:
  247. ERROR_SUCCESS if successful
  248. Win32 error code otherwise.
  249. --*/
  250. {
  251. DWORD Status;
  252. if (ApiState == ApiStateOffline) {
  253. ClRtlLogPrint(LOG_NOISE, "[API] Online read only\n");
  254. //
  255. // Register the clusapi RPC server interface so resources can use
  256. // the API when they are created by the FM. Note that we won't receive
  257. // any calls from remote clients yet because we haven't registered
  258. // the dynamic UDP endpoint. That will happnen in ApiOnline().
  259. //
  260. Status = RpcServerRegisterIfEx(s_clusapi_v2_0_s_ifspec,
  261. NULL,
  262. NULL,
  263. 0,
  264. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  265. CsUseAuthenticatedRPC ? ApipConnectCallback : NULL
  266. );
  267. if (Status != RPC_S_OK) {
  268. ClRtlLogPrint(LOG_UNUSUAL,
  269. "[API] Failed to register clusapi RPC interface, status %1!u!.\n",
  270. Status
  271. );
  272. return(Status);
  273. }
  274. ApiState = ApiStateReadOnly;
  275. }
  276. else {
  277. //CL_ASSERT(ApiState == ApiStateOffline);
  278. }
  279. return(ERROR_SUCCESS);
  280. }
  281. DWORD
  282. ApiOnline(
  283. VOID
  284. )
  285. /*++
  286. Routine Description:
  287. Enables the rest of the API set and starts listening for remote
  288. connections.
  289. Arguments:
  290. None
  291. Return Value:
  292. ERROR_SUCCESS if successful.
  293. Win32 error code otherwise.
  294. --*/
  295. {
  296. DWORD Status;
  297. ClRtlLogPrint(LOG_NOISE, "[API] Online\n");
  298. if (ApiState == ApiStateReadOnly) {
  299. //
  300. // Register for all events
  301. //
  302. Status = EpRegisterEventHandler(CLUSTER_EVENT_ALL,ApipEventHandler);
  303. if (Status != ERROR_SUCCESS) {
  304. return(Status);
  305. }
  306. //
  307. // Register the dynamic UDP endpoint for the clusapi interface.
  308. // This will enable remote clients to begin calling us. We do this
  309. // here to minimize the chances that we will service an external
  310. // call before we are ready. If we ever have to rollback after
  311. // this point, we will still be listening externally. Nothing we can
  312. // do about that.
  313. //
  314. CL_ASSERT(CsRpcBindingVector != NULL);
  315. Status = RpcEpRegister(s_clusapi_v2_0_s_ifspec,
  316. CsRpcBindingVector,
  317. NULL,
  318. L"Microsoft Cluster Server API");
  319. if (Status != RPC_S_OK) {
  320. ClRtlLogPrint(LOG_UNUSUAL,
  321. "[API] Failed to register endpoint for clusapi RPC interface, status %1!u!.\n",
  322. Status
  323. );
  324. NmDumpRpcExtErrorInfo(Status);
  325. return(Status);
  326. }
  327. ApiState = ApiStateOnline;
  328. }
  329. else {
  330. CL_ASSERT(ApiState == ApiStateReadOnly);
  331. }
  332. return(ERROR_SUCCESS);
  333. }
  334. VOID
  335. ApiOffline(
  336. VOID
  337. )
  338. /*++
  339. Routine Description:
  340. Takes the Cluster Api offline.
  341. Arguments:
  342. None.
  343. Returns:
  344. None.
  345. --*/
  346. {
  347. DWORD Status;
  348. if (ApiState == ApiStateOnline) {
  349. ClRtlLogPrint(LOG_NOISE, "[API] Offline\n");
  350. //
  351. // Deregister the Clusapi RPC endpoint
  352. //
  353. CL_ASSERT(CsRpcBindingVector != NULL);
  354. Status = RpcEpUnregister(
  355. s_clusapi_v2_0_s_ifspec,
  356. CsRpcBindingVector,
  357. NULL
  358. );
  359. if ((Status != RPC_S_OK) && (Status != EPT_S_NOT_REGISTERED)) {
  360. ClRtlLogPrint(LOG_UNUSUAL,
  361. "[API] Failed to deregister endpoint for clusapi RPC interface, status %1!u!.\n",
  362. Status
  363. );
  364. }
  365. ApiState = ApiStateReadOnly;
  366. }
  367. //
  368. // KB - We can't deregister the interface because we can't wait for
  369. // pending calls to complete - pending notifies never complete.
  370. // If we deregistered the interface after a failed join without
  371. // a complete shutdown, the subsequent form would fail. As a
  372. // result, the API won't go offline until service shutdown.
  373. //
  374. #if 0
  375. if (ApiState == ApiStateReadOnly) {
  376. //
  377. // Deregister the Clusapi RPC interface
  378. //
  379. Status = RpcServerUnregisterIf(
  380. s_clusapi_v2_0_s_ifspec,
  381. NULL,
  382. 1 // Wait for outstanding calls to complete
  383. );
  384. if ((Status != RPC_S_OK) && (Status != RPC_S_UNKNOWN_IF)) {
  385. ClRtlLogPrint(LOG_UNUSUAL,
  386. "[INIT] Unable to deregister the clusapi RPC interface, Status %1!u!.\n",
  387. Status
  388. );
  389. }
  390. ApiState = ApiStateOffline;
  391. }
  392. #endif
  393. return;
  394. }
  395. VOID
  396. ApiShutdown(
  397. VOID
  398. )
  399. /*++
  400. Routine Description:
  401. Shuts down the Cluster Api
  402. Arguments:
  403. None.
  404. Returns:
  405. None.
  406. --*/
  407. {
  408. DWORD Status;
  409. if (ApiState > ApiStateOffline) {
  410. ApiOffline();
  411. //
  412. // KB - We do this here because shutdown of the Clusapi RPC
  413. // interface is broken due to pending notifies.
  414. //
  415. Status = RpcServerUnregisterIf(
  416. s_clusapi_v2_0_s_ifspec,
  417. NULL,
  418. 0 // Don't wait for calls to complete
  419. );
  420. if ((Status != RPC_S_OK) && (Status != RPC_S_UNKNOWN_IF)) {
  421. ClRtlLogPrint(LOG_UNUSUAL,
  422. "[INIT] Unable to deregister the clusapi RPC interface, Status %1!u!.\n",
  423. Status
  424. );
  425. }
  426. ApiState = ApiStateOffline;
  427. }
  428. if (ApiState == ApiStateOffline) {
  429. ClRtlLogPrint(LOG_NOISE, "[API] Shutdown\n");
  430. //
  431. // KB
  432. //
  433. // Because we cannot shutdown the RPC server and cannot
  434. // unregister our event handler, it is not safe to delete
  435. // the critical section.
  436. //
  437. // DeleteCriticalSection(&NotifyListLock);
  438. // ApiState = ApiStateUninitialized;
  439. //
  440. // TODO?
  441. //
  442. // SS: free notify list head
  443. // SS: how do we deregister with the event handler
  444. //
  445. }
  446. return;
  447. }
  448. DWORD
  449. ApipGetLocalCallerInfo(
  450. IN handle_t hIDL,
  451. IN OUT OPTIONAL LPDWORD pdwCheckPid,
  452. IN OPTIONAL LPCWSTR pszModuleName,
  453. OUT BOOL *pbLocal,
  454. OUT OPTIONAL BOOL *pbMatchedPid,
  455. OUT OPTIONAL BOOL *pbMatchedModule,
  456. OUT OPTIONAL BOOL *pbLocalSystemAccount
  457. )
  458. /*++
  459. Routine Description:
  460. This function checks whether the caller's account is the local system
  461. account.
  462. Arguments:
  463. hIDL - The handle to the binding context
  464. pdwCheckPid - if the value passed in is NULL, the pid of the calling process is returned. If
  465. is returned.
  466. pszModuleName - If non null, the call performs the check to compare
  467. the module name of the caller against pszModuleName. If they
  468. match, *pbMatchedPid is set to TRUE.
  469. pbLocal - TRUE is returned if the caller initiated this call using
  470. lrpc. If this is FALSE, all other output values will be FALSE.
  471. pbMatchedModule - TRUE is returned, if the caller matches the module
  472. name specified by lpszModuleName. This pointer can be NULL.
  473. pbMatchedPid - if *pdwCheckPid is non NULL, and it matched the pid of the
  474. caller, then this is set to TRUE. Else, this is set to FALSE.
  475. pbLocalSystemAccount - If this is NON NULL, the call performs a check
  476. to see if the the caller is running in LocalSystemAccount. If it is
  477. then TRUE is returned, else FALSE is returned.
  478. Return Value:
  479. ERROR_SUCCESS on success.
  480. Win32 error code on failure.
  481. Remarks:
  482. --*/
  483. {
  484. DWORD Pid;
  485. HANDLE hProcess = NULL;
  486. DWORD dwNumChar;
  487. DWORD dwLen;
  488. WCHAR wCallerPath[MAX_PATH + 1];
  489. RPC_STATUS RpcStatus;
  490. DWORD dwStatus = ERROR_SUCCESS;
  491. BOOLEAN bWasEnabled;
  492. if (pbMatchedModule)
  493. *pbMatchedModule = FALSE;
  494. if (pbMatchedPid)
  495. *pbMatchedPid = FALSE;
  496. if (pbLocalSystemAccount)
  497. *pbLocalSystemAccount = FALSE;
  498. //assume the caller is local
  499. *pbLocal = TRUE;
  500. RpcStatus = I_RpcBindingInqLocalClientPID(NULL, &Pid );
  501. if (RpcStatus == RPC_S_INVALID_BINDING)
  502. {
  503. *pbLocal = FALSE;
  504. RpcStatus = RPC_S_OK;
  505. goto FnExit;
  506. }
  507. dwStatus = I_RpcMapWin32Status(RpcStatus);
  508. if (dwStatus != ERROR_SUCCESS)
  509. {
  510. ClRtlLogPrint( LOG_CRITICAL,
  511. "[API] ApipGetLocalCallerInfo: Error %1!u! calling RpcBindingInqLocalClientPID.\n",
  512. dwStatus
  513. );
  514. goto FnExit;
  515. }
  516. dwStatus = ClRtlEnableThreadPrivilege(SE_DEBUG_PRIVILEGE, &bWasEnabled);
  517. if ( dwStatus != ERROR_SUCCESS )
  518. {
  519. if (dwStatus == STATUS_PRIVILEGE_NOT_HELD)
  520. {
  521. ClRtlLogPrint(LOG_CRITICAL,
  522. "[API] ApipGetLocalCallerInfo: Debug privilege not held by cluster service\n");
  523. }
  524. else
  525. {
  526. ClRtlLogPrint(LOG_CRITICAL,
  527. "[API] ApipGetLocalCallerInfo: Attempt to enable debug privilege failed %1!lx!\n",
  528. dwStatus);
  529. }
  530. goto FnExit;
  531. }
  532. // Get the process
  533. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Pid);
  534. //restore the thread privilege, now that we have a process handle with the right access
  535. ClRtlRestoreThreadPrivilege(SE_DEBUG_PRIVILEGE,
  536. bWasEnabled);
  537. if(hProcess == NULL)
  538. {
  539. dwStatus = GetLastError();
  540. ClRtlLogPrint( LOG_CRITICAL,
  541. "[API] ApipGetLocalCallerInfo: Error %1!u! calling OpenProcess %2!u!.\n",
  542. dwStatus,
  543. Pid
  544. );
  545. goto FnExit;
  546. }
  547. //if a process id has been specified, see if it matches that one
  548. if (pdwCheckPid)
  549. {
  550. if ((*pdwCheckPid) && (*pdwCheckPid == Pid))
  551. {
  552. *pbMatchedPid = TRUE;
  553. }
  554. }
  555. if (pszModuleName && pbMatchedModule)
  556. {
  557. // Get the module name of whoever is calling us.
  558. dwNumChar = GetModuleFileNameExW(hProcess, NULL, wCallerPath, MAX_PATH);
  559. if(dwNumChar == 0)
  560. {
  561. dwStatus = GetLastError();
  562. ClRtlLogPrint( LOG_CRITICAL,
  563. "[API] ApipGetLocalCallerInfo: Error %1!u! calling GetModuleFileNameExW.\n",
  564. dwStatus
  565. );
  566. goto FnExit;
  567. }
  568. if(!lstrcmpiW(wCallerPath, pszModuleName))
  569. {
  570. *pbMatchedModule = TRUE;
  571. }
  572. }
  573. //check if it is the local system account, if requested
  574. if (pbLocalSystemAccount && hIDL)
  575. {
  576. // Impersonate the client.
  577. if ( ( RpcStatus = RpcImpersonateClient( hIDL ) ) != RPC_S_OK )
  578. {
  579. dwStatus = I_RpcMapWin32Status(RpcStatus);
  580. ClRtlLogPrint( LOG_CRITICAL,
  581. "[API] ApipGetLocalCallerInfo: Error %1!u! trying to impersonate caller...\n",
  582. dwStatus
  583. );
  584. goto FnExit;
  585. }
  586. // Check that the caller's account is local system account
  587. dwStatus = ClRtlIsCallerAccountLocalSystemAccount(pbLocalSystemAccount );
  588. RpcRevertToSelf();
  589. if (dwStatus != ERROR_SUCCESS )
  590. {
  591. ClRtlLogPrint( LOG_CRITICAL,
  592. "[API] ApipGetLocalCallerInfo : Error %1!u! trying to check caller's account...\n",
  593. dwStatus);
  594. goto FnExit;
  595. }
  596. }
  597. //return the pid if the pid passed in is NULL and the pid passes
  598. //the criteria - matches pszModuleName if specified and is in
  599. //local system account
  600. if (pdwCheckPid && !(*pdwCheckPid))
  601. {
  602. //if we need to check for local system, the process must be in local system account
  603. //if the module name needs to be checked
  604. if (((pbLocalSystemAccount && *pbLocalSystemAccount) || (!pbLocalSystemAccount))
  605. && ((pszModuleName && pbMatchedModule && *pbMatchedModule) || (!pbMatchedModule)))
  606. {
  607. ClRtlLogPrint( LOG_NOISE,
  608. "[API] ApipGetLocalCallerInfo : Returning Pid %1!u!\n",
  609. Pid);
  610. *pdwCheckPid = Pid;
  611. }
  612. }
  613. FnExit:
  614. if (hProcess)
  615. CloseHandle(hProcess);
  616. return(dwStatus);
  617. }