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-PAR] Interface implementation 

11# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-par 

12# 

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

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

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

16# 

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

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

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

20# There are test cases for them too. 

21# 

22# Author: 

23# Adam (@cube0x0) 

24# 

25from impacket import system_errors 

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

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

28from impacket.dcerpc.v5.rpcrt import DCERPCException 

29from impacket.uuid import uuidtup_to_bin, string_to_bin 

30 

31MSRPC_UUID_PAR = uuidtup_to_bin(('76F03F96-CDFD-44FC-A22C-64950A001209', '1.0')) 

32MSRPC_UUID_WINSPOOL = string_to_bin('9940CA8E-512F-4C58-88A9-61098D6896BD') 

33 

34class DCERPCSessionError(DCERPCException): 

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

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

37 

38 def __str__( self ): 

39 key = self.error_code 

40 if key in system_errors.ERROR_MESSAGES: 

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

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

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

44 else: 

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

46 

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

48# CONSTANTS 

49################################################################################ 

50# 2.2.1.1.7 STRING_HANDLE 

51STRING_HANDLE = LPWSTR 

52class PSTRING_HANDLE(NDRPOINTER): 

53 referent = ( 

54 ('Data', STRING_HANDLE), 

55 ) 

56 

57# 2.2.3.1 Access Values 

58JOB_ACCESS_ADMINISTER = 0x00000010 

59JOB_ACCESS_READ = 0x00000020 

60JOB_EXECUTE = 0x00020010 

61JOB_READ = 0x00020020 

62JOB_WRITE = 0x00020010 

63JOB_ALL_ACCESS = 0x000F0030 

64PRINTER_ACCESS_ADMINISTER = 0x00000004 

65PRINTER_ACCESS_USE = 0x00000008 

66PRINTER_ACCESS_MANAGE_LIMITED = 0x00000040 

67PRINTER_ALL_ACCESS = 0x000F000C 

68PRINTER_EXECUTE = 0x00020008 

69PRINTER_READ = 0x00020008 

70PRINTER_WRITE = 0x00020008 

71SERVER_ACCESS_ADMINISTER = 0x00000001 

72SERVER_ACCESS_ENUMERATE = 0x00000002 

73SERVER_ALL_ACCESS = 0x000F0003 

74SERVER_EXECUTE = 0x00020002 

75SERVER_READ = 0x00020002 

76SERVER_WRITE = 0x00020003 

77SPECIFIC_RIGHTS_ALL = 0x0000FFFF 

78STANDARD_RIGHTS_ALL = 0x001F0000 

79STANDARD_RIGHTS_EXECUTE = 0x00020000 

80STANDARD_RIGHTS_READ = 0x00020000 

81STANDARD_RIGHTS_REQUIRED = 0x000F0000 

82STANDARD_RIGHTS_WRITE = 0x00020000 

83SYNCHRONIZE = 0x00100000 

84DELETE = 0x00010000 

85READ_CONTROL = 0x00020000 

86WRITE_DAC = 0x00040000 

87WRITE_OWNER = 0x00080000 

88GENERIC_READ = 0x80000000 

89GENERIC_WRITE = 0x40000000 

90GENERIC_EXECUTE = 0x20000000 

91GENERIC_ALL = 0x10000000 

92 

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

94PRINTER_CHANGE_SET_PRINTER = 0x00000002 

95PRINTER_CHANGE_DELETE_PRINTER = 0x00000004 

96PRINTER_CHANGE_PRINTER = 0x000000FF 

97PRINTER_CHANGE_ADD_JOB = 0x00000100 

98PRINTER_CHANGE_SET_JOB = 0x00000200 

99PRINTER_CHANGE_DELETE_JOB = 0x00000400 

100PRINTER_CHANGE_WRITE_JOB = 0x00000800 

101PRINTER_CHANGE_JOB = 0x0000FF00 

102PRINTER_CHANGE_SET_PRINTER_DRIVER = 0x20000000 

103PRINTER_CHANGE_TIMEOUT = 0x80000000 

104PRINTER_CHANGE_ALL = 0x7777FFFF 

105PRINTER_CHANGE_ALL_2 = 0x7F77FFFF 

106 

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

108PRINTER_CHANGE_ADD_PRINTER_DRIVER = 0x10000000 

109PRINTER_CHANGE_DELETE_PRINTER_DRIVER = 0x40000000 

110PRINTER_CHANGE_PRINTER_DRIVER = 0x70000000 

111PRINTER_CHANGE_ADD_FORM = 0x00010000 

112PRINTER_CHANGE_DELETE_FORM = 0x00040000 

113PRINTER_CHANGE_SET_FORM = 0x00020000 

