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.

525 lines
10 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. idletskc.c
  5. Abstract:
  6. This module implements the idle task client APIs.
  7. Author:
  8. Dave Fields (davidfie) 26-July-1998
  9. Cenk Ergan (cenke) 14-June-2000
  10. Revision History:
  11. --*/
  12. //
  13. // Define this to note that we are being built as a part of advapi32 and the
  14. // routines we'll call from advapi32 should not be marked as "dll imports".
  15. //
  16. #define _ADVAPI32_
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include "idletskc.h"
  22. //
  23. // Implementation of client side exposed functions.
  24. //
  25. DWORD
  26. RegisterIdleTask (
  27. IN IT_IDLE_TASK_ID IdleTaskId,
  28. OUT HANDLE *ItHandle,
  29. OUT HANDLE *StartEvent,
  30. OUT HANDLE *StopEvent
  31. )
  32. /*++
  33. Routine Description:
  34. This function is a stub to ItCliRegisterIdleTask. Please see that
  35. function for comments.
  36. Arguments:
  37. See ItCliRegisterIdleTask.
  38. Return Value:
  39. See ItCliRegisterIdleTask.
  40. --*/
  41. {
  42. return ItCliRegisterIdleTask(IdleTaskId,
  43. ItHandle,
  44. StartEvent,
  45. StopEvent);
  46. }
  47. DWORD
  48. ItCliRegisterIdleTask (
  49. IN IT_IDLE_TASK_ID IdleTaskId,
  50. OUT HANDLE *ItHandle,
  51. OUT HANDLE *StartEvent,
  52. OUT HANDLE *StopEvent
  53. )
  54. /*++
  55. Routine Description:
  56. Registers an idle task in the current process with the server and
  57. returns handles to two events that will be used by the server to
  58. signal the idle task to start/stop running.
  59. When the task gets to run and is completed, or not needed anymore,
  60. UnregisterIdleTask should be called with the same Id and returned
  61. event handles.
  62. The caller should not set and reset the events. It should just
  63. wait on them.
  64. An idle task should not run indefinitely as this may prevent the
  65. system from signaling other idle tasks. There is no guarantee that
  66. the StartEvent will be signaled, as the system could be always
  67. active/in use. If your task really has to run at least once every
  68. so often you can also queue a timer-queue timer.
  69. Arguments:
  70. IdleTaskId - Which idle task this is. There can be only a single
  71. task registered from a process with this id.
  72. ItHandle - Handle to registered idle task is returned here.
  73. StartEvent - Handle to a manual reset event that is set when the
  74. task should start running is returned here.
  75. StopEvent - Handle to a manual reset event that is set when the
  76. task should stop running is returned here.
  77. Return Value:
  78. Win32 error code.
  79. --*/
  80. {
  81. DWORD ErrorCode;
  82. BOOLEAN CreatedStartEvent;
  83. BOOLEAN CreatedStopEvent;
  84. IT_IDLE_TASK_PROPERTIES IdleTask;
  85. DWORD ProcessId;
  86. //
  87. // Initialize locals.
  88. //
  89. CreatedStartEvent = FALSE;
  90. CreatedStopEvent = FALSE;
  91. ProcessId = GetCurrentProcessId();
  92. DBGPR((ITID,ITTRC,"IDLE: CliRegisterIdleTask(%d,%d)\n",IdleTaskId,ProcessId));
  93. //
  94. // Setup IdleTask fields.
  95. //
  96. IdleTask.Size = sizeof(IdleTask);
  97. IdleTask.IdleTaskId = IdleTaskId;
  98. IdleTask.ProcessId = ProcessId;
  99. //
  100. // Create events for start/stop. Start event is initially
  101. // nonsignalled.
  102. //
  103. (*StartEvent) = CreateEvent(NULL, TRUE, FALSE, NULL);
  104. if (!(*StartEvent)) {
  105. ErrorCode = GetLastError();
  106. goto cleanup;
  107. }
  108. IdleTask.StartEventHandle = (ULONG_PTR) (*StartEvent);
  109. CreatedStartEvent = TRUE;
  110. //
  111. // Stop event is initially signaled.
  112. //
  113. (*StopEvent) = CreateEvent(NULL, TRUE, TRUE, NULL);
  114. if (!(*StopEvent)) {
  115. ErrorCode = GetLastError();
  116. goto cleanup;
  117. }
  118. IdleTask.StopEventHandle = (ULONG_PTR) (*StopEvent);
  119. CreatedStopEvent = TRUE;
  120. //
  121. // Call the server.
  122. //
  123. RpcTryExcept {
  124. ErrorCode = ItSrvRegisterIdleTask(NULL, (IT_HANDLE *) ItHandle, &IdleTask);
  125. }
  126. RpcExcept(IT_RPC_EXCEPTION_HANDLER()) {
  127. ErrorCode = RpcExceptionCode();
  128. }
  129. RpcEndExcept
  130. cleanup:
  131. if (ErrorCode != ERROR_SUCCESS) {
  132. if (CreatedStartEvent) {
  133. CloseHandle(*StartEvent);
  134. }
  135. if (CreatedStopEvent) {
  136. CloseHandle(*StopEvent);
  137. }
  138. }
  139. DBGPR((ITID,ITTRC,"IDLE: CliRegisterIdleTask(%d,%d,%p)=%x\n",IdleTaskId,ProcessId,*ItHandle,ErrorCode));
  140. return ErrorCode;
  141. }
  142. DWORD
  143. UnregisterIdleTask (
  144. IN HANDLE ItHandle,
  145. IN HANDLE StartEvent,
  146. IN HANDLE StopEvent
  147. )
  148. /*++
  149. Routine Description:
  150. This function is a stub to ItCliUnregisterIdleTask. Please see
  151. that function for comments.
  152. Arguments:
  153. See ItCliUnregisterIdleTask.
  154. Return Value:
  155. Win32 error code.
  156. --*/
  157. {
  158. ItCliUnregisterIdleTask(ItHandle,
  159. StartEvent,
  160. StopEvent);
  161. return ERROR_SUCCESS;
  162. }
  163. VOID
  164. ItCliUnregisterIdleTask (
  165. IN HANDLE ItHandle,
  166. IN HANDLE StartEvent,
  167. IN HANDLE StopEvent
  168. )
  169. /*++
  170. Routine Description:
  171. Unregisters an idle task in the current process with the server
  172. and cleans up any allocated resources. This function should be
  173. called when the idle task is completed, or not needed anymore
  174. (e.g. the process is exiting).
  175. Arguments:
  176. ItHandle - Registration RPC context handle.
  177. StartEvent - Handle returned from RegisterIdleTask.
  178. StopEvent - Handle returned from RegisterIdleTask.
  179. Return Value:
  180. Win32 error code.
  181. --*/
  182. {
  183. DWORD ErrorCode;
  184. //
  185. // Initialize locals.
  186. //
  187. DBGPR((ITID,ITTRC,"IDLE: CliUnregisterIdleTask(%p)\n", ItHandle));
  188. //
  189. // Call server to unregister the idle task.
  190. //
  191. RpcTryExcept {
  192. ItSrvUnregisterIdleTask(NULL, (IT_HANDLE *)&ItHandle);
  193. ErrorCode = ERROR_SUCCESS;
  194. }
  195. RpcExcept(IT_RPC_EXCEPTION_HANDLER()) {
  196. ErrorCode = RpcExceptionCode();
  197. }
  198. RpcEndExcept
  199. //
  200. // Close handles to the start/stop events.
  201. //
  202. CloseHandle(StartEvent);
  203. CloseHandle(StopEvent);
  204. DBGPR((ITID,ITTRC,"IDLE: CliUnregisterIdleTask(%p)=0\n",ItHandle));
  205. return;
  206. }
  207. DWORD
  208. ProcessIdleTasks (
  209. VOID
  210. )
  211. /*++
  212. Routine Description:
  213. This routine forces all queued tasks (if there are any) to be processed
  214. right away.
  215. Arguments:
  216. None.
  217. Return Value:
  218. Win32 error code.
  219. --*/
  220. {
  221. DWORD ErrorCode;
  222. DBGPR((ITID,ITTRC,"IDLE: ProcessIdleTasks()\n"));
  223. //
  224. // Call the server.
  225. //
  226. RpcTryExcept {
  227. ErrorCode = ItSrvProcessIdleTasks(NULL);
  228. }
  229. RpcExcept(IT_RPC_EXCEPTION_HANDLER()) {
  230. ErrorCode = RpcExceptionCode();
  231. }
  232. RpcEndExcept
  233. DBGPR((ITID,ITTRC,"IDLE: ProcessIdleTasks()=%x\n",ErrorCode));
  234. return ErrorCode;
  235. }
  236. //
  237. // These are the custom binding functions that are called by RPC stubs
  238. // when we call interface functions:
  239. //
  240. handle_t
  241. __RPC_USER
  242. ITRPC_HANDLE_bind(
  243. ITRPC_HANDLE Reserved
  244. )
  245. /*++
  246. Routine Description:
  247. Typical RPC custom binding routine. It is called to get a binding
  248. for the RPC interface functions that require explicit_binding.
  249. Arguments:
  250. Reserved - Ignored.
  251. Return Value:
  252. RPC binding handle or NULL if there was an error.
  253. --*/
  254. {
  255. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  256. RPC_BINDING_HANDLE BindingHandle;
  257. RPC_SECURITY_QOS SecurityQOS;
  258. PSID LocalSystemSid;
  259. WCHAR *StringBinding;
  260. SID_NAME_USE AccountType;
  261. WCHAR AccountName[128];
  262. DWORD AccountNameSize = sizeof(AccountName);
  263. WCHAR DomainName[128];
  264. DWORD DomainNameSize = sizeof(DomainName);
  265. DWORD ErrorCode;
  266. //
  267. // Initialize locals.
  268. //
  269. LocalSystemSid = NULL;
  270. BindingHandle = NULL;
  271. StringBinding = NULL;
  272. ErrorCode = RpcStringBindingCompose(NULL,
  273. IT_RPC_PROTSEQ,
  274. NULL,
  275. NULL,
  276. NULL,
  277. &StringBinding);
  278. if (ErrorCode != RPC_S_OK) {
  279. goto cleanup;
  280. }
  281. ErrorCode = RpcBindingFromStringBinding(StringBinding,
  282. &BindingHandle);
  283. if (ErrorCode != RPC_S_OK) {
  284. IT_ASSERT(BindingHandle == NULL);
  285. goto cleanup;
  286. }
  287. //
  288. // Set security information.
  289. //
  290. SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
  291. SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  292. SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  293. SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  294. //
  295. // Get the security principal name for LocalSystem: we'll only allow an
  296. // RPC server running as LocalSystem to impersonate us.
  297. //
  298. if (!AllocateAndInitializeSid(&NtAuthority,
  299. 1,
  300. SECURITY_LOCAL_SYSTEM_RID,
  301. 0, 0, 0, 0, 0, 0, 0,
  302. &LocalSystemSid)) {
  303. ErrorCode = GetLastError();
  304. goto cleanup;
  305. }
  306. if (LookupAccountSid(NULL,
  307. LocalSystemSid,
  308. AccountName,
  309. &AccountNameSize,
  310. DomainName,
  311. &DomainNameSize,
  312. &AccountType) == 0) {
  313. ErrorCode = GetLastError();
  314. goto cleanup;
  315. }
  316. //
  317. // Set mutual authentication requirements on the binding handle.
  318. //
  319. ErrorCode = RpcBindingSetAuthInfoEx(BindingHandle,
  320. AccountName,
  321. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  322. RPC_C_AUTHN_WINNT,
  323. NULL,
  324. 0,
  325. &SecurityQOS);
  326. if (ErrorCode!= RPC_S_OK) {
  327. goto cleanup;
  328. }
  329. ErrorCode = ERROR_SUCCESS;
  330. cleanup:
  331. if (StringBinding) {
  332. RpcStringFree(&StringBinding);
  333. }
  334. if (LocalSystemSid) {
  335. FreeSid(LocalSystemSid);
  336. }
  337. return BindingHandle;
  338. }
  339. VOID
  340. __RPC_USER
  341. ITRPC_HANDLE_unbind(
  342. ITRPC_HANDLE Reserved,
  343. RPC_BINDING_HANDLE BindingHandle
  344. )
  345. /*++
  346. Routine Description:
  347. Typical RPC custom unbinding routine. It is called to close a
  348. binding established for an RPC interface function that required
  349. explicit_binding.
  350. Arguments:
  351. Reserved - Ignored.
  352. BindingHandle - Primitive binding handle.
  353. Return Value:
  354. None.
  355. --*/
  356. {
  357. RPC_STATUS Status;
  358. Status = RpcBindingFree(&BindingHandle);
  359. IT_ASSERT(Status == RPC_S_OK);
  360. IT_ASSERT(BindingHandle == NULL);
  361. return;
  362. }