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# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

2# 

3# This software is provided under under a slightly modified version 

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

5# for more information. 

6# 

7# Author: Alberto Solino (@agsolino) 

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# 

21from impacket import system_errors 

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

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

24from impacket.dcerpc.v5.rpcrt import DCERPCException 

25from impacket.uuid import uuidtup_to_bin 

26 

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

28 

29class DCERPCSessionError(DCERPCException): 

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

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

32 

33 def __str__( self ): 

34 key = self.error_code 

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

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

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

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

39 else: 

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

41 

42################################################################################ 

43# CONSTANTS 

44################################################################################ 

45# 2.2.1.1.7 STRING_HANDLE 

46STRING_HANDLE = LPWSTR 

47class PSTRING_HANDLE(NDRPOINTER): 

48 referent = ( 

49 ('Data', STRING_HANDLE), 

50 ) 

51 

52# 2.2.3.1 Access Values 

53JOB_ACCESS_ADMINISTER = 0x00000010 

54JOB_ACCESS_READ = 0x00000020 

55JOB_EXECUTE = 0x00020010 

56JOB_READ = 0x00020020 

57JOB_WRITE = 0x00020010 

58JOB_ALL_ACCESS = 0x000F0030 

59PRINTER_ACCESS_ADMINISTER = 0x00000004 

60PRINTER_ACCESS_USE = 0x00000008 

61PRINTER_ACCESS_MANAGE_LIMITED = 0x00000040 

62PRINTER_ALL_ACCESS = 0x000F000C 

63PRINTER_EXECUTE = 0x00020008 

64PRINTER_READ = 0x00020008 

65PRINTER_WRITE = 0x00020008 

66SERVER_ACCESS_ADMINISTER = 0x00000001 

67SERVER_ACCESS_ENUMERATE = 0x00000002 

68SERVER_ALL_ACCESS = 0x000F0003 

69SERVER_EXECUTE = 0x00020002 

70SERVER_READ = 0x00020002 

71SERVER_WRITE = 0x00020003 

72SPECIFIC_RIGHTS_ALL = 0x0000FFFF 

73STANDARD_RIGHTS_ALL = 0x001F0000 

74STANDARD_RIGHTS_EXECUTE = 0x00020000 

75STANDARD_RIGHTS_READ = 0x00020000 

76STANDARD_RIGHTS_REQUIRED = 0x000F0000 

77STANDARD_RIGHTS_WRITE = 0x00020000 

78SYNCHRONIZE = 0x00100000 

79DELETE = 0x00010000 

80READ_CONTROL = 0x00020000 

81WRITE_DAC = 0x00040000 

82WRITE_OWNER = 0x00080000 

83GENERIC_READ = 0x80000000 

84GENERIC_WRITE = 0x40000000 

85GENERIC_EXECUTE = 0x20000000 

86GENERIC_ALL = 0x10000000 

87 

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

89PRINTER_CHANGE_SET_PRINTER = 0x00000002 

90PRINTER_CHANGE_DELETE_PRINTER = 0x00000004 

91PRINTER_CHANGE_PRINTER = 0x000000FF 

92PRINTER_CHANGE_ADD_JOB = 0x00000100 

93PRINTER_CHANGE_SET_JOB = 0x00000200 

94PRINTER_CHANGE_DELETE_JOB = 0x00000400 

95PRINTER_CHANGE_WRITE_JOB = 0x00000800 

96PRINTER_CHANGE_JOB = 0x0000FF00 

97PRINTER_CHANGE_SET_PRINTER_DRIVER = 0x20000000 

98PRINTER_CHANGE_TIMEOUT = 0x80000000 

99PRINTER_CHANGE_ALL = 0x7777FFFF 

100PRINTER_CHANGE_ALL_2 = 0x7F77FFFF 

101 

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

103PRINTER_CHANGE_ADD_PRINTER_DRIVER = 0x10000000 

104PRINTER_CHANGE_DELETE_PRINTER_DRIVER = 0x40000000 

105PRINTER_CHANGE_PRINTER_DRIVER = 0x70000000 

106PRINTER_CHANGE_ADD_FORM = 0x00010000 

107PRINTER_CHANGE_DELETE_FORM = 0x00040000 

108PRINTER_CHANGE_SET_FORM = 0x00020000 

109PRINTER_CHANGE_FORM = 0x00070000 

110PRINTER_CHANGE_ADD_PORT = 0x00100000 

111PRINTER_CHANGE_CONFIGURE_PORT = 0x00200000 

112PRINTER_CHANGE_DELETE_PORT = 0x00400000 

113PRINTER_CHANGE_PORT = 0x00700000 

