1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009-2014, Mario Vilas
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10#     * Redistributions of source code must retain the above copyright notice,
11#       this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above copyright
13#       notice,this list of conditions and the following disclaimer in the
14#       documentation and/or other materials provided with the distribution.
15#     * Neither the name of the copyright holder nor the names of its
16#       contributors may be used to endorse or promote products derived from
17#       this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31"""
32Wrapper for advapi32.dll in ctypes.
33"""
34
35__revision__ = "$Id$"
36
37from winappdbg.win32.defines import *
38from winappdbg.win32.kernel32 import *
39
40# XXX TODO
41# + add transacted registry operations
42
43#==============================================================================
44# This is used later on to calculate the list of exported symbols.
45_all = None
46_all = set(vars().keys())
47#==============================================================================
48
49#--- Constants ----------------------------------------------------------------
50
51# Privilege constants
52SE_ASSIGNPRIMARYTOKEN_NAME      = "SeAssignPrimaryTokenPrivilege"
53SE_AUDIT_NAME                   = "SeAuditPrivilege"
54SE_BACKUP_NAME                  = "SeBackupPrivilege"
55SE_CHANGE_NOTIFY_NAME           = "SeChangeNotifyPrivilege"
56SE_CREATE_GLOBAL_NAME           = "SeCreateGlobalPrivilege"
57SE_CREATE_PAGEFILE_NAME         = "SeCreatePagefilePrivilege"
58SE_CREATE_PERMANENT_NAME        = "SeCreatePermanentPrivilege"
59SE_CREATE_SYMBOLIC_LINK_NAME    = "SeCreateSymbolicLinkPrivilege"
60SE_CREATE_TOKEN_NAME            = "SeCreateTokenPrivilege"
61SE_DEBUG_NAME                   = "SeDebugPrivilege"
62SE_ENABLE_DELEGATION_NAME       = "SeEnableDelegationPrivilege"
63SE_IMPERSONATE_NAME             = "SeImpersonatePrivilege"
64SE_INC_BASE_PRIORITY_NAME       = "SeIncreaseBasePriorityPrivilege"
65SE_INCREASE_QUOTA_NAME          = "SeIncreaseQuotaPrivilege"
66SE_INC_WORKING_SET_NAME         = "SeIncreaseWorkingSetPrivilege"
67SE_LOAD_DRIVER_NAME             = "SeLoadDriverPrivilege"
68SE_LOCK_MEMORY_NAME             = "SeLockMemoryPrivilege"
69SE_MACHINE_ACCOUNT_NAME         = "SeMachineAccountPrivilege"
70SE_MANAGE_VOLUME_NAME           = "SeManageVolumePrivilege"
71SE_PROF_SINGLE_PROCESS_NAME     = "SeProfileSingleProcessPrivilege"
72SE_RELABEL_NAME                 = "SeRelabelPrivilege"
73SE_REMOTE_SHUTDOWN_NAME         = "SeRemoteShutdownPrivilege"
74SE_RESTORE_NAME                 = "SeRestorePrivilege"
75SE_SECURITY_NAME                = "SeSecurityPrivilege"
76SE_SHUTDOWN_NAME                = "SeShutdownPrivilege"
77SE_SYNC_AGENT_NAME              = "SeSyncAgentPrivilege"
78SE_SYSTEM_ENVIRONMENT_NAME      = "SeSystemEnvironmentPrivilege"
79SE_SYSTEM_PROFILE_NAME          = "SeSystemProfilePrivilege"
80SE_SYSTEMTIME_NAME              = "SeSystemtimePrivilege"
81SE_TAKE_OWNERSHIP_NAME          = "SeTakeOwnershipPrivilege"
82SE_TCB_NAME                     = "SeTcbPrivilege"
83SE_TIME_ZONE_NAME               = "SeTimeZonePrivilege"
84SE_TRUSTED_CREDMAN_ACCESS_NAME  = "SeTrustedCredManAccessPrivilege"
85SE_UNDOCK_NAME                  = "SeUndockPrivilege"
86SE_UNSOLICITED_INPUT_NAME       = "SeUnsolicitedInputPrivilege"
87
88SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
89SE_PRIVILEGE_ENABLED            = 0x00000002
90SE_PRIVILEGE_REMOVED            = 0x00000004
91SE_PRIVILEGE_USED_FOR_ACCESS    = 0x80000000
92
93TOKEN_ADJUST_PRIVILEGES         = 0x00000020
94
95LOGON_WITH_PROFILE              = 0x00000001
96LOGON_NETCREDENTIALS_ONLY       = 0x00000002
97
98# Token access rights
99TOKEN_ASSIGN_PRIMARY    = 0x0001
100TOKEN_DUPLICATE         = 0x0002
101TOKEN_IMPERSONATE       = 0x0004
102TOKEN_QUERY             = 0x0008
103TOKEN_QUERY_SOURCE      = 0x0010
104TOKEN_ADJUST_PRIVILEGES = 0x0020
105TOKEN_ADJUST_GROUPS     = 0x0040
106TOKEN_ADJUST_DEFAULT    = 0x0080
107TOKEN_ADJUST_SESSIONID  = 0x0100
108TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
109TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
110        TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
111        TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
112        TOKEN_ADJUST_SESSIONID)
113
114# Predefined HKEY values
115HKEY_CLASSES_ROOT       = 0x80000000
116HKEY_CURRENT_USER       = 0x80000001
117HKEY_LOCAL_MACHINE      = 0x80000002
118HKEY_USERS              = 0x80000003
119HKEY_PERFORMANCE_DATA   = 0x80000004
120HKEY_CURRENT_CONFIG     = 0x80000005
121
122# Registry access rights
123KEY_ALL_ACCESS          = 0xF003F
124KEY_CREATE_LINK         = 0x0020
125KEY_CREATE_SUB_KEY      = 0x0004
126KEY_ENUMERATE_SUB_KEYS  = 0x0008
127KEY_EXECUTE             = 0x20019
128KEY_NOTIFY              = 0x0010
129KEY_QUERY_VALUE         = 0x0001
130KEY_READ                = 0x20019
131KEY_SET_VALUE           = 0x0002
132KEY_WOW64_32KEY         = 0x0200
133KEY_WOW64_64KEY         = 0x0100
134KEY_WRITE               = 0x20006
135
136# Registry value types
137REG_NONE                        = 0
138REG_SZ                          = 1
139REG_EXPAND_SZ                   = 2
140REG_BINARY                      = 3
141REG_DWORD                       = 4
142REG_DWORD_LITTLE_ENDIAN         = REG_DWORD
143REG_DWORD_BIG_ENDIAN            = 5
144REG_LINK                        = 6
145REG_MULTI_SZ                    = 7
146REG_RESOURCE_LIST               = 8
147REG_FULL_RESOURCE_DESCRIPTOR    = 9
148REG_RESOURCE_REQUIREMENTS_LIST  = 10
149REG_QWORD                       = 11
150REG_QWORD_LITTLE_ENDIAN         = REG_QWORD
151
152#--- TOKEN_PRIVILEGE structure ------------------------------------------------
153
154# typedef struct _LUID {
155#   DWORD LowPart;
156#   LONG HighPart;
157# } LUID,
158#  *PLUID;
159class LUID(Structure):
160    _fields_ = [
161        ("LowPart",     DWORD),
162        ("HighPart",    LONG),
163    ]
164
165PLUID = POINTER(LUID)
166
167# typedef struct _LUID_AND_ATTRIBUTES {
168#   LUID Luid;
169#   DWORD Attributes;
170# } LUID_AND_ATTRIBUTES,
171#  *PLUID_AND_ATTRIBUTES;
172class LUID_AND_ATTRIBUTES(Structure):
173    _fields_ = [
174        ("Luid",        LUID),
175        ("Attributes",  DWORD),
176    ]
177
178# typedef struct _TOKEN_PRIVILEGES {
179#   DWORD PrivilegeCount;
180#   LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
181# } TOKEN_PRIVILEGES,
182#  *PTOKEN_PRIVILEGES;
183class TOKEN_PRIVILEGES(Structure):
184    _fields_ = [
185        ("PrivilegeCount",  DWORD),
186##        ("Privileges",      LUID_AND_ATTRIBUTES * ANYSIZE_ARRAY),
187        ("Privileges",      LUID_AND_ATTRIBUTES),
188    ]
189    # See comments on AdjustTokenPrivileges about this structure
190
191PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
192
193#--- GetTokenInformation enums and structures ---------------------------------
194
195# typedef enum _TOKEN_INFORMATION_CLASS {
196#   TokenUser                              = 1,
197#   TokenGroups,
198#   TokenPrivileges,
199#   TokenOwner,
200#   TokenPrimaryGroup,
201#   TokenDefaultDacl,
202#   TokenSource,
203#   TokenType,
204#   TokenImpersonationLevel,
205#   TokenStatistics,
206#   TokenRestrictedSids,
207#   TokenSessionId,
208#   TokenGroupsAndPrivileges,
209#   TokenSessionReference,
210#   TokenSandBoxInert,
211#   TokenAuditPolicy,
212#   TokenOrigin,
213#   TokenElevationType,
214#   TokenLinkedToken,
215#   TokenElevation,
216#   TokenHasRestrictions,
217#   TokenAccessInformation,
218#   TokenVirtualizationAllowed,
219#   TokenVirtualizationEnabled,
220#   TokenIntegrityLevel,
221#   TokenUIAccess,
222#   TokenMandatoryPolicy,
223#   TokenLogonSid,
224#   TokenIsAppContainer,
225#   TokenCapabilities,
226#   TokenAppContainerSid,
227#   TokenAppContainerNumber,
228#   TokenUserClaimAttributes,
229#   TokenDeviceClaimAttributes,
230#   TokenRestrictedUserClaimAttributes,
231#   TokenRestrictedDeviceClaimAttributes,
232#   TokenDeviceGroups,
233#   TokenRestrictedDeviceGroups,
234#   TokenSecurityAttributes,
235#   TokenIsRestricted,
236#   MaxTokenInfoClass
237# } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;
238
239TOKEN_INFORMATION_CLASS = ctypes.c_int
240
241TokenUser                               = 1
242TokenGroups                             = 2
243TokenPrivileges                         = 3
244TokenOwner                              = 4
245TokenPrimaryGroup                       = 5
246TokenDefaultDacl                        = 6
247TokenSource                             = 7
248TokenType                               = 8
249TokenImpersonationLevel                 = 9
250TokenStatistics                         = 10
251TokenRestrictedSids                     = 11
252TokenSessionId                          = 12
253TokenGroupsAndPrivileges                = 13
254TokenSessionReference                   = 14
255TokenSandBoxInert                       = 15
256TokenAuditPolicy                        = 16
257TokenOrigin                             = 17
258TokenElevationType                      = 18
259TokenLinkedToken                        = 19
260TokenElevation                          = 20
261TokenHasRestrictions                    = 21
262TokenAccessInformation                  = 22
263TokenVirtualizationAllowed              = 23
264TokenVirtualizationEnabled              = 24
265TokenIntegrityLevel                     = 25
266TokenUIAccess                           = 26
267TokenMandatoryPolicy                    = 27
268TokenLogonSid                           = 28
269TokenIsAppContainer                     = 29
270TokenCapabilities                       = 30
271TokenAppContainerSid                    = 31
272TokenAppContainerNumber                 = 32
273TokenUserClaimAttributes                = 33
274TokenDeviceClaimAttributes              = 34
275TokenRestrictedUserClaimAttributes      = 35
276TokenRestrictedDeviceClaimAttributes    = 36
277TokenDeviceGroups                       = 37
278TokenRestrictedDeviceGroups             = 38
279TokenSecurityAttributes                 = 39
280TokenIsRestricted                       = 40
281MaxTokenInfoClass                       = 41
282
283# typedef enum tagTOKEN_TYPE {
284#   TokenPrimary         = 1,
285#   TokenImpersonation
286# } TOKEN_TYPE, *PTOKEN_TYPE;
287
288TOKEN_TYPE = ctypes.c_int
289PTOKEN_TYPE = POINTER(TOKEN_TYPE)
290
291TokenPrimary        = 1
292TokenImpersonation  = 2
293
294# typedef enum  {
295#   TokenElevationTypeDefault   = 1,
296#   TokenElevationTypeFull,
297#   TokenElevationTypeLimited
298# } TOKEN_ELEVATION_TYPE , *PTOKEN_ELEVATION_TYPE;
299
300TokenElevationTypeDefault   = 1
301TokenElevationTypeFull      = 2
302TokenElevationTypeLimited   = 3
303
304TOKEN_ELEVATION_TYPE = ctypes.c_int
305PTOKEN_ELEVATION_TYPE = POINTER(TOKEN_ELEVATION_TYPE)
306
307# typedef enum _SECURITY_IMPERSONATION_LEVEL {
308#   SecurityAnonymous,
309#   SecurityIdentification,
310#   SecurityImpersonation,
311#   SecurityDelegation
312# } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
313
314SecurityAnonymous       = 0
315SecurityIdentification  = 1
316SecurityImpersonation   = 2
317SecurityDelegation      = 3
318
319SECURITY_IMPERSONATION_LEVEL = ctypes.c_int
320PSECURITY_IMPERSONATION_LEVEL = POINTER(SECURITY_IMPERSONATION_LEVEL)
321
322# typedef struct _SID_AND_ATTRIBUTES {
323#   PSID  Sid;
324#   DWORD Attributes;
325# } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;
326class SID_AND_ATTRIBUTES(Structure):
327    _fields_ = [
328        ("Sid",         PSID),
329        ("Attributes",  DWORD),
330    ]
331PSID_AND_ATTRIBUTES = POINTER(SID_AND_ATTRIBUTES)
332
333# typedef struct _TOKEN_USER {
334#   SID_AND_ATTRIBUTES User;
335# } TOKEN_USER, *PTOKEN_USER;
336class TOKEN_USER(Structure):
337    _fields_ = [
338        ("User", SID_AND_ATTRIBUTES),
339    ]
340PTOKEN_USER = POINTER(TOKEN_USER)
341
342# typedef struct _TOKEN_MANDATORY_LABEL {
343#   SID_AND_ATTRIBUTES Label;
344# } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
345class TOKEN_MANDATORY_LABEL(Structure):
346    _fields_ = [
347        ("Label", SID_AND_ATTRIBUTES),
348    ]
349PTOKEN_MANDATORY_LABEL = POINTER(TOKEN_MANDATORY_LABEL)
350
351# typedef struct _TOKEN_OWNER {
352#   PSID Owner;
353# } TOKEN_OWNER, *PTOKEN_OWNER;
354class TOKEN_OWNER(Structure):
355    _fields_ = [
356        ("Owner", PSID),
357    ]
358PTOKEN_OWNER = POINTER(TOKEN_OWNER)
359
360# typedef struct _TOKEN_PRIMARY_GROUP {
361#   PSID PrimaryGroup;
362# } TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP;
363class TOKEN_PRIMARY_GROUP(Structure):
364    _fields_ = [
365        ("PrimaryGroup", PSID),
366    ]
367PTOKEN_PRIMARY_GROUP = POINTER(TOKEN_PRIMARY_GROUP)
368
369# typedef struct _TOKEN_APPCONTAINER_INFORMATION {
370#   	PSID TokenAppContainer;
371# } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
372class TOKEN_APPCONTAINER_INFORMATION(Structure):
373    _fields_ = [
374        ("TokenAppContainer", PSID),
375    ]
376PTOKEN_APPCONTAINER_INFORMATION = POINTER(TOKEN_APPCONTAINER_INFORMATION)
377
378# typedef struct _TOKEN_ORIGIN {
379#   LUID OriginatingLogonSession;
380# } TOKEN_ORIGIN, *PTOKEN_ORIGIN;
381class TOKEN_ORIGIN(Structure):
382    _fields_ = [
383        ("OriginatingLogonSession", LUID),
384    ]
385PTOKEN_ORIGIN = POINTER(TOKEN_ORIGIN)
386
387# typedef struct _TOKEN_LINKED_TOKEN {
388#   HANDLE LinkedToken;
389# } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
390class TOKEN_LINKED_TOKEN(Structure):
391    _fields_ = [
392        ("LinkedToken", HANDLE),
393    ]
394PTOKEN_LINKED_TOKEN = POINTER(TOKEN_LINKED_TOKEN)
395
396# typedef struct _TOKEN_STATISTICS {
397#   LUID                         TokenId;
398#   LUID                         AuthenticationId;
399#   LARGE_INTEGER                ExpirationTime;
400#   TOKEN_TYPE                   TokenType;
401#   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
402#   DWORD                        DynamicCharged;
403#   DWORD                        DynamicAvailable;
404#   DWORD                        GroupCount;
405#   DWORD                        PrivilegeCount;
406#   LUID                         ModifiedId;
407# } TOKEN_STATISTICS, *PTOKEN_STATISTICS;
408class TOKEN_STATISTICS(Structure):
409    _fields_ = [
410        ("TokenId",             LUID),
411        ("AuthenticationId",    LUID),
412        ("ExpirationTime",      LONGLONG),  # LARGE_INTEGER
413        ("TokenType",           TOKEN_TYPE),
414        ("ImpersonationLevel",  SECURITY_IMPERSONATION_LEVEL),
415        ("DynamicCharged",      DWORD),
416        ("DynamicAvailable",    DWORD),
417        ("GroupCount",          DWORD),
418        ("PrivilegeCount",      DWORD),
419        ("ModifiedId",          LUID),
420    ]
421PTOKEN_STATISTICS = POINTER(TOKEN_STATISTICS)
422
423#--- SID_NAME_USE enum --------------------------------------------------------
424
425# typedef enum _SID_NAME_USE {
426#   SidTypeUser             = 1,
427#   SidTypeGroup,
428#   SidTypeDomain,
429#   SidTypeAlias,
430#   SidTypeWellKnownGroup,
431#   SidTypeDeletedAccount,
432#   SidTypeInvalid,
433#   SidTypeUnknown,
434#   SidTypeComputer,
435#   SidTypeLabel
436# } SID_NAME_USE, *PSID_NAME_USE;
437
438SidTypeUser             = 1
439SidTypeGroup            = 2
440SidTypeDomain           = 3
441SidTypeAlias            = 4
442SidTypeWellKnownGroup   = 5
443SidTypeDeletedAccount   = 6
444SidTypeInvalid          = 7
445SidTypeUnknown          = 8
446SidTypeComputer         = 9
447SidTypeLabel            = 10
448
449#--- WAITCHAIN_NODE_INFO structure and types ----------------------------------
450
451WCT_MAX_NODE_COUNT       = 16
452WCT_OBJNAME_LENGTH       = 128
453WCT_ASYNC_OPEN_FLAG      = 1
454WCTP_OPEN_ALL_FLAGS      = WCT_ASYNC_OPEN_FLAG
455WCT_OUT_OF_PROC_FLAG     = 1
456WCT_OUT_OF_PROC_COM_FLAG = 2
457WCT_OUT_OF_PROC_CS_FLAG  = 4
458WCTP_GETINFO_ALL_FLAGS   = WCT_OUT_OF_PROC_FLAG | WCT_OUT_OF_PROC_COM_FLAG | WCT_OUT_OF_PROC_CS_FLAG
459
460HWCT = LPVOID
461
462# typedef enum _WCT_OBJECT_TYPE
463# {
464#     WctCriticalSectionType = 1,
465#     WctSendMessageType,
466#     WctMutexType,
467#     WctAlpcType,
468#     WctComType,
469#     WctThreadWaitType,
470#     WctProcessWaitType,
471#     WctThreadType,
472#     WctComActivationType,
473#     WctUnknownType,
474#     WctMaxType
475# } WCT_OBJECT_TYPE;
476
477WCT_OBJECT_TYPE         = DWORD
478
479WctCriticalSectionType  = 1
480WctSendMessageType      = 2
481WctMutexType            = 3
482WctAlpcType             = 4
483WctComType              = 5
484WctThreadWaitType       = 6
485WctProcessWaitType      = 7
486WctThreadType           = 8
487WctComActivationType    = 9
488WctUnknownType          = 10
489WctMaxType              = 11
490
491# typedef enum _WCT_OBJECT_STATUS
492# {
493#     WctStatusNoAccess = 1,            // ACCESS_DENIED for this object
494#     WctStatusRunning,                 // Thread status
495#     WctStatusBlocked,                 // Thread status
496#     WctStatusPidOnly,                 // Thread status
497#     WctStatusPidOnlyRpcss,            // Thread status
498#     WctStatusOwned,                   // Dispatcher object status
499#     WctStatusNotOwned,                // Dispatcher object status
500#     WctStatusAbandoned,               // Dispatcher object status
501#     WctStatusUnknown,                 // All objects
502#     WctStatusError,                   // All objects
503#     WctStatusMax
504# } WCT_OBJECT_STATUS;
505
506WCT_OBJECT_STATUS       = DWORD
507
508WctStatusNoAccess       = 1             # ACCESS_DENIED for this object
509WctStatusRunning        = 2             # Thread status
510WctStatusBlocked        = 3             # Thread status
511WctStatusPidOnly        = 4             # Thread status
512WctStatusPidOnlyRpcss   = 5             # Thread status
513WctStatusOwned          = 6             # Dispatcher object status
514WctStatusNotOwned       = 7             # Dispatcher object status
515WctStatusAbandoned      = 8             # Dispatcher object status
516WctStatusUnknown        = 9             # All objects
517WctStatusError          = 10            # All objects
518WctStatusMax            = 11
519
520# typedef struct _WAITCHAIN_NODE_INFO {
521#   WCT_OBJECT_TYPE   ObjectType;
522#   WCT_OBJECT_STATUS ObjectStatus;
523#   union {
524#     struct {
525#       WCHAR ObjectName[WCT_OBJNAME_LENGTH];
526#       LARGE_INTEGER Timeout;
527#       BOOL Alertable;
528#     } LockObject;
529#     struct {
530#       DWORD ProcessId;
531#       DWORD ThreadId;
532#       DWORD WaitTime;
533#       DWORD ContextSwitches;
534#     } ThreadObject;
535#   } ;
536# }WAITCHAIN_NODE_INFO, *PWAITCHAIN_NODE_INFO;
537
538class _WAITCHAIN_NODE_INFO_STRUCT_1(Structure):
539    _fields_ = [
540        ("ObjectName",      WCHAR * WCT_OBJNAME_LENGTH),
541        ("Timeout",         LONGLONG), # LARGE_INTEGER
542        ("Alertable",       BOOL),
543    ]
544
545class _WAITCHAIN_NODE_INFO_STRUCT_2(Structure):
546    _fields_ = [
547        ("ProcessId",       DWORD),
548        ("ThreadId",        DWORD),
549        ("WaitTime",        DWORD),
550        ("ContextSwitches", DWORD),
551    ]
552
553class _WAITCHAIN_NODE_INFO_UNION(Union):
554    _fields_ = [
555        ("LockObject",      _WAITCHAIN_NODE_INFO_STRUCT_1),
556        ("ThreadObject",    _WAITCHAIN_NODE_INFO_STRUCT_2),
557    ]
558
559class WAITCHAIN_NODE_INFO(Structure):
560    _fields_ = [
561        ("ObjectType",      WCT_OBJECT_TYPE),
562        ("ObjectStatus",    WCT_OBJECT_STATUS),
563        ("u",               _WAITCHAIN_NODE_INFO_UNION),
564    ]
565
566PWAITCHAIN_NODE_INFO = POINTER(WAITCHAIN_NODE_INFO)
567
568class WaitChainNodeInfo (object):
569    """
570    Represents a node in the wait chain.
571
572    It's a wrapper on the L{WAITCHAIN_NODE_INFO} structure.
573
574    The following members are defined only
575    if the node is of L{WctThreadType} type:
576     - C{ProcessId}
577     - C{ThreadId}
578     - C{WaitTime}
579     - C{ContextSwitches}
580
581    @see: L{GetThreadWaitChain}
582
583    @type ObjectName: unicode
584    @ivar ObjectName: Object name. May be an empty string.
585
586    @type ObjectType: int
587    @ivar ObjectType: Object type.
588        Should be one of the following values:
589         - L{WctCriticalSectionType}
590         - L{WctSendMessageType}
591         - L{WctMutexType}
592         - L{WctAlpcType}
593         - L{WctComType}
594         - L{WctThreadWaitType}
595         - L{WctProcessWaitType}
596         - L{WctThreadType}
597         - L{WctComActivationType}
598         - L{WctUnknownType}
599
600    @type ObjectStatus: int
601    @ivar ObjectStatus: Wait status.
602        Should be one of the following values:
603         - L{WctStatusNoAccess} I{(ACCESS_DENIED for this object)}
604         - L{WctStatusRunning} I{(Thread status)}
605         - L{WctStatusBlocked} I{(Thread status)}
606         - L{WctStatusPidOnly} I{(Thread status)}
607         - L{WctStatusPidOnlyRpcss} I{(Thread status)}
608         - L{WctStatusOwned} I{(Dispatcher object status)}
609         - L{WctStatusNotOwned} I{(Dispatcher object status)}
610         - L{WctStatusAbandoned} I{(Dispatcher object status)}
611         - L{WctStatusUnknown} I{(All objects)}
612         - L{WctStatusError} I{(All objects)}
613
614    @type ProcessId: int
615    @ivar ProcessId: Process global ID.
616
617    @type ThreadId: int
618    @ivar ThreadId: Thread global ID.
619
620    @type WaitTime: int
621    @ivar WaitTime: Wait time.
622
623    @type ContextSwitches: int
624    @ivar ContextSwitches: Number of context switches.
625    """
626
627    #@type Timeout: int
628    #@ivar Timeout: Currently not documented in MSDN.
629    #
630    #@type Alertable: bool
631    #@ivar Alertable: Currently not documented in MSDN.
632
633    # TODO: __repr__
634
635    def __init__(self, aStructure):
636        self.ObjectType = aStructure.ObjectType
637        self.ObjectStatus = aStructure.ObjectStatus
638        if self.ObjectType == WctThreadType:
639            self.ProcessId = aStructure.u.ThreadObject.ProcessId
640            self.ThreadId = aStructure.u.ThreadObject.ThreadId
641            self.WaitTime = aStructure.u.ThreadObject.WaitTime
642            self.ContextSwitches = aStructure.u.ThreadObject.ContextSwitches
643            self.ObjectName = u''
644        else:
645            self.ObjectName = aStructure.u.LockObject.ObjectName.value
646            #self.Timeout = aStructure.u.LockObject.Timeout
647            #self.Alertable = bool(aStructure.u.LockObject.Alertable)
648
649class ThreadWaitChainSessionHandle (Handle):
650    """
651    Thread wait chain session handle.
652
653    Returned by L{OpenThreadWaitChainSession}.
654
655    @see: L{Handle}
656    """
657
658    def __init__(self, aHandle = None):
659        """
660        @type  aHandle: int
661        @param aHandle: Win32 handle value.
662        """
663        super(ThreadWaitChainSessionHandle, self).__init__(aHandle,
664                                                           bOwnership = True)
665
666    def _close(self):
667        if self.value is None:
668            raise ValueError("Handle was already closed!")
669        CloseThreadWaitChainSession(self.value)
670
671    def dup(self):
672        raise NotImplementedError()
673
674    def wait(self, dwMilliseconds = None):
675        raise NotImplementedError()
676
677    @property
678    def inherit(self):
679        return False
680
681    @property
682    def protectFromClose(self):
683        return False
684
685#--- Privilege dropping -------------------------------------------------------
686
687SAFER_LEVEL_HANDLE = HANDLE
688
689SAFER_SCOPEID_MACHINE = 1
690SAFER_SCOPEID_USER    = 2
691
692SAFER_LEVEL_OPEN = 1
693
694SAFER_LEVELID_DISALLOWED   = 0x00000
695SAFER_LEVELID_UNTRUSTED    = 0x01000
696SAFER_LEVELID_CONSTRAINED  = 0x10000
697SAFER_LEVELID_NORMALUSER   = 0x20000
698SAFER_LEVELID_FULLYTRUSTED = 0x40000
699
700SAFER_POLICY_INFO_CLASS = DWORD
701SaferPolicyLevelList = 1
702SaferPolicyEnableTransparentEnforcement = 2
703SaferPolicyDefaultLevel = 3
704SaferPolicyEvaluateUserScope = 4
705SaferPolicyScopeFlags = 5
706
707SAFER_TOKEN_NULL_IF_EQUAL = 1
708SAFER_TOKEN_COMPARE_ONLY  = 2
709SAFER_TOKEN_MAKE_INERT    = 4
710SAFER_TOKEN_WANT_FLAGS    = 8
711SAFER_TOKEN_MASK          = 15
712
713#--- Service Control Manager types, constants and structures ------------------
714
715SC_HANDLE = HANDLE
716
717SERVICES_ACTIVE_DATABASEW = u"ServicesActive"
718SERVICES_FAILED_DATABASEW = u"ServicesFailed"
719
720SERVICES_ACTIVE_DATABASEA = "ServicesActive"
721SERVICES_FAILED_DATABASEA = "ServicesFailed"
722
723SC_GROUP_IDENTIFIERW = u'+'
724SC_GROUP_IDENTIFIERA = '+'
725
726SERVICE_NO_CHANGE = 0xffffffff
727
728# enum SC_STATUS_TYPE
729SC_STATUS_TYPE         = ctypes.c_int
730SC_STATUS_PROCESS_INFO = 0
731
732# enum SC_ENUM_TYPE
733SC_ENUM_TYPE         = ctypes.c_int
734SC_ENUM_PROCESS_INFO = 0
735
736# Access rights
737# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
738
739SERVICE_ALL_ACCESS           = 0xF01FF
740SERVICE_QUERY_CONFIG         = 0x0001
741SERVICE_CHANGE_CONFIG        = 0x0002
742SERVICE_QUERY_STATUS         = 0x0004
743SERVICE_ENUMERATE_DEPENDENTS = 0x0008
744SERVICE_START                = 0x0010
745SERVICE_STOP                 = 0x0020
746SERVICE_PAUSE_CONTINUE       = 0x0040
747SERVICE_INTERROGATE          = 0x0080
748SERVICE_USER_DEFINED_CONTROL = 0x0100
749
750SC_MANAGER_ALL_ACCESS           = 0xF003F
751SC_MANAGER_CONNECT              = 0x0001
752SC_MANAGER_CREATE_SERVICE       = 0x0002
753SC_MANAGER_ENUMERATE_SERVICE    = 0x0004
754SC_MANAGER_LOCK                 = 0x0008
755SC_MANAGER_QUERY_LOCK_STATUS    = 0x0010
756SC_MANAGER_MODIFY_BOOT_CONFIG   = 0x0020
757
758# CreateService() service start type
759SERVICE_BOOT_START   = 0x00000000
760SERVICE_SYSTEM_START = 0x00000001
761SERVICE_AUTO_START   = 0x00000002
762SERVICE_DEMAND_START = 0x00000003
763SERVICE_DISABLED     = 0x00000004
764
765# CreateService() error control flags
766SERVICE_ERROR_IGNORE    = 0x00000000
767SERVICE_ERROR_NORMAL    = 0x00000001
768SERVICE_ERROR_SEVERE    = 0x00000002
769SERVICE_ERROR_CRITICAL  = 0x00000003
770
771# EnumServicesStatusEx() service state filters
772SERVICE_ACTIVE    = 1
773SERVICE_INACTIVE  = 2
774SERVICE_STATE_ALL = 3
775
776# SERVICE_STATUS_PROCESS.dwServiceType
777SERVICE_KERNEL_DRIVER       = 0x00000001
778SERVICE_FILE_SYSTEM_DRIVER  = 0x00000002
779SERVICE_ADAPTER             = 0x00000004
780SERVICE_RECOGNIZER_DRIVER   = 0x00000008
781SERVICE_WIN32_OWN_PROCESS   = 0x00000010
782SERVICE_WIN32_SHARE_PROCESS = 0x00000020
783SERVICE_INTERACTIVE_PROCESS = 0x00000100
784
785# EnumServicesStatusEx() service type filters (in addition to actual types)
786SERVICE_DRIVER = 0x0000000B # SERVICE_KERNEL_DRIVER and SERVICE_FILE_SYSTEM_DRIVER
787SERVICE_WIN32  = 0x00000030 # SERVICE_WIN32_OWN_PROCESS and SERVICE_WIN32_SHARE_PROCESS
788
789# SERVICE_STATUS_PROCESS.dwCurrentState
790SERVICE_STOPPED             = 0x00000001
791SERVICE_START_PENDING       = 0x00000002
792SERVICE_STOP_PENDING        = 0x00000003
793SERVICE_RUNNING             = 0x00000004
794SERVICE_CONTINUE_PENDING    = 0x00000005
795SERVICE_PAUSE_PENDING       = 0x00000006
796SERVICE_PAUSED              = 0x00000007
797
798# SERVICE_STATUS_PROCESS.dwControlsAccepted
799SERVICE_ACCEPT_STOP                  = 0x00000001
800SERVICE_ACCEPT_PAUSE_CONTINUE        = 0x00000002
801SERVICE_ACCEPT_SHUTDOWN              = 0x00000004
802SERVICE_ACCEPT_PARAMCHANGE           = 0x00000008
803SERVICE_ACCEPT_NETBINDCHANGE         = 0x00000010
804SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
805SERVICE_ACCEPT_POWEREVENT            = 0x00000040
806SERVICE_ACCEPT_SESSIONCHANGE         = 0x00000080
807SERVICE_ACCEPT_PRESHUTDOWN           = 0x00000100
808
809# SERVICE_STATUS_PROCESS.dwServiceFlags
810SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x00000001
811
812# Service control flags
813SERVICE_CONTROL_STOP                  = 0x00000001
814SERVICE_CONTROL_PAUSE                 = 0x00000002
815SERVICE_CONTROL_CONTINUE              = 0x00000003
816SERVICE_CONTROL_INTERROGATE           = 0x00000004
817SERVICE_CONTROL_SHUTDOWN              = 0x00000005
818SERVICE_CONTROL_PARAMCHANGE           = 0x00000006
819SERVICE_CONTROL_NETBINDADD            = 0x00000007
820SERVICE_CONTROL_NETBINDREMOVE         = 0x00000008
821SERVICE_CONTROL_NETBINDENABLE         = 0x00000009
822SERVICE_CONTROL_NETBINDDISABLE        = 0x0000000A
823SERVICE_CONTROL_DEVICEEVENT           = 0x0000000B
824SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
825SERVICE_CONTROL_POWEREVENT            = 0x0000000D
826SERVICE_CONTROL_SESSIONCHANGE         = 0x0000000E
827
828# Service control accepted bitmasks
829SERVICE_ACCEPT_STOP                  = 0x00000001
830SERVICE_ACCEPT_PAUSE_CONTINUE        = 0x00000002
831SERVICE_ACCEPT_SHUTDOWN              = 0x00000004
832SERVICE_ACCEPT_PARAMCHANGE           = 0x00000008
833SERVICE_ACCEPT_NETBINDCHANGE         = 0x00000010
834SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
835SERVICE_ACCEPT_POWEREVENT            = 0x00000040
836SERVICE_ACCEPT_SESSIONCHANGE         = 0x00000080
837SERVICE_ACCEPT_PRESHUTDOWN           = 0x00000100
838SERVICE_ACCEPT_TIMECHANGE            = 0x00000200
839SERVICE_ACCEPT_TRIGGEREVENT          = 0x00000400
840SERVICE_ACCEPT_USERMODEREBOOT        = 0x00000800
841
842# enum SC_ACTION_TYPE
843SC_ACTION_NONE        = 0
844SC_ACTION_RESTART     = 1
845SC_ACTION_REBOOT      = 2
846SC_ACTION_RUN_COMMAND = 3
847
848# QueryServiceConfig2
849SERVICE_CONFIG_DESCRIPTION     = 1
850SERVICE_CONFIG_FAILURE_ACTIONS = 2
851
852# typedef struct _SERVICE_STATUS {
853#   DWORD dwServiceType;
854#   DWORD dwCurrentState;
855#   DWORD dwControlsAccepted;
856#   DWORD dwWin32ExitCode;
857#   DWORD dwServiceSpecificExitCode;
858#   DWORD dwCheckPoint;
859#   DWORD dwWaitHint;
860# } SERVICE_STATUS, *LPSERVICE_STATUS;
861class SERVICE_STATUS(Structure):
862    _fields_ = [
863        ("dwServiceType",               DWORD),
864        ("dwCurrentState",              DWORD),
865        ("dwControlsAccepted",          DWORD),
866        ("dwWin32ExitCode",             DWORD),
867        ("dwServiceSpecificExitCode",   DWORD),
868        ("dwCheckPoint",                DWORD),
869        ("dwWaitHint",                  DWORD),
870    ]
871LPSERVICE_STATUS = POINTER(SERVICE_STATUS)
872
873# typedef struct _SERVICE_STATUS_PROCESS {
874#   DWORD dwServiceType;
875#   DWORD dwCurrentState;
876#   DWORD dwControlsAccepted;
877#   DWORD dwWin32ExitCode;
878#   DWORD dwServiceSpecificExitCode;
879#   DWORD dwCheckPoint;
880#   DWORD dwWaitHint;
881#   DWORD dwProcessId;
882#   DWORD dwServiceFlags;
883# } SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
884class SERVICE_STATUS_PROCESS(Structure):
885    _fields_ = SERVICE_STATUS._fields_ + [
886        ("dwProcessId",                 DWORD),
887        ("dwServiceFlags",              DWORD),
888    ]
889LPSERVICE_STATUS_PROCESS = POINTER(SERVICE_STATUS_PROCESS)
890
891# typedef struct _ENUM_SERVICE_STATUS {
892#   LPTSTR         lpServiceName;
893#   LPTSTR         lpDisplayName;
894#   SERVICE_STATUS ServiceStatus;
895# } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;
896class ENUM_SERVICE_STATUSA(Structure):
897    _fields_ = [
898        ("lpServiceName", LPSTR),
899        ("lpDisplayName", LPSTR),
900        ("ServiceStatus", SERVICE_STATUS),
901    ]
902class ENUM_SERVICE_STATUSW(Structure):
903    _fields_ = [
904        ("lpServiceName", LPWSTR),
905        ("lpDisplayName", LPWSTR),
906        ("ServiceStatus", SERVICE_STATUS),
907    ]
908LPENUM_SERVICE_STATUSA = POINTER(ENUM_SERVICE_STATUSA)
909LPENUM_SERVICE_STATUSW = POINTER(ENUM_SERVICE_STATUSW)
910
911# typedef struct _ENUM_SERVICE_STATUS_PROCESS {
912#   LPTSTR                 lpServiceName;
913#   LPTSTR                 lpDisplayName;
914#   SERVICE_STATUS_PROCESS ServiceStatusProcess;
915# } ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS;
916class ENUM_SERVICE_STATUS_PROCESSA(Structure):
917    _fields_ = [
918        ("lpServiceName",        LPSTR),
919        ("lpDisplayName",        LPSTR),
920        ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
921    ]
922class ENUM_SERVICE_STATUS_PROCESSW(Structure):
923    _fields_ = [
924        ("lpServiceName",        LPWSTR),
925        ("lpDisplayName",        LPWSTR),
926        ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
927    ]
928LPENUM_SERVICE_STATUS_PROCESSA = POINTER(ENUM_SERVICE_STATUS_PROCESSA)
929LPENUM_SERVICE_STATUS_PROCESSW = POINTER(ENUM_SERVICE_STATUS_PROCESSW)
930
931class ServiceStatus(object):
932    """
933    Wrapper for the L{SERVICE_STATUS} structure.
934    """
935
936    def __init__(self, raw):
937        """
938        @type  raw: L{SERVICE_STATUS}
939        @param raw: Raw structure for this service status data.
940        """
941        self.ServiceType             = raw.dwServiceType
942        self.CurrentState            = raw.dwCurrentState
943        self.ControlsAccepted        = raw.dwControlsAccepted
944        self.Win32ExitCode           = raw.dwWin32ExitCode
945        self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
946        self.CheckPoint              = raw.dwCheckPoint
947        self.WaitHint                = raw.dwWaitHint
948
949class ServiceStatusProcess(object):
950    """
951    Wrapper for the L{SERVICE_STATUS_PROCESS} structure.
952    """
953
954    def __init__(self, raw):
955        """
956        @type  raw: L{SERVICE_STATUS_PROCESS}
957        @param raw: Raw structure for this service status data.
958        """
959        self.ServiceType             = raw.dwServiceType
960        self.CurrentState            = raw.dwCurrentState
961        self.ControlsAccepted        = raw.dwControlsAccepted
962        self.Win32ExitCode           = raw.dwWin32ExitCode
963        self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
964        self.CheckPoint              = raw.dwCheckPoint
965        self.WaitHint                = raw.dwWaitHint
966        self.ProcessId               = raw.dwProcessId
967        self.ServiceFlags            = raw.dwServiceFlags
968
969class ServiceStatusEntry(object):
970    """
971    Service status entry returned by L{EnumServicesStatus}.
972    """
973
974    def __init__(self, raw):
975        """
976        @type  raw: L{ENUM_SERVICE_STATUSA} or L{ENUM_SERVICE_STATUSW}
977        @param raw: Raw structure for this service status entry.
978        """
979        self.ServiceName             = raw.lpServiceName
980        self.DisplayName             = raw.lpDisplayName
981        self.ServiceType             = raw.ServiceStatus.dwServiceType
982        self.CurrentState            = raw.ServiceStatus.dwCurrentState
983        self.ControlsAccepted        = raw.ServiceStatus.dwControlsAccepted
984        self.Win32ExitCode           = raw.ServiceStatus.dwWin32ExitCode
985        self.ServiceSpecificExitCode = raw.ServiceStatus.dwServiceSpecificExitCode
986        self.CheckPoint              = raw.ServiceStatus.dwCheckPoint
987        self.WaitHint                = raw.ServiceStatus.dwWaitHint
988
989    def __str__(self):
990        output = []
991        if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
992            output.append("Interactive service")
993        else:
994            output.append("Service")
995        if self.DisplayName:
996            output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
997        else:
998            output.append("\"%s\"" % self.ServiceName)
999        if   self.CurrentState == SERVICE_CONTINUE_PENDING:
1000            output.append("is about to continue.")
1001        elif self.CurrentState == SERVICE_PAUSE_PENDING:
1002            output.append("is pausing.")
1003        elif self.CurrentState == SERVICE_PAUSED:
1004            output.append("is paused.")
1005        elif self.CurrentState == SERVICE_RUNNING:
1006            output.append("is running.")
1007        elif self.CurrentState == SERVICE_START_PENDING:
1008            output.append("is starting.")
1009        elif self.CurrentState == SERVICE_STOP_PENDING:
1010            output.append("is stopping.")
1011        elif self.CurrentState == SERVICE_STOPPED:
1012            output.append("is stopped.")
1013        return " ".join(output)
1014
1015class ServiceStatusProcessEntry(object):
1016    """
1017    Service status entry returned by L{EnumServicesStatusEx}.
1018    """
1019
1020    def __init__(self, raw):
1021        """
1022        @type  raw: L{ENUM_SERVICE_STATUS_PROCESSA} or L{ENUM_SERVICE_STATUS_PROCESSW}
1023        @param raw: Raw structure for this service status entry.
1024        """
1025        self.ServiceName             = raw.lpServiceName
1026        self.DisplayName             = raw.lpDisplayName
1027        self.ServiceType             = raw.ServiceStatusProcess.dwServiceType
1028        self.CurrentState            = raw.ServiceStatusProcess.dwCurrentState
1029        self.ControlsAccepted        = raw.ServiceStatusProcess.dwControlsAccepted
1030        self.Win32ExitCode           = raw.ServiceStatusProcess.dwWin32ExitCode
1031        self.ServiceSpecificExitCode = raw.ServiceStatusProcess.dwServiceSpecificExitCode
1032        self.CheckPoint              = raw.ServiceStatusProcess.dwCheckPoint
1033        self.WaitHint                = raw.ServiceStatusProcess.dwWaitHint
1034        self.ProcessId               = raw.ServiceStatusProcess.dwProcessId
1035        self.ServiceFlags            = raw.ServiceStatusProcess.dwServiceFlags
1036
1037    def __str__(self):
1038        output = []
1039        if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
1040            output.append("Interactive service ")
1041        else:
1042            output.append("Service ")
1043        if self.DisplayName:
1044            output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
1045        else:
1046            output.append("\"%s\"" % self.ServiceName)
1047        if   self.CurrentState == SERVICE_CONTINUE_PENDING:
1048            output.append(" is about to continue")
1049        elif self.CurrentState == SERVICE_PAUSE_PENDING:
1050            output.append(" is pausing")
1051        elif self.CurrentState == SERVICE_PAUSED:
1052            output.append(" is paused")
1053        elif self.CurrentState == SERVICE_RUNNING:
1054            output.append(" is running")
1055        elif self.CurrentState == SERVICE_START_PENDING:
1056            output.append(" is starting")
1057        elif self.CurrentState == SERVICE_STOP_PENDING:
1058            output.append(" is stopping")
1059        elif self.CurrentState == SERVICE_STOPPED:
1060            output.append(" is stopped")
1061        if self.ProcessId:
1062            output.append(" at process %d" % self.ProcessId)
1063        output.append(".")
1064        return "".join(output)
1065
1066#--- Handle wrappers ----------------------------------------------------------
1067
1068# XXX maybe add functions related to the tokens here?
1069class TokenHandle (Handle):
1070    """
1071    Access token handle.
1072
1073    @see: L{Handle}
1074    """
1075    pass
1076
1077class RegistryKeyHandle (UserModeHandle):
1078    """
1079    Registry key handle.
1080    """
1081
1082    _TYPE = HKEY
1083
1084    def _close(self):
1085        RegCloseKey(self.value)
1086
1087class SaferLevelHandle (UserModeHandle):
1088    """
1089    Safer level handle.
1090
1091    @see: U{http://msdn.microsoft.com/en-us/library/ms722425(VS.85).aspx}
1092    """
1093
1094    _TYPE = SAFER_LEVEL_HANDLE
1095
1096    def _close(self):
1097        SaferCloseLevel(self.value)
1098
1099class ServiceHandle (UserModeHandle):
1100    """
1101    Service handle.
1102
1103    @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx}
1104    """
1105
1106    _TYPE = SC_HANDLE
1107
1108    def _close(self):
1109        CloseServiceHandle(self.value)
1110
1111class ServiceControlManagerHandle (UserModeHandle):
1112    """
1113    Service Control Manager (SCM) handle.
1114
1115    @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx}
1116    """
1117
1118    _TYPE = SC_HANDLE
1119
1120    def _close(self):
1121        CloseServiceHandle(self.value)
1122
1123#--- advapi32.dll -------------------------------------------------------------
1124
1125# BOOL WINAPI GetUserName(
1126#   __out    LPTSTR lpBuffer,
1127#   __inout  LPDWORD lpnSize
1128# );
1129def GetUserNameA():
1130    _GetUserNameA = windll.advapi32.GetUserNameA
1131    _GetUserNameA.argtypes = [LPSTR, LPDWORD]
1132    _GetUserNameA.restype  = bool
1133
1134    nSize = DWORD(0)
1135    _GetUserNameA(None, byref(nSize))
1136    error = GetLastError()
1137    if error != ERROR_INSUFFICIENT_BUFFER:
1138        raise ctypes.WinError(error)
1139    lpBuffer = ctypes.create_string_buffer('', nSize.value + 1)
1140    success = _GetUserNameA(lpBuffer, byref(nSize))
1141    if not success:
1142        raise ctypes.WinError()
1143    return lpBuffer.value
1144
1145def GetUserNameW():
1146    _GetUserNameW = windll.advapi32.GetUserNameW
1147    _GetUserNameW.argtypes = [LPWSTR, LPDWORD]
1148    _GetUserNameW.restype  = bool
1149
1150    nSize = DWORD(0)
1151    _GetUserNameW(None, byref(nSize))
1152    error = GetLastError()
1153    if error != ERROR_INSUFFICIENT_BUFFER:
1154        raise ctypes.WinError(error)
1155    lpBuffer = ctypes.create_unicode_buffer(u'', nSize.value + 1)
1156    success = _GetUserNameW(lpBuffer, byref(nSize))
1157    if not success:
1158        raise ctypes.WinError()
1159    return lpBuffer.value
1160
1161GetUserName = DefaultStringType(GetUserNameA, GetUserNameW)
1162
1163# BOOL WINAPI LookupAccountName(
1164#   __in_opt   LPCTSTR lpSystemName,
1165#   __in       LPCTSTR lpAccountName,
1166#   __out_opt  PSID Sid,
1167#   __inout    LPDWORD cbSid,
1168#   __out_opt  LPTSTR ReferencedDomainName,
1169#   __inout    LPDWORD cchReferencedDomainName,
1170#   __out      PSID_NAME_USE peUse
1171# );
1172
1173# XXX TO DO
1174
1175# BOOL WINAPI LookupAccountSid(
1176#   __in_opt   LPCTSTR lpSystemName,
1177#   __in       PSID lpSid,
1178#   __out_opt  LPTSTR lpName,
1179#   __inout    LPDWORD cchName,
1180#   __out_opt  LPTSTR lpReferencedDomainName,
1181#   __inout    LPDWORD cchReferencedDomainName,
1182#   __out      PSID_NAME_USE peUse
1183# );
1184def LookupAccountSidA(lpSystemName, lpSid):
1185    _LookupAccountSidA = windll.advapi32.LookupAccountSidA
1186    _LookupAccountSidA.argtypes = [LPSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, LPDWORD]
1187    _LookupAccountSidA.restype  = bool
1188
1189    cchName = DWORD(0)
1190    cchReferencedDomainName = DWORD(0)
1191    peUse = DWORD(0)
1192    _LookupAccountSidA(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1193    error = GetLastError()
1194    if error != ERROR_INSUFFICIENT_BUFFER:
1195        raise ctypes.WinError(error)
1196    lpName = ctypes.create_string_buffer('', cchName + 1)
1197    lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName + 1)
1198    success = _LookupAccountSidA(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1199    if not success:
1200        raise ctypes.WinError()
1201    return lpName.value, lpReferencedDomainName.value, peUse.value
1202
1203def LookupAccountSidW(lpSystemName, lpSid):
1204    _LookupAccountSidW = windll.advapi32.LookupAccountSidA
1205    _LookupAccountSidW.argtypes = [LPSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
1206    _LookupAccountSidW.restype  = bool
1207
1208    cchName = DWORD(0)
1209    cchReferencedDomainName = DWORD(0)
1210    peUse = DWORD(0)
1211    _LookupAccountSidW(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1212    error = GetLastError()
1213    if error != ERROR_INSUFFICIENT_BUFFER:
1214        raise ctypes.WinError(error)
1215    lpName = ctypes.create_unicode_buffer(u'', cchName + 1)
1216    lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName + 1)
1217    success = _LookupAccountSidW(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1218    if not success:
1219        raise ctypes.WinError()
1220    return lpName.value, lpReferencedDomainName.value, peUse.value
1221
1222LookupAccountSid = GuessStringType(LookupAccountSidA, LookupAccountSidW)
1223
1224# BOOL ConvertSidToStringSid(
1225#   __in   PSID Sid,
1226#   __out  LPTSTR *StringSid
1227# );
1228def ConvertSidToStringSidA(Sid):
1229    _ConvertSidToStringSidA = windll.advapi32.ConvertSidToStringSidA
1230    _ConvertSidToStringSidA.argtypes = [PSID, LPSTR]
1231    _ConvertSidToStringSidA.restype  = bool
1232    _ConvertSidToStringSidA.errcheck = RaiseIfZero
1233
1234    pStringSid = LPSTR()
1235    _ConvertSidToStringSidA(Sid, byref(pStringSid))
1236    try:
1237        StringSid = pStringSid.value
1238    finally:
1239        LocalFree(pStringSid)
1240    return StringSid
1241
1242def ConvertSidToStringSidW(Sid):
1243    _ConvertSidToStringSidW = windll.advapi32.ConvertSidToStringSidW
1244    _ConvertSidToStringSidW.argtypes = [PSID, LPWSTR]
1245    _ConvertSidToStringSidW.restype  = bool
1246    _ConvertSidToStringSidW.errcheck = RaiseIfZero
1247
1248    pStringSid = LPWSTR()
1249    _ConvertSidToStringSidW(Sid, byref(pStringSid))
1250    try:
1251        StringSid = pStringSid.value
1252    finally:
1253        LocalFree(pStringSid)
1254    return StringSid
1255
1256ConvertSidToStringSid = DefaultStringType(ConvertSidToStringSidA, ConvertSidToStringSidW)
1257
1258# BOOL WINAPI ConvertStringSidToSid(
1259#   __in   LPCTSTR StringSid,
1260#   __out  PSID *Sid
1261# );
1262def ConvertStringSidToSidA(StringSid):
1263    _ConvertStringSidToSidA = windll.advapi32.ConvertStringSidToSidA
1264    _ConvertStringSidToSidA.argtypes = [LPSTR, PVOID]
1265    _ConvertStringSidToSidA.restype  = bool
1266    _ConvertStringSidToSidA.errcheck = RaiseIfZero
1267
1268    Sid = PVOID()
1269    _ConvertStringSidToSidA(StringSid, ctypes.pointer(Sid))
1270    return Sid.value
1271
1272def ConvertStringSidToSidW(StringSid):
1273    _ConvertStringSidToSidW = windll.advapi32.ConvertStringSidToSidW
1274    _ConvertStringSidToSidW.argtypes = [LPWSTR, PVOID]
1275    _ConvertStringSidToSidW.restype  = bool
1276    _ConvertStringSidToSidW.errcheck = RaiseIfZero
1277
1278    Sid = PVOID()
1279    _ConvertStringSidToSidW(StringSid, ctypes.pointer(Sid))
1280    return Sid.value
1281
1282ConvertStringSidToSid = GuessStringType(ConvertStringSidToSidA, ConvertStringSidToSidW)
1283
1284# BOOL WINAPI IsValidSid(
1285#   __in  PSID pSid
1286# );
1287def IsValidSid(pSid):
1288    _IsValidSid = windll.advapi32.IsValidSid
1289    _IsValidSid.argtypes = [PSID]
1290    _IsValidSid.restype  = bool
1291    return _IsValidSid(pSid)
1292
1293# BOOL WINAPI EqualSid(
1294#   __in  PSID pSid1,
1295#   __in  PSID pSid2
1296# );
1297def EqualSid(pSid1, pSid2):
1298    _EqualSid = windll.advapi32.EqualSid
1299    _EqualSid.argtypes = [PSID, PSID]
1300    _EqualSid.restype  = bool
1301    return _EqualSid(pSid1, pSid2)
1302
1303# DWORD WINAPI GetLengthSid(
1304#   __in  PSID pSid
1305# );
1306def GetLengthSid(pSid):
1307    _GetLengthSid = windll.advapi32.GetLengthSid
1308    _GetLengthSid.argtypes = [PSID]
1309    _GetLengthSid.restype  = DWORD
1310    return _GetLengthSid(pSid)
1311
1312# BOOL WINAPI CopySid(
1313#   __in   DWORD nDestinationSidLength,
1314#   __out  PSID pDestinationSid,
1315#   __in   PSID pSourceSid
1316# );
1317def CopySid(pSourceSid):
1318    _CopySid = windll.advapi32.CopySid
1319    _CopySid.argtypes = [DWORD, PVOID, PSID]
1320    _CopySid.restype  = bool
1321    _CopySid.errcheck = RaiseIfZero
1322
1323    nDestinationSidLength = GetLengthSid(pSourceSid)
1324    DestinationSid = ctypes.create_string_buffer('', nDestinationSidLength)
1325    pDestinationSid = ctypes.cast(ctypes.pointer(DestinationSid), PVOID)
1326    _CopySid(nDestinationSidLength, pDestinationSid, pSourceSid)
1327    return ctypes.cast(pDestinationSid, PSID)
1328
1329# PVOID WINAPI FreeSid(
1330#   __in  PSID pSid
1331# );
1332def FreeSid(pSid):
1333    _FreeSid = windll.advapi32.FreeSid
1334    _FreeSid.argtypes = [PSID]
1335    _FreeSid.restype  = PSID
1336    _FreeSid.errcheck = RaiseIfNotZero
1337    _FreeSid(pSid)
1338
1339# BOOL WINAPI OpenProcessToken(
1340#   __in   HANDLE ProcessHandle,
1341#   __in   DWORD DesiredAccess,
1342#   __out  PHANDLE TokenHandle
1343# );
1344def OpenProcessToken(ProcessHandle, DesiredAccess = TOKEN_ALL_ACCESS):
1345    _OpenProcessToken = windll.advapi32.OpenProcessToken
1346    _OpenProcessToken.argtypes = [HANDLE, DWORD, PHANDLE]
1347    _OpenProcessToken.restype  = bool
1348    _OpenProcessToken.errcheck = RaiseIfZero
1349
1350    NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1351    _OpenProcessToken(ProcessHandle, DesiredAccess, byref(NewTokenHandle))
1352    return TokenHandle(NewTokenHandle.value)
1353
1354# BOOL WINAPI OpenThreadToken(
1355#   __in   HANDLE ThreadHandle,
1356#   __in   DWORD DesiredAccess,
1357#   __in   BOOL OpenAsSelf,
1358#   __out  PHANDLE TokenHandle
1359# );
1360def OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf = True):
1361    _OpenThreadToken = windll.advapi32.OpenThreadToken
1362    _OpenThreadToken.argtypes = [HANDLE, DWORD, BOOL, PHANDLE]
1363    _OpenThreadToken.restype  = bool
1364    _OpenThreadToken.errcheck = RaiseIfZero
1365
1366    NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1367    _OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, byref(NewTokenHandle))
1368    return TokenHandle(NewTokenHandle.value)
1369
1370# BOOL WINAPI DuplicateToken(
1371#   _In_   HANDLE ExistingTokenHandle,
1372#   _In_   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1373#   _Out_  PHANDLE DuplicateTokenHandle
1374# );
1375def DuplicateToken(ExistingTokenHandle, ImpersonationLevel = SecurityImpersonation):
1376    _DuplicateToken = windll.advapi32.DuplicateToken
1377    _DuplicateToken.argtypes = [HANDLE, SECURITY_IMPERSONATION_LEVEL, PHANDLE]
1378    _DuplicateToken.restype  = bool
1379    _DuplicateToken.errcheck = RaiseIfZero
1380
1381    DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1382    _DuplicateToken(ExistingTokenHandle, ImpersonationLevel, byref(DuplicateTokenHandle))
1383    return TokenHandle(DuplicateTokenHandle.value)
1384
1385# BOOL WINAPI DuplicateTokenEx(
1386#   _In_      HANDLE hExistingToken,
1387#   _In_      DWORD dwDesiredAccess,
1388#   _In_opt_  LPSECURITY_ATTRIBUTES lpTokenAttributes,
1389#   _In_      SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1390#   _In_      TOKEN_TYPE TokenType,
1391#   _Out_     PHANDLE phNewToken
1392# );
1393def DuplicateTokenEx(hExistingToken, dwDesiredAccess = TOKEN_ALL_ACCESS, lpTokenAttributes = None, ImpersonationLevel = SecurityImpersonation, TokenType = TokenPrimary):
1394    _DuplicateTokenEx = windll.advapi32.DuplicateTokenEx
1395    _DuplicateTokenEx.argtypes = [HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE]
1396    _DuplicateTokenEx.restype  = bool
1397    _DuplicateTokenEx.errcheck = RaiseIfZero
1398
1399    DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1400    _DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, byref(DuplicateTokenHandle))
1401    return TokenHandle(DuplicateTokenHandle.value)
1402
1403# BOOL WINAPI IsTokenRestricted(
1404#   __in  HANDLE TokenHandle
1405# );
1406def IsTokenRestricted(hTokenHandle):
1407    _IsTokenRestricted = windll.advapi32.IsTokenRestricted
1408    _IsTokenRestricted.argtypes = [HANDLE]
1409    _IsTokenRestricted.restype  = bool
1410    _IsTokenRestricted.errcheck = RaiseIfNotErrorSuccess
1411
1412    SetLastError(ERROR_SUCCESS)
1413    return _IsTokenRestricted(hTokenHandle)
1414
1415# BOOL WINAPI LookupPrivilegeValue(
1416#   __in_opt  LPCTSTR lpSystemName,
1417#   __in      LPCTSTR lpName,
1418#   __out     PLUID lpLuid
1419# );
1420def LookupPrivilegeValueA(lpSystemName, lpName):
1421    _LookupPrivilegeValueA = windll.advapi32.LookupPrivilegeValueA
1422    _LookupPrivilegeValueA.argtypes = [LPSTR, LPSTR, PLUID]
1423    _LookupPrivilegeValueA.restype  = bool
1424    _LookupPrivilegeValueA.errcheck = RaiseIfZero
1425
1426    lpLuid = LUID()
1427    if not lpSystemName:
1428        lpSystemName = None
1429    _LookupPrivilegeValueA(lpSystemName, lpName, byref(lpLuid))
1430    return lpLuid
1431
1432def LookupPrivilegeValueW(lpSystemName, lpName):
1433    _LookupPrivilegeValueW = windll.advapi32.LookupPrivilegeValueW
1434    _LookupPrivilegeValueW.argtypes = [LPWSTR, LPWSTR, PLUID]
1435    _LookupPrivilegeValueW.restype  = bool
1436    _LookupPrivilegeValueW.errcheck = RaiseIfZero
1437
1438    lpLuid = LUID()
1439    if not lpSystemName:
1440        lpSystemName = None
1441    _LookupPrivilegeValueW(lpSystemName, lpName, byref(lpLuid))
1442    return lpLuid
1443
1444LookupPrivilegeValue = GuessStringType(LookupPrivilegeValueA, LookupPrivilegeValueW)
1445
1446# BOOL WINAPI LookupPrivilegeName(
1447#   __in_opt   LPCTSTR lpSystemName,
1448#   __in       PLUID lpLuid,
1449#   __out_opt  LPTSTR lpName,
1450#   __inout    LPDWORD cchName
1451# );
1452
1453def LookupPrivilegeNameA(lpSystemName, lpLuid):
1454    _LookupPrivilegeNameA = windll.advapi32.LookupPrivilegeNameA
1455    _LookupPrivilegeNameA.argtypes = [LPSTR, PLUID, LPSTR, LPDWORD]
1456    _LookupPrivilegeNameA.restype  = bool
1457    _LookupPrivilegeNameA.errcheck = RaiseIfZero
1458
1459    cchName = DWORD(0)
1460    _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1461    lpName = ctypes.create_string_buffer("", cchName.value)
1462    _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1463    return lpName.value
1464
1465def LookupPrivilegeNameW(lpSystemName, lpLuid):
1466    _LookupPrivilegeNameW = windll.advapi32.LookupPrivilegeNameW
1467    _LookupPrivilegeNameW.argtypes = [LPWSTR, PLUID, LPWSTR, LPDWORD]
1468    _LookupPrivilegeNameW.restype  = bool
1469    _LookupPrivilegeNameW.errcheck = RaiseIfZero
1470
1471    cchName = DWORD(0)
1472    _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1473    lpName = ctypes.create_unicode_buffer(u"", cchName.value)
1474    _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1475    return lpName.value
1476
1477LookupPrivilegeName = GuessStringType(LookupPrivilegeNameA, LookupPrivilegeNameW)
1478
1479# BOOL WINAPI AdjustTokenPrivileges(
1480#   __in       HANDLE TokenHandle,
1481#   __in       BOOL DisableAllPrivileges,
1482#   __in_opt   PTOKEN_PRIVILEGES NewState,
1483#   __in       DWORD BufferLength,
1484#   __out_opt  PTOKEN_PRIVILEGES PreviousState,
1485#   __out_opt  PDWORD ReturnLength
1486# );
1487def AdjustTokenPrivileges(TokenHandle, NewState = ()):
1488    _AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
1489    _AdjustTokenPrivileges.argtypes = [HANDLE, BOOL, LPVOID, DWORD, LPVOID, LPVOID]
1490    _AdjustTokenPrivileges.restype  = bool
1491    _AdjustTokenPrivileges.errcheck = RaiseIfZero
1492    #
1493    # I don't know how to allocate variable sized structures in ctypes :(
1494    # so this hack will work by using always TOKEN_PRIVILEGES of one element
1495    # and calling the API many times. This also means the PreviousState
1496    # parameter won't be supported yet as it's too much hassle. In a future
1497    # version I look forward to implementing this function correctly.
1498    #
1499    if not NewState:
1500        _AdjustTokenPrivileges(TokenHandle, TRUE, NULL, 0, NULL, NULL)
1501    else:
1502        success = True
1503        for (privilege, enabled) in NewState:
1504            if not isinstance(privilege, LUID):
1505                privilege = LookupPrivilegeValue(NULL, privilege)
1506            if enabled == True:
1507                flags = SE_PRIVILEGE_ENABLED
1508            elif enabled == False:
1509                flags = SE_PRIVILEGE_REMOVED
1510            elif enabled == None:
1511                flags = 0
1512            else:
1513                flags = enabled
1514            laa = LUID_AND_ATTRIBUTES(privilege, flags)
1515            tp  = TOKEN_PRIVILEGES(1, laa)
1516            _AdjustTokenPrivileges(TokenHandle, FALSE, byref(tp), sizeof(tp), NULL, NULL)
1517
1518# BOOL WINAPI GetTokenInformation(
1519#   __in       HANDLE TokenHandle,
1520#   __in       TOKEN_INFORMATION_CLASS TokenInformationClass,
1521#   __out_opt  LPVOID TokenInformation,
1522#   __in       DWORD TokenInformationLength,
1523#   __out      PDWORD ReturnLength
1524# );
1525def GetTokenInformation(hTokenHandle, TokenInformationClass):
1526    if TokenInformationClass <= 0 or TokenInformationClass > MaxTokenInfoClass:
1527        raise ValueError("Invalid value for TokenInformationClass (%i)" % TokenInformationClass)
1528
1529    # User SID.
1530    if TokenInformationClass == TokenUser:
1531        TokenInformation = TOKEN_USER()
1532        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1533        return TokenInformation.User.Sid.value
1534
1535    # Owner SID.
1536    if TokenInformationClass == TokenOwner:
1537        TokenInformation = TOKEN_OWNER()
1538        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1539        return TokenInformation.Owner.value
1540
1541    # Primary group SID.
1542    if TokenInformationClass == TokenOwner:
1543        TokenInformation = TOKEN_PRIMARY_GROUP()
1544        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1545        return TokenInformation.PrimaryGroup.value
1546
1547    # App container SID.
1548    if TokenInformationClass == TokenAppContainerSid:
1549        TokenInformation = TOKEN_APPCONTAINER_INFORMATION()
1550        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1551        return TokenInformation.TokenAppContainer.value
1552
1553    # Integrity level SID.
1554    if TokenInformationClass == TokenIntegrityLevel:
1555        TokenInformation = TOKEN_MANDATORY_LABEL()
1556        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1557        return TokenInformation.Label.Sid.value, TokenInformation.Label.Attributes
1558
1559    # Logon session LUID.
1560    if TokenInformationClass == TokenOrigin:
1561        TokenInformation = TOKEN_ORIGIN()
1562        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1563        return TokenInformation.OriginatingLogonSession
1564
1565    # Primary or impersonation token.
1566    if TokenInformationClass == TokenType:
1567        TokenInformation = TOKEN_TYPE(0)
1568        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1569        return TokenInformation.value
1570
1571    # Elevated token.
1572    if TokenInformationClass == TokenElevation:
1573        TokenInformation = TOKEN_ELEVATION(0)
1574        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1575        return TokenInformation.value
1576
1577    # Security impersonation level.
1578    if TokenInformationClass == TokenElevation:
1579        TokenInformation = SECURITY_IMPERSONATION_LEVEL(0)
1580        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1581        return TokenInformation.value
1582
1583    # Session ID and other DWORD values.
1584    if TokenInformationClass in (TokenSessionId, TokenAppContainerNumber):
1585        TokenInformation = DWORD(0)
1586        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1587        return TokenInformation.value
1588
1589    # Various boolean flags.
1590    if TokenInformationClass in (TokenSandBoxInert, TokenHasRestrictions, TokenUIAccess,
1591                                 TokenVirtualizationAllowed, TokenVirtualizationEnabled):
1592        TokenInformation = DWORD(0)
1593        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1594        return bool(TokenInformation.value)
1595
1596    # Linked token.
1597    if TokenInformationClass == TokenLinkedToken:
1598        TokenInformation = TOKEN_LINKED_TOKEN(0)
1599        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1600        return TokenHandle(TokenInformation.LinkedToken.value, bOwnership = True)
1601
1602    # Token statistics.
1603    if TokenInformationClass == TokenStatistics:
1604        TokenInformation = TOKEN_STATISTICS()
1605        _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1606        return TokenInformation # TODO add a class wrapper?
1607
1608    # Currently unsupported flags.
1609    raise NotImplementedError("TokenInformationClass(%i) not yet supported!" % TokenInformationClass)
1610
1611def _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation):
1612    _GetTokenInformation = windll.advapi32.GetTokenInformation
1613    _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD]
1614    _GetTokenInformation.restype  = bool
1615    _GetTokenInformation.errcheck = RaiseIfZero
1616
1617    ReturnLength = DWORD(0)
1618    TokenInformationLength = SIZEOF(TokenInformation)
1619    _GetTokenInformation(hTokenHandle, TokenInformationClass, byref(TokenInformation), TokenInformationLength, byref(ReturnLength))
1620    if ReturnLength.value != TokenInformationLength:
1621        raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER)
1622    return TokenInformation
1623
1624# BOOL WINAPI SetTokenInformation(
1625#   __in  HANDLE TokenHandle,
1626#   __in  TOKEN_INFORMATION_CLASS TokenInformationClass,
1627#   __in  LPVOID TokenInformation,
1628#   __in  DWORD TokenInformationLength
1629# );
1630
1631# XXX TODO
1632
1633# BOOL WINAPI CreateProcessWithLogonW(
1634#   __in         LPCWSTR lpUsername,
1635#   __in_opt     LPCWSTR lpDomain,
1636#   __in         LPCWSTR lpPassword,
1637#   __in         DWORD dwLogonFlags,
1638#   __in_opt     LPCWSTR lpApplicationName,
1639#   __inout_opt  LPWSTR lpCommandLine,
1640#   __in         DWORD dwCreationFlags,
1641#   __in_opt     LPVOID lpEnvironment,
1642#   __in_opt     LPCWSTR lpCurrentDirectory,
1643#   __in         LPSTARTUPINFOW lpStartupInfo,
1644#   __out        LPPROCESS_INFORMATION lpProcessInfo
1645# );
1646def CreateProcessWithLogonW(lpUsername = None, lpDomain = None, lpPassword = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1647    _CreateProcessWithLogonW = windll.advapi32.CreateProcessWithLogonW
1648    _CreateProcessWithLogonW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1649    _CreateProcessWithLogonW.restype = bool
1650    _CreateProcessWithLogonW.errcheck = RaiseIfZero
1651
1652    if not lpUsername:
1653        lpUsername          = None
1654    if not lpDomain:
1655        lpDomain            = None
1656    if not lpPassword:
1657        lpPassword          = None
1658    if not lpApplicationName:
1659        lpApplicationName   = None
1660    if not lpCommandLine:
1661        lpCommandLine       = None
1662    else:
1663        lpCommandLine       = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
1664    if not lpEnvironment:
1665        lpEnvironment       = None
1666    else:
1667        lpEnvironment       = ctypes.create_unicode_buffer(lpEnvironment)
1668    if not lpCurrentDirectory:
1669        lpCurrentDirectory  = None
1670    if not lpStartupInfo:
1671        lpStartupInfo              = STARTUPINFOW()
1672        lpStartupInfo.cb           = sizeof(STARTUPINFOW)
1673        lpStartupInfo.lpReserved   = 0
1674        lpStartupInfo.lpDesktop    = 0
1675        lpStartupInfo.lpTitle      = 0
1676        lpStartupInfo.dwFlags      = 0
1677        lpStartupInfo.cbReserved2  = 0
1678        lpStartupInfo.lpReserved2  = 0
1679    lpProcessInformation              = PROCESS_INFORMATION()
1680    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
1681    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
1682    lpProcessInformation.dwProcessId  = 0
1683    lpProcessInformation.dwThreadId   = 0
1684    _CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1685    return ProcessInformation(lpProcessInformation)
1686
1687CreateProcessWithLogonA = MakeANSIVersion(CreateProcessWithLogonW)
1688CreateProcessWithLogon = DefaultStringType(CreateProcessWithLogonA, CreateProcessWithLogonW)
1689
1690# BOOL WINAPI CreateProcessWithTokenW(
1691#   __in         HANDLE hToken,
1692#   __in         DWORD dwLogonFlags,
1693#   __in_opt     LPCWSTR lpApplicationName,
1694#   __inout_opt  LPWSTR lpCommandLine,
1695#   __in         DWORD dwCreationFlags,
1696#   __in_opt     LPVOID lpEnvironment,
1697#   __in_opt     LPCWSTR lpCurrentDirectory,
1698#   __in         LPSTARTUPINFOW lpStartupInfo,
1699#   __out        LPPROCESS_INFORMATION lpProcessInfo
1700# );
1701def CreateProcessWithTokenW(hToken = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1702    _CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW
1703    _CreateProcessWithTokenW.argtypes = [HANDLE, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1704    _CreateProcessWithTokenW.restype = bool
1705    _CreateProcessWithTokenW.errcheck = RaiseIfZero
1706
1707    if not hToken:
1708        hToken              = None
1709    if not lpApplicationName:
1710        lpApplicationName   = None
1711    if not lpCommandLine:
1712        lpCommandLine       = None
1713    else:
1714        lpCommandLine       = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
1715    if not lpEnvironment:
1716        lpEnvironment       = None
1717    else:
1718        lpEnvironment       = ctypes.create_unicode_buffer(lpEnvironment)
1719    if not lpCurrentDirectory:
1720        lpCurrentDirectory  = None
1721    if not lpStartupInfo:
1722        lpStartupInfo              = STARTUPINFOW()
1723        lpStartupInfo.cb           = sizeof(STARTUPINFOW)
1724        lpStartupInfo.lpReserved   = 0
1725        lpStartupInfo.lpDesktop    = 0
1726        lpStartupInfo.lpTitle      = 0
1727        lpStartupInfo.dwFlags      = 0
1728        lpStartupInfo.cbReserved2  = 0
1729        lpStartupInfo.lpReserved2  = 0
1730    lpProcessInformation              = PROCESS_INFORMATION()
1731    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
1732    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
1733    lpProcessInformation.dwProcessId  = 0
1734    lpProcessInformation.dwThreadId   = 0
1735    _CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1736    return ProcessInformation(lpProcessInformation)
1737
1738CreateProcessWithTokenA = MakeANSIVersion(CreateProcessWithTokenW)
1739CreateProcessWithToken = DefaultStringType(CreateProcessWithTokenA, CreateProcessWithTokenW)
1740
1741# BOOL WINAPI CreateProcessAsUser(
1742#   __in_opt     HANDLE hToken,
1743#   __in_opt     LPCTSTR lpApplicationName,
1744#   __inout_opt  LPTSTR lpCommandLine,
1745#   __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
1746#   __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
1747#   __in         BOOL bInheritHandles,
1748#   __in         DWORD dwCreationFlags,
1749#   __in_opt     LPVOID lpEnvironment,
1750#   __in_opt     LPCTSTR lpCurrentDirectory,
1751#   __in         LPSTARTUPINFO lpStartupInfo,
1752#   __out        LPPROCESS_INFORMATION lpProcessInformation
1753# );
1754def CreateProcessAsUserA(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1755    _CreateProcessAsUserA = windll.advapi32.CreateProcessAsUserA
1756    _CreateProcessAsUserA.argtypes = [HANDLE, LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION]
1757    _CreateProcessAsUserA.restype  = bool
1758    _CreateProcessAsUserA.errcheck = RaiseIfZero
1759
1760    if not lpApplicationName:
1761        lpApplicationName   = None
1762    if not lpCommandLine:
1763        lpCommandLine       = None
1764    else:
1765        lpCommandLine       = ctypes.create_string_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
1766    if not lpEnvironment:
1767        lpEnvironment       = None
1768    else:
1769        lpEnvironment       = ctypes.create_string_buffer(lpEnvironment)
1770    if not lpCurrentDirectory:
1771        lpCurrentDirectory  = None
1772    if not lpProcessAttributes:
1773        lpProcessAttributes = None
1774    else:
1775        lpProcessAttributes = byref(lpProcessAttributes)
1776    if not lpThreadAttributes:
1777        lpThreadAttributes = None
1778    else:
1779        lpThreadAttributes = byref(lpThreadAttributes)
1780    if not lpStartupInfo:
1781        lpStartupInfo              = STARTUPINFO()
1782        lpStartupInfo.cb           = sizeof(STARTUPINFO)
1783        lpStartupInfo.lpReserved   = 0
1784        lpStartupInfo.lpDesktop    = 0
1785        lpStartupInfo.lpTitle      = 0
1786        lpStartupInfo.dwFlags      = 0
1787        lpStartupInfo.cbReserved2  = 0
1788        lpStartupInfo.lpReserved2  = 0
1789    lpProcessInformation              = PROCESS_INFORMATION()
1790    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
1791    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
1792    lpProcessInformation.dwProcessId  = 0
1793    lpProcessInformation.dwThreadId   = 0
1794    _CreateProcessAsUserA(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1795    return ProcessInformation(lpProcessInformation)
1796
1797def CreateProcessAsUserW(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1798    _CreateProcessAsUserW = windll.advapi32.CreateProcessAsUserW
1799    _CreateProcessAsUserW.argtypes = [HANDLE, LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1800    _CreateProcessAsUserW.restype  = bool
1801    _CreateProcessAsUserW.errcheck = RaiseIfZero
1802
1803    if not lpApplicationName:
1804        lpApplicationName   = None
1805    if not lpCommandLine:
1806        lpCommandLine       = None
1807    else:
1808        lpCommandLine       = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
1809    if not lpEnvironment:
1810        lpEnvironment       = None
1811    else:
1812        lpEnvironment       = ctypes.create_unicode_buffer(lpEnvironment)
1813    if not lpCurrentDirectory:
1814        lpCurrentDirectory  = None
1815    if not lpProcessAttributes:
1816        lpProcessAttributes = None
1817    else:
1818        lpProcessAttributes = byref(lpProcessAttributes)
1819    if not lpThreadAttributes:
1820        lpThreadAttributes = None
1821    else:
1822        lpThreadAttributes = byref(lpThreadAttributes)
1823    if not lpStartupInfo:
1824        lpStartupInfo              = STARTUPINFO()
1825        lpStartupInfo.cb           = sizeof(STARTUPINFO)
1826        lpStartupInfo.lpReserved   = 0
1827        lpStartupInfo.lpDesktop    = 0
1828        lpStartupInfo.lpTitle      = 0
1829        lpStartupInfo.dwFlags      = 0
1830        lpStartupInfo.cbReserved2  = 0
1831        lpStartupInfo.lpReserved2  = 0
1832    lpProcessInformation              = PROCESS_INFORMATION()
1833    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
1834    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
1835    lpProcessInformation.dwProcessId  = 0
1836    lpProcessInformation.dwThreadId   = 0
1837    _CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1838    return ProcessInformation(lpProcessInformation)
1839
1840CreateProcessAsUser = GuessStringType(CreateProcessAsUserA, CreateProcessAsUserW)
1841
1842# VOID CALLBACK WaitChainCallback(
1843#     HWCT WctHandle,
1844#     DWORD_PTR Context,
1845#     DWORD CallbackStatus,
1846#     LPDWORD NodeCount,
1847#     PWAITCHAIN_NODE_INFO NodeInfoArray,
1848#     LPBOOL IsCycle
1849# );
1850PWAITCHAINCALLBACK = WINFUNCTYPE(HWCT, DWORD_PTR, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL)
1851
1852# HWCT WINAPI OpenThreadWaitChainSession(
1853#   __in      DWORD Flags,
1854#   __in_opt  PWAITCHAINCALLBACK callback
1855# );
1856def OpenThreadWaitChainSession(Flags = 0, callback = None):
1857    _OpenThreadWaitChainSession = windll.advapi32.OpenThreadWaitChainSession
1858    _OpenThreadWaitChainSession.argtypes = [DWORD, PVOID]
1859    _OpenThreadWaitChainSession.restype  = HWCT
1860    _OpenThreadWaitChainSession.errcheck = RaiseIfZero
1861
1862    if callback is not None:
1863        callback = PWAITCHAINCALLBACK(callback)
1864    aHandle = _OpenThreadWaitChainSession(Flags, callback)
1865    return ThreadWaitChainSessionHandle(aHandle)
1866
1867# BOOL WINAPI GetThreadWaitChain(
1868#   _In_      HWCT WctHandle,
1869#   _In_opt_  DWORD_PTR Context,
1870#   _In_      DWORD Flags,
1871#   _In_      DWORD ThreadId,
1872#   _Inout_   LPDWORD NodeCount,
1873#   _Out_     PWAITCHAIN_NODE_INFO NodeInfoArray,
1874#   _Out_     LPBOOL IsCycle
1875# );
1876def GetThreadWaitChain(WctHandle, Context = None, Flags = WCTP_GETINFO_ALL_FLAGS, ThreadId = -1, NodeCount = WCT_MAX_NODE_COUNT):
1877    _GetThreadWaitChain = windll.advapi32.GetThreadWaitChain
1878    _GetThreadWaitChain.argtypes = [HWCT, LPDWORD, DWORD, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL]
1879    _GetThreadWaitChain.restype  = bool
1880    _GetThreadWaitChain.errcheck = RaiseIfZero
1881
1882    dwNodeCount = DWORD(NodeCount)
1883    NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1884    IsCycle = BOOL(0)
1885    _GetThreadWaitChain(WctHandle, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1886    while dwNodeCount.value > NodeCount:
1887        NodeCount = dwNodeCount.value
1888        NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1889        _GetThreadWaitChain(WctHandle, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1890    return (
1891        [ WaitChainNodeInfo(NodeInfoArray[index]) for index in compat.xrange(dwNodeCount.value) ],
1892        bool(IsCycle.value)
1893    )
1894
1895# VOID WINAPI CloseThreadWaitChainSession(
1896#   __in  HWCT WctHandle
1897# );
1898def CloseThreadWaitChainSession(WctHandle):
1899    _CloseThreadWaitChainSession = windll.advapi32.CloseThreadWaitChainSession
1900    _CloseThreadWaitChainSession.argtypes = [HWCT]
1901    _CloseThreadWaitChainSession(WctHandle)
1902
1903# BOOL WINAPI SaferCreateLevel(
1904#   __in        DWORD dwScopeId,
1905#   __in        DWORD dwLevelId,
1906#   __in        DWORD OpenFlags,
1907#   __out       SAFER_LEVEL_HANDLE *pLevelHandle,
1908#   __reserved  LPVOID lpReserved
1909# );
1910def SaferCreateLevel(dwScopeId=SAFER_SCOPEID_USER, dwLevelId=SAFER_LEVELID_NORMALUSER, OpenFlags=0):
1911    _SaferCreateLevel = windll.advapi32.SaferCreateLevel
1912    _SaferCreateLevel.argtypes = [DWORD, DWORD, DWORD, POINTER(SAFER_LEVEL_HANDLE), LPVOID]
1913    _SaferCreateLevel.restype  = BOOL
1914    _SaferCreateLevel.errcheck = RaiseIfZero
1915
1916    hLevelHandle = SAFER_LEVEL_HANDLE(INVALID_HANDLE_VALUE)
1917    _SaferCreateLevel(dwScopeId, dwLevelId, OpenFlags, byref(hLevelHandle), None)
1918    return SaferLevelHandle(hLevelHandle.value)
1919
1920# BOOL WINAPI SaferIdentifyLevel(
1921#   __in        DWORD dwNumProperties,
1922#   __in_opt    PSAFER_CODE_PROPERTIES pCodeProperties,
1923#   __out       SAFER_LEVEL_HANDLE *pLevelHandle,
1924#   __reserved  LPVOID lpReserved
1925# );
1926
1927# XXX TODO
1928
1929# BOOL WINAPI SaferComputeTokenFromLevel(
1930#   __in         SAFER_LEVEL_HANDLE LevelHandle,
1931#   __in_opt     HANDLE InAccessToken,
1932#   __out        PHANDLE OutAccessToken,
1933#   __in         DWORD dwFlags,
1934#   __inout_opt  LPVOID lpReserved
1935# );
1936def SaferComputeTokenFromLevel(LevelHandle, InAccessToken=None, dwFlags=0):
1937    _SaferComputeTokenFromLevel = windll.advapi32.SaferComputeTokenFromLevel
1938    _SaferComputeTokenFromLevel.argtypes = [SAFER_LEVEL_HANDLE, HANDLE, PHANDLE, DWORD, LPDWORD]
1939    _SaferComputeTokenFromLevel.restype  = BOOL
1940    _SaferComputeTokenFromLevel.errcheck = RaiseIfZero
1941
1942    OutAccessToken = HANDLE(INVALID_HANDLE_VALUE)
1943    lpReserved = DWORD(0)
1944    _SaferComputeTokenFromLevel(LevelHandle, InAccessToken, byref(OutAccessToken), dwFlags, byref(lpReserved))
1945    return TokenHandle(OutAccessToken.value), lpReserved.value
1946
1947# BOOL WINAPI SaferCloseLevel(
1948#   __in  SAFER_LEVEL_HANDLE hLevelHandle
1949# );
1950def SaferCloseLevel(hLevelHandle):
1951    _SaferCloseLevel = windll.advapi32.SaferCloseLevel
1952    _SaferCloseLevel.argtypes = [SAFER_LEVEL_HANDLE]
1953    _SaferCloseLevel.restype  = BOOL
1954    _SaferCloseLevel.errcheck = RaiseIfZero
1955
1956    if hasattr(hLevelHandle, 'value'):
1957        _SaferCloseLevel(hLevelHandle.value)
1958    else:
1959        _SaferCloseLevel(hLevelHandle)
1960
1961# BOOL SaferiIsExecutableFileType(
1962#   __in  LPCWSTR szFullPath,
1963#   __in  BOOLEAN bFromShellExecute
1964# );
1965def SaferiIsExecutableFileType(szFullPath, bFromShellExecute = False):
1966    _SaferiIsExecutableFileType = windll.advapi32.SaferiIsExecutableFileType
1967    _SaferiIsExecutableFileType.argtypes = [LPWSTR, BOOLEAN]
1968    _SaferiIsExecutableFileType.restype  = BOOL
1969    _SaferiIsExecutableFileType.errcheck = RaiseIfLastError
1970
1971    SetLastError(ERROR_SUCCESS)
1972    return bool(_SaferiIsExecutableFileType(compat.unicode(szFullPath), bFromShellExecute))
1973
1974# useful alias since I'm likely to misspell it :P
1975SaferIsExecutableFileType = SaferiIsExecutableFileType
1976
1977#------------------------------------------------------------------------------
1978
1979# LONG WINAPI RegCloseKey(
1980#   __in  HKEY hKey
1981# );
1982def RegCloseKey(hKey):
1983    if hasattr(hKey, 'value'):
1984        value = hKey.value
1985    else:
1986        value = hKey
1987
1988    if value in (
1989            HKEY_CLASSES_ROOT,
1990            HKEY_CURRENT_USER,
1991            HKEY_LOCAL_MACHINE,
1992            HKEY_USERS,
1993            HKEY_PERFORMANCE_DATA,
1994            HKEY_CURRENT_CONFIG
1995        ):
1996        return
1997
1998    _RegCloseKey = windll.advapi32.RegCloseKey
1999    _RegCloseKey.argtypes = [HKEY]
2000    _RegCloseKey.restype  = LONG
2001    _RegCloseKey.errcheck = RaiseIfNotErrorSuccess
2002    _RegCloseKey(hKey)
2003
2004# LONG WINAPI RegConnectRegistry(
2005#   __in_opt  LPCTSTR lpMachineName,
2006#   __in      HKEY hKey,
2007#   __out     PHKEY phkResult
2008# );
2009def RegConnectRegistryA(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2010    _RegConnectRegistryA = windll.advapi32.RegConnectRegistryA
2011    _RegConnectRegistryA.argtypes = [LPSTR, HKEY, PHKEY]
2012    _RegConnectRegistryA.restype  = LONG
2013    _RegConnectRegistryA.errcheck = RaiseIfNotErrorSuccess
2014
2015    hkResult = HKEY(INVALID_HANDLE_VALUE)
2016    _RegConnectRegistryA(lpMachineName, hKey, byref(hkResult))
2017    return RegistryKeyHandle(hkResult.value)
2018
2019def RegConnectRegistryW(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2020    _RegConnectRegistryW = windll.advapi32.RegConnectRegistryW
2021    _RegConnectRegistryW.argtypes = [LPWSTR, HKEY, PHKEY]
2022    _RegConnectRegistryW.restype  = LONG
2023    _RegConnectRegistryW.errcheck = RaiseIfNotErrorSuccess
2024
2025    hkResult = HKEY(INVALID_HANDLE_VALUE)
2026    _RegConnectRegistryW(lpMachineName, hKey, byref(hkResult))
2027    return RegistryKeyHandle(hkResult.value)
2028
2029RegConnectRegistry = GuessStringType(RegConnectRegistryA, RegConnectRegistryW)
2030
2031# LONG WINAPI RegCreateKey(
2032#   __in      HKEY hKey,
2033#   __in_opt  LPCTSTR lpSubKey,
2034#   __out     PHKEY phkResult
2035# );
2036def RegCreateKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2037    _RegCreateKeyA = windll.advapi32.RegCreateKeyA
2038    _RegCreateKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2039    _RegCreateKeyA.restype  = LONG
2040    _RegCreateKeyA.errcheck = RaiseIfNotErrorSuccess
2041
2042    hkResult = HKEY(INVALID_HANDLE_VALUE)
2043    _RegCreateKeyA(hKey, lpSubKey, byref(hkResult))
2044    return RegistryKeyHandle(hkResult.value)
2045
2046def RegCreateKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2047    _RegCreateKeyW = windll.advapi32.RegCreateKeyW
2048    _RegCreateKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2049    _RegCreateKeyW.restype  = LONG
2050    _RegCreateKeyW.errcheck = RaiseIfNotErrorSuccess
2051
2052    hkResult = HKEY(INVALID_HANDLE_VALUE)
2053    _RegCreateKeyW(hKey, lpSubKey, byref(hkResult))
2054    return RegistryKeyHandle(hkResult.value)
2055
2056RegCreateKey = GuessStringType(RegCreateKeyA, RegCreateKeyW)
2057
2058# LONG WINAPI RegCreateKeyEx(
2059#   __in        HKEY hKey,
2060#   __in        LPCTSTR lpSubKey,
2061#   __reserved  DWORD Reserved,
2062#   __in_opt    LPTSTR lpClass,
2063#   __in        DWORD dwOptions,
2064#   __in        REGSAM samDesired,
2065#   __in_opt    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2066#   __out       PHKEY phkResult,
2067#   __out_opt   LPDWORD lpdwDisposition
2068# );
2069
2070# XXX TODO
2071
2072# LONG WINAPI RegOpenKey(
2073#   __in      HKEY hKey,
2074#   __in_opt  LPCTSTR lpSubKey,
2075#   __out     PHKEY phkResult
2076# );
2077def RegOpenKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2078    _RegOpenKeyA = windll.advapi32.RegOpenKeyA
2079    _RegOpenKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2080    _RegOpenKeyA.restype  = LONG
2081    _RegOpenKeyA.errcheck = RaiseIfNotErrorSuccess
2082
2083    hkResult = HKEY(INVALID_HANDLE_VALUE)
2084    _RegOpenKeyA(hKey, lpSubKey, byref(hkResult))
2085    return RegistryKeyHandle(hkResult.value)
2086
2087def RegOpenKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2088    _RegOpenKeyW = windll.advapi32.RegOpenKeyW
2089    _RegOpenKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2090    _RegOpenKeyW.restype  = LONG
2091    _RegOpenKeyW.errcheck = RaiseIfNotErrorSuccess
2092
2093    hkResult = HKEY(INVALID_HANDLE_VALUE)
2094    _RegOpenKeyW(hKey, lpSubKey, byref(hkResult))
2095    return RegistryKeyHandle(hkResult.value)
2096
2097RegOpenKey = GuessStringType(RegOpenKeyA, RegOpenKeyW)
2098
2099# LONG WINAPI RegOpenKeyEx(
2100#   __in        HKEY hKey,
2101#   __in_opt    LPCTSTR lpSubKey,
2102#   __reserved  DWORD ulOptions,
2103#   __in        REGSAM samDesired,
2104#   __out       PHKEY phkResult
2105# );
2106def RegOpenKeyExA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2107    _RegOpenKeyExA = windll.advapi32.RegOpenKeyExA
2108    _RegOpenKeyExA.argtypes = [HKEY, LPSTR, DWORD, REGSAM, PHKEY]
2109    _RegOpenKeyExA.restype  = LONG
2110    _RegOpenKeyExA.errcheck = RaiseIfNotErrorSuccess
2111
2112    hkResult = HKEY(INVALID_HANDLE_VALUE)
2113    _RegOpenKeyExA(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2114    return RegistryKeyHandle(hkResult.value)
2115
2116def RegOpenKeyExW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2117    _RegOpenKeyExW = windll.advapi32.RegOpenKeyExW
2118    _RegOpenKeyExW.argtypes = [HKEY, LPWSTR, DWORD, REGSAM, PHKEY]
2119    _RegOpenKeyExW.restype  = LONG
2120    _RegOpenKeyExW.errcheck = RaiseIfNotErrorSuccess
2121
2122    hkResult = HKEY(INVALID_HANDLE_VALUE)
2123    _RegOpenKeyExW(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2124    return RegistryKeyHandle(hkResult.value)
2125
2126RegOpenKeyEx = GuessStringType(RegOpenKeyExA, RegOpenKeyExW)
2127
2128# LONG WINAPI RegOpenCurrentUser(
2129#   __in   REGSAM samDesired,
2130#   __out  PHKEY phkResult
2131# );
2132def RegOpenCurrentUser(samDesired = KEY_ALL_ACCESS):
2133    _RegOpenCurrentUser = windll.advapi32.RegOpenCurrentUser
2134    _RegOpenCurrentUser.argtypes = [REGSAM, PHKEY]
2135    _RegOpenCurrentUser.restype  = LONG
2136    _RegOpenCurrentUser.errcheck = RaiseIfNotErrorSuccess
2137
2138    hkResult = HKEY(INVALID_HANDLE_VALUE)
2139    _RegOpenCurrentUser(samDesired, byref(hkResult))
2140    return RegistryKeyHandle(hkResult.value)
2141
2142# LONG WINAPI RegOpenUserClassesRoot(
2143#   __in        HANDLE hToken,
2144#   __reserved  DWORD dwOptions,
2145#   __in        REGSAM samDesired,
2146#   __out       PHKEY phkResult
2147# );
2148def RegOpenUserClassesRoot(hToken, samDesired = KEY_ALL_ACCESS):
2149    _RegOpenUserClassesRoot = windll.advapi32.RegOpenUserClassesRoot
2150    _RegOpenUserClassesRoot.argtypes = [HANDLE, DWORD, REGSAM, PHKEY]
2151    _RegOpenUserClassesRoot.restype  = LONG
2152    _RegOpenUserClassesRoot.errcheck = RaiseIfNotErrorSuccess
2153
2154    hkResult = HKEY(INVALID_HANDLE_VALUE)
2155    _RegOpenUserClassesRoot(hToken, 0, samDesired, byref(hkResult))
2156    return RegistryKeyHandle(hkResult.value)
2157
2158# LONG WINAPI RegQueryValue(
2159#   __in         HKEY hKey,
2160#   __in_opt     LPCTSTR lpSubKey,
2161#   __out_opt    LPTSTR lpValue,
2162#   __inout_opt  PLONG lpcbValue
2163# );
2164def RegQueryValueA(hKey, lpSubKey = None):
2165    _RegQueryValueA = windll.advapi32.RegQueryValueA
2166    _RegQueryValueA.argtypes = [HKEY, LPSTR, LPVOID, PLONG]
2167    _RegQueryValueA.restype  = LONG
2168    _RegQueryValueA.errcheck = RaiseIfNotErrorSuccess
2169
2170    cbValue = LONG(0)
2171    _RegQueryValueA(hKey, lpSubKey, None, byref(cbValue))
2172    lpValue = ctypes.create_string_buffer(cbValue.value)
2173    _RegQueryValueA(hKey, lpSubKey, lpValue, byref(cbValue))
2174    return lpValue.value
2175
2176def RegQueryValueW(hKey, lpSubKey = None):
2177    _RegQueryValueW = windll.advapi32.RegQueryValueW
2178    _RegQueryValueW.argtypes = [HKEY, LPWSTR, LPVOID, PLONG]
2179    _RegQueryValueW.restype  = LONG
2180    _RegQueryValueW.errcheck = RaiseIfNotErrorSuccess
2181
2182    cbValue = LONG(0)
2183    _RegQueryValueW(hKey, lpSubKey, None, byref(cbValue))
2184    lpValue = ctypes.create_unicode_buffer(cbValue.value * sizeof(WCHAR))
2185    _RegQueryValueW(hKey, lpSubKey, lpValue, byref(cbValue))
2186    return lpValue.value
2187
2188RegQueryValue = GuessStringType(RegQueryValueA, RegQueryValueW)
2189
2190# LONG WINAPI RegQueryValueEx(
2191#   __in         HKEY hKey,
2192#   __in_opt     LPCTSTR lpValueName,
2193#   __reserved   LPDWORD lpReserved,
2194#   __out_opt    LPDWORD lpType,
2195#   __out_opt    LPBYTE lpData,
2196#   __inout_opt  LPDWORD lpcbData
2197# );
2198def _internal_RegQueryValueEx(ansi, hKey, lpValueName = None, bGetData = True):
2199    _RegQueryValueEx = _caller_RegQueryValueEx(ansi)
2200
2201    cbData = DWORD(0)
2202    dwType = DWORD(-1)
2203    _RegQueryValueEx(hKey, lpValueName, None, byref(dwType), None, byref(cbData))
2204    Type = dwType.value
2205
2206    if not bGetData:
2207        return cbData.value, Type
2208
2209    if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN):   # REG_DWORD_LITTLE_ENDIAN
2210        if cbData.value != 4:
2211            raise ValueError("REG_DWORD value of size %d" % cbData.value)
2212        dwData = DWORD(0)
2213        _RegQueryValueEx(hKey, lpValueName, None, None, byref(dwData), byref(cbData))
2214        return dwData.value, Type
2215
2216    if Type == REG_QWORD:   # REG_QWORD_LITTLE_ENDIAN
2217        if cbData.value != 8:
2218            raise ValueError("REG_QWORD value of size %d" % cbData.value)
2219        qwData = QWORD(long(0))
2220        _RegQueryValueEx(hKey, lpValueName, None, None, byref(qwData), byref(cbData))
2221        return qwData.value, Type
2222
2223    if Type in (REG_SZ, REG_EXPAND_SZ):
2224        if ansi:
2225            szData = ctypes.create_string_buffer(cbData.value)
2226        else:
2227            szData = ctypes.create_unicode_buffer(cbData.value)
2228        _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2229        return szData.value, Type
2230
2231    if Type == REG_MULTI_SZ:
2232        if ansi:
2233            szData = ctypes.create_string_buffer(cbData.value)
2234        else:
2235            szData = ctypes.create_unicode_buffer(cbData.value)
2236        _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2237        Data = szData[:]
2238        if ansi:
2239            aData = Data.split('\0')
2240        else:
2241            aData = Data.split(u'\0')
2242        aData = [token for token in aData if token]
2243        return aData, Type
2244
2245    if Type == REG_LINK:
2246        szData = ctypes.create_unicode_buffer(cbData.value)
2247        _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2248        return szData.value, Type
2249
2250    # REG_BINARY, REG_NONE, and any future types
2251    szData = ctypes.create_string_buffer(cbData.value)
2252    _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2253    return szData.raw, Type
2254
2255def _caller_RegQueryValueEx(ansi):
2256    if ansi:
2257        _RegQueryValueEx = windll.advapi32.RegQueryValueExA
2258        _RegQueryValueEx.argtypes = [HKEY, LPSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2259    else:
2260        _RegQueryValueEx = windll.advapi32.RegQueryValueExW
2261        _RegQueryValueEx.argtypes = [HKEY, LPWSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2262    _RegQueryValueEx.restype  = LONG
2263    _RegQueryValueEx.errcheck = RaiseIfNotErrorSuccess
2264    return _RegQueryValueEx
2265
2266# see _internal_RegQueryValueEx
2267def RegQueryValueExA(hKey, lpValueName = None, bGetData = True):
2268    return _internal_RegQueryValueEx(True, hKey, lpValueName, bGetData)
2269
2270# see _internal_RegQueryValueEx
2271def RegQueryValueExW(hKey, lpValueName = None, bGetData = True):
2272    return _internal_RegQueryValueEx(False, hKey, lpValueName, bGetData)
2273
2274RegQueryValueEx = GuessStringType(RegQueryValueExA, RegQueryValueExW)
2275
2276# LONG WINAPI RegSetValueEx(
2277#   __in        HKEY hKey,
2278#   __in_opt    LPCTSTR lpValueName,
2279#   __reserved  DWORD Reserved,
2280#   __in        DWORD dwType,
2281#   __in_opt    const BYTE *lpData,
2282#   __in        DWORD cbData
2283# );
2284def RegSetValueEx(hKey, lpValueName = None, lpData = None, dwType = None):
2285
2286    # Determine which version of the API to use, ANSI or Widechar.
2287    if lpValueName is None:
2288        if isinstance(lpData, GuessStringType.t_ansi):
2289            ansi = True
2290        elif isinstance(lpData, GuessStringType.t_unicode):
2291            ansi = False
2292        else:
2293            ansi = (GuessStringType.t_ansi == GuessStringType.t_default)
2294    elif isinstance(lpValueName, GuessStringType.t_ansi):
2295        ansi = True
2296    elif isinstance(lpValueName, GuessStringType.t_unicode):
2297        ansi = False
2298    else:
2299        raise TypeError("String expected, got %s instead" % type(lpValueName))
2300
2301    # Autodetect the type when not given.
2302    # TODO: improve detection of DWORD and QWORD by seeing if the value "fits".
2303    if dwType is None:
2304        if lpValueName is None:
2305            dwType = REG_SZ
2306        elif lpData is None:
2307            dwType = REG_NONE
2308        elif isinstance(lpData, GuessStringType.t_ansi):
2309            dwType = REG_SZ
2310        elif isinstance(lpData, GuessStringType.t_unicode):
2311            dwType = REG_SZ
2312        elif isinstance(lpData, int):
2313            dwType = REG_DWORD
2314        elif isinstance(lpData, long):
2315            dwType = REG_QWORD
2316        else:
2317            dwType = REG_BINARY
2318
2319    # Load the ctypes caller.
2320    if ansi:
2321        _RegSetValueEx = windll.advapi32.RegSetValueExA
2322        _RegSetValueEx.argtypes = [HKEY, LPSTR, DWORD, DWORD, LPVOID, DWORD]
2323    else:
2324        _RegSetValueEx = windll.advapi32.RegSetValueExW
2325        _RegSetValueEx.argtypes = [HKEY, LPWSTR, DWORD, DWORD, LPVOID, DWORD]
2326    _RegSetValueEx.restype  = LONG
2327    _RegSetValueEx.errcheck = RaiseIfNotErrorSuccess
2328
2329    # Convert the arguments so ctypes can understand them.
2330    if lpData is None:
2331        DataRef  = None
2332        DataSize = 0
2333    else:
2334        if dwType in (REG_DWORD, REG_DWORD_BIG_ENDIAN):  # REG_DWORD_LITTLE_ENDIAN
2335            Data = DWORD(lpData)
2336        elif dwType == REG_QWORD:   # REG_QWORD_LITTLE_ENDIAN
2337            Data = QWORD(lpData)
2338        elif dwType in (REG_SZ, REG_EXPAND_SZ):
2339            if ansi:
2340                Data = ctypes.create_string_buffer(lpData)
2341            else:
2342                Data = ctypes.create_unicode_buffer(lpData)
2343        elif dwType == REG_MULTI_SZ:
2344            if ansi:
2345                Data = ctypes.create_string_buffer('\0'.join(lpData) + '\0\0')
2346            else:
2347                Data = ctypes.create_unicode_buffer(u'\0'.join(lpData) + u'\0\0')
2348        elif dwType == REG_LINK:
2349            Data = ctypes.create_unicode_buffer(lpData)
2350        else:
2351            Data = ctypes.create_string_buffer(lpData)
2352        DataRef  = byref(Data)
2353        DataSize = sizeof(Data)
2354
2355    # Call the API with the converted arguments.
2356    _RegSetValueEx(hKey, lpValueName, 0, dwType, DataRef, DataSize)
2357
2358# No "GuessStringType" here since detection is done inside.
2359RegSetValueExA = RegSetValueExW = RegSetValueEx
2360
2361# LONG WINAPI RegEnumKey(
2362#   __in   HKEY hKey,
2363#   __in   DWORD dwIndex,
2364#   __out  LPTSTR lpName,
2365#   __in   DWORD cchName
2366# );
2367def RegEnumKeyA(hKey, dwIndex):
2368    _RegEnumKeyA = windll.advapi32.RegEnumKeyA
2369    _RegEnumKeyA.argtypes = [HKEY, DWORD, LPSTR, DWORD]
2370    _RegEnumKeyA.restype  = LONG
2371
2372    cchName = 1024
2373    while True:
2374        lpName = ctypes.create_string_buffer(cchName)
2375        errcode = _RegEnumKeyA(hKey, dwIndex, lpName, cchName)
2376        if errcode != ERROR_MORE_DATA:
2377            break
2378        cchName = cchName + 1024
2379        if cchName > 65536:
2380            raise ctypes.WinError(errcode)
2381    if errcode == ERROR_NO_MORE_ITEMS:
2382        return None
2383    if errcode != ERROR_SUCCESS:
2384        raise ctypes.WinError(errcode)
2385    return lpName.value
2386
2387def RegEnumKeyW(hKey, dwIndex):
2388    _RegEnumKeyW = windll.advapi32.RegEnumKeyW
2389    _RegEnumKeyW.argtypes = [HKEY, DWORD, LPWSTR, DWORD]
2390    _RegEnumKeyW.restype  = LONG
2391
2392    cchName = 512
2393    while True:
2394        lpName = ctypes.create_unicode_buffer(cchName)
2395        errcode = _RegEnumKeyW(hKey, dwIndex, lpName, cchName * 2)
2396        if errcode != ERROR_MORE_DATA:
2397            break
2398        cchName = cchName + 512
2399        if cchName > 32768:
2400            raise ctypes.WinError(errcode)
2401    if errcode == ERROR_NO_MORE_ITEMS:
2402        return None
2403    if errcode != ERROR_SUCCESS:
2404        raise ctypes.WinError(errcode)
2405    return lpName.value
2406
2407RegEnumKey = DefaultStringType(RegEnumKeyA, RegEnumKeyW)
2408
2409# LONG WINAPI RegEnumKeyEx(
2410#   __in         HKEY hKey,
2411#   __in         DWORD dwIndex,
2412#   __out        LPTSTR lpName,
2413#   __inout      LPDWORD lpcName,
2414#   __reserved   LPDWORD lpReserved,
2415#   __inout      LPTSTR lpClass,
2416#   __inout_opt  LPDWORD lpcClass,
2417#   __out_opt    PFILETIME lpftLastWriteTime
2418# );
2419
2420# XXX TODO
2421
2422# LONG WINAPI RegEnumValue(
2423#   __in         HKEY hKey,
2424#   __in         DWORD dwIndex,
2425#   __out        LPTSTR lpValueName,
2426#   __inout      LPDWORD lpcchValueName,
2427#   __reserved   LPDWORD lpReserved,
2428#   __out_opt    LPDWORD lpType,
2429#   __out_opt    LPBYTE lpData,
2430#   __inout_opt  LPDWORD lpcbData
2431# );
2432def _internal_RegEnumValue(ansi, hKey, dwIndex, bGetData = True):
2433    if ansi:
2434        _RegEnumValue = windll.advapi32.RegEnumValueA
2435        _RegEnumValue.argtypes = [HKEY, DWORD, LPSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2436    else:
2437        _RegEnumValue = windll.advapi32.RegEnumValueW
2438        _RegEnumValue.argtypes = [HKEY, DWORD, LPWSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2439    _RegEnumValue.restype  = LONG
2440
2441    cchValueName = DWORD(1024)
2442    dwType = DWORD(-1)
2443    lpcchValueName = byref(cchValueName)
2444    lpType = byref(dwType)
2445    if ansi:
2446        lpValueName = ctypes.create_string_buffer(cchValueName.value)
2447    else:
2448        lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2449    if bGetData:
2450        cbData = DWORD(0)
2451        lpcbData = byref(cbData)
2452    else:
2453        lpcbData = None
2454    lpData = None
2455    errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2456
2457    if errcode == ERROR_MORE_DATA or (bGetData and errcode == ERROR_SUCCESS):
2458        if ansi:
2459            cchValueName.value = cchValueName.value + sizeof(CHAR)
2460            lpValueName = ctypes.create_string_buffer(cchValueName.value)
2461        else:
2462            cchValueName.value = cchValueName.value + sizeof(WCHAR)
2463            lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2464
2465        if bGetData:
2466            Type = dwType.value
2467
2468            if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN):   # REG_DWORD_LITTLE_ENDIAN
2469                if cbData.value != sizeof(DWORD):
2470                    raise ValueError("REG_DWORD value of size %d" % cbData.value)
2471                Data = DWORD(0)
2472
2473            elif Type == REG_QWORD:   # REG_QWORD_LITTLE_ENDIAN
2474                if cbData.value != sizeof(QWORD):
2475                    raise ValueError("REG_QWORD value of size %d" % cbData.value)
2476                Data = QWORD(long(0))
2477
2478            elif Type in (REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ):
2479                if ansi:
2480                    Data = ctypes.create_string_buffer(cbData.value)
2481                else:
2482                    Data = ctypes.create_unicode_buffer(cbData.value)
2483
2484            elif Type == REG_LINK:
2485                Data = ctypes.create_unicode_buffer(cbData.value)
2486
2487            else:       # REG_BINARY, REG_NONE, and any future types
2488                Data = ctypes.create_string_buffer(cbData.value)
2489
2490            lpData = byref(Data)
2491
2492        errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2493
2494    if errcode == ERROR_NO_MORE_ITEMS:
2495        return None
2496    #if errcode  != ERROR_SUCCESS:
2497    #    raise ctypes.WinError(errcode)
2498
2499    if not bGetData:
2500        return lpValueName.value, dwType.value
2501
2502    if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD, REG_SZ, REG_EXPAND_SZ, REG_LINK): # REG_DWORD_LITTLE_ENDIAN, REG_QWORD_LITTLE_ENDIAN
2503        return lpValueName.value, dwType.value, Data.value
2504
2505    if Type == REG_MULTI_SZ:
2506        sData = Data[:]
2507        del Data
2508        if ansi:
2509            aData = sData.split('\0')
2510        else:
2511            aData = sData.split(u'\0')
2512        aData = [token for token in aData if token]
2513        return lpValueName.value, dwType.value, aData
2514
2515    # REG_BINARY, REG_NONE, and any future types
2516    return lpValueName.value, dwType.value, Data.raw
2517
2518def RegEnumValueA(hKey, dwIndex, bGetData = True):
2519    return _internal_RegEnumValue(True, hKey, dwIndex, bGetData)
2520
2521def RegEnumValueW(hKey, dwIndex, bGetData = True):
2522    return _internal_RegEnumValue(False, hKey, dwIndex, bGetData)
2523
2524RegEnumValue = DefaultStringType(RegEnumValueA, RegEnumValueW)
2525
2526# XXX TODO
2527
2528# LONG WINAPI RegSetKeyValue(
2529#   __in      HKEY hKey,
2530#   __in_opt  LPCTSTR lpSubKey,
2531#   __in_opt  LPCTSTR lpValueName,
2532#   __in      DWORD dwType,
2533#   __in_opt  LPCVOID lpData,
2534#   __in      DWORD cbData
2535# );
2536
2537# XXX TODO
2538
2539# LONG WINAPI RegQueryMultipleValues(
2540#   __in         HKEY hKey,
2541#   __out        PVALENT val_list,
2542#   __in         DWORD num_vals,
2543#   __out_opt    LPTSTR lpValueBuf,
2544#   __inout_opt  LPDWORD ldwTotsize
2545# );
2546
2547# XXX TODO
2548
2549# LONG WINAPI RegDeleteValue(
2550#   __in      HKEY hKey,
2551#   __in_opt  LPCTSTR lpValueName
2552# );
2553def RegDeleteValueA(hKeySrc, lpValueName = None):
2554    _RegDeleteValueA = windll.advapi32.RegDeleteValueA
2555    _RegDeleteValueA.argtypes = [HKEY, LPSTR]
2556    _RegDeleteValueA.restype  = LONG
2557    _RegDeleteValueA.errcheck = RaiseIfNotErrorSuccess
2558    _RegDeleteValueA(hKeySrc, lpValueName)
2559def RegDeleteValueW(hKeySrc, lpValueName = None):
2560    _RegDeleteValueW = windll.advapi32.RegDeleteValueW
2561    _RegDeleteValueW.argtypes = [HKEY, LPWSTR]
2562    _RegDeleteValueW.restype  = LONG
2563    _RegDeleteValueW.errcheck = RaiseIfNotErrorSuccess
2564    _RegDeleteValueW(hKeySrc, lpValueName)
2565RegDeleteValue = GuessStringType(RegDeleteValueA, RegDeleteValueW)
2566
2567# LONG WINAPI RegDeleteKeyValue(
2568#   __in      HKEY hKey,
2569#   __in_opt  LPCTSTR lpSubKey,
2570#   __in_opt  LPCTSTR lpValueName
2571# );
2572def RegDeleteKeyValueA(hKeySrc, lpSubKey = None, lpValueName = None):
2573    _RegDeleteKeyValueA = windll.advapi32.RegDeleteKeyValueA
2574    _RegDeleteKeyValueA.argtypes = [HKEY, LPSTR, LPSTR]
2575    _RegDeleteKeyValueA.restype  = LONG
2576    _RegDeleteKeyValueA.errcheck = RaiseIfNotErrorSuccess
2577    _RegDeleteKeyValueA(hKeySrc, lpSubKey, lpValueName)
2578def RegDeleteKeyValueW(hKeySrc, lpSubKey = None, lpValueName = None):
2579    _RegDeleteKeyValueW = windll.advapi32.RegDeleteKeyValueW
2580    _RegDeleteKeyValueW.argtypes = [HKEY, LPWSTR, LPWSTR]
2581    _RegDeleteKeyValueW.restype  = LONG
2582    _RegDeleteKeyValueW.errcheck = RaiseIfNotErrorSuccess
2583    _RegDeleteKeyValueW(hKeySrc, lpSubKey, lpValueName)
2584RegDeleteKeyValue = GuessStringType(RegDeleteKeyValueA, RegDeleteKeyValueW)
2585
2586# LONG WINAPI RegDeleteKey(
2587#   __in  HKEY hKey,
2588#   __in  LPCTSTR lpSubKey
2589# );
2590def RegDeleteKeyA(hKeySrc, lpSubKey = None):
2591    _RegDeleteKeyA = windll.advapi32.RegDeleteKeyA
2592    _RegDeleteKeyA.argtypes = [HKEY, LPSTR]
2593    _RegDeleteKeyA.restype  = LONG
2594    _RegDeleteKeyA.errcheck = RaiseIfNotErrorSuccess
2595    _RegDeleteKeyA(hKeySrc, lpSubKey)
2596def RegDeleteKeyW(hKeySrc, lpSubKey = None):
2597    _RegDeleteKeyW = windll.advapi32.RegDeleteKeyW
2598    _RegDeleteKeyW.argtypes = [HKEY, LPWSTR]
2599    _RegDeleteKeyW.restype  = LONG
2600    _RegDeleteKeyW.errcheck = RaiseIfNotErrorSuccess
2601    _RegDeleteKeyW(hKeySrc, lpSubKey)
2602RegDeleteKey = GuessStringType(RegDeleteKeyA, RegDeleteKeyW)
2603
2604# LONG WINAPI RegDeleteKeyEx(
2605#   __in        HKEY hKey,
2606#   __in        LPCTSTR lpSubKey,
2607#   __in        REGSAM samDesired,
2608#   __reserved  DWORD Reserved
2609# );
2610
2611def RegDeleteKeyExA(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2612    _RegDeleteKeyExA = windll.advapi32.RegDeleteKeyExA
2613    _RegDeleteKeyExA.argtypes = [HKEY, LPSTR, REGSAM, DWORD]
2614    _RegDeleteKeyExA.restype  = LONG
2615    _RegDeleteKeyExA.errcheck = RaiseIfNotErrorSuccess
2616    _RegDeleteKeyExA(hKeySrc, lpSubKey, samDesired, 0)
2617def RegDeleteKeyExW(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2618    _RegDeleteKeyExW = windll.advapi32.RegDeleteKeyExW
2619    _RegDeleteKeyExW.argtypes = [HKEY, LPWSTR, REGSAM, DWORD]
2620    _RegDeleteKeyExW.restype  = LONG
2621    _RegDeleteKeyExW.errcheck = RaiseIfNotErrorSuccess
2622    _RegDeleteKeyExW(hKeySrc, lpSubKey, samDesired, 0)
2623RegDeleteKeyEx = GuessStringType(RegDeleteKeyExA, RegDeleteKeyExW)
2624
2625# LONG WINAPI RegCopyTree(
2626#   __in      HKEY hKeySrc,
2627#   __in_opt  LPCTSTR lpSubKey,
2628#   __in      HKEY hKeyDest
2629# );
2630def RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest):
2631    _RegCopyTreeA = windll.advapi32.RegCopyTreeA
2632    _RegCopyTreeA.argtypes = [HKEY, LPSTR, HKEY]
2633    _RegCopyTreeA.restype  = LONG
2634    _RegCopyTreeA.errcheck = RaiseIfNotErrorSuccess
2635    _RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest)
2636def RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest):
2637    _RegCopyTreeW = windll.advapi32.RegCopyTreeW
2638    _RegCopyTreeW.argtypes = [HKEY, LPWSTR, HKEY]
2639    _RegCopyTreeW.restype  = LONG
2640    _RegCopyTreeW.errcheck = RaiseIfNotErrorSuccess
2641    _RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest)
2642RegCopyTree = GuessStringType(RegCopyTreeA, RegCopyTreeW)
2643
2644# LONG WINAPI RegDeleteTree(
2645#   __in      HKEY hKey,
2646#   __in_opt  LPCTSTR lpSubKey
2647# );
2648def RegDeleteTreeA(hKey, lpSubKey = None):
2649    _RegDeleteTreeA = windll.advapi32.RegDeleteTreeA
2650    _RegDeleteTreeA.argtypes = [HKEY, LPWSTR]
2651    _RegDeleteTreeA.restype  = LONG
2652    _RegDeleteTreeA.errcheck = RaiseIfNotErrorSuccess
2653    _RegDeleteTreeA(hKey, lpSubKey)
2654def RegDeleteTreeW(hKey, lpSubKey = None):
2655    _RegDeleteTreeW = windll.advapi32.RegDeleteTreeW
2656    _RegDeleteTreeW.argtypes = [HKEY, LPWSTR]
2657    _RegDeleteTreeW.restype  = LONG
2658    _RegDeleteTreeW.errcheck = RaiseIfNotErrorSuccess
2659    _RegDeleteTreeW(hKey, lpSubKey)
2660RegDeleteTree = GuessStringType(RegDeleteTreeA, RegDeleteTreeW)
2661
2662# LONG WINAPI RegFlushKey(
2663#   __in  HKEY hKey
2664# );
2665def RegFlushKey(hKey):
2666    _RegFlushKey = windll.advapi32.RegFlushKey
2667    _RegFlushKey.argtypes = [HKEY]
2668    _RegFlushKey.restype  = LONG
2669    _RegFlushKey.errcheck = RaiseIfNotErrorSuccess
2670    _RegFlushKey(hKey)
2671
2672# LONG WINAPI RegLoadMUIString(
2673#   _In_       HKEY hKey,
2674#   _In_opt_   LPCTSTR pszValue,
2675#   _Out_opt_  LPTSTR pszOutBuf,
2676#   _In_       DWORD cbOutBuf,
2677#   _Out_opt_  LPDWORD pcbData,
2678#   _In_       DWORD Flags,
2679#   _In_opt_   LPCTSTR pszDirectory
2680# );
2681
2682# TO DO
2683
2684#------------------------------------------------------------------------------
2685
2686# BOOL WINAPI CloseServiceHandle(
2687#   _In_  SC_HANDLE hSCObject
2688# );
2689def CloseServiceHandle(hSCObject):
2690    _CloseServiceHandle = windll.advapi32.CloseServiceHandle
2691    _CloseServiceHandle.argtypes = [SC_HANDLE]
2692    _CloseServiceHandle.restype  = bool
2693    _CloseServiceHandle.errcheck = RaiseIfZero
2694
2695    if isinstance(hSCObject, Handle):
2696        # Prevents the handle from being closed without notifying the Handle object.
2697        hSCObject.close()
2698    else:
2699        _CloseServiceHandle(hSCObject)
2700
2701# SC_HANDLE WINAPI OpenSCManager(
2702#   _In_opt_  LPCTSTR lpMachineName,
2703#   _In_opt_  LPCTSTR lpDatabaseName,
2704#   _In_      DWORD dwDesiredAccess
2705# );
2706def OpenSCManagerA(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2707    _OpenSCManagerA = windll.advapi32.OpenSCManagerA
2708    _OpenSCManagerA.argtypes = [LPSTR, LPSTR, DWORD]
2709    _OpenSCManagerA.restype  = SC_HANDLE
2710    _OpenSCManagerA.errcheck = RaiseIfZero
2711
2712    hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2713    return ServiceControlManagerHandle(hSCObject)
2714
2715def OpenSCManagerW(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2716    _OpenSCManagerW = windll.advapi32.OpenSCManagerW
2717    _OpenSCManagerW.argtypes = [LPWSTR, LPWSTR, DWORD]
2718    _OpenSCManagerW.restype  = SC_HANDLE
2719    _OpenSCManagerW.errcheck = RaiseIfZero
2720
2721    hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2722    return ServiceControlManagerHandle(hSCObject)
2723
2724OpenSCManager = GuessStringType(OpenSCManagerA, OpenSCManagerW)
2725
2726# SC_HANDLE WINAPI OpenService(
2727#   _In_  SC_HANDLE hSCManager,
2728#   _In_  LPCTSTR lpServiceName,
2729#   _In_  DWORD dwDesiredAccess
2730# );
2731def OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2732    _OpenServiceA = windll.advapi32.OpenServiceA
2733    _OpenServiceA.argtypes = [SC_HANDLE, LPSTR, DWORD]
2734    _OpenServiceA.restype  = SC_HANDLE
2735    _OpenServiceA.errcheck = RaiseIfZero
2736    return ServiceHandle( _OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess) )
2737
2738def OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2739    _OpenServiceW = windll.advapi32.OpenServiceW
2740    _OpenServiceW.argtypes = [SC_HANDLE, LPWSTR, DWORD]
2741    _OpenServiceW.restype  = SC_HANDLE
2742    _OpenServiceW.errcheck = RaiseIfZero
2743    return ServiceHandle( _OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess) )
2744
2745OpenService = GuessStringType(OpenServiceA, OpenServiceW)
2746
2747# SC_HANDLE WINAPI CreateService(
2748#   _In_       SC_HANDLE hSCManager,
2749#   _In_       LPCTSTR lpServiceName,
2750#   _In_opt_   LPCTSTR lpDisplayName,
2751#   _In_       DWORD dwDesiredAccess,
2752#   _In_       DWORD dwServiceType,
2753#   _In_       DWORD dwStartType,
2754#   _In_       DWORD dwErrorControl,
2755#   _In_opt_   LPCTSTR lpBinaryPathName,
2756#   _In_opt_   LPCTSTR lpLoadOrderGroup,
2757#   _Out_opt_  LPDWORD lpdwTagId,
2758#   _In_opt_   LPCTSTR lpDependencies,
2759#   _In_opt_   LPCTSTR lpServiceStartName,
2760#   _In_opt_   LPCTSTR lpPassword
2761# );
2762def CreateServiceA(hSCManager, lpServiceName,
2763                   lpDisplayName = None,
2764                   dwDesiredAccess = SERVICE_ALL_ACCESS,
2765                   dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2766                   dwStartType = SERVICE_DEMAND_START,
2767                   dwErrorControl = SERVICE_ERROR_NORMAL,
2768                   lpBinaryPathName = None,
2769                   lpLoadOrderGroup = None,
2770                   lpDependencies = None,
2771                   lpServiceStartName = None,
2772                   lpPassword = None):
2773
2774    _CreateServiceA = windll.advapi32.CreateServiceA
2775    _CreateServiceA.argtypes = [SC_HANDLE, LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD, LPSTR, LPSTR, LPDWORD, LPSTR, LPSTR, LPSTR]
2776    _CreateServiceA.restype  = SC_HANDLE
2777    _CreateServiceA.errcheck = RaiseIfZero
2778
2779    dwTagId = DWORD(0)
2780    hService = _CreateServiceA(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2781    return ServiceHandle(hService), dwTagId.value
2782
2783def CreateServiceW(hSCManager, lpServiceName,
2784                   lpDisplayName = None,
2785                   dwDesiredAccess = SERVICE_ALL_ACCESS,
2786                   dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2787                   dwStartType = SERVICE_DEMAND_START,
2788                   dwErrorControl = SERVICE_ERROR_NORMAL,
2789                   lpBinaryPathName = None,
2790                   lpLoadOrderGroup = None,
2791                   lpDependencies = None,
2792                   lpServiceStartName = None,
2793                   lpPassword = None):
2794
2795    _CreateServiceW = windll.advapi32.CreateServiceW
2796    _CreateServiceW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, DWORD, DWORD, DWORD, DWORD, LPWSTR, LPWSTR, LPDWORD, LPWSTR, LPWSTR, LPWSTR]
2797    _CreateServiceW.restype  = SC_HANDLE
2798    _CreateServiceW.errcheck = RaiseIfZero
2799
2800    dwTagId = DWORD(0)
2801    hService = _CreateServiceW(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2802    return ServiceHandle(hService), dwTagId.value
2803
2804CreateService = GuessStringType(CreateServiceA, CreateServiceW)
2805
2806# BOOL WINAPI DeleteService(
2807#   _In_  SC_HANDLE hService
2808# );
2809def DeleteService(hService):
2810    _DeleteService = windll.advapi32.DeleteService
2811    _DeleteService.argtypes = [SC_HANDLE]
2812    _DeleteService.restype  = bool
2813    _DeleteService.errcheck = RaiseIfZero
2814    _DeleteService(hService)
2815
2816# BOOL WINAPI GetServiceKeyName(
2817#   _In_       SC_HANDLE hSCManager,
2818#   _In_       LPCTSTR lpDisplayName,
2819#   _Out_opt_  LPTSTR lpServiceName,
2820#   _Inout_    LPDWORD lpcchBuffer
2821# );
2822def GetServiceKeyNameA(hSCManager, lpDisplayName):
2823    _GetServiceKeyNameA = windll.advapi32.GetServiceKeyNameA
2824    _GetServiceKeyNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2825    _GetServiceKeyNameA.restype  = bool
2826
2827    cchBuffer = DWORD(0)
2828    _GetServiceKeyNameA(hSCManager, lpDisplayName, None, byref(cchBuffer))
2829    if cchBuffer.value == 0:
2830        raise ctypes.WinError()
2831    lpServiceName = ctypes.create_string_buffer(cchBuffer.value + 1)
2832    cchBuffer.value = sizeof(lpServiceName)
2833    success = _GetServiceKeyNameA(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2834    if not success:
2835        raise ctypes.WinError()
2836    return lpServiceName.value
2837
2838def GetServiceKeyNameW(hSCManager, lpDisplayName):
2839    _GetServiceKeyNameW = windll.advapi32.GetServiceKeyNameW
2840    _GetServiceKeyNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2841    _GetServiceKeyNameW.restype  = bool
2842
2843    cchBuffer = DWORD(0)
2844    _GetServiceKeyNameW(hSCManager, lpDisplayName, None, byref(cchBuffer))
2845    if cchBuffer.value == 0:
2846        raise ctypes.WinError()
2847    lpServiceName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2848    cchBuffer.value = sizeof(lpServiceName)
2849    success = _GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2850    if not success:
2851        raise ctypes.WinError()
2852    return lpServiceName.value
2853
2854GetServiceKeyName = GuessStringType(GetServiceKeyNameA, GetServiceKeyNameW)
2855
2856# BOOL WINAPI GetServiceDisplayName(
2857#   _In_       SC_HANDLE hSCManager,
2858#   _In_       LPCTSTR lpServiceName,
2859#   _Out_opt_  LPTSTR lpDisplayName,
2860#   _Inout_    LPDWORD lpcchBuffer
2861# );
2862def GetServiceDisplayNameA(hSCManager, lpServiceName):
2863    _GetServiceDisplayNameA = windll.advapi32.GetServiceDisplayNameA
2864    _GetServiceDisplayNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2865    _GetServiceDisplayNameA.restype  = bool
2866
2867    cchBuffer = DWORD(0)
2868    _GetServiceDisplayNameA(hSCManager, lpServiceName, None, byref(cchBuffer))
2869    if cchBuffer.value == 0:
2870        raise ctypes.WinError()
2871    lpDisplayName = ctypes.create_string_buffer(cchBuffer.value + 1)
2872    cchBuffer.value = sizeof(lpDisplayName)
2873    success = _GetServiceDisplayNameA(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2874    if not success:
2875        raise ctypes.WinError()
2876    return lpDisplayName.value
2877
2878def GetServiceDisplayNameW(hSCManager, lpServiceName):
2879    _GetServiceDisplayNameW = windll.advapi32.GetServiceDisplayNameW
2880    _GetServiceDisplayNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2881    _GetServiceDisplayNameW.restype  = bool
2882
2883    cchBuffer = DWORD(0)
2884    _GetServiceDisplayNameW(hSCManager, lpServiceName, None, byref(cchBuffer))
2885    if cchBuffer.value == 0:
2886        raise ctypes.WinError()
2887    lpDisplayName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2888    cchBuffer.value = sizeof(lpDisplayName)
2889    success = _GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2890    if not success:
2891        raise ctypes.WinError()
2892    return lpDisplayName.value
2893
2894GetServiceDisplayName = GuessStringType(GetServiceDisplayNameA, GetServiceDisplayNameW)
2895
2896# BOOL WINAPI QueryServiceConfig(
2897#   _In_       SC_HANDLE hService,
2898#   _Out_opt_  LPQUERY_SERVICE_CONFIG lpServiceConfig,
2899#   _In_       DWORD cbBufSize,
2900#   _Out_      LPDWORD pcbBytesNeeded
2901# );
2902
2903# TO DO
2904
2905# BOOL WINAPI QueryServiceConfig2(
2906#   _In_       SC_HANDLE hService,
2907#   _In_       DWORD dwInfoLevel,
2908#   _Out_opt_  LPBYTE lpBuffer,
2909#   _In_       DWORD cbBufSize,
2910#   _Out_      LPDWORD pcbBytesNeeded
2911# );
2912
2913# TO DO
2914
2915# BOOL WINAPI ChangeServiceConfig(
2916#   _In_       SC_HANDLE hService,
2917#   _In_       DWORD dwServiceType,
2918#   _In_       DWORD dwStartType,
2919#   _In_       DWORD dwErrorControl,
2920#   _In_opt_   LPCTSTR lpBinaryPathName,
2921#   _In_opt_   LPCTSTR lpLoadOrderGroup,
2922#   _Out_opt_  LPDWORD lpdwTagId,
2923#   _In_opt_   LPCTSTR lpDependencies,
2924#   _In_opt_   LPCTSTR lpServiceStartName,
2925#   _In_opt_   LPCTSTR lpPassword,
2926#   _In_opt_   LPCTSTR lpDisplayName
2927# );
2928
2929# TO DO
2930
2931# BOOL WINAPI ChangeServiceConfig2(
2932#   _In_      SC_HANDLE hService,
2933#   _In_      DWORD dwInfoLevel,
2934#   _In_opt_  LPVOID lpInfo
2935# );
2936
2937# TO DO
2938
2939# BOOL WINAPI StartService(
2940#   _In_      SC_HANDLE hService,
2941#   _In_      DWORD dwNumServiceArgs,
2942#   _In_opt_  LPCTSTR *lpServiceArgVectors
2943# );
2944def StartServiceA(hService, ServiceArgVectors = None):
2945    _StartServiceA = windll.advapi32.StartServiceA
2946    _StartServiceA.argtypes = [SC_HANDLE, DWORD, LPVOID]
2947    _StartServiceA.restype  = bool
2948    _StartServiceA.errcheck = RaiseIfZero
2949
2950    if ServiceArgVectors:
2951        dwNumServiceArgs = len(ServiceArgVectors)
2952        CServiceArgVectors = (LPSTR * dwNumServiceArgs)(*ServiceArgVectors)
2953        lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
2954    else:
2955        dwNumServiceArgs = 0
2956        lpServiceArgVectors = None
2957    _StartServiceA(hService, dwNumServiceArgs, lpServiceArgVectors)
2958
2959def StartServiceW(hService, ServiceArgVectors = None):
2960    _StartServiceW = windll.advapi32.StartServiceW
2961    _StartServiceW.argtypes = [SC_HANDLE, DWORD, LPVOID]
2962    _StartServiceW.restype  = bool
2963    _StartServiceW.errcheck = RaiseIfZero
2964
2965    if ServiceArgVectors:
2966        dwNumServiceArgs = len(ServiceArgVectors)
2967        CServiceArgVectors = (LPWSTR * dwNumServiceArgs)(*ServiceArgVectors)
2968        lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
2969    else:
2970        dwNumServiceArgs = 0
2971        lpServiceArgVectors = None
2972    _StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors)
2973
2974StartService = GuessStringType(StartServiceA, StartServiceW)
2975
2976# BOOL WINAPI ControlService(
2977#   _In_   SC_HANDLE hService,
2978#   _In_   DWORD dwControl,
2979#   _Out_  LPSERVICE_STATUS lpServiceStatus
2980# );
2981def ControlService(hService, dwControl):
2982    _ControlService = windll.advapi32.ControlService
2983    _ControlService.argtypes = [SC_HANDLE, DWORD, LPSERVICE_STATUS]
2984    _ControlService.restype  = bool
2985    _ControlService.errcheck = RaiseIfZero
2986
2987    rawServiceStatus = SERVICE_STATUS()
2988    _ControlService(hService, dwControl, byref(rawServiceStatus))
2989    return ServiceStatus(rawServiceStatus)
2990
2991# BOOL WINAPI ControlServiceEx(
2992#   _In_     SC_HANDLE hService,
2993#   _In_     DWORD dwControl,
2994#   _In_     DWORD dwInfoLevel,
2995#   _Inout_  PVOID pControlParams
2996# );
2997
2998# TO DO
2999
3000# DWORD WINAPI NotifyServiceStatusChange(
3001#   _In_  SC_HANDLE hService,
3002#   _In_  DWORD dwNotifyMask,
3003#   _In_  PSERVICE_NOTIFY pNotifyBuffer
3004# );
3005
3006# TO DO
3007
3008# BOOL WINAPI QueryServiceStatus(
3009#   _In_   SC_HANDLE hService,
3010#   _Out_  LPSERVICE_STATUS lpServiceStatus
3011# );
3012def QueryServiceStatus(hService):
3013    _QueryServiceStatus = windll.advapi32.QueryServiceStatus
3014    _QueryServiceStatus.argtypes = [SC_HANDLE, LPSERVICE_STATUS]
3015    _QueryServiceStatus.restype  = bool
3016    _QueryServiceStatus.errcheck = RaiseIfZero
3017
3018    rawServiceStatus = SERVICE_STATUS()
3019    _QueryServiceStatus(hService, byref(rawServiceStatus))
3020    return ServiceStatus(rawServiceStatus)
3021
3022# BOOL WINAPI QueryServiceStatusEx(
3023#   _In_       SC_HANDLE hService,
3024#   _In_       SC_STATUS_TYPE InfoLevel,
3025#   _Out_opt_  LPBYTE lpBuffer,
3026#   _In_       DWORD cbBufSize,
3027#   _Out_      LPDWORD pcbBytesNeeded
3028# );
3029def QueryServiceStatusEx(hService, InfoLevel = SC_STATUS_PROCESS_INFO):
3030
3031    if InfoLevel != SC_STATUS_PROCESS_INFO:
3032        raise NotImplementedError()
3033
3034    _QueryServiceStatusEx = windll.advapi32.QueryServiceStatusEx
3035    _QueryServiceStatusEx.argtypes = [SC_HANDLE, SC_STATUS_TYPE, LPVOID, DWORD, LPDWORD]
3036    _QueryServiceStatusEx.restype  = bool
3037    _QueryServiceStatusEx.errcheck = RaiseIfZero
3038
3039    lpBuffer = SERVICE_STATUS_PROCESS()
3040    cbBytesNeeded = DWORD(sizeof(lpBuffer))
3041    _QueryServiceStatusEx(hService, InfoLevel, byref(lpBuffer), sizeof(lpBuffer), byref(cbBytesNeeded))
3042    return ServiceStatusProcess(lpBuffer)
3043
3044# BOOL WINAPI EnumServicesStatus(
3045#   _In_         SC_HANDLE hSCManager,
3046#   _In_         DWORD dwServiceType,
3047#   _In_         DWORD dwServiceState,
3048#   _Out_opt_    LPENUM_SERVICE_STATUS lpServices,
3049#   _In_         DWORD cbBufSize,
3050#   _Out_        LPDWORD pcbBytesNeeded,
3051#   _Out_        LPDWORD lpServicesReturned,
3052#   _Inout_opt_  LPDWORD lpResumeHandle
3053# );
3054def EnumServicesStatusA(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3055    _EnumServicesStatusA = windll.advapi32.EnumServicesStatusA
3056    _EnumServicesStatusA.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3057    _EnumServicesStatusA.restype  = bool
3058
3059    cbBytesNeeded    = DWORD(0)
3060    ServicesReturned = DWORD(0)
3061    ResumeHandle     = DWORD(0)
3062
3063    _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle))
3064
3065    Services = []
3066    success = False
3067    while GetLastError() == ERROR_MORE_DATA:
3068        if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSA):
3069            break
3070        ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3071        success = _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle))
3072        if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSA) * ServicesReturned.value):
3073            raise ctypes.WinError()
3074        lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSA)
3075        for index in compat.xrange(0, ServicesReturned.value):
3076            Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3077        if success: break
3078    if not success:
3079        raise ctypes.WinError()
3080
3081    return Services
3082
3083def EnumServicesStatusW(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3084    _EnumServicesStatusW = windll.advapi32.EnumServicesStatusW
3085    _EnumServicesStatusW.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3086    _EnumServicesStatusW.restype  = bool
3087
3088    cbBytesNeeded    = DWORD(0)
3089    ServicesReturned = DWORD(0)
3090    ResumeHandle     = DWORD(0)
3091
3092    _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle))
3093
3094    Services = []
3095    success = False
3096    while GetLastError() == ERROR_MORE_DATA:
3097        if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSW):
3098            break
3099        ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3100        success = _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle))
3101        if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSW) * ServicesReturned.value):
3102            raise ctypes.WinError()
3103        lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSW)
3104        for index in compat.xrange(0, ServicesReturned.value):
3105            Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3106        if success: break
3107    if not success:
3108        raise ctypes.WinError()
3109
3110    return Services
3111
3112EnumServicesStatus = DefaultStringType(EnumServicesStatusA, EnumServicesStatusW)
3113
3114# BOOL WINAPI EnumServicesStatusEx(
3115#   _In_         SC_HANDLE hSCManager,
3116#   _In_         SC_ENUM_TYPE InfoLevel,
3117#   _In_         DWORD dwServiceType,
3118#   _In_         DWORD dwServiceState,
3119#   _Out_opt_    LPBYTE lpServices,
3120#   _In_         DWORD cbBufSize,
3121#   _Out_        LPDWORD pcbBytesNeeded,
3122#   _Out_        LPDWORD lpServicesReturned,
3123#   _Inout_opt_  LPDWORD lpResumeHandle,
3124#   _In_opt_     LPCTSTR pszGroupName
3125# );
3126def EnumServicesStatusExA(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3127
3128    if InfoLevel != SC_ENUM_PROCESS_INFO:
3129        raise NotImplementedError()
3130
3131    _EnumServicesStatusExA = windll.advapi32.EnumServicesStatusExA
3132    _EnumServicesStatusExA.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR]
3133    _EnumServicesStatusExA.restype  = bool
3134
3135    cbBytesNeeded    = DWORD(0)
3136    ServicesReturned = DWORD(0)
3137    ResumeHandle     = DWORD(0)
3138
3139    _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName)
3140
3141    Services = []
3142    success = False
3143    while GetLastError() == ERROR_MORE_DATA:
3144        if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSA):
3145            break
3146        ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3147        success = _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName)
3148        if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSA) * ServicesReturned.value):
3149            raise ctypes.WinError()
3150        lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSA)
3151        for index in compat.xrange(0, ServicesReturned.value):
3152            Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3153        if success: break
3154    if not success:
3155        raise ctypes.WinError()
3156
3157    return Services
3158
3159def EnumServicesStatusExW(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3160    _EnumServicesStatusExW = windll.advapi32.EnumServicesStatusExW
3161    _EnumServicesStatusExW.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR]
3162    _EnumServicesStatusExW.restype  = bool
3163
3164    if InfoLevel != SC_ENUM_PROCESS_INFO:
3165        raise NotImplementedError()
3166
3167    cbBytesNeeded    = DWORD(0)
3168    ServicesReturned = DWORD(0)
3169    ResumeHandle     = DWORD(0)
3170
3171    _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName)
3172
3173    Services = []
3174    success = False
3175    while GetLastError() == ERROR_MORE_DATA:
3176        if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSW):
3177            break
3178        ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3179        success = _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName)
3180        if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSW) * ServicesReturned.value):
3181            raise ctypes.WinError()
3182        lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSW)
3183        for index in compat.xrange(0, ServicesReturned.value):
3184            Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3185        if success: break
3186    if not success:
3187        raise ctypes.WinError()
3188
3189    return Services
3190
3191EnumServicesStatusEx = DefaultStringType(EnumServicesStatusExA, EnumServicesStatusExW)
3192
3193# BOOL WINAPI EnumDependentServices(
3194#   _In_       SC_HANDLE hService,
3195#   _In_       DWORD dwServiceState,
3196#   _Out_opt_  LPENUM_SERVICE_STATUS lpServices,
3197#   _In_       DWORD cbBufSize,
3198#   _Out_      LPDWORD pcbBytesNeeded,
3199#   _Out_      LPDWORD lpServicesReturned
3200# );
3201
3202# TO DO
3203
3204#==============================================================================
3205# This calculates the list of exported symbols.
3206_all = set(vars().keys()).difference(_all)
3207__all__ = [_x for _x in _all if not _x.startswith('_')]
3208__all__.sort()
3209#==============================================================================
3210