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 gdi32.dll in ctypes.
33"""
34
35__revision__ = "$Id$"
36
37from winappdbg.win32.defines import *
38from winappdbg.win32.kernel32 import GetLastError, SetLastError
39
40#==============================================================================
41# This is used later on to calculate the list of exported symbols.
42_all = None
43_all = set(vars().keys())
44#==============================================================================
45
46#--- Helpers ------------------------------------------------------------------
47
48#--- Types --------------------------------------------------------------------
49
50#--- Constants ----------------------------------------------------------------
51
52# GDI object types
53OBJ_PEN             = 1
54OBJ_BRUSH           = 2
55OBJ_DC              = 3
56OBJ_METADC          = 4
57OBJ_PAL             = 5
58OBJ_FONT            = 6
59OBJ_BITMAP          = 7
60OBJ_REGION          = 8
61OBJ_METAFILE        = 9
62OBJ_MEMDC           = 10
63OBJ_EXTPEN          = 11
64OBJ_ENHMETADC       = 12
65OBJ_ENHMETAFILE     = 13
66OBJ_COLORSPACE      = 14
67GDI_OBJ_LAST        = OBJ_COLORSPACE
68
69# Ternary raster operations
70SRCCOPY         = 0x00CC0020 # dest = source
71SRCPAINT        = 0x00EE0086 # dest = source OR dest
72SRCAND          = 0x008800C6 # dest = source AND dest
73SRCINVERT       = 0x00660046 # dest = source XOR dest
74SRCERASE        = 0x00440328 # dest = source AND (NOT dest)
75NOTSRCCOPY      = 0x00330008 # dest = (NOT source)
76NOTSRCERASE     = 0x001100A6 # dest = (NOT src) AND (NOT dest)
77MERGECOPY       = 0x00C000CA # dest = (source AND pattern)
78MERGEPAINT      = 0x00BB0226 # dest = (NOT source) OR dest
79PATCOPY         = 0x00F00021 # dest = pattern
80PATPAINT        = 0x00FB0A09 # dest = DPSnoo
81PATINVERT       = 0x005A0049 # dest = pattern XOR dest
82DSTINVERT       = 0x00550009 # dest = (NOT dest)
83BLACKNESS       = 0x00000042 # dest = BLACK
84WHITENESS       = 0x00FF0062 # dest = WHITE
85NOMIRRORBITMAP  = 0x80000000 # Do not Mirror the bitmap in this call
86CAPTUREBLT      = 0x40000000 # Include layered windows
87
88# Region flags
89ERROR               = 0
90NULLREGION          = 1
91SIMPLEREGION        = 2
92COMPLEXREGION       = 3
93RGN_ERROR           = ERROR
94
95# CombineRgn() styles
96RGN_AND             = 1
97RGN_OR              = 2
98RGN_XOR             = 3
99RGN_DIFF            = 4
100RGN_COPY            = 5
101RGN_MIN             = RGN_AND
102RGN_MAX             = RGN_COPY
103
104# StretchBlt() modes
105BLACKONWHITE        = 1
106WHITEONBLACK        = 2
107COLORONCOLOR        = 3
108HALFTONE            = 4
109MAXSTRETCHBLTMODE   = 4
110STRETCH_ANDSCANS    = BLACKONWHITE
111STRETCH_ORSCANS     = WHITEONBLACK
112STRETCH_DELETESCANS = COLORONCOLOR
113STRETCH_HALFTONE    = HALFTONE
114
115# PolyFill() modes
116ALTERNATE       = 1
117WINDING         = 2
118POLYFILL_LAST   = 2
119
120# Layout orientation options
121LAYOUT_RTL                         = 0x00000001 # Right to left
122LAYOUT_BTT                         = 0x00000002 # Bottom to top
123LAYOUT_VBH                         = 0x00000004 # Vertical before horizontal
124LAYOUT_ORIENTATIONMASK             = LAYOUT_RTL + LAYOUT_BTT + LAYOUT_VBH
125LAYOUT_BITMAPORIENTATIONPRESERVED  = 0x00000008
126
127# Stock objects
128WHITE_BRUSH         = 0
129LTGRAY_BRUSH        = 1
130GRAY_BRUSH          = 2
131DKGRAY_BRUSH        = 3
132BLACK_BRUSH         = 4
133NULL_BRUSH          = 5
134HOLLOW_BRUSH        = NULL_BRUSH
135WHITE_PEN           = 6
136BLACK_PEN           = 7
137NULL_PEN            = 8
138OEM_FIXED_FONT      = 10
139ANSI_FIXED_FONT     = 11
140ANSI_VAR_FONT       = 12
141SYSTEM_FONT         = 13
142DEVICE_DEFAULT_FONT = 14
143DEFAULT_PALETTE     = 15
144SYSTEM_FIXED_FONT   = 16
145
146# Metafile functions
147META_SETBKCOLOR              = 0x0201
148META_SETBKMODE               = 0x0102
149META_SETMAPMODE              = 0x0103
150META_SETROP2                 = 0x0104
151META_SETRELABS               = 0x0105
152META_SETPOLYFILLMODE         = 0x0106
153META_SETSTRETCHBLTMODE       = 0x0107
154META_SETTEXTCHAREXTRA        = 0x0108
155META_SETTEXTCOLOR            = 0x0209
156META_SETTEXTJUSTIFICATION    = 0x020A
157META_SETWINDOWORG            = 0x020B
158META_SETWINDOWEXT            = 0x020C
159META_SETVIEWPORTORG          = 0x020D
160META_SETVIEWPORTEXT          = 0x020E
161META_OFFSETWINDOWORG         = 0x020F
162META_SCALEWINDOWEXT          = 0x0410
163META_OFFSETVIEWPORTORG       = 0x0211
164META_SCALEVIEWPORTEXT        = 0x0412
165META_LINETO                  = 0x0213
166META_MOVETO                  = 0x0214
167META_EXCLUDECLIPRECT         = 0x0415
168META_INTERSECTCLIPRECT       = 0x0416
169META_ARC                     = 0x0817
170META_ELLIPSE                 = 0x0418
171META_FLOODFILL               = 0x0419
172META_PIE                     = 0x081A
173META_RECTANGLE               = 0x041B
174META_ROUNDRECT               = 0x061C
175META_PATBLT                  = 0x061D
176META_SAVEDC                  = 0x001E
177META_SETPIXEL                = 0x041F
178META_OFFSETCLIPRGN           = 0x0220
179META_TEXTOUT                 = 0x0521
180META_BITBLT                  = 0x0922
181META_STRETCHBLT              = 0x0B23
182META_POLYGON                 = 0x0324
183META_POLYLINE                = 0x0325
184META_ESCAPE                  = 0x0626
185META_RESTOREDC               = 0x0127
186META_FILLREGION              = 0x0228
187META_FRAMEREGION             = 0x0429
188META_INVERTREGION            = 0x012A
189META_PAINTREGION             = 0x012B
190META_SELECTCLIPREGION        = 0x012C
191META_SELECTOBJECT            = 0x012D
192META_SETTEXTALIGN            = 0x012E
193META_CHORD                   = 0x0830
194META_SETMAPPERFLAGS          = 0x0231
195META_EXTTEXTOUT              = 0x0a32
196META_SETDIBTODEV             = 0x0d33
197META_SELECTPALETTE           = 0x0234
198META_REALIZEPALETTE          = 0x0035
199META_ANIMATEPALETTE          = 0x0436
200META_SETPALENTRIES           = 0x0037
201META_POLYPOLYGON             = 0x0538
202META_RESIZEPALETTE           = 0x0139
203META_DIBBITBLT               = 0x0940
204META_DIBSTRETCHBLT           = 0x0b41
205META_DIBCREATEPATTERNBRUSH   = 0x0142
206META_STRETCHDIB              = 0x0f43
207META_EXTFLOODFILL            = 0x0548
208META_SETLAYOUT               = 0x0149
209META_DELETEOBJECT            = 0x01f0
210META_CREATEPALETTE           = 0x00f7
211META_CREATEPATTERNBRUSH      = 0x01F9
212META_CREATEPENINDIRECT       = 0x02FA
213META_CREATEFONTINDIRECT      = 0x02FB
214META_CREATEBRUSHINDIRECT     = 0x02FC
215META_CREATEREGION            = 0x06FF
216
217# Metafile escape codes
218NEWFRAME                     = 1
219ABORTDOC                     = 2
220NEXTBAND                     = 3
221SETCOLORTABLE                = 4
222GETCOLORTABLE                = 5
223FLUSHOUTPUT                  = 6
224DRAFTMODE                    = 7
225QUERYESCSUPPORT              = 8
226SETABORTPROC                 = 9
227STARTDOC                     = 10
228ENDDOC                       = 11
229GETPHYSPAGESIZE              = 12
230GETPRINTINGOFFSET            = 13
231GETSCALINGFACTOR             = 14
232MFCOMMENT                    = 15
233GETPENWIDTH                  = 16
234SETCOPYCOUNT                 = 17
235SELECTPAPERSOURCE            = 18
236DEVICEDATA                   = 19
237PASSTHROUGH                  = 19
238GETTECHNOLGY                 = 20
239GETTECHNOLOGY                = 20
240SETLINECAP                   = 21
241SETLINEJOIN                  = 22
242SETMITERLIMIT                = 23
243BANDINFO                     = 24
244DRAWPATTERNRECT              = 25
245GETVECTORPENSIZE             = 26
246GETVECTORBRUSHSIZE           = 27
247ENABLEDUPLEX                 = 28
248GETSETPAPERBINS              = 29
249GETSETPRINTORIENT            = 30
250ENUMPAPERBINS                = 31
251SETDIBSCALING                = 32
252EPSPRINTING                  = 33
253ENUMPAPERMETRICS             = 34
254GETSETPAPERMETRICS           = 35
255POSTSCRIPT_DATA              = 37
256POSTSCRIPT_IGNORE            = 38
257MOUSETRAILS                  = 39
258GETDEVICEUNITS               = 42
259GETEXTENDEDTEXTMETRICS       = 256
260GETEXTENTTABLE               = 257
261GETPAIRKERNTABLE             = 258
262GETTRACKKERNTABLE            = 259
263EXTTEXTOUT                   = 512
264GETFACENAME                  = 513
265DOWNLOADFACE                 = 514
266ENABLERELATIVEWIDTHS         = 768
267ENABLEPAIRKERNING            = 769
268SETKERNTRACK                 = 770
269SETALLJUSTVALUES             = 771
270SETCHARSET                   = 772
271STRETCHBLT                   = 2048
272METAFILE_DRIVER              = 2049
273GETSETSCREENPARAMS           = 3072
274QUERYDIBSUPPORT              = 3073
275BEGIN_PATH                   = 4096
276CLIP_TO_PATH                 = 4097
277END_PATH                     = 4098
278EXT_DEVICE_CAPS              = 4099
279RESTORE_CTM                  = 4100
280SAVE_CTM                     = 4101
281SET_ARC_DIRECTION            = 4102
282SET_BACKGROUND_COLOR         = 4103
283SET_POLY_MODE                = 4104
284SET_SCREEN_ANGLE             = 4105
285SET_SPREAD                   = 4106
286TRANSFORM_CTM                = 4107
287SET_CLIP_BOX                 = 4108
288SET_BOUNDS                   = 4109
289SET_MIRROR_MODE              = 4110
290OPENCHANNEL                  = 4110
291DOWNLOADHEADER               = 4111
292CLOSECHANNEL                 = 4112
293POSTSCRIPT_PASSTHROUGH       = 4115
294ENCAPSULATED_POSTSCRIPT      = 4116
295POSTSCRIPT_IDENTIFY          = 4117
296POSTSCRIPT_INJECTION         = 4118
297CHECKJPEGFORMAT              = 4119
298CHECKPNGFORMAT               = 4120
299GET_PS_FEATURESETTING        = 4121
300GDIPLUS_TS_QUERYVER          = 4122
301GDIPLUS_TS_RECORD            = 4123
302SPCLPASSTHROUGH2             = 4568
303
304#--- Structures ---------------------------------------------------------------
305
306# typedef struct _RECT {
307#   LONG left;
308#   LONG top;
309#   LONG right;
310#   LONG bottom;
311# }RECT, *PRECT;
312class RECT(Structure):
313    _fields_ = [
314        ('left',    LONG),
315        ('top',     LONG),
316        ('right',   LONG),
317        ('bottom',  LONG),
318    ]
319PRECT  = POINTER(RECT)
320LPRECT = PRECT
321
322# typedef struct tagPOINT {
323#   LONG x;
324#   LONG y;
325# } POINT;
326class POINT(Structure):
327    _fields_ = [
328        ('x',   LONG),
329        ('y',   LONG),
330    ]
331PPOINT  = POINTER(POINT)
332LPPOINT = PPOINT
333
334# typedef struct tagBITMAP {
335#   LONG   bmType;
336#   LONG   bmWidth;
337#   LONG   bmHeight;
338#   LONG   bmWidthBytes;
339#   WORD   bmPlanes;
340#   WORD   bmBitsPixel;
341#   LPVOID bmBits;
342# } BITMAP, *PBITMAP;
343class BITMAP(Structure):
344    _fields_ = [
345        ("bmType",          LONG),
346        ("bmWidth",         LONG),
347        ("bmHeight",        LONG),
348        ("bmWidthBytes",    LONG),
349        ("bmPlanes",        WORD),
350        ("bmBitsPixel",     WORD),
351        ("bmBits",          LPVOID),
352    ]
353PBITMAP  = POINTER(BITMAP)
354LPBITMAP = PBITMAP
355
356#--- High level classes -------------------------------------------------------
357
358#--- gdi32.dll ----------------------------------------------------------------
359
360# HDC GetDC(
361#   __in  HWND hWnd
362# );
363def GetDC(hWnd):
364    _GetDC = windll.gdi32.GetDC
365    _GetDC.argtypes = [HWND]
366    _GetDC.restype  = HDC
367    _GetDC.errcheck = RaiseIfZero
368    return _GetDC(hWnd)
369
370# HDC GetWindowDC(
371#   __in  HWND hWnd
372# );
373def GetWindowDC(hWnd):
374    _GetWindowDC = windll.gdi32.GetWindowDC
375    _GetWindowDC.argtypes = [HWND]
376    _GetWindowDC.restype  = HDC
377    _GetWindowDC.errcheck = RaiseIfZero
378    return _GetWindowDC(hWnd)
379
380# int ReleaseDC(
381#   __in  HWND hWnd,
382#   __in  HDC hDC
383# );
384def ReleaseDC(hWnd, hDC):
385    _ReleaseDC = windll.gdi32.ReleaseDC
386    _ReleaseDC.argtypes = [HWND, HDC]
387    _ReleaseDC.restype  = ctypes.c_int
388    _ReleaseDC.errcheck = RaiseIfZero
389    _ReleaseDC(hWnd, hDC)
390
391# HGDIOBJ SelectObject(
392#   __in  HDC hdc,
393#   __in  HGDIOBJ hgdiobj
394# );
395def SelectObject(hdc, hgdiobj):
396    _SelectObject = windll.gdi32.SelectObject
397    _SelectObject.argtypes = [HDC, HGDIOBJ]
398    _SelectObject.restype  = HGDIOBJ
399    _SelectObject.errcheck = RaiseIfZero
400    return _SelectObject(hdc, hgdiobj)
401
402# HGDIOBJ GetStockObject(
403#   __in  int fnObject
404# );
405def GetStockObject(fnObject):
406    _GetStockObject = windll.gdi32.GetStockObject
407    _GetStockObject.argtypes = [ctypes.c_int]
408    _GetStockObject.restype  = HGDIOBJ
409    _GetStockObject.errcheck = RaiseIfZero
410    return _GetStockObject(fnObject)
411
412# DWORD GetObjectType(
413#   __in  HGDIOBJ h
414# );
415def GetObjectType(h):
416    _GetObjectType = windll.gdi32.GetObjectType
417    _GetObjectType.argtypes = [HGDIOBJ]
418    _GetObjectType.restype  = DWORD
419    _GetObjectType.errcheck = RaiseIfZero
420    return _GetObjectType(h)
421
422# int GetObject(
423#   __in   HGDIOBJ hgdiobj,
424#   __in   int cbBuffer,
425#   __out  LPVOID lpvObject
426# );
427def GetObject(hgdiobj, cbBuffer = None, lpvObject = None):
428    _GetObject = windll.gdi32.GetObject
429    _GetObject.argtypes = [HGDIOBJ, ctypes.c_int, LPVOID]
430    _GetObject.restype  = ctypes.c_int
431    _GetObject.errcheck = RaiseIfZero
432
433    # Both cbBuffer and lpvObject can be omitted, the correct
434    # size and structure to return are automatically deduced.
435    # If lpvObject is given it must be a ctypes object, not a pointer.
436    # Always returns a ctypes object.
437
438    if cbBuffer is not None:
439        if lpvObject is None:
440            lpvObject = ctypes.create_string_buffer("", cbBuffer)
441    elif lpvObject is not None:
442        cbBuffer = sizeof(lpvObject)
443    else: # most likely case, both are None
444        t = GetObjectType(hgdiobj)
445        if   t == OBJ_PEN:
446            cbBuffer  = sizeof(LOGPEN)
447            lpvObject = LOGPEN()
448        elif t == OBJ_BRUSH:
449            cbBuffer  = sizeof(LOGBRUSH)
450            lpvObject = LOGBRUSH()
451        elif t == OBJ_PAL:
452            cbBuffer  = _GetObject(hgdiobj, 0, None)
453            lpvObject = (WORD * (cbBuffer // sizeof(WORD)))()
454        elif t == OBJ_FONT:
455            cbBuffer  = sizeof(LOGFONT)
456            lpvObject = LOGFONT()
457        elif t == OBJ_BITMAP:  # try the two possible types of bitmap
458            cbBuffer  = sizeof(DIBSECTION)
459            lpvObject = DIBSECTION()
460            try:
461                _GetObject(hgdiobj, cbBuffer, byref(lpvObject))
462                return lpvObject
463            except WindowsError:
464                cbBuffer  = sizeof(BITMAP)
465                lpvObject = BITMAP()
466        elif t == OBJ_EXTPEN:
467            cbBuffer  = sizeof(LOGEXTPEN)
468            lpvObject = LOGEXTPEN()
469        else:
470            cbBuffer  = _GetObject(hgdiobj, 0, None)
471            lpvObject = ctypes.create_string_buffer("", cbBuffer)
472    _GetObject(hgdiobj, cbBuffer, byref(lpvObject))
473    return lpvObject
474
475# LONG GetBitmapBits(
476#   __in   HBITMAP hbmp,
477#   __in   LONG cbBuffer,
478#   __out  LPVOID lpvBits
479# );
480def GetBitmapBits(hbmp):
481    _GetBitmapBits = windll.gdi32.GetBitmapBits
482    _GetBitmapBits.argtypes = [HBITMAP, LONG, LPVOID]
483    _GetBitmapBits.restype  = LONG
484    _GetBitmapBits.errcheck = RaiseIfZero
485
486    bitmap   = GetObject(hbmp, lpvObject = BITMAP())
487    cbBuffer = bitmap.bmWidthBytes * bitmap.bmHeight
488    lpvBits  = ctypes.create_string_buffer("", cbBuffer)
489    _GetBitmapBits(hbmp, cbBuffer, byref(lpvBits))
490    return lpvBits.raw
491
492# HBITMAP CreateBitmapIndirect(
493#   __in  const BITMAP *lpbm
494# );
495def CreateBitmapIndirect(lpbm):
496    _CreateBitmapIndirect = windll.gdi32.CreateBitmapIndirect
497    _CreateBitmapIndirect.argtypes = [PBITMAP]
498    _CreateBitmapIndirect.restype  = HBITMAP
499    _CreateBitmapIndirect.errcheck = RaiseIfZero
500    return _CreateBitmapIndirect(lpbm)
501
502#==============================================================================
503# This calculates the list of exported symbols.
504_all = set(vars().keys()).difference(_all)
505__all__ = [_x for _x in _all if not _x.startswith('_')]
506__all__.sort()
507#==============================================================================
508