114PRINTER_CHANGE_ADD_PRINT_PROCESSOR = 0x01000000 

115PRINTER_CHANGE_DELETE_PRINT_PROCESSOR = 0x04000000 

116PRINTER_CHANGE_PRINT_PROCESSOR = 0x07000000 

117PRINTER_CHANGE_ADD_PRINTER = 0x00000001 

118PRINTER_CHANGE_FAILED_CONNECTION_PRINTER = 0x00000008 

119PRINTER_CHANGE_SERVER = 0x08000000 

120 

121# 2.2.3.7 Printer Enumeration Flags 

122PRINTER_ENUM_LOCAL = 0x00000002 

123PRINTER_ENUM_CONNECTIONS = 0x00000004 

124PRINTER_ENUM_NAME = 0x00000008 

125PRINTER_ENUM_REMOTE = 0x00000010 

126PRINTER_ENUM_SHARED = 0x00000020 

127PRINTER_ENUM_NETWORK = 0x00000040 

128PRINTER_ENUM_EXPAND = 0x00004000 

129PRINTER_ENUM_CONTAINER = 0x00008000 

130PRINTER_ENUM_ICON1 = 0x00010000 

131PRINTER_ENUM_ICON2 = 0x00020000 

132PRINTER_ENUM_ICON3 = 0x00040000 

133PRINTER_ENUM_ICON8 = 0x00800000 

134PRINTER_ENUM_HIDE = 0x01000000 

135 

136 

137# 2.2.3.8 Printer Notification Values 

138PRINTER_NOTIFY_CATEGORY_2D = 0x00000000 

139PRINTER_NOTIFY_CATEGORY_ALL = 0x00010000 

140PRINTER_NOTIFY_CATEGORY_3D = 0x00020000 

141 

142 

143################################################################################ 

144# STRUCTURES 

145################################################################################ 

146# 2.2.1.1.4 PRINTER_HANDLE 

147class PRINTER_HANDLE(NDRSTRUCT): 

148 structure = ( 

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

150 ) 

151 def getAlignment(self): 

152 if self._isNDR64 is True: 

153 return 8 

154 else: 

155 return 4 

156 

157# 2.2.1.2.1 DEVMODE_CONTAINER 

158class BYTE_ARRAY(NDRUniConformantArray): 

159 item = 'c' 

160 

161class PBYTE_ARRAY(NDRPOINTER): 

162 referent = ( 

163 ('Data', BYTE_ARRAY), 

164 ) 

165 

166class DEVMODE_CONTAINER(NDRSTRUCT): 

167 structure = ( 

168 ('cbBuf',DWORD), 

169 ('pDevMode',PBYTE_ARRAY), 

170 ) 

171 

172# 2.2.1.11.1 SPLCLIENT_INFO_1 

173class SPLCLIENT_INFO_1(NDRSTRUCT): 

174 structure = ( 

175 ('dwSize',DWORD), 

176 ('pMachineName',LPWSTR), 

177 ('pUserName',LPWSTR), 

178 ('dwBuildNum',DWORD), 

179 ('dwMajorVersion',DWORD), 

180 ('dwMinorVersion',DWORD), 

181 ('wProcessorArchitecture',USHORT), 

182 ) 

183 

184class PSPLCLIENT_INFO_1(NDRPOINTER): 

185 referent = ( 

186 ('Data', SPLCLIENT_INFO_1), 

187 ) 

188 

189# 2.2.1.11.2 SPLCLIENT_INFO_2 

190class SPLCLIENT_INFO_2(NDRSTRUCT): 

191 structure = ( 

192 ('notUsed',ULONGLONG), 

193 ) 

194 

195class PSPLCLIENT_INFO_2(NDRPOINTER): 

196 referent = ( 

197 ('Data', SPLCLIENT_INFO_2), 

198 ) 

199# 2.2.1.11.3 SPLCLIENT_INFO_3 

200class SPLCLIENT_INFO_3(NDRSTRUCT): 

201 structure = ( 

202 ('cbSize',UINT), 

203 ('dwFlags',DWORD), 

204 ('dwFlags',DWORD), 

205 ('pMachineName',LPWSTR), 

206 ('pUserName',LPWSTR), 

207 ('dwBuildNum',DWORD), 

208 ('dwMajorVersion',DWORD), 

209 ('dwMinorVersion',DWORD), 

210 ('wProcessorArchitecture',USHORT), 

211 ('hSplPrinter',ULONGLONG), 

212 ) 

213 

214class PSPLCLIENT_INFO_3(NDRPOINTER): 

