Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Impacket - Collection of Python classes for working with network protocols. 

2# 

3# SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved. 

4# 

5# This software is provided under a slightly modified version 

6# of the Apache Software License. See the accompanying LICENSE file 

7# for more information. 

8# 

9# Description: 

10# [MS-RPRN] Interface implementation 

11# 

12# Best way to learn how to use these calls is to grab the protocol standard 

13# so you understand what the call does, and then read the test case located 

14# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC 

15# 

16# Some calls have helper functions, which makes it even easier to use. 

17# They are located at the end of this file. 

18# Helper functions start with "h"<name of the call>. 

19# There are test cases for them too. 

20# 

21# Author: 

22# Alberto Solino (@agsolino) 

23# 

24from impacket import system_errors 

25from impacket.dcerpc.v5.dtypes import ULONGLONG, UINT, USHORT, LPWSTR, DWORD, ULONG, NULL 

26from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRUNION, NDRPOINTER, NDRUniConformantArray 

27from impacket.dcerpc.v5.rpcrt import DCERPCException 

28from impacket.uuid import uuidtup_to_bin 

29 

30MSRPC_UUID_RPRN = uuidtup_to_bin(('12345678-1234-ABCD-EF00-0123456789AB', '1.0')) 

31 

32class DCERPCSessionError(DCERPCException): 

33 def __init__(self, error_string=None, error_code=None, packet=None): 

34 DCERPCException.__init__(self, error_string, error_code, packet) 

35 

36 def __str__( self ): 

37 key = self.error_code 

38 if key in system_errors.ERROR_MESSAGES: 38 ↛ 43line 38 didn't jump to line 43, because the condition on line 38 was never false

39 error_msg_short = system_errors.ERROR_MESSAGES[key][0] 

40 error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] 

41 return 'RPRN SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 

42 else: 

43 return 'RPRN SessionError: unknown error code: 0x%x' % self.error_code 

44 

45################################################################################ 

46# CONSTANTS 

47################################################################################ 

48# 2.2.1.1.7 STRING_HANDLE 

49STRING_HANDLE = LPWSTR 

50class PSTRING_HANDLE(NDRPOINTER): 

51 referent = ( 

52 ('Data', STRING_HANDLE), 

53 ) 

54 

55# 2.2.3.1 Access Values 

56JOB_ACCESS_ADMINISTER = 0x00000010 

57JOB_ACCESS_READ = 0x00000020 

58JOB_EXECUTE = 0x00020010 

59JOB_READ = 0x00020020 

60JOB_WRITE = 0x00020010 

61JOB_ALL_ACCESS = 0x000F0030 

62PRINTER_ACCESS_ADMINISTER = 0x00000004 

63PRINTER_ACCESS_USE = 0x00000008 

64PRINTER_ACCESS_MANAGE_LIMITED = 0x00000040 

65PRINTER_ALL_ACCESS = 0x000F000C 

66PRINTER_EXECUTE = 0x00020008 

67PRINTER_READ = 0x00020008 

68PRINTER_WRITE = 0x00020008 

69SERVER_ACCESS_ADMINISTER = 0x00000001 

70SERVER_ACCESS_ENUMERATE = 0x00000002 

71SERVER_ALL_ACCESS = 0x000F0003 

72SERVER_EXECUTE = 0x00020002 

73SERVER_READ = 0x00020002 

74SERVER_WRITE = 0x00020003 

75SPECIFIC_RIGHTS_ALL = 0x0000FFFF 

76STANDARD_RIGHTS_ALL = 0x001F0000 

77STANDARD_RIGHTS_EXECUTE = 0x00020000 

78STANDARD_RIGHTS_READ = 0x00020000 

79STANDARD_RIGHTS_REQUIRED = 0x000F0000 

80STANDARD_RIGHTS_WRITE = 0x00020000 

81SYNCHRONIZE = 0x00100000 

82DELETE = 0x00010000 

83READ_CONTROL = 0x00020000 

84WRITE_DAC = 0x00040000 

85WRITE_OWNER = 0x00080000 

86GENERIC_READ = 0x80000000 

87GENERIC_WRITE = 0x40000000 

