1# Copyright (c) 2016 Cloudbase Solutions Srl 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at: 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import sys 16 17if sys.platform != 'win32': 18 raise Exception("Intended to use only on Windows") 19else: 20 import ntsecuritycon 21 import pywintypes 22 import win32con 23 import win32event 24 import win32file 25 import win32pipe 26 import win32security 27 import winerror 28 29 30def close_handle(handle, logger=None): 31 try: 32 win32file.CloseHandle(handle) 33 return None 34 except pywintypes.error as e: 35 if logger is not None: 36 logger("failed to close handle: %s" % e.strerror) 37 return e.winerror 38 39 40def windows_create_pipe(sAttrs=-1, nSize=None): 41 # Default values if parameters are not passed 42 if sAttrs == -1: 43 sAttrs = win32security.SECURITY_ATTRIBUTES() 44 sAttrs.bInheritHandle = 1 45 if nSize is None: 46 # If this parameter is zero, the system uses the default buffer size. 47 nSize = 0 48 49 try: 50 (read_pipe, write_pipe) = win32pipe.CreatePipe(sAttrs, nSize) 51 except pywintypes.error: 52 raise 53 54 return (read_pipe, write_pipe) 55 56 57def windows_read_pipe(fd, length): 58 try: 59 (error, data) = win32file.ReadFile(fd, length) 60 return error, data 61 except pywintypes.error as e: 62 return e.winerror, "" 63 64 65def create_file(filename, desiredAccess=None, shareMode=None, attributes=-1, 66 CreationDisposition=None, flagsAndAttributes=None, 67 hTemplateFile=-1): 68 # Default values if parameters are not passed 69 if desiredAccess is None: 70 desiredAccess = win32file.GENERIC_READ | win32file.GENERIC_WRITE 71 if shareMode is None: 72 shareMode = 0 73 if attributes == -1: 74 # attributes can be None 75 attributes = None 76 if CreationDisposition is None: 77 CreationDisposition = win32file.OPEN_EXISTING 78 if flagsAndAttributes is None: 79 flagsAndAttributes = (win32file.FILE_ATTRIBUTE_NORMAL | 80 win32file.FILE_FLAG_OVERLAPPED | 81 win32file.FILE_FLAG_NO_BUFFERING) 82 if hTemplateFile == -1: 83 hTemplateFile = None 84 85 try: 86 npipe = win32file.CreateFile(filename, 87 desiredAccess, 88 shareMode, 89 attributes, 90 CreationDisposition, 91 flagsAndAttributes, 92 hTemplateFile) 93 except pywintypes.error: 94 raise 95 return npipe 96 97 98def write_file(handle, data, overlapped=None): 99 try: 100 (errCode, nBytesWritten) = win32file.WriteFile(handle, 101 data, 102 overlapped) 103 # Note: win32file.WriteFile doesn't throw an exception 104 # in case it receives ERROR_IO_PENDING. 105 return (errCode, nBytesWritten) 106 except pywintypes.error as e: 107 return (e.winerror, 0) 108 109 110def read_file(handle, bufsize, overlapped=None): 111 try: 112 # Note: win32file.ReadFile doesn't throw an exception 113 # in case it receives ERROR_IO_PENDING. 114 (errCode, read_buffer) = win32file.ReadFile( 115 handle, bufsize, overlapped) 116 return (errCode, read_buffer) 117 except pywintypes.error as e: 118 return (e.winerror, "") 119 120 121def create_named_pipe(pipename, openMode=None, pipeMode=None, 122 nMaxInstances=None, nOutBufferSize=None, 123 nInBufferSize=None, nDefaultTimeOut=None, 124 saAttr=-1): 125 # Default values if parameters are not passed 126 if openMode is None: 127 openMode = win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED 128 if pipeMode is None: 129 pipeMode = (win32con.PIPE_TYPE_MESSAGE | 130 win32con.PIPE_READMODE_BYTE | 131 win32con.PIPE_WAIT) 132 if nMaxInstances is None: 133 nMaxInstances = 64 134 if nOutBufferSize is None: 135 nOutBufferSize = 65000 136 if nInBufferSize is None: 137 nInBufferSize = 65000 138 if nDefaultTimeOut is None: 139 nDefaultTimeOut = 0 140 if saAttr == -1: 141 # saAttr can be None 142 saAttr = win32security.SECURITY_ATTRIBUTES() 143 144 # The identifier authority. 145 sia = ntsecuritycon.SECURITY_NT_AUTHORITY 146 147 # Initialize the SID. 148 remoteAccessSid = win32security.SID() 149 remoteAccessSid.Initialize( 150 sia, # The identifier authority. 151 1) # The number of sub authorities to allocate. 152 # Disable access over network. 153 remoteAccessSid.SetSubAuthority( 154 0, # The index of the sub authority to set 155 ntsecuritycon.SECURITY_NETWORK_RID) 156 157 allowedPsids = [] 158 # Allow Windows Services to access the Named Pipe. 159 allowedPsid_0 = win32security.SID() 160 allowedPsid_0.Initialize( 161 sia, # The identifier authority. 162 1) # The number of sub authorities to allocate. 163 allowedPsid_0.SetSubAuthority( 164 0, # The index of the sub authority to set 165 ntsecuritycon.SECURITY_LOCAL_SYSTEM_RID) 166 # Allow Administrators to access the Named Pipe. 167 allowedPsid_1 = win32security.SID() 168 allowedPsid_1.Initialize( 169 sia, # The identifier authority. 170 2) # The number of sub authorities to allocate. 171 allowedPsid_1.SetSubAuthority( 172 0, # The index of the sub authority to set 173 ntsecuritycon.SECURITY_BUILTIN_DOMAIN_RID) 174 allowedPsid_1.SetSubAuthority( 175 1, # The index of the sub authority to set 176 ntsecuritycon.DOMAIN_ALIAS_RID_ADMINS) 177 178 allowedPsids.append(allowedPsid_0) 179 allowedPsids.append(allowedPsid_1) 180 181 # Initialize an ACL. 182 acl = win32security.ACL() 183 acl.Initialize() 184 # Add denied ACL. 185 acl.AddAccessDeniedAce(win32security.ACL_REVISION, 186 ntsecuritycon.GENERIC_ALL, 187 remoteAccessSid) 188 # Add allowed ACLs. 189 for allowedPsid in allowedPsids: 190 acl.AddAccessAllowedAce(win32security.ACL_REVISION, 191 ntsecuritycon.GENERIC_ALL, 192 allowedPsid) 193 194 # Initialize an SD. 195 sd = win32security.SECURITY_DESCRIPTOR() 196 sd.Initialize() 197 # Set DACL. 198 sd.SetSecurityDescriptorDacl(True, acl, False) 199 200 saAttr.bInheritHandle = 1 201 saAttr.SECURITY_DESCRIPTOR = sd 202 203 try: 204 npipe = win32pipe.CreateNamedPipe(pipename, 205 openMode, 206 pipeMode, 207 nMaxInstances, 208 nOutBufferSize, 209 nInBufferSize, 210 nDefaultTimeOut, 211 saAttr) 212 213 if npipe == win32file.INVALID_HANDLE_VALUE: 214 return None 215 216 return npipe 217 except pywintypes.error: 218 return None 219 220 221def set_pipe_mode(hPipe, mode=-1, maxCollectionCount=None, 222 collectDataTimeout=None): 223 # Default values if parameters are not passed 224 if mode == -1: 225 mode = win32pipe.PIPE_READMODE_BYTE 226 try: 227 win32pipe.SetNamedPipeHandleState( 228 hPipe, mode, maxCollectionCount, collectDataTimeout) 229 except pywintypes.error: 230 raise 231 232 233def connect_named_pipe(pipe_handle, overlapped=None): 234 try: 235 # If the result of ConnectNamedPipe is ERROR_IO_PENDING or 236 # ERROR_PIPE_CONNECTED, then this value is returned. 237 # All other error values raise a win32 exception 238 error = win32pipe.ConnectNamedPipe(pipe_handle, overlapped) 239 return error 240 except pywintypes.error as e: 241 return e.winerror 242 243 244def get_pipe_name(name): 245 name = name.replace('/', '') 246 name = name.replace('\\', '') 247 name = "\\\\.\\pipe\\" + name 248 return name 249 250 251def get_overlapped_result(handle, overlapped=None, bWait=False): 252 try: 253 return win32file.GetOverlappedResult(handle, overlapped, bWait) 254 except pywintypes.error: 255 raise 256 257 258def get_new_event(sa=None, bManualReset=True, bInitialState=True, 259 objectName=None): 260 return win32event.CreateEvent(sa, bManualReset, bInitialState, objectName) 261 262 263pipe_disconnected_errors = [winerror.ERROR_PIPE_NOT_CONNECTED, 264 winerror.ERROR_BAD_PIPE, 265 winerror.ERROR_NO_DATA, 266 winerror.ERROR_BROKEN_PIPE] 267