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

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
30MSRPC_UUID_RPRN = uuidtup_to_bin(('12345678-1234-ABCD-EF00-0123456789AB', '1.0'))
32class DCERPCSessionError(DCERPCException):
33 def __init__(self, error_string=None, error_code=None, packet=None):
34 DCERPCException.__init__(self, error_string, error_code, packet)
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
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 )
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
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
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
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
140# 2.2.3.8 Printer Notification Values
141PRINTER_NOTIFY_CATEGORY_2D = 0x00000000
142PRINTER_NOTIFY_CATEGORY_ALL = 0x00010000
143PRINTER_NOTIFY_CATEGORY_3D = 0x00020000
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
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
171# 2.2.1.2.1 DEVMODE_CONTAINER
172class BYTE_ARRAY(NDRUniConformantArray):
173 item = 'c'
175class PBYTE_ARRAY(NDRPOINTER):
176 referent = (
177 ('Data', BYTE_ARRAY),
178 )
180class DEVMODE_CONTAINER(NDRSTRUCT):
181 structure = (
182 ('cbBuf',DWORD),
183 ('pDevMode',PBYTE_ARRAY),
184 )
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 )
198class PSPLCLIENT_INFO_1(NDRPOINTER):
199 referent = (
200 ('Data', SPLCLIENT_INFO_1),
201 )
203# 2.2.1.11.2 SPLCLIENT_INFO_2
204class SPLCLIENT_INFO_2(NDRSTRUCT):
205 structure = (
206 ('notUsed',ULONGLONG),
207 )
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 )
228class PSPLCLIENT_INFO_3(NDRPOINTER):
229 referent = (
230 ('Data', SPLCLIENT_INFO_3),
231 )
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 )
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 )
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 }
268class DRIVER_CONTAINER(NDRSTRUCT):
269 structure = (
270 ('Level', DWORD),
271 ('DriverInfo', DRIVER_INFO_UNION),
272 )
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 }
285class SPLCLIENT_CONTAINER(NDRSTRUCT):
286 structure = (
287 ('Level',DWORD),
288 ('ClientInfo',CLIENT_INFO_UNION),
289 )
291# 2.2.1.13.2 RPC_V2_NOTIFY_OPTIONS_TYPE
292class USHORT_ARRAY(NDRUniConformantArray):
293 item = '<H'
295class PUSHORT_ARRAY(NDRPOINTER):
296 referent = (
297 ('Data', USHORT_ARRAY),
298 )
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 )
310class PRPC_V2_NOTIFY_OPTIONS_TYPE_ARRAY(NDRPOINTER):
311 referent = (
312 ('Data', RPC_V2_NOTIFY_OPTIONS_TYPE),
313 )
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 )
324class PRPC_V2_NOTIFY_OPTIONS(NDRPOINTER):
325 referent = (
326 ('Data', RPC_V2_NOTIFY_OPTIONS),
327 )
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 )
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 )
361class RpcOpenPrinterResponse(NDRCALL):
362 structure = (
363 ('pHandle', PRINTER_HANDLE),
364 ('ErrorCode', ULONG),
365 )
367# 3.1.4.2.9 RpcClosePrinter (Opnum 29)
368class RpcClosePrinter(NDRCALL):
369 opnum = 29
370 structure = (
371 ('phPrinter', PRINTER_HANDLE),
372 )
374class RpcClosePrinterResponse(NDRCALL):
375 structure = (
376 ('phPrinter', PRINTER_HANDLE),
377 ('ErrorCode', ULONG),
378 )
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 )
392class RpcRemoteFindFirstPrinterChangeNotificationExResponse(NDRCALL):
393 structure = (
394 ('ErrorCode', ULONG),
395 )
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 )
408class RpcOpenPrinterExResponse(NDRCALL):
409 structure = (
410 ('pHandle', PRINTER_HANDLE),
411 ('ErrorCode', ULONG),
412 )
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 )
425class RpcEnumPrinterDriversResponse(NDRCALL):
426 structure = (
427 ('pDrivers', PBYTE_ARRAY),
428 ('pcbNeeded', DWORD),
429 ('pcReturned', DWORD),
430 ('ErrorCode', ULONG),
431 )
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 )
442class RpcAddPrinterDriverExResponse(NDRCALL):
443 structure = (
444 ('ErrorCode', ULONG),
445 )
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}
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
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
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
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.
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
498 request['AccessRequired'] = accessRequired
499 return dce.request(request)
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
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.
509 :return: a RpcClosePrinterResponse instance, raises DCERPCSessionError on error.
510 """
511 request = RpcClosePrinter()
512 request['phPrinter'] = phPrinter
513 return dce.request(request)
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
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.
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
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')
548 request['pClientInfo'] = pClientInfo
549 return dce.request(request)
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
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.
568 :return: a RpcRemoteFindFirstPrinterChangeNotificationExResponse instance, raises DCERPCSessionError on error.
569 """
570 request = RpcRemoteFindFirstPrinterChangeNotificationEx()
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)
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
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.
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']
608 request = RpcEnumPrinters()
609 request['Flags'] = flags
610 request['Name'] = name
611 request['Level'] = level
613 request['cbBuf'] = bytesNeeded
614 request['pPrinterEnum'] = b'a' * bytesNeeded
615 return dce.request(request)
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
623 :param DCERPC_v5 dce: a connected DCE instance.
624 :param pName
625 :param pDriverContainer
626 :param dwFileCopyFlags
628 :return: raises DCERPCSessionError on error.
629 """
630 request = RpcAddPrinterDriverEx()
631 request['pName'] = checkNullString(pName)
632 request['pDriverContainer'] = pDriverContainer
633 request['dwFileCopyFlags'] = dwFileCopyFlags
635 #return request
636 return dce.request(request)
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
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
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']
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
677 #return request
678 return dce.request(request)