114PRINTER_CHANGE_FORM = 0x00070000 

115PRINTER_CHANGE_ADD_PORT = 0x00100000 

116PRINTER_CHANGE_CONFIGURE_PORT = 0x00200000 

117PRINTER_CHANGE_DELETE_PORT = 0x00400000 

118PRINTER_CHANGE_PORT = 0x00700000 

119PRINTER_CHANGE_ADD_PRINT_PROCESSOR = 0x01000000 

120PRINTER_CHANGE_DELETE_PRINT_PROCESSOR = 0x04000000 

121PRINTER_CHANGE_PRINT_PROCESSOR = 0x07000000 

122PRINTER_CHANGE_ADD_PRINTER = 0x00000001 

123PRINTER_CHANGE_FAILED_CONNECTION_PRINTER = 0x00000008 

124PRINTER_CHANGE_SERVER = 0x08000000 

125 

126# 2.2.3.7 Printer Enumeration Flags 

127PRINTER_ENUM_LOCAL = 0x00000002 

128PRINTER_ENUM_CONNECTIONS = 0x00000004 

129PRINTER_ENUM_NAME = 0x00000008 

130PRINTER_ENUM_REMOTE = 0x00000010 

131PRINTER_ENUM_SHARED = 0x00000020 

132PRINTER_ENUM_NETWORK = 0x00000040 

133PRINTER_ENUM_EXPAND = 0x00004000 

134PRINTER_ENUM_CONTAINER = 0x00008000 

135PRINTER_ENUM_ICON1 = 0x00010000 

136PRINTER_ENUM_ICON2 = 0x00020000 

137PRINTER_ENUM_ICON3 = 0x00040000 

138PRINTER_ENUM_ICON8 = 0x00800000 

139PRINTER_ENUM_HIDE = 0x01000000 

140 

141 

142# 2.2.3.8 Printer Notification Values 

143PRINTER_NOTIFY_CATEGORY_2D = 0x00000000 

144PRINTER_NOTIFY_CATEGORY_ALL = 0x00010000 

145PRINTER_NOTIFY_CATEGORY_3D = 0x00020000 

146 

147 

148# 3.1.4.4.8 RpcAddPrinterDriverEx Values 

149APD_STRICT_UPGRADE = 0x00000001 

150APD_STRICT_DOWNGRADE = 0x00000002 

151APD_COPY_ALL_FILES = 0x00000004 

152APD_COPY_NEW_FILES = 0x00000008 

153APD_COPY_FROM_DIRECTORY = 0x00000010 

154APD_DONT_COPY_FILES_TO_CLUSTER = 0x00001000 

155APD_COPY_TO_ALL_SPOOLERS = 0x00002000 

156APD_INSTALL_WARNED_DRIVER = 0x00008000 

157APD_RETURN_BLOCKING_STATUS_CODE = 0x00010000 

158 

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

160# STRUCTURES 

161################################################################################ 

162# 2.2.1.1.4 PRINTER_HANDLE 

163class PRINTER_HANDLE(NDRSTRUCT): 

164 structure = ( 

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

166 ) 

167 def getAlignment(self): 

168 if self._isNDR64 is True: 

169 return 8 

170 else: 

171 return 4 

172 

173# 2.2.1.2.1 DEVMODE_CONTAINER 

174class BYTE_ARRAY(NDRUniConformantArray): 

175 item = 'c' 

176 

177class PBYTE_ARRAY(NDRPOINTER): 

178 referent = ( 

179 ('Data', BYTE_ARRAY), 

180 ) 

181 

182class DEVMODE_CONTAINER(NDRSTRUCT): 

183 structure = ( 

184 ('cbBuf',DWORD), 

185 ('pDevMode',PBYTE_ARRAY), 

186 ) 

187 

188# 2.2.1.11.1 SPLCLIENT_INFO_1 

189class SPLCLIENT_INFO_1(NDRSTRUCT): 

190 structure = ( 

191 ('dwSize',DWORD), 

192 ('pMachineName',LPWSTR), 

193 ('pUserName',LPWSTR), 

194 ('dwBuildNum',DWORD), 

195 ('dwMajorVersion',DWORD), 

196 ('dwMinorVersion',DWORD), 

197 ('wProcessorArchitecture',USHORT), 

198 ) 

199 

200class PSPLCLIENT_INFO_1(NDRPOINTER): 

201 referent = ( 

202 ('Data', SPLCLIENT_INFO_1), 

203 ) 

204 

205# 2.2.1.11.2 SPLCLIENT_INFO_2 

206class SPLCLIENT_INFO_2(NDRSTRUCT): 

