1# Copyright (c) 2003-2016 CORE Security Technologies
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-SCMR] 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/CoreSecurity/impacket/tree/master/impacket/testcases/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 struct import pack, unpack
22
23from impacket import system_errors
24from impacket.uuid import uuidtup_to_bin
25from impacket.dcerpc.v5.ndr import NDRCALL, NDR, NDRSTRUCT, NDRPOINTER, NDRPOINTERNULL, NDRUniConformantArray, NDRUNION
26from impacket.dcerpc.v5.dtypes import NULL, DWORD, LPWSTR, ULONG, BOOL, LPBYTE, ULONGLONG, PGUID, USHORT, LPDWORD, WSTR, \
27    GUID, PBOOL, WIDESTR
28from impacket.dcerpc.v5.rpcrt import DCERPCException
29
30MSRPC_UUID_SCMR = uuidtup_to_bin(('367ABB81-9844-35F1-AD32-98F038001003', '2.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 system_errors.ERROR_MESSAGES.has_key(key):
39            error_msg_short = system_errors.ERROR_MESSAGES[key][0]
40            error_msg_verbose = system_errors.ERROR_MESSAGES[key][1]
41            return 'SCMR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
42        else:
43            return 'SCMR SessionError: unknown error code: 0x%x' % self.error_code
44
45################################################################################
46# CONSTANTS
47################################################################################
48
49# Access codes
50SERVICE_ALL_ACCESS            = 0X000F01FF
51SERVICE_CHANGE_CONFIG         = 0X00000002
52SERVICE_ENUMERATE_DEPENDENTS  = 0X00000008
53SERVICE_INTERROGATE           = 0X00000080
54SERVICE_PAUSE_CONTINUE        = 0X00000040
55SERVICE_QUERY_CONFIG          = 0X00000001
56SERVICE_QUERY_STATUS          = 0X00000004
57SERVICE_START                 = 0X00000010
58SERVICE_STOP                  = 0X00000020
59SERVICE_USER_DEFINED_CTRL     = 0X00000100
60SERVICE_SET_STATUS            = 0X00008000
61
62# Specific Access for SCM
63SC_MANAGER_LOCK               = 0x00000008
64SC_MANAGER_CREATE_SERVICE     = 0x00000002
65SC_MANAGER_ENUMERATE_SERVICE  = 0x00000004
66SC_MANAGER_CONNECT            = 0x00000001
67SC_MANAGER_QUERY_LOCK_STATUS  = 0x00000010
68SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00000020
69
70# Service Types
71SERVICE_KERNEL_DRIVER         = 0x00000001
72SERVICE_FILE_SYSTEM_DRIVER    = 0x00000002
73SERVICE_WIN32_OWN_PROCESS     = 0x00000010
74SERVICE_WIN32_SHARE_PROCESS   = 0x00000020
75SERVICE_INTERACTIVE_PROCESS   = 0x00000100
76SERVICE_NO_CHANGE             = 0xffffffff
77
78# Start Types
79SERVICE_BOOT_START            = 0x00000000
80SERVICE_SYSTEM_START          = 0x00000001
81SERVICE_AUTO_START            = 0x00000002
82SERVICE_DEMAND_START          = 0x00000003
83SERVICE_DISABLED              = 0x00000004
84SERVICE_NO_CHANGE             = 0xffffffff
85
86# Error Control
87SERVICE_ERROR_IGNORE          = 0x00000000
88SERVICE_ERROR_NORMAL          = 0x00000001
89SERVICE_ERROR_SEVERE          = 0x00000002
90SERVICE_ERROR_CRITICAL        = 0x00000003
91SERVICE_NO_CHANGE             = 0xffffffff
92
93# Service Control Codes
94SERVICE_CONTROL_CONTINUE      = 0x00000003
95SERVICE_CONTROL_INTERROGATE   = 0x00000004
96SERVICE_CONTROL_PARAMCHANGE   = 0x00000006
97SERVICE_CONTROL_PAUSE         = 0x00000002
98SERVICE_CONTROL_STOP          = 0x00000001
99SERVICE_CONTROL_NETBINDADD    = 0x00000007
100SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
101SERVICE_CONTROL_NETBINDENABLE = 0x00000009
102SERVICE_CONTROL_NETBINDDISABLE= 0x0000000A
103
104# Service State
105SERVICE_ACTIVE                = 0x00000001
106SERVICE_INACTIVE              = 0x00000002
107SERVICE_STATE_ALL             = 0x00000003
108
109# Current State
110SERVICE_CONTINUE_PENDING      = 0x00000005
111SERVICE_PAUSE_PENDING         = 0x00000006
112SERVICE_PAUSED                = 0x00000007
113SERVICE_RUNNING               = 0x00000004
114SERVICE_START_PENDING         = 0x00000002
115SERVICE_STOP_PENDING          = 0x00000003
116SERVICE_STOPPED               = 0x00000001
117
118# Controls Accepted
119SERVICE_ACCEPT_PARAMCHANGE           = 0x00000008
120SERVICE_ACCEPT_PAUSE_CONTINUE        = 0x00000002
121SERVICE_ACCEPT_SHUTDOWN              = 0x00000004
122SERVICE_ACCEPT_STOP                  = 0x00000001
123SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
124SERVICE_ACCEPT_POWEREVENT            = 0x00000040
125SERVICE_ACCEPT_SESSIONCHANGE         = 0x00000080
126SERVICE_ACCEPT_PRESHUTDOWN           = 0x00000100
127SERVICE_ACCEPT_TIMECHANGE            = 0x00000200
128ERVICE_ACCEPT_TRIGGEREVENT           = 0x00000400
129
130# Security Information
131DACL_SECURITY_INFORMATION     = 0x4
132GROUP_SECURITY_INFORMATION    = 0x2
133OWNER_SECURITY_INFORMATION    = 0x1
134SACL_SECURITY_INFORMATION     = 0x8
135
136# Service Config2 Info Levels
137SERVICE_CONFIG_DESCRIPTION              = 0x00000001
138SERVICE_CONFIG_FAILURE_ACTIONS          = 0x00000002
139SERVICE_CONFIG_DELAYED_AUTO_START_INFO  = 0x00000003
140SERVICE_CONFIG_FAILURE_ACTIONS_FLAG     = 0x00000004
141SERVICE_CONFIG_SERVICE_SID_INFO         = 0x00000005
142SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 0x00000006
143SERVICE_CONFIG_PRESHUTDOWN_INFO         = 0x00000007
144SERVICE_CONFIG_PREFERRED_NODE           = 0x00000009
145SERVICE_CONFIG_RUNLEVEL_INFO            = 0x0000000A
146
147# SC_ACTIONS Types
148SC_ACTION_NONE        = 0
149SC_ACTION_RESTART     = 1
150SC_ACTION_REBOOT      = 2
151SC_ACTION_RUN_COMMAND = 3
152
153# SERVICE_SID_INFO types
154SERVICE_SID_TYPE_NONE         = 0x00000000
155SERVICE_SID_TYPE_RESTRICTED   = 0x00000003
156SERVICE_SID_TYPE_UNRESTRICTED = 0x00000001
157
158# SC_STATUS_TYPE types
159SC_STATUS_PROCESS_INFO = 0
160
161# Notify Mask
162SERVICE_NOTIFY_CREATED          = 0x00000080
163SERVICE_NOTIFY_CONTINUE_PENDING = 0x00000010
164SERVICE_NOTIFY_DELETE_PENDING   = 0x00000200
165SERVICE_NOTIFY_DELETED          = 0x00000100
166SERVICE_NOTIFY_PAUSE_PENDING    = 0x00000020
167SERVICE_NOTIFY_PAUSED           = 0x00000040
168SERVICE_NOTIFY_RUNNING          = 0x00000008
169SERVICE_NOTIFY_START_PENDING    = 0x00000002
170SERVICE_NOTIFY_STOP_PENDING     = 0x00000004
171SERVICE_NOTIFY_STOPPED          = 0x00000001
172
173# SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW Reasons
174SERVICE_STOP_CUSTOM    =  0x20000000
175SERVICE_STOP_PLANNED   =  0x40000000
176SERVICE_STOP_UNPLANNED =  0x10000000
177
178# SERVICE_TRIGGER triggers
179SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL  = 0x00000001
180SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY   = 0x00000002
181SERVICE_TRIGGER_TYPE_DOMAIN_JOIN               = 0x00000003
182SERVICE_TRIGGER_TYPE_FIREWALL_PORT_EVENT       = 0x00000004
183SERVICE_TRIGGER_TYPE_GROUP_POLICY              = 0x00000005
184SERVICE_TRIGGER_TYPE_CUSTOM                    = 0x00000020
185
186# SERVICE_TRIGGER actions
187SERVICE_TRIGGER_ACTION_SERVICE_START = 0x00000001
188SERVICE_TRIGGER_ACTION_SERVICE_STOP  = 0x00000002
189
190# SERVICE_TRIGGER subTypes
191DOMAIN_JOIN_GUID                                = '1ce20aba-9851-4421-9430-1ddeb766e809'
192DOMAIN_LEAVE_GUID                               = 'ddaf516e-58c2-4866-9574-c3b615d42ea1'
193FIREWALL_PORT_OPEN_GUID                         = 'b7569e07-8421-4ee0-ad10-86915afdad09'
194FIREWALL_PORT_CLOSE_GUID                        = 'a144ed38-8e12-4de4-9d96-e64740b1a524'
195MACHINE_POLICY_PRESENT_GUID                     = '659FCAE6-5BDB-4DA9-B1FF-CA2A178D46E0'
196NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID   = '4f27f2de-14e2-430b-a549-7cd48cbc8245'
197NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID    = 'cc4ba62a-162e-4648-847a-b6bdf993e335'
198USER_POLICY_PRESENT_GUID                        = '54FB46C8-F089-464C-B1FD-59D1B62C3B50'
199
200# SERVICE_TRIGGER_SPECIFIC_DATA_ITEM dataTypes
201SERVICE_TRIGGER_DATA_TYPE_BINARY = 0x00000001
202SERVICE_TRIGGER_DATA_TYPE_STRING = 0x00000002
203
204################################################################################
205# STRUCTURES
206################################################################################
207
208class SC_RPC_HANDLE(NDRSTRUCT):
209    structure =  (
210        ('Data','20s=""'),
211    )
212    def getAlignment(self):
213        return 1
214
215SC_NOTIFY_RPC_HANDLE = SC_RPC_HANDLE
216
217class SERVICE_STATUS(NDRSTRUCT):
218    structure =  (
219        ('dwServiceType',DWORD),
220        ('dwCurrentState',DWORD),
221        ('dwControlsAccepted',DWORD),
222        ('dwWin32ExitCode',DWORD),
223        ('dwServiceSpecificExitCode',DWORD),
224        ('dwCheckPoint',DWORD),
225        ('dwWaitHint',DWORD),
226    )
227
228class QUERY_SERVICE_CONFIGW(NDRSTRUCT):
229    structure = (
230        ('dwServiceType',DWORD),
231        ('dwStartType',DWORD),
232        ('dwErrorControl',DWORD),
233        ('lpBinaryPathName', LPWSTR),
234        ('lpLoadOrderGroup',LPWSTR),
235        ('dwTagId',DWORD),
236        ('lpDependencies',LPWSTR),
237        ('lpServiceStartName',LPWSTR),
238        ('lpDisplayName',LPWSTR),
239    )
240
241class SC_RPC_LOCK(NDRSTRUCT):
242    structure =  (
243        ('Data','20s=""'),
244    )
245    def getAlignment(self):
246        return 1
247
248class LPSERVICE_STATUS(NDRPOINTER):
249    referent = (
250        ('Data',SERVICE_STATUS),
251    )
252
253SECURITY_INFORMATION = ULONG
254
255BOUNDED_DWORD_256K = DWORD
256
257class LPBOUNDED_DWORD_256K(NDRPOINTER):
258    referent = (
259        ('Data', BOUNDED_DWORD_256K),
260    )
261
262SVCCTL_HANDLEW = LPWSTR
263
264class ENUM_SERVICE_STATUSW(NDRSTRUCT):
265    structure = (
266        ('lpServiceName',LPWSTR),
267        ('lpDisplayName',LPWSTR),
268        ('ServiceStatus',SERVICE_STATUS),
269    )
270
271class LPQUERY_SERVICE_CONFIGW(NDRPOINTER):
272    referent = (
273        ('Data', QUERY_SERVICE_CONFIGW),
274    )
275
276BOUNDED_DWORD_8K = DWORD
277BOUNDED_DWORD_4K = DWORD
278
279class STRING_PTRSW(NDRSTRUCT):
280    structure = (
281        ('Data',NDRUniConformantArray),
282    )
283    def __init__(self, data = None, isNDR64 = False):
284        NDR.__init__(self,None,isNDR64)
285        self.fields['Data'].item = LPWSTR
286        if data is not None:
287            self.fromString(data)
288
289class UNIQUE_STRING_PTRSW(NDRPOINTER):
290    referent = (
291        ('Data', STRING_PTRSW),
292    )
293
294class QUERY_SERVICE_LOCK_STATUSW(NDRSTRUCT):
295    structure = (
296        ('fIsLocked',DWORD),
297        ('lpLockOwner',LPWSTR),
298        ('dwLockDuration',DWORD),
299    )
300
301class SERVICE_DESCRIPTION_WOW64(NDRSTRUCT):
302    structure = (
303        ('dwDescriptionOffset', DWORD),
304    )
305
306class SERVICE_DESCRIPTIONW(NDRSTRUCT):
307    structure = (
308        ('lpDescription', LPWSTR),
309    )
310
311class LPSERVICE_DESCRIPTIONW(NDRPOINTER):
312    referent = (
313        ('Data', SERVICE_DESCRIPTIONW),
314    )
315
316class SERVICE_FAILURE_ACTIONS_WOW64(NDRSTRUCT):
317    structure = (
318        ('dwResetPeriod', DWORD),
319        ('dwRebootMsgOffset', DWORD),
320        ('dwCommandOffset', DWORD),
321        ('cActions', DWORD),
322        ('dwsaActionsOffset', DWORD),
323    )
324
325class SC_ACTION(NDRSTRUCT):
326    structure = (
327        ('Type', DWORD),
328        ('Delay', DWORD) ,
329    )
330
331class SC_ACTIONS(NDRSTRUCT):
332    structure = (
333       ('Data', NDRUniConformantArray),
334    )
335    def __init__(self, data = None, isNDR64 = False):
336        NDR.__init__(self,None,isNDR64)
337        self.fields['Data'].item = SC_ACTION
338        if data is not None:
339            self.fromString(data)
340
341class SERVICE_FAILURE_ACTIONSW(NDRSTRUCT):
342    structure = (
343        ('dwResetPeriod', DWORD),
344        ('lpRebootMsg', LPWSTR) ,
345        ('lpCommand', LPWSTR) ,
346        ('cActions', DWORD) ,
347        ('lpsaActions', SC_ACTIONS) ,
348    )
349
350class LPSERVICE_FAILURE_ACTIONSW(NDRPOINTER):
351    referent = (
352        ('Data', SERVICE_FAILURE_ACTIONSW),
353    )
354
355class SERVICE_FAILURE_ACTIONS_FLAG(NDRSTRUCT):
356    structure = (
357        ('fFailureActionsOnNonCrashFailures', BOOL),
358    )
359
360class LPSERVICE_FAILURE_ACTIONS_FLAG(NDRPOINTER):
361    referent = (
362        ('Data', SERVICE_FAILURE_ACTIONS_FLAG),
363    )
364
365class SERVICE_DELAYED_AUTO_START_INFO(NDRSTRUCT):
366    structure = (
367        ('fDelayedAutostart', BOOL),
368    )
369
370class LPSERVICE_DELAYED_AUTO_START_INFO(NDRPOINTER):
371    referent = (
372        ('Data', SERVICE_DELAYED_AUTO_START_INFO),
373    )
374
375class SERVICE_SID_INFO(NDRSTRUCT):
376    structure = (
377        ('dwServiceSidType', DWORD),
378    )
379
380class LPSERVICE_SID_INFO(NDRPOINTER):
381    referent = (
382        ('Data', SERVICE_SID_INFO),
383    )
384
385
386class SERVICE_RPC_REQUIRED_PRIVILEGES_INFO(NDRSTRUCT):
387    structure = (
388        ('cbRequiredPrivileges',DWORD),
389        ('pRequiredPrivileges',LPBYTE),
390    )
391    def getData(self, soFar = 0):
392        self['cbRequiredPrivileges'] = len(self['pRequiredPrivileges'])
393        return NDR.getData(self, soFar = 0)
394
395
396class LPSERVICE_RPC_REQUIRED_PRIVILEGES_INFO(NDRPOINTER):
397    referent = (
398        ('Data', SERVICE_RPC_REQUIRED_PRIVILEGES_INFO),
399    )
400
401class SERVICE_REQUIRED_PRIVILEGES_INFO_WOW64(NDRSTRUCT):
402    structure = (
403        ('dwRequiredPrivilegesOffset', DWORD),
404    )
405
406class SERVICE_PRESHUTDOWN_INFO(NDRSTRUCT):
407    structure = (
408        ('dwPreshutdownTimeout', DWORD),
409    )
410
411class LPSERVICE_PRESHUTDOWN_INFO(NDRPOINTER):
412    referent = (
413        ('Data', SERVICE_PRESHUTDOWN_INFO),
414    )
415
416class SERVICE_STATUS_PROCESS(NDRSTRUCT):
417    structure = (
418        ('dwServiceType', DWORD),
419        ('dwCurrentState', DWORD),
420        ('dwControlsAccepted', DWORD),
421        ('dwWin32ExitCode', DWORD),
422        ('dwServiceSpecificExitCode', DWORD),
423        ('dwCheckPoint', DWORD),
424        ('dwWaitHint', DWORD),
425        ('dwProcessId', DWORD),
426        ('dwServiceFlags', DWORD),
427    )
428
429class UCHAR_16(NDRSTRUCT):
430    structure = (
431        ('Data', '16s=""'),
432    )
433    def getAlignment(self):
434        return 1
435
436class SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1(NDRSTRUCT):
437    structure = (
438        ('ullThreadId',ULONGLONG),
439        ('dwNotifyMask',DWORD),
440        ('CallbackAddressArray',UCHAR_16),
441        ('CallbackParamAddressArray',UCHAR_16),
442        ('ServiceStatus', SERVICE_STATUS_PROCESS),
443        ('dwNotificationStatus',DWORD),
444        ('dwSequence',DWORD),
445    )
446
447class SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2(NDRSTRUCT):
448    structure = (
449        ('ullThreadId',ULONGLONG),
450        ('dwNotifyMask',DWORD),
451        ('CallbackAddressArray',UCHAR_16),
452        ('CallbackParamAddressArray',UCHAR_16),
453        ('ServiceStatus',SERVICE_STATUS_PROCESS),
454        ('dwNotificationStatus',DWORD),
455        ('dwSequence',DWORD),
456        ('dwNotificationTriggered',DWORD),
457        ('pszServiceNames',LPWSTR),
458    )
459
460class PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1(NDRPOINTER):
461    referent = (
462        ('Data', SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1),
463    )
464
465class PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2(NDRPOINTER):
466    referent = (
467        ('Data', SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2),
468    )
469
470class SC_RPC_NOTIFY_PARAMS(NDRUNION):
471    union = {
472        1: ('pStatusChangeParam1', PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1),
473        2: ('pStatusChangeParams', PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2),
474    }
475
476class SC_RPC_NOTIFY_PARAMS_ARRAY(NDRUniConformantArray):
477     item = SC_RPC_NOTIFY_PARAMS
478
479class PSC_RPC_NOTIFY_PARAMS_LIST(NDRSTRUCT):
480    structure = (
481        ('cElements',BOUNDED_DWORD_4K),
482        ('NotifyParamsArray', SC_RPC_NOTIFY_PARAMS_ARRAY),
483    )
484
485class SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW(NDRSTRUCT):
486    structure = (
487        ('dwReason', DWORD),
488        ('pszComment', LPWSTR),
489    )
490
491class SERVICE_TRIGGER_SPECIFIC_DATA_ITEM(NDRSTRUCT):
492    structure = (
493        ('dwDataType',DWORD ),
494        ('cbData',DWORD),
495        ('pData', LPBYTE),
496    )
497    def getData(self, soFar = 0):
498        if self['pData'] != 0:
499            self['cbData'] = len(self['pData'])
500        return NDR.getData(self, soFar)
501
502class SERVICE_TRIGGER_SPECIFIC_DATA_ITEM_ARRAY(NDRUniConformantArray):
503    item = SERVICE_TRIGGER_SPECIFIC_DATA_ITEM
504
505class PSERVICE_TRIGGER_SPECIFIC_DATA_ITEM(NDRPOINTER):
506    referent = (
507        ('Data', SERVICE_TRIGGER_SPECIFIC_DATA_ITEM_ARRAY),
508    )
509
510class SERVICE_TRIGGER(NDRSTRUCT):
511    structure = (
512        ('dwTriggerType', DWORD),
513        ('dwAction', DWORD),
514        ('pTriggerSubtype', PGUID),
515        ('cDataItems', DWORD),
516        ('pDataItems', PSERVICE_TRIGGER_SPECIFIC_DATA_ITEM),
517    )
518    def getData(self, soFar = 0):
519        if self['pDataItems'] != 0:
520            self['cDataItems'] = len(self['pDataItems'])
521        return NDR.getData(self, soFar)
522
523class SERVICE_TRIGGER_ARRAY(NDRUniConformantArray):
524    item = SERVICE_TRIGGER
525
526class PSERVICE_TRIGGER(NDRPOINTER):
527    referent = (
528        ('Data', SERVICE_TRIGGER_ARRAY),
529    )
530
531class SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS(NDRSTRUCT):
532    structure = (
533       ('ServiceStatus', SERVICE_STATUS_PROCESS),
534    )
535
536class SERVICE_TRIGGER_INFO(NDRSTRUCT):
537    structure = (
538        ('cTriggers', DWORD),
539        ('pTriggers', PSERVICE_TRIGGER),
540        ('pReserved', NDRPOINTERNULL ),
541    )
542    def getData(self, soFar = 0):
543        if self['pTriggers'] != 0:
544            self['cTriggers'] = len(self['pTriggers'])
545        return NDR.getData(self, soFar)
546
547class PSERVICE_TRIGGER_INFO(NDRPOINTER):
548    referent = (
549        ('Data', SERVICE_TRIGGER_INFO),
550    )
551
552class SERVICE_PREFERRED_NODE_INFO(NDRSTRUCT):
553    structure = (
554        ('usPreferredNode', USHORT),
555        ('fDelete', BOOL),
556    )
557
558class LPSERVICE_PREFERRED_NODE_INFO(NDRPOINTER):
559    referent = (
560        ('Data', SERVICE_PREFERRED_NODE_INFO),
561    )
562
563class SERVICE_RUNLEVEL_INFO(NDRSTRUCT):
564    structure = (
565        ('eLowestRunLevel', DWORD),
566    )
567
568class PSERVICE_RUNLEVEL_INFO(NDRPOINTER):
569    referent = (
570        ('Data', SERVICE_RUNLEVEL_INFO),
571    )
572
573class SERVICE_MANAGEDACCOUNT_INFO(NDRSTRUCT):
574    structure = (
575        ('fIsManagedAccount', DWORD),
576    )
577
578class PSERVICE_MANAGEDACCOUNT_INFO(NDRPOINTER):
579    referent = (
580        ('Data', SERVICE_MANAGEDACCOUNT_INFO),
581    )
582
583class SC_RPC_CONFIG_INFOW_UNION(NDRUNION):
584    commonHdr = (
585        ('tag', ULONG),
586    )
587
588    union = {
589        1: ('psd', LPSERVICE_DESCRIPTIONW),
590        2: ('psfa',LPSERVICE_FAILURE_ACTIONSW ),
591        3: ('psda',LPSERVICE_DELAYED_AUTO_START_INFO),
592        4: ('psfaf',LPSERVICE_FAILURE_ACTIONS_FLAG),
593        5: ('pssid',LPSERVICE_SID_INFO),
594        6: ('psrp',LPSERVICE_RPC_REQUIRED_PRIVILEGES_INFO),
595        7: ('psps',LPSERVICE_PRESHUTDOWN_INFO),
596        8: ('psti',PSERVICE_TRIGGER_INFO),
597        9: ('pspn',LPSERVICE_PREFERRED_NODE_INFO),
598        10: ('psri',PSERVICE_RUNLEVEL_INFO),
599        11: ('psma',PSERVICE_MANAGEDACCOUNT_INFO),
600    }
601
602class SC_RPC_CONFIG_INFOW(NDRSTRUCT):
603    structure = (
604        ('dwInfoLevel', DWORD),
605        ('Union', SC_RPC_CONFIG_INFOW_UNION),
606    )
607
608################################################################################
609# RPC CALLS
610################################################################################
611
612class RCloseServiceHandle(NDRCALL):
613    opnum = 0
614    structure = (
615        ('hSCObject',SC_RPC_HANDLE),
616    )
617
618class RCloseServiceHandleResponse(NDRCALL):
619    structure = (
620        ('hSCObject',SC_RPC_HANDLE),
621        ('ErrorCode', DWORD),
622    )
623
624class RControlService(NDRCALL):
625    opnum = 1
626    structure = (
627        ('hService',SC_RPC_HANDLE),
628        ('dwControl',DWORD),
629    )
630
631class RControlServiceResponse(NDRCALL):
632    structure = (
633        ('lpServiceStatus',SERVICE_STATUS),
634        ('ErrorCode', DWORD),
635    )
636
637class RDeleteService(NDRCALL):
638    opnum = 2
639    structure = (
640        ('hService',SC_RPC_HANDLE),
641    )
642
643class RDeleteServiceResponse(NDRCALL):
644    structure = (
645        ('ErrorCode', DWORD),
646    )
647
648class RLockServiceDatabase(NDRCALL):
649    opnum = 3
650    structure = (
651        ('hSCManager',SC_RPC_HANDLE),
652    )
653
654class RLockServiceDatabaseResponse(NDRCALL):
655    structure = (
656        ('lpLock',SC_RPC_LOCK),
657        ('ErrorCode', DWORD),
658    )
659
660class RQueryServiceObjectSecurity(NDRCALL):
661    opnum = 4
662    structure = (
663        ('hService',SC_RPC_HANDLE),
664        ('dwSecurityInformation',SECURITY_INFORMATION),
665        ('cbBufSize',DWORD),
666    )
667
668class RQueryServiceObjectSecurityResponse(NDRCALL):
669    structure = (
670        ('lpSecurityDescriptor',LPBYTE),
671        ('pcbBytesNeeded',BOUNDED_DWORD_256K),
672        ('ErrorCode', DWORD),
673    )
674
675class RSetServiceObjectSecurity(NDRCALL):
676    opnum = 5
677    structure = (
678        ('hService',SC_RPC_HANDLE),
679        ('dwSecurityInformation',SECURITY_INFORMATION),
680        ('lpSecurityDescriptor',LPBYTE),
681        ('cbBufSize',DWORD),
682    )
683
684class RSetServiceObjectSecurityResponse(NDRCALL):
685    structure = (
686        ('ErrorCode', DWORD),
687    )
688
689class RQueryServiceStatus(NDRCALL):
690    opnum = 6
691    structure = (
692        ('hService',SC_RPC_HANDLE),
693    )
694
695class RQueryServiceStatusResponse(NDRCALL):
696    structure = (
697        ('lpServiceStatus',SERVICE_STATUS),
698        ('ErrorCode', DWORD),
699    )
700
701class RSetServiceStatus(NDRCALL):
702    opnum = 7
703    structure = (
704        ('hServiceStatus',SC_RPC_HANDLE),
705        ('lpServiceStatus',SERVICE_STATUS),
706    )
707
708class RSetServiceStatusResponse(NDRCALL):
709    structure = (
710        ('ErrorCode', DWORD),
711    )
712
713class RUnlockServiceDatabase(NDRCALL):
714    opnum = 8
715    structure = (
716        ('Lock',SC_RPC_LOCK),
717    )
718
719class RUnlockServiceDatabaseResponse(NDRCALL):
720    structure = (
721        ('Lock',SC_RPC_LOCK),
722        ('ErrorCode', DWORD),
723    )
724
725class RNotifyBootConfigStatus(NDRCALL):
726    opnum = 9
727    structure = (
728        ('lpMachineName',SVCCTL_HANDLEW),
729        ('BootAcceptable',DWORD),
730    )
731
732class RNotifyBootConfigStatusResponse(NDRCALL):
733    structure = (
734        ('ErrorCode', DWORD),
735    )
736
737class RChangeServiceConfigW(NDRCALL):
738    opnum = 11
739    structure = (
740        ('hService',SC_RPC_HANDLE),
741        ('dwServiceType',DWORD),
742        ('dwStartType',DWORD),
743        ('dwErrorControl',DWORD),
744        ('lpBinaryPathName',LPWSTR),
745        ('lpLoadOrderGroup',LPWSTR),
746        ('lpdwTagId',LPDWORD),
747        ('lpDependencies',LPBYTE),
748        ('dwDependSize',DWORD),
749        ('lpServiceStartName',LPWSTR),
750        ('lpPassword',LPBYTE),
751        ('dwPwSize',DWORD),
752        ('lpDisplayName',LPWSTR),
753    )
754
755class RChangeServiceConfigWResponse(NDRCALL):
756    structure = (
757        ('lpdwTagId',LPDWORD),
758        ('ErrorCode', DWORD),
759    )
760
761class RCreateServiceW(NDRCALL):
762    opnum = 12
763    structure = (
764        ('hSCManager',SC_RPC_HANDLE),
765        ('lpServiceName',WSTR),
766        ('lpDisplayName',LPWSTR),
767        ('dwDesiredAccess',DWORD),
768        ('dwServiceType',DWORD),
769        ('dwStartType',DWORD),
770        ('dwErrorControl',DWORD),
771        ('lpBinaryPathName',WSTR),
772        ('lpLoadOrderGroup',LPWSTR),
773        ('lpdwTagId',LPDWORD),
774        ('lpDependencies',LPBYTE),
775        ('dwDependSize',DWORD),
776        ('lpServiceStartName',LPWSTR),
777        ('lpPassword',LPBYTE),
778        ('dwPwSize',DWORD),
779    )
780
781class RCreateServiceWResponse(NDRCALL):
782    structure = (
783        ('lpdwTagId',LPWSTR),
784        ('lpServiceHandle',SC_RPC_HANDLE),
785        ('ErrorCode', DWORD),
786    )
787
788class REnumDependentServicesW(NDRCALL):
789    opnum = 13
790    structure = (
791        ('hService',SC_RPC_HANDLE),
792        ('dwServiceState',DWORD),
793        ('cbBufSize',DWORD),
794    )
795
796class REnumDependentServicesWResponse(NDRCALL):
797    structure = (
798        ('lpServices',NDRUniConformantArray),
799        ('pcbBytesNeeded',BOUNDED_DWORD_256K),
800        ('lpServicesReturned',BOUNDED_DWORD_256K),
801        ('ErrorCode', DWORD),
802    )
803
804class REnumServicesStatusW(NDRCALL):
805    opnum = 14
806    structure = (
807        ('hSCManager',SC_RPC_HANDLE),
808        ('dwServiceType',DWORD),
809        ('dwServiceState',DWORD),
810        ('cbBufSize',DWORD),
811        ('lpResumeIndex',LPBOUNDED_DWORD_256K),
812    )
813
814class REnumServicesStatusWResponse(NDRCALL):
815    structure = (
816        ('lpBuffer',NDRUniConformantArray),
817        ('pcbBytesNeeded',BOUNDED_DWORD_256K),
818        ('lpServicesReturned',BOUNDED_DWORD_256K),
819        ('lpResumeIndex',LPBOUNDED_DWORD_256K),
820        ('ErrorCode', DWORD),
821    )
822
823class ROpenSCManagerW(NDRCALL):
824    opnum = 15
825    structure = (
826        ('lpMachineName',SVCCTL_HANDLEW),
827        ('lpDatabaseName',LPWSTR),
828        ('dwDesiredAccess',DWORD),
829    )
830
831class ROpenSCManagerWResponse(NDRCALL):
832    structure = (
833        ('lpScHandle',SC_RPC_HANDLE),
834        ('ErrorCode', DWORD),
835    )
836
837class ROpenServiceW(NDRCALL):
838    opnum = 16
839    structure = (
840        ('hSCManager',SC_RPC_HANDLE),
841        ('lpServiceName',WSTR),
842        ('dwDesiredAccess',DWORD),
843    )
844
845class ROpenServiceWResponse(NDRCALL):
846    structure = (
847        ('lpServiceHandle',SC_RPC_HANDLE),
848        ('ErrorCode', DWORD),
849    )
850
851class RQueryServiceConfigW(NDRCALL):
852    opnum = 17
853    structure = (
854        ('hService',SC_RPC_HANDLE),
855        ('cbBufSize',DWORD),
856    )
857
858class RQueryServiceConfigWResponse(NDRCALL):
859    structure = (
860        ('lpServiceConfig',QUERY_SERVICE_CONFIGW),
861        ('pcbBytesNeeded',BOUNDED_DWORD_8K),
862        ('ErrorCode', DWORD),
863    )
864
865class RQueryServiceLockStatusW(NDRCALL):
866    opnum = 18
867    structure = (
868        ('hSCManager',SC_RPC_HANDLE),
869        ('cbBufSize',DWORD),
870    )
871
872class RQueryServiceLockStatusWResponse(NDRCALL):
873    structure = (
874        ('lpLockStatus',QUERY_SERVICE_LOCK_STATUSW),
875        ('pcbBytesNeeded',BOUNDED_DWORD_4K),
876        ('ErrorCode', DWORD),
877    )
878
879class RStartServiceW(NDRCALL):
880    opnum = 19
881    structure = (
882        ('hService',SC_RPC_HANDLE),
883        ('argc',DWORD),
884        ('argv',UNIQUE_STRING_PTRSW),
885    )
886
887class RStartServiceWResponse(NDRCALL):
888    structure = (
889        ('ErrorCode', DWORD),
890    )
891
892class RGetServiceDisplayNameW(NDRCALL):
893    opnum = 20
894    structure = (
895        ('hSCManager',SC_RPC_HANDLE),
896        ('lpServiceName',WSTR),
897        ('lpcchBuffer',DWORD),
898    )
899
900class RGetServiceDisplayNameWResponse(NDRCALL):
901    structure = (
902        ('lpDisplayName',WSTR),
903        ('lpcchBuffer',DWORD),
904        ('ErrorCode', DWORD),
905    )
906
907class RGetServiceKeyNameW(NDRCALL):
908    opnum = 21
909    structure = (
910        ('hSCManager',SC_RPC_HANDLE),
911        ('lpDisplayName',WSTR),
912        ('lpcchBuffer',DWORD),
913    )
914
915class RGetServiceKeyNameWResponse(NDRCALL):
916    structure = (
917        ('lpDisplayName',WSTR),
918        ('lpcchBuffer',DWORD),
919        ('ErrorCode', DWORD),
920    )
921
922class REnumServiceGroupW(NDRCALL):
923    opnum = 35
924    structure = (
925        ('hSCManager',SC_RPC_HANDLE),
926        ('dwServiceType',DWORD),
927        ('dwServiceState',DWORD),
928        ('cbBufSize',DWORD),
929        ('lpResumeIndex',LPBOUNDED_DWORD_256K),
930        ('pszGroupName',LPWSTR),
931    )
932
933class REnumServiceGroupWResponse(NDRCALL):
934    structure = (
935        ('lpBuffer',LPBYTE),
936        ('pcbBytesNeeded',BOUNDED_DWORD_256K),
937        ('lpServicesReturned',BOUNDED_DWORD_256K),
938        ('lpResumeIndex',BOUNDED_DWORD_256K),
939        ('ErrorCode', DWORD),
940    )
941
942class RChangeServiceConfig2W(NDRCALL):
943    opnum = 37
944    structure = (
945       ('hService',SC_RPC_HANDLE),
946       ('Info',SC_RPC_CONFIG_INFOW),
947    )
948
949class RChangeServiceConfig2WResponse(NDRCALL):
950    structure = (
951        ('ErrorCode', DWORD),
952    )
953
954class RQueryServiceConfig2W(NDRCALL):
955    opnum = 39
956    structure = (
957        ('hService',SC_RPC_HANDLE),
958        ('dwInfoLevel',DWORD),
959        ('cbBufSize',DWORD),
960    )
961
962class RQueryServiceConfig2WResponse(NDRCALL):
963    structure = (
964        ('lpBuffer',NDRUniConformantArray),
965        ('pcbBytesNeeded',BOUNDED_DWORD_8K),
966        ('ErrorCode', DWORD),
967    )
968
969class RQueryServiceStatusEx(NDRCALL):
970    opnum = 40
971    structure = (
972        ('hService',SC_RPC_HANDLE),
973        ('InfoLevel',DWORD),
974        ('cbBufSize',DWORD),
975    )
976
977class RQueryServiceStatusExResponse(NDRCALL):
978    structure = (
979        ('lpBuffer',NDRUniConformantArray),
980        ('pcbBytesNeeded',BOUNDED_DWORD_8K),
981        ('ErrorCode', DWORD),
982    )
983
984class REnumServicesStatusExW(NDRCALL):
985    opnum = 42
986    structure = (
987        ('hSCManager',SC_RPC_HANDLE),
988        ('InfoLevel',DWORD),
989        ('dwServiceType',DWORD),
990        ('dwServiceState',DWORD),
991        ('cbBufSize',DWORD),
992        ('lpResumeIndex',LPBOUNDED_DWORD_256K),
993        ('pszGroupName',LPWSTR),
994    )
995
996class REnumServicesStatusExWResponse(NDRCALL):
997    structure = (
998        ('lpBuffer',NDRUniConformantArray),
999        ('pcbBytesNeeded',BOUNDED_DWORD_256K),
1000        ('lpServicesReturned',BOUNDED_DWORD_256K),
1001        ('lpResumeIndex',BOUNDED_DWORD_256K),
1002        ('ErrorCode', DWORD),
1003    )
1004
1005class RCreateServiceWOW64W(NDRCALL):
1006    opnum = 45
1007    structure = (
1008        ('hSCManager',SC_RPC_HANDLE),
1009        ('lpServiceName',WSTR),
1010        ('lpDisplayName',LPWSTR),
1011        ('dwDesiredAccess',DWORD),
1012        ('dwServiceType',DWORD),
1013        ('dwStartType',DWORD),
1014        ('dwErrorControl',DWORD),
1015        ('lpBinaryPathName',WSTR),
1016        ('lpLoadOrderGroup',LPWSTR),
1017        ('lpdwTagId',LPDWORD),
1018        ('lpDependencies',LPBYTE),
1019        ('dwDependSize',DWORD),
1020        ('lpServiceStartName',LPWSTR),
1021        ('lpPassword',LPBYTE),
1022        ('dwPwSize',DWORD),
1023    )
1024
1025class RCreateServiceWOW64WResponse(NDRCALL):
1026    structure = (
1027        ('lpdwTagId',LPWSTR),
1028        ('lpServiceHandle',SC_RPC_HANDLE),
1029        ('ErrorCode', DWORD),
1030    )
1031
1032# Still not working, for some reason something changes in the way the pointer inside SC_RPC_NOTIFY_PARAMS is marshalled here
1033class RNotifyServiceStatusChange(NDRCALL):
1034    opnum = 47
1035    structure = (
1036        ('hService',SC_RPC_HANDLE),
1037        ('NotifyParams',SC_RPC_NOTIFY_PARAMS),
1038        ('pClientProcessGuid',GUID),
1039    )
1040
1041class RNotifyServiceStatusChangeResponse(NDRCALL):
1042    structure = (
1043        ('pSCMProcessGuid',GUID),
1044        ('pfCreateRemoteQueue',PBOOL),
1045        ('phNotify',SC_NOTIFY_RPC_HANDLE),
1046        ('ErrorCode', DWORD),
1047    )
1048
1049# Not working, until I don't fix the previous one
1050class RGetNotifyResults(NDRCALL):
1051    opnum = 48
1052    structure = (
1053        ('hNotify',SC_NOTIFY_RPC_HANDLE),
1054    )
1055
1056class RGetNotifyResultsResponse(NDRCALL):
1057    structure = (
1058        ('ppNotifyParams',PSC_RPC_NOTIFY_PARAMS_LIST),
1059        ('ErrorCode', DWORD),
1060    )
1061
1062# Not working, until I don't fix the previous ones
1063class RCloseNotifyHandle(NDRCALL):
1064    opnum = 49
1065    structure = (
1066        ('phNotify',SC_NOTIFY_RPC_HANDLE),
1067    )
1068
1069class RCloseNotifyHandleResponse(NDRCALL):
1070    structure = (
1071        ('phNotify',SC_NOTIFY_RPC_HANDLE),
1072        ('pfApcFired',PBOOL),
1073        ('ErrorCode', DWORD),
1074    )
1075
1076# Not working, returning bad_stub_data
1077class RControlServiceExW(NDRCALL):
1078    opnum = 51
1079    structure = (
1080        ('hService',SC_RPC_HANDLE),
1081        ('dwControl',DWORD),
1082        ('dwInfoLevel',DWORD),
1083        ('pControlInParams',SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW),
1084    )
1085
1086class RControlServiceExWResponse(NDRCALL):
1087    structure = (
1088        ('pControlOutParams',SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS),
1089        ('ErrorCode', DWORD),
1090    )
1091
1092class RQueryServiceConfigEx(NDRCALL):
1093    opnum = 56
1094    structure = (
1095        ('hService',SC_RPC_HANDLE),
1096        ('dwInfoLevel',DWORD),
1097    )
1098
1099class RQueryServiceConfigExResponse(NDRCALL):
1100    structure = (
1101        ('pInfo',SC_RPC_CONFIG_INFOW),
1102        ('ErrorCode', DWORD),
1103    )
1104
1105################################################################################
1106# OPNUMs and their corresponding structures
1107################################################################################
1108OPNUMS = {
1109 0 : (RCloseServiceHandle, RCloseServiceHandleResponse),
1110 1 : (RControlService, RControlServiceResponse),
1111 2 : (RDeleteService, RDeleteServiceResponse),
1112 3 : (RLockServiceDatabase, RLockServiceDatabaseResponse),
1113 4 : (RQueryServiceObjectSecurity, RQueryServiceObjectSecurityResponse),
1114 5 : (RSetServiceObjectSecurity, RSetServiceObjectSecurityResponse),
1115 6 : (RQueryServiceStatus, RQueryServiceStatusResponse),
1116 7 : (RSetServiceStatus, RSetServiceStatusResponse),
1117 8 : (RUnlockServiceDatabase, RUnlockServiceDatabaseResponse),
1118 9 : (RNotifyBootConfigStatus, RNotifyBootConfigStatusResponse),
111911 : (RChangeServiceConfigW, RChangeServiceConfigWResponse),
112012 : (RCreateServiceW, RCreateServiceWResponse),
112113 : (REnumDependentServicesW, REnumDependentServicesWResponse),
112214 : (REnumServicesStatusW, REnumServicesStatusWResponse),
112315 : (ROpenSCManagerW, ROpenSCManagerWResponse),
112416 : (ROpenServiceW, ROpenServiceWResponse),
112517 : (RQueryServiceConfigW, RQueryServiceConfigWResponse),
112618 : (RQueryServiceLockStatusW, RQueryServiceLockStatusWResponse),
112719 : (RStartServiceW, RStartServiceWResponse),
112820 : (RGetServiceDisplayNameW, RGetServiceDisplayNameWResponse),
112921 : (RGetServiceKeyNameW, RGetServiceKeyNameWResponse),
113035 : (REnumServiceGroupW, REnumServiceGroupWResponse),
113137 : (RChangeServiceConfig2W, RChangeServiceConfig2WResponse),
113239 : (RQueryServiceConfig2W, RQueryServiceConfig2WResponse),
113340 : (RQueryServiceStatusEx, RQueryServiceStatusExResponse),
113442 : (REnumServicesStatusExW, REnumServicesStatusExWResponse),
113545 : (RCreateServiceWOW64W, RCreateServiceWOW64WResponse),
113647 : (RNotifyServiceStatusChange, RNotifyServiceStatusChangeResponse),
113748 : (RGetNotifyResults, RGetNotifyResultsResponse),
113849 : (RCloseNotifyHandle, RCloseNotifyHandleResponse),
113951 : (RControlServiceExW, RControlServiceExWResponse),
114056 : (RQueryServiceConfigEx, RQueryServiceConfigExResponse),
1141}
1142
1143################################################################################
1144# HELPER FUNCTIONS
1145################################################################################
1146def checkNullString(string):
1147    if string == NULL:
1148        return string
1149
1150    if string[-1:] != '\x00':
1151        return string + '\x00'
1152    else:
1153        return string
1154
1155def hRCloseServiceHandle(dce, hSCObject):
1156    request = RCloseServiceHandle()
1157    request['hSCObject'] = hSCObject
1158    return dce.request(request)
1159
1160def hRControlService(dce, hService, dwControl):
1161    request = RControlService()
1162    request['hService'] = hService
1163    request['dwControl'] = dwControl
1164    return dce.request(request)
1165
1166def hRDeleteService(dce, hService):
1167    request = RDeleteService()
1168    request ['hService'] = hService
1169    return dce.request(request)
1170
1171def hRLockServiceDatabase(dce, hSCManager):
1172    request = RLockServiceDatabase()
1173    request['hSCManager'] = hSCManager
1174    return dce.request(request)
1175
1176def hRQueryServiceObjectSecurity(dce, hService, dwSecurityInformation, cbBufSize ):
1177    request = RQueryServiceObjectSecurity()
1178    request['hService'] = hService
1179    request['dwSecurityInformation'] = dwSecurityInformation
1180    request['cbBufSize'] = cbBufSize
1181    return dce.request(request)
1182
1183def hRSetServiceObjectSecurity(dce, hService, dwSecurityInformation, lpSecurityDescriptor, cbBufSize ):
1184    request = RSetServiceObjectSecurity()
1185    request['hService'] = hService
1186    request['dwSecurityInformation'] = dwSecurityInformation
1187    request['cbBufSize'] = cbBufSize
1188    return dce.request(request)
1189
1190def hRQueryServiceStatus(dce, hService ):
1191    request = RQueryServiceStatus()
1192    request['hService'] = hService
1193    return dce.request(request)
1194
1195def hRSetServiceStatus(dce, hServiceStatus, lpServiceStatus ):
1196    request = RSetServiceStatus()
1197    request['hServiceStatus'] = hServiceStatus
1198    request['lpServiceStatus'] = lpServiceStatus
1199    return dce.request(request)
1200
1201def hRUnlockServiceDatabase(dce, Lock ):
1202    request = RUnlockServiceDatabase()
1203    request['Lock'] = Lock
1204    return dce.request(request)
1205
1206def hRNotifyBootConfigStatus(dce, lpMachineName, BootAcceptable ):
1207    request = RNotifyBootConfigStatus()
1208    request['lpMachineName'] = lpMachineName
1209    request['BootAcceptable'] = BootAcceptable
1210    return dce.request(request)
1211
1212def hRChangeServiceConfigW(dce, hService, dwServiceType=SERVICE_NO_CHANGE, dwStartType=SERVICE_NO_CHANGE, dwErrorControl=SERVICE_NO_CHANGE, lpBinaryPathName=NULL, lpLoadOrderGroup=NULL, lpdwTagId=NULL, lpDependencies=NULL, dwDependSize=0, lpServiceStartName=NULL, lpPassword=NULL, dwPwSize=0, lpDisplayName=NULL):
1213    changeServiceConfig = RChangeServiceConfigW()
1214    changeServiceConfig['hService'] = hService
1215    changeServiceConfig['dwServiceType'] = dwServiceType
1216    changeServiceConfig['dwStartType'] = dwStartType
1217    changeServiceConfig['dwErrorControl'] = dwErrorControl
1218    changeServiceConfig['lpBinaryPathName'] = checkNullString(lpBinaryPathName)
1219    changeServiceConfig['lpLoadOrderGroup'] = checkNullString(lpLoadOrderGroup)
1220    changeServiceConfig['lpdwTagId'] = lpdwTagId
1221    changeServiceConfig['lpDependencies'] = lpDependencies
1222    # Strings MUST be NULL terminated for lpDependencies
1223    changeServiceConfig['dwDependSize'] = dwDependSize
1224    changeServiceConfig['lpServiceStartName'] = checkNullString(lpServiceStartName)
1225    changeServiceConfig['lpPassword'] = lpPassword
1226    changeServiceConfig['dwPwSize'] = dwPwSize
1227    changeServiceConfig['lpDisplayName'] = checkNullString(lpDisplayName)
1228    return dce.request(changeServiceConfig)
1229
1230def hRCreateServiceW(dce, hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess=SERVICE_ALL_ACCESS, dwServiceType=SERVICE_WIN32_OWN_PROCESS, dwStartType=SERVICE_AUTO_START, dwErrorControl=SERVICE_ERROR_IGNORE, lpBinaryPathName=NULL, lpLoadOrderGroup=NULL, lpdwTagId=NULL, lpDependencies=NULL, dwDependSize=0, lpServiceStartName=NULL, lpPassword=NULL, dwPwSize=0):
1231    createService = RCreateServiceW()
1232    createService['hSCManager'] = hSCManager
1233    createService['lpServiceName'] = checkNullString(lpServiceName)
1234    createService['lpDisplayName'] = checkNullString(lpDisplayName)
1235    createService['dwDesiredAccess'] = dwDesiredAccess
1236    createService['dwServiceType'] = dwServiceType
1237    createService['dwStartType'] = dwStartType
1238    createService['dwErrorControl'] = dwErrorControl
1239    createService['lpBinaryPathName'] = checkNullString(lpBinaryPathName)
1240    createService['lpLoadOrderGroup'] = checkNullString(lpLoadOrderGroup)
1241    createService['lpdwTagId'] = lpdwTagId
1242    # Strings MUST be NULL terminated for lpDependencies
1243    createService['lpDependencies'] = lpDependencies
1244    createService['dwDependSize'] = dwDependSize
1245    createService['lpServiceStartName'] = checkNullString(lpServiceStartName)
1246    createService['lpPassword'] = lpPassword
1247    createService['dwPwSize'] = dwPwSize
1248    return dce.request(createService)
1249
1250def hREnumDependentServicesW(dce, hService, dwServiceState, cbBufSize ):
1251    enumDependentServices = REnumDependentServicesW()
1252    enumDependentServices['hService'] = hService
1253    enumDependentServices['dwServiceState'] = dwServiceState
1254    enumDependentServices['cbBufSize'] = cbBufSize
1255    return dce.request(enumDependentServices)
1256
1257def hREnumServicesStatusW(dce, hSCManager, dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_KERNEL_DRIVER|SERVICE_FILE_SYSTEM_DRIVER|SERVICE_WIN32_SHARE_PROCESS|SERVICE_INTERACTIVE_PROCESS, dwServiceState=SERVICE_STATE_ALL):
1258    class ENUM_SERVICE_STATUSW2(NDRSTRUCT):
1259        # This is a little trick, since the original structure is slightly different
1260        # but instead of parsing the LPBYTE buffer at hand, we just do it with the aid
1261        # of the NDR library, although the pointers are swapped from the original specification.
1262        # Why is this? Well.. since we're getting an LPBYTE back, it's just a copy of the remote's memory
1263        # where the pointers are actually POINTING to the data.
1264        # Sadly, the pointers are not aligned based on the services records, so we gotta do this
1265        # It should be easier in C of course.
1266        class STR(NDRPOINTER):
1267            referent = (
1268                ('Data', WIDESTR),
1269            )
1270        structure = (
1271            ('lpServiceName',STR),
1272            ('lpDisplayName',STR),
1273            ('ServiceStatus',SERVICE_STATUS),
1274        )
1275
1276    enumServicesStatus = REnumServicesStatusW()
1277    enumServicesStatus['hSCManager'] = hSCManager
1278    enumServicesStatus['dwServiceType'] = dwServiceType
1279    enumServicesStatus['dwServiceState'] = dwServiceState
1280    enumServicesStatus['cbBufSize'] = 0
1281    enumServicesStatus['lpResumeIndex'] = NULL
1282
1283    try:
1284        resp = dce.request(enumServicesStatus)
1285    except DCERPCSessionError, e:
1286        if e.get_error_code() == system_errors.ERROR_MORE_DATA:
1287            resp = e.get_packet()
1288            enumServicesStatus['cbBufSize'] = resp['pcbBytesNeeded']
1289            resp = dce.request(enumServicesStatus)
1290        else:
1291            raise
1292
1293    # Now we're supposed to have all services returned. Now we gotta parse them
1294
1295    enumArray = NDRUniConformantArray()
1296    enumArray.item = ENUM_SERVICE_STATUSW2
1297
1298    enumArray.setArraySize(resp['lpServicesReturned'])
1299
1300    data = ''.join(resp['lpBuffer'])
1301    enumArray.fromString(data)
1302    data = data[4:]
1303    # Since the pointers here are pointing to the actual data, we have to reparse
1304    # the referents
1305    for record in enumArray['Data']:
1306        offset =  record.fields['lpDisplayName'].fields['ReferentID']-4
1307        name = WIDESTR(data[offset:])
1308        record['lpDisplayName'] = name['Data']
1309        offset =  record.fields['lpServiceName'].fields['ReferentID']-4
1310        name = WIDESTR(data[offset:])
1311        record['lpServiceName'] = name['Data']
1312
1313    return enumArray['Data']
1314
1315def hROpenSCManagerW(dce, lpMachineName='DUMMY\x00', lpDatabaseName='ServicesActive\x00', dwDesiredAccess=SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SC_MANAGER_ENUMERATE_SERVICE):
1316    openSCManager = ROpenSCManagerW()
1317    openSCManager['lpMachineName'] = checkNullString(lpMachineName)
1318    openSCManager['lpDatabaseName'] = checkNullString(lpDatabaseName)
1319    openSCManager['dwDesiredAccess'] = dwDesiredAccess
1320    return dce.request(openSCManager)
1321
1322def hROpenServiceW(dce, hSCManager, lpServiceName, dwDesiredAccess= SERVICE_ALL_ACCESS):
1323    openService = ROpenServiceW()
1324    openService['hSCManager'] = hSCManager
1325    openService['lpServiceName'] = checkNullString(lpServiceName)
1326    openService['dwDesiredAccess'] = dwDesiredAccess
1327    return dce.request(openService)
1328
1329def hRQueryServiceConfigW(dce, hService):
1330    queryService = RQueryServiceConfigW()
1331    queryService['hService'] = hService
1332    queryService['cbBufSize'] = 0
1333    try:
1334        resp = dce.request(queryService)
1335    except DCERPCSessionError, e:
1336        if e.get_error_code() == system_errors.ERROR_INSUFFICIENT_BUFFER:
1337            resp = e.get_packet()
1338            queryService['cbBufSize'] = resp['pcbBytesNeeded']
1339            resp = dce.request(queryService)
1340        else:
1341            raise
1342
1343    return resp
1344
1345def hRQueryServiceLockStatusW(dce, hSCManager, cbBufSize ):
1346    queryServiceLock = RQueryServiceLockStatusW()
1347    queryServiceLock['hSCManager'] = hSCManager
1348    queryServiceLock['cbBufSize'] = cbBufSize
1349    return dce.request(queryServiceLock)
1350
1351def hRStartServiceW(dce, hService, argc=0, argv=NULL ):
1352    startService = RStartServiceW()
1353    startService['hService'] = hService
1354    startService['argc'] = argc
1355    if argc == 0:
1356        startService['argv'] = NULL
1357    else:
1358        for item in argv:
1359            itemn = LPWSTR()
1360            itemn['Data'] = checkNullString(item)
1361            startService['argv'].append(itemn)
1362    return dce.request(startService)
1363
1364def hRGetServiceDisplayNameW(dce, hSCManager, lpServiceName, lpcchBuffer ):
1365    getServiceDisplay = RGetServiceDisplayNameW()
1366    getServiceDisplay['hSCManager'] = hSCManager
1367    getServiceDisplay['lpServiceName'] = checkNullString(lpServiceName)
1368    getServiceDisplay['lpcchBuffer'] = lpcchBuffer
1369    return dce.request(getServiceDisplay)
1370
1371def hRGetServiceKeyNameW(dce, hSCManager, lpDisplayName, lpcchBuffer ):
1372    getServiceKeyName = RGetServiceKeyNameW()
1373    getServiceKeyName['hSCManager'] = hSCManager
1374    getServiceKeyName['lpDisplayName'] = checkNullString(lpDisplayName)
1375    getServiceKeyName['lpcchBuffer'] = lpcchBuffer
1376    return dce.request(getServiceKeyName)
1377
1378def hREnumServiceGroupW(dce, hSCManager, dwServiceType, dwServiceState, cbBufSize, lpResumeIndex = NULL, pszGroupName = NULL ):
1379    enumServiceGroup = REnumServiceGroupW()
1380    enumServiceGroup['hSCManager'] = hSCManager
1381    enumServiceGroup['dwServiceType'] = dwServiceType
1382    enumServiceGroup['dwServiceState'] = dwServiceState
1383    enumServiceGroup['cbBufSize'] = cbBufSize
1384    enumServiceGroup['lpResumeIndex'] = lpResumeIndex
1385    enumServiceGroup['pszGroupName'] = pszGroupName
1386    return dce.request(enumServiceGroup)
1387
1388