215 referent = ( 

216 ('Data', SPLCLIENT_INFO_3), 

217 ) 

218# 2.2.1.2.14 SPLCLIENT_CONTAINER 

219class CLIENT_INFO_UNION(NDRUNION): 

220 commonHdr = ( 

221 ('tag', ULONG), 

222 ) 

223 union = { 

224 1 : ('pClientInfo1', PSPLCLIENT_INFO_1), 

225 2 : ('pNotUsed1', PSPLCLIENT_INFO_2), 

226 3 : ('pNotUsed2', PSPLCLIENT_INFO_3), 

227 } 

228 

229class SPLCLIENT_CONTAINER(NDRSTRUCT): 

230 structure = ( 

231 ('Level',DWORD), 

232 ('ClientInfo',CLIENT_INFO_UNION), 

233 ) 

234 

235 

236# 2.2.1.13.2 RPC_V2_NOTIFY_OPTIONS_TYPE 

237class USHORT_ARRAY(NDRUniConformantArray): 

238 item = '<H' 

239 

240class PUSHORT_ARRAY(NDRPOINTER): 

241 referent = ( 

242 ('Data', USHORT_ARRAY), 

243 ) 

244 

245class RPC_V2_NOTIFY_OPTIONS_TYPE(NDRSTRUCT): 

246 structure = ( 

247 ('Type',USHORT), 

248 ('Reserved0',USHORT), 

249 ('Reserved1',DWORD), 

250 ('Reserved2',DWORD), 

251 ('Count',DWORD), 

252 ('pFields',PUSHORT_ARRAY), 

253 ) 

254 

255class PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY(NDRPOINTER): 

256 referent = ( 

257 ('Data', RPC_V2_NOTIFY_OPTIONS_TYPE), 

258 ) 

259 

260# 2.2.1.13.1 RPC_V2_NOTIFY_OPTIONS 

261class RPC_V2_NOTIFY_OPTIONS(NDRSTRUCT): 

262 structure = ( 

263 ('Version',DWORD), 

264 ('Reserved',DWORD), 

265 ('Count',DWORD), 

266 ('pTypes',PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY), 

267 ) 

268 

269class PRPC_V2_NOTIFY_OPTIONS(NDRPOINTER): 

270 referent = ( 

271 ('Data', RPC_V2_NOTIFY_OPTIONS), 

272 ) 

273 

274 

275################################################################################ 

276# RPC CALLS 

277################################################################################ 

278# 3.1.4.2.1 RpcEnumPrinters (Opnum 0) 

279class RpcEnumPrinters(NDRCALL): 

280 opnum = 0 

281 structure = ( 

282 ('Flags', DWORD), 

283 ('Name', STRING_HANDLE), 

284 ('Level', DWORD), 

285 ('pPrinterEnum', PBYTE_ARRAY), 

286 ('cbBuf', DWORD), 

287 ) 

288 

289class RpcEnumPrintersResponse(NDRCALL): 

290 structure = ( 

291 ('pPrinterEnum', PBYTE_ARRAY), 

292 ('pcbNeeded', DWORD), 

293 ('pcReturned', DWORD), 

294 ('ErrorCode', ULONG), 

295 ) 

296# 3.1.4.2.2 RpcOpenPrinter (Opnum 1) 

297class RpcOpenPrinter(NDRCALL): 

298 opnum = 1 

299 structure = ( 

300 ('pPrinterName', STRING_HANDLE), 

301 ('pDatatype', LPWSTR), 

302 ('pDevModeContainer', DEVMODE_CONTAINER), 

303 ('AccessRequired', DWORD), 

304 ) 

305 

306class RpcOpenPrinterResponse(NDRCALL): 

307 structure = ( 

308 ('pHandle', PRINTER_HANDLE), 

309 ('ErrorCode', ULONG), 

310 ) 

311 

312# 3.1.4.2.9 RpcClosePrinter (Opnum 29) 

313class RpcClosePrinter(NDRCALL): 

314 opnum = 29 

315 structure = ( 

316 ('phPrinter', PRINTER_HANDLE), 

317 ) 

318 

319class RpcClosePrinterResponse(NDRCALL): 

320 structure = ( 

321 ('phPrinter', PRINTER_HANDLE), 

322 ('ErrorCode', ULONG), 

323 ) 

324 

325# 3.1.4.10.4 RpcRemoteFindFirstPrinterChangeNotificationEx (Opnum 65) 

326class RpcRemoteFindFirstPrinterChangeNotificationEx(NDRCALL): 

327 opnum = 65 