207 structure = ( 

208 ('notUsed',ULONGLONG), 

209 ) 

210 

211class PSPLCLIENT_INFO_2(NDRPOINTER): 

212 referent = ( 

213 ('Data', SPLCLIENT_INFO_2), 

214 ) 

215# 2.2.1.11.3 SPLCLIENT_INFO_3 

216class SPLCLIENT_INFO_3(NDRSTRUCT): 

217 structure = ( 

218 ('cbSize',UINT), 

219 ('dwFlags',DWORD), 

220 ('dwFlags',DWORD), 

221 ('pMachineName',LPWSTR), 

222 ('pUserName',LPWSTR), 

223 ('dwBuildNum',DWORD), 

224 ('dwMajorVersion',DWORD), 

225 ('dwMinorVersion',DWORD), 

226 ('wProcessorArchitecture',USHORT), 

227 ('hSplPrinter',ULONGLONG), 

228 ) 

229 

230class PSPLCLIENT_INFO_3(NDRPOINTER): 

231 referent = ( 

232 ('Data', SPLCLIENT_INFO_3), 

233 ) 

234 

235# 2.2.1.5.1 DRIVER_INFO_1 

236class DRIVER_INFO_1(NDRSTRUCT): 

237 structure = ( 

238 ('pName', STRING_HANDLE ), 

239 ) 

240class PDRIVER_INFO_1(NDRPOINTER): 

241 referent = ( 

242 ('Data', DRIVER_INFO_1), 

243 ) 

244 

245# 2.2.1.5.2 DRIVER_INFO_2 

246class DRIVER_INFO_2(NDRSTRUCT): 

247 structure = ( 

248 ('cVersion',DWORD), 

249 ('pName', LPWSTR), 

250 ('pEnvironment', LPWSTR), 

251 ('pDriverPath', LPWSTR), 

252 ('pDataFile', LPWSTR), 

253 ('pConfigFile', LPWSTR), 

254 ) 

255class PDRIVER_INFO_2(NDRPOINTER): 

256 referent = ( 

257 ('Data', DRIVER_INFO_2), 

258 ) 

259 

260# 2.2.1.2.3 DRIVER_CONTAINER 

261class DRIVER_INFO_UNION(NDRUNION): 

262 commonHdr = ( 

263 ('tag', ULONG), 

264 ) 

265 union = { 

266 1 : ('pNotUsed', PDRIVER_INFO_1), 

267 2 : ('Level2', PDRIVER_INFO_2), 

268 } 

269 

270class DRIVER_CONTAINER(NDRSTRUCT): 

271 structure = ( 

272 ('Level', DWORD), 

273 ('DriverInfo', DRIVER_INFO_UNION), 

274 ) 

275 

276# 2.2.1.2.14 SPLCLIENT_CONTAINER 

277class CLIENT_INFO_UNION(NDRUNION): 

278 commonHdr = ( 

279 ('tag', ULONG), 

280 ) 

281 union = { 

282 1 : ('pClientInfo1', PSPLCLIENT_INFO_1), 

283 2 : ('pNotUsed1', PSPLCLIENT_INFO_2), 

284 3 : ('pNotUsed2', PSPLCLIENT_INFO_3), 

285 } 

286 

287class SPLCLIENT_CONTAINER(NDRSTRUCT): 

288 structure = ( 

289 ('Level',DWORD), 

290 ('ClientInfo',CLIENT_INFO_UNION), 

291 ) 

292 

293# 2.2.1.13.2 RPC_V2_NOTIFY_OPTIONS_TYPE 

294class USHORT_ARRAY(NDRUniConformantArray): 

295 item = '<H' 

296 

297class PUSHORT_ARRAY(NDRPOINTER): 

298 referent = ( 

299 ('Data', USHORT_ARRAY), 

300 ) 

301 

302class RpcAsync_V2_NOTIFY_OPTIONS_TYPE(NDRSTRUCT): 

303 structure = ( 

304 ('Type',USHORT), 

305 ('Reserved0',USHORT), 

306 ('Reserved1',DWORD), 

307 ('Reserved2',DWORD), 

308 ('Count',DWORD), 

309 ('pFields',PUSHORT_ARRAY), 

310 ) 

311 

312class PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY(NDRPOINTER): 

313 referent = ( 

314 ('Data', RpcAsync_V2_NOTIFY_OPTIONS_TYPE), 

315 ) 

316 

317# 2.2.1.13.1 RPC_V2_NOTIFY_OPTIONS 

318class RpcAsync_V2_NOTIFY_OPTIONS(NDRSTRUCT): 