88GENERIC_EXECUTE = 0x20000000 

89GENERIC_ALL = 0x10000000 

90 

91# 2.2.3.6.1 Printer Change Flags for Use with a Printer Handle 

92PRINTER_CHANGE_SET_PRINTER = 0x00000002 

93PRINTER_CHANGE_DELETE_PRINTER = 0x00000004 

94PRINTER_CHANGE_PRINTER = 0x000000FF 

95PRINTER_CHANGE_ADD_JOB = 0x00000100 

96PRINTER_CHANGE_SET_JOB = 0x00000200 

97PRINTER_CHANGE_DELETE_JOB = 0x00000400 

98PRINTER_CHANGE_WRITE_JOB = 0x00000800 

99PRINTER_CHANGE_JOB = 0x0000FF00 

100PRINTER_CHANGE_SET_PRINTER_DRIVER = 0x20000000 

101PRINTER_CHANGE_TIMEOUT = 0x80000000 

102PRINTER_CHANGE_ALL = 0x7777FFFF 

103PRINTER_CHANGE_ALL_2 = 0x7F77FFFF 

104 

105# 2.2.3.6.2 Printer Change Flags for Use with a Server Handle 

106PRINTER_CHANGE_ADD_PRINTER_DRIVER = 0x10000000 

107PRINTER_CHANGE_DELETE_PRINTER_DRIVER = 0x40000000 

108PRINTER_CHANGE_PRINTER_DRIVER = 0x70000000 

109PRINTER_CHANGE_ADD_FORM = 0x00010000 

110PRINTER_CHANGE_DELETE_FORM = 0x00040000 

111PRINTER_CHANGE_SET_FORM = 0x00020000 

112PRINTER_CHANGE_FORM = 0x00070000 

113PRINTER_CHANGE_ADD_PORT = 0x00100000 

114PRINTER_CHANGE_CONFIGURE_PORT = 0x00200000 

115PRINTER_CHANGE_DELETE_PORT = 0x00400000 

116PRINTER_CHANGE_PORT = 0x00700000 

117PRINTER_CHANGE_ADD_PRINT_PROCESSOR = 0x01000000 

118PRINTER_CHANGE_DELETE_PRINT_PROCESSOR = 0x04000000 

119PRINTER_CHANGE_PRINT_PROCESSOR = 0x07000000 

120PRINTER_CHANGE_ADD_PRINTER = 0x00000001 

121PRINTER_CHANGE_FAILED_CONNECTION_PRINTER = 0x00000008 

122PRINTER_CHANGE_SERVER = 0x08000000 

123 

124# 2.2.3.7 Printer Enumeration Flags 

125PRINTER_ENUM_LOCAL = 0x00000002 

126PRINTER_ENUM_CONNECTIONS = 0x00000004 

127PRINTER_ENUM_NAME = 0x00000008 

128PRINTER_ENUM_REMOTE = 0x00000010 

129PRINTER_ENUM_SHARED = 0x00000020 

130PRINTER_ENUM_NETWORK = 0x00000040 

131PRINTER_ENUM_EXPAND = 0x00004000 

132PRINTER_ENUM_CONTAINER = 0x00008000 

133PRINTER_ENUM_ICON1 = 0x00010000 

134PRINTER_ENUM_ICON2 = 0x00020000 

135PRINTER_ENUM_ICON3 = 0x00040000 

136PRINTER_ENUM_ICON8 = 0x00800000 

137PRINTER_ENUM_HIDE = 0x01000000 

138 

139 

140# 2.2.3.8 Printer Notification Values 

141PRINTER_NOTIFY_CATEGORY_2D = 0x00000000 

142PRINTER_NOTIFY_CATEGORY_ALL = 0x00010000 

143PRINTER_NOTIFY_CATEGORY_3D = 0x00020000 

144 

145 

146# 3.1.4.4.8 RpcAddPrinterDriverEx Values 

147APD_STRICT_UPGRADE = 0x00000001 

148APD_STRICT_DOWNGRADE = 0x00000002 

149APD_COPY_ALL_FILES = 0x00000004 

