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.

186 lines
4.5 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: schedlog.c
  7. //
  8. // Contents: Task Scheduler StartShell notification
  9. //
  10. // Classes: None.
  11. //
  12. // Functions:
  13. // SchedStartShell - queue the work to the WinLogon thread pool.
  14. // DoSchedStartShell - notify Sched service that a user logged on.
  15. //
  16. // History: 07-Mar-01 JBenton Created
  17. //
  18. //-----------------------------------------------------------------------------
  19. //
  20. // Note: We don't build/publish a lib here as suggested in wlnotify.cxx.
  21. // Rather we include the source file here because there is only a single
  22. // simple function.
  23. //
  24. // Note: We are using the StartShell event because the Scheduler service
  25. // expects the user's explorer session to be running.
  26. //
  27. #include <windows.h>
  28. #include <winwlx.h>
  29. #define SCHED_SERVICE_NAME TEXT("Schedule")
  30. //
  31. // The following LOGON and LOGOFF defines must be kept in sync with
  32. // the definition in %sdxroot%\admin\services\sched\inc\common.hxx
  33. //
  34. #define SERVICE_CONTROL_USER_LOGON 128
  35. #define SERVICE_CONTROL_USER_LOGOFF 133
  36. DWORD WINAPI SchedStartShell(LPVOID lpvParam);
  37. DWORD WINAPI DoSchedStartShell(LPVOID lpvParam);
  38. DWORD WINAPI
  39. SchedEventLogOff(LPVOID lpvParam)
  40. //
  41. //
  42. // Routine Description:
  43. //
  44. // Send a logoff notification to the Task Scheduler service
  45. // via a user defined Service Control.
  46. //
  47. // Arguments:
  48. //
  49. // lpvParam - Winlogon notification info (unused as of yet)
  50. //
  51. // Return Value:
  52. //
  53. // Extended error status from Service control functions.
  54. //
  55. {
  56. DWORD status = ERROR_SUCCESS;
  57. SC_HANDLE hSC = NULL;
  58. SC_HANDLE hSvc = NULL;
  59. BOOL bSucceeded = FALSE;
  60. SERVICE_STATUS ServiceStatus;
  61. hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  62. if (hSC == NULL)
  63. {
  64. return GetLastError();
  65. }
  66. hSvc = OpenService(hSC, SCHED_SERVICE_NAME,
  67. SERVICE_USER_DEFINED_CONTROL);
  68. if (hSvc == NULL)
  69. {
  70. CloseServiceHandle(hSC);
  71. return GetLastError();
  72. }
  73. bSucceeded = ControlService(hSvc,
  74. SERVICE_CONTROL_USER_LOGOFF,
  75. &ServiceStatus);
  76. if( !bSucceeded )
  77. {
  78. status = GetLastError();
  79. }
  80. CloseServiceHandle(hSvc);
  81. CloseServiceHandle(hSC);
  82. return status;
  83. }
  84. DWORD WINAPI
  85. SchedStartShell(LPVOID lpvParam)
  86. {
  87. DWORD dwSessionId = 0;
  88. //
  89. // Don't send logon notification to Terminal Server sessions.
  90. //
  91. if (ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId) &&
  92. (dwSessionId == 0))
  93. {
  94. //
  95. // Queue the work to the thread pool since we may
  96. // be looping on the notification.
  97. //
  98. QueueUserWorkItem(DoSchedStartShell, lpvParam, WT_EXECUTELONGFUNCTION);
  99. }
  100. return GetLastError();
  101. }
  102. DWORD WINAPI
  103. DoSchedStartShell(LPVOID lpvParam)
  104. //
  105. //
  106. // Routine Description:
  107. //
  108. // Send a logon notification to the Task Scheduler service
  109. // via a user defined Service Control.
  110. //
  111. // Arguments:
  112. //
  113. // lpvParam - Winlogon notification info (unused as of yet)
  114. //
  115. // Return Value:
  116. //
  117. // Extended error status from Service control functions.
  118. //
  119. {
  120. DWORD status = ERROR_SUCCESS;
  121. PWLX_NOTIFICATION_INFO pTempInfo = (PWLX_NOTIFICATION_INFO) lpvParam;
  122. SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  123. if (hSC == NULL)
  124. {
  125. return GetLastError();
  126. }
  127. SC_HANDLE hSvc = OpenService(hSC, SCHED_SERVICE_NAME,
  128. SERVICE_USER_DEFINED_CONTROL);
  129. if (hSvc == NULL)
  130. {
  131. CloseServiceHandle(hSC);
  132. return GetLastError();
  133. }
  134. BOOL fSucceeded;
  135. const int NOTIFY_RETRIES = 20;
  136. const DWORD NOTIFY_SLEEP = 4000;
  137. //
  138. // Use a retry loop to notify the service. This is done
  139. // because, if the user logs in quickly, the service may not
  140. // be started when the shell runs this instance.
  141. //
  142. for (int i = 1; ; i++)
  143. {
  144. SERVICE_STATUS Status;
  145. fSucceeded = ControlService(hSvc,
  146. SERVICE_CONTROL_USER_LOGON,
  147. &Status);
  148. if (fSucceeded)
  149. {
  150. break;
  151. }
  152. if (i >= NOTIFY_RETRIES)
  153. {
  154. status = GetLastError();
  155. break;
  156. }
  157. Sleep(NOTIFY_SLEEP);
  158. }
  159. CloseServiceHandle(hSvc);
  160. CloseServiceHandle(hSC);
  161. return status;
  162. }