319 structure = ( 

320 ('Version',DWORD), 

321 ('Reserved',DWORD), 

322 ('Count',DWORD), 

323 ('pTypes',PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY), 

324 ) 

325 

326class PRPC_V2_NOTIFY_OPTIONS(NDRPOINTER): 

327 referent = ( 

328 ('Data', RpcAsync_V2_NOTIFY_OPTIONS), 

329 ) 

330 

331 

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

333# RPC CALLS 

334################################################################################ 

335# 3.1.4.1.21 RpcAsyncEnumPrinters (Opnum 38) 

336class RpcAsyncEnumPrinters(NDRCALL): 

337 opnum = 38 

338 structure = ( 

339 ('Flags', DWORD), 

340 ('Name', STRING_HANDLE), 

341 ('Level', DWORD), 

342 ('pPrinterEnum', PBYTE_ARRAY), 

343 ('cbBuf', DWORD), 

344 ) 

345 

346class RpcAsyncEnumPrintersResponse(NDRCALL): 

347 structure = ( 

348 ('pPrinterEnum', PBYTE_ARRAY), 

349 ('pcbNeeded', DWORD), 

350 ('pcReturned', DWORD), 

351 ('ErrorCode', ULONG), 

352 ) 

353 

354# 3.1.4.1.1 RpcAsyncOpenPrinter (Opnum 0) 

355class RpcAsyncOpenPrinter(NDRCALL): 

356 opnum = 0 

357 structure = ( 

358 ('pPrinterName', STRING_HANDLE), 

359 ('pDatatype', LPWSTR), 

360 ('pDevModeContainer', DEVMODE_CONTAINER), 

361 ('AccessRequired', DWORD), 

362 ('pClientInfo', SPLCLIENT_CONTAINER), 

363 ) 

364 

365class RpcAsyncOpenPrinterResponse(NDRCALL): 

366 structure = ( 

367 ('pHandle', PRINTER_HANDLE), 

368 ('ErrorCode', ULONG), 

369 ) 

370 

371# 3.1.4.1.10 RpcAsyncClosePrinter (Opnum 20) 

372class RpcAsyncClosePrinter(NDRCALL): 

373 opnum = 20 

374 structure = ( 

375 ('phPrinter', PRINTER_HANDLE), 

376 ) 

377 

378class RpcAsyncClosePrinterResponse(NDRCALL): 

379 structure = ( 

380 ('phPrinter', PRINTER_HANDLE), 

381 ('ErrorCode', ULONG), 

382 ) 

383 

384# 3.1.4.2.3 RpcAsyncEnumPrinterDrivers (Opnum 40) 

385class RpcAsyncEnumPrinterDrivers(NDRCALL): 

386 opnum = 40 

387 structure = ( 

388 ('pName', STRING_HANDLE), 

389 ('pEnvironment', LPWSTR), 

390 ('Level', DWORD), 

391 ('pDrivers', PBYTE_ARRAY), 

392 ('cbBuf', DWORD), 

393 ) 

394 

395class RpcAsyncEnumPrinterDriversResponse(NDRCALL): 

396 structure = ( 

397 ('pDrivers', PBYTE_ARRAY), 

398 ('pcbNeeded', DWORD), 

399 ('pcReturned', DWORD), 

400 ('ErrorCode', ULONG), 

401 ) 

402 

403# 3.1.4.2.2 RpcAsyncAddPrinterDriver (Opnum 39) 

404class RpcAsyncAddPrinterDriver(NDRCALL): 

405 opnum = 39 

406 structure = ( 

407 ('pName', STRING_HANDLE), 

408 ('pDriverContainer', DRIVER_CONTAINER), 

409 ('dwFileCopyFlags', DWORD), 

410 ) 

411 

412class RpcAsyncAddPrinterDriverResponse(NDRCALL): 

413 structure = ( 

414 ('ErrorCode', ULONG), 

415 ) 

416 

417################################################################################ 

418# OPNUMs and their corresponding structures 

419################################################################################ 

420OPNUMS = { 

421 0 : (RpcAsyncOpenPrinter, RpcAsyncOpenPrinterResponse), 

422 #1 : (RpcAsyncAddPrinter, RpcAsyncAddPrinterResponse), 

423 20 : (RpcAsyncClosePrinter, RpcAsyncClosePrinterResponse), 

424 38 : (RpcAsyncEnumPrinters, RpcAsyncEnumPrintersResponse), 

425 39 : (RpcAsyncAddPrinterDriver, RpcAsyncAddPrinterDriver), 

426 40 : (RpcAsyncEnumPrinterDrivers, RpcAsyncEnumPrinterDriversResponse), 

427} 

428 

429################################################################################ 