150APD_COPY_NEW_FILES = 0x00000008 

151APD_COPY_FROM_DIRECTORY = 0x00000010 

152APD_DONT_COPY_FILES_TO_CLUSTER = 0x00001000 

153APD_COPY_TO_ALL_SPOOLERS = 0x00002000 

154APD_INSTALL_WARNED_DRIVER = 0x00008000 

155APD_RETURN_BLOCKING_STATUS_CODE = 0x00010000 

156 

157################################################################################ 

158# STRUCTURES 

159################################################################################ 

160# 2.2.1.1.4 PRINTER_HANDLE 

161class PRINTER_HANDLE(NDRSTRUCT): 

162 structure = ( 

163 ('Data','20s=b""'), 

164 ) 

165 def getAlignment(self): 

166 if self._isNDR64 is True: 

167 return 8 

168 else: 

169 return 4 

170 

171# 2.2.1.2.1 DEVMODE_CONTAINER 

172class BYTE_ARRAY(NDRUniConformantArray): 

173 item = 'c' 

174 

175class PBYTE_ARRAY(NDRPOINTER): 

176 referent = ( 

177 ('Data', BYTE_ARRAY), 

178 ) 

179 

180class DEVMODE_CONTAINER(NDRSTRUCT): 

181 structure = ( 

182 ('cbBuf',DWORD), 

183 ('pDevMode',PBYTE_ARRAY), 

184 ) 

185 

186# 2.2.1.11.1 SPLCLIENT_INFO_1 

187class SPLCLIENT_INFO_1(NDRSTRUCT): 

188 structure = ( 

189 ('dwSize',DWORD), 

190 ('pMachineName',LPWSTR), 

191 ('pUserName',LPWSTR), 

192 ('dwBuildNum',DWORD), 

193 ('dwMajorVersion',DWORD), 

194 ('dwMinorVersion',DWORD), 

195 ('wProcessorArchitecture',USHORT), 

196 ) 

197 

198class PSPLCLIENT_INFO_1(NDRPOINTER): 

199 referent = ( 

200 ('Data', SPLCLIENT_INFO_1), 

201 ) 

202 

203# 2.2.1.11.2 SPLCLIENT_INFO_2 

204class SPLCLIENT_INFO_2(NDRSTRUCT): 

205 structure = ( 

206 ('notUsed',ULONGLONG), 

207 ) 

208 

209class PSPLCLIENT_INFO_2(NDRPOINTER): 

210 referent = ( 

211 ('Data', SPLCLIENT_INFO_2), 

212 ) 

213# 2.2.1.11.3 SPLCLIENT_INFO_3 

214class SPLCLIENT_INFO_3(NDRSTRUCT): 

215 structure = ( 

216 ('cbSize',UINT), 

217 ('dwFlags',DWORD), 

218 ('dwFlags',DWORD), 

219 ('pMachineName',LPWSTR), 

220 ('pUserName',LPWSTR), 

221 ('dwBuildNum',DWORD), 

222 ('dwMajorVersion',DWORD), 

223 ('dwMinorVersion',DWORD), 

224 ('wProcessorArchitecture',USHORT), 

225 ('hSplPrinter',ULONGLONG), 

226 ) 

227 

228class PSPLCLIENT_INFO_3(NDRPOINTER): 

229 referent = ( 

230 ('Data', SPLCLIENT_INFO_3), 

231 ) 

232 

233# 2.2.1.5.1 DRIVER_INFO_1 

234class DRIVER_INFO_1(NDRSTRUCT): 

235 structure = ( 

236 ('pName', STRING_HANDLE ), 

237 ) 

238class PDRIVER_INFO_1(NDRPOINTER): 

239 referent = ( 

240 ('Data', DRIVER_INFO_1), 

241 ) 

242 

243# 2.2.1.5.2 DRIVER_INFO_2 

244class DRIVER_INFO_2(NDRSTRUCT): 

245 structure = ( 

246 ('cVersion',DWORD), 

247 ('pName', LPWSTR), 

248 ('pEnvironment', LPWSTR), 

249 ('pDriverPath', LPWSTR), 

250 ('pDataFile', LPWSTR), 

251 ('pConfigFile', LPWSTR), 

252 ) 

