/*++ Copyright (c) 1997 Microsoft Corporation Module Name: addsrvc.c Abstract: Create the file replication service (ntfrs): addsrvc Author: Billy J. Fuller 2-Sep-1997 Environment User mode winnt --*/ #include #include #include #include #include #include // // Lower case // #define FRS_WCSLWR(_s_) \ { \ if (_s_) { \ _wcslwr(_s_); \ } \ } SC_HANDLE OpenServiceHandle( IN PWCHAR ServiceName ) /*++ Routine Description: Open a service on a machine. Arguments: ServiceName - the service to open Return Value: The service's handle or NULL. --*/ { SC_HANDLE SCMHandle; SC_HANDLE ServiceHandle; // // Attempt to contact the SC manager. // SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (SCMHandle == NULL) { printf("Couldn't open service control manager; error %d\n", GetLastError()); return NULL; } // // Contact the service. // ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS); CloseServiceHandle(SCMHandle); return ServiceHandle; } DWORD FrsGetServiceState( IN PWCHAR ServiceName ) /*++ Routine Description: Return the service's state Arguments: ServiceName - the service to check Return Value: The service's state or 0 if the state could not be obtained. --*/ { BOOL Status; SC_HANDLE ServiceHandle; SERVICE_STATUS ServiceStatus; // // Open the service. // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) return 0; // // Get the service's status // if (!ControlService(ServiceHandle, SERVICE_CONTROL_INTERROGATE, &ServiceStatus)) { CloseServiceHandle(ServiceHandle); return GetLastError(); } return ServiceStatus.dwCurrentState; } VOID FrsWaitServicePending( IN PWCHAR ServiceName, IN ULONG IntervalMS, IN ULONG TotalMS ) /*++ Routine Description: Wait for a service to leave any "pending" state. Check every so often, up to a maximum time. Arguments: ServiceName - Name of the NT service to interrogate. IntervalMS - Check every IntervalMS milliseconds. TotalMS - Stop checking after this long. Return Value: TRUE - Service is not in a pending state FALSE - Service is still in a pending state --*/ { DWORD State; do { State = FrsGetServiceState(ServiceName); if (State == 0) return; switch (State) { case ERROR_IO_PENDING: printf("IO is pending for %ws; waiting\n", ServiceName); break; case SERVICE_START_PENDING: printf("Start is pending for %ws; waiting\n", ServiceName); break; case SERVICE_STOP_PENDING: printf("Stop is pending for %ws; waiting\n", ServiceName); break; case SERVICE_CONTINUE_PENDING: printf("Continue is pending for %ws; waiting\n", ServiceName); break; case SERVICE_PAUSE_PENDING: printf("Pause is pending for %ws; waiting\n", ServiceName); break; default:; return; } Sleep(IntervalMS); } while ((TotalMS -= IntervalMS) > 0); } VOID FrsStartService( IN PWCHAR ServiceName ) /*++ Routine Description: Start a service on a machine. Arguments: ServiceName - the service to start Return Value: None. --*/ { SC_HANDLE ServiceHandle; // // Open the service. // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) { printf("Couldn't open %ws\n", ServiceName); return; } // // Start the service // if (!StartService(ServiceHandle, 0, NULL)) { printf("Couldn't start %ws; error %d\n", ServiceName, GetLastError()); CloseServiceHandle(ServiceHandle); return; } CloseServiceHandle(ServiceHandle); printf("Started %ws\n", ServiceName); } VOID FrsStopService( IN PWCHAR ServiceName ) /*++ Routine Description: Stop a service on a machine. Arguments: ServiceName - the service to stop Return Value: None. --*/ { BOOL Status; SC_HANDLE ServiceHandle; SERVICE_STATUS ServiceStatus; // // Open the service. // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) { printf("Couldn't open %ws\n", ServiceName); return; } // // Stop the service // Status = ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus); if (!Status) { printf("Couldn't stop %ws; error %d\n", ServiceName, GetLastError()); CloseServiceHandle(ServiceHandle); return; } CloseServiceHandle(ServiceHandle); printf("Stopped %ws\n", ServiceName); } VOID FrsPauseService( IN PWCHAR ServiceName ) /*++ Routine Description: Pause a service on a machine. Arguments: ServiceName - the service to pause Return Value: None. --*/ { BOOL Status; SC_HANDLE ServiceHandle; SERVICE_STATUS ServiceStatus; // // Open the service. // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) { printf("Couldn't open %ws\n", ServiceName); return; } // // Stop the service // Status = ControlService(ServiceHandle, SERVICE_CONTROL_PAUSE, &ServiceStatus); if (!Status) { printf("Couldn't pause %ws; error %d\n", ServiceName, GetLastError()); CloseServiceHandle(ServiceHandle); return; } CloseServiceHandle(ServiceHandle); printf("Paused %ws\n", ServiceName); } VOID FrsContinueService( IN PWCHAR ServiceName ) /*++ Routine Description: Continue a service on a machine. Arguments: ServiceName - the service to continue Return Value: None. --*/ { BOOL Status; SC_HANDLE ServiceHandle; SERVICE_STATUS ServiceStatus; // // Open the service. // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) { printf("Couldn't open %ws\n", ServiceName); return; } // // Stop the service // Status = ControlService(ServiceHandle, SERVICE_CONTROL_CONTINUE, &ServiceStatus); if (!Status) { printf("Couldn't continue %ws; error %d\n", ServiceName, GetLastError()); CloseServiceHandle(ServiceHandle); return; } CloseServiceHandle(ServiceHandle); printf("Continued %ws\n", ServiceName); } VOID FrsDeleteService( IN PWCHAR ServiceName ) /*++ Routine Description: Delete a service on a machine. Arguments: ServiceName - the service to delete Return Value: None. --*/ { SC_HANDLE ServiceHandle; // FrsWaitServicePending(ServiceName, 5000, 20000); // // Open the service // ServiceHandle = OpenServiceHandle(ServiceName); if (ServiceHandle == NULL) { return; } // // Delete the service // if (!DeleteService(ServiceHandle) && GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) { printf("Couldn't delete %ws; error %d\n", ServiceName, GetLastError()); } CloseServiceHandle(ServiceHandle); printf("Deleted %ws\n", ServiceName); } VOID FrsCreateService( IN PWCHAR ServiceName, IN PWCHAR PathName, IN PWCHAR DisplayName ) /*++ Routine Description: If the service doesn't exist on the machine, create it. Arguments: ServiceName - the service to create PathName - the path of the service's .exe DisplayName - the display name of the service Return Value: TRUE - Service was created (or already existed) FALSE - Service was not created and didn't already exist --*/ { SC_HANDLE SCMHandle; SC_HANDLE ServiceHandle; // // Attempt to contact the SC manager. // SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (SCMHandle == NULL) { printf("Couldn't open service control manager; error %d\n", GetLastError()); return; } // // Create the service // ServiceHandle = CreateService( SCMHandle, ServiceName, DisplayName, SERVICE_ALL_ACCESS, // XXX is this right!!! SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, PathName, NULL, // No load order group NULL, // No Tag Id required L"eventlog\0rpcss\0", NULL, NULL); // No password if (ServiceHandle == NULL) { FrsWaitServicePending(ServiceName, 5000, 20000); // // Create the service // ServiceHandle = CreateService(SCMHandle, ServiceName, DisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, PathName, NULL, NULL, L"eventlog\0rpcss\0", NULL, NULL); } CloseServiceHandle(SCMHandle); // // Couldn't create the service // if (ServiceHandle == NULL) { printf("Couldn't create %ws; error %d\n", ServiceName, GetLastError()); } else { CloseServiceHandle(ServiceHandle); printf("Created %ws\n", ServiceName); } } PWCHAR * ConvertArgv( DWORD argc, PCHAR *argv ) /*++ Routine Description: Convert short char argv into wide char argv Arguments: argc - From main argv - From main Return Value: Address of the new argv --*/ { PWCHAR *newargv; newargv = malloc((argc + 1) * sizeof(PWCHAR)); newargv[argc] = NULL; while (argc-- >= 1) { newargv[argc] = malloc((strlen(argv[argc]) + 1) * sizeof(WCHAR)); wsprintf(newargv[argc], L"%hs", argv[argc]); FRS_WCSLWR(newargv[argc]); } return newargv; } VOID _cdecl main( IN DWORD argc, IN PCHAR *argv ) /*++ Routine Description: Create the file replication service: addsrvc Arguments: None. Return Value: None. --*/ { DWORD i; PWCHAR *NewArgv; if (argc == 1) { printf("service create [full path to exe]\n"); printf("service delete\n"); printf("service start\n"); printf("service stop\n"); printf("service pause\n"); printf("service continue\n"); return; } NewArgv = ConvertArgv(argc, argv); // // CLI overrides registry // for (i = 1; i < argc; ++i) { // // create // if (wcsstr(NewArgv[i], L"create")) { FrsDeleteService(SERVICE_NAME); FrsCreateService(SERVICE_NAME, NewArgv[2], SERVICE_LONG_NAME); break; // // delete // } else if (wcsstr(NewArgv[i], L"delete")) { FrsDeleteService(SERVICE_NAME); break; // // start // } else if (wcsstr(NewArgv[i], L"start")) { FrsStartService(SERVICE_NAME); break; // // stop // } else if (wcsstr(NewArgv[i], L"stop")) { FrsStopService(SERVICE_NAME); break; // // pause // } else if (wcsstr(NewArgv[i], L"pause")) { FrsPauseService(SERVICE_NAME); break; // // continue // } else if (wcsstr(NewArgv[i], L"continue")) { FrsContinueService(SERVICE_NAME); break; // // unknown // } else { printf("Don't understand \"%ws\"\n", NewArgv[i]); } } }