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 kernel32.dll in ctypes.
33"""
34
35__revision__ = "$Id$"
36
37import warnings
38
39from winappdbg.win32.defines import *
40
41from winappdbg.win32 import context_i386
42from winappdbg.win32 import context_amd64
43
44#==============================================================================
45# This is used later on to calculate the list of exported symbols.
46_all = None
47_all = set(vars().keys())
48_all.add('version')
49#==============================================================================
50
51from winappdbg.win32.version import *
52
53#------------------------------------------------------------------------------
54
55# This can't be defined in defines.py because it calls GetLastError().
56def RaiseIfLastError(result, func = None, arguments = ()):
57    """
58    Error checking for Win32 API calls with no error-specific return value.
59
60    Regardless of the return value, the function calls GetLastError(). If the
61    code is not C{ERROR_SUCCESS} then a C{WindowsError} exception is raised.
62
63    For this to work, the user MUST call SetLastError(ERROR_SUCCESS) prior to
64    calling the API. Otherwise an exception may be raised even on success,
65    since most API calls don't clear the error status code.
66    """
67    code = GetLastError()
68    if code != ERROR_SUCCESS:
69        raise ctypes.WinError(code)
70    return result
71
72#--- CONTEXT structure and constants ------------------------------------------
73
74ContextArchMask = 0x0FFF0000    # just guessing here! seems to work, though
75
76if   arch == ARCH_I386:
77    from winappdbg.win32.context_i386 import *
78elif arch == ARCH_AMD64:
79    if bits == 64:
80        from winappdbg.win32.context_amd64 import *
81    else:
82        from winappdbg.win32.context_i386 import *
83else:
84    warnings.warn("Unknown or unsupported architecture: %s" % arch)
85
86#--- Constants ----------------------------------------------------------------
87
88STILL_ACTIVE = 259
89
90WAIT_TIMEOUT        = 0x102
91WAIT_FAILED         = -1
92WAIT_OBJECT_0       = 0
93
94EXCEPTION_NONCONTINUABLE        = 0x1       # Noncontinuable exception
95EXCEPTION_MAXIMUM_PARAMETERS    = 15        # maximum number of exception parameters
96MAXIMUM_WAIT_OBJECTS            = 64        # Maximum number of wait objects
97MAXIMUM_SUSPEND_COUNT           = 0x7f      # Maximum times thread can be suspended
98
99FORMAT_MESSAGE_ALLOCATE_BUFFER  = 0x00000100
100FORMAT_MESSAGE_FROM_SYSTEM      = 0x00001000
101
102GR_GDIOBJECTS  = 0
103GR_USEROBJECTS = 1
104
105PROCESS_NAME_NATIVE = 1
106
107MAXINTATOM = 0xC000
108
109STD_INPUT_HANDLE  = 0xFFFFFFF6      # (DWORD)-10
110STD_OUTPUT_HANDLE = 0xFFFFFFF5      # (DWORD)-11
111STD_ERROR_HANDLE  = 0xFFFFFFF4      # (DWORD)-12
112
113ATTACH_PARENT_PROCESS = 0xFFFFFFFF  # (DWORD)-1
114
115# LoadLibraryEx constants
116DONT_RESOLVE_DLL_REFERENCES         = 0x00000001
117LOAD_LIBRARY_AS_DATAFILE            = 0x00000002
118LOAD_WITH_ALTERED_SEARCH_PATH       = 0x00000008
119LOAD_IGNORE_CODE_AUTHZ_LEVEL        = 0x00000010
120LOAD_LIBRARY_AS_IMAGE_RESOURCE      = 0x00000020
121LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE  = 0x00000040
122
123# SetSearchPathMode flags
124# TODO I couldn't find these constants :(
125##BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE     = ???
126##BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE    = ???
127##BASE_SEARCH_PATH_PERMANENT                  = ???
128
129# Console control events
130CTRL_C_EVENT        = 0
131CTRL_BREAK_EVENT    = 1
132CTRL_CLOSE_EVENT    = 2
133CTRL_LOGOFF_EVENT   = 5
134CTRL_SHUTDOWN_EVENT = 6
135
136# Heap flags
137HEAP_NO_SERIALIZE           = 0x00000001
138HEAP_GENERATE_EXCEPTIONS    = 0x00000004
139HEAP_ZERO_MEMORY            = 0x00000008
140HEAP_CREATE_ENABLE_EXECUTE  = 0x00040000
141
142# Standard access rights
143DELETE                      = long(0x00010000)
144READ_CONTROL                = long(0x00020000)
145WRITE_DAC                   = long(0x00040000)
146WRITE_OWNER                 = long(0x00080000)
147SYNCHRONIZE                 = long(0x00100000)
148STANDARD_RIGHTS_REQUIRED    = long(0x000F0000)
149STANDARD_RIGHTS_READ        = (READ_CONTROL)
150STANDARD_RIGHTS_WRITE       = (READ_CONTROL)
151STANDARD_RIGHTS_EXECUTE     = (READ_CONTROL)
152STANDARD_RIGHTS_ALL         = long(0x001F0000)
153SPECIFIC_RIGHTS_ALL         = long(0x0000FFFF)
154
155# Mutex access rights
156MUTEX_ALL_ACCESS   = 0x1F0001
157MUTEX_MODIFY_STATE = 1
158
159# Event access rights
160EVENT_ALL_ACCESS   = 0x1F0003
161EVENT_MODIFY_STATE = 2
162
163# Semaphore access rights
164SEMAPHORE_ALL_ACCESS   = 0x1F0003
165SEMAPHORE_MODIFY_STATE = 2
166
167# Timer access rights
168TIMER_ALL_ACCESS   = 0x1F0003
169TIMER_MODIFY_STATE = 2
170TIMER_QUERY_STATE  = 1
171
172# Process access rights for OpenProcess
173PROCESS_TERMINATE                 = 0x0001
174PROCESS_CREATE_THREAD             = 0x0002
175PROCESS_SET_SESSIONID             = 0x0004
176PROCESS_VM_OPERATION              = 0x0008
177PROCESS_VM_READ                   = 0x0010
178PROCESS_VM_WRITE                  = 0x0020
179PROCESS_DUP_HANDLE                = 0x0040
180PROCESS_CREATE_PROCESS            = 0x0080
181PROCESS_SET_QUOTA                 = 0x0100
182PROCESS_SET_INFORMATION           = 0x0200
183PROCESS_QUERY_INFORMATION         = 0x0400
184PROCESS_SUSPEND_RESUME            = 0x0800
185PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
186
187# Thread access rights for OpenThread
188THREAD_TERMINATE                 = 0x0001
189THREAD_SUSPEND_RESUME            = 0x0002
190THREAD_ALERT                     = 0x0004
191THREAD_GET_CONTEXT               = 0x0008
192THREAD_SET_CONTEXT               = 0x0010
193THREAD_SET_INFORMATION           = 0x0020
194THREAD_QUERY_INFORMATION         = 0x0040
195THREAD_SET_THREAD_TOKEN          = 0x0080
196THREAD_IMPERSONATE               = 0x0100
197THREAD_DIRECT_IMPERSONATION      = 0x0200
198THREAD_SET_LIMITED_INFORMATION   = 0x0400
199THREAD_QUERY_LIMITED_INFORMATION = 0x0800
200
201# The values of PROCESS_ALL_ACCESS and THREAD_ALL_ACCESS were changed in Vista/2008
202PROCESS_ALL_ACCESS_NT = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
203PROCESS_ALL_ACCESS_VISTA = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
204THREAD_ALL_ACCESS_NT = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
205THREAD_ALL_ACCESS_VISTA = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
206if NTDDI_VERSION < NTDDI_VISTA:
207    PROCESS_ALL_ACCESS = PROCESS_ALL_ACCESS_NT
208    THREAD_ALL_ACCESS = THREAD_ALL_ACCESS_NT
209else:
210    PROCESS_ALL_ACCESS = PROCESS_ALL_ACCESS_VISTA
211    THREAD_ALL_ACCESS = THREAD_ALL_ACCESS_VISTA
212
213# Process priority classes
214
215IDLE_PRIORITY_CLASS         = 0x00000040
216BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
217NORMAL_PRIORITY_CLASS       = 0x00000020
218ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
219HIGH_PRIORITY_CLASS         = 0x00000080
220REALTIME_PRIORITY_CLASS     = 0x00000100
221
222PROCESS_MODE_BACKGROUND_BEGIN   = 0x00100000
223PROCESS_MODE_BACKGROUND_END     = 0x00200000
224
225# dwCreationFlag values
226
227DEBUG_PROCESS                     = 0x00000001
228DEBUG_ONLY_THIS_PROCESS           = 0x00000002
229CREATE_SUSPENDED                  = 0x00000004    # Threads and processes
230DETACHED_PROCESS                  = 0x00000008
231CREATE_NEW_CONSOLE                = 0x00000010
232NORMAL_PRIORITY_CLASS             = 0x00000020
233IDLE_PRIORITY_CLASS               = 0x00000040
234HIGH_PRIORITY_CLASS               = 0x00000080
235REALTIME_PRIORITY_CLASS           = 0x00000100
236CREATE_NEW_PROCESS_GROUP          = 0x00000200
237CREATE_UNICODE_ENVIRONMENT        = 0x00000400
238CREATE_SEPARATE_WOW_VDM           = 0x00000800
239CREATE_SHARED_WOW_VDM             = 0x00001000
240CREATE_FORCEDOS                   = 0x00002000
241BELOW_NORMAL_PRIORITY_CLASS       = 0x00004000
242ABOVE_NORMAL_PRIORITY_CLASS       = 0x00008000
243INHERIT_PARENT_AFFINITY           = 0x00010000
244STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000    # Threads only
245INHERIT_CALLER_PRIORITY           = 0x00020000    # Deprecated
246CREATE_PROTECTED_PROCESS          = 0x00040000
247EXTENDED_STARTUPINFO_PRESENT      = 0x00080000
248PROCESS_MODE_BACKGROUND_BEGIN     = 0x00100000
249PROCESS_MODE_BACKGROUND_END       = 0x00200000
250CREATE_BREAKAWAY_FROM_JOB         = 0x01000000
251CREATE_PRESERVE_CODE_AUTHZ_LEVEL  = 0x02000000
252CREATE_DEFAULT_ERROR_MODE         = 0x04000000
253CREATE_NO_WINDOW                  = 0x08000000
254PROFILE_USER                      = 0x10000000
255PROFILE_KERNEL                    = 0x20000000
256PROFILE_SERVER                    = 0x40000000
257CREATE_IGNORE_SYSTEM_DEFAULT      = 0x80000000
258
259# Thread priority values
260
261THREAD_BASE_PRIORITY_LOWRT  = 15    # value that gets a thread to LowRealtime-1
262THREAD_BASE_PRIORITY_MAX    = 2     # maximum thread base priority boost
263THREAD_BASE_PRIORITY_MIN    = (-2)  # minimum thread base priority boost
264THREAD_BASE_PRIORITY_IDLE   = (-15) # value that gets a thread to idle
265
266THREAD_PRIORITY_LOWEST          = THREAD_BASE_PRIORITY_MIN
267THREAD_PRIORITY_BELOW_NORMAL    = (THREAD_PRIORITY_LOWEST+1)
268THREAD_PRIORITY_NORMAL          = 0
269THREAD_PRIORITY_HIGHEST         = THREAD_BASE_PRIORITY_MAX
270THREAD_PRIORITY_ABOVE_NORMAL    = (THREAD_PRIORITY_HIGHEST-1)
271THREAD_PRIORITY_ERROR_RETURN    = long(0xFFFFFFFF)
272
273THREAD_PRIORITY_TIME_CRITICAL   = THREAD_BASE_PRIORITY_LOWRT
274THREAD_PRIORITY_IDLE            = THREAD_BASE_PRIORITY_IDLE
275
276# Memory access
277SECTION_QUERY                = 0x0001
278SECTION_MAP_WRITE            = 0x0002
279SECTION_MAP_READ             = 0x0004
280SECTION_MAP_EXECUTE          = 0x0008
281SECTION_EXTEND_SIZE          = 0x0010
282SECTION_MAP_EXECUTE_EXPLICIT = 0x0020 # not included in SECTION_ALL_ACCESS
283
284SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\
285                             SECTION_MAP_WRITE |      \
286                             SECTION_MAP_READ |       \
287                             SECTION_MAP_EXECUTE |    \
288                             SECTION_EXTEND_SIZE)
289PAGE_NOACCESS          = 0x01
290PAGE_READONLY          = 0x02
291PAGE_READWRITE         = 0x04
292PAGE_WRITECOPY         = 0x08
293PAGE_EXECUTE           = 0x10
294PAGE_EXECUTE_READ      = 0x20
295PAGE_EXECUTE_READWRITE = 0x40
296PAGE_EXECUTE_WRITECOPY = 0x80
297PAGE_GUARD            = 0x100
298PAGE_NOCACHE          = 0x200
299PAGE_WRITECOMBINE     = 0x400
300MEM_COMMIT           = 0x1000
301MEM_RESERVE          = 0x2000
302MEM_DECOMMIT         = 0x4000
303MEM_RELEASE          = 0x8000
304MEM_FREE            = 0x10000
305MEM_PRIVATE         = 0x20000
306MEM_MAPPED          = 0x40000
307MEM_RESET           = 0x80000
308MEM_TOP_DOWN       = 0x100000
309MEM_WRITE_WATCH    = 0x200000
310MEM_PHYSICAL       = 0x400000
311MEM_LARGE_PAGES  = 0x20000000
312MEM_4MB_PAGES    = 0x80000000
313SEC_FILE           = 0x800000
314SEC_IMAGE         = 0x1000000
315SEC_RESERVE       = 0x4000000
316SEC_COMMIT        = 0x8000000
317SEC_NOCACHE      = 0x10000000
318SEC_LARGE_PAGES  = 0x80000000
319MEM_IMAGE         = SEC_IMAGE
320WRITE_WATCH_FLAG_RESET = 0x01
321FILE_MAP_ALL_ACCESS = 0xF001F
322
323SECTION_QUERY                   = 0x0001
324SECTION_MAP_WRITE               = 0x0002
325SECTION_MAP_READ                = 0x0004
326SECTION_MAP_EXECUTE             = 0x0008
327SECTION_EXTEND_SIZE             = 0x0010
328SECTION_MAP_EXECUTE_EXPLICIT    = 0x0020 # not included in SECTION_ALL_ACCESS
329
330SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\
331                 SECTION_MAP_WRITE |      \
332                 SECTION_MAP_READ |       \
333                 SECTION_MAP_EXECUTE |    \
334                 SECTION_EXTEND_SIZE)
335
336FILE_MAP_COPY       = SECTION_QUERY
337FILE_MAP_WRITE      = SECTION_MAP_WRITE
338FILE_MAP_READ       = SECTION_MAP_READ
339FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
340FILE_MAP_EXECUTE    = SECTION_MAP_EXECUTE_EXPLICIT  # not included in FILE_MAP_ALL_ACCESS
341
342GENERIC_READ                     = 0x80000000
343GENERIC_WRITE                    = 0x40000000
344GENERIC_EXECUTE                  = 0x20000000
345GENERIC_ALL                      = 0x10000000
346
347FILE_SHARE_READ                  = 0x00000001
348FILE_SHARE_WRITE                 = 0x00000002
349FILE_SHARE_DELETE                = 0x00000004
350
351CREATE_NEW                       = 1
352CREATE_ALWAYS                    = 2
353OPEN_EXISTING                    = 3
354OPEN_ALWAYS                      = 4
355TRUNCATE_EXISTING                = 5
356
357FILE_ATTRIBUTE_READONLY          = 0x00000001
358FILE_ATTRIBUTE_NORMAL            = 0x00000080
359FILE_ATTRIBUTE_TEMPORARY         = 0x00000100
360
361FILE_FLAG_WRITE_THROUGH          = 0x80000000
362FILE_FLAG_NO_BUFFERING           = 0x20000000
363FILE_FLAG_RANDOM_ACCESS          = 0x10000000
364FILE_FLAG_SEQUENTIAL_SCAN        = 0x08000000
365FILE_FLAG_DELETE_ON_CLOSE        = 0x04000000
366FILE_FLAG_OVERLAPPED             = 0x40000000
367
368FILE_ATTRIBUTE_READONLY          = 0x00000001
369FILE_ATTRIBUTE_HIDDEN            = 0x00000002
370FILE_ATTRIBUTE_SYSTEM            = 0x00000004
371FILE_ATTRIBUTE_DIRECTORY         = 0x00000010
372FILE_ATTRIBUTE_ARCHIVE           = 0x00000020
373FILE_ATTRIBUTE_DEVICE            = 0x00000040
374FILE_ATTRIBUTE_NORMAL            = 0x00000080
375FILE_ATTRIBUTE_TEMPORARY         = 0x00000100
376
377# Debug events
378EXCEPTION_DEBUG_EVENT       = 1
379CREATE_THREAD_DEBUG_EVENT   = 2
380CREATE_PROCESS_DEBUG_EVENT  = 3
381EXIT_THREAD_DEBUG_EVENT     = 4
382EXIT_PROCESS_DEBUG_EVENT    = 5
383LOAD_DLL_DEBUG_EVENT        = 6
384UNLOAD_DLL_DEBUG_EVENT      = 7
385OUTPUT_DEBUG_STRING_EVENT   = 8
386RIP_EVENT                   = 9
387
388# Debug status codes (ContinueDebugEvent)
389DBG_EXCEPTION_HANDLED           = long(0x00010001)
390DBG_CONTINUE                    = long(0x00010002)
391DBG_REPLY_LATER                 = long(0x40010001)
392DBG_UNABLE_TO_PROVIDE_HANDLE    = long(0x40010002)
393DBG_TERMINATE_THREAD            = long(0x40010003)
394DBG_TERMINATE_PROCESS           = long(0x40010004)
395DBG_CONTROL_C                   = long(0x40010005)
396DBG_PRINTEXCEPTION_C            = long(0x40010006)
397DBG_RIPEXCEPTION                = long(0x40010007)
398DBG_CONTROL_BREAK               = long(0x40010008)
399DBG_COMMAND_EXCEPTION           = long(0x40010009)
400DBG_EXCEPTION_NOT_HANDLED       = long(0x80010001)
401DBG_NO_STATE_CHANGE             = long(0xC0010001)
402DBG_APP_NOT_IDLE                = long(0xC0010002)
403
404# Status codes
405STATUS_WAIT_0                   = long(0x00000000)
406STATUS_ABANDONED_WAIT_0         = long(0x00000080)
407STATUS_USER_APC                 = long(0x000000C0)
408STATUS_TIMEOUT                  = long(0x00000102)
409STATUS_PENDING                  = long(0x00000103)
410STATUS_SEGMENT_NOTIFICATION     = long(0x40000005)
411STATUS_GUARD_PAGE_VIOLATION     = long(0x80000001)
412STATUS_DATATYPE_MISALIGNMENT    = long(0x80000002)
413STATUS_BREAKPOINT               = long(0x80000003)
414STATUS_SINGLE_STEP              = long(0x80000004)
415STATUS_INVALID_INFO_CLASS       = long(0xC0000003)
416STATUS_ACCESS_VIOLATION         = long(0xC0000005)
417STATUS_IN_PAGE_ERROR            = long(0xC0000006)
418STATUS_INVALID_HANDLE           = long(0xC0000008)
419STATUS_NO_MEMORY                = long(0xC0000017)
420STATUS_ILLEGAL_INSTRUCTION      = long(0xC000001D)
421STATUS_NONCONTINUABLE_EXCEPTION = long(0xC0000025)
422STATUS_INVALID_DISPOSITION      = long(0xC0000026)
423STATUS_ARRAY_BOUNDS_EXCEEDED    = long(0xC000008C)
424STATUS_FLOAT_DENORMAL_OPERAND   = long(0xC000008D)
425STATUS_FLOAT_DIVIDE_BY_ZERO     = long(0xC000008E)
426STATUS_FLOAT_INEXACT_RESULT     = long(0xC000008F)
427STATUS_FLOAT_INVALID_OPERATION  = long(0xC0000090)
428STATUS_FLOAT_OVERFLOW           = long(0xC0000091)
429STATUS_FLOAT_STACK_CHECK        = long(0xC0000092)
430STATUS_FLOAT_UNDERFLOW          = long(0xC0000093)
431STATUS_INTEGER_DIVIDE_BY_ZERO   = long(0xC0000094)
432STATUS_INTEGER_OVERFLOW         = long(0xC0000095)
433STATUS_PRIVILEGED_INSTRUCTION   = long(0xC0000096)
434STATUS_STACK_OVERFLOW           = long(0xC00000FD)
435STATUS_CONTROL_C_EXIT           = long(0xC000013A)
436STATUS_FLOAT_MULTIPLE_FAULTS    = long(0xC00002B4)
437STATUS_FLOAT_MULTIPLE_TRAPS     = long(0xC00002B5)
438STATUS_REG_NAT_CONSUMPTION      = long(0xC00002C9)
439STATUS_SXS_EARLY_DEACTIVATION   = long(0xC015000F)
440STATUS_SXS_INVALID_DEACTIVATION = long(0xC0150010)
441
442STATUS_STACK_BUFFER_OVERRUN     = long(0xC0000409)
443STATUS_WX86_BREAKPOINT          = long(0x4000001F)
444STATUS_HEAP_CORRUPTION          = long(0xC0000374)
445
446STATUS_POSSIBLE_DEADLOCK        = long(0xC0000194)
447
448STATUS_UNWIND_CONSOLIDATE       = long(0x80000029)
449
450# Exception codes
451
452EXCEPTION_ACCESS_VIOLATION          = STATUS_ACCESS_VIOLATION
453EXCEPTION_ARRAY_BOUNDS_EXCEEDED     = STATUS_ARRAY_BOUNDS_EXCEEDED
454EXCEPTION_BREAKPOINT                = STATUS_BREAKPOINT
455EXCEPTION_DATATYPE_MISALIGNMENT     = STATUS_DATATYPE_MISALIGNMENT
456EXCEPTION_FLT_DENORMAL_OPERAND      = STATUS_FLOAT_DENORMAL_OPERAND
457EXCEPTION_FLT_DIVIDE_BY_ZERO        = STATUS_FLOAT_DIVIDE_BY_ZERO
458EXCEPTION_FLT_INEXACT_RESULT        = STATUS_FLOAT_INEXACT_RESULT
459EXCEPTION_FLT_INVALID_OPERATION     = STATUS_FLOAT_INVALID_OPERATION
460EXCEPTION_FLT_OVERFLOW              = STATUS_FLOAT_OVERFLOW
461EXCEPTION_FLT_STACK_CHECK           = STATUS_FLOAT_STACK_CHECK
462EXCEPTION_FLT_UNDERFLOW             = STATUS_FLOAT_UNDERFLOW
463EXCEPTION_ILLEGAL_INSTRUCTION       = STATUS_ILLEGAL_INSTRUCTION
464EXCEPTION_IN_PAGE_ERROR             = STATUS_IN_PAGE_ERROR
465EXCEPTION_INT_DIVIDE_BY_ZERO        = STATUS_INTEGER_DIVIDE_BY_ZERO
466EXCEPTION_INT_OVERFLOW              = STATUS_INTEGER_OVERFLOW
467EXCEPTION_INVALID_DISPOSITION       = STATUS_INVALID_DISPOSITION
468EXCEPTION_NONCONTINUABLE_EXCEPTION  = STATUS_NONCONTINUABLE_EXCEPTION
469EXCEPTION_PRIV_INSTRUCTION          = STATUS_PRIVILEGED_INSTRUCTION
470EXCEPTION_SINGLE_STEP               = STATUS_SINGLE_STEP
471EXCEPTION_STACK_OVERFLOW            = STATUS_STACK_OVERFLOW
472
473EXCEPTION_GUARD_PAGE                = STATUS_GUARD_PAGE_VIOLATION
474EXCEPTION_INVALID_HANDLE            = STATUS_INVALID_HANDLE
475EXCEPTION_POSSIBLE_DEADLOCK         = STATUS_POSSIBLE_DEADLOCK
476EXCEPTION_WX86_BREAKPOINT           = STATUS_WX86_BREAKPOINT
477
478CONTROL_C_EXIT                      = STATUS_CONTROL_C_EXIT
479
480DBG_CONTROL_C                       = long(0x40010005)
481MS_VC_EXCEPTION                     = long(0x406D1388)
482
483# Access violation types
484ACCESS_VIOLATION_TYPE_READ      = EXCEPTION_READ_FAULT
485ACCESS_VIOLATION_TYPE_WRITE     = EXCEPTION_WRITE_FAULT
486ACCESS_VIOLATION_TYPE_DEP       = EXCEPTION_EXECUTE_FAULT
487
488# RIP event types
489SLE_ERROR      = 1
490SLE_MINORERROR = 2
491SLE_WARNING    = 3
492
493# DuplicateHandle constants
494DUPLICATE_CLOSE_SOURCE      = 0x00000001
495DUPLICATE_SAME_ACCESS       = 0x00000002
496
497# GetFinalPathNameByHandle constants
498FILE_NAME_NORMALIZED        = 0x0
499FILE_NAME_OPENED            = 0x8
500VOLUME_NAME_DOS             = 0x0
501VOLUME_NAME_GUID            = 0x1
502VOLUME_NAME_NONE            = 0x4
503VOLUME_NAME_NT              = 0x2
504
505# GetProductInfo constants
506PRODUCT_BUSINESS = 0x00000006
507PRODUCT_BUSINESS_N = 0x00000010
508PRODUCT_CLUSTER_SERVER = 0x00000012
509PRODUCT_DATACENTER_SERVER = 0x00000008
510PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C
511PRODUCT_DATACENTER_SERVER_CORE_V = 0x00000027
512PRODUCT_DATACENTER_SERVER_V = 0x00000025
513PRODUCT_ENTERPRISE = 0x00000004
514PRODUCT_ENTERPRISE_E = 0x00000046
515PRODUCT_ENTERPRISE_N = 0x0000001B
516PRODUCT_ENTERPRISE_SERVER = 0x0000000A
517PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E
518PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029
519PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F
520PRODUCT_ENTERPRISE_SERVER_V = 0x00000026
521PRODUCT_HOME_BASIC = 0x00000002
522PRODUCT_HOME_BASIC_E = 0x00000043
523PRODUCT_HOME_BASIC_N = 0x00000005
524PRODUCT_HOME_PREMIUM = 0x00000003
525PRODUCT_HOME_PREMIUM_E = 0x00000044
526PRODUCT_HOME_PREMIUM_N = 0x0000001A
527PRODUCT_HYPERV = 0x0000002A
528PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E
529PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020
530PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F
531PRODUCT_PROFESSIONAL = 0x00000030
532PRODUCT_PROFESSIONAL_E = 0x00000045
533PRODUCT_PROFESSIONAL_N = 0x00000031
534PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018
535PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023
536PRODUCT_SERVER_FOUNDATION = 0x00000021
537PRODUCT_SMALLBUSINESS_SERVER = 0x00000009
538PRODUCT_STANDARD_SERVER = 0x00000007
539PRODUCT_STANDARD_SERVER_CORE = 0x0000000D
540PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028
541PRODUCT_STANDARD_SERVER_V = 0x00000024
542PRODUCT_STARTER = 0x0000000B
543PRODUCT_STARTER_E = 0x00000042
544PRODUCT_STARTER_N = 0x0000002F
545PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017
546PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014
547PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015
548PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016
549PRODUCT_UNDEFINED = 0x00000000
550PRODUCT_UNLICENSED = 0xABCDABCD
551PRODUCT_ULTIMATE = 0x00000001
552PRODUCT_ULTIMATE_E = 0x00000047
553PRODUCT_ULTIMATE_N = 0x0000001C
554PRODUCT_WEB_SERVER = 0x00000011
555PRODUCT_WEB_SERVER_CORE = 0x0000001D
556
557# DEP policy flags
558PROCESS_DEP_ENABLE = 1
559PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION = 2
560
561# Error modes
562SEM_FAILCRITICALERRORS      = 0x001
563SEM_NOGPFAULTERRORBOX       = 0x002
564SEM_NOALIGNMENTFAULTEXCEPT  = 0x004
565SEM_NOOPENFILEERRORBOX      = 0x800
566
567# GetHandleInformation / SetHandleInformation
568HANDLE_FLAG_INHERIT             = 0x00000001
569HANDLE_FLAG_PROTECT_FROM_CLOSE  = 0x00000002
570
571#--- Handle wrappers ----------------------------------------------------------
572
573class Handle (object):
574    """
575    Encapsulates Win32 handles to avoid leaking them.
576
577    @type inherit: bool
578    @ivar inherit: C{True} if the handle is to be inherited by child processes,
579        C{False} otherwise.
580
581    @type protectFromClose: bool
582    @ivar protectFromClose: Set to C{True} to prevent the handle from being
583        closed. Must be set to C{False} before you're done using the handle,
584        or it will be left open until the debugger exits. Use with care!
585
586    @see:
587        L{ProcessHandle}, L{ThreadHandle}, L{FileHandle}, L{SnapshotHandle}
588    """
589
590    # XXX DEBUG
591    # When this private flag is True each Handle will print a message to
592    # standard output when it's created and destroyed. This is useful for
593    # detecting handle leaks within WinAppDbg itself.
594    __bLeakDetection = False
595
596    def __init__(self, aHandle = None, bOwnership = True):
597        """
598        @type  aHandle: int
599        @param aHandle: Win32 handle value.
600
601        @type  bOwnership: bool
602        @param bOwnership:
603           C{True} if we own the handle and we need to close it.
604           C{False} if someone else will be calling L{CloseHandle}.
605        """
606        super(Handle, self).__init__()
607        self._value     = self._normalize(aHandle)
608        self.bOwnership = bOwnership
609        if Handle.__bLeakDetection:     # XXX DEBUG
610            print("INIT HANDLE (%r) %r" % (self.value, self))
611
612    @property
613    def value(self):
614        return self._value
615
616    def __del__(self):
617        """
618        Closes the Win32 handle when the Python object is destroyed.
619        """
620        try:
621            if Handle.__bLeakDetection:     # XXX DEBUG
622                print("DEL HANDLE %r" % self)
623            self.close()
624        except Exception:
625            pass
626
627    def __enter__(self):
628        """
629        Compatibility with the "C{with}" Python statement.
630        """
631        if Handle.__bLeakDetection:     # XXX DEBUG
632            print("ENTER HANDLE %r" % self)
633        return self
634
635    def __exit__(self, type, value, traceback):
636        """
637        Compatibility with the "C{with}" Python statement.
638        """
639        if Handle.__bLeakDetection:     # XXX DEBUG
640            print("EXIT HANDLE %r" % self)
641        try:
642            self.close()
643        except Exception:
644            pass
645
646    def __copy__(self):
647        """
648        Duplicates the Win32 handle when copying the Python object.
649
650        @rtype:  L{Handle}
651        @return: A new handle to the same Win32 object.
652        """
653        return self.dup()
654
655    def __deepcopy__(self):
656        """
657        Duplicates the Win32 handle when copying the Python object.
658
659        @rtype:  L{Handle}
660        @return: A new handle to the same win32 object.
661        """
662        return self.dup()
663
664    @property
665    def _as_parameter_(self):
666        """
667        Compatibility with ctypes.
668        Allows passing transparently a Handle object to an API call.
669        """
670        return HANDLE(self.value)
671
672    @staticmethod
673    def from_param(value):
674        """
675        Compatibility with ctypes.
676        Allows passing transparently a Handle object to an API call.
677
678        @type  value: int
679        @param value: Numeric handle value.
680        """
681        return HANDLE(value)
682
683    def close(self):
684        """
685        Closes the Win32 handle.
686        """
687        if self.bOwnership and self.value not in (None, INVALID_HANDLE_VALUE):
688            if Handle.__bLeakDetection:     # XXX DEBUG
689                print("CLOSE HANDLE (%d) %r" % (self.value, self))
690            try:
691                self._close()
692            finally:
693                self._value = None
694
695    def _close(self):
696        """
697        Low-level close method.
698        This is a private method, do not call it.
699        """
700        CloseHandle(self.value)
701
702    def dup(self):
703        """
704        @rtype:  L{Handle}
705        @return: A new handle to the same Win32 object.
706        """
707        if self.value is None:
708            raise ValueError("Closed handles can't be duplicated!")
709        new_handle = DuplicateHandle(self.value)
710        if Handle.__bLeakDetection:     # XXX DEBUG
711            print("DUP HANDLE (%d -> %d) %r %r" % \
712                            (self.value, new_handle.value, self, new_handle))
713        return new_handle
714
715    @staticmethod
716    def _normalize(value):
717        """
718        Normalize handle values.
719        """
720        if hasattr(value, 'value'):
721            value = value.value
722        if value is not None:
723            value = long(value)
724        return value
725
726    def wait(self, dwMilliseconds = None):
727        """
728        Wait for the Win32 object to be signaled.
729
730        @type  dwMilliseconds: int
731        @param dwMilliseconds: (Optional) Timeout value in milliseconds.
732            Use C{INFINITE} or C{None} for no timeout.
733        """
734        if self.value is None:
735            raise ValueError("Handle is already closed!")
736        if dwMilliseconds is None:
737            dwMilliseconds = INFINITE
738        r = WaitForSingleObject(self.value, dwMilliseconds)
739        if r != WAIT_OBJECT_0:
740            raise ctypes.WinError(r)
741
742    def __repr__(self):
743        return '<%s: %s>' % (self.__class__.__name__, self.value)
744
745    def __get_inherit(self):
746        if self.value is None:
747            raise ValueError("Handle is already closed!")
748        return bool( GetHandleInformation(self.value) & HANDLE_FLAG_INHERIT )
749
750    def __set_inherit(self, value):
751        if self.value is None:
752            raise ValueError("Handle is already closed!")
753        flag = (0, HANDLE_FLAG_INHERIT)[ bool(value) ]
754        SetHandleInformation(self.value, flag, flag)
755
756    inherit = property(__get_inherit, __set_inherit)
757
758    def __get_protectFromClose(self):
759        if self.value is None:
760            raise ValueError("Handle is already closed!")
761        return bool( GetHandleInformation(self.value) & HANDLE_FLAG_PROTECT_FROM_CLOSE )
762
763    def __set_protectFromClose(self, value):
764        if self.value is None:
765            raise ValueError("Handle is already closed!")
766        flag = (0, HANDLE_FLAG_PROTECT_FROM_CLOSE)[ bool(value) ]
767        SetHandleInformation(self.value, flag, flag)
768
769    protectFromClose = property(__get_protectFromClose, __set_protectFromClose)
770
771class UserModeHandle (Handle):
772    """
773    Base class for non-kernel handles. Generally this means they are closed
774    by special Win32 API functions instead of CloseHandle() and some standard
775    operations (synchronizing, duplicating, inheritance) are not supported.
776
777    @type _TYPE: C type
778    @cvar _TYPE: C type to translate this handle to.
779        Subclasses should override this.
780        Defaults to L{HANDLE}.
781    """
782
783    # Subclasses should override this.
784    _TYPE = HANDLE
785
786    # This method must be implemented by subclasses.
787    def _close(self):
788        raise NotImplementedError()
789
790    # Translation to C type.
791    @property
792    def _as_parameter_(self):
793        return self._TYPE(self.value)
794
795    # Translation to C type.
796    @staticmethod
797    def from_param(value):
798        return self._TYPE(self.value)
799
800    # Operation not supported.
801    @property
802    def inherit(self):
803        return False
804
805    # Operation not supported.
806    @property
807    def protectFromClose(self):
808        return False
809
810    # Operation not supported.
811    def dup(self):
812        raise NotImplementedError()
813
814    # Operation not supported.
815    def wait(self, dwMilliseconds = None):
816        raise NotImplementedError()
817
818class ProcessHandle (Handle):
819    """
820    Win32 process handle.
821
822    @type dwAccess: int
823    @ivar dwAccess: Current access flags to this handle.
824            This is the same value passed to L{OpenProcess}.
825            Can only be C{None} if C{aHandle} is also C{None}.
826            Defaults to L{PROCESS_ALL_ACCESS}.
827
828    @see: L{Handle}
829    """
830
831    def __init__(self, aHandle = None, bOwnership = True,
832                       dwAccess = PROCESS_ALL_ACCESS):
833        """
834        @type  aHandle: int
835        @param aHandle: Win32 handle value.
836
837        @type  bOwnership: bool
838        @param bOwnership:
839           C{True} if we own the handle and we need to close it.
840           C{False} if someone else will be calling L{CloseHandle}.
841
842        @type  dwAccess: int
843        @param dwAccess: Current access flags to this handle.
844            This is the same value passed to L{OpenProcess}.
845            Can only be C{None} if C{aHandle} is also C{None}.
846            Defaults to L{PROCESS_ALL_ACCESS}.
847        """
848        super(ProcessHandle, self).__init__(aHandle, bOwnership)
849        self.dwAccess = dwAccess
850        if aHandle is not None and dwAccess is None:
851            msg = "Missing access flags for process handle: %x" % aHandle
852            raise TypeError(msg)
853
854    def get_pid(self):
855        """
856        @rtype:  int
857        @return: Process global ID.
858        """
859        return GetProcessId(self.value)
860
861class ThreadHandle (Handle):
862    """
863    Win32 thread handle.
864
865    @type dwAccess: int
866    @ivar dwAccess: Current access flags to this handle.
867            This is the same value passed to L{OpenThread}.
868            Can only be C{None} if C{aHandle} is also C{None}.
869            Defaults to L{THREAD_ALL_ACCESS}.
870
871    @see: L{Handle}
872    """
873
874    def __init__(self, aHandle = None, bOwnership = True,
875                       dwAccess = THREAD_ALL_ACCESS):
876        """
877        @type  aHandle: int
878        @param aHandle: Win32 handle value.
879
880        @type  bOwnership: bool
881        @param bOwnership:
882           C{True} if we own the handle and we need to close it.
883           C{False} if someone else will be calling L{CloseHandle}.
884
885        @type  dwAccess: int
886        @param dwAccess: Current access flags to this handle.
887            This is the same value passed to L{OpenThread}.
888            Can only be C{None} if C{aHandle} is also C{None}.
889            Defaults to L{THREAD_ALL_ACCESS}.
890        """
891        super(ThreadHandle, self).__init__(aHandle, bOwnership)
892        self.dwAccess = dwAccess
893        if aHandle is not None and dwAccess is None:
894            msg = "Missing access flags for thread handle: %x" % aHandle
895            raise TypeError(msg)
896
897    def get_tid(self):
898        """
899        @rtype:  int
900        @return: Thread global ID.
901        """
902        return GetThreadId(self.value)
903
904class FileHandle (Handle):
905    """
906    Win32 file handle.
907
908    @see: L{Handle}
909    """
910
911    def get_filename(self):
912        """
913        @rtype:  None or str
914        @return: Name of the open file, or C{None} if unavailable.
915        """
916        #
917        # XXX BUG
918        #
919        # This code truncates the first two bytes of the path.
920        # It seems to be the expected behavior of NtQueryInformationFile.
921        #
922        # My guess is it only returns the NT pathname, without the device name.
923        # It's like dropping the drive letter in a Win32 pathname.
924        #
925        # Note that using the "official" GetFileInformationByHandleEx
926        # API introduced in Vista doesn't change the results!
927        #
928        dwBufferSize      = 0x1004
929        lpFileInformation = ctypes.create_string_buffer(dwBufferSize)
930        try:
931            GetFileInformationByHandleEx(self.value,
932                                        FILE_INFO_BY_HANDLE_CLASS.FileNameInfo,
933                                        lpFileInformation, dwBufferSize)
934        except AttributeError:
935            from winappdbg.win32.ntdll import NtQueryInformationFile, \
936                              FileNameInformation, \
937                              FILE_NAME_INFORMATION
938            NtQueryInformationFile(self.value,
939                                   FileNameInformation,
940                                   lpFileInformation,
941                                   dwBufferSize)
942        FileName = compat.unicode(lpFileInformation.raw[sizeof(DWORD):], 'U16')
943        FileName = ctypes.create_unicode_buffer(FileName).value
944        if not FileName:
945            FileName = None
946        elif FileName[1:2] != ':':
947            # When the drive letter is missing, we'll assume SYSTEMROOT.
948            # Not a good solution but it could be worse.
949            import os
950            FileName = os.environ['SYSTEMROOT'][:2] + FileName
951        return FileName
952
953class FileMappingHandle (Handle):
954    """
955    File mapping handle.
956
957    @see: L{Handle}
958    """
959    pass
960
961# XXX maybe add functions related to the toolhelp snapshots here?
962class SnapshotHandle (Handle):
963    """
964    Toolhelp32 snapshot handle.
965
966    @see: L{Handle}
967    """
968    pass
969
970#--- Structure wrappers -------------------------------------------------------
971
972class ProcessInformation (object):
973    """
974    Process information object returned by L{CreateProcess}.
975    """
976
977    def __init__(self, pi):
978        self.hProcess    = ProcessHandle(pi.hProcess)
979        self.hThread     = ThreadHandle(pi.hThread)
980        self.dwProcessId = pi.dwProcessId
981        self.dwThreadId  = pi.dwThreadId
982
983# Don't psyco-optimize this class because it needs to be serialized.
984class MemoryBasicInformation (object):
985    """
986    Memory information object returned by L{VirtualQueryEx}.
987    """
988
989    READABLE = (
990                PAGE_EXECUTE_READ       |
991                PAGE_EXECUTE_READWRITE  |
992                PAGE_EXECUTE_WRITECOPY  |
993                PAGE_READONLY           |
994                PAGE_READWRITE          |
995                PAGE_WRITECOPY
996    )
997
998    WRITEABLE = (
999                PAGE_EXECUTE_READWRITE  |
1000                PAGE_EXECUTE_WRITECOPY  |
1001                PAGE_READWRITE          |
1002                PAGE_WRITECOPY
1003    )
1004
1005    COPY_ON_WRITE = (
1006                PAGE_EXECUTE_WRITECOPY  |
1007                PAGE_WRITECOPY
1008    )
1009
1010    EXECUTABLE = (
1011                PAGE_EXECUTE            |
1012                PAGE_EXECUTE_READ       |
1013                PAGE_EXECUTE_READWRITE  |
1014                PAGE_EXECUTE_WRITECOPY
1015    )
1016
1017    EXECUTABLE_AND_WRITEABLE = (
1018                PAGE_EXECUTE_READWRITE  |
1019                PAGE_EXECUTE_WRITECOPY
1020    )
1021
1022    def __init__(self, mbi=None):
1023        """
1024        @type  mbi: L{MEMORY_BASIC_INFORMATION} or L{MemoryBasicInformation}
1025        @param mbi: Either a L{MEMORY_BASIC_INFORMATION} structure or another
1026            L{MemoryBasicInformation} instance.
1027        """
1028        if mbi is None:
1029            self.BaseAddress        = None
1030            self.AllocationBase     = None
1031            self.AllocationProtect  = None
1032            self.RegionSize         = None
1033            self.State              = None
1034            self.Protect            = None
1035            self.Type               = None
1036        else:
1037            self.BaseAddress        = mbi.BaseAddress
1038            self.AllocationBase     = mbi.AllocationBase
1039            self.AllocationProtect  = mbi.AllocationProtect
1040            self.RegionSize         = mbi.RegionSize
1041            self.State              = mbi.State
1042            self.Protect            = mbi.Protect
1043            self.Type               = mbi.Type
1044
1045            # Only used when copying MemoryBasicInformation objects, instead of
1046            # instancing them from a MEMORY_BASIC_INFORMATION structure.
1047            if hasattr(mbi, 'content'):
1048                self.content = mbi.content
1049            if hasattr(mbi, 'filename'):
1050                self.content = mbi.filename
1051
1052    def __contains__(self, address):
1053        """
1054        Test if the given memory address falls within this memory region.
1055
1056        @type  address: int
1057        @param address: Memory address to test.
1058
1059        @rtype:  bool
1060        @return: C{True} if the given memory address falls within this memory
1061            region, C{False} otherwise.
1062        """
1063        return self.BaseAddress <= address < (self.BaseAddress + self.RegionSize)
1064
1065    def is_free(self):
1066        """
1067        @rtype:  bool
1068        @return: C{True} if the memory in this region is free.
1069        """
1070        return self.State == MEM_FREE
1071
1072    def is_reserved(self):
1073        """
1074        @rtype:  bool
1075        @return: C{True} if the memory in this region is reserved.
1076        """
1077        return self.State == MEM_RESERVE
1078
1079    def is_commited(self):
1080        """
1081        @rtype:  bool
1082        @return: C{True} if the memory in this region is commited.
1083        """
1084        return self.State == MEM_COMMIT
1085
1086    def is_image(self):
1087        """
1088        @rtype:  bool
1089        @return: C{True} if the memory in this region belongs to an executable
1090            image.
1091        """
1092        return self.Type == MEM_IMAGE
1093
1094    def is_mapped(self):
1095        """
1096        @rtype:  bool
1097        @return: C{True} if the memory in this region belongs to a mapped file.
1098        """
1099        return self.Type == MEM_MAPPED
1100
1101    def is_private(self):
1102        """
1103        @rtype:  bool
1104        @return: C{True} if the memory in this region is private.
1105        """
1106        return self.Type == MEM_PRIVATE
1107
1108    def is_guard(self):
1109        """
1110        @rtype:  bool
1111        @return: C{True} if all pages in this region are guard pages.
1112        """
1113        return self.is_commited() and bool(self.Protect & PAGE_GUARD)
1114
1115    def has_content(self):
1116        """
1117        @rtype:  bool
1118        @return: C{True} if the memory in this region has any data in it.
1119        """
1120        return self.is_commited() and not bool(self.Protect & (PAGE_GUARD | PAGE_NOACCESS))
1121
1122    def is_readable(self):
1123        """
1124        @rtype:  bool
1125        @return: C{True} if all pages in this region are readable.
1126        """
1127        return self.has_content() and bool(self.Protect & self.READABLE)
1128
1129    def is_writeable(self):
1130        """
1131        @rtype:  bool
1132        @return: C{True} if all pages in this region are writeable.
1133        """
1134        return self.has_content() and bool(self.Protect & self.WRITEABLE)
1135
1136    def is_copy_on_write(self):
1137        """
1138        @rtype:  bool
1139        @return: C{True} if all pages in this region are marked as
1140            copy-on-write. This means the pages are writeable, but changes
1141            are not propagated to disk.
1142        @note:
1143            Tipically data sections in executable images are marked like this.
1144        """
1145        return self.has_content() and bool(self.Protect & self.COPY_ON_WRITE)
1146
1147    def is_executable(self):
1148        """
1149        @rtype:  bool
1150        @return: C{True} if all pages in this region are executable.
1151        @note: Executable pages are always readable.
1152        """
1153        return self.has_content() and bool(self.Protect & self.EXECUTABLE)
1154
1155    def is_executable_and_writeable(self):
1156        """
1157        @rtype:  bool
1158        @return: C{True} if all pages in this region are executable and
1159            writeable.
1160        @note: The presence of such pages make memory corruption
1161            vulnerabilities much easier to exploit.
1162        """
1163        return self.has_content() and bool(self.Protect & self.EXECUTABLE_AND_WRITEABLE)
1164
1165class ProcThreadAttributeList (object):
1166    """
1167    Extended process and thread attribute support.
1168
1169    To be used with L{STARTUPINFOEX}.
1170    Only available for Windows Vista and above.
1171
1172    @type AttributeList: list of tuple( int, ctypes-compatible object )
1173    @ivar AttributeList: List of (Attribute, Value) pairs.
1174
1175    @type AttributeListBuffer: L{LPPROC_THREAD_ATTRIBUTE_LIST}
1176    @ivar AttributeListBuffer: Memory buffer used to store the attribute list.
1177        L{InitializeProcThreadAttributeList},
1178        L{UpdateProcThreadAttribute},
1179        L{DeleteProcThreadAttributeList} and
1180        L{STARTUPINFOEX}.
1181    """
1182
1183    def __init__(self, AttributeList):
1184        """
1185        @type  AttributeList: list of tuple( int, ctypes-compatible object )
1186        @param AttributeList: List of (Attribute, Value) pairs.
1187        """
1188        self.AttributeList = AttributeList
1189        self.AttributeListBuffer = InitializeProcThreadAttributeList(
1190                                                            len(AttributeList))
1191        try:
1192            for Attribute, Value in AttributeList:
1193                UpdateProcThreadAttribute(self.AttributeListBuffer,
1194                                          Attribute, Value)
1195        except:
1196            ProcThreadAttributeList.__del__(self)
1197            raise
1198
1199    def __del__(self):
1200        try:
1201            DeleteProcThreadAttributeList(self.AttributeListBuffer)
1202            del self.AttributeListBuffer
1203        except Exception:
1204            pass
1205
1206    def __copy__(self):
1207        return self.__deepcopy__()
1208
1209    def __deepcopy__(self):
1210        return self.__class__(self.AttributeList)
1211
1212    @property
1213    def value(self):
1214        return ctypes.cast(ctypes.pointer(self.AttributeListBuffer), LPVOID)
1215
1216    @property
1217    def _as_parameter_(self):
1218        return self.value
1219
1220    # XXX TODO
1221    @staticmethod
1222    def from_param(value):
1223        raise NotImplementedError()
1224
1225#--- OVERLAPPED structure -----------------------------------------------------
1226
1227# typedef struct _OVERLAPPED {
1228#   ULONG_PTR Internal;
1229#   ULONG_PTR InternalHigh;
1230#   union {
1231#     struct {
1232#       DWORD Offset;
1233#       DWORD OffsetHigh;
1234#     } ;
1235#     PVOID Pointer;
1236#   } ;
1237#   HANDLE    hEvent;
1238# }OVERLAPPED, *LPOVERLAPPED;
1239class _OVERLAPPED_STRUCT(Structure):
1240    _fields_ = [
1241        ('Offset',          DWORD),
1242        ('OffsetHigh',      DWORD),
1243    ]
1244class _OVERLAPPED_UNION(Union):
1245    _fields_ = [
1246        ('s',               _OVERLAPPED_STRUCT),
1247        ('Pointer',         PVOID),
1248    ]
1249class OVERLAPPED(Structure):
1250    _fields_ = [
1251        ('Internal',        ULONG_PTR),
1252        ('InternalHigh',    ULONG_PTR),
1253        ('u',               _OVERLAPPED_UNION),
1254        ('hEvent',          HANDLE),
1255    ]
1256LPOVERLAPPED = POINTER(OVERLAPPED)
1257
1258#--- SECURITY_ATTRIBUTES structure --------------------------------------------
1259
1260# typedef struct _SECURITY_ATTRIBUTES {
1261#     DWORD nLength;
1262#     LPVOID lpSecurityDescriptor;
1263#     BOOL bInheritHandle;
1264# } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
1265class SECURITY_ATTRIBUTES(Structure):
1266    _fields_ = [
1267        ('nLength',                 DWORD),
1268        ('lpSecurityDescriptor',    LPVOID),
1269        ('bInheritHandle',          BOOL),
1270    ]
1271LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
1272
1273# --- Extended process and thread attribute support ---------------------------
1274
1275PPROC_THREAD_ATTRIBUTE_LIST  = LPVOID
1276LPPROC_THREAD_ATTRIBUTE_LIST = PPROC_THREAD_ATTRIBUTE_LIST
1277
1278PROC_THREAD_ATTRIBUTE_NUMBER   = 0x0000FFFF
1279PROC_THREAD_ATTRIBUTE_THREAD   = 0x00010000  # Attribute may be used with thread creation
1280PROC_THREAD_ATTRIBUTE_INPUT    = 0x00020000  # Attribute is input only
1281PROC_THREAD_ATTRIBUTE_ADDITIVE = 0x00040000  # Attribute may be "accumulated," e.g. bitmasks, counters, etc.
1282
1283# PROC_THREAD_ATTRIBUTE_NUM
1284ProcThreadAttributeParentProcess    = 0
1285ProcThreadAttributeExtendedFlags    = 1
1286ProcThreadAttributeHandleList       = 2
1287ProcThreadAttributeGroupAffinity    = 3
1288ProcThreadAttributePreferredNode    = 4
1289ProcThreadAttributeIdealProcessor   = 5
1290ProcThreadAttributeUmsThread        = 6
1291ProcThreadAttributeMitigationPolicy = 7
1292ProcThreadAttributeMax              = 8
1293
1294PROC_THREAD_ATTRIBUTE_PARENT_PROCESS    = ProcThreadAttributeParentProcess      |                                PROC_THREAD_ATTRIBUTE_INPUT
1295PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS    = ProcThreadAttributeExtendedFlags      |                                PROC_THREAD_ATTRIBUTE_INPUT | PROC_THREAD_ATTRIBUTE_ADDITIVE
1296PROC_THREAD_ATTRIBUTE_HANDLE_LIST       = ProcThreadAttributeHandleList         |                                PROC_THREAD_ATTRIBUTE_INPUT
1297PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY    = ProcThreadAttributeGroupAffinity      | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
1298PROC_THREAD_ATTRIBUTE_PREFERRED_NODE    = ProcThreadAttributePreferredNode      |                                PROC_THREAD_ATTRIBUTE_INPUT
1299PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR   = ProcThreadAttributeIdealProcessor     | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
1300PROC_THREAD_ATTRIBUTE_UMS_THREAD        = ProcThreadAttributeUmsThread          | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
1301PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = ProcThreadAttributeMitigationPolicy   |                                PROC_THREAD_ATTRIBUTE_INPUT
1302
1303PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE           = 0x01
1304PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE = 0x02
1305PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE         = 0x04
1306
1307#--- VS_FIXEDFILEINFO structure -----------------------------------------------
1308
1309# struct VS_FIXEDFILEINFO {
1310#   DWORD dwSignature;
1311#   DWORD dwStrucVersion;
1312#   DWORD dwFileVersionMS;
1313#   DWORD dwFileVersionLS;
1314#   DWORD dwProductVersionMS;
1315#   DWORD dwProductVersionLS;
1316#   DWORD dwFileFlagsMask;
1317#   DWORD dwFileFlags;
1318#   DWORD dwFileOS;
1319#   DWORD dwFileType;
1320#   DWORD dwFileSubtype;
1321#   DWORD dwFileDateMS;
1322#   DWORD dwFileDateLS;
1323# };
1324class VS_FIXEDFILEINFO (Structure):
1325    _fields_ = [
1326        ("dwSignature",             DWORD),     # 0xFEEF04BD
1327        ("dwStrucVersion",          DWORD),
1328        ("dwFileVersionMS",         DWORD),
1329        ("dwFileVersionLS",         DWORD),
1330        ("dwProductVersionMS",      DWORD),
1331        ("dwProductVersionLS",      DWORD),
1332        ("dwFileFlagsMask",         DWORD),
1333        ("dwFileFlags",             DWORD),
1334        ("dwFileOS",                DWORD),
1335        ("dwFileType",              DWORD),
1336        ("dwFileSubtype",           DWORD),
1337        ("dwFileDateMS",            DWORD),
1338        ("dwFileDateLS",            DWORD),
1339    ]
1340
1341#--- THREADNAME_INFO structure ------------------------------------------------
1342
1343# typedef struct tagTHREADNAME_INFO
1344# {
1345#    DWORD dwType; // Must be 0x1000.
1346#    LPCSTR szName; // Pointer to name (in user addr space).
1347#    DWORD dwThreadID; // Thread ID (-1=caller thread).
1348#    DWORD dwFlags; // Reserved for future use, must be zero.
1349# } THREADNAME_INFO;
1350class THREADNAME_INFO(Structure):
1351    _fields_ = [
1352        ("dwType",      DWORD),     # 0x1000
1353        ("szName",      LPVOID),    # remote pointer
1354        ("dwThreadID",  DWORD),     # -1 usually
1355        ("dwFlags",     DWORD),     # 0
1356    ]
1357
1358#--- MEMORY_BASIC_INFORMATION structure ---------------------------------------
1359
1360# typedef struct _MEMORY_BASIC_INFORMATION32 {
1361#     DWORD BaseAddress;
1362#     DWORD AllocationBase;
1363#     DWORD AllocationProtect;
1364#     DWORD RegionSize;
1365#     DWORD State;
1366#     DWORD Protect;
1367#     DWORD Type;
1368# } MEMORY_BASIC_INFORMATION32, *PMEMORY_BASIC_INFORMATION32;
1369class MEMORY_BASIC_INFORMATION32(Structure):
1370    _fields_ = [
1371        ('BaseAddress',         DWORD),         # remote pointer
1372        ('AllocationBase',      DWORD),         # remote pointer
1373        ('AllocationProtect',   DWORD),
1374        ('RegionSize',          DWORD),
1375        ('State',               DWORD),
1376        ('Protect',             DWORD),
1377        ('Type',                DWORD),
1378    ]
1379
1380# typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION64 {
1381#     ULONGLONG BaseAddress;
1382#     ULONGLONG AllocationBase;
1383#     DWORD     AllocationProtect;
1384#     DWORD     __alignment1;
1385#     ULONGLONG RegionSize;
1386#     DWORD     State;
1387#     DWORD     Protect;
1388#     DWORD     Type;
1389#     DWORD     __alignment2;
1390# } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;
1391class MEMORY_BASIC_INFORMATION64(Structure):
1392    _fields_ = [
1393        ('BaseAddress',         ULONGLONG),     # remote pointer
1394        ('AllocationBase',      ULONGLONG),     # remote pointer
1395        ('AllocationProtect',   DWORD),
1396        ('__alignment1',        DWORD),
1397        ('RegionSize',          ULONGLONG),
1398        ('State',               DWORD),
1399        ('Protect',             DWORD),
1400        ('Type',                DWORD),
1401        ('__alignment2',        DWORD),
1402    ]
1403
1404# typedef struct _MEMORY_BASIC_INFORMATION {
1405#     PVOID BaseAddress;
1406#     PVOID AllocationBase;
1407#     DWORD AllocationProtect;
1408#     SIZE_T RegionSize;
1409#     DWORD State;
1410#     DWORD Protect;
1411#     DWORD Type;
1412# } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
1413class MEMORY_BASIC_INFORMATION(Structure):
1414    _fields_ = [
1415        ('BaseAddress',         SIZE_T),    # remote pointer
1416        ('AllocationBase',      SIZE_T),    # remote pointer
1417        ('AllocationProtect',   DWORD),
1418        ('RegionSize',          SIZE_T),
1419        ('State',               DWORD),
1420        ('Protect',             DWORD),
1421        ('Type',                DWORD),
1422    ]
1423PMEMORY_BASIC_INFORMATION = POINTER(MEMORY_BASIC_INFORMATION)
1424
1425#--- BY_HANDLE_FILE_INFORMATION structure -------------------------------------
1426
1427# typedef struct _FILETIME {
1428#    DWORD dwLowDateTime;
1429#    DWORD dwHighDateTime;
1430# } FILETIME, *PFILETIME;
1431class FILETIME(Structure):
1432    _fields_ = [
1433        ('dwLowDateTime',       DWORD),
1434        ('dwHighDateTime',      DWORD),
1435    ]
1436LPFILETIME = POINTER(FILETIME)
1437
1438# typedef struct _SYSTEMTIME {
1439#   WORD wYear;
1440#   WORD wMonth;
1441#   WORD wDayOfWeek;
1442#   WORD wDay;
1443#   WORD wHour;
1444#   WORD wMinute;
1445#   WORD wSecond;
1446#   WORD wMilliseconds;
1447# }SYSTEMTIME, *PSYSTEMTIME;
1448class SYSTEMTIME(Structure):
1449    _fields_ = [
1450        ('wYear',           WORD),
1451        ('wMonth',          WORD),
1452        ('wDayOfWeek',      WORD),
1453        ('wDay',            WORD),
1454        ('wHour',           WORD),
1455        ('wMinute',         WORD),
1456        ('wSecond',         WORD),
1457        ('wMilliseconds',   WORD),
1458    ]
1459LPSYSTEMTIME = POINTER(SYSTEMTIME)
1460
1461# typedef struct _BY_HANDLE_FILE_INFORMATION {
1462#   DWORD dwFileAttributes;
1463#   FILETIME ftCreationTime;
1464#   FILETIME ftLastAccessTime;
1465#   FILETIME ftLastWriteTime;
1466#   DWORD dwVolumeSerialNumber;
1467#   DWORD nFileSizeHigh;
1468#   DWORD nFileSizeLow;
1469#   DWORD nNumberOfLinks;
1470#   DWORD nFileIndexHigh;
1471#   DWORD nFileIndexLow;
1472# } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;
1473class BY_HANDLE_FILE_INFORMATION(Structure):
1474    _fields_ = [
1475        ('dwFileAttributes',        DWORD),
1476        ('ftCreationTime',          FILETIME),
1477        ('ftLastAccessTime',        FILETIME),
1478        ('ftLastWriteTime',         FILETIME),
1479        ('dwVolumeSerialNumber',    DWORD),
1480        ('nFileSizeHigh',           DWORD),
1481        ('nFileSizeLow',            DWORD),
1482        ('nNumberOfLinks',          DWORD),
1483        ('nFileIndexHigh',          DWORD),
1484        ('nFileIndexLow',           DWORD),
1485    ]
1486LPBY_HANDLE_FILE_INFORMATION = POINTER(BY_HANDLE_FILE_INFORMATION)
1487
1488# typedef enum _FILE_INFO_BY_HANDLE_CLASS {
1489#   FileBasicInfo = 0,
1490#   FileStandardInfo = 1,
1491#   FileNameInfo = 2,
1492#   FileRenameInfo = 3,
1493#   FileDispositionInfo = 4,
1494#   FileAllocationInfo = 5,
1495#   FileEndOfFileInfo = 6,
1496#   FileStreamInfo = 7,
1497#   FileCompressionInfo = 8,
1498#   FileAttributeTagInfo = 9,
1499#   FileIdBothDirectoryInfo = 10,
1500#   FileIdBothDirectoryRestartInfo = 11,
1501#   FileIoPriorityHintInfo = 12,
1502#   MaximumFileInfoByHandlesClass = 13
1503# } FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;
1504class FILE_INFO_BY_HANDLE_CLASS(object):
1505    FileBasicInfo                   = 0
1506    FileStandardInfo                = 1
1507    FileNameInfo                    = 2
1508    FileRenameInfo                  = 3
1509    FileDispositionInfo             = 4
1510    FileAllocationInfo              = 5
1511    FileEndOfFileInfo               = 6
1512    FileStreamInfo                  = 7
1513    FileCompressionInfo             = 8
1514    FileAttributeTagInfo            = 9
1515    FileIdBothDirectoryInfo         = 10
1516    FileIdBothDirectoryRestartInfo  = 11
1517    FileIoPriorityHintInfo          = 12
1518    MaximumFileInfoByHandlesClass   = 13
1519
1520# typedef struct _FILE_NAME_INFO {
1521#   DWORD  FileNameLength;
1522#   WCHAR FileName[1];
1523# } FILE_NAME_INFO, *PFILE_NAME_INFO;
1524##class FILE_NAME_INFO(Structure):
1525##    _fields_ = [
1526##        ('FileNameLength',  DWORD),
1527##        ('FileName',        WCHAR * 1),
1528##    ]
1529
1530# TO DO: add more structures used by GetFileInformationByHandleEx()
1531
1532#--- PROCESS_INFORMATION structure --------------------------------------------
1533
1534# typedef struct _PROCESS_INFORMATION {
1535#     HANDLE hProcess;
1536#     HANDLE hThread;
1537#     DWORD dwProcessId;
1538#     DWORD dwThreadId;
1539# } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
1540class PROCESS_INFORMATION(Structure):
1541    _fields_ = [
1542        ('hProcess',    HANDLE),
1543        ('hThread',     HANDLE),
1544        ('dwProcessId', DWORD),
1545        ('dwThreadId',  DWORD),
1546    ]
1547LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
1548
1549#--- STARTUPINFO and STARTUPINFOEX structures ---------------------------------
1550
1551# typedef struct _STARTUPINFO {
1552#   DWORD  cb;
1553#   LPTSTR lpReserved;
1554#   LPTSTR lpDesktop;
1555#   LPTSTR lpTitle;
1556#   DWORD  dwX;
1557#   DWORD  dwY;
1558#   DWORD  dwXSize;
1559#   DWORD  dwYSize;
1560#   DWORD  dwXCountChars;
1561#   DWORD  dwYCountChars;
1562#   DWORD  dwFillAttribute;
1563#   DWORD  dwFlags;
1564#   WORD   wShowWindow;
1565#   WORD   cbReserved2;
1566#   LPBYTE lpReserved2;
1567#   HANDLE hStdInput;
1568#   HANDLE hStdOutput;
1569#   HANDLE hStdError;
1570# }STARTUPINFO, *LPSTARTUPINFO;
1571class STARTUPINFO(Structure):
1572    _fields_ = [
1573        ('cb',              DWORD),
1574        ('lpReserved',      LPSTR),
1575        ('lpDesktop',       LPSTR),
1576        ('lpTitle',         LPSTR),
1577        ('dwX',             DWORD),
1578        ('dwY',             DWORD),
1579        ('dwXSize',         DWORD),
1580        ('dwYSize',         DWORD),
1581        ('dwXCountChars',   DWORD),
1582        ('dwYCountChars',   DWORD),
1583        ('dwFillAttribute', DWORD),
1584        ('dwFlags',         DWORD),
1585        ('wShowWindow',     WORD),
1586        ('cbReserved2',     WORD),
1587        ('lpReserved2',     LPVOID),    # LPBYTE
1588        ('hStdInput',       HANDLE),
1589        ('hStdOutput',      HANDLE),
1590        ('hStdError',       HANDLE),
1591    ]
1592LPSTARTUPINFO = POINTER(STARTUPINFO)
1593
1594# typedef struct _STARTUPINFOEX {
1595#   STARTUPINFO StartupInfo;
1596#   PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
1597# } STARTUPINFOEX,  *LPSTARTUPINFOEX;
1598class STARTUPINFOEX(Structure):
1599    _fields_ = [
1600        ('StartupInfo',     STARTUPINFO),
1601        ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
1602    ]
1603LPSTARTUPINFOEX = POINTER(STARTUPINFOEX)
1604
1605class STARTUPINFOW(Structure):
1606    _fields_ = [
1607        ('cb',              DWORD),
1608        ('lpReserved',      LPWSTR),
1609        ('lpDesktop',       LPWSTR),
1610        ('lpTitle',         LPWSTR),
1611        ('dwX',             DWORD),
1612        ('dwY',             DWORD),
1613        ('dwXSize',         DWORD),
1614        ('dwYSize',         DWORD),
1615        ('dwXCountChars',   DWORD),
1616        ('dwYCountChars',   DWORD),
1617        ('dwFillAttribute', DWORD),
1618        ('dwFlags',         DWORD),
1619        ('wShowWindow',     WORD),
1620        ('cbReserved2',     WORD),
1621        ('lpReserved2',     LPVOID),    # LPBYTE
1622        ('hStdInput',       HANDLE),
1623        ('hStdOutput',      HANDLE),
1624        ('hStdError',       HANDLE),
1625    ]
1626LPSTARTUPINFOW = POINTER(STARTUPINFOW)
1627
1628class STARTUPINFOEXW(Structure):
1629    _fields_ = [
1630        ('StartupInfo',     STARTUPINFOW),
1631        ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
1632    ]
1633LPSTARTUPINFOEXW = POINTER(STARTUPINFOEXW)
1634
1635#--- JIT_DEBUG_INFO structure -------------------------------------------------
1636
1637# typedef struct _JIT_DEBUG_INFO {
1638#     DWORD dwSize;
1639#     DWORD dwProcessorArchitecture;
1640#     DWORD dwThreadID;
1641#     DWORD dwReserved0;
1642#     ULONG64 lpExceptionAddress;
1643#     ULONG64 lpExceptionRecord;
1644#     ULONG64 lpContextRecord;
1645# } JIT_DEBUG_INFO, *LPJIT_DEBUG_INFO;
1646class JIT_DEBUG_INFO(Structure):
1647    _fields_ = [
1648        ('dwSize',                  DWORD),
1649        ('dwProcessorArchitecture', DWORD),
1650        ('dwThreadID',              DWORD),
1651        ('dwReserved0',             DWORD),
1652        ('lpExceptionAddress',      ULONG64),
1653        ('lpExceptionRecord',       ULONG64),
1654        ('lpContextRecord',         ULONG64),
1655    ]
1656JIT_DEBUG_INFO32 = JIT_DEBUG_INFO
1657JIT_DEBUG_INFO64 = JIT_DEBUG_INFO
1658
1659LPJIT_DEBUG_INFO   = POINTER(JIT_DEBUG_INFO)
1660LPJIT_DEBUG_INFO32 = POINTER(JIT_DEBUG_INFO32)
1661LPJIT_DEBUG_INFO64 = POINTER(JIT_DEBUG_INFO64)
1662
1663#--- DEBUG_EVENT structure ----------------------------------------------------
1664
1665# typedef struct _EXCEPTION_RECORD32 {
1666#     DWORD ExceptionCode;
1667#     DWORD ExceptionFlags;
1668#     DWORD ExceptionRecord;
1669#     DWORD ExceptionAddress;
1670#     DWORD NumberParameters;
1671#     DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
1672# } EXCEPTION_RECORD32, *PEXCEPTION_RECORD32;
1673class EXCEPTION_RECORD32(Structure):
1674    _fields_ = [
1675        ('ExceptionCode',           DWORD),
1676        ('ExceptionFlags',          DWORD),
1677        ('ExceptionRecord',         DWORD),
1678        ('ExceptionAddress',        DWORD),
1679        ('NumberParameters',        DWORD),
1680        ('ExceptionInformation',    DWORD * EXCEPTION_MAXIMUM_PARAMETERS),
1681    ]
1682
1683PEXCEPTION_RECORD32 = POINTER(EXCEPTION_RECORD32)
1684
1685# typedef struct _EXCEPTION_RECORD64 {
1686#     DWORD    ExceptionCode;
1687#     DWORD ExceptionFlags;
1688#     DWORD64 ExceptionRecord;
1689#     DWORD64 ExceptionAddress;
1690#     DWORD NumberParameters;
1691#     DWORD __unusedAlignment;
1692#     DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
1693# } EXCEPTION_RECORD64, *PEXCEPTION_RECORD64;
1694class EXCEPTION_RECORD64(Structure):
1695    _fields_ = [
1696        ('ExceptionCode',           DWORD),
1697        ('ExceptionFlags',          DWORD),
1698        ('ExceptionRecord',         DWORD64),
1699        ('ExceptionAddress',        DWORD64),
1700        ('NumberParameters',        DWORD),
1701        ('__unusedAlignment',       DWORD),
1702        ('ExceptionInformation',    DWORD64 * EXCEPTION_MAXIMUM_PARAMETERS),
1703    ]
1704
1705PEXCEPTION_RECORD64 = POINTER(EXCEPTION_RECORD64)
1706
1707# typedef struct _EXCEPTION_RECORD {
1708#     DWORD ExceptionCode;
1709#     DWORD ExceptionFlags;
1710#     LPVOID ExceptionRecord;
1711#     LPVOID ExceptionAddress;
1712#     DWORD NumberParameters;
1713#     LPVOID ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
1714# } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
1715class EXCEPTION_RECORD(Structure):
1716    pass
1717PEXCEPTION_RECORD = POINTER(EXCEPTION_RECORD)
1718EXCEPTION_RECORD._fields_ = [
1719        ('ExceptionCode',           DWORD),
1720        ('ExceptionFlags',          DWORD),
1721        ('ExceptionRecord',         PEXCEPTION_RECORD),
1722        ('ExceptionAddress',        LPVOID),
1723        ('NumberParameters',        DWORD),
1724        ('ExceptionInformation',    LPVOID * EXCEPTION_MAXIMUM_PARAMETERS),
1725    ]
1726
1727# typedef struct _EXCEPTION_DEBUG_INFO {
1728#   EXCEPTION_RECORD ExceptionRecord;
1729#   DWORD dwFirstChance;
1730# } EXCEPTION_DEBUG_INFO;
1731class EXCEPTION_DEBUG_INFO(Structure):
1732    _fields_ = [
1733        ('ExceptionRecord',     EXCEPTION_RECORD),
1734        ('dwFirstChance',       DWORD),
1735    ]
1736
1737# typedef struct _CREATE_THREAD_DEBUG_INFO {
1738#   HANDLE hThread;
1739#   LPVOID lpThreadLocalBase;
1740#   LPTHREAD_START_ROUTINE lpStartAddress;
1741# } CREATE_THREAD_DEBUG_INFO;
1742class CREATE_THREAD_DEBUG_INFO(Structure):
1743    _fields_ = [
1744        ('hThread',             HANDLE),
1745        ('lpThreadLocalBase',   LPVOID),
1746        ('lpStartAddress',      LPVOID),
1747    ]
1748
1749# typedef struct _CREATE_PROCESS_DEBUG_INFO {
1750#   HANDLE hFile;
1751#   HANDLE hProcess;
1752#   HANDLE hThread;
1753#   LPVOID lpBaseOfImage;
1754#   DWORD dwDebugInfoFileOffset;
1755#   DWORD nDebugInfoSize;
1756#   LPVOID lpThreadLocalBase;
1757#   LPTHREAD_START_ROUTINE lpStartAddress;
1758#   LPVOID lpImageName;
1759#   WORD fUnicode;
1760# } CREATE_PROCESS_DEBUG_INFO;
1761class CREATE_PROCESS_DEBUG_INFO(Structure):
1762    _fields_ = [
1763        ('hFile',                   HANDLE),
1764        ('hProcess',                HANDLE),
1765        ('hThread',                 HANDLE),
1766        ('lpBaseOfImage',           LPVOID),
1767        ('dwDebugInfoFileOffset',   DWORD),
1768        ('nDebugInfoSize',          DWORD),
1769        ('lpThreadLocalBase',       LPVOID),
1770        ('lpStartAddress',          LPVOID),
1771        ('lpImageName',             LPVOID),
1772        ('fUnicode',                WORD),
1773    ]
1774
1775# typedef struct _EXIT_THREAD_DEBUG_INFO {
1776#   DWORD dwExitCode;
1777# } EXIT_THREAD_DEBUG_INFO;
1778class EXIT_THREAD_DEBUG_INFO(Structure):
1779    _fields_ = [
1780        ('dwExitCode',          DWORD),
1781    ]
1782
1783# typedef struct _EXIT_PROCESS_DEBUG_INFO {
1784#   DWORD dwExitCode;
1785# } EXIT_PROCESS_DEBUG_INFO;
1786class EXIT_PROCESS_DEBUG_INFO(Structure):
1787    _fields_ = [
1788        ('dwExitCode',          DWORD),
1789    ]
1790
1791# typedef struct _LOAD_DLL_DEBUG_INFO {
1792#   HANDLE hFile;
1793#   LPVOID lpBaseOfDll;
1794#   DWORD dwDebugInfoFileOffset;
1795#   DWORD nDebugInfoSize;
1796#   LPVOID lpImageName;
1797#   WORD fUnicode;
1798# } LOAD_DLL_DEBUG_INFO;
1799class LOAD_DLL_DEBUG_INFO(Structure):
1800    _fields_ = [
1801        ('hFile',                   HANDLE),
1802        ('lpBaseOfDll',             LPVOID),
1803        ('dwDebugInfoFileOffset',   DWORD),
1804        ('nDebugInfoSize',          DWORD),
1805        ('lpImageName',             LPVOID),
1806        ('fUnicode',                WORD),
1807    ]
1808
1809# typedef struct _UNLOAD_DLL_DEBUG_INFO {
1810#   LPVOID lpBaseOfDll;
1811# } UNLOAD_DLL_DEBUG_INFO;
1812class UNLOAD_DLL_DEBUG_INFO(Structure):
1813    _fields_ = [
1814        ('lpBaseOfDll',         LPVOID),
1815    ]
1816
1817# typedef struct _OUTPUT_DEBUG_STRING_INFO {
1818#   LPSTR lpDebugStringData;
1819#   WORD fUnicode;
1820#   WORD nDebugStringLength;
1821# } OUTPUT_DEBUG_STRING_INFO;
1822class OUTPUT_DEBUG_STRING_INFO(Structure):
1823    _fields_ = [
1824        ('lpDebugStringData',   LPVOID),    # don't use LPSTR
1825        ('fUnicode',            WORD),
1826        ('nDebugStringLength',  WORD),
1827    ]
1828
1829# typedef struct _RIP_INFO {
1830#     DWORD dwError;
1831#     DWORD dwType;
1832# } RIP_INFO, *LPRIP_INFO;
1833class RIP_INFO(Structure):
1834    _fields_ = [
1835        ('dwError',             DWORD),
1836        ('dwType',              DWORD),
1837    ]
1838
1839# typedef struct _DEBUG_EVENT {
1840#   DWORD dwDebugEventCode;
1841#   DWORD dwProcessId;
1842#   DWORD dwThreadId;
1843#   union {
1844#     EXCEPTION_DEBUG_INFO Exception;
1845#     CREATE_THREAD_DEBUG_INFO CreateThread;
1846#     CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
1847#     EXIT_THREAD_DEBUG_INFO ExitThread;
1848#     EXIT_PROCESS_DEBUG_INFO ExitProcess;
1849#     LOAD_DLL_DEBUG_INFO LoadDll;
1850#     UNLOAD_DLL_DEBUG_INFO UnloadDll;
1851#     OUTPUT_DEBUG_STRING_INFO DebugString;
1852#     RIP_INFO RipInfo;
1853#   } u;
1854# } DEBUG_EVENT;.
1855class _DEBUG_EVENT_UNION_(Union):
1856    _fields_ = [
1857        ('Exception',           EXCEPTION_DEBUG_INFO),
1858        ('CreateThread',        CREATE_THREAD_DEBUG_INFO),
1859        ('CreateProcessInfo',   CREATE_PROCESS_DEBUG_INFO),
1860        ('ExitThread',          EXIT_THREAD_DEBUG_INFO),
1861        ('ExitProcess',         EXIT_PROCESS_DEBUG_INFO),
1862        ('LoadDll',             LOAD_DLL_DEBUG_INFO),
1863        ('UnloadDll',           UNLOAD_DLL_DEBUG_INFO),
1864        ('DebugString',         OUTPUT_DEBUG_STRING_INFO),
1865        ('RipInfo',             RIP_INFO),
1866    ]
1867class DEBUG_EVENT(Structure):
1868    _fields_ = [
1869        ('dwDebugEventCode',    DWORD),
1870        ('dwProcessId',         DWORD),
1871        ('dwThreadId',          DWORD),
1872        ('u',                   _DEBUG_EVENT_UNION_),
1873    ]
1874LPDEBUG_EVENT = POINTER(DEBUG_EVENT)
1875
1876#--- Console API defines and structures ---------------------------------------
1877
1878FOREGROUND_MASK = 0x000F
1879BACKGROUND_MASK = 0x00F0
1880COMMON_LVB_MASK = 0xFF00
1881
1882FOREGROUND_BLACK     = 0x0000
1883FOREGROUND_BLUE      = 0x0001
1884FOREGROUND_GREEN     = 0x0002
1885FOREGROUND_CYAN      = 0x0003
1886FOREGROUND_RED       = 0x0004
1887FOREGROUND_MAGENTA   = 0x0005
1888FOREGROUND_YELLOW    = 0x0006
1889FOREGROUND_GREY      = 0x0007
1890FOREGROUND_INTENSITY = 0x0008
1891
1892BACKGROUND_BLACK     = 0x0000
1893BACKGROUND_BLUE      = 0x0010
1894BACKGROUND_GREEN     = 0x0020
1895BACKGROUND_CYAN      = 0x0030
1896BACKGROUND_RED       = 0x0040
1897BACKGROUND_MAGENTA   = 0x0050
1898BACKGROUND_YELLOW    = 0x0060
1899BACKGROUND_GREY      = 0x0070
1900BACKGROUND_INTENSITY = 0x0080
1901
1902COMMON_LVB_LEADING_BYTE    = 0x0100
1903COMMON_LVB_TRAILING_BYTE   = 0x0200
1904COMMON_LVB_GRID_HORIZONTAL = 0x0400
1905COMMON_LVB_GRID_LVERTICAL  = 0x0800
1906COMMON_LVB_GRID_RVERTICAL  = 0x1000
1907COMMON_LVB_REVERSE_VIDEO   = 0x4000
1908COMMON_LVB_UNDERSCORE      = 0x8000
1909
1910# typedef struct _CHAR_INFO {
1911#   union {
1912#     WCHAR UnicodeChar;
1913#     CHAR  AsciiChar;
1914#   } Char;
1915#   WORD  Attributes;
1916# } CHAR_INFO, *PCHAR_INFO;
1917class _CHAR_INFO_CHAR(Union):
1918    _fields_ = [
1919        ('UnicodeChar', WCHAR),
1920        ('AsciiChar',   CHAR),
1921    ]
1922class CHAR_INFO(Structure):
1923    _fields_ = [
1924        ('Char',       _CHAR_INFO_CHAR),
1925        ('Attributes', WORD),
1926   ]
1927PCHAR_INFO = POINTER(CHAR_INFO)
1928
1929# typedef struct _COORD {
1930#   SHORT X;
1931#   SHORT Y;
1932# } COORD, *PCOORD;
1933class COORD(Structure):
1934    _fields_ = [
1935        ('X', SHORT),
1936        ('Y', SHORT),
1937    ]
1938PCOORD = POINTER(COORD)
1939
1940# typedef struct _SMALL_RECT {
1941#   SHORT Left;
1942#   SHORT Top;
1943#   SHORT Right;
1944#   SHORT Bottom;
1945# } SMALL_RECT;
1946class SMALL_RECT(Structure):
1947    _fields_ = [
1948        ('Left',   SHORT),
1949        ('Top',    SHORT),
1950        ('Right',  SHORT),
1951        ('Bottom', SHORT),
1952    ]
1953PSMALL_RECT = POINTER(SMALL_RECT)
1954
1955# typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
1956#   COORD      dwSize;
1957#   COORD      dwCursorPosition;
1958#   WORD       wAttributes;
1959#   SMALL_RECT srWindow;
1960#   COORD      dwMaximumWindowSize;
1961# } CONSOLE_SCREEN_BUFFER_INFO;
1962class CONSOLE_SCREEN_BUFFER_INFO(Structure):
1963    _fields_ = [
1964        ('dwSize',              COORD),
1965        ('dwCursorPosition',    COORD),
1966        ('wAttributes',         WORD),
1967        ('srWindow',            SMALL_RECT),
1968        ('dwMaximumWindowSize', COORD),
1969    ]
1970PCONSOLE_SCREEN_BUFFER_INFO = POINTER(CONSOLE_SCREEN_BUFFER_INFO)
1971
1972#--- Toolhelp library defines and structures ----------------------------------
1973
1974TH32CS_SNAPHEAPLIST = 0x00000001
1975TH32CS_SNAPPROCESS  = 0x00000002
1976TH32CS_SNAPTHREAD   = 0x00000004
1977TH32CS_SNAPMODULE   = 0x00000008
1978TH32CS_INHERIT      = 0x80000000
1979TH32CS_SNAPALL      = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
1980
1981# typedef struct tagTHREADENTRY32 {
1982#   DWORD dwSize;
1983#   DWORD cntUsage;
1984#   DWORD th32ThreadID;
1985#   DWORD th32OwnerProcessID;
1986#   LONG tpBasePri;
1987#   LONG tpDeltaPri;
1988#   DWORD dwFlags;
1989# } THREADENTRY32,  *PTHREADENTRY32;
1990class THREADENTRY32(Structure):
1991    _fields_ = [
1992        ('dwSize',             DWORD),
1993        ('cntUsage',           DWORD),
1994        ('th32ThreadID',       DWORD),
1995        ('th32OwnerProcessID', DWORD),
1996        ('tpBasePri',          LONG),
1997        ('tpDeltaPri',         LONG),
1998        ('dwFlags',            DWORD),
1999    ]
2000LPTHREADENTRY32 = POINTER(THREADENTRY32)
2001
2002# typedef struct tagPROCESSENTRY32 {
2003#    DWORD dwSize;
2004#    DWORD cntUsage;
2005#    DWORD th32ProcessID;
2006#    ULONG_PTR th32DefaultHeapID;
2007#    DWORD th32ModuleID;
2008#    DWORD cntThreads;
2009#    DWORD th32ParentProcessID;
2010#    LONG pcPriClassBase;
2011#    DWORD dwFlags;
2012#    TCHAR szExeFile[MAX_PATH];
2013# } PROCESSENTRY32,  *PPROCESSENTRY32;
2014class PROCESSENTRY32(Structure):
2015    _fields_ = [
2016        ('dwSize',              DWORD),
2017        ('cntUsage',            DWORD),
2018        ('th32ProcessID',       DWORD),
2019        ('th32DefaultHeapID',   ULONG_PTR),
2020        ('th32ModuleID',        DWORD),
2021        ('cntThreads',          DWORD),
2022        ('th32ParentProcessID', DWORD),
2023        ('pcPriClassBase',      LONG),
2024        ('dwFlags',             DWORD),
2025        ('szExeFile',           TCHAR * 260),
2026    ]
2027LPPROCESSENTRY32 = POINTER(PROCESSENTRY32)
2028
2029# typedef struct tagMODULEENTRY32 {
2030#   DWORD dwSize;
2031#   DWORD th32ModuleID;
2032#   DWORD th32ProcessID;
2033#   DWORD GlblcntUsage;
2034#   DWORD ProccntUsage;
2035#   BYTE* modBaseAddr;
2036#   DWORD modBaseSize;
2037#   HMODULE hModule;
2038#   TCHAR szModule[MAX_MODULE_NAME32 + 1];
2039#   TCHAR szExePath[MAX_PATH];
2040# } MODULEENTRY32,  *PMODULEENTRY32;
2041class MODULEENTRY32(Structure):
2042    _fields_ = [
2043        ("dwSize",        DWORD),
2044        ("th32ModuleID",  DWORD),
2045        ("th32ProcessID", DWORD),
2046        ("GlblcntUsage",  DWORD),
2047        ("ProccntUsage",  DWORD),
2048        ("modBaseAddr",   LPVOID),  # BYTE*
2049        ("modBaseSize",   DWORD),
2050        ("hModule",       HMODULE),
2051        ("szModule",      TCHAR * (MAX_MODULE_NAME32 + 1)),
2052        ("szExePath",     TCHAR * MAX_PATH),
2053    ]
2054LPMODULEENTRY32 = POINTER(MODULEENTRY32)
2055
2056# typedef struct tagHEAPENTRY32 {
2057#   SIZE_T    dwSize;
2058#   HANDLE    hHandle;
2059#   ULONG_PTR dwAddress;
2060#   SIZE_T    dwBlockSize;
2061#   DWORD     dwFlags;
2062#   DWORD     dwLockCount;
2063#   DWORD     dwResvd;
2064#   DWORD     th32ProcessID;
2065#   ULONG_PTR th32HeapID;
2066# } HEAPENTRY32,
2067# *PHEAPENTRY32;
2068class HEAPENTRY32(Structure):
2069    _fields_ = [
2070        ("dwSize",          SIZE_T),
2071        ("hHandle",         HANDLE),
2072        ("dwAddress",       ULONG_PTR),
2073        ("dwBlockSize",     SIZE_T),
2074        ("dwFlags",         DWORD),
2075        ("dwLockCount",     DWORD),
2076        ("dwResvd",         DWORD),
2077        ("th32ProcessID",   DWORD),
2078        ("th32HeapID",      ULONG_PTR),
2079]
2080LPHEAPENTRY32 = POINTER(HEAPENTRY32)
2081
2082# typedef struct tagHEAPLIST32 {
2083#   SIZE_T    dwSize;
2084#   DWORD     th32ProcessID;
2085#   ULONG_PTR th32HeapID;
2086#   DWORD     dwFlags;
2087# } HEAPLIST32,
2088#  *PHEAPLIST32;
2089class HEAPLIST32(Structure):
2090    _fields_ = [
2091        ("dwSize",          SIZE_T),
2092        ("th32ProcessID",   DWORD),
2093        ("th32HeapID",      ULONG_PTR),
2094        ("dwFlags",         DWORD),
2095]
2096LPHEAPLIST32 = POINTER(HEAPLIST32)
2097
2098#--- kernel32.dll -------------------------------------------------------------
2099
2100# DWORD WINAPI GetLastError(void);
2101def GetLastError():
2102    _GetLastError = windll.kernel32.GetLastError
2103    _GetLastError.argtypes = []
2104    _GetLastError.restype  = DWORD
2105    return _GetLastError()
2106
2107# void WINAPI SetLastError(
2108#   __in  DWORD dwErrCode
2109# );
2110def SetLastError(dwErrCode):
2111    _SetLastError = windll.kernel32.SetLastError
2112    _SetLastError.argtypes = [DWORD]
2113    _SetLastError.restype  = None
2114    _SetLastError(dwErrCode)
2115
2116# UINT WINAPI GetErrorMode(void);
2117def GetErrorMode():
2118    _GetErrorMode = windll.kernel32.GetErrorMode
2119    _GetErrorMode.argtypes = []
2120    _GetErrorMode.restype  = UINT
2121    return _GetErrorMode()
2122
2123# UINT WINAPI SetErrorMode(
2124#   __in  UINT uMode
2125# );
2126def SetErrorMode(uMode):
2127    _SetErrorMode = windll.kernel32.SetErrorMode
2128    _SetErrorMode.argtypes = [UINT]
2129    _SetErrorMode.restype  = UINT
2130    return _SetErrorMode(dwErrCode)
2131
2132# DWORD GetThreadErrorMode(void);
2133def GetThreadErrorMode():
2134    _GetThreadErrorMode = windll.kernel32.GetThreadErrorMode
2135    _GetThreadErrorMode.argtypes = []
2136    _GetThreadErrorMode.restype  = DWORD
2137    return _GetThreadErrorMode()
2138
2139# BOOL SetThreadErrorMode(
2140#   __in   DWORD dwNewMode,
2141#   __out  LPDWORD lpOldMode
2142# );
2143def SetThreadErrorMode(dwNewMode):
2144    _SetThreadErrorMode = windll.kernel32.SetThreadErrorMode
2145    _SetThreadErrorMode.argtypes = [DWORD, LPDWORD]
2146    _SetThreadErrorMode.restype  = BOOL
2147    _SetThreadErrorMode.errcheck = RaiseIfZero
2148
2149    old = DWORD(0)
2150    _SetThreadErrorMode(dwErrCode, byref(old))
2151    return old.value
2152
2153# BOOL WINAPI CloseHandle(
2154#   __in  HANDLE hObject
2155# );
2156def CloseHandle(hHandle):
2157    if isinstance(hHandle, Handle):
2158        # Prevents the handle from being closed without notifying the Handle object.
2159        hHandle.close()
2160    else:
2161        _CloseHandle = windll.kernel32.CloseHandle
2162        _CloseHandle.argtypes = [HANDLE]
2163        _CloseHandle.restype  = bool
2164        _CloseHandle.errcheck = RaiseIfZero
2165        _CloseHandle(hHandle)
2166
2167# BOOL WINAPI DuplicateHandle(
2168#   __in   HANDLE hSourceProcessHandle,
2169#   __in   HANDLE hSourceHandle,
2170#   __in   HANDLE hTargetProcessHandle,
2171#   __out  LPHANDLE lpTargetHandle,
2172#   __in   DWORD dwDesiredAccess,
2173#   __in   BOOL bInheritHandle,
2174#   __in   DWORD dwOptions
2175# );
2176def DuplicateHandle(hSourceHandle, hSourceProcessHandle = None, hTargetProcessHandle = None, dwDesiredAccess = STANDARD_RIGHTS_ALL, bInheritHandle = False, dwOptions = DUPLICATE_SAME_ACCESS):
2177    _DuplicateHandle = windll.kernel32.DuplicateHandle
2178    _DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD]
2179    _DuplicateHandle.restype  = bool
2180    _DuplicateHandle.errcheck = RaiseIfZero
2181
2182    # NOTE: the arguments to this function are in a different order,
2183    # so we can set default values for all of them but one (hSourceHandle).
2184
2185    if hSourceProcessHandle is None:
2186        hSourceProcessHandle = GetCurrentProcess()
2187    if hTargetProcessHandle is None:
2188        hTargetProcessHandle = hSourceProcessHandle
2189    lpTargetHandle = HANDLE(INVALID_HANDLE_VALUE)
2190    _DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, byref(lpTargetHandle), dwDesiredAccess, bool(bInheritHandle), dwOptions)
2191    if isinstance(hSourceHandle, Handle):
2192        HandleClass = hSourceHandle.__class__
2193    else:
2194        HandleClass = Handle
2195    if hasattr(hSourceHandle, 'dwAccess'):
2196        return HandleClass(lpTargetHandle.value, dwAccess = hSourceHandle.dwAccess)
2197    else:
2198        return HandleClass(lpTargetHandle.value)
2199
2200# HLOCAL WINAPI LocalFree(
2201#   __in  HLOCAL hMem
2202# );
2203def LocalFree(hMem):
2204    _LocalFree = windll.kernel32.LocalFree
2205    _LocalFree.argtypes = [HLOCAL]
2206    _LocalFree.restype  = HLOCAL
2207
2208    result = _LocalFree(hMem)
2209    if result != NULL:
2210        ctypes.WinError()
2211
2212#------------------------------------------------------------------------------
2213# Console API
2214
2215# HANDLE WINAPI GetStdHandle(
2216#   _In_  DWORD nStdHandle
2217# );
2218def GetStdHandle(nStdHandle):
2219    _GetStdHandle = windll.kernel32.GetStdHandle
2220    _GetStdHandle.argytpes = [DWORD]
2221    _GetStdHandle.restype  = HANDLE
2222    _GetStdHandle.errcheck = RaiseIfZero
2223    return Handle( _GetStdHandle(nStdHandle), bOwnership = False )
2224
2225# BOOL WINAPI SetStdHandle(
2226#   _In_  DWORD nStdHandle,
2227#   _In_  HANDLE hHandle
2228# );
2229
2230# TODO
2231
2232# UINT WINAPI GetConsoleCP(void);
2233def GetConsoleCP():
2234    _GetConsoleCP = windll.kernel32.GetConsoleCP
2235    _GetConsoleCP.argytpes = []
2236    _GetConsoleCP.restype  = UINT
2237    return _GetConsoleCP()
2238
2239# UINT WINAPI GetConsoleOutputCP(void);
2240def GetConsoleOutputCP():
2241    _GetConsoleOutputCP = windll.kernel32.GetConsoleOutputCP
2242    _GetConsoleOutputCP.argytpes = []
2243    _GetConsoleOutputCP.restype  = UINT
2244    return _GetConsoleOutputCP()
2245
2246#BOOL WINAPI SetConsoleCP(
2247#  _In_  UINT wCodePageID
2248#);
2249def SetConsoleCP(wCodePageID):
2250    _SetConsoleCP = windll.kernel32.SetConsoleCP
2251    _SetConsoleCP.argytpes = [UINT]
2252    _SetConsoleCP.restype  = bool
2253    _SetConsoleCP.errcheck = RaiseIfZero
2254    _SetConsoleCP(wCodePageID)
2255
2256#BOOL WINAPI SetConsoleOutputCP(
2257#  _In_  UINT wCodePageID
2258#);
2259def SetConsoleOutputCP(wCodePageID):
2260    _SetConsoleOutputCP = windll.kernel32.SetConsoleOutputCP
2261    _SetConsoleOutputCP.argytpes = [UINT]
2262    _SetConsoleOutputCP.restype  = bool
2263    _SetConsoleOutputCP.errcheck = RaiseIfZero
2264    _SetConsoleOutputCP(wCodePageID)
2265
2266# HANDLE WINAPI CreateConsoleScreenBuffer(
2267#   _In_        DWORD dwDesiredAccess,
2268#   _In_        DWORD dwShareMode,
2269#   _In_opt_    const SECURITY_ATTRIBUTES *lpSecurityAttributes,
2270#   _In_        DWORD dwFlags,
2271#   _Reserved_  LPVOID lpScreenBufferData
2272# );
2273
2274# TODO
2275
2276# BOOL WINAPI SetConsoleActiveScreenBuffer(
2277#   _In_  HANDLE hConsoleOutput
2278# );
2279def SetConsoleActiveScreenBuffer(hConsoleOutput = None):
2280    _SetConsoleActiveScreenBuffer = windll.kernel32.SetConsoleActiveScreenBuffer
2281    _SetConsoleActiveScreenBuffer.argytpes = [HANDLE]
2282    _SetConsoleActiveScreenBuffer.restype  = bool
2283    _SetConsoleActiveScreenBuffer.errcheck = RaiseIfZero
2284
2285    if hConsoleOutput is None:
2286        hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE)
2287    _SetConsoleActiveScreenBuffer(hConsoleOutput)
2288
2289# BOOL WINAPI GetConsoleScreenBufferInfo(
2290#   _In_   HANDLE hConsoleOutput,
2291#   _Out_  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo
2292# );
2293def GetConsoleScreenBufferInfo(hConsoleOutput = None):
2294    _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
2295    _GetConsoleScreenBufferInfo.argytpes = [HANDLE, PCONSOLE_SCREEN_BUFFER_INFO]
2296    _GetConsoleScreenBufferInfo.restype  = bool
2297    _GetConsoleScreenBufferInfo.errcheck = RaiseIfZero
2298
2299    if hConsoleOutput is None:
2300        hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE)
2301    ConsoleScreenBufferInfo = CONSOLE_SCREEN_BUFFER_INFO()
2302    _GetConsoleScreenBufferInfo(hConsoleOutput, byref(ConsoleScreenBufferInfo))
2303    return ConsoleScreenBufferInfo
2304
2305# BOOL WINAPI GetConsoleScreenBufferInfoEx(
2306#   _In_   HANDLE hConsoleOutput,
2307#   _Out_  PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx
2308# );
2309
2310# TODO
2311
2312# BOOL WINAPI SetConsoleWindowInfo(
2313#   _In_  HANDLE hConsoleOutput,
2314#   _In_  BOOL bAbsolute,
2315#   _In_  const SMALL_RECT *lpConsoleWindow
2316# );
2317def SetConsoleWindowInfo(hConsoleOutput, bAbsolute, lpConsoleWindow):
2318    _SetConsoleWindowInfo = windll.kernel32.SetConsoleWindowInfo
2319    _SetConsoleWindowInfo.argytpes = [HANDLE, BOOL, PSMALL_RECT]
2320    _SetConsoleWindowInfo.restype  = bool
2321    _SetConsoleWindowInfo.errcheck = RaiseIfZero
2322
2323    if hConsoleOutput is None:
2324        hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE)
2325    if isinstance(lpConsoleWindow, SMALL_RECT):
2326        ConsoleWindow = lpConsoleWindow
2327    else:
2328        ConsoleWindow = SMALL_RECT(*lpConsoleWindow)
2329    _SetConsoleWindowInfo(hConsoleOutput, bAbsolute, byref(ConsoleWindow))
2330
2331# BOOL WINAPI SetConsoleTextAttribute(
2332#   _In_  HANDLE hConsoleOutput,
2333#   _In_  WORD wAttributes
2334# );
2335def SetConsoleTextAttribute(hConsoleOutput = None, wAttributes = 0):
2336    _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
2337    _SetConsoleTextAttribute.argytpes = [HANDLE, WORD]
2338    _SetConsoleTextAttribute.restype  = bool
2339    _SetConsoleTextAttribute.errcheck = RaiseIfZero
2340
2341    if hConsoleOutput is None:
2342        hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE)
2343    _SetConsoleTextAttribute(hConsoleOutput, wAttributes)
2344
2345# HANDLE WINAPI CreateConsoleScreenBuffer(
2346#   _In_        DWORD dwDesiredAccess,
2347#   _In_        DWORD dwShareMode,
2348#   _In_opt_    const SECURITY_ATTRIBUTES *lpSecurityAttributes,
2349#   _In_        DWORD dwFlags,
2350#   _Reserved_  LPVOID lpScreenBufferData
2351# );
2352
2353# TODO
2354
2355# BOOL WINAPI AllocConsole(void);
2356def AllocConsole():
2357    _AllocConsole = windll.kernel32.AllocConsole
2358    _AllocConsole.argytpes = []
2359    _AllocConsole.restype  = bool
2360    _AllocConsole.errcheck = RaiseIfZero
2361    _AllocConsole()
2362
2363# BOOL WINAPI AttachConsole(
2364#   _In_  DWORD dwProcessId
2365# );
2366def AttachConsole(dwProcessId = ATTACH_PARENT_PROCESS):
2367    _AttachConsole = windll.kernel32.AttachConsole
2368    _AttachConsole.argytpes = [DWORD]
2369    _AttachConsole.restype  = bool
2370    _AttachConsole.errcheck = RaiseIfZero
2371    _AttachConsole(dwProcessId)
2372
2373# BOOL WINAPI FreeConsole(void);
2374def FreeConsole():
2375    _FreeConsole = windll.kernel32.FreeConsole
2376    _FreeConsole.argytpes = []
2377    _FreeConsole.restype  = bool
2378    _FreeConsole.errcheck = RaiseIfZero
2379    _FreeConsole()
2380
2381# DWORD WINAPI GetConsoleProcessList(
2382#   _Out_  LPDWORD lpdwProcessList,
2383#   _In_   DWORD dwProcessCount
2384# );
2385
2386# TODO
2387
2388# DWORD WINAPI GetConsoleTitle(
2389#   _Out_  LPTSTR lpConsoleTitle,
2390#   _In_   DWORD nSize
2391# );
2392
2393# TODO
2394
2395#BOOL WINAPI SetConsoleTitle(
2396#  _In_  LPCTSTR lpConsoleTitle
2397#);
2398
2399# TODO
2400
2401# COORD WINAPI GetLargestConsoleWindowSize(
2402#   _In_  HANDLE hConsoleOutput
2403# );
2404
2405# TODO
2406
2407# BOOL WINAPI GetConsoleHistoryInfo(
2408#   _Out_  PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo
2409# );
2410
2411# TODO
2412
2413#------------------------------------------------------------------------------
2414# DLL API
2415
2416# DWORD WINAPI GetDllDirectory(
2417#   __in   DWORD nBufferLength,
2418#   __out  LPTSTR lpBuffer
2419# );
2420def GetDllDirectoryA():
2421    _GetDllDirectoryA = windll.kernel32.GetDllDirectoryA
2422    _GetDllDirectoryA.argytpes = [DWORD, LPSTR]
2423    _GetDllDirectoryA.restype  = DWORD
2424
2425    nBufferLength = _GetDllDirectoryA(0, None)
2426    if nBufferLength == 0:
2427        return None
2428    lpBuffer = ctypes.create_string_buffer("", nBufferLength)
2429    _GetDllDirectoryA(nBufferLength, byref(lpBuffer))
2430    return lpBuffer.value
2431
2432def GetDllDirectoryW():
2433    _GetDllDirectoryW = windll.kernel32.GetDllDirectoryW
2434    _GetDllDirectoryW.argytpes = [DWORD, LPWSTR]
2435    _GetDllDirectoryW.restype  = DWORD
2436
2437    nBufferLength = _GetDllDirectoryW(0, None)
2438    if nBufferLength == 0:
2439        return None
2440    lpBuffer = ctypes.create_unicode_buffer(u"", nBufferLength)
2441    _GetDllDirectoryW(nBufferLength, byref(lpBuffer))
2442    return lpBuffer.value
2443
2444GetDllDirectory = GuessStringType(GetDllDirectoryA, GetDllDirectoryW)
2445
2446# BOOL WINAPI SetDllDirectory(
2447#   __in_opt  LPCTSTR lpPathName
2448# );
2449def SetDllDirectoryA(lpPathName = None):
2450    _SetDllDirectoryA = windll.kernel32.SetDllDirectoryA
2451    _SetDllDirectoryA.argytpes = [LPSTR]
2452    _SetDllDirectoryA.restype  = bool
2453    _SetDllDirectoryA.errcheck = RaiseIfZero
2454    _SetDllDirectoryA(lpPathName)
2455
2456def SetDllDirectoryW(lpPathName):
2457    _SetDllDirectoryW = windll.kernel32.SetDllDirectoryW
2458    _SetDllDirectoryW.argytpes = [LPWSTR]
2459    _SetDllDirectoryW.restype  = bool
2460    _SetDllDirectoryW.errcheck = RaiseIfZero
2461    _SetDllDirectoryW(lpPathName)
2462
2463SetDllDirectory = GuessStringType(SetDllDirectoryA, SetDllDirectoryW)
2464
2465# HMODULE WINAPI LoadLibrary(
2466#   __in  LPCTSTR lpFileName
2467# );
2468def LoadLibraryA(pszLibrary):
2469    _LoadLibraryA = windll.kernel32.LoadLibraryA
2470    _LoadLibraryA.argtypes = [LPSTR]
2471    _LoadLibraryA.restype  = HMODULE
2472    hModule = _LoadLibraryA(pszLibrary)
2473    if hModule == NULL:
2474        raise ctypes.WinError()
2475    return hModule
2476
2477def LoadLibraryW(pszLibrary):
2478    _LoadLibraryW = windll.kernel32.LoadLibraryW
2479    _LoadLibraryW.argtypes = [LPWSTR]
2480    _LoadLibraryW.restype  = HMODULE
2481    hModule = _LoadLibraryW(pszLibrary)
2482    if hModule == NULL:
2483        raise ctypes.WinError()
2484    return hModule
2485
2486LoadLibrary = GuessStringType(LoadLibraryA, LoadLibraryW)
2487
2488# HMODULE WINAPI LoadLibraryEx(
2489#   __in        LPCTSTR lpFileName,
2490#   __reserved  HANDLE hFile,
2491#   __in        DWORD dwFlags
2492# );
2493def LoadLibraryExA(pszLibrary, dwFlags = 0):
2494    _LoadLibraryExA = windll.kernel32.LoadLibraryExA
2495    _LoadLibraryExA.argtypes = [LPSTR, HANDLE, DWORD]
2496    _LoadLibraryExA.restype  = HMODULE
2497    hModule = _LoadLibraryExA(pszLibrary, NULL, dwFlags)
2498    if hModule == NULL:
2499        raise ctypes.WinError()
2500    return hModule
2501
2502def LoadLibraryExW(pszLibrary, dwFlags = 0):
2503    _LoadLibraryExW = windll.kernel32.LoadLibraryExW
2504    _LoadLibraryExW.argtypes = [LPWSTR, HANDLE, DWORD]
2505    _LoadLibraryExW.restype  = HMODULE
2506    hModule = _LoadLibraryExW(pszLibrary, NULL, dwFlags)
2507    if hModule == NULL:
2508        raise ctypes.WinError()
2509    return hModule
2510
2511LoadLibraryEx = GuessStringType(LoadLibraryExA, LoadLibraryExW)
2512
2513# HMODULE WINAPI GetModuleHandle(
2514#   __in_opt  LPCTSTR lpModuleName
2515# );
2516def GetModuleHandleA(lpModuleName):
2517    _GetModuleHandleA = windll.kernel32.GetModuleHandleA
2518    _GetModuleHandleA.argtypes = [LPSTR]
2519    _GetModuleHandleA.restype  = HMODULE
2520    hModule = _GetModuleHandleA(lpModuleName)
2521    if hModule == NULL:
2522        raise ctypes.WinError()
2523    return hModule
2524
2525def GetModuleHandleW(lpModuleName):
2526    _GetModuleHandleW = windll.kernel32.GetModuleHandleW
2527    _GetModuleHandleW.argtypes = [LPWSTR]
2528    _GetModuleHandleW.restype  = HMODULE
2529    hModule = _GetModuleHandleW(lpModuleName)
2530    if hModule == NULL:
2531        raise ctypes.WinError()
2532    return hModule
2533
2534GetModuleHandle = GuessStringType(GetModuleHandleA, GetModuleHandleW)
2535
2536# FARPROC WINAPI GetProcAddress(
2537#   __in  HMODULE hModule,
2538#   __in  LPCSTR lpProcName
2539# );
2540def GetProcAddressA(hModule, lpProcName):
2541    _GetProcAddress = windll.kernel32.GetProcAddress
2542    _GetProcAddress.argtypes = [HMODULE, LPVOID]
2543    _GetProcAddress.restype  = LPVOID
2544
2545    if type(lpProcName) in (type(0), type(long(0))):
2546        lpProcName = LPVOID(lpProcName)
2547        if lpProcName.value & (~0xFFFF):
2548            raise ValueError('Ordinal number too large: %d' % lpProcName.value)
2549    elif type(lpProcName) == type(compat.b("")):
2550        lpProcName = ctypes.c_char_p(lpProcName)
2551    else:
2552        raise TypeError(str(type(lpProcName)))
2553    return _GetProcAddress(hModule, lpProcName)
2554
2555GetProcAddressW = MakeWideVersion(GetProcAddressA)
2556GetProcAddress = GuessStringType(GetProcAddressA, GetProcAddressW)
2557
2558# BOOL WINAPI FreeLibrary(
2559#   __in  HMODULE hModule
2560# );
2561def FreeLibrary(hModule):
2562    _FreeLibrary = windll.kernel32.FreeLibrary
2563    _FreeLibrary.argtypes = [HMODULE]
2564    _FreeLibrary.restype  = bool
2565    _FreeLibrary.errcheck = RaiseIfZero
2566    _FreeLibrary(hModule)
2567
2568# PVOID WINAPI RtlPcToFileHeader(
2569#   __in   PVOID PcValue,
2570#   __out  PVOID *BaseOfImage
2571# );
2572def RtlPcToFileHeader(PcValue):
2573    _RtlPcToFileHeader = windll.kernel32.RtlPcToFileHeader
2574    _RtlPcToFileHeader.argtypes = [PVOID, POINTER(PVOID)]
2575    _RtlPcToFileHeader.restype  = PRUNTIME_FUNCTION
2576
2577    BaseOfImage = PVOID(0)
2578    _RtlPcToFileHeader(PcValue, byref(BaseOfImage))
2579    return BaseOfImage.value
2580
2581#------------------------------------------------------------------------------
2582# File API and related
2583
2584# BOOL WINAPI GetHandleInformation(
2585#   __in   HANDLE hObject,
2586#   __out  LPDWORD lpdwFlags
2587# );
2588def GetHandleInformation(hObject):
2589    _GetHandleInformation = windll.kernel32.GetHandleInformation
2590    _GetHandleInformation.argtypes = [HANDLE, PDWORD]
2591    _GetHandleInformation.restype  = bool
2592    _GetHandleInformation.errcheck = RaiseIfZero
2593
2594    dwFlags = DWORD(0)
2595    _GetHandleInformation(hObject, byref(dwFlags))
2596    return dwFlags.value
2597
2598# BOOL WINAPI SetHandleInformation(
2599#   __in  HANDLE hObject,
2600#   __in  DWORD dwMask,
2601#   __in  DWORD dwFlags
2602# );
2603def SetHandleInformation(hObject, dwMask, dwFlags):
2604    _SetHandleInformation = windll.kernel32.SetHandleInformation
2605    _SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD]
2606    _SetHandleInformation.restype  = bool
2607    _SetHandleInformation.errcheck = RaiseIfZero
2608    _SetHandleInformation(hObject, dwMask, dwFlags)
2609
2610# UINT WINAPI GetWindowModuleFileName(
2611#   __in   HWND hwnd,
2612#   __out  LPTSTR lpszFileName,
2613#   __in   UINT cchFileNameMax
2614# );
2615# Not included because it doesn't work in other processes.
2616# See: http://support.microsoft.com/?id=228469
2617
2618# BOOL WINAPI QueryFullProcessImageName(
2619#   __in     HANDLE hProcess,
2620#   __in     DWORD dwFlags,
2621#   __out    LPTSTR lpExeName,
2622#   __inout  PDWORD lpdwSize
2623# );
2624def QueryFullProcessImageNameA(hProcess, dwFlags = 0):
2625    _QueryFullProcessImageNameA = windll.kernel32.QueryFullProcessImageNameA
2626    _QueryFullProcessImageNameA.argtypes = [HANDLE, DWORD, LPSTR, PDWORD]
2627    _QueryFullProcessImageNameA.restype  = bool
2628
2629    dwSize = MAX_PATH
2630    while 1:
2631        lpdwSize = DWORD(dwSize)
2632        lpExeName = ctypes.create_string_buffer('', lpdwSize.value + 1)
2633        success = _QueryFullProcessImageNameA(hProcess, dwFlags, lpExeName, byref(lpdwSize))
2634        if success and 0 < lpdwSize.value < dwSize:
2635            break
2636        error = GetLastError()
2637        if error != ERROR_INSUFFICIENT_BUFFER:
2638            raise ctypes.WinError(error)
2639        dwSize = dwSize + 256
2640        if dwSize > 0x1000:
2641            # this prevents an infinite loop in Windows 2008 when the path has spaces,
2642            # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4
2643            raise ctypes.WinError(error)
2644    return lpExeName.value
2645
2646def QueryFullProcessImageNameW(hProcess, dwFlags = 0):
2647    _QueryFullProcessImageNameW = windll.kernel32.QueryFullProcessImageNameW
2648    _QueryFullProcessImageNameW.argtypes = [HANDLE, DWORD, LPWSTR, PDWORD]
2649    _QueryFullProcessImageNameW.restype  = bool
2650
2651    dwSize = MAX_PATH
2652    while 1:
2653        lpdwSize = DWORD(dwSize)
2654        lpExeName = ctypes.create_unicode_buffer('', lpdwSize.value + 1)
2655        success = _QueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, byref(lpdwSize))
2656        if success and 0 < lpdwSize.value < dwSize:
2657            break
2658        error = GetLastError()
2659        if error != ERROR_INSUFFICIENT_BUFFER:
2660            raise ctypes.WinError(error)
2661        dwSize = dwSize + 256
2662        if dwSize > 0x1000:
2663            # this prevents an infinite loop in Windows 2008 when the path has spaces,
2664            # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4
2665            raise ctypes.WinError(error)
2666    return lpExeName.value
2667
2668QueryFullProcessImageName = GuessStringType(QueryFullProcessImageNameA, QueryFullProcessImageNameW)
2669
2670# DWORD WINAPI GetLogicalDriveStrings(
2671#   __in   DWORD nBufferLength,
2672#   __out  LPTSTR lpBuffer
2673# );
2674def GetLogicalDriveStringsA():
2675    _GetLogicalDriveStringsA = ctypes.windll.kernel32.GetLogicalDriveStringsA
2676    _GetLogicalDriveStringsA.argtypes = [DWORD, LPSTR]
2677    _GetLogicalDriveStringsA.restype  = DWORD
2678    _GetLogicalDriveStringsA.errcheck = RaiseIfZero
2679
2680    nBufferLength = (4 * 26) + 1    # "X:\\\0" from A to Z plus empty string
2681    lpBuffer = ctypes.create_string_buffer('', nBufferLength)
2682    _GetLogicalDriveStringsA(nBufferLength, lpBuffer)
2683    drive_strings = list()
2684    string_p = addressof(lpBuffer)
2685    sizeof_char = sizeof(ctypes.c_char)
2686    while True:
2687        string_v = ctypes.string_at(string_p)
2688        if string_v == '':
2689            break
2690        drive_strings.append(string_v)
2691        string_p += len(string_v) + sizeof_char
2692    return drive_strings
2693
2694def GetLogicalDriveStringsW():
2695    _GetLogicalDriveStringsW = ctypes.windll.kernel32.GetLogicalDriveStringsW
2696    _GetLogicalDriveStringsW.argtypes = [DWORD, LPWSTR]
2697    _GetLogicalDriveStringsW.restype  = DWORD
2698    _GetLogicalDriveStringsW.errcheck = RaiseIfZero
2699
2700    nBufferLength = (4 * 26) + 1    # "X:\\\0" from A to Z plus empty string
2701    lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength)
2702    _GetLogicalDriveStringsW(nBufferLength, lpBuffer)
2703    drive_strings = list()
2704    string_p = addressof(lpBuffer)
2705    sizeof_wchar = sizeof(ctypes.c_wchar)
2706    while True:
2707        string_v = ctypes.wstring_at(string_p)
2708        if string_v == u'':
2709            break
2710        drive_strings.append(string_v)
2711        string_p += (len(string_v) * sizeof_wchar) + sizeof_wchar
2712    return drive_strings
2713
2714##def GetLogicalDriveStringsA():
2715##    _GetLogicalDriveStringsA = windll.kernel32.GetLogicalDriveStringsA
2716##    _GetLogicalDriveStringsA.argtypes = [DWORD, LPSTR]
2717##    _GetLogicalDriveStringsA.restype  = DWORD
2718##    _GetLogicalDriveStringsA.errcheck = RaiseIfZero
2719##
2720##    nBufferLength = (4 * 26) + 1    # "X:\\\0" from A to Z plus empty string
2721##    lpBuffer = ctypes.create_string_buffer('', nBufferLength)
2722##    _GetLogicalDriveStringsA(nBufferLength, lpBuffer)
2723##    result = list()
2724##    index = 0
2725##    while 1:
2726##        string = list()
2727##        while 1:
2728##            character = lpBuffer[index]
2729##            index = index + 1
2730##            if character == '\0':
2731##                break
2732##            string.append(character)
2733##        if not string:
2734##            break
2735##        result.append(''.join(string))
2736##    return result
2737##
2738##def GetLogicalDriveStringsW():
2739##    _GetLogicalDriveStringsW = windll.kernel32.GetLogicalDriveStringsW
2740##    _GetLogicalDriveStringsW.argtypes = [DWORD, LPWSTR]
2741##    _GetLogicalDriveStringsW.restype  = DWORD
2742##    _GetLogicalDriveStringsW.errcheck = RaiseIfZero
2743##
2744##    nBufferLength = (4 * 26) + 1    # "X:\\\0" from A to Z plus empty string
2745##    lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength)
2746##    _GetLogicalDriveStringsW(nBufferLength, lpBuffer)
2747##    result = list()
2748##    index = 0
2749##    while 1:
2750##        string = list()
2751##        while 1:
2752##            character = lpBuffer[index]
2753##            index = index + 1
2754##            if character == u'\0':
2755##                break
2756##            string.append(character)
2757##        if not string:
2758##            break
2759##        result.append(u''.join(string))
2760##    return result
2761
2762GetLogicalDriveStrings = GuessStringType(GetLogicalDriveStringsA, GetLogicalDriveStringsW)
2763
2764# DWORD WINAPI QueryDosDevice(
2765#   __in_opt  LPCTSTR lpDeviceName,
2766#   __out     LPTSTR lpTargetPath,
2767#   __in      DWORD ucchMax
2768# );
2769def QueryDosDeviceA(lpDeviceName = None):
2770    _QueryDosDeviceA = windll.kernel32.QueryDosDeviceA
2771    _QueryDosDeviceA.argtypes = [LPSTR, LPSTR, DWORD]
2772    _QueryDosDeviceA.restype  = DWORD
2773    _QueryDosDeviceA.errcheck = RaiseIfZero
2774
2775    if not lpDeviceName:
2776        lpDeviceName = None
2777    ucchMax = 0x1000
2778    lpTargetPath = ctypes.create_string_buffer('', ucchMax)
2779    _QueryDosDeviceA(lpDeviceName, lpTargetPath, ucchMax)
2780    return lpTargetPath.value
2781
2782def QueryDosDeviceW(lpDeviceName):
2783    _QueryDosDeviceW = windll.kernel32.QueryDosDeviceW
2784    _QueryDosDeviceW.argtypes = [LPWSTR, LPWSTR, DWORD]
2785    _QueryDosDeviceW.restype  = DWORD
2786    _QueryDosDeviceW.errcheck = RaiseIfZero
2787
2788    if not lpDeviceName:
2789        lpDeviceName = None
2790    ucchMax = 0x1000
2791    lpTargetPath = ctypes.create_unicode_buffer(u'', ucchMax)
2792    _QueryDosDeviceW(lpDeviceName, lpTargetPath, ucchMax)
2793    return lpTargetPath.value
2794
2795QueryDosDevice = GuessStringType(QueryDosDeviceA, QueryDosDeviceW)
2796
2797# LPVOID WINAPI MapViewOfFile(
2798#   __in  HANDLE hFileMappingObject,
2799#   __in  DWORD dwDesiredAccess,
2800#   __in  DWORD dwFileOffsetHigh,
2801#   __in  DWORD dwFileOffsetLow,
2802#   __in  SIZE_T dwNumberOfBytesToMap
2803# );
2804def MapViewOfFile(hFileMappingObject, dwDesiredAccess = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, dwFileOffsetHigh = 0, dwFileOffsetLow = 0, dwNumberOfBytesToMap = 0):
2805    _MapViewOfFile = windll.kernel32.MapViewOfFile
2806    _MapViewOfFile.argtypes = [HANDLE, DWORD, DWORD, DWORD, SIZE_T]
2807    _MapViewOfFile.restype  = LPVOID
2808    lpBaseAddress = _MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap)
2809    if lpBaseAddress == NULL:
2810        raise ctypes.WinError()
2811    return lpBaseAddress
2812
2813# BOOL WINAPI UnmapViewOfFile(
2814#   __in  LPCVOID lpBaseAddress
2815# );
2816def UnmapViewOfFile(lpBaseAddress):
2817    _UnmapViewOfFile = windll.kernel32.UnmapViewOfFile
2818    _UnmapViewOfFile.argtypes = [LPVOID]
2819    _UnmapViewOfFile.restype  = bool
2820    _UnmapViewOfFile.errcheck = RaiseIfZero
2821    _UnmapViewOfFile(lpBaseAddress)
2822
2823# HANDLE WINAPI OpenFileMapping(
2824#   __in  DWORD dwDesiredAccess,
2825#   __in  BOOL bInheritHandle,
2826#   __in  LPCTSTR lpName
2827# );
2828def OpenFileMappingA(dwDesiredAccess, bInheritHandle, lpName):
2829    _OpenFileMappingA = windll.kernel32.OpenFileMappingA
2830    _OpenFileMappingA.argtypes = [DWORD, BOOL, LPSTR]
2831    _OpenFileMappingA.restype  = HANDLE
2832    _OpenFileMappingA.errcheck = RaiseIfZero
2833    hFileMappingObject = _OpenFileMappingA(dwDesiredAccess, bool(bInheritHandle), lpName)
2834    return FileMappingHandle(hFileMappingObject)
2835
2836def OpenFileMappingW(dwDesiredAccess, bInheritHandle, lpName):
2837    _OpenFileMappingW = windll.kernel32.OpenFileMappingW
2838    _OpenFileMappingW.argtypes = [DWORD, BOOL, LPWSTR]
2839    _OpenFileMappingW.restype  = HANDLE
2840    _OpenFileMappingW.errcheck = RaiseIfZero
2841    hFileMappingObject = _OpenFileMappingW(dwDesiredAccess, bool(bInheritHandle), lpName)
2842    return FileMappingHandle(hFileMappingObject)
2843
2844OpenFileMapping = GuessStringType(OpenFileMappingA, OpenFileMappingW)
2845
2846# HANDLE WINAPI CreateFileMapping(
2847#   __in      HANDLE hFile,
2848#   __in_opt  LPSECURITY_ATTRIBUTES lpAttributes,
2849#   __in      DWORD flProtect,
2850#   __in      DWORD dwMaximumSizeHigh,
2851#   __in      DWORD dwMaximumSizeLow,
2852#   __in_opt  LPCTSTR lpName
2853# );
2854def CreateFileMappingA(hFile, lpAttributes = None, flProtect = PAGE_EXECUTE_READWRITE, dwMaximumSizeHigh = 0, dwMaximumSizeLow = 0, lpName = None):
2855    _CreateFileMappingA = windll.kernel32.CreateFileMappingA
2856    _CreateFileMappingA.argtypes = [HANDLE, LPVOID, DWORD, DWORD, DWORD, LPSTR]
2857    _CreateFileMappingA.restype  = HANDLE
2858    _CreateFileMappingA.errcheck = RaiseIfZero
2859
2860    if lpAttributes:
2861        lpAttributes = ctypes.pointer(lpAttributes)
2862    if not lpName:
2863        lpName = None
2864    hFileMappingObject = _CreateFileMappingA(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName)
2865    return FileMappingHandle(hFileMappingObject)
2866
2867def CreateFileMappingW(hFile, lpAttributes = None, flProtect = PAGE_EXECUTE_READWRITE, dwMaximumSizeHigh = 0, dwMaximumSizeLow = 0, lpName = None):
2868    _CreateFileMappingW = windll.kernel32.CreateFileMappingW
2869    _CreateFileMappingW.argtypes = [HANDLE, LPVOID, DWORD, DWORD, DWORD, LPWSTR]
2870    _CreateFileMappingW.restype  = HANDLE
2871    _CreateFileMappingW.errcheck = RaiseIfZero
2872
2873    if lpAttributes:
2874        lpAttributes = ctypes.pointer(lpAttributes)
2875    if not lpName:
2876        lpName = None
2877    hFileMappingObject = _CreateFileMappingW(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName)
2878    return FileMappingHandle(hFileMappingObject)
2879
2880CreateFileMapping = GuessStringType(CreateFileMappingA, CreateFileMappingW)
2881
2882# HANDLE WINAPI CreateFile(
2883#   __in      LPCTSTR lpFileName,
2884#   __in      DWORD dwDesiredAccess,
2885#   __in      DWORD dwShareMode,
2886#   __in_opt  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2887#   __in      DWORD dwCreationDisposition,
2888#   __in      DWORD dwFlagsAndAttributes,
2889#   __in_opt  HANDLE hTemplateFile
2890# );
2891def CreateFileA(lpFileName, dwDesiredAccess = GENERIC_ALL, dwShareMode = 0, lpSecurityAttributes = None, dwCreationDisposition = OPEN_ALWAYS, dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, hTemplateFile = None):
2892    _CreateFileA = windll.kernel32.CreateFileA
2893    _CreateFileA.argtypes = [LPSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE]
2894    _CreateFileA.restype  = HANDLE
2895
2896    if not lpFileName:
2897        lpFileName = None
2898    if lpSecurityAttributes:
2899        lpSecurityAttributes = ctypes.pointer(lpSecurityAttributes)
2900    hFile = _CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
2901    if hFile == INVALID_HANDLE_VALUE:
2902        raise ctypes.WinError()
2903    return FileHandle(hFile)
2904
2905def CreateFileW(lpFileName, dwDesiredAccess = GENERIC_ALL, dwShareMode = 0, lpSecurityAttributes = None, dwCreationDisposition = OPEN_ALWAYS, dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, hTemplateFile = None):
2906    _CreateFileW = windll.kernel32.CreateFileW
2907    _CreateFileW.argtypes = [LPWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE]
2908    _CreateFileW.restype  = HANDLE
2909
2910    if not lpFileName:
2911        lpFileName = None
2912    if lpSecurityAttributes:
2913        lpSecurityAttributes = ctypes.pointer(lpSecurityAttributes)
2914    hFile = _CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
2915    if hFile == INVALID_HANDLE_VALUE:
2916        raise ctypes.WinError()
2917    return FileHandle(hFile)
2918
2919CreateFile = GuessStringType(CreateFileA, CreateFileW)
2920
2921# BOOL WINAPI FlushFileBuffers(
2922#   __in  HANDLE hFile
2923# );
2924def FlushFileBuffers(hFile):
2925    _FlushFileBuffers = windll.kernel32.FlushFileBuffers
2926    _FlushFileBuffers.argtypes = [HANDLE]
2927    _FlushFileBuffers.restype  = bool
2928    _FlushFileBuffers.errcheck = RaiseIfZero
2929    _FlushFileBuffers(hFile)
2930
2931# BOOL WINAPI FlushViewOfFile(
2932#   __in  LPCVOID lpBaseAddress,
2933#   __in  SIZE_T dwNumberOfBytesToFlush
2934# );
2935def FlushViewOfFile(lpBaseAddress, dwNumberOfBytesToFlush = 0):
2936    _FlushViewOfFile = windll.kernel32.FlushViewOfFile
2937    _FlushViewOfFile.argtypes = [LPVOID, SIZE_T]
2938    _FlushViewOfFile.restype  = bool
2939    _FlushViewOfFile.errcheck = RaiseIfZero
2940    _FlushViewOfFile(lpBaseAddress, dwNumberOfBytesToFlush)
2941
2942# DWORD WINAPI SearchPath(
2943#   __in_opt   LPCTSTR lpPath,
2944#   __in       LPCTSTR lpFileName,
2945#   __in_opt   LPCTSTR lpExtension,
2946#   __in       DWORD nBufferLength,
2947#   __out      LPTSTR lpBuffer,
2948#   __out_opt  LPTSTR *lpFilePart
2949# );
2950def SearchPathA(lpPath, lpFileName, lpExtension):
2951    _SearchPathA = windll.kernel32.SearchPathA
2952    _SearchPathA.argtypes = [LPSTR, LPSTR, LPSTR, DWORD, LPSTR, POINTER(LPSTR)]
2953    _SearchPathA.restype  = DWORD
2954    _SearchPathA.errcheck = RaiseIfZero
2955
2956    if not lpPath:
2957        lpPath = None
2958    if not lpExtension:
2959        lpExtension = None
2960    nBufferLength = _SearchPathA(lpPath, lpFileName, lpExtension, 0, None, None)
2961    lpBuffer = ctypes.create_string_buffer('', nBufferLength + 1)
2962    lpFilePart = LPSTR()
2963    _SearchPathA(lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, byref(lpFilePart))
2964    lpFilePart = lpFilePart.value
2965    lpBuffer = lpBuffer.value
2966    if lpBuffer == '':
2967        if GetLastError() == ERROR_SUCCESS:
2968            raise ctypes.WinError(ERROR_FILE_NOT_FOUND)
2969        raise ctypes.WinError()
2970    return (lpBuffer, lpFilePart)
2971
2972def SearchPathW(lpPath, lpFileName, lpExtension):
2973    _SearchPathW = windll.kernel32.SearchPathW
2974    _SearchPathW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, POINTER(LPWSTR)]
2975    _SearchPathW.restype  = DWORD
2976    _SearchPathW.errcheck = RaiseIfZero
2977
2978    if not lpPath:
2979        lpPath = None
2980    if not lpExtension:
2981        lpExtension = None
2982    nBufferLength = _SearchPathW(lpPath, lpFileName, lpExtension, 0, None, None)
2983    lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength + 1)
2984    lpFilePart = LPWSTR()
2985    _SearchPathW(lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, byref(lpFilePart))
2986    lpFilePart = lpFilePart.value
2987    lpBuffer = lpBuffer.value
2988    if lpBuffer == u'':
2989        if GetLastError() == ERROR_SUCCESS:
2990            raise ctypes.WinError(ERROR_FILE_NOT_FOUND)
2991        raise ctypes.WinError()
2992    return (lpBuffer, lpFilePart)
2993
2994SearchPath = GuessStringType(SearchPathA, SearchPathW)
2995
2996# BOOL SetSearchPathMode(
2997#   __in  DWORD Flags
2998# );
2999def SetSearchPathMode(Flags):
3000    _SetSearchPathMode = windll.kernel32.SetSearchPathMode
3001    _SetSearchPathMode.argtypes = [DWORD]
3002    _SetSearchPathMode.restype  = bool
3003    _SetSearchPathMode.errcheck = RaiseIfZero
3004    _SetSearchPathMode(Flags)
3005
3006# BOOL WINAPI DeviceIoControl(
3007#   __in         HANDLE hDevice,
3008#   __in         DWORD dwIoControlCode,
3009#   __in_opt     LPVOID lpInBuffer,
3010#   __in         DWORD nInBufferSize,
3011#   __out_opt    LPVOID lpOutBuffer,
3012#   __in         DWORD nOutBufferSize,
3013#   __out_opt    LPDWORD lpBytesReturned,
3014#   __inout_opt  LPOVERLAPPED lpOverlapped
3015# );
3016def DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpOverlapped):
3017    _DeviceIoControl = windll.kernel32.DeviceIoControl
3018    _DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED]
3019    _DeviceIoControl.restype  = bool
3020    _DeviceIoControl.errcheck = RaiseIfZero
3021
3022    if not lpInBuffer:
3023        lpInBuffer = None
3024    if not lpOutBuffer:
3025        lpOutBuffer = None
3026    if lpOverlapped:
3027        lpOverlapped = ctypes.pointer(lpOverlapped)
3028    lpBytesReturned = DWORD(0)
3029    _DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, byref(lpBytesReturned), lpOverlapped)
3030    return lpBytesReturned.value
3031
3032# BOOL GetFileInformationByHandle(
3033#   HANDLE hFile,
3034#   LPBY_HANDLE_FILE_INFORMATION lpFileInformation
3035# );
3036def GetFileInformationByHandle(hFile):
3037    _GetFileInformationByHandle = windll.kernel32.GetFileInformationByHandle
3038    _GetFileInformationByHandle.argtypes = [HANDLE, LPBY_HANDLE_FILE_INFORMATION]
3039    _GetFileInformationByHandle.restype  = bool
3040    _GetFileInformationByHandle.errcheck = RaiseIfZero
3041
3042    lpFileInformation = BY_HANDLE_FILE_INFORMATION()
3043    _GetFileInformationByHandle(hFile, byref(lpFileInformation))
3044    return lpFileInformation
3045
3046# BOOL WINAPI GetFileInformationByHandleEx(
3047#   __in   HANDLE hFile,
3048#   __in   FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
3049#   __out  LPVOID lpFileInformation,
3050#   __in   DWORD dwBufferSize
3051# );
3052def GetFileInformationByHandleEx(hFile, FileInformationClass, lpFileInformation, dwBufferSize):
3053    _GetFileInformationByHandleEx = windll.kernel32.GetFileInformationByHandleEx
3054    _GetFileInformationByHandleEx.argtypes = [HANDLE, DWORD, LPVOID, DWORD]
3055    _GetFileInformationByHandleEx.restype  = bool
3056    _GetFileInformationByHandleEx.errcheck = RaiseIfZero
3057    # XXX TODO
3058    # support each FileInformationClass so the function can allocate the
3059    # corresponding structure for the lpFileInformation parameter
3060    _GetFileInformationByHandleEx(hFile, FileInformationClass, byref(lpFileInformation), dwBufferSize)
3061
3062# DWORD WINAPI GetFinalPathNameByHandle(
3063#   __in   HANDLE hFile,
3064#   __out  LPTSTR lpszFilePath,
3065#   __in   DWORD cchFilePath,
3066#   __in   DWORD dwFlags
3067# );
3068def GetFinalPathNameByHandleA(hFile, dwFlags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS):
3069    _GetFinalPathNameByHandleA = windll.kernel32.GetFinalPathNameByHandleA
3070    _GetFinalPathNameByHandleA.argtypes = [HANDLE, LPSTR, DWORD, DWORD]
3071    _GetFinalPathNameByHandleA.restype  = DWORD
3072
3073    cchFilePath = _GetFinalPathNameByHandleA(hFile, None, 0, dwFlags)
3074    if cchFilePath == 0:
3075        raise ctypes.WinError()
3076    lpszFilePath = ctypes.create_string_buffer('', cchFilePath + 1)
3077    nCopied = _GetFinalPathNameByHandleA(hFile, lpszFilePath, cchFilePath, dwFlags)
3078    if nCopied <= 0 or nCopied > cchFilePath:
3079        raise ctypes.WinError()
3080    return lpszFilePath.value
3081
3082def GetFinalPathNameByHandleW(hFile, dwFlags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS):
3083    _GetFinalPathNameByHandleW = windll.kernel32.GetFinalPathNameByHandleW
3084    _GetFinalPathNameByHandleW.argtypes = [HANDLE, LPWSTR, DWORD, DWORD]
3085    _GetFinalPathNameByHandleW.restype  = DWORD
3086
3087    cchFilePath = _GetFinalPathNameByHandleW(hFile, None, 0, dwFlags)
3088    if cchFilePath == 0:
3089        raise ctypes.WinError()
3090    lpszFilePath = ctypes.create_unicode_buffer(u'', cchFilePath + 1)
3091    nCopied = _GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
3092    if nCopied <= 0 or nCopied > cchFilePath:
3093        raise ctypes.WinError()
3094    return lpszFilePath.value
3095
3096GetFinalPathNameByHandle = GuessStringType(GetFinalPathNameByHandleA, GetFinalPathNameByHandleW)
3097
3098# DWORD GetFullPathName(
3099#   LPCTSTR lpFileName,
3100#   DWORD nBufferLength,
3101#   LPTSTR lpBuffer,
3102#   LPTSTR* lpFilePart
3103# );
3104def GetFullPathNameA(lpFileName):
3105    _GetFullPathNameA = windll.kernel32.GetFullPathNameA
3106    _GetFullPathNameA.argtypes = [LPSTR, DWORD, LPSTR, POINTER(LPSTR)]
3107    _GetFullPathNameA.restype  = DWORD
3108
3109    nBufferLength = _GetFullPathNameA(lpFileName, 0, None, None)
3110    if nBufferLength <= 0:
3111        raise ctypes.WinError()
3112    lpBuffer   = ctypes.create_string_buffer('', nBufferLength + 1)
3113    lpFilePart = LPSTR()
3114    nCopied = _GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, byref(lpFilePart))
3115    if nCopied > nBufferLength or nCopied == 0:
3116        raise ctypes.WinError()
3117    return lpBuffer.value, lpFilePart.value
3118
3119def GetFullPathNameW(lpFileName):
3120    _GetFullPathNameW = windll.kernel32.GetFullPathNameW
3121    _GetFullPathNameW.argtypes = [LPWSTR, DWORD, LPWSTR, POINTER(LPWSTR)]
3122    _GetFullPathNameW.restype  = DWORD
3123
3124    nBufferLength = _GetFullPathNameW(lpFileName, 0, None, None)
3125    if nBufferLength <= 0:
3126        raise ctypes.WinError()
3127    lpBuffer   = ctypes.create_unicode_buffer(u'', nBufferLength + 1)
3128    lpFilePart = LPWSTR()
3129    nCopied = _GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, byref(lpFilePart))
3130    if nCopied > nBufferLength or nCopied == 0:
3131        raise ctypes.WinError()
3132    return lpBuffer.value, lpFilePart.value
3133
3134GetFullPathName = GuessStringType(GetFullPathNameA, GetFullPathNameW)
3135
3136# DWORD WINAPI GetTempPath(
3137#   __in   DWORD nBufferLength,
3138#   __out  LPTSTR lpBuffer
3139# );
3140def GetTempPathA():
3141    _GetTempPathA = windll.kernel32.GetTempPathA
3142    _GetTempPathA.argtypes = [DWORD, LPSTR]
3143    _GetTempPathA.restype  = DWORD
3144
3145    nBufferLength = _GetTempPathA(0, None)
3146    if nBufferLength <= 0:
3147        raise ctypes.WinError()
3148    lpBuffer = ctypes.create_string_buffer('', nBufferLength)
3149    nCopied = _GetTempPathA(nBufferLength, lpBuffer)
3150    if nCopied > nBufferLength or nCopied == 0:
3151        raise ctypes.WinError()
3152    return lpBuffer.value
3153
3154def GetTempPathW():
3155    _GetTempPathW = windll.kernel32.GetTempPathW
3156    _GetTempPathW.argtypes = [DWORD, LPWSTR]
3157    _GetTempPathW.restype  = DWORD
3158
3159    nBufferLength = _GetTempPathW(0, None)
3160    if nBufferLength <= 0:
3161        raise ctypes.WinError()
3162    lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength)
3163    nCopied = _GetTempPathW(nBufferLength, lpBuffer)
3164    if nCopied > nBufferLength or nCopied == 0:
3165        raise ctypes.WinError()
3166    return lpBuffer.value
3167
3168GetTempPath = GuessStringType(GetTempPathA, GetTempPathW)
3169
3170# UINT WINAPI GetTempFileName(
3171#   __in   LPCTSTR lpPathName,
3172#   __in   LPCTSTR lpPrefixString,
3173#   __in   UINT uUnique,
3174#   __out  LPTSTR lpTempFileName
3175# );
3176def GetTempFileNameA(lpPathName = None, lpPrefixString = "TMP", uUnique = 0):
3177    _GetTempFileNameA = windll.kernel32.GetTempFileNameA
3178    _GetTempFileNameA.argtypes = [LPSTR, LPSTR, UINT, LPSTR]
3179    _GetTempFileNameA.restype  = UINT
3180
3181    if lpPathName is None:
3182        lpPathName = GetTempPathA()
3183    lpTempFileName = ctypes.create_string_buffer('', MAX_PATH)
3184    uUnique = _GetTempFileNameA(lpPathName, lpPrefixString, uUnique, lpTempFileName)
3185    if uUnique == 0:
3186        raise ctypes.WinError()
3187    return lpTempFileName.value, uUnique
3188
3189def GetTempFileNameW(lpPathName = None, lpPrefixString = u"TMP", uUnique = 0):
3190    _GetTempFileNameW = windll.kernel32.GetTempFileNameW
3191    _GetTempFileNameW.argtypes = [LPWSTR, LPWSTR, UINT, LPWSTR]
3192    _GetTempFileNameW.restype  = UINT
3193
3194    if lpPathName is None:
3195        lpPathName = GetTempPathW()
3196    lpTempFileName = ctypes.create_unicode_buffer(u'', MAX_PATH)
3197    uUnique = _GetTempFileNameW(lpPathName, lpPrefixString, uUnique, lpTempFileName)
3198    if uUnique == 0:
3199        raise ctypes.WinError()
3200    return lpTempFileName.value, uUnique
3201
3202GetTempFileName = GuessStringType(GetTempFileNameA, GetTempFileNameW)
3203
3204# DWORD WINAPI GetCurrentDirectory(
3205#   __in   DWORD nBufferLength,
3206#   __out  LPTSTR lpBuffer
3207# );
3208def GetCurrentDirectoryA():
3209    _GetCurrentDirectoryA = windll.kernel32.GetCurrentDirectoryA
3210    _GetCurrentDirectoryA.argtypes = [DWORD, LPSTR]
3211    _GetCurrentDirectoryA.restype  = DWORD
3212
3213    nBufferLength = _GetCurrentDirectoryA(0, None)
3214    if nBufferLength <= 0:
3215        raise ctypes.WinError()
3216    lpBuffer = ctypes.create_string_buffer('', nBufferLength)
3217    nCopied = _GetCurrentDirectoryA(nBufferLength, lpBuffer)
3218    if nCopied > nBufferLength or nCopied == 0:
3219        raise ctypes.WinError()
3220    return lpBuffer.value
3221
3222def GetCurrentDirectoryW():
3223    _GetCurrentDirectoryW = windll.kernel32.GetCurrentDirectoryW
3224    _GetCurrentDirectoryW.argtypes = [DWORD, LPWSTR]
3225    _GetCurrentDirectoryW.restype  = DWORD
3226
3227    nBufferLength = _GetCurrentDirectoryW(0, None)
3228    if nBufferLength <= 0:
3229        raise ctypes.WinError()
3230    lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength)
3231    nCopied = _GetCurrentDirectoryW(nBufferLength, lpBuffer)
3232    if nCopied > nBufferLength or nCopied == 0:
3233        raise ctypes.WinError()
3234    return lpBuffer.value
3235
3236GetCurrentDirectory = GuessStringType(GetCurrentDirectoryA, GetCurrentDirectoryW)
3237
3238#------------------------------------------------------------------------------
3239# Contrl-C handler
3240
3241# BOOL WINAPI HandlerRoutine(
3242#   __in  DWORD dwCtrlType
3243# );
3244PHANDLER_ROUTINE = ctypes.WINFUNCTYPE(BOOL, DWORD)
3245
3246# BOOL WINAPI SetConsoleCtrlHandler(
3247#   __in_opt  PHANDLER_ROUTINE HandlerRoutine,
3248#   __in      BOOL Add
3249# );
3250def SetConsoleCtrlHandler(HandlerRoutine = None, Add = True):
3251    _SetConsoleCtrlHandler = windll.kernel32.SetConsoleCtrlHandler
3252    _SetConsoleCtrlHandler.argtypes = [PHANDLER_ROUTINE, BOOL]
3253    _SetConsoleCtrlHandler.restype  = bool
3254    _SetConsoleCtrlHandler.errcheck = RaiseIfZero
3255    _SetConsoleCtrlHandler(HandlerRoutine, bool(Add))
3256    # we can't automagically transform Python functions to PHANDLER_ROUTINE
3257    # because a) the actual pointer value is meaningful to the API
3258    # and b) if it gets garbage collected bad things would happen
3259
3260# BOOL WINAPI GenerateConsoleCtrlEvent(
3261#   __in  DWORD dwCtrlEvent,
3262#   __in  DWORD dwProcessGroupId
3263# );
3264def GenerateConsoleCtrlEvent(dwCtrlEvent, dwProcessGroupId):
3265    _GenerateConsoleCtrlEvent = windll.kernel32.GenerateConsoleCtrlEvent
3266    _GenerateConsoleCtrlEvent.argtypes = [DWORD, DWORD]
3267    _GenerateConsoleCtrlEvent.restype  = bool
3268    _GenerateConsoleCtrlEvent.errcheck = RaiseIfZero
3269    _GenerateConsoleCtrlEvent(dwCtrlEvent, dwProcessGroupId)
3270
3271#------------------------------------------------------------------------------
3272# Synchronization API
3273
3274# XXX NOTE
3275#
3276# Instead of waiting forever, we wait for a small period of time and loop.
3277# This is a workaround for an unwanted behavior of psyco-accelerated code:
3278# you can't interrupt a blocking call using Ctrl+C, because signal processing
3279# is only done between C calls.
3280#
3281# Also see: bug #2793618 in Psyco project
3282# http://sourceforge.net/tracker/?func=detail&aid=2793618&group_id=41036&atid=429622
3283
3284# DWORD WINAPI WaitForSingleObject(
3285#   HANDLE hHandle,
3286#   DWORD dwMilliseconds
3287# );
3288def WaitForSingleObject(hHandle, dwMilliseconds = INFINITE):
3289    _WaitForSingleObject = windll.kernel32.WaitForSingleObject
3290    _WaitForSingleObject.argtypes = [HANDLE, DWORD]
3291    _WaitForSingleObject.restype  = DWORD
3292
3293    if not dwMilliseconds and dwMilliseconds != 0:
3294        dwMilliseconds = INFINITE
3295    if dwMilliseconds != INFINITE:
3296        r = _WaitForSingleObject(hHandle, dwMilliseconds)
3297        if r == WAIT_FAILED:
3298            raise ctypes.WinError()
3299    else:
3300        while 1:
3301            r = _WaitForSingleObject(hHandle, 100)
3302            if r == WAIT_FAILED:
3303                raise ctypes.WinError()
3304            if r != WAIT_TIMEOUT:
3305                break
3306    return r
3307
3308# DWORD WINAPI WaitForSingleObjectEx(
3309#   HANDLE hHandle,
3310#   DWORD dwMilliseconds,
3311#   BOOL bAlertable
3312# );
3313def WaitForSingleObjectEx(hHandle, dwMilliseconds = INFINITE, bAlertable = True):
3314    _WaitForSingleObjectEx = windll.kernel32.WaitForSingleObjectEx
3315    _WaitForSingleObjectEx.argtypes = [HANDLE, DWORD, BOOL]
3316    _WaitForSingleObjectEx.restype  = DWORD
3317
3318    if not dwMilliseconds and dwMilliseconds != 0:
3319        dwMilliseconds = INFINITE
3320    if dwMilliseconds != INFINITE:
3321        r = _WaitForSingleObjectEx(hHandle, dwMilliseconds, bool(bAlertable))
3322        if r == WAIT_FAILED:
3323            raise ctypes.WinError()
3324    else:
3325        while 1:
3326            r = _WaitForSingleObjectEx(hHandle, 100, bool(bAlertable))
3327            if r == WAIT_FAILED:
3328                raise ctypes.WinError()
3329            if r != WAIT_TIMEOUT:
3330                break
3331    return r
3332
3333# DWORD WINAPI WaitForMultipleObjects(
3334#   DWORD nCount,
3335#   const HANDLE *lpHandles,
3336#   BOOL bWaitAll,
3337#   DWORD dwMilliseconds
3338# );
3339def WaitForMultipleObjects(handles, bWaitAll = False, dwMilliseconds = INFINITE):
3340    _WaitForMultipleObjects = windll.kernel32.WaitForMultipleObjects
3341    _WaitForMultipleObjects.argtypes = [DWORD, POINTER(HANDLE), BOOL, DWORD]
3342    _WaitForMultipleObjects.restype  = DWORD
3343
3344    if not dwMilliseconds and dwMilliseconds != 0:
3345        dwMilliseconds = INFINITE
3346    nCount          = len(handles)
3347    lpHandlesType   = HANDLE * nCount
3348    lpHandles       = lpHandlesType(*handles)
3349    if dwMilliseconds != INFINITE:
3350        r = _WaitForMultipleObjects(byref(lpHandles), bool(bWaitAll), dwMilliseconds)
3351        if r == WAIT_FAILED:
3352            raise ctypes.WinError()
3353    else:
3354        while 1:
3355            r = _WaitForMultipleObjects(byref(lpHandles), bool(bWaitAll), 100)
3356            if r == WAIT_FAILED:
3357                raise ctypes.WinError()
3358            if r != WAIT_TIMEOUT:
3359                break
3360    return r
3361
3362# DWORD WINAPI WaitForMultipleObjectsEx(
3363#   DWORD nCount,
3364#   const HANDLE *lpHandles,
3365#   BOOL bWaitAll,
3366#   DWORD dwMilliseconds,
3367#   BOOL bAlertable
3368# );
3369def WaitForMultipleObjectsEx(handles, bWaitAll = False, dwMilliseconds = INFINITE, bAlertable = True):
3370    _WaitForMultipleObjectsEx = windll.kernel32.WaitForMultipleObjectsEx
3371    _WaitForMultipleObjectsEx.argtypes = [DWORD, POINTER(HANDLE), BOOL, DWORD]
3372    _WaitForMultipleObjectsEx.restype  = DWORD
3373
3374    if not dwMilliseconds and dwMilliseconds != 0:
3375        dwMilliseconds = INFINITE
3376    nCount          = len(handles)
3377    lpHandlesType   = HANDLE * nCount
3378    lpHandles       = lpHandlesType(*handles)
3379    if dwMilliseconds != INFINITE:
3380        r = _WaitForMultipleObjectsEx(byref(lpHandles), bool(bWaitAll), dwMilliseconds, bool(bAlertable))
3381        if r == WAIT_FAILED:
3382            raise ctypes.WinError()
3383    else:
3384        while 1:
3385            r = _WaitForMultipleObjectsEx(byref(lpHandles), bool(bWaitAll), 100, bool(bAlertable))
3386            if r == WAIT_FAILED:
3387                raise ctypes.WinError()
3388            if r != WAIT_TIMEOUT:
3389                break
3390    return r
3391
3392# HANDLE WINAPI CreateMutex(
3393#   _In_opt_  LPSECURITY_ATTRIBUTES lpMutexAttributes,
3394#   _In_      BOOL bInitialOwner,
3395#   _In_opt_  LPCTSTR lpName
3396# );
3397def CreateMutexA(lpMutexAttributes = None, bInitialOwner = True, lpName = None):
3398    _CreateMutexA = windll.kernel32.CreateMutexA
3399    _CreateMutexA.argtypes = [LPVOID, BOOL, LPSTR]
3400    _CreateMutexA.restype  = HANDLE
3401    _CreateMutexA.errcheck = RaiseIfZero
3402    return Handle( _CreateMutexA(lpMutexAttributes, bInitialOwner, lpName) )
3403
3404def CreateMutexW(lpMutexAttributes = None, bInitialOwner = True, lpName = None):
3405    _CreateMutexW = windll.kernel32.CreateMutexW
3406    _CreateMutexW.argtypes = [LPVOID, BOOL, LPWSTR]
3407    _CreateMutexW.restype  = HANDLE
3408    _CreateMutexW.errcheck = RaiseIfZero
3409    return Handle( _CreateMutexW(lpMutexAttributes, bInitialOwner, lpName) )
3410
3411CreateMutex = GuessStringType(CreateMutexA, CreateMutexW)
3412
3413# HANDLE WINAPI OpenMutex(
3414#   _In_  DWORD dwDesiredAccess,
3415#   _In_  BOOL bInheritHandle,
3416#   _In_  LPCTSTR lpName
3417# );
3418def OpenMutexA(dwDesiredAccess = MUTEX_ALL_ACCESS, bInitialOwner = True, lpName = None):
3419    _OpenMutexA = windll.kernel32.OpenMutexA
3420    _OpenMutexA.argtypes = [DWORD, BOOL, LPSTR]
3421    _OpenMutexA.restype  = HANDLE
3422    _OpenMutexA.errcheck = RaiseIfZero
3423    return Handle( _OpenMutexA(lpMutexAttributes, bInitialOwner, lpName) )
3424
3425def OpenMutexW(dwDesiredAccess = MUTEX_ALL_ACCESS, bInitialOwner = True, lpName = None):
3426    _OpenMutexW = windll.kernel32.OpenMutexW
3427    _OpenMutexW.argtypes = [DWORD, BOOL, LPWSTR]
3428    _OpenMutexW.restype  = HANDLE
3429    _OpenMutexW.errcheck = RaiseIfZero
3430    return Handle( _OpenMutexW(lpMutexAttributes, bInitialOwner, lpName) )
3431
3432OpenMutex = GuessStringType(OpenMutexA, OpenMutexW)
3433
3434# HANDLE WINAPI CreateEvent(
3435#   _In_opt_  LPSECURITY_ATTRIBUTES lpEventAttributes,
3436#   _In_      BOOL bManualReset,
3437#   _In_      BOOL bInitialState,
3438#   _In_opt_  LPCTSTR lpName
3439# );
3440def CreateEventA(lpMutexAttributes = None, bManualReset = False, bInitialState = False, lpName = None):
3441    _CreateEventA = windll.kernel32.CreateEventA
3442    _CreateEventA.argtypes = [LPVOID, BOOL, BOOL, LPSTR]
3443    _CreateEventA.restype  = HANDLE
3444    _CreateEventA.errcheck = RaiseIfZero
3445    return Handle( _CreateEventA(lpMutexAttributes, bManualReset, bInitialState, lpName) )
3446
3447def CreateEventW(lpMutexAttributes = None, bManualReset = False, bInitialState = False, lpName = None):
3448    _CreateEventW = windll.kernel32.CreateEventW
3449    _CreateEventW.argtypes = [LPVOID, BOOL, BOOL, LPWSTR]
3450    _CreateEventW.restype  = HANDLE
3451    _CreateEventW.errcheck = RaiseIfZero
3452    return Handle( _CreateEventW(lpMutexAttributes, bManualReset, bInitialState, lpName) )
3453
3454CreateEvent = GuessStringType(CreateEventA, CreateEventW)
3455
3456# HANDLE WINAPI OpenEvent(
3457#   _In_  DWORD dwDesiredAccess,
3458#   _In_  BOOL bInheritHandle,
3459#   _In_  LPCTSTR lpName
3460# );
3461def OpenEventA(dwDesiredAccess = EVENT_ALL_ACCESS, bInheritHandle = False, lpName = None):
3462    _OpenEventA = windll.kernel32.OpenEventA
3463    _OpenEventA.argtypes = [DWORD, BOOL, LPSTR]
3464    _OpenEventA.restype  = HANDLE
3465    _OpenEventA.errcheck = RaiseIfZero
3466    return Handle( _OpenEventA(dwDesiredAccess, bInheritHandle, lpName) )
3467
3468def OpenEventW(dwDesiredAccess = EVENT_ALL_ACCESS, bInheritHandle = False, lpName = None):
3469    _OpenEventW = windll.kernel32.OpenEventW
3470    _OpenEventW.argtypes = [DWORD, BOOL, LPWSTR]
3471    _OpenEventW.restype  = HANDLE
3472    _OpenEventW.errcheck = RaiseIfZero
3473    return Handle( _OpenEventW(dwDesiredAccess, bInheritHandle, lpName) )
3474
3475OpenEvent = GuessStringType(OpenEventA, OpenEventW)
3476
3477# HANDLE WINAPI CreateSemaphore(
3478#   _In_opt_  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
3479#   _In_      LONG lInitialCount,
3480#   _In_      LONG lMaximumCount,
3481#   _In_opt_  LPCTSTR lpName
3482# );
3483
3484# TODO
3485
3486# HANDLE WINAPI OpenSemaphore(
3487#   _In_  DWORD dwDesiredAccess,
3488#   _In_  BOOL bInheritHandle,
3489#   _In_  LPCTSTR lpName
3490# );
3491
3492# TODO
3493
3494# BOOL WINAPI ReleaseMutex(
3495#   _In_  HANDLE hMutex
3496# );
3497def ReleaseMutex(hMutex):
3498    _ReleaseMutex = windll.kernel32.ReleaseMutex
3499    _ReleaseMutex.argtypes = [HANDLE]
3500    _ReleaseMutex.restype  = bool
3501    _ReleaseMutex.errcheck = RaiseIfZero
3502    _ReleaseMutex(hMutex)
3503
3504# BOOL WINAPI SetEvent(
3505#   _In_  HANDLE hEvent
3506# );
3507def SetEvent(hEvent):
3508    _SetEvent = windll.kernel32.SetEvent
3509    _SetEvent.argtypes = [HANDLE]
3510    _SetEvent.restype  = bool
3511    _SetEvent.errcheck = RaiseIfZero
3512    _SetEvent(hEvent)
3513
3514# BOOL WINAPI ResetEvent(
3515#   _In_  HANDLE hEvent
3516# );
3517def ResetEvent(hEvent):
3518    _ResetEvent = windll.kernel32.ResetEvent
3519    _ResetEvent.argtypes = [HANDLE]
3520    _ResetEvent.restype  = bool
3521    _ResetEvent.errcheck = RaiseIfZero
3522    _ResetEvent(hEvent)
3523
3524# BOOL WINAPI PulseEvent(
3525#   _In_  HANDLE hEvent
3526# );
3527def PulseEvent(hEvent):
3528    _PulseEvent = windll.kernel32.PulseEvent
3529    _PulseEvent.argtypes = [HANDLE]
3530    _PulseEvent.restype  = bool
3531    _PulseEvent.errcheck = RaiseIfZero
3532    _PulseEvent(hEvent)
3533
3534# BOOL WINAPI ReleaseSemaphore(
3535#   _In_       HANDLE hSemaphore,
3536#   _In_       LONG lReleaseCount,
3537#   _Out_opt_  LPLONG lpPreviousCount
3538# );
3539
3540# TODO
3541
3542#------------------------------------------------------------------------------
3543# Debug API
3544
3545# BOOL WaitForDebugEvent(
3546#   LPDEBUG_EVENT lpDebugEvent,
3547#   DWORD dwMilliseconds
3548# );
3549def WaitForDebugEvent(dwMilliseconds = INFINITE):
3550    _WaitForDebugEvent = windll.kernel32.WaitForDebugEvent
3551    _WaitForDebugEvent.argtypes = [LPDEBUG_EVENT, DWORD]
3552    _WaitForDebugEvent.restype  = DWORD
3553
3554    if not dwMilliseconds and dwMilliseconds != 0:
3555        dwMilliseconds = INFINITE
3556    lpDebugEvent                  = DEBUG_EVENT()
3557    lpDebugEvent.dwDebugEventCode = 0
3558    lpDebugEvent.dwProcessId      = 0
3559    lpDebugEvent.dwThreadId       = 0
3560    if dwMilliseconds != INFINITE:
3561        success = _WaitForDebugEvent(byref(lpDebugEvent), dwMilliseconds)
3562        if success == 0:
3563            raise ctypes.WinError()
3564    else:
3565        # this avoids locking the Python GIL for too long
3566        while 1:
3567            success = _WaitForDebugEvent(byref(lpDebugEvent), 100)
3568            if success != 0:
3569                break
3570            code = GetLastError()
3571            if code not in (ERROR_SEM_TIMEOUT, WAIT_TIMEOUT):
3572                raise ctypes.WinError(code)
3573    return lpDebugEvent
3574
3575# BOOL ContinueDebugEvent(
3576#   DWORD dwProcessId,
3577#   DWORD dwThreadId,
3578#   DWORD dwContinueStatus
3579# );
3580def ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED):
3581    _ContinueDebugEvent = windll.kernel32.ContinueDebugEvent
3582    _ContinueDebugEvent.argtypes = [DWORD, DWORD, DWORD]
3583    _ContinueDebugEvent.restype  = bool
3584    _ContinueDebugEvent.errcheck = RaiseIfZero
3585    _ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus)
3586
3587# BOOL WINAPI FlushInstructionCache(
3588#   __in  HANDLE hProcess,
3589#   __in  LPCVOID lpBaseAddress,
3590#   __in  SIZE_T dwSize
3591# );
3592def FlushInstructionCache(hProcess, lpBaseAddress = None, dwSize = 0):
3593    # http://blogs.msdn.com/oldnewthing/archive/2003/12/08/55954.aspx#55958
3594    _FlushInstructionCache = windll.kernel32.FlushInstructionCache
3595    _FlushInstructionCache.argtypes = [HANDLE, LPVOID, SIZE_T]
3596    _FlushInstructionCache.restype  = bool
3597    _FlushInstructionCache.errcheck = RaiseIfZero
3598    _FlushInstructionCache(hProcess, lpBaseAddress, dwSize)
3599
3600# BOOL DebugActiveProcess(
3601#   DWORD dwProcessId
3602# );
3603def DebugActiveProcess(dwProcessId):
3604    _DebugActiveProcess = windll.kernel32.DebugActiveProcess
3605    _DebugActiveProcess.argtypes = [DWORD]
3606    _DebugActiveProcess.restype  = bool
3607    _DebugActiveProcess.errcheck = RaiseIfZero
3608    _DebugActiveProcess(dwProcessId)
3609
3610# BOOL DebugActiveProcessStop(
3611#   DWORD dwProcessId
3612# );
3613def DebugActiveProcessStop(dwProcessId):
3614    _DebugActiveProcessStop = windll.kernel32.DebugActiveProcessStop
3615    _DebugActiveProcessStop.argtypes = [DWORD]
3616    _DebugActiveProcessStop.restype  = bool
3617    _DebugActiveProcessStop.errcheck = RaiseIfZero
3618    _DebugActiveProcessStop(dwProcessId)
3619
3620# BOOL CheckRemoteDebuggerPresent(
3621#   HANDLE hProcess,
3622#   PBOOL pbDebuggerPresent
3623# );
3624def CheckRemoteDebuggerPresent(hProcess):
3625    _CheckRemoteDebuggerPresent = windll.kernel32.CheckRemoteDebuggerPresent
3626    _CheckRemoteDebuggerPresent.argtypes = [HANDLE, PBOOL]
3627    _CheckRemoteDebuggerPresent.restype  = bool
3628    _CheckRemoteDebuggerPresent.errcheck = RaiseIfZero
3629
3630    pbDebuggerPresent = BOOL(0)
3631    _CheckRemoteDebuggerPresent(hProcess, byref(pbDebuggerPresent))
3632    return bool(pbDebuggerPresent.value)
3633
3634# BOOL DebugSetProcessKillOnExit(
3635#   BOOL KillOnExit
3636# );
3637def DebugSetProcessKillOnExit(KillOnExit):
3638    _DebugSetProcessKillOnExit = windll.kernel32.DebugSetProcessKillOnExit
3639    _DebugSetProcessKillOnExit.argtypes = [BOOL]
3640    _DebugSetProcessKillOnExit.restype  = bool
3641    _DebugSetProcessKillOnExit.errcheck = RaiseIfZero
3642    _DebugSetProcessKillOnExit(bool(KillOnExit))
3643
3644# BOOL DebugBreakProcess(
3645#   HANDLE Process
3646# );
3647def DebugBreakProcess(hProcess):
3648    _DebugBreakProcess = windll.kernel32.DebugBreakProcess
3649    _DebugBreakProcess.argtypes = [HANDLE]
3650    _DebugBreakProcess.restype  = bool
3651    _DebugBreakProcess.errcheck = RaiseIfZero
3652    _DebugBreakProcess(hProcess)
3653
3654# void WINAPI OutputDebugString(
3655#   __in_opt  LPCTSTR lpOutputString
3656# );
3657def OutputDebugStringA(lpOutputString):
3658    _OutputDebugStringA = windll.kernel32.OutputDebugStringA
3659    _OutputDebugStringA.argtypes = [LPSTR]
3660    _OutputDebugStringA.restype  = None
3661    _OutputDebugStringA(lpOutputString)
3662
3663def OutputDebugStringW(lpOutputString):
3664    _OutputDebugStringW = windll.kernel32.OutputDebugStringW
3665    _OutputDebugStringW.argtypes = [LPWSTR]
3666    _OutputDebugStringW.restype  = None
3667    _OutputDebugStringW(lpOutputString)
3668
3669OutputDebugString = GuessStringType(OutputDebugStringA, OutputDebugStringW)
3670
3671# BOOL WINAPI ReadProcessMemory(
3672#   __in   HANDLE hProcess,
3673#   __in   LPCVOID lpBaseAddress,
3674#   __out  LPVOID lpBuffer,
3675#   __in   SIZE_T nSize,
3676#   __out  SIZE_T* lpNumberOfBytesRead
3677# );
3678def ReadProcessMemory(hProcess, lpBaseAddress, nSize):
3679    _ReadProcessMemory = windll.kernel32.ReadProcessMemory
3680    _ReadProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
3681    _ReadProcessMemory.restype  = bool
3682
3683    lpBuffer            = ctypes.create_string_buffer(compat.b(''), nSize)
3684    lpNumberOfBytesRead = SIZE_T(0)
3685    success = _ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesRead))
3686    if not success and GetLastError() != ERROR_PARTIAL_COPY:
3687        raise ctypes.WinError()
3688    return compat.b(lpBuffer.raw)[:lpNumberOfBytesRead.value]
3689
3690# BOOL WINAPI WriteProcessMemory(
3691#   __in   HANDLE hProcess,
3692#   __in   LPCVOID lpBaseAddress,
3693#   __in   LPVOID lpBuffer,
3694#   __in   SIZE_T nSize,
3695#   __out  SIZE_T* lpNumberOfBytesWritten
3696# );
3697def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer):
3698    _WriteProcessMemory = windll.kernel32.WriteProcessMemory
3699    _WriteProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
3700    _WriteProcessMemory.restype  = bool
3701
3702    nSize                   = len(lpBuffer)
3703    lpBuffer                = ctypes.create_string_buffer(lpBuffer)
3704    lpNumberOfBytesWritten  = SIZE_T(0)
3705    success = _WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesWritten))
3706    if not success and GetLastError() != ERROR_PARTIAL_COPY:
3707        raise ctypes.WinError()
3708    return lpNumberOfBytesWritten.value
3709
3710# LPVOID WINAPI VirtualAllocEx(
3711#   __in      HANDLE hProcess,
3712#   __in_opt  LPVOID lpAddress,
3713#   __in      SIZE_T dwSize,
3714#   __in      DWORD flAllocationType,
3715#   __in      DWORD flProtect
3716# );
3717def VirtualAllocEx(hProcess, lpAddress = 0, dwSize = 0x1000, flAllocationType = MEM_COMMIT | MEM_RESERVE, flProtect = PAGE_EXECUTE_READWRITE):
3718    _VirtualAllocEx = windll.kernel32.VirtualAllocEx
3719    _VirtualAllocEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, DWORD]
3720    _VirtualAllocEx.restype  = LPVOID
3721
3722    lpAddress = _VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
3723    if lpAddress == NULL:
3724        raise ctypes.WinError()
3725    return lpAddress
3726
3727# SIZE_T WINAPI VirtualQueryEx(
3728#   __in      HANDLE hProcess,
3729#   __in_opt  LPCVOID lpAddress,
3730#   __out     PMEMORY_BASIC_INFORMATION lpBuffer,
3731#   __in      SIZE_T dwLength
3732# );
3733def VirtualQueryEx(hProcess, lpAddress):
3734    _VirtualQueryEx = windll.kernel32.VirtualQueryEx
3735    _VirtualQueryEx.argtypes = [HANDLE, LPVOID, PMEMORY_BASIC_INFORMATION, SIZE_T]
3736    _VirtualQueryEx.restype  = SIZE_T
3737
3738    lpBuffer  = MEMORY_BASIC_INFORMATION()
3739    dwLength  = sizeof(MEMORY_BASIC_INFORMATION)
3740    success   = _VirtualQueryEx(hProcess, lpAddress, byref(lpBuffer), dwLength)
3741    if success == 0:
3742        raise ctypes.WinError()
3743    return MemoryBasicInformation(lpBuffer)
3744
3745# BOOL WINAPI VirtualProtectEx(
3746#   __in   HANDLE hProcess,
3747#   __in   LPVOID lpAddress,
3748#   __in   SIZE_T dwSize,
3749#   __in   DWORD flNewProtect,
3750#   __out  PDWORD lpflOldProtect
3751# );
3752def VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect = PAGE_EXECUTE_READWRITE):
3753    _VirtualProtectEx = windll.kernel32.VirtualProtectEx
3754    _VirtualProtectEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, PDWORD]
3755    _VirtualProtectEx.restype  = bool
3756    _VirtualProtectEx.errcheck = RaiseIfZero
3757
3758    flOldProtect = DWORD(0)
3759    _VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, byref(flOldProtect))
3760    return flOldProtect.value
3761
3762# BOOL WINAPI VirtualFreeEx(
3763#   __in  HANDLE hProcess,
3764#   __in  LPVOID lpAddress,
3765#   __in  SIZE_T dwSize,
3766#   __in  DWORD dwFreeType
3767# );
3768def VirtualFreeEx(hProcess, lpAddress, dwSize = 0, dwFreeType = MEM_RELEASE):
3769    _VirtualFreeEx = windll.kernel32.VirtualFreeEx
3770    _VirtualFreeEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD]
3771    _VirtualFreeEx.restype  = bool
3772    _VirtualFreeEx.errcheck = RaiseIfZero
3773    _VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType)
3774
3775# HANDLE WINAPI CreateRemoteThread(
3776#   __in   HANDLE hProcess,
3777#   __in   LPSECURITY_ATTRIBUTES lpThreadAttributes,
3778#   __in   SIZE_T dwStackSize,
3779#   __in   LPTHREAD_START_ROUTINE lpStartAddress,
3780#   __in   LPVOID lpParameter,
3781#   __in   DWORD dwCreationFlags,
3782#   __out  LPDWORD lpThreadId
3783# );
3784def CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags):
3785    _CreateRemoteThread = windll.kernel32.CreateRemoteThread
3786    _CreateRemoteThread.argtypes = [HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPVOID, LPVOID, DWORD, LPDWORD]
3787    _CreateRemoteThread.restype  = HANDLE
3788
3789    if not lpThreadAttributes:
3790        lpThreadAttributes = None
3791    else:
3792        lpThreadAttributes = byref(lpThreadAttributes)
3793    dwThreadId = DWORD(0)
3794    hThread = _CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, byref(dwThreadId))
3795    if not hThread:
3796        raise ctypes.WinError()
3797    return ThreadHandle(hThread), dwThreadId.value
3798
3799#------------------------------------------------------------------------------
3800# Process API
3801
3802# BOOL WINAPI CreateProcess(
3803#   __in_opt     LPCTSTR lpApplicationName,
3804#   __inout_opt  LPTSTR lpCommandLine,
3805#   __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
3806#   __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
3807#   __in         BOOL bInheritHandles,
3808#   __in         DWORD dwCreationFlags,
3809#   __in_opt     LPVOID lpEnvironment,
3810#   __in_opt     LPCTSTR lpCurrentDirectory,
3811#   __in         LPSTARTUPINFO lpStartupInfo,
3812#   __out        LPPROCESS_INFORMATION lpProcessInformation
3813# );
3814def CreateProcessA(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
3815    _CreateProcessA = windll.kernel32.CreateProcessA
3816    _CreateProcessA.argtypes = [LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION]
3817    _CreateProcessA.restype  = bool
3818    _CreateProcessA.errcheck = RaiseIfZero
3819
3820    if not lpApplicationName:
3821        lpApplicationName   = None
3822    if not lpCommandLine:
3823        lpCommandLine       = None
3824    else:
3825        lpCommandLine       = ctypes.create_string_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
3826    if not lpEnvironment:
3827        lpEnvironment       = None
3828    else:
3829        lpEnvironment       = ctypes.create_string_buffer(lpEnvironment)
3830    if not lpCurrentDirectory:
3831        lpCurrentDirectory  = None
3832    if not lpProcessAttributes:
3833        lpProcessAttributes = None
3834    else:
3835        lpProcessAttributes = byref(lpProcessAttributes)
3836    if not lpThreadAttributes:
3837        lpThreadAttributes = None
3838    else:
3839        lpThreadAttributes = byref(lpThreadAttributes)
3840    if not lpStartupInfo:
3841        lpStartupInfo              = STARTUPINFO()
3842        lpStartupInfo.cb           = sizeof(STARTUPINFO)
3843        lpStartupInfo.lpReserved   = 0
3844        lpStartupInfo.lpDesktop    = 0
3845        lpStartupInfo.lpTitle      = 0
3846        lpStartupInfo.dwFlags      = 0
3847        lpStartupInfo.cbReserved2  = 0
3848        lpStartupInfo.lpReserved2  = 0
3849    lpProcessInformation              = PROCESS_INFORMATION()
3850    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
3851    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
3852    lpProcessInformation.dwProcessId  = 0
3853    lpProcessInformation.dwThreadId   = 0
3854    _CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
3855    return ProcessInformation(lpProcessInformation)
3856
3857def CreateProcessW(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
3858    _CreateProcessW = windll.kernel32.CreateProcessW
3859    _CreateProcessW.argtypes = [LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
3860    _CreateProcessW.restype  = bool
3861    _CreateProcessW.errcheck = RaiseIfZero
3862
3863    if not lpApplicationName:
3864        lpApplicationName   = None
3865    if not lpCommandLine:
3866        lpCommandLine       = None
3867    else:
3868        lpCommandLine       = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine)))
3869    if not lpEnvironment:
3870        lpEnvironment       = None
3871    else:
3872        lpEnvironment       = ctypes.create_unicode_buffer(lpEnvironment)
3873    if not lpCurrentDirectory:
3874        lpCurrentDirectory  = None
3875    if not lpProcessAttributes:
3876        lpProcessAttributes = None
3877    else:
3878        lpProcessAttributes = byref(lpProcessAttributes)
3879    if not lpThreadAttributes:
3880        lpThreadAttributes = None
3881    else:
3882        lpThreadAttributes = byref(lpThreadAttributes)
3883    if not lpStartupInfo:
3884        lpStartupInfo              = STARTUPINFO()
3885        lpStartupInfo.cb           = sizeof(STARTUPINFO)
3886        lpStartupInfo.lpReserved   = 0
3887        lpStartupInfo.lpDesktop    = 0
3888        lpStartupInfo.lpTitle      = 0
3889        lpStartupInfo.dwFlags      = 0
3890        lpStartupInfo.cbReserved2  = 0
3891        lpStartupInfo.lpReserved2  = 0
3892    lpProcessInformation              = PROCESS_INFORMATION()
3893    lpProcessInformation.hProcess     = INVALID_HANDLE_VALUE
3894    lpProcessInformation.hThread      = INVALID_HANDLE_VALUE
3895    lpProcessInformation.dwProcessId  = 0
3896    lpProcessInformation.dwThreadId   = 0
3897    _CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
3898    return ProcessInformation(lpProcessInformation)
3899
3900CreateProcess = GuessStringType(CreateProcessA, CreateProcessW)
3901
3902# BOOL WINAPI InitializeProcThreadAttributeList(
3903#   __out_opt   LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
3904#   __in        DWORD dwAttributeCount,
3905#   __reserved  DWORD dwFlags,
3906#   __inout     PSIZE_T lpSize
3907# );
3908def InitializeProcThreadAttributeList(dwAttributeCount):
3909    _InitializeProcThreadAttributeList = windll.kernel32.InitializeProcThreadAttributeList
3910    _InitializeProcThreadAttributeList.argtypes = [LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T]
3911    _InitializeProcThreadAttributeList.restype  = bool
3912
3913    Size = SIZE_T(0)
3914    _InitializeProcThreadAttributeList(None, dwAttributeCount, 0, byref(Size))
3915    RaiseIfZero(Size.value)
3916    AttributeList = (BYTE * Size.value)()
3917    success = _InitializeProcThreadAttributeList(byref(AttributeList), dwAttributeCount, 0, byref(Size))
3918    RaiseIfZero(success)
3919    return AttributeList
3920
3921# BOOL WINAPI UpdateProcThreadAttribute(
3922#   __inout    LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
3923#   __in       DWORD dwFlags,
3924#   __in       DWORD_PTR Attribute,
3925#   __in       PVOID lpValue,
3926#   __in       SIZE_T cbSize,
3927#   __out_opt  PVOID lpPreviousValue,
3928#   __in_opt   PSIZE_T lpReturnSize
3929# );
3930def UpdateProcThreadAttribute(lpAttributeList, Attribute, Value, cbSize = None):
3931    _UpdateProcThreadAttribute = windll.kernel32.UpdateProcThreadAttribute
3932    _UpdateProcThreadAttribute.argtypes = [LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, PVOID, SIZE_T, PVOID, PSIZE_T]
3933    _UpdateProcThreadAttribute.restype  = bool
3934    _UpdateProcThreadAttribute.errcheck = RaiseIfZero
3935
3936    if cbSize is None:
3937        cbSize = sizeof(Value)
3938    _UpdateProcThreadAttribute(byref(lpAttributeList), 0, Attribute, byref(Value), cbSize, None, None)
3939
3940# VOID WINAPI DeleteProcThreadAttributeList(
3941#   __inout  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList
3942# );
3943def DeleteProcThreadAttributeList(lpAttributeList):
3944    _DeleteProcThreadAttributeList = windll.kernel32.DeleteProcThreadAttributeList
3945    _DeleteProcThreadAttributeList.restype = None
3946    _DeleteProcThreadAttributeList(byref(lpAttributeList))
3947
3948# HANDLE WINAPI OpenProcess(
3949#   __in  DWORD dwDesiredAccess,
3950#   __in  BOOL bInheritHandle,
3951#   __in  DWORD dwProcessId
3952# );
3953def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
3954    _OpenProcess = windll.kernel32.OpenProcess
3955    _OpenProcess.argtypes = [DWORD, BOOL, DWORD]
3956    _OpenProcess.restype  = HANDLE
3957
3958    hProcess = _OpenProcess(dwDesiredAccess, bool(bInheritHandle), dwProcessId)
3959    if hProcess == NULL:
3960        raise ctypes.WinError()
3961    return ProcessHandle(hProcess, dwAccess = dwDesiredAccess)
3962
3963# HANDLE WINAPI OpenThread(
3964#   __in  DWORD dwDesiredAccess,
3965#   __in  BOOL bInheritHandle,
3966#   __in  DWORD dwThreadId
3967# );
3968def OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId):
3969    _OpenThread = windll.kernel32.OpenThread
3970    _OpenThread.argtypes = [DWORD, BOOL, DWORD]
3971    _OpenThread.restype  = HANDLE
3972
3973    hThread = _OpenThread(dwDesiredAccess, bool(bInheritHandle), dwThreadId)
3974    if hThread == NULL:
3975        raise ctypes.WinError()
3976    return ThreadHandle(hThread, dwAccess = dwDesiredAccess)
3977
3978# DWORD WINAPI SuspendThread(
3979#   __in  HANDLE hThread
3980# );
3981def SuspendThread(hThread):
3982    _SuspendThread = windll.kernel32.SuspendThread
3983    _SuspendThread.argtypes = [HANDLE]
3984    _SuspendThread.restype  = DWORD
3985
3986    previousCount = _SuspendThread(hThread)
3987    if previousCount == DWORD(-1).value:
3988        raise ctypes.WinError()
3989    return previousCount
3990
3991# DWORD WINAPI ResumeThread(
3992#   __in  HANDLE hThread
3993# );
3994def ResumeThread(hThread):
3995    _ResumeThread = windll.kernel32.ResumeThread
3996    _ResumeThread.argtypes = [HANDLE]
3997    _ResumeThread.restype  = DWORD
3998
3999    previousCount = _ResumeThread(hThread)
4000    if previousCount == DWORD(-1).value:
4001        raise ctypes.WinError()
4002    return previousCount
4003
4004# BOOL WINAPI TerminateThread(
4005#   __inout  HANDLE hThread,
4006#   __in     DWORD dwExitCode
4007# );
4008def TerminateThread(hThread, dwExitCode = 0):
4009    _TerminateThread = windll.kernel32.TerminateThread
4010    _TerminateThread.argtypes = [HANDLE, DWORD]
4011    _TerminateThread.restype  = bool
4012    _TerminateThread.errcheck = RaiseIfZero
4013    _TerminateThread(hThread, dwExitCode)
4014
4015# BOOL WINAPI TerminateProcess(
4016#   __inout  HANDLE hProcess,
4017#   __in     DWORD dwExitCode
4018# );
4019def TerminateProcess(hProcess, dwExitCode = 0):
4020    _TerminateProcess = windll.kernel32.TerminateProcess
4021    _TerminateProcess.argtypes = [HANDLE, DWORD]
4022    _TerminateProcess.restype  = bool
4023    _TerminateProcess.errcheck = RaiseIfZero
4024    _TerminateProcess(hProcess, dwExitCode)
4025
4026# DWORD WINAPI GetCurrentProcessId(void);
4027def GetCurrentProcessId():
4028    _GetCurrentProcessId = windll.kernel32.GetCurrentProcessId
4029    _GetCurrentProcessId.argtypes = []
4030    _GetCurrentProcessId.restype  = DWORD
4031    return _GetCurrentProcessId()
4032
4033# DWORD WINAPI GetCurrentThreadId(void);
4034def GetCurrentThreadId():
4035    _GetCurrentThreadId = windll.kernel32.GetCurrentThreadId
4036    _GetCurrentThreadId.argtypes = []
4037    _GetCurrentThreadId.restype  = DWORD
4038    return _GetCurrentThreadId()
4039
4040# DWORD WINAPI GetProcessId(
4041#   __in  HANDLE hProcess
4042# );
4043def GetProcessId(hProcess):
4044    _GetProcessId = windll.kernel32.GetProcessId
4045    _GetProcessId.argtypes = [HANDLE]
4046    _GetProcessId.restype  = DWORD
4047    _GetProcessId.errcheck = RaiseIfZero
4048    return _GetProcessId(hProcess)
4049
4050# DWORD WINAPI GetThreadId(
4051#   __in  HANDLE hThread
4052# );
4053def GetThreadId(hThread):
4054    _GetThreadId = windll.kernel32._GetThreadId
4055    _GetThreadId.argtypes = [HANDLE]
4056    _GetThreadId.restype  = DWORD
4057
4058    dwThreadId = _GetThreadId(hThread)
4059    if dwThreadId == 0:
4060        raise ctypes.WinError()
4061    return dwThreadId
4062
4063# DWORD WINAPI GetProcessIdOfThread(
4064#   __in  HANDLE hThread
4065# );
4066def GetProcessIdOfThread(hThread):
4067    _GetProcessIdOfThread = windll.kernel32.GetProcessIdOfThread
4068    _GetProcessIdOfThread.argtypes = [HANDLE]
4069    _GetProcessIdOfThread.restype  = DWORD
4070
4071    dwProcessId = _GetProcessIdOfThread(hThread)
4072    if dwProcessId == 0:
4073        raise ctypes.WinError()
4074    return dwProcessId
4075
4076# BOOL WINAPI GetExitCodeProcess(
4077#   __in   HANDLE hProcess,
4078#   __out  LPDWORD lpExitCode
4079# );
4080def GetExitCodeProcess(hProcess):
4081    _GetExitCodeProcess = windll.kernel32.GetExitCodeProcess
4082    _GetExitCodeProcess.argtypes = [HANDLE]
4083    _GetExitCodeProcess.restype  = bool
4084    _GetExitCodeProcess.errcheck = RaiseIfZero
4085
4086    lpExitCode = DWORD(0)
4087    _GetExitCodeProcess(hProcess, byref(lpExitCode))
4088    return lpExitCode.value
4089
4090# BOOL WINAPI GetExitCodeThread(
4091#   __in   HANDLE hThread,
4092#   __out  LPDWORD lpExitCode
4093# );
4094def GetExitCodeThread(hThread):
4095    _GetExitCodeThread = windll.kernel32.GetExitCodeThread
4096    _GetExitCodeThread.argtypes = [HANDLE]
4097    _GetExitCodeThread.restype  = bool
4098    _GetExitCodeThread.errcheck = RaiseIfZero
4099
4100    lpExitCode = DWORD(0)
4101    _GetExitCodeThread(hThread, byref(lpExitCode))
4102    return lpExitCode.value
4103
4104# DWORD WINAPI GetProcessVersion(
4105#   __in  DWORD ProcessId
4106# );
4107def GetProcessVersion(ProcessId):
4108    _GetProcessVersion = windll.kernel32.GetProcessVersion
4109    _GetProcessVersion.argtypes = [DWORD]
4110    _GetProcessVersion.restype  = DWORD
4111
4112    retval = _GetProcessVersion(ProcessId)
4113    if retval == 0:
4114        raise ctypes.WinError()
4115    return retval
4116
4117# DWORD WINAPI GetPriorityClass(
4118#   __in  HANDLE hProcess
4119# );
4120def GetPriorityClass(hProcess):
4121    _GetPriorityClass = windll.kernel32.GetPriorityClass
4122    _GetPriorityClass.argtypes = [HANDLE]
4123    _GetPriorityClass.restype  = DWORD
4124
4125    retval = _GetPriorityClass(hProcess)
4126    if retval == 0:
4127        raise ctypes.WinError()
4128    return retval
4129
4130# BOOL WINAPI SetPriorityClass(
4131#   __in  HANDLE hProcess,
4132#   __in  DWORD dwPriorityClass
4133# );
4134def SetPriorityClass(hProcess, dwPriorityClass = NORMAL_PRIORITY_CLASS):
4135    _SetPriorityClass = windll.kernel32.SetPriorityClass
4136    _SetPriorityClass.argtypes = [HANDLE, DWORD]
4137    _SetPriorityClass.restype  = bool
4138    _SetPriorityClass.errcheck = RaiseIfZero
4139    _SetPriorityClass(hProcess, dwPriorityClass)
4140
4141# BOOL WINAPI GetProcessPriorityBoost(
4142#   __in   HANDLE hProcess,
4143#   __out  PBOOL pDisablePriorityBoost
4144# );
4145def GetProcessPriorityBoost(hProcess):
4146    _GetProcessPriorityBoost = windll.kernel32.GetProcessPriorityBoost
4147    _GetProcessPriorityBoost.argtypes = [HANDLE, PBOOL]
4148    _GetProcessPriorityBoost.restype  = bool
4149    _GetProcessPriorityBoost.errcheck = RaiseIfZero
4150
4151    pDisablePriorityBoost = BOOL(False)
4152    _GetProcessPriorityBoost(hProcess, byref(pDisablePriorityBoost))
4153    return bool(pDisablePriorityBoost.value)
4154
4155# BOOL WINAPI SetProcessPriorityBoost(
4156#   __in  HANDLE hProcess,
4157#   __in  BOOL DisablePriorityBoost
4158# );
4159def SetProcessPriorityBoost(hProcess, DisablePriorityBoost):
4160    _SetProcessPriorityBoost = windll.kernel32.SetProcessPriorityBoost
4161    _SetProcessPriorityBoost.argtypes = [HANDLE, BOOL]
4162    _SetProcessPriorityBoost.restype  = bool
4163    _SetProcessPriorityBoost.errcheck = RaiseIfZero
4164    _SetProcessPriorityBoost(hProcess, bool(DisablePriorityBoost))
4165
4166# BOOL WINAPI GetProcessAffinityMask(
4167#   __in   HANDLE hProcess,
4168#   __out  PDWORD_PTR lpProcessAffinityMask,
4169#   __out  PDWORD_PTR lpSystemAffinityMask
4170# );
4171def GetProcessAffinityMask(hProcess):
4172    _GetProcessAffinityMask = windll.kernel32.GetProcessAffinityMask
4173    _GetProcessAffinityMask.argtypes = [HANDLE, PDWORD_PTR, PDWORD_PTR]
4174    _GetProcessAffinityMask.restype  = bool
4175    _GetProcessAffinityMask.errcheck = RaiseIfZero
4176
4177    lpProcessAffinityMask = DWORD_PTR(0)
4178    lpSystemAffinityMask  = DWORD_PTR(0)
4179    _GetProcessAffinityMask(hProcess, byref(lpProcessAffinityMask), byref(lpSystemAffinityMask))
4180    return lpProcessAffinityMask.value, lpSystemAffinityMask.value
4181
4182# BOOL WINAPI SetProcessAffinityMask(
4183#   __in  HANDLE hProcess,
4184#   __in  DWORD_PTR dwProcessAffinityMask
4185# );
4186def SetProcessAffinityMask(hProcess, dwProcessAffinityMask):
4187    _SetProcessAffinityMask = windll.kernel32.SetProcessAffinityMask
4188    _SetProcessAffinityMask.argtypes = [HANDLE, DWORD_PTR]
4189    _SetProcessAffinityMask.restype  = bool
4190    _SetProcessAffinityMask.errcheck = RaiseIfZero
4191    _SetProcessAffinityMask(hProcess, dwProcessAffinityMask)
4192
4193#------------------------------------------------------------------------------
4194# Toolhelp32 API
4195
4196# HANDLE WINAPI CreateToolhelp32Snapshot(
4197#   __in  DWORD dwFlags,
4198#   __in  DWORD th32ProcessID
4199# );
4200def CreateToolhelp32Snapshot(dwFlags = TH32CS_SNAPALL, th32ProcessID = 0):
4201    _CreateToolhelp32Snapshot = windll.kernel32.CreateToolhelp32Snapshot
4202    _CreateToolhelp32Snapshot.argtypes = [DWORD, DWORD]
4203    _CreateToolhelp32Snapshot.restype  = HANDLE
4204
4205    hSnapshot = _CreateToolhelp32Snapshot(dwFlags, th32ProcessID)
4206    if hSnapshot == INVALID_HANDLE_VALUE:
4207        raise ctypes.WinError()
4208    return SnapshotHandle(hSnapshot)
4209
4210# BOOL WINAPI Process32First(
4211#   __in     HANDLE hSnapshot,
4212#   __inout  LPPROCESSENTRY32 lppe
4213# );
4214def Process32First(hSnapshot):
4215    _Process32First = windll.kernel32.Process32First
4216    _Process32First.argtypes = [HANDLE, LPPROCESSENTRY32]
4217    _Process32First.restype  = bool
4218
4219    pe        = PROCESSENTRY32()
4220    pe.dwSize = sizeof(PROCESSENTRY32)
4221    success = _Process32First(hSnapshot, byref(pe))
4222    if not success:
4223        if GetLastError() == ERROR_NO_MORE_FILES:
4224            return None
4225        raise ctypes.WinError()
4226    return pe
4227
4228# BOOL WINAPI Process32Next(
4229#   __in     HANDLE hSnapshot,
4230#   __out  LPPROCESSENTRY32 lppe
4231# );
4232def Process32Next(hSnapshot, pe = None):
4233    _Process32Next = windll.kernel32.Process32Next
4234    _Process32Next.argtypes = [HANDLE, LPPROCESSENTRY32]
4235    _Process32Next.restype  = bool
4236
4237    if pe is None:
4238        pe = PROCESSENTRY32()
4239    pe.dwSize = sizeof(PROCESSENTRY32)
4240    success = _Process32Next(hSnapshot, byref(pe))
4241    if not success:
4242        if GetLastError() == ERROR_NO_MORE_FILES:
4243            return None
4244        raise ctypes.WinError()
4245    return pe
4246
4247# BOOL WINAPI Thread32First(
4248#   __in     HANDLE hSnapshot,
4249#   __inout  LPTHREADENTRY32 lpte
4250# );
4251def Thread32First(hSnapshot):
4252    _Thread32First = windll.kernel32.Thread32First
4253    _Thread32First.argtypes = [HANDLE, LPTHREADENTRY32]
4254    _Thread32First.restype  = bool
4255
4256    te = THREADENTRY32()
4257    te.dwSize = sizeof(THREADENTRY32)
4258    success = _Thread32First(hSnapshot, byref(te))
4259    if not success:
4260        if GetLastError() == ERROR_NO_MORE_FILES:
4261            return None
4262        raise ctypes.WinError()
4263    return te
4264
4265# BOOL WINAPI Thread32Next(
4266#   __in     HANDLE hSnapshot,
4267#   __out  LPTHREADENTRY32 lpte
4268# );
4269def Thread32Next(hSnapshot, te = None):
4270    _Thread32Next = windll.kernel32.Thread32Next
4271    _Thread32Next.argtypes = [HANDLE, LPTHREADENTRY32]
4272    _Thread32Next.restype  = bool
4273
4274    if te is None:
4275        te = THREADENTRY32()
4276    te.dwSize = sizeof(THREADENTRY32)
4277    success = _Thread32Next(hSnapshot, byref(te))
4278    if not success:
4279        if GetLastError() == ERROR_NO_MORE_FILES:
4280            return None
4281        raise ctypes.WinError()
4282    return te
4283
4284# BOOL WINAPI Module32First(
4285#   __in     HANDLE hSnapshot,
4286#   __inout  LPMODULEENTRY32 lpme
4287# );
4288def Module32First(hSnapshot):
4289    _Module32First = windll.kernel32.Module32First
4290    _Module32First.argtypes = [HANDLE, LPMODULEENTRY32]
4291    _Module32First.restype  = bool
4292
4293    me = MODULEENTRY32()
4294    me.dwSize = sizeof(MODULEENTRY32)
4295    success = _Module32First(hSnapshot, byref(me))
4296    if not success:
4297        if GetLastError() == ERROR_NO_MORE_FILES:
4298            return None
4299        raise ctypes.WinError()
4300    return me
4301
4302# BOOL WINAPI Module32Next(
4303#   __in     HANDLE hSnapshot,
4304#   __out  LPMODULEENTRY32 lpme
4305# );
4306def Module32Next(hSnapshot, me = None):
4307    _Module32Next = windll.kernel32.Module32Next
4308    _Module32Next.argtypes = [HANDLE, LPMODULEENTRY32]
4309    _Module32Next.restype  = bool
4310
4311    if me is None:
4312        me = MODULEENTRY32()
4313    me.dwSize = sizeof(MODULEENTRY32)
4314    success = _Module32Next(hSnapshot, byref(me))
4315    if not success:
4316        if GetLastError() == ERROR_NO_MORE_FILES:
4317            return None
4318        raise ctypes.WinError()
4319    return me
4320
4321# BOOL WINAPI Heap32First(
4322#   __inout  LPHEAPENTRY32 lphe,
4323#   __in     DWORD th32ProcessID,
4324#   __in     ULONG_PTR th32HeapID
4325# );
4326def Heap32First(th32ProcessID, th32HeapID):
4327    _Heap32First = windll.kernel32.Heap32First
4328    _Heap32First.argtypes = [LPHEAPENTRY32, DWORD, ULONG_PTR]
4329    _Heap32First.restype  = bool
4330
4331    he = HEAPENTRY32()
4332    he.dwSize = sizeof(HEAPENTRY32)
4333    success = _Heap32First(byref(he), th32ProcessID, th32HeapID)
4334    if not success:
4335        if GetLastError() == ERROR_NO_MORE_FILES:
4336            return None
4337        raise ctypes.WinError()
4338    return he
4339
4340# BOOL WINAPI Heap32Next(
4341#   __out  LPHEAPENTRY32 lphe
4342# );
4343def Heap32Next(he):
4344    _Heap32Next = windll.kernel32.Heap32Next
4345    _Heap32Next.argtypes = [LPHEAPENTRY32]
4346    _Heap32Next.restype  = bool
4347
4348    he.dwSize = sizeof(HEAPENTRY32)
4349    success = _Heap32Next(byref(he))
4350    if not success:
4351        if GetLastError() == ERROR_NO_MORE_FILES:
4352            return None
4353        raise ctypes.WinError()
4354    return he
4355
4356# BOOL WINAPI Heap32ListFirst(
4357#   __in     HANDLE hSnapshot,
4358#   __inout  LPHEAPLIST32 lphl
4359# );
4360def Heap32ListFirst(hSnapshot):
4361    _Heap32ListFirst = windll.kernel32.Heap32ListFirst
4362    _Heap32ListFirst.argtypes = [HANDLE, LPHEAPLIST32]
4363    _Heap32ListFirst.restype  = bool
4364
4365    hl = HEAPLIST32()
4366    hl.dwSize = sizeof(HEAPLIST32)
4367    success = _Heap32ListFirst(hSnapshot, byref(hl))
4368    if not success:
4369        if GetLastError() == ERROR_NO_MORE_FILES:
4370            return None
4371        raise ctypes.WinError()
4372    return hl
4373
4374# BOOL WINAPI Heap32ListNext(
4375#   __in     HANDLE hSnapshot,
4376#   __out  LPHEAPLIST32 lphl
4377# );
4378def Heap32ListNext(hSnapshot, hl = None):
4379    _Heap32ListNext = windll.kernel32.Heap32ListNext
4380    _Heap32ListNext.argtypes = [HANDLE, LPHEAPLIST32]
4381    _Heap32ListNext.restype  = bool
4382
4383    if hl is None:
4384        hl = HEAPLIST32()
4385    hl.dwSize = sizeof(HEAPLIST32)
4386    success = _Heap32ListNext(hSnapshot, byref(hl))
4387    if not success:
4388        if GetLastError() == ERROR_NO_MORE_FILES:
4389            return None
4390        raise ctypes.WinError()
4391    return hl
4392
4393# BOOL WINAPI Toolhelp32ReadProcessMemory(
4394#   __in   DWORD th32ProcessID,
4395#   __in   LPCVOID lpBaseAddress,
4396#   __out  LPVOID lpBuffer,
4397#   __in   SIZE_T cbRead,
4398#   __out  SIZE_T lpNumberOfBytesRead
4399# );
4400def Toolhelp32ReadProcessMemory(th32ProcessID, lpBaseAddress, cbRead):
4401    _Toolhelp32ReadProcessMemory = windll.kernel32.Toolhelp32ReadProcessMemory
4402    _Toolhelp32ReadProcessMemory.argtypes = [DWORD, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
4403    _Toolhelp32ReadProcessMemory.restype  = bool
4404
4405    lpBuffer            = ctypes.create_string_buffer('', cbRead)
4406    lpNumberOfBytesRead = SIZE_T(0)
4407    success = _Toolhelp32ReadProcessMemory(th32ProcessID, lpBaseAddress, lpBuffer, cbRead, byref(lpNumberOfBytesRead))
4408    if not success and GetLastError() != ERROR_PARTIAL_COPY:
4409        raise ctypes.WinError()
4410    return str(lpBuffer.raw)[:lpNumberOfBytesRead.value]
4411
4412#------------------------------------------------------------------------------
4413# Miscellaneous system information
4414
4415# BOOL WINAPI GetProcessDEPPolicy(
4416#  __in   HANDLE hProcess,
4417#  __out  LPDWORD lpFlags,
4418#  __out  PBOOL lpPermanent
4419# );
4420# Contribution by ivanlef0u (http://ivanlef0u.fr/)
4421# XP SP3 and > only
4422def GetProcessDEPPolicy(hProcess):
4423    _GetProcessDEPPolicy = windll.kernel32.GetProcessDEPPolicy
4424    _GetProcessDEPPolicy.argtypes = [HANDLE, LPDWORD, PBOOL]
4425    _GetProcessDEPPolicy.restype  = bool
4426    _GetProcessDEPPolicy.errcheck = RaiseIfZero
4427
4428    lpFlags = DWORD(0)
4429    lpPermanent = BOOL(0)
4430    _GetProcessDEPPolicy(hProcess, byref(lpFlags), byref(lpPermanent))
4431    return (lpFlags.value, lpPermanent.value)
4432
4433# DWORD WINAPI GetCurrentProcessorNumber(void);
4434def GetCurrentProcessorNumber():
4435    _GetCurrentProcessorNumber = windll.kernel32.GetCurrentProcessorNumber
4436    _GetCurrentProcessorNumber.argtypes = []
4437    _GetCurrentProcessorNumber.restype  = DWORD
4438    _GetCurrentProcessorNumber.errcheck = RaiseIfZero
4439    return _GetCurrentProcessorNumber()
4440
4441# VOID WINAPI FlushProcessWriteBuffers(void);
4442def FlushProcessWriteBuffers():
4443    _FlushProcessWriteBuffers = windll.kernel32.FlushProcessWriteBuffers
4444    _FlushProcessWriteBuffers.argtypes = []
4445    _FlushProcessWriteBuffers.restype  = None
4446    _FlushProcessWriteBuffers()
4447
4448# BOOL WINAPI GetLogicalProcessorInformation(
4449#   __out    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
4450#   __inout  PDWORD ReturnLength
4451# );
4452
4453# TO DO http://msdn.microsoft.com/en-us/library/ms683194(VS.85).aspx
4454
4455# BOOL WINAPI GetProcessIoCounters(
4456#   __in   HANDLE hProcess,
4457#   __out  PIO_COUNTERS lpIoCounters
4458# );
4459
4460# TO DO http://msdn.microsoft.com/en-us/library/ms683218(VS.85).aspx
4461
4462# DWORD WINAPI GetGuiResources(
4463#   __in  HANDLE hProcess,
4464#   __in  DWORD uiFlags
4465# );
4466def GetGuiResources(hProcess, uiFlags = GR_GDIOBJECTS):
4467    _GetGuiResources = windll.kernel32.GetGuiResources
4468    _GetGuiResources.argtypes = [HANDLE, DWORD]
4469    _GetGuiResources.restype  = DWORD
4470
4471    dwCount = _GetGuiResources(hProcess, uiFlags)
4472    if dwCount == 0:
4473        errcode = GetLastError()
4474        if errcode != ERROR_SUCCESS:
4475            raise ctypes.WinError(errcode)
4476    return dwCount
4477
4478# BOOL WINAPI GetProcessHandleCount(
4479#   __in     HANDLE hProcess,
4480#   __inout  PDWORD pdwHandleCount
4481# );
4482def GetProcessHandleCount(hProcess):
4483    _GetProcessHandleCount = windll.kernel32.GetProcessHandleCount
4484    _GetProcessHandleCount.argtypes = [HANDLE, PDWORD]
4485    _GetProcessHandleCount.restype  = DWORD
4486    _GetProcessHandleCount.errcheck = RaiseIfZero
4487
4488    pdwHandleCount = DWORD(0)
4489    _GetProcessHandleCount(hProcess, byref(pdwHandleCount))
4490    return pdwHandleCount.value
4491
4492# BOOL WINAPI GetProcessTimes(
4493#   __in   HANDLE hProcess,
4494#   __out  LPFILETIME lpCreationTime,
4495#   __out  LPFILETIME lpExitTime,
4496#   __out  LPFILETIME lpKernelTime,
4497#   __out  LPFILETIME lpUserTime
4498# );
4499def GetProcessTimes(hProcess = None):
4500    _GetProcessTimes = windll.kernel32.GetProcessTimes
4501    _GetProcessTimes.argtypes = [HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME]
4502    _GetProcessTimes.restype  = bool
4503    _GetProcessTimes.errcheck = RaiseIfZero
4504
4505    if hProcess is None:
4506        hProcess = GetCurrentProcess()
4507
4508    CreationTime = FILETIME()
4509    ExitTime     = FILETIME()
4510    KernelTime   = FILETIME()
4511    UserTime     = FILETIME()
4512
4513    _GetProcessTimes(hProcess, byref(CreationTime), byref(ExitTime), byref(KernelTime), byref(UserTime))
4514
4515    return (CreationTime, ExitTime, KernelTime, UserTime)
4516
4517# BOOL WINAPI FileTimeToSystemTime(
4518#   __in   const FILETIME *lpFileTime,
4519#   __out  LPSYSTEMTIME lpSystemTime
4520# );
4521def FileTimeToSystemTime(lpFileTime):
4522    _FileTimeToSystemTime = windll.kernel32.FileTimeToSystemTime
4523    _FileTimeToSystemTime.argtypes = [LPFILETIME, LPSYSTEMTIME]
4524    _FileTimeToSystemTime.restype  = bool
4525    _FileTimeToSystemTime.errcheck = RaiseIfZero
4526
4527    if isinstance(lpFileTime, FILETIME):
4528        FileTime = lpFileTime
4529    else:
4530        FileTime = FILETIME()
4531        FileTime.dwLowDateTime  = lpFileTime & 0xFFFFFFFF
4532        FileTime.dwHighDateTime = lpFileTime >> 32
4533    SystemTime = SYSTEMTIME()
4534    _FileTimeToSystemTime(byref(FileTime), byref(SystemTime))
4535    return SystemTime
4536
4537# void WINAPI GetSystemTimeAsFileTime(
4538#   __out  LPFILETIME lpSystemTimeAsFileTime
4539# );
4540def GetSystemTimeAsFileTime():
4541    _GetSystemTimeAsFileTime = windll.kernel32.GetSystemTimeAsFileTime
4542    _GetSystemTimeAsFileTime.argtypes = [LPFILETIME]
4543    _GetSystemTimeAsFileTime.restype  = None
4544
4545    FileTime = FILETIME()
4546    _GetSystemTimeAsFileTime(byref(FileTime))
4547    return FileTime
4548
4549#------------------------------------------------------------------------------
4550# Global ATOM API
4551
4552# ATOM GlobalAddAtom(
4553#   __in  LPCTSTR lpString
4554# );
4555def GlobalAddAtomA(lpString):
4556    _GlobalAddAtomA = windll.kernel32.GlobalAddAtomA
4557    _GlobalAddAtomA.argtypes = [LPSTR]
4558    _GlobalAddAtomA.restype  = ATOM
4559    _GlobalAddAtomA.errcheck = RaiseIfZero
4560    return _GlobalAddAtomA(lpString)
4561
4562def GlobalAddAtomW(lpString):
4563    _GlobalAddAtomW = windll.kernel32.GlobalAddAtomW
4564    _GlobalAddAtomW.argtypes = [LPWSTR]
4565    _GlobalAddAtomW.restype  = ATOM
4566    _GlobalAddAtomW.errcheck = RaiseIfZero
4567    return _GlobalAddAtomW(lpString)
4568
4569GlobalAddAtom = GuessStringType(GlobalAddAtomA, GlobalAddAtomW)
4570
4571# ATOM GlobalFindAtom(
4572#   __in  LPCTSTR lpString
4573# );
4574def GlobalFindAtomA(lpString):
4575    _GlobalFindAtomA = windll.kernel32.GlobalFindAtomA
4576    _GlobalFindAtomA.argtypes = [LPSTR]
4577    _GlobalFindAtomA.restype  = ATOM
4578    _GlobalFindAtomA.errcheck = RaiseIfZero
4579    return _GlobalFindAtomA(lpString)
4580
4581def GlobalFindAtomW(lpString):
4582    _GlobalFindAtomW = windll.kernel32.GlobalFindAtomW
4583    _GlobalFindAtomW.argtypes = [LPWSTR]
4584    _GlobalFindAtomW.restype  = ATOM
4585    _GlobalFindAtomW.errcheck = RaiseIfZero
4586    return _GlobalFindAtomW(lpString)
4587
4588GlobalFindAtom = GuessStringType(GlobalFindAtomA, GlobalFindAtomW)
4589
4590# UINT GlobalGetAtomName(
4591#   __in   ATOM nAtom,
4592#   __out  LPTSTR lpBuffer,
4593#   __in   int nSize
4594# );
4595def GlobalGetAtomNameA(nAtom):
4596    _GlobalGetAtomNameA = windll.kernel32.GlobalGetAtomNameA
4597    _GlobalGetAtomNameA.argtypes = [ATOM, LPSTR, ctypes.c_int]
4598    _GlobalGetAtomNameA.restype  = UINT
4599    _GlobalGetAtomNameA.errcheck = RaiseIfZero
4600
4601    nSize = 64
4602    while 1:
4603        lpBuffer = ctypes.create_string_buffer("", nSize)
4604        nCopied  = _GlobalGetAtomNameA(nAtom, lpBuffer, nSize)
4605        if nCopied < nSize - 1:
4606            break
4607        nSize = nSize + 64
4608    return lpBuffer.value
4609
4610def GlobalGetAtomNameW(nAtom):
4611    _GlobalGetAtomNameW = windll.kernel32.GlobalGetAtomNameW
4612    _GlobalGetAtomNameW.argtypes = [ATOM, LPWSTR, ctypes.c_int]
4613    _GlobalGetAtomNameW.restype  = UINT
4614    _GlobalGetAtomNameW.errcheck = RaiseIfZero
4615
4616    nSize = 64
4617    while 1:
4618        lpBuffer = ctypes.create_unicode_buffer(u"", nSize)
4619        nCopied  = _GlobalGetAtomNameW(nAtom, lpBuffer, nSize)
4620        if nCopied < nSize - 1:
4621            break
4622        nSize = nSize + 64
4623    return lpBuffer.value
4624
4625GlobalGetAtomName = GuessStringType(GlobalGetAtomNameA, GlobalGetAtomNameW)
4626
4627# ATOM GlobalDeleteAtom(
4628#   __in  ATOM nAtom
4629# );
4630def GlobalDeleteAtom(nAtom):
4631    _GlobalDeleteAtom = windll.kernel32.GlobalDeleteAtom
4632    _GlobalDeleteAtom.argtypes
4633    _GlobalDeleteAtom.restype
4634    SetLastError(ERROR_SUCCESS)
4635    _GlobalDeleteAtom(nAtom)
4636    error = GetLastError()
4637    if error != ERROR_SUCCESS:
4638        raise ctypes.WinError(error)
4639
4640#------------------------------------------------------------------------------
4641# Wow64
4642
4643# DWORD WINAPI Wow64SuspendThread(
4644#   _In_  HANDLE hThread
4645# );
4646def Wow64SuspendThread(hThread):
4647    _Wow64SuspendThread = windll.kernel32.Wow64SuspendThread
4648    _Wow64SuspendThread.argtypes = [HANDLE]
4649    _Wow64SuspendThread.restype  = DWORD
4650
4651    previousCount = _Wow64SuspendThread(hThread)
4652    if previousCount == DWORD(-1).value:
4653        raise ctypes.WinError()
4654    return previousCount
4655
4656# BOOLEAN WINAPI Wow64EnableWow64FsRedirection(
4657#   __in  BOOLEAN Wow64FsEnableRedirection
4658# );
4659def Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection):
4660    """
4661    This function may not work reliably when there are nested calls. Therefore,
4662    this function has been replaced by the L{Wow64DisableWow64FsRedirection}
4663    and L{Wow64RevertWow64FsRedirection} functions.
4664
4665    @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/aa365744(v=vs.85).aspx}
4666    """
4667    _Wow64EnableWow64FsRedirection = windll.kernel32.Wow64EnableWow64FsRedirection
4668    _Wow64EnableWow64FsRedirection.argtypes = [BOOLEAN]
4669    _Wow64EnableWow64FsRedirection.restype  = BOOLEAN
4670    _Wow64EnableWow64FsRedirection.errcheck = RaiseIfZero
4671
4672# BOOL WINAPI Wow64DisableWow64FsRedirection(
4673#   __out  PVOID *OldValue
4674# );
4675def Wow64DisableWow64FsRedirection():
4676    _Wow64DisableWow64FsRedirection = windll.kernel32.Wow64DisableWow64FsRedirection
4677    _Wow64DisableWow64FsRedirection.argtypes = [PPVOID]
4678    _Wow64DisableWow64FsRedirection.restype  = BOOL
4679    _Wow64DisableWow64FsRedirection.errcheck = RaiseIfZero
4680
4681    OldValue = PVOID(None)
4682    _Wow64DisableWow64FsRedirection(byref(OldValue))
4683    return OldValue
4684
4685# BOOL WINAPI Wow64RevertWow64FsRedirection(
4686#   __in  PVOID OldValue
4687# );
4688def Wow64RevertWow64FsRedirection(OldValue):
4689    _Wow64RevertWow64FsRedirection = windll.kernel32.Wow64RevertWow64FsRedirection
4690    _Wow64RevertWow64FsRedirection.argtypes = [PVOID]
4691    _Wow64RevertWow64FsRedirection.restype  = BOOL
4692    _Wow64RevertWow64FsRedirection.errcheck = RaiseIfZero
4693    _Wow64RevertWow64FsRedirection(OldValue)
4694
4695#==============================================================================
4696# This calculates the list of exported symbols.
4697_all = set(vars().keys()).difference(_all)
4698__all__ = [_x for _x in _all if not _x.startswith('_')]
4699__all__.sort()
4700#==============================================================================
4701
4702#==============================================================================
4703# Mark functions that Psyco cannot compile.
4704# In your programs, don't use psyco.full().
4705# Call psyco.bind() on your main function instead.
4706
4707try:
4708    import psyco
4709    psyco.cannotcompile(WaitForDebugEvent)
4710    psyco.cannotcompile(WaitForSingleObject)
4711    psyco.cannotcompile(WaitForSingleObjectEx)
4712    psyco.cannotcompile(WaitForMultipleObjects)
4713    psyco.cannotcompile(WaitForMultipleObjectsEx)
4714except ImportError:
4715    pass
4716#==============================================================================
4717