253class PDRIVER_INFO_2(NDRPOINTER): 

254 referent = ( 

255 ('Data', DRIVER_INFO_2), 

256 ) 

257 

258# 2.2.1.2.3 DRIVER_CONTAINER 

259class DRIVER_INFO_UNION(NDRUNION): 

260 commonHdr = ( 

261 ('tag', ULONG), 

262 ) 

263 union = { 

264 1 : ('pNotUsed', PDRIVER_INFO_1), 

265 2 : ('Level2', PDRIVER_INFO_2), 

266 } 

267 

268class DRIVER_CONTAINER(NDRSTRUCT): 

269 structure = ( 

270 ('Level', DWORD), 

271 ('DriverInfo', DRIVER_INFO_UNION), 

272 ) 

273 

274# 2.2.1.2.14 SPLCLIENT_CONTAINER 

275class CLIENT_INFO_UNION(NDRUNION): 

276 commonHdr = ( 

277 ('tag', ULONG), 

278 ) 

279 union = { 

280 1 : ('pClientInfo1', PSPLCLIENT_INFO_1), 

281 2 : ('pNotUsed1', PSPLCLIENT_INFO_2), 

282 3 : ('pNotUsed2', PSPLCLIENT_INFO_3), 

283 } 

284 

285class SPLCLIENT_CONTAINER(NDRSTRUCT): 

286 structure = ( 

287 ('Level',DWORD), 

288 ('ClientInfo',CLIENT_INFO_UNION), 

289 ) 

290 

291# 2.2.1.13.2 RPC_V2_NOTIFY_OPTIONS_TYPE 

292class USHORT_ARRAY(NDRUniConformantArray): 

293 item = '<H' 

294 

295class PUSHORT_ARRAY(NDRPOINTER): 

296 referent = ( 

297 ('Data', USHORT_ARRAY), 

298 ) 

299 

300class RPC_V2_NOTIFY_OPTIONS_TYPE(NDRSTRUCT): 

301 structure = ( 

302 ('Type',USHORT), 

303 ('Reserved0',USHORT), 

304 ('Reserved1',DWORD), 

305 ('Reserved2',DWORD), 

306 ('Count',DWORD), 

307 ('pFields',PUSHORT_ARRAY), 

308 ) 

309 

310class PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY(NDRPOINTER): 

311 referent = ( 

312 ('Data', RPC_V2_NOTIFY_OPTIONS_TYPE), 

313 ) 

314 

315# 2.2.1.13.1 RPC_V2_NOTIFY_OPTIONS 

316class RPC_V2_NOTIFY_OPTIONS(NDRSTRUCT): 

317 structure = ( 

318 ('Version',DWORD), 

319 ('Reserved',DWORD), 

320 ('Count',DWORD), 

321 ('pTypes',PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY), 

322 ) 

323 

324class PRPC_V2_NOTIFY_OPTIONS(NDRPOINTER): 

325 referent = ( 

326 ('Data', RPC_V2_NOTIFY_OPTIONS), 

327 ) 

328 

329 

330################################################################################ 

331# RPC CALLS 

332################################################################################ 

333# 3.1.4.2.1 RpcEnumPrinters (Opnum 0) 

334class RpcEnumPrinters(NDRCALL): 

335 opnum = 0 

336 structure = ( 

337 ('Flags', DWORD), 

338 ('Name', STRING_HANDLE), 

339 ('Level', DWORD), 

340 ('pPrinterEnum', PBYTE_ARRAY), 

341 ('cbBuf', DWORD), 

342 ) 

343 

344class RpcEnumPrintersResponse(NDRCALL): 

345 structure = ( 

346 ('pPrinterEnum', PBYTE_ARRAY), 

347 ('pcbNeeded', DWORD), 

348 ('pcReturned', DWORD), 

349 ('ErrorCode', ULONG), 

350 ) 

351# 3.1.4.2.2 RpcOpenPrinter (Opnum 1) 

352class RpcOpenPrinter(NDRCALL): 

353 opnum = 1 

