/* * APIs to manage the timeservice on another machine. */ #include #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); }