Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/rprn.py: 93%

# Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/rprn.py : 93%

## 227 statements

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#

21 from impacket import system_errors

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

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

24 from impacket.dcerpc.v5.rpcrt import DCERPCException

25 from impacket.uuid import uuidtup_to_bin

26

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

28

29 class 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

46 STRING_HANDLE = LPWSTR

47 class PSTRING_HANDLE(NDRPOINTER):

48 referent = (

49 ('Data', STRING_HANDLE),

50 )

51

52# 2.2.3.1 Access Values

53 JOB_ACCESS_ADMINISTER = 0x00000010

54 JOB_ACCESS_READ = 0x00000020

55 JOB_EXECUTE = 0x00020010

56 JOB_READ = 0x00020020

57 JOB_WRITE = 0x00020010

58 JOB_ALL_ACCESS = 0x000F0030

59 PRINTER_ACCESS_ADMINISTER = 0x00000004

60 PRINTER_ACCESS_USE = 0x00000008

61 PRINTER_ACCESS_MANAGE_LIMITED = 0x00000040

62 PRINTER_ALL_ACCESS = 0x000F000C

63 PRINTER_EXECUTE = 0x00020008

64 PRINTER_READ = 0x00020008

65 PRINTER_WRITE = 0x00020008

66 SERVER_ACCESS_ADMINISTER = 0x00000001

67 SERVER_ACCESS_ENUMERATE = 0x00000002

68 SERVER_ALL_ACCESS = 0x000F0003

69 SERVER_EXECUTE = 0x00020002

70 SERVER_READ = 0x00020002

71 SERVER_WRITE = 0x00020003

72 SPECIFIC_RIGHTS_ALL = 0x0000FFFF

73 STANDARD_RIGHTS_ALL = 0x001F0000

74 STANDARD_RIGHTS_EXECUTE = 0x00020000

75 STANDARD_RIGHTS_READ = 0x00020000

76 STANDARD_RIGHTS_REQUIRED = 0x000F0000

77 STANDARD_RIGHTS_WRITE = 0x00020000

78 SYNCHRONIZE = 0x00100000

79 DELETE = 0x00010000

80 READ_CONTROL = 0x00020000

81 WRITE_DAC = 0x00040000

82 WRITE_OWNER = 0x00080000

83 GENERIC_READ = 0x80000000

84 GENERIC_WRITE = 0x40000000

85 GENERIC_EXECUTE = 0x20000000

86 GENERIC_ALL = 0x10000000

87

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

89 PRINTER_CHANGE_SET_PRINTER = 0x00000002

90 PRINTER_CHANGE_DELETE_PRINTER = 0x00000004

91 PRINTER_CHANGE_PRINTER = 0x000000FF

92 PRINTER_CHANGE_ADD_JOB = 0x00000100

93 PRINTER_CHANGE_SET_JOB = 0x00000200

94 PRINTER_CHANGE_DELETE_JOB = 0x00000400

95 PRINTER_CHANGE_WRITE_JOB = 0x00000800

96 PRINTER_CHANGE_JOB = 0x0000FF00

97 PRINTER_CHANGE_SET_PRINTER_DRIVER = 0x20000000

98 PRINTER_CHANGE_TIMEOUT = 0x80000000

99 PRINTER_CHANGE_ALL = 0x7777FFFF

100 PRINTER_CHANGE_ALL_2 = 0x7F77FFFF

101

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

103 PRINTER_CHANGE_ADD_PRINTER_DRIVER = 0x10000000

104 PRINTER_CHANGE_DELETE_PRINTER_DRIVER = 0x40000000

105 PRINTER_CHANGE_PRINTER_DRIVER = 0x70000000

106 PRINTER_CHANGE_ADD_FORM = 0x00010000

107 PRINTER_CHANGE_DELETE_FORM = 0x00040000

108 PRINTER_CHANGE_SET_FORM = 0x00020000

109 PRINTER_CHANGE_FORM = 0x00070000

110 PRINTER_CHANGE_ADD_PORT = 0x00100000

111 PRINTER_CHANGE_CONFIGURE_PORT = 0x00200000

112 PRINTER_CHANGE_DELETE_PORT = 0x00400000

113 PRINTER_CHANGE_PORT = 0x00700000

114 PRINTER_CHANGE_ADD_PRINT_PROCESSOR = 0x01000000

115 PRINTER_CHANGE_DELETE_PRINT_PROCESSOR = 0x04000000

116 PRINTER_CHANGE_PRINT_PROCESSOR = 0x07000000

117 PRINTER_CHANGE_ADD_PRINTER = 0x00000001

118 PRINTER_CHANGE_FAILED_CONNECTION_PRINTER = 0x00000008

119 PRINTER_CHANGE_SERVER = 0x08000000

120

121# 2.2.3.7 Printer Enumeration Flags

