236 lines
6.1 KiB
C
236 lines
6.1 KiB
C
|
/*
|
||
|
* APIs to manage the timeservice on another machine.
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "tsconfig.h"
|
||
|
#include "stdio.h"
|
||
|
|
||
|
// data and definitions
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// API to set the new primary target and to cycle the service. This
|
||
|
// is used by the cluster code to distribute new information
|
||
|
//
|
||
|
|
||
|
DWORD
|
||
|
TSNewSource(
|
||
|
IN LPTSTR ServerName,
|
||
|
IN LPTSTR SourceName,
|
||
|
IN DWORD Reserved
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Set the PrimarySource for the Time Service on the given server system to
|
||
|
the specified source.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ServerName - The remote system on which to set the PrimarySource.
|
||
|
|
||
|
SourceName - The PrimarySource for the Time Service's time.
|
||
|
|
||
|
Reserved - not used.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS if successful.
|
||
|
|
||
|
A Win32 error code on failure.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HKEY hKey = 0, hKey1 = 0;
|
||
|
SC_HANDLE scHandle, scHandle1 = 0;
|
||
|
PWCHAR pwszData;
|
||
|
PWCHAR pwszVersion = NULL;
|
||
|
DWORD err;
|
||
|
DWORD dwSize, dwTotalSize;
|
||
|
DWORD type;
|
||
|
|
||
|
//
|
||
|
// REG_MULTI_SZ data needs an extra NULL at the end. So copy
|
||
|
// the string into a buffer large enough to add a NULL.
|
||
|
//
|
||
|
dwSize = wcslen(SourceName);
|
||
|
|
||
|
dwTotalSize = (dwSize + 1) * sizeof(WCHAR);
|
||
|
|
||
|
pwszData = LocalAlloc(LMEM_FIXED,
|
||
|
dwTotalSize);
|
||
|
|
||
|
if(!pwszData) {
|
||
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
|
||
|
wcscpy(pwszData, SourceName);
|
||
|
pwszData[dwSize] = (WCHAR)0;
|
||
|
|
||
|
//
|
||
|
// Open the remote service controller.
|
||
|
//
|
||
|
scHandle = OpenSCManager(ServerName,
|
||
|
NULL,
|
||
|
SERVICE_START |
|
||
|
SERVICE_STOP) ;
|
||
|
|
||
|
if (!scHandle) {
|
||
|
err = GetLastError();
|
||
|
goto NonStart;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure the remote registry is accessible as well
|
||
|
//
|
||
|
|
||
|
err = RegConnectRegistry(ServerName,
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
&hKey);
|
||
|
|
||
|
if ((err == ERROR_SUCCESS)
|
||
|
&&
|
||
|
(err = RegOpenKeyEx(hKey,
|
||
|
TSKEY,
|
||
|
0,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey1)) == ERROR_SUCCESS)
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// First check the Time Service version to see if we should even
|
||
|
// attempt to stop it.
|
||
|
//
|
||
|
dwSize = 2;
|
||
|
|
||
|
retry:
|
||
|
if ( pwszVersion != NULL ) {
|
||
|
LocalFree(pwszVersion);
|
||
|
}
|
||
|
pwszVersion = LocalAlloc( LMEM_FIXED, dwSize );
|
||
|
if ( pwszVersion == NULL ) {
|
||
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
err = RegQueryValueEx(hKey1,
|
||
|
TEXT("Version"),
|
||
|
0,
|
||
|
&type,
|
||
|
(PBYTE)pwszVersion,
|
||
|
&dwSize);
|
||
|
if ( err == ERROR_MORE_DATA ) {
|
||
|
goto retry;
|
||
|
}
|
||
|
|
||
|
if ( (err != ERROR_FILE_NOT_FOUND) &&
|
||
|
((err != ERROR_SUCCESS) ||
|
||
|
(type != REG_SZ)) ) {
|
||
|
LocalFree(pwszVersion);
|
||
|
return(err);
|
||
|
}
|
||
|
|
||
|
if ( (err != ERROR_FILE_NOT_FOUND) &&
|
||
|
(_wcsicmp( pwszVersion, L"Base" ) != 0) ) {
|
||
|
printf("Remote Time Service is not running as a base service!\n");
|
||
|
LocalFree(pwszVersion);
|
||
|
return(ERROR_SUCCESS);
|
||
|
}
|
||
|
LocalFree(pwszVersion);
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Change the key now
|
||
|
//
|
||
|
|
||
|
err = RegSetValueEx(hKey1,
|
||
|
TEXT("PrimarySource"),
|
||
|
0,
|
||
|
REG_MULTI_SZ,
|
||
|
(PBYTE)pwszData,
|
||
|
dwTotalSize);
|
||
|
|
||
|
if (err == ERROR_SUCCESS) {
|
||
|
DWORD retryCount = 20;
|
||
|
|
||
|
//
|
||
|
// cycle the service. If the service cannot be opened,
|
||
|
// return no error. If the service can be opened but
|
||
|
// is not started, also return no error.
|
||
|
//
|
||
|
|
||
|
scHandle1 = OpenService(scHandle,
|
||
|
TEXT("TimeServ"),
|
||
|
SERVICE_START |
|
||
|
SERVICE_STOP | SERVICE_INTERROGATE);
|
||
|
|
||
|
if (scHandle1) {
|
||
|
SERVICE_STATUS ss;
|
||
|
BOOL fStatus;
|
||
|
|
||
|
fStatus = ControlService(scHandle1,
|
||
|
SERVICE_CONTROL_INTERROGATE,
|
||
|
&ss);
|
||
|
if (!fStatus) {
|
||
|
//
|
||
|
// can't control it. If that is because it's
|
||
|
// not active, report OK.
|
||
|
//
|
||
|
err = GetLastError();
|
||
|
if (err == ERROR_SERVICE_NOT_ACTIVE) {
|
||
|
if (!StartService(scHandle1, 0, 0)) {
|
||
|
err = GetLastError();
|
||
|
} else {
|
||
|
err = ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
} else if (ss.dwCurrentState == SERVICE_RUNNING) {
|
||
|
if (!ControlService(scHandle1,
|
||
|
SERVICE_CONTROL_STOP,
|
||
|
&ss) ) {
|
||
|
err = GetLastError();
|
||
|
} else {
|
||
|
// Wait for Service to stop.
|
||
|
ss.dwCurrentState = SERVICE_RUNNING;
|
||
|
while ( (ss.dwCurrentState != SERVICE_STOPPED) &&
|
||
|
retryCount-- ) {
|
||
|
|
||
|
ControlService(scHandle1,
|
||
|
SERVICE_CONTROL_INTERROGATE,
|
||
|
&ss);
|
||
|
Sleep(300);
|
||
|
}
|
||
|
if ( (_wcsicmp( ServerName, SourceName ) != 0) &&
|
||
|
!StartService(scHandle1, 0, 0) ) {
|
||
|
err = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (scHandle1) {
|
||
|
CloseServiceHandle(scHandle1);
|
||
|
}
|
||
|
|
||
|
CloseServiceHandle(scHandle);
|
||
|
|
||
|
if(hKey1) {
|
||
|
RegCloseKey(hKey1);
|
||
|
}
|
||
|
|
||
|
if(hKey) {
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
NonStart:
|
||
|
LocalFree(pwszData);
|
||
|
return(err);
|
||
|
}
|
||
|
|
||
|
|