1import salt.utils.platform 2from salt.exceptions import CommandExecutionError 3 4try: 5 import pywintypes 6 import win32security 7 import win32service 8 9 HAS_WIN32 = True 10except ImportError: 11 HAS_WIN32 = False 12 13SERVICE_TYPE = { 14 1: "Kernel Driver", 15 2: "File System Driver", 16 4: "Adapter Driver", 17 8: "Recognizer Driver", 18 16: "Win32 Own Process", 19 32: "Win32 Share Process", 20 256: "Interactive", 21 "kernel": 1, 22 "filesystem": 2, 23 "adapter": 4, 24 "recognizer": 8, 25 "own": 16, 26 "share": 32, 27} 28 29SERVICE_CONTROLS = { 30 1: "Stop", 31 2: "Pause/Continue", 32 4: "Shutdown", 33 8: "Change Parameters", 34 16: "Netbind Change", 35 32: "Hardware Profile Change", 36 64: "Power Event", 37 128: "Session Change", 38 256: "Pre-Shutdown", 39 512: "Time Change", 40 1024: "Trigger Event", 41} 42 43SERVICE_STATE = { 44 1: "Stopped", 45 2: "Start Pending", 46 3: "Stop Pending", 47 4: "Running", 48 5: "Continue Pending", 49 6: "Pause Pending", 50 7: "Paused", 51} 52 53SERVICE_ERRORS = {0: "No Error", 1066: "Service Specific Error"} 54 55SERVICE_START_TYPE = { 56 "boot": 0, 57 "system": 1, 58 "auto": 2, 59 "manual": 3, 60 "disabled": 4, 61 0: "Boot", 62 1: "System", 63 2: "Auto", 64 3: "Manual", 65 4: "Disabled", 66} 67 68SERVICE_ERROR_CONTROL = { 69 0: "Ignore", 70 1: "Normal", 71 2: "Severe", 72 3: "Critical", 73 "ignore": 0, 74 "normal": 1, 75 "severe": 2, 76 "critical": 3, 77} 78 79__virtualname__ = "win_service" 80 81 82def __virtual__(): 83 """ 84 Only load if Win32 Libraries are installed 85 """ 86 if not salt.utils.platform.is_windows(): 87 return False, "win_dacl: Requires Windows" 88 89 if not HAS_WIN32: 90 return False, "win_dacl: Requires pywin32" 91 92 return __virtualname__ 93 94 95def info(name): 96 """ 97 Get information about a service on the system 98 99 Args: 100 name (str): The name of the service. This is not the display name. Use 101 ``get_service_name`` to find the service name. 102 103 Returns: 104 dict: A dictionary containing information about the service. 105 106 CLI Example: 107 108 .. code-block:: bash 109 110 salt '*' service.info spooler 111 """ 112 try: 113 handle_scm = win32service.OpenSCManager( 114 None, None, win32service.SC_MANAGER_CONNECT 115 ) 116 except pywintypes.error as exc: 117 raise CommandExecutionError( 118 "Failed to connect to the SCM: {}".format(exc.strerror) 119 ) 120 121 try: 122 handle_svc = win32service.OpenService( 123 handle_scm, 124 name, 125 win32service.SERVICE_ENUMERATE_DEPENDENTS 126 | win32service.SERVICE_INTERROGATE 127 | win32service.SERVICE_QUERY_CONFIG 128 | win32service.SERVICE_QUERY_STATUS, 129 ) 130 except pywintypes.error as exc: 131 raise CommandExecutionError("Failed To Open {}: {}".format(name, exc.strerror)) 132 133 try: 134 config_info = win32service.QueryServiceConfig(handle_svc) 135 status_info = win32service.QueryServiceStatusEx(handle_svc) 136 137 try: 138 description = win32service.QueryServiceConfig2( 139 handle_svc, win32service.SERVICE_CONFIG_DESCRIPTION 140 ) 141 except pywintypes.error: 142 description = "Failed to get description" 143 144 delayed_start = win32service.QueryServiceConfig2( 145 handle_svc, win32service.SERVICE_CONFIG_DELAYED_AUTO_START_INFO 146 ) 147 finally: 148 win32service.CloseServiceHandle(handle_scm) 149 win32service.CloseServiceHandle(handle_svc) 150 151 ret = dict() 152 try: 153 sid = win32security.LookupAccountName("", "NT Service\\{}".format(name))[0] 154 ret["sid"] = win32security.ConvertSidToStringSid(sid) 155 except pywintypes.error: 156 ret["sid"] = "Failed to get SID" 157 158 ret["BinaryPath"] = config_info[3] 159 ret["LoadOrderGroup"] = config_info[4] 160 ret["TagID"] = config_info[5] 161 ret["Dependencies"] = config_info[6] 162 ret["ServiceAccount"] = config_info[7] 163 ret["DisplayName"] = config_info[8] 164 ret["Description"] = description 165 ret["Status_ServiceCode"] = status_info["ServiceSpecificExitCode"] 166 ret["Status_CheckPoint"] = status_info["CheckPoint"] 167 ret["Status_WaitHint"] = status_info["WaitHint"] 168 ret["StartTypeDelayed"] = delayed_start 169 170 flags = list() 171 for bit in SERVICE_TYPE: 172 if isinstance(bit, int): 173 if config_info[0] & bit: 174 flags.append(SERVICE_TYPE[bit]) 175 176 ret["ServiceType"] = flags if flags else config_info[0] 177 178 flags = list() 179 for bit in SERVICE_CONTROLS: 180 if status_info["ControlsAccepted"] & bit: 181 flags.append(SERVICE_CONTROLS[bit]) 182 183 ret["ControlsAccepted"] = flags if flags else status_info["ControlsAccepted"] 184 185 try: 186 ret["Status_ExitCode"] = SERVICE_ERRORS[status_info["Win32ExitCode"]] 187 except KeyError: 188 ret["Status_ExitCode"] = status_info["Win32ExitCode"] 189 190 try: 191 ret["StartType"] = SERVICE_START_TYPE[config_info[1]] 192 except KeyError: 193 ret["StartType"] = config_info[1] 194 195 try: 196 ret["ErrorControl"] = SERVICE_ERROR_CONTROL[config_info[2]] 197 except KeyError: 198 ret["ErrorControl"] = config_info[2] 199 200 try: 201 ret["Status"] = SERVICE_STATE[status_info["CurrentState"]] 202 except KeyError: 203 ret["Status"] = status_info["CurrentState"] 204 205 return ret 206