354 structure = ( 

355 ('pPrinterName', STRING_HANDLE), 

356 ('pDatatype', LPWSTR), 

357 ('pDevModeContainer', DEVMODE_CONTAINER), 

358 ('AccessRequired', DWORD), 

359 ) 

360 

361class RpcOpenPrinterResponse(NDRCALL): 

362 structure = ( 

363 ('pHandle', PRINTER_HANDLE), 

364 ('ErrorCode', ULONG), 

365 ) 

366 

367# 3.1.4.2.9 RpcClosePrinter (Opnum 29) 

368class RpcClosePrinter(NDRCALL): 

369 opnum = 29 

370 structure = ( 

371 ('phPrinter', PRINTER_HANDLE), 

372 ) 

373 

374class RpcClosePrinterResponse(NDRCALL): 

375 structure = ( 

376 ('phPrinter', PRINTER_HANDLE), 

377 ('ErrorCode', ULONG), 

378 ) 

379 

380# 3.1.4.10.4 RpcRemoteFindFirstPrinterChangeNotificationEx (Opnum 65) 

381class RpcRemoteFindFirstPrinterChangeNotificationEx(NDRCALL): 

382 opnum = 65 

383 structure = ( 

384 ('hPrinter', PRINTER_HANDLE), 

385 ('fdwFlags', DWORD), 

386 ('fdwOptions', DWORD), 

387 ('pszLocalMachine', LPWSTR), 

388 ('dwPrinterLocal', DWORD), 

389 ('pOptions', PRPC_V2_NOTIFY_OPTIONS), 

390 ) 

391 

392class RpcRemoteFindFirstPrinterChangeNotificationExResponse(NDRCALL): 

393 structure = ( 

394 ('ErrorCode', ULONG), 

395 ) 

396 

397# 3.1.4.2.14 RpcOpenPrinterEx (Opnum 69) 

398class RpcOpenPrinterEx(NDRCALL): 

399 opnum = 69 

400 structure = ( 

401 ('pPrinterName', STRING_HANDLE), 

402 ('pDatatype', LPWSTR), 

403 ('pDevModeContainer', DEVMODE_CONTAINER), 

404 ('AccessRequired', DWORD), 

405 ('pClientInfo', SPLCLIENT_CONTAINER), 

406 ) 

407 

408class RpcOpenPrinterExResponse(NDRCALL): 

409 structure = ( 

410 ('pHandle', PRINTER_HANDLE), 

411 ('ErrorCode', ULONG), 

412 ) 

413 

414# 3.1.4.4.2 RpcEnumPrinterDrivers (Opnum 10) 

415class RpcEnumPrinterDrivers(NDRCALL): 

416 opnum = 10 

417 structure = ( 

418 ('pName', STRING_HANDLE), 

419 ('pEnvironment', LPWSTR), 

420 ('Level', DWORD), 

421 ('pDrivers', PBYTE_ARRAY), 

422 ('cbBuf', DWORD), 

423 ) 

424 

425class RpcEnumPrinterDriversResponse(NDRCALL): 

426 structure = ( 

427 ('pDrivers', PBYTE_ARRAY), 

428 ('pcbNeeded', DWORD), 

429 ('pcReturned', DWORD), 

430 ('ErrorCode', ULONG), 

431 ) 

432 

433# 3.1.4.4.8 RpcAddPrinterDriverEx (Opnum 89) 

434class RpcAddPrinterDriverEx(NDRCALL): 

435 opnum = 89 

436 structure = ( 

437 ('pName', STRING_HANDLE), 

438 ('pDriverContainer', DRIVER_CONTAINER), 

439 ('dwFileCopyFlags', DWORD), 

440 ) 

441 

442class RpcAddPrinterDriverExResponse(NDRCALL): 

443 structure = ( 

444 ('ErrorCode', ULONG), 

445 ) 

446 

447################################################################################ 

448# OPNUMs and their corresponding structures 

449################################################################################ 