122 PRINTER_ENUM_LOCAL = 0x00000002

123 PRINTER_ENUM_CONNECTIONS = 0x00000004

124 PRINTER_ENUM_NAME = 0x00000008

125 PRINTER_ENUM_REMOTE = 0x00000010

126 PRINTER_ENUM_SHARED = 0x00000020

127 PRINTER_ENUM_NETWORK = 0x00000040

128 PRINTER_ENUM_EXPAND = 0x00004000

129 PRINTER_ENUM_CONTAINER = 0x00008000

130 PRINTER_ENUM_ICON1 = 0x00010000

131 PRINTER_ENUM_ICON2 = 0x00020000

132 PRINTER_ENUM_ICON3 = 0x00040000

133 PRINTER_ENUM_ICON8 = 0x00800000

134 PRINTER_ENUM_HIDE = 0x01000000

135

136

137# 2.2.3.8 Printer Notification Values

138 PRINTER_NOTIFY_CATEGORY_2D = 0x00000000

139 PRINTER_NOTIFY_CATEGORY_ALL = 0x00010000

140 PRINTER_NOTIFY_CATEGORY_3D = 0x00020000

141

142

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

144# STRUCTURES

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

146# 2.2.1.1.4 PRINTER_HANDLE

147 class 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

158 class BYTE_ARRAY(NDRUniConformantArray):

159 item = 'c'

160

161 class PBYTE_ARRAY(NDRPOINTER):

162 referent = (

163 ('Data', BYTE_ARRAY),

164 )

165

166 class DEVMODE_CONTAINER(NDRSTRUCT):

167 structure = (

168 ('cbBuf',DWORD),

169 ('pDevMode',PBYTE_ARRAY),

170 )

171

172# 2.2.1.11.1 SPLCLIENT_INFO_1

173 class 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

184 class PSPLCLIENT_INFO_1(NDRPOINTER):

185 referent = (

186 ('Data', SPLCLIENT_INFO_1),

187 )

188

189# 2.2.1.11.2 SPLCLIENT_INFO_2

190 class SPLCLIENT_INFO_2(NDRSTRUCT):

191 structure = (

192 ('notUsed',ULONGLONG),

193 )

194

195 class PSPLCLIENT_INFO_2(NDRPOINTER):

196 referent = (

197 ('Data', SPLCLIENT_INFO_2),

198 )

199# 2.2.1.11.3 SPLCLIENT_INFO_3

200 class 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

214 class PSPLCLIENT_INFO_3(NDRPOINTER):

215 referent = (

216 ('Data', SPLCLIENT_INFO_3),

217 )

218# 2.2.1.2.14 SPLCLIENT_CONTAINER

219 class 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

229 class 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

237 class USHORT_ARRAY(NDRUniConformantArray):

238 item = '<H'

239

240 class PUSHORT_ARRAY(NDRPOINTER):

241 referent = (

242 ('Data', USHORT_ARRAY),

243 )

244

245 class 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

255 class 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

261 class 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

269 class 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)

279 class 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

289 class 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)

297 class RpcOpenPrinter(NDRCALL):

298 opnum = 1

299 structure = (

300 ('pPrinterName', STRING_HANDLE),

301 ('pDatatype', LPWSTR),

302 ('pDevModeContainer', DEVMODE_CONTAINER),

303 ('AccessRequired', DWORD),

304 )

305

306 class RpcOpenPrinterResponse(NDRCALL):

307 structure = (

308 ('pHandle', PRINTER_HANDLE),

309 ('ErrorCode', ULONG),

310 )

311

312# 3.1.4.2.9 RpcClosePrinter (Opnum 29)

313 class RpcClosePrinter(NDRCALL):

314 opnum = 29

315 structure = (

316 ('phPrinter', PRINTER_HANDLE),

317 )

318

319 class RpcClosePrinterResponse(NDRCALL):

320 structure = (

321 ('phPrinter', PRINTER_HANDLE),

322 ('ErrorCode', ULONG),

323 )

324

325# 3.1.4.10.4 RpcRemoteFindFirstPrinterChangeNotificationEx (Opnum 65)

326 class 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

337 class RpcRemoteFindFirstPrinterChangeNotificationExResponse(NDRCALL):

338 structure = (

339 ('ErrorCode', ULONG),

340 )

341

342# 3.1.4.2.14 RpcOpenPrinterEx (Opnum 69)

343 class 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

353 class RpcOpenPrinterExResponse(NDRCALL):

354 structure = (

355 ('pHandle', PRINTER_HANDLE),

356 ('ErrorCode', ULONG),

357 )

358

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

360# OPNUMs and their corresponding structures

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

362 OPNUMS = {

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################################################################################

373 def 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

382 def 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

411 def 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

426 def 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

462 def 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

492 def 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)