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.

235 lines
6.1 KiB

  1. /*
  2. * APIs to manage the timeservice on another machine.
  3. */
  4. #include <windows.h>
  5. #include "tsconfig.h"
  6. #include "stdio.h"
  7. // data and definitions
  8. //
  9. // API to set the new primary target and to cycle the service. This
  10. // is used by the cluster code to distribute new information
  11. //
  12. DWORD
  13. TSNewSource(
  14. IN LPTSTR ServerName,
  15. IN LPTSTR SourceName,
  16. IN DWORD Reserved
  17. )
  18. /*++
  19. Routine Description:
  20. Set the PrimarySource for the Time Service on the given server system to
  21. the specified source.
  22. Arguments:
  23. ServerName - The remote system on which to set the PrimarySource.
  24. SourceName - The PrimarySource for the Time Service's time.
  25. Reserved - not used.
  26. Return Value:
  27. ERROR_SUCCESS if successful.
  28. A Win32 error code on failure.
  29. --*/
  30. {
  31. HKEY hKey = 0, hKey1 = 0;
  32. SC_HANDLE scHandle, scHandle1 = 0;
  33. PWCHAR pwszData;
  34. PWCHAR pwszVersion = NULL;
  35. DWORD err;
  36. DWORD dwSize, dwTotalSize;
  37. DWORD type;
  38. //
  39. // REG_MULTI_SZ data needs an extra NULL at the end. So copy
  40. // the string into a buffer large enough to add a NULL.
  41. //
  42. dwSize = wcslen(SourceName);
  43. dwTotalSize = (dwSize + 1) * sizeof(WCHAR);
  44. pwszData = LocalAlloc(LMEM_FIXED,
  45. dwTotalSize);
  46. if(!pwszData) {
  47. return(ERROR_NOT_ENOUGH_MEMORY);
  48. }
  49. wcscpy(pwszData, SourceName);
  50. pwszData[dwSize] = (WCHAR)0;
  51. //
  52. // Open the remote service controller.
  53. //
  54. scHandle = OpenSCManager(ServerName,
  55. NULL,
  56. SERVICE_START |
  57. SERVICE_STOP) ;
  58. if (!scHandle) {
  59. err = GetLastError();
  60. goto NonStart;
  61. }
  62. //
  63. // Make sure the remote registry is accessible as well
  64. //
  65. err = RegConnectRegistry(ServerName,
  66. HKEY_LOCAL_MACHINE,
  67. &hKey);
  68. if ((err == ERROR_SUCCESS)
  69. &&
  70. (err = RegOpenKeyEx(hKey,
  71. TSKEY,
  72. 0,
  73. KEY_READ | KEY_WRITE,
  74. &hKey1)) == ERROR_SUCCESS)
  75. {
  76. //
  77. // First check the Time Service version to see if we should even
  78. // attempt to stop it.
  79. //
  80. dwSize = 2;
  81. retry:
  82. if ( pwszVersion != NULL ) {
  83. LocalFree(pwszVersion);
  84. }
  85. pwszVersion = LocalAlloc( LMEM_FIXED, dwSize );
  86. if ( pwszVersion == NULL ) {
  87. return(ERROR_NOT_ENOUGH_MEMORY);
  88. }
  89. err = RegQueryValueEx(hKey1,
  90. TEXT("Version"),
  91. 0,
  92. &type,
  93. (PBYTE)pwszVersion,
  94. &dwSize);
  95. if ( err == ERROR_MORE_DATA ) {
  96. goto retry;
  97. }
  98. if ( (err != ERROR_FILE_NOT_FOUND) &&
  99. ((err != ERROR_SUCCESS) ||
  100. (type != REG_SZ)) ) {
  101. LocalFree(pwszVersion);
  102. return(err);
  103. }
  104. if ( (err != ERROR_FILE_NOT_FOUND) &&
  105. (_wcsicmp( pwszVersion, L"Base" ) != 0) ) {
  106. printf("Remote Time Service is not running as a base service!\n");
  107. LocalFree(pwszVersion);
  108. return(ERROR_SUCCESS);
  109. }
  110. LocalFree(pwszVersion);
  111. //
  112. //
  113. // Change the key now
  114. //
  115. err = RegSetValueEx(hKey1,
  116. TEXT("PrimarySource"),
  117. 0,
  118. REG_MULTI_SZ,
  119. (PBYTE)pwszData,
  120. dwTotalSize);
  121. if (err == ERROR_SUCCESS) {
  122. DWORD retryCount = 20;
  123. //
  124. // cycle the service. If the service cannot be opened,
  125. // return no error. If the service can be opened but
  126. // is not started, also return no error.
  127. //
  128. scHandle1 = OpenService(scHandle,
  129. TEXT("TimeServ"),
  130. SERVICE_START |
  131. SERVICE_STOP | SERVICE_INTERROGATE);
  132. if (scHandle1) {
  133. SERVICE_STATUS ss;
  134. BOOL fStatus;
  135. fStatus = ControlService(scHandle1,
  136. SERVICE_CONTROL_INTERROGATE,
  137. &ss);
  138. if (!fStatus) {
  139. //
  140. // can't control it. If that is because it's
  141. // not active, report OK.
  142. //
  143. err = GetLastError();
  144. if (err == ERROR_SERVICE_NOT_ACTIVE) {
  145. if (!StartService(scHandle1, 0, 0)) {
  146. err = GetLastError();
  147. } else {
  148. err = ERROR_SUCCESS;
  149. }
  150. }
  151. } else if (ss.dwCurrentState == SERVICE_RUNNING) {
  152. if (!ControlService(scHandle1,
  153. SERVICE_CONTROL_STOP,
  154. &ss) ) {
  155. err = GetLastError();
  156. } else {
  157. // Wait for Service to stop.
  158. ss.dwCurrentState = SERVICE_RUNNING;
  159. while ( (ss.dwCurrentState != SERVICE_STOPPED) &&
  160. retryCount-- ) {
  161. ControlService(scHandle1,
  162. SERVICE_CONTROL_INTERROGATE,
  163. &ss);
  164. Sleep(300);
  165. }
  166. if ( (_wcsicmp( ServerName, SourceName ) != 0) &&
  167. !StartService(scHandle1, 0, 0) ) {
  168. err = GetLastError();
  169. }
  170. }
  171. }
  172. }
  173. }
  174. }
  175. if (scHandle1) {
  176. CloseServiceHandle(scHandle1);
  177. }
  178. CloseServiceHandle(scHandle);
  179. if(hKey1) {
  180. RegCloseKey(hKey1);
  181. }
  182. if(hKey) {
  183. RegCloseKey(hKey);
  184. }
  185. NonStart:
  186. LocalFree(pwszData);
  187. return(err);
  188. }