Leaked source code of windows server 2003
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.

191 lines
4.9 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. {
  93. if (dwSessionId == 0)
  94. {
  95. //
  96. // Queue the work to the thread pool since we may
  97. // be looping on the notification.
  98. //
  99. if (QueueUserWorkItem(DoSchedStartShell, lpvParam, WT_EXECUTELONGFUNCTION))
  100. return ERROR_SUCCESS;
  101. }
  102. else
  103. return ERROR_SUCCESS;
  104. }
  105. return GetLastError();
  106. }
  107. DWORD WINAPI
  108. DoSchedStartShell(LPVOID lpvParam)
  109. //
  110. //
  111. // Routine Description:
  112. //
  113. // Send a logon notification to the Task Scheduler service
  114. // via a user defined Service Control.
  115. //
  116. // Arguments:
  117. //
  118. // lpvParam - Winlogon notification info (unused as of yet)
  119. //
  120. // Return Value:
  121. //
  122. // Extended error status from Service control functions.
  123. //
  124. {
  125. DWORD status = ERROR_SUCCESS;
  126. PWLX_NOTIFICATION_INFO pTempInfo = (PWLX_NOTIFICATION_INFO) lpvParam;
  127. SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  128. if (hSC == NULL)
  129. {
  130. return GetLastError();
  131. }
  132. SC_HANDLE hSvc = OpenService(hSC, SCHED_SERVICE_NAME,
  133. SERVICE_USER_DEFINED_CONTROL);
  134. if (hSvc == NULL)
  135. {
  136. CloseServiceHandle(hSC);
  137. return GetLastError();
  138. }
  139. BOOL fSucceeded;
  140. const int NOTIFY_RETRIES = 20;
  141. const DWORD NOTIFY_SLEEP = 4000;
  142. //
  143. // Use a retry loop to notify the service. This is done
  144. // because, if the user logs in quickly, the service may not
  145. // be started when the shell runs this instance.
  146. //
  147. for (int i = 1; ; i++)
  148. {
  149. SERVICE_STATUS Status;
  150. fSucceeded = ControlService(hSvc,
  151. SERVICE_CONTROL_USER_LOGON,
  152. &Status);
  153. if (fSucceeded)
  154. {
  155. break;
  156. }
  157. if (i >= NOTIFY_RETRIES)
  158. {
  159. status = GetLastError();
  160. break;
  161. }
  162. Sleep(NOTIFY_SLEEP);
  163. }
  164. CloseServiceHandle(hSvc);
  165. CloseServiceHandle(hSC);
  166. return status;
  167. }