450OPNUMS = { 

451 0 : (RpcEnumPrinters, RpcEnumPrintersResponse), 

452 1 : (RpcOpenPrinter, RpcOpenPrinterResponse), 

453 10 : (RpcEnumPrinterDrivers, RpcEnumPrinterDriversResponse), 

454 29 : (RpcClosePrinter, RpcClosePrinterResponse), 

455 65 : (RpcRemoteFindFirstPrinterChangeNotificationEx, RpcRemoteFindFirstPrinterChangeNotificationExResponse), 

456 69 : (RpcOpenPrinterEx, RpcOpenPrinterExResponse), 

457 89 : (RpcAddPrinterDriverEx, RpcAddPrinterDriverExResponse), 

458} 

459 

460################################################################################ 

461# HELPER FUNCTIONS 

462################################################################################ 

463def checkNullString(string): 

464 if string == NULL: 464 ↛ 465line 464 didn't jump to line 465, because the condition on line 464 was never true

465 return string 

466 

467 if string[-1:] != '\x00': 467 ↛ 468line 467 didn't jump to line 468, because the condition on line 467 was never true

468 return string + '\x00' 

469 else: 

470 return string 

471 

472def hRpcOpenPrinter(dce, printerName, pDatatype = NULL, pDevModeContainer = NULL, accessRequired = SERVER_READ): 

473 """ 

474 RpcOpenPrinter retrieves a handle for a printer, port, port monitor, print job, or print server. 

475 Full Documentation: https://msdn.microsoft.com/en-us/library/cc244808.aspx 

476 

477 :param DCERPC_v5 dce: a connected DCE instance. 

478 :param string printerName: A string for a printer connection, printer object, server object, job object, port 

479 object, or port monitor object. This MUST be a Domain Name System (DNS), NetBIOS, Internet Protocol version 4 

480 (IPv4), Internet Protocol version 6 (IPv6), or Universal Naming Convention (UNC) name that remote procedure 

481 call (RPC) binds to, and it MUST uniquely identify a print server on the network. 

482 :param string pDatatype: A string that specifies the data type to be associated with the printer handle. 

483 :param DEVMODE_CONTAINER pDevModeContainer: A DEVMODE_CONTAINER structure. This parameter MUST adhere to the specification in 

484 DEVMODE_CONTAINER Parameters (section 3.1.4.1.8.1). 

485 :param int accessRequired: The access level that the client requires for interacting with the object to which a 

486 handle is being opened. 

487 

488 :return: a RpcOpenPrinterResponse instance, raises DCERPCSessionError on error. 

489 """ 

490 request = RpcOpenPrinter() 

491 request['pPrinterName'] = checkNullString(printerName) 

492 request['pDatatype'] = pDatatype 

493 if pDevModeContainer is NULL: 493 ↛ 496line 493 didn't jump to line 496, because the condition on line 493 was never false

494 request['pDevModeContainer']['pDevMode'] = NULL 

495 else: 

496 request['pDevModeContainer'] = pDevModeContainer 

497 

498 request['AccessRequired'] = accessRequired 

499 return dce.request(request) 

500 

501def hRpcClosePrinter(dce, phPrinter): 

502 """ 

503 RpcClosePrinter closes a handle to a printer object, server object, job object, or port object. 

504 Full Documentation: https://msdn.microsoft.com/en-us/library/cc244768.aspx 

505 

506 :param DCERPC_v5 dce: a connected DCE instance. 

507 :param PRINTER_HANDLE phPrinter: A handle to a printer object, server object, job object, or port object. 

508 

509 :return: a RpcClosePrinterResponse instance, raises DCERPCSessionError on error. 

510 """ 

511 request = RpcClosePrinter() 

512 request['phPrinter'] = phPrinter 

513 return dce.request(request) 

514 

515 

516def hRpcOpenPrinterEx(dce, printerName, pDatatype=NULL, pDevModeContainer=NULL, accessRequired=SERVER_READ, 

517 pClientInfo=NULL): 

