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"""
32CONTEXT structure for amd64.
33"""
34
35__revision__ = "$Id$"
36
37from winappdbg.win32.defines import *
38from winappdbg.win32.version import ARCH_AMD64
39from winappdbg.win32 import context_i386
40
41#==============================================================================
42# This is used later on to calculate the list of exported symbols.
43_all = None
44_all = set(vars().keys())
45#==============================================================================
46
47#--- CONTEXT structures and constants -----------------------------------------
48
49# The following values specify the type of access in the first parameter
50# of the exception record when the exception code specifies an access
51# violation.
52EXCEPTION_READ_FAULT        = 0     # exception caused by a read
53EXCEPTION_WRITE_FAULT       = 1     # exception caused by a write
54EXCEPTION_EXECUTE_FAULT     = 8     # exception caused by an instruction fetch
55
56CONTEXT_AMD64           = 0x00100000
57
58CONTEXT_CONTROL         = (CONTEXT_AMD64 | long(0x1))
59CONTEXT_INTEGER         = (CONTEXT_AMD64 | long(0x2))
60CONTEXT_SEGMENTS        = (CONTEXT_AMD64 | long(0x4))
61CONTEXT_FLOATING_POINT  = (CONTEXT_AMD64 | long(0x8))
62CONTEXT_DEBUG_REGISTERS = (CONTEXT_AMD64 | long(0x10))
63
64CONTEXT_MMX_REGISTERS   = CONTEXT_FLOATING_POINT
65
66CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
67
68CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
69               CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS)
70
71CONTEXT_EXCEPTION_ACTIVE    = 0x8000000
72CONTEXT_SERVICE_ACTIVE      = 0x10000000
73CONTEXT_EXCEPTION_REQUEST   = 0x40000000
74CONTEXT_EXCEPTION_REPORTING = 0x80000000
75
76INITIAL_MXCSR = 0x1f80            # initial MXCSR value
77INITIAL_FPCSR = 0x027f            # initial FPCSR value
78
79# typedef struct _XMM_SAVE_AREA32 {
80#     WORD   ControlWord;
81#     WORD   StatusWord;
82#     BYTE  TagWord;
83#     BYTE  Reserved1;
84#     WORD   ErrorOpcode;
85#     DWORD ErrorOffset;
86#     WORD   ErrorSelector;
87#     WORD   Reserved2;
88#     DWORD DataOffset;
89#     WORD   DataSelector;
90#     WORD   Reserved3;
91#     DWORD MxCsr;
92#     DWORD MxCsr_Mask;
93#     M128A FloatRegisters[8];
94#     M128A XmmRegisters[16];
95#     BYTE  Reserved4[96];
96# } XMM_SAVE_AREA32, *PXMM_SAVE_AREA32;
97class XMM_SAVE_AREA32(Structure):
98    _pack_ = 1
99    _fields_ = [
100        ('ControlWord',     WORD),
101        ('StatusWord',      WORD),
102        ('TagWord',         BYTE),
103        ('Reserved1',       BYTE),
104        ('ErrorOpcode',     WORD),
105        ('ErrorOffset',     DWORD),
106        ('ErrorSelector',   WORD),
107        ('Reserved2',       WORD),
108        ('DataOffset',      DWORD),
109        ('DataSelector',    WORD),
110        ('Reserved3',       WORD),
111        ('MxCsr',           DWORD),
112        ('MxCsr_Mask',      DWORD),
113        ('FloatRegisters',  M128A * 8),
114        ('XmmRegisters',    M128A * 16),
115        ('Reserved4',       BYTE * 96),
116    ]
117
118    def from_dict(self):
119        raise NotImplementedError()
120
121    def to_dict(self):
122        d = dict()
123        for name, type in self._fields_:
124            if name in ('FloatRegisters', 'XmmRegisters'):
125                d[name] = tuple([ (x.LowPart + (x.HighPart << 64)) for x in getattr(self, name) ])
126            elif name == 'Reserved4':
127                d[name] = tuple([ chr(x) for x in getattr(self, name) ])
128            else:
129                d[name] = getattr(self, name)
130        return d
131
132LEGACY_SAVE_AREA_LENGTH = sizeof(XMM_SAVE_AREA32)
133
134PXMM_SAVE_AREA32 = ctypes.POINTER(XMM_SAVE_AREA32)
135LPXMM_SAVE_AREA32 = PXMM_SAVE_AREA32
136
137# //
138# // Context Frame
139# //
140# //  This frame has a several purposes: 1) it is used as an argument to
141# //  NtContinue, 2) is is used to constuct a call frame for APC delivery,
142# //  and 3) it is used in the user level thread creation routines.
143# //
144# //
145# // The flags field within this record controls the contents of a CONTEXT
146# // record.
147# //
148# // If the context record is used as an input parameter, then for each
149# // portion of the context record controlled by a flag whose value is
150# // set, it is assumed that that portion of the context record contains
151# // valid context. If the context record is being used to modify a threads
152# // context, then only that portion of the threads context is modified.
153# //
154# // If the context record is used as an output parameter to capture the
155# // context of a thread, then only those portions of the thread's context
156# // corresponding to set flags will be returned.
157# //
158# // CONTEXT_CONTROL specifies SegSs, Rsp, SegCs, Rip, and EFlags.
159# //
160# // CONTEXT_INTEGER specifies Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, and R8-R15.
161# //
162# // CONTEXT_SEGMENTS specifies SegDs, SegEs, SegFs, and SegGs.
163# //
164# // CONTEXT_DEBUG_REGISTERS specifies Dr0-Dr3 and Dr6-Dr7.
165# //
166# // CONTEXT_MMX_REGISTERS specifies the floating point and extended registers
167# //     Mm0/St0-Mm7/St7 and Xmm0-Xmm15).
168# //
169#
170# typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
171#
172#     //
173#     // Register parameter home addresses.
174#     //
175#     // N.B. These fields are for convience - they could be used to extend the
176#     //      context record in the future.
177#     //
178#
179#     DWORD64 P1Home;
180#     DWORD64 P2Home;
181#     DWORD64 P3Home;
182#     DWORD64 P4Home;
183#     DWORD64 P5Home;
184#     DWORD64 P6Home;
185#
186#     //
187#     // Control flags.
188#     //
189#
190#     DWORD ContextFlags;
191#     DWORD MxCsr;
192#
193#     //
194#     // Segment Registers and processor flags.
195#     //
196#
197#     WORD   SegCs;
198#     WORD   SegDs;
199#     WORD   SegEs;
200#     WORD   SegFs;
201#     WORD   SegGs;
202#     WORD   SegSs;
203#     DWORD EFlags;
204#
205#     //
206#     // Debug registers
207#     //
208#
209#     DWORD64 Dr0;
210#     DWORD64 Dr1;
211#     DWORD64 Dr2;
212#     DWORD64 Dr3;
213#     DWORD64 Dr6;
214#     DWORD64 Dr7;
215#
216#     //
217#     // Integer registers.
218#     //
219#
220#     DWORD64 Rax;
221#     DWORD64 Rcx;
222#     DWORD64 Rdx;
223#     DWORD64 Rbx;
224#     DWORD64 Rsp;
225#     DWORD64 Rbp;
226#     DWORD64 Rsi;
227#     DWORD64 Rdi;
228#     DWORD64 R8;
229#     DWORD64 R9;
230#     DWORD64 R10;
231#     DWORD64 R11;
232#     DWORD64 R12;
233#     DWORD64 R13;
234#     DWORD64 R14;
235#     DWORD64 R15;
236#
237#     //
238#     // Program counter.
239#     //
240#
241#     DWORD64 Rip;
242#
243#     //
244#     // Floating point state.
245#     //
246#
247#     union {
248#         XMM_SAVE_AREA32 FltSave;
249#         struct {
250#             M128A Header[2];
251#             M128A Legacy[8];
252#             M128A Xmm0;
253#             M128A Xmm1;
254#             M128A Xmm2;
255#             M128A Xmm3;
256#             M128A Xmm4;
257#             M128A Xmm5;
258#             M128A Xmm6;
259#             M128A Xmm7;
260#             M128A Xmm8;
261#             M128A Xmm9;
262#             M128A Xmm10;
263#             M128A Xmm11;
264#             M128A Xmm12;
265#             M128A Xmm13;
266#             M128A Xmm14;
267#             M128A Xmm15;
268#         };
269#     };
270#
271#     //
272#     // Vector registers.
273#     //
274#
275#     M128A VectorRegister[26];
276#     DWORD64 VectorControl;
277#
278#     //
279#     // Special debug control registers.
280#     //
281#
282#     DWORD64 DebugControl;
283#     DWORD64 LastBranchToRip;
284#     DWORD64 LastBranchFromRip;
285#     DWORD64 LastExceptionToRip;
286#     DWORD64 LastExceptionFromRip;
287# } CONTEXT, *PCONTEXT;
288
289class _CONTEXT_FLTSAVE_STRUCT(Structure):
290    _fields_ = [
291        ('Header',                  M128A * 2),
292        ('Legacy',                  M128A * 8),
293        ('Xmm0',                    M128A),
294        ('Xmm1',                    M128A),
295        ('Xmm2',                    M128A),
296        ('Xmm3',                    M128A),
297        ('Xmm4',                    M128A),
298        ('Xmm5',                    M128A),
299        ('Xmm6',                    M128A),
300        ('Xmm7',                    M128A),
301        ('Xmm8',                    M128A),
302        ('Xmm9',                    M128A),
303        ('Xmm10',                   M128A),
304        ('Xmm11',                   M128A),
305        ('Xmm12',                   M128A),
306        ('Xmm13',                   M128A),
307        ('Xmm14',                   M128A),
308        ('Xmm15',                   M128A),
309    ]
310
311    def from_dict(self):
312        raise NotImplementedError()
313
314    def to_dict(self):
315        d = dict()
316        for name, type in self._fields_:
317            if name in ('Header', 'Legacy'):
318                d[name] = tuple([ (x.Low + (x.High << 64)) for x in getattr(self, name) ])
319            else:
320                x = getattr(self, name)
321                d[name] = x.Low + (x.High << 64)
322        return d
323
324class _CONTEXT_FLTSAVE_UNION(Union):
325    _fields_ = [
326        ('flt',                     XMM_SAVE_AREA32),
327        ('xmm',                     _CONTEXT_FLTSAVE_STRUCT),
328    ]
329
330    def from_dict(self):
331        raise NotImplementedError()
332
333    def to_dict(self):
334        d = dict()
335        d['flt'] = self.flt.to_dict()
336        d['xmm'] = self.xmm.to_dict()
337        return d
338
339class CONTEXT(Structure):
340    arch = ARCH_AMD64
341
342    _pack_ = 16
343    _fields_ = [
344
345        # Register parameter home addresses.
346        ('P1Home',                  DWORD64),
347        ('P2Home',                  DWORD64),
348        ('P3Home',                  DWORD64),
349        ('P4Home',                  DWORD64),
350        ('P5Home',                  DWORD64),
351        ('P6Home',                  DWORD64),
352
353        # Control flags.
354        ('ContextFlags',            DWORD),
355        ('MxCsr',                   DWORD),
356
357        # Segment Registers and processor flags.
358        ('SegCs',                   WORD),
359        ('SegDs',                   WORD),
360        ('SegEs',                   WORD),
361        ('SegFs',                   WORD),
362        ('SegGs',                   WORD),
363        ('SegSs',                   WORD),
364        ('EFlags',                  DWORD),
365
366        # Debug registers.
367        ('Dr0',                     DWORD64),
368        ('Dr1',                     DWORD64),
369        ('Dr2',                     DWORD64),
370        ('Dr3',                     DWORD64),
371        ('Dr6',                     DWORD64),
372        ('Dr7',                     DWORD64),
373
374        # Integer registers.
375        ('Rax',                     DWORD64),
376        ('Rcx',                     DWORD64),
377        ('Rdx',                     DWORD64),
378        ('Rbx',                     DWORD64),
379        ('Rsp',                     DWORD64),
380        ('Rbp',                     DWORD64),
381        ('Rsi',                     DWORD64),
382        ('Rdi',                     DWORD64),
383        ('R8',                      DWORD64),
384        ('R9',                      DWORD64),
385        ('R10',                     DWORD64),
386        ('R11',                     DWORD64),
387        ('R12',                     DWORD64),
388        ('R13',                     DWORD64),
389        ('R14',                     DWORD64),
390        ('R15',                     DWORD64),
391
392        # Program counter.
393        ('Rip',                     DWORD64),
394
395        # Floating point state.
396        ('FltSave',                 _CONTEXT_FLTSAVE_UNION),
397
398        # Vector registers.
399        ('VectorRegister',          M128A * 26),
400        ('VectorControl',           DWORD64),
401
402        # Special debug control registers.
403        ('DebugControl',            DWORD64),
404        ('LastBranchToRip',         DWORD64),
405        ('LastBranchFromRip',       DWORD64),
406        ('LastExceptionToRip',      DWORD64),
407        ('LastExceptionFromRip',    DWORD64),
408    ]
409
410    _others = ('P1Home', 'P2Home', 'P3Home', 'P4Home', 'P5Home', 'P6Home', \
411               'MxCsr', 'VectorRegister', 'VectorControl')
412    _control = ('SegSs', 'Rsp', 'SegCs', 'Rip', 'EFlags')
413    _integer = ('Rax', 'Rcx', 'Rdx', 'Rbx', 'Rsp', 'Rbp', 'Rsi', 'Rdi', \
414                'R8', 'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15')
415    _segments = ('SegDs', 'SegEs', 'SegFs', 'SegGs')
416    _debug = ('Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7', \
417              'DebugControl', 'LastBranchToRip', 'LastBranchFromRip', \
418              'LastExceptionToRip', 'LastExceptionFromRip')
419    _mmx = ('Xmm0', 'Xmm1', 'Xmm2', 'Xmm3', 'Xmm4', 'Xmm5', 'Xmm6', 'Xmm7', \
420          'Xmm8', 'Xmm9', 'Xmm10', 'Xmm11', 'Xmm12', 'Xmm13', 'Xmm14', 'Xmm15')
421
422    # XXX TODO
423    # Convert VectorRegister and Xmm0-Xmm15 to pure Python types!
424
425    @classmethod
426    def from_dict(cls, ctx):
427        'Instance a new structure from a Python native type.'
428        ctx = Context(ctx)
429        s = cls()
430        ContextFlags = ctx['ContextFlags']
431        s.ContextFlags = ContextFlags
432        for key in cls._others:
433            if key != 'VectorRegister':
434                setattr(s, key, ctx[key])
435            else:
436                w = ctx[key]
437                v = (M128A * len(w))()
438                i = 0
439                for x in w:
440                    y = M128A()
441                    y.High = x >> 64
442                    y.Low = x - (x >> 64)
443                    v[i] = y
444                    i += 1
445                setattr(s, key, v)
446        if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL:
447            for key in cls._control:
448                setattr(s, key, ctx[key])
449        if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER:
450            for key in cls._integer:
451                setattr(s, key, ctx[key])
452        if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS:
453            for key in cls._segments:
454                setattr(s, key, ctx[key])
455        if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS:
456            for key in cls._debug:
457                setattr(s, key, ctx[key])
458        if (ContextFlags & CONTEXT_MMX_REGISTERS) == CONTEXT_MMX_REGISTERS:
459            xmm = s.FltSave.xmm
460            for key in cls._mmx:
461                y = M128A()
462                y.High = x >> 64
463                y.Low = x - (x >> 64)
464                setattr(xmm, key, y)
465        return s
466
467    def to_dict(self):
468        'Convert a structure into a Python dictionary.'
469        ctx = Context()
470        ContextFlags = self.ContextFlags
471        ctx['ContextFlags'] = ContextFlags
472        for key in self._others:
473            if key != 'VectorRegister':
474                ctx[key] = getattr(self, key)
475            else:
476                ctx[key] = tuple([ (x.Low + (x.High << 64)) for x in getattr(self, key) ])
477        if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL:
478            for key in self._control:
479                ctx[key] = getattr(self, key)
480        if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER:
481            for key in self._integer:
482                ctx[key] = getattr(self, key)
483        if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS:
484            for key in self._segments:
485                ctx[key] = getattr(self, key)
486        if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS:
487            for key in self._debug:
488                ctx[key] = getattr(self, key)
489        if (ContextFlags & CONTEXT_MMX_REGISTERS) == CONTEXT_MMX_REGISTERS:
490            xmm = self.FltSave.xmm.to_dict()
491            for key in self._mmx:
492                ctx[key] = xmm.get(key)
493        return ctx
494
495PCONTEXT = ctypes.POINTER(CONTEXT)
496LPCONTEXT = PCONTEXT
497
498class Context(dict):
499    """
500    Register context dictionary for the amd64 architecture.
501    """
502
503    arch = CONTEXT.arch
504
505    def __get_pc(self):
506        return self['Rip']
507    def __set_pc(self, value):
508        self['Rip'] = value
509    pc = property(__get_pc, __set_pc)
510
511    def __get_sp(self):
512        return self['Rsp']
513    def __set_sp(self, value):
514        self['Rsp'] = value
515    sp = property(__get_sp, __set_sp)
516
517    def __get_fp(self):
518        return self['Rbp']
519    def __set_fp(self, value):
520        self['Rbp'] = value
521    fp = property(__get_fp, __set_fp)
522
523#--- LDT_ENTRY structure ------------------------------------------------------
524
525# typedef struct _LDT_ENTRY {
526#   WORD LimitLow;
527#   WORD BaseLow;
528#   union {
529#     struct {
530#       BYTE BaseMid;
531#       BYTE Flags1;
532#       BYTE Flags2;
533#       BYTE BaseHi;
534#     } Bytes;
535#     struct {
536#       DWORD BaseMid  :8;
537#       DWORD Type  :5;
538#       DWORD Dpl  :2;
539#       DWORD Pres  :1;
540#       DWORD LimitHi  :4;
541#       DWORD Sys  :1;
542#       DWORD Reserved_0  :1;
543#       DWORD Default_Big  :1;
544#       DWORD Granularity  :1;
545#       DWORD BaseHi  :8;
546#     } Bits;
547#   } HighWord;
548# } LDT_ENTRY,
549#  *PLDT_ENTRY;
550
551class _LDT_ENTRY_BYTES_(Structure):
552    _pack_ = 1
553    _fields_ = [
554        ('BaseMid',         BYTE),
555        ('Flags1',          BYTE),
556        ('Flags2',          BYTE),
557        ('BaseHi',          BYTE),
558    ]
559
560class _LDT_ENTRY_BITS_(Structure):
561    _pack_ = 1
562    _fields_ = [
563        ('BaseMid',         DWORD,  8),
564        ('Type',            DWORD,  5),
565        ('Dpl',             DWORD,  2),
566        ('Pres',            DWORD,  1),
567        ('LimitHi',         DWORD,  4),
568        ('Sys',             DWORD,  1),
569        ('Reserved_0',      DWORD,  1),
570        ('Default_Big',     DWORD,  1),
571        ('Granularity',     DWORD,  1),
572        ('BaseHi',          DWORD,  8),
573    ]
574
575class _LDT_ENTRY_HIGHWORD_(Union):
576    _pack_ = 1
577    _fields_ = [
578        ('Bytes',           _LDT_ENTRY_BYTES_),
579        ('Bits',            _LDT_ENTRY_BITS_),
580    ]
581
582class LDT_ENTRY(Structure):
583    _pack_ = 1
584    _fields_ = [
585        ('LimitLow',        WORD),
586        ('BaseLow',         WORD),
587        ('HighWord',        _LDT_ENTRY_HIGHWORD_),
588    ]
589
590PLDT_ENTRY = POINTER(LDT_ENTRY)
591LPLDT_ENTRY = PLDT_ENTRY
592
593#--- WOW64 CONTEXT structure and constants ------------------------------------
594
595# Value of SegCs in a Wow64 thread when running in 32 bits mode
596WOW64_CS32 = 0x23
597
598WOW64_CONTEXT_i386 = long(0x00010000)
599WOW64_CONTEXT_i486 = long(0x00010000)
600
601WOW64_CONTEXT_CONTROL               = (WOW64_CONTEXT_i386 | long(0x00000001))
602WOW64_CONTEXT_INTEGER               = (WOW64_CONTEXT_i386 | long(0x00000002))
603WOW64_CONTEXT_SEGMENTS              = (WOW64_CONTEXT_i386 | long(0x00000004))
604WOW64_CONTEXT_FLOATING_POINT        = (WOW64_CONTEXT_i386 | long(0x00000008))
605WOW64_CONTEXT_DEBUG_REGISTERS       = (WOW64_CONTEXT_i386 | long(0x00000010))
606WOW64_CONTEXT_EXTENDED_REGISTERS    = (WOW64_CONTEXT_i386 | long(0x00000020))
607
608WOW64_CONTEXT_FULL                  = (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)
609WOW64_CONTEXT_ALL                   = (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | WOW64_CONTEXT_EXTENDED_REGISTERS)
610
611WOW64_SIZE_OF_80387_REGISTERS       = 80
612WOW64_MAXIMUM_SUPPORTED_EXTENSION   = 512
613
614class WOW64_FLOATING_SAVE_AREA (context_i386.FLOATING_SAVE_AREA):
615    pass
616
617class WOW64_CONTEXT (context_i386.CONTEXT):
618    pass
619
620class WOW64_LDT_ENTRY (context_i386.LDT_ENTRY):
621    pass
622
623PWOW64_FLOATING_SAVE_AREA   = POINTER(WOW64_FLOATING_SAVE_AREA)
624PWOW64_CONTEXT              = POINTER(WOW64_CONTEXT)
625PWOW64_LDT_ENTRY            = POINTER(WOW64_LDT_ENTRY)
626
627###############################################################################
628
629# BOOL WINAPI GetThreadSelectorEntry(
630#   __in   HANDLE hThread,
631#   __in   DWORD dwSelector,
632#   __out  LPLDT_ENTRY lpSelectorEntry
633# );
634def GetThreadSelectorEntry(hThread, dwSelector):
635    _GetThreadSelectorEntry = windll.kernel32.GetThreadSelectorEntry
636    _GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, LPLDT_ENTRY]
637    _GetThreadSelectorEntry.restype  = bool
638    _GetThreadSelectorEntry.errcheck = RaiseIfZero
639
640    ldt = LDT_ENTRY()
641    _GetThreadSelectorEntry(hThread, dwSelector, byref(ldt))
642    return ldt
643
644# BOOL WINAPI GetThreadContext(
645#   __in     HANDLE hThread,
646#   __inout  LPCONTEXT lpContext
647# );
648def GetThreadContext(hThread, ContextFlags = None, raw = False):
649    _GetThreadContext = windll.kernel32.GetThreadContext
650    _GetThreadContext.argtypes = [HANDLE, LPCONTEXT]
651    _GetThreadContext.restype  = bool
652    _GetThreadContext.errcheck = RaiseIfZero
653
654    if ContextFlags is None:
655        ContextFlags = CONTEXT_ALL | CONTEXT_AMD64
656    Context = CONTEXT()
657    Context.ContextFlags = ContextFlags
658    _GetThreadContext(hThread, byref(Context))
659    if raw:
660        return Context
661    return Context.to_dict()
662
663# BOOL WINAPI SetThreadContext(
664#   __in  HANDLE hThread,
665#   __in  const CONTEXT* lpContext
666# );
667def SetThreadContext(hThread, lpContext):
668    _SetThreadContext = windll.kernel32.SetThreadContext
669    _SetThreadContext.argtypes = [HANDLE, LPCONTEXT]
670    _SetThreadContext.restype  = bool
671    _SetThreadContext.errcheck = RaiseIfZero
672
673    if isinstance(lpContext, dict):
674        lpContext = CONTEXT.from_dict(lpContext)
675    _SetThreadContext(hThread, byref(lpContext))
676
677# BOOL Wow64GetThreadSelectorEntry(
678#   __in   HANDLE hThread,
679#   __in   DWORD dwSelector,
680#   __out  PWOW64_LDT_ENTRY lpSelectorEntry
681# );
682def Wow64GetThreadSelectorEntry(hThread, dwSelector):
683    _Wow64GetThreadSelectorEntry = windll.kernel32.Wow64GetThreadSelectorEntry
684    _Wow64GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, PWOW64_LDT_ENTRY]
685    _Wow64GetThreadSelectorEntry.restype  = bool
686    _Wow64GetThreadSelectorEntry.errcheck = RaiseIfZero
687
688    lpSelectorEntry = WOW64_LDT_ENTRY()
689    _Wow64GetThreadSelectorEntry(hThread, dwSelector, byref(lpSelectorEntry))
690    return lpSelectorEntry
691
692# DWORD WINAPI Wow64ResumeThread(
693#   __in  HANDLE hThread
694# );
695def Wow64ResumeThread(hThread):
696    _Wow64ResumeThread = windll.kernel32.Wow64ResumeThread
697    _Wow64ResumeThread.argtypes = [HANDLE]
698    _Wow64ResumeThread.restype  = DWORD
699
700    previousCount = _Wow64ResumeThread(hThread)
701    if previousCount == DWORD(-1).value:
702        raise ctypes.WinError()
703    return previousCount
704
705# DWORD WINAPI Wow64SuspendThread(
706#   __in  HANDLE hThread
707# );
708def Wow64SuspendThread(hThread):
709    _Wow64SuspendThread = windll.kernel32.Wow64SuspendThread
710    _Wow64SuspendThread.argtypes = [HANDLE]
711    _Wow64SuspendThread.restype  = DWORD
712
713    previousCount = _Wow64SuspendThread(hThread)
714    if previousCount == DWORD(-1).value:
715        raise ctypes.WinError()
716    return previousCount
717
718# XXX TODO Use this http://www.nynaeve.net/Code/GetThreadWow64Context.cpp
719# Also see http://www.woodmann.com/forum/archive/index.php/t-11162.html
720
721# BOOL WINAPI Wow64GetThreadContext(
722#   __in     HANDLE hThread,
723#   __inout  PWOW64_CONTEXT lpContext
724# );
725def Wow64GetThreadContext(hThread, ContextFlags = None):
726    _Wow64GetThreadContext = windll.kernel32.Wow64GetThreadContext
727    _Wow64GetThreadContext.argtypes = [HANDLE, PWOW64_CONTEXT]
728    _Wow64GetThreadContext.restype  = bool
729    _Wow64GetThreadContext.errcheck = RaiseIfZero
730
731    # XXX doesn't exist in XP 64 bits
732
733    Context = WOW64_CONTEXT()
734    if ContextFlags is None:
735        Context.ContextFlags = WOW64_CONTEXT_ALL | WOW64_CONTEXT_i386
736    else:
737        Context.ContextFlags = ContextFlags
738    _Wow64GetThreadContext(hThread, byref(Context))
739    return Context.to_dict()
740
741# BOOL WINAPI Wow64SetThreadContext(
742#   __in  HANDLE hThread,
743#   __in  const WOW64_CONTEXT *lpContext
744# );
745def Wow64SetThreadContext(hThread, lpContext):
746    _Wow64SetThreadContext = windll.kernel32.Wow64SetThreadContext
747    _Wow64SetThreadContext.argtypes = [HANDLE, PWOW64_CONTEXT]
748    _Wow64SetThreadContext.restype  = bool
749    _Wow64SetThreadContext.errcheck = RaiseIfZero
750
751    # XXX doesn't exist in XP 64 bits
752
753    if isinstance(lpContext, dict):
754        lpContext = WOW64_CONTEXT.from_dict(lpContext)
755    _Wow64SetThreadContext(hThread, byref(lpContext))
756
757#==============================================================================
758# This calculates the list of exported symbols.
759_all = set(vars().keys()).difference(_all)
760__all__ = [_x for _x in _all if not _x.startswith('_')]
761__all__.sort()
762#==============================================================================
763