430# HELPER FUNCTIONS 

431################################################################################ 

432def checkNullString(string): 

433 if string == NULL: 

434 return string 

435 

436 if string[-1:] != '\x00': 

437 return string + '\x00' 

438 else: 

439 return string 

440 

441def hRpcAsyncClosePrinter(dce, phPrinter): 

442 """ 

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

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

445 

446 :param DCERPC_v5 dce: a connected DCE instance. 

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

448 

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

450 """ 

451 request = RpcAsyncClosePrinter() 

452 request['phPrinter'] = phPrinter 

453 return dce.request(request, MSRPC_UUID_WINSPOOL) 

454 

455 

456def hRpcAsyncOpenPrinter(dce, printerName, pDatatype=NULL, pDevModeContainer=NULL, accessRequired=SERVER_READ, 

457 pClientInfo=NULL): 

458 """ 

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

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

461 

462 :param DCERPC_v5 dce: a connected DCE instance. 

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

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

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

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

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

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

469 DEVMODE_CONTAINER Parameters (section 3.1.4.1.8.1). 

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

471 handle is being opened. 

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

473 

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

475 """ 

476 request = RpcAsyncOpenPrinter() 

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

478 request['pDatatype'] = pDatatype 

479 if pDevModeContainer is NULL: 

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

481 else: 

482 request['pDevModeContainer'] = pDevModeContainer 

483 

484 request['AccessRequired'] = accessRequired 

485 if pClientInfo is NULL: 

486 raise Exception('pClientInfo cannot be NULL') 

487 

488 request['pClientInfo'] = pClientInfo 

489 return dce.request(request, MSRPC_UUID_WINSPOOL) 

490 

491 

492def hRpcAsyncEnumPrinters(dce, flags, name = NULL, level = 1): 

493 """ 

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

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

496 

497 :param DCERPC_v5 dce: a connected DCE instance. 

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

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

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

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

502 

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

504 """ 

505 request = RpcAsyncEnumPrinters() 

506 request['Flags'] = flags 

507 request['Name'] = name 

508 request['pPrinterEnum'] = NULL 

509 request['Level'] = level 

510 bytesNeeded = 0 

511 try: 

512 dce.request(request, MSRPC_UUID_WINSPOOL) 

513 except DCERPCSessionError as e: 

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

515 raise 

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

517 

518 request = RpcAsyncEnumPrinters() 

519 request['Flags'] = flags 

520 request['Name'] = name 

521 request['Level'] = level 

522 

523 request['cbBuf'] = bytesNeeded 

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

525 return dce.request(request, MSRPC_UUID_WINSPOOL) 

526 

527 

528def hRpcAsyncAddPrinterDriver(dce, pName, pDriverContainer, dwFileCopyFlags): 

529 """ 

530 RpcAddPrinterDriverEx installs a printer driver on the print server 

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

532 

533 :param DCERPC_v5 dce: a connected DCE instance. 

534 :param pName 

535 :param pDriverContainer 

536 :param dwFileCopyFlags 

537 

538 :return: raises DCERPCSessionError on error. 

539 """ 

540 request = RpcAsyncAddPrinterDriver() 

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

542 request['pDriverContainer'] = pDriverContainer 

543 request['dwFileCopyFlags'] = dwFileCopyFlags 

544 

545 #return request 

546 return dce.request(request, MSRPC_UUID_WINSPOOL) 

547 

548 

549def hRpcAsyncEnumPrinterDrivers(dce, pName, pEnvironment, Level): 

550 """ 

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

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

553 

554 :param DCERPC_v5 dce: a connected DCE instance. 

555 :param pName 

556 :param pEnvironment 

557 :param Level 

558 :param pDrivers 

559 :param cbBuf 

560 :param pcbNeeded 

561 :param pcReturned 

562 

563 :return: raises DCERPCSessionError on error. 

564 """ 

565 # get value for cbBuf 

566 request = RpcAsyncEnumPrinterDrivers() 

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

568 request['pEnvironment'] = pEnvironment 

569 request['Level'] = Level 

570 request['pDrivers'] = NULL 

571 request['cbBuf'] = 0 

572 try: 

573 dce.request(request, MSRPC_UUID_WINSPOOL) 

574 except DCERPCSessionError as e: 

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

576 raise 

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

578 

579 # now do RpcEnumPrinterDrivers again 

580 request = RpcAsyncEnumPrinterDrivers() 

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

582 request['pEnvironment'] = pEnvironment 

583 request['Level'] = Level 

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

585 request['cbBuf'] = bytesNeeded 

586 

587 #return request 

588 return dce.request(request, MSRPC_UUID_WINSPOOL)