518 """ 

519 RpcOpenPrinterEx retrieves a handle for a printer, port, port monitor, print job, or print server 

520 Full Documentation: https://msdn.microsoft.com/en-us/library/cc244809.aspx 

521 

522 :param DCERPC_v5 dce: a connected DCE instance. 

523 :param string printerName: A string for a printer connection, printer object, server object, job object, port 

524 object, or port monitor object. This MUST be a Domain Name System (DNS), NetBIOS, Internet Protocol version 4 

525 (IPv4), Internet Protocol version 6 (IPv6), or Universal Naming Convention (UNC) name that remote procedure 

526 call (RPC) binds to, and it MUST uniquely identify a print server on the network. 

527 :param string pDatatype: A string that specifies the data type to be associated with the printer handle. 

528 :param DEVMODE_CONTAINER pDevModeContainer: A DEVMODE_CONTAINER structure. This parameter MUST adhere to the specification in 

529 DEVMODE_CONTAINER Parameters (section 3.1.4.1.8.1). 

530 :param int accessRequired: The access level that the client requires for interacting with the object to which a 

531 handle is being opened. 

532 :param SPLCLIENT_CONTAINER pClientInfo: This parameter MUST adhere to the specification in SPLCLIENT_CONTAINER Parameters. 

533 

534 :return: a RpcOpenPrinterExResponse instance, raises DCERPCSessionError on error. 

535 """ 

536 request = RpcOpenPrinterEx() 

537 request['pPrinterName'] = checkNullString(printerName) 

538 request['pDatatype'] = pDatatype 

539 if pDevModeContainer is NULL: 539 ↛ 542line 539 didn't jump to line 542, because the condition on line 539 was never false

540 request['pDevModeContainer']['pDevMode'] = NULL 

541 else: 

542 request['pDevModeContainer'] = pDevModeContainer 

543 

544 request['AccessRequired'] = accessRequired 

545 if pClientInfo is NULL: 545 ↛ 546line 545 didn't jump to line 546, because the condition on line 545 was never true

546 raise Exception('pClientInfo cannot be NULL') 

547 

548 request['pClientInfo'] = pClientInfo 

549 return dce.request(request) 

550 

551 

552def hRpcRemoteFindFirstPrinterChangeNotificationEx(dce, hPrinter, fdwFlags, fdwOptions=0, pszLocalMachine=NULL, 

553 dwPrinterLocal=0, pOptions=NULL): 

554 """ 

555 creates a remote change notification object that monitors changes to printer objects and sends change notifications 

556 to a print client using either RpcRouterReplyPrinter (section 3.2.4.1.2) or RpcRouterReplyPrinterEx (section 3.2.4.1.4) 

557 Full Documentation: https://msdn.microsoft.com/en-us/library/cc244813.aspx 

558 

559 :param DCERPC_v5 dce: a connected DCE instance. 

560 :param PRINTER_HANDLE hPrinter: A handle to a printer or server object. 

561 :param int fdwFlags: Flags that specify the conditions that are required for a change notification object to enter a signaled state. 

562 :param int fdwOptions: The category of printers for which change notifications are returned. 

563 :param string pszLocalMachine: A string that represents the name of the client computer. 

564 :param int dwPrinterLocal: An implementation-specific unique value that MUST be sufficient for the client to determine 

565 whether a call to RpcReplyOpenPrinter by the server is associated with the hPrinter parameter in this call. 

566 :param RPC_V2_NOTIFY_OPTIONS pOptions: An RPC_V2_NOTIFY_OPTIONS structure that specifies printer or job members that the client listens to for notifications. 

567 

568 :return: a RpcRemoteFindFirstPrinterChangeNotificationExResponse instance, raises DCERPCSessionError on error. 

569 """ 

570 request = RpcRemoteFindFirstPrinterChangeNotificationEx() 

571 

572 request['hPrinter'] = hPrinter 

573 request['fdwFlags'] = fdwFlags 

574 request['fdwOptions'] = fdwOptions 

575 request['dwPrinterLocal'] = dwPrinterLocal 

576 if pszLocalMachine is NULL: 576 ↛ 577line 576 didn't jump to line 577, because the condition on line 576 was never true

577 raise Exception('pszLocalMachine cannot be NULL') 

578 request['pszLocalMachine'] = checkNullString(pszLocalMachine) 

579 request['pOptions'] = pOptions 

580 return dce.request(request) 

581 