328 structure = ( 

329 ('hPrinter', PRINTER_HANDLE), 

330 ('fdwFlags', DWORD), 

331 ('fdwOptions', DWORD), 

332 ('pszLocalMachine', LPWSTR), 

333 ('dwPrinterLocal', DWORD), 

334 ('pOptions', PRPC_V2_NOTIFY_OPTIONS), 

335 ) 

336 

337class RpcRemoteFindFirstPrinterChangeNotificationExResponse(NDRCALL): 

338 structure = ( 

339 ('ErrorCode', ULONG), 

340 ) 

341 

342# 3.1.4.2.14 RpcOpenPrinterEx (Opnum 69) 

343class RpcOpenPrinterEx(NDRCALL): 

344 opnum = 69 

345 structure = ( 

346 ('pPrinterName', STRING_HANDLE), 

347 ('pDatatype', LPWSTR), 

348 ('pDevModeContainer', DEVMODE_CONTAINER), 

349 ('AccessRequired', DWORD), 

350 ('pClientInfo', SPLCLIENT_CONTAINER), 

351 ) 

352 

353class RpcOpenPrinterExResponse(NDRCALL): 

354 structure = ( 

355 ('pHandle', PRINTER_HANDLE), 

356 ('ErrorCode', ULONG), 

357 ) 

358 

359################################################################################ 

360# OPNUMs and their corresponding structures 

361################################################################################ 

362OPNUMS = { 

363 0 : (RpcEnumPrinters, RpcEnumPrintersResponse), 

364 1 : (RpcOpenPrinter, RpcOpenPrinterResponse), 

365 29 : (RpcClosePrinter, RpcClosePrinterResponse), 

366 65 : (RpcRemoteFindFirstPrinterChangeNotificationEx, RpcRemoteFindFirstPrinterChangeNotificationExResponse), 

367 69 : (RpcOpenPrinterEx, RpcOpenPrinterExResponse), 

368} 

369 

370################################################################################ 

371# HELPER FUNCTIONS 

372################################################################################ 

373def checkNullString(string): 

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

375 return string 

376 

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

378 return string + '\x00' 

379 else: 

380 return string 

381 

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

383 """ 

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

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

386 

387 :param DCERPC_v5 dce: a connected DCE instance. 

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

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

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

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

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

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

394 DEVMODE_CONTAINER Parameters (section 3.1.4.1.8.1). 

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

396 handle is being opened. 

397 

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

399 """ 

400 request = RpcOpenPrinter() 

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

402 request['pDatatype'] = pDatatype 

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

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

405 else: 

406 request['pDevModeContainer'] = pDevModeContainer 

407 

408 request['AccessRequired'] = accessRequired 

409 return dce.request(request) 

410 

411def hRpcClosePrinter(dce, phPrinter): 

412 """ 

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

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

415 

416 :param DCERPC_v5 dce: a connected DCE instance. 

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

418 

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

420 """ 

421 request = RpcClosePrinter() 

422 request['phPrinter'] = phPrinter 

423 return dce.request(request) 

424 

425 

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

427 pClientInfo=NULL): 

428 """ 

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

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

431 

432 :param DCERPC_v5 dce: a connected DCE instance. 

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

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

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

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

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

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

439 DEVMODE_CONTAINER Parameters (section 3.1.4.1.8.1). 

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

441 handle is being opened. 

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

443 

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

445 """ 

446 request = RpcOpenPrinterEx() 

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

448 request['pDatatype'] = pDatatype 

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

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

451 else: 

452 request['pDevModeContainer'] = pDevModeContainer 

453 

454 request['AccessRequired'] = accessRequired 

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

456 raise Exception('pClientInfo cannot be NULL') 

457 

458 request['pClientInfo'] = pClientInfo 

459 return dce.request(request) 

460 

461 

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

463 dwPrinterLocal=0, pOptions=NULL): 

464 """ 

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

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

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

468 

469 :param DCERPC_v5 dce: a connected DCE instance. 

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

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

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

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

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

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

476 :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. 

477 

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

479 """ 

480 request = RpcRemoteFindFirstPrinterChangeNotificationEx() 

481 

482 request['hPrinter'] = hPrinter 

483 request['fdwFlags'] = fdwFlags 

484 request['fdwOptions'] = fdwOptions 

485 request['dwPrinterLocal'] = dwPrinterLocal 

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

487 raise Exception('pszLocalMachine cannot be NULL') 

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

489 request['pOptions'] = pOptions 

490 return dce.request(request) 

491 

492def hRpcEnumPrinters(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 = RpcEnumPrinters() 

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) 

513 except DCERPCSessionError as e: 

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

515 raise 

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

517 

518 request = RpcEnumPrinters() 

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)