582def hRpcEnumPrinters(dce, flags, name = NULL, level = 1): 

583 """ 

584 RpcEnumPrinters enumerates available printers, print servers, domains, or print providers. 

585 Full Documentation: https://msdn.microsoft.com/en-us/library/cc244794.aspx 

586 

587 :param DCERPC_v5 dce: a connected DCE instance. 

588 :param int flags: The types of print objects that this method enumerates. The value of this parameter is the 

589 result of a bitwise OR of one or more of the Printer Enumeration Flags (section 2.2.3.7). 

590 :param string name: NULL or a server name parameter as specified in Printer Server Name Parameters (section 3.1.4.1.4). 

591 :param level: The level of printer information structure. 

592 

593 :return: a RpcEnumPrintersResponse instance, raises DCERPCSessionError on error. 

594 """ 

595 request = RpcEnumPrinters() 

596 request['Flags'] = flags 

597 request['Name'] = name 

598 request['pPrinterEnum'] = NULL 

599 request['Level'] = level 

600 bytesNeeded = 0 

601 try: 

602 dce.request(request) 

603 except DCERPCSessionError as e: 

604 if str(e).find('ERROR_INSUFFICIENT_BUFFER') < 0: 604 ↛ 605line 604 didn't jump to line 605, because the condition on line 604 was never true

605 raise 

606 bytesNeeded = e.get_packet()['pcbNeeded'] 

607 

608 request = RpcEnumPrinters() 

609 request['Flags'] = flags 

610 request['Name'] = name 

611 request['Level'] = level 

612 

613 request['cbBuf'] = bytesNeeded 

614 request['pPrinterEnum'] = b'a' * bytesNeeded 

615 return dce.request(request) 

616 

617 

618def hRpcAddPrinterDriverEx(dce, pName, pDriverContainer, dwFileCopyFlags): 

619 """ 

620 RpcAddPrinterDriverEx installs a printer driver on the print server 

621 Full Documentation: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b 

622 

623 :param DCERPC_v5 dce: a connected DCE instance. 

624 :param pName 

625 :param pDriverContainer 

626 :param dwFileCopyFlags 

627 

628 :return: raises DCERPCSessionError on error. 

629 """ 

630 request = RpcAddPrinterDriverEx() 

631 request['pName'] = checkNullString(pName) 

632 request['pDriverContainer'] = pDriverContainer 

633 request['dwFileCopyFlags'] = dwFileCopyFlags 

634 

635 #return request 

636 return dce.request(request) 

637 

638 

639def hRpcEnumPrinterDrivers(dce, pName, pEnvironment, Level): 

640 """ 

641 RpcEnumPrinterDrivers enumerates the printer drivers installed on a specified print server. 

642 Full Documentation: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/857d00ac-3682-4a0d-86ca-3d3c372e5e4a 

643 

644 :param DCERPC_v5 dce: a connected DCE instance. 

645 :param pName 

646 :param pEnvironment 

647 :param Level 

648 :param pDrivers 

649 :param cbBuf 

650 :param pcbNeeded 

651 :param pcReturned 

652 

653 :return: raises DCERPCSessionError on error. 

654 """ 

655 # get value for cbBuf 

656 request = RpcEnumPrinterDrivers() 

657 request['pName'] = checkNullString(pName) 

658 request['pEnvironment'] = pEnvironment 

659 request['Level'] = Level 

660 request['pDrivers'] = NULL 

661 request['cbBuf'] = 0 

662 try: 

663 dce.request(request) 

664 except DCERPCSessionError as e: 

665 if str(e).find('ERROR_INSUFFICIENT_BUFFER') < 0: 

666 raise 

667 bytesNeeded = e.get_packet()['pcbNeeded'] 

668 

669 # now do RpcEnumPrinterDrivers again 

670 request = RpcEnumPrinterDrivers() 

671 request['pName'] = checkNullString(pName) 

672 request['pEnvironment'] = pEnvironment 

673 request['Level'] = Level 

674 request['pDrivers'] = b'a' * bytesNeeded 

675 request['cbBuf'] = bytesNeeded 

676 

677 #return request 

678 return dce.request(request)