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 shell32.dll in ctypes. 33""" 34 35# TODO 36# * Add a class wrapper to SHELLEXECUTEINFO 37# * More logic into ShellExecuteEx 38 39__revision__ = "$Id$" 40 41from winappdbg.win32.defines import * 42from winappdbg.win32.kernel32 import LocalFree 43 44#============================================================================== 45# This is used later on to calculate the list of exported symbols. 46_all = None 47_all = set(vars().keys()) 48#============================================================================== 49 50#--- Constants ---------------------------------------------------------------- 51 52SEE_MASK_DEFAULT = 0x00000000 53SEE_MASK_CLASSNAME = 0x00000001 54SEE_MASK_CLASSKEY = 0x00000003 55SEE_MASK_IDLIST = 0x00000004 56SEE_MASK_INVOKEIDLIST = 0x0000000C 57SEE_MASK_ICON = 0x00000010 58SEE_MASK_HOTKEY = 0x00000020 59SEE_MASK_NOCLOSEPROCESS = 0x00000040 60SEE_MASK_CONNECTNETDRV = 0x00000080 61SEE_MASK_NOASYNC = 0x00000100 62SEE_MASK_DOENVSUBST = 0x00000200 63SEE_MASK_FLAG_NO_UI = 0x00000400 64SEE_MASK_UNICODE = 0x00004000 65SEE_MASK_NO_CONSOLE = 0x00008000 66SEE_MASK_ASYNCOK = 0x00100000 67SEE_MASK_HMONITOR = 0x00200000 68SEE_MASK_NOZONECHECKS = 0x00800000 69SEE_MASK_WAITFORINPUTIDLE = 0x02000000 70SEE_MASK_FLAG_LOG_USAGE = 0x04000000 71 72SE_ERR_FNF = 2 73SE_ERR_PNF = 3 74SE_ERR_ACCESSDENIED = 5 75SE_ERR_OOM = 8 76SE_ERR_DLLNOTFOUND = 32 77SE_ERR_SHARE = 26 78SE_ERR_ASSOCINCOMPLETE = 27 79SE_ERR_DDETIMEOUT = 28 80SE_ERR_DDEFAIL = 29 81SE_ERR_DDEBUSY = 30 82SE_ERR_NOASSOC = 31 83 84SHGFP_TYPE_CURRENT = 0 85SHGFP_TYPE_DEFAULT = 1 86 87CSIDL_DESKTOP = 0x0000 88CSIDL_INTERNET = 0x0001 89CSIDL_PROGRAMS = 0x0002 90CSIDL_CONTROLS = 0x0003 91CSIDL_PRINTERS = 0x0004 92CSIDL_PERSONAL = 0x0005 93CSIDL_FAVORITES = 0x0006 94CSIDL_STARTUP = 0x0007 95CSIDL_RECENT = 0x0008 96CSIDL_SENDTO = 0x0009 97CSIDL_BITBUCKET = 0x000a 98CSIDL_STARTMENU = 0x000b 99CSIDL_MYDOCUMENTS = CSIDL_PERSONAL 100CSIDL_MYMUSIC = 0x000d 101CSIDL_MYVIDEO = 0x000e 102CSIDL_DESKTOPDIRECTORY = 0x0010 103CSIDL_DRIVES = 0x0011 104CSIDL_NETWORK = 0x0012 105CSIDL_NETHOOD = 0x0013 106CSIDL_FONTS = 0x0014 107CSIDL_TEMPLATES = 0x0015 108CSIDL_COMMON_STARTMENU = 0x0016 109CSIDL_COMMON_PROGRAMS = 0x0017 110CSIDL_COMMON_STARTUP = 0x0018 111CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019 112CSIDL_APPDATA = 0x001a 113CSIDL_PRINTHOOD = 0x001b 114CSIDL_LOCAL_APPDATA = 0x001c 115CSIDL_ALTSTARTUP = 0x001d 116CSIDL_COMMON_ALTSTARTUP = 0x001e 117CSIDL_COMMON_FAVORITES = 0x001f 118CSIDL_INTERNET_CACHE = 0x0020 119CSIDL_COOKIES = 0x0021 120CSIDL_HISTORY = 0x0022 121CSIDL_COMMON_APPDATA = 0x0023 122CSIDL_WINDOWS = 0x0024 123CSIDL_SYSTEM = 0x0025 124CSIDL_PROGRAM_FILES = 0x0026 125CSIDL_MYPICTURES = 0x0027 126CSIDL_PROFILE = 0x0028 127CSIDL_SYSTEMX86 = 0x0029 128CSIDL_PROGRAM_FILESX86 = 0x002a 129CSIDL_PROGRAM_FILES_COMMON = 0x002b 130CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c 131CSIDL_COMMON_TEMPLATES = 0x002d 132CSIDL_COMMON_DOCUMENTS = 0x002e 133CSIDL_COMMON_ADMINTOOLS = 0x002f 134CSIDL_ADMINTOOLS = 0x0030 135CSIDL_CONNECTIONS = 0x0031 136CSIDL_COMMON_MUSIC = 0x0035 137CSIDL_COMMON_PICTURES = 0x0036 138CSIDL_COMMON_VIDEO = 0x0037 139CSIDL_RESOURCES = 0x0038 140CSIDL_RESOURCES_LOCALIZED = 0x0039 141CSIDL_COMMON_OEM_LINKS = 0x003a 142CSIDL_CDBURN_AREA = 0x003b 143CSIDL_COMPUTERSNEARME = 0x003d 144CSIDL_PROFILES = 0x003e 145 146CSIDL_FOLDER_MASK = 0x00ff 147 148CSIDL_FLAG_PER_USER_INIT = 0x0800 149CSIDL_FLAG_NO_ALIAS = 0x1000 150CSIDL_FLAG_DONT_VERIFY = 0x4000 151CSIDL_FLAG_CREATE = 0x8000 152 153CSIDL_FLAG_MASK = 0xff00 154 155#--- Structures --------------------------------------------------------------- 156 157# typedef struct _SHELLEXECUTEINFO { 158# DWORD cbSize; 159# ULONG fMask; 160# HWND hwnd; 161# LPCTSTR lpVerb; 162# LPCTSTR lpFile; 163# LPCTSTR lpParameters; 164# LPCTSTR lpDirectory; 165# int nShow; 166# HINSTANCE hInstApp; 167# LPVOID lpIDList; 168# LPCTSTR lpClass; 169# HKEY hkeyClass; 170# DWORD dwHotKey; 171# union { 172# HANDLE hIcon; 173# HANDLE hMonitor; 174# } DUMMYUNIONNAME; 175# HANDLE hProcess; 176# } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO; 177 178class SHELLEXECUTEINFO(Structure): 179 _fields_ = [ 180 ("cbSize", DWORD), 181 ("fMask", ULONG), 182 ("hwnd", HWND), 183 ("lpVerb", LPSTR), 184 ("lpFile", LPSTR), 185 ("lpParameters", LPSTR), 186 ("lpDirectory", LPSTR), 187 ("nShow", ctypes.c_int), 188 ("hInstApp", HINSTANCE), 189 ("lpIDList", LPVOID), 190 ("lpClass", LPSTR), 191 ("hkeyClass", HKEY), 192 ("dwHotKey", DWORD), 193 ("hIcon", HANDLE), 194 ("hProcess", HANDLE), 195 ] 196 197 def __get_hMonitor(self): 198 return self.hIcon 199 def __set_hMonitor(self, hMonitor): 200 self.hIcon = hMonitor 201 hMonitor = property(__get_hMonitor, __set_hMonitor) 202 203LPSHELLEXECUTEINFO = POINTER(SHELLEXECUTEINFO) 204 205#--- shell32.dll -------------------------------------------------------------- 206 207# LPWSTR *CommandLineToArgvW( 208# LPCWSTR lpCmdLine, 209# int *pNumArgs 210# ); 211def CommandLineToArgvW(lpCmdLine): 212 _CommandLineToArgvW = windll.shell32.CommandLineToArgvW 213 _CommandLineToArgvW.argtypes = [LPVOID, POINTER(ctypes.c_int)] 214 _CommandLineToArgvW.restype = LPVOID 215 216 if not lpCmdLine: 217 lpCmdLine = None 218 argc = ctypes.c_int(0) 219 vptr = ctypes.windll.shell32.CommandLineToArgvW(lpCmdLine, byref(argc)) 220 if vptr == NULL: 221 raise ctypes.WinError() 222 argv = vptr 223 try: 224 argc = argc.value 225 if argc <= 0: 226 raise ctypes.WinError() 227 argv = ctypes.cast(argv, ctypes.POINTER(LPWSTR * argc) ) 228 argv = [ argv.contents[i] for i in compat.xrange(0, argc) ] 229 finally: 230 if vptr is not None: 231 LocalFree(vptr) 232 return argv 233 234def CommandLineToArgvA(lpCmdLine): 235 t_ansi = GuessStringType.t_ansi 236 t_unicode = GuessStringType.t_unicode 237 if isinstance(lpCmdLine, t_ansi): 238 cmdline = t_unicode(lpCmdLine) 239 else: 240 cmdline = lpCmdLine 241 return [t_ansi(x) for x in CommandLineToArgvW(cmdline)] 242 243CommandLineToArgv = GuessStringType(CommandLineToArgvA, CommandLineToArgvW) 244 245# HINSTANCE ShellExecute( 246# HWND hwnd, 247# LPCTSTR lpOperation, 248# LPCTSTR lpFile, 249# LPCTSTR lpParameters, 250# LPCTSTR lpDirectory, 251# INT nShowCmd 252# ); 253def ShellExecuteA(hwnd = None, lpOperation = None, lpFile = None, lpParameters = None, lpDirectory = None, nShowCmd = None): 254 _ShellExecuteA = windll.shell32.ShellExecuteA 255 _ShellExecuteA.argtypes = [HWND, LPSTR, LPSTR, LPSTR, LPSTR, INT] 256 _ShellExecuteA.restype = HINSTANCE 257 258 if not nShowCmd: 259 nShowCmd = 0 260 success = _ShellExecuteA(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd) 261 success = ctypes.cast(success, c_int) 262 success = success.value 263 if not success > 32: # weird! isn't it? 264 raise ctypes.WinError(success) 265 266def ShellExecuteW(hwnd = None, lpOperation = None, lpFile = None, lpParameters = None, lpDirectory = None, nShowCmd = None): 267 _ShellExecuteW = windll.shell32.ShellExecuteW 268 _ShellExecuteW.argtypes = [HWND, LPWSTR, LPWSTR, LPWSTR, LPWSTR, INT] 269 _ShellExecuteW.restype = HINSTANCE 270 271 if not nShowCmd: 272 nShowCmd = 0 273 success = _ShellExecuteW(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd) 274 success = ctypes.cast(success, c_int) 275 success = success.value 276 if not success > 32: # weird! isn't it? 277 raise ctypes.WinError(success) 278 279ShellExecute = GuessStringType(ShellExecuteA, ShellExecuteW) 280 281# BOOL ShellExecuteEx( 282# __inout LPSHELLEXECUTEINFO lpExecInfo 283# ); 284def ShellExecuteEx(lpExecInfo): 285 if isinstance(lpExecInfo, SHELLEXECUTEINFOA): 286 ShellExecuteExA(lpExecInfo) 287 elif isinstance(lpExecInfo, SHELLEXECUTEINFOW): 288 ShellExecuteExW(lpExecInfo) 289 else: 290 raise TypeError("Expected SHELLEXECUTEINFOA or SHELLEXECUTEINFOW, got %s instead" % type(lpExecInfo)) 291 292def ShellExecuteExA(lpExecInfo): 293 _ShellExecuteExA = windll.shell32.ShellExecuteExA 294 _ShellExecuteExA.argtypes = [LPSHELLEXECUTEINFOA] 295 _ShellExecuteExA.restype = BOOL 296 _ShellExecuteExA.errcheck = RaiseIfZero 297 _ShellExecuteExA(byref(lpExecInfo)) 298 299def ShellExecuteExW(lpExecInfo): 300 _ShellExecuteExW = windll.shell32.ShellExecuteExW 301 _ShellExecuteExW.argtypes = [LPSHELLEXECUTEINFOW] 302 _ShellExecuteExW.restype = BOOL 303 _ShellExecuteExW.errcheck = RaiseIfZero 304 _ShellExecuteExW(byref(lpExecInfo)) 305 306# HINSTANCE FindExecutable( 307# __in LPCTSTR lpFile, 308# __in_opt LPCTSTR lpDirectory, 309# __out LPTSTR lpResult 310# ); 311def FindExecutableA(lpFile, lpDirectory = None): 312 _FindExecutableA = windll.shell32.FindExecutableA 313 _FindExecutableA.argtypes = [LPSTR, LPSTR, LPSTR] 314 _FindExecutableA.restype = HINSTANCE 315 316 lpResult = ctypes.create_string_buffer(MAX_PATH) 317 success = _FindExecutableA(lpFile, lpDirectory, lpResult) 318 success = ctypes.cast(success, ctypes.c_void_p) 319 success = success.value 320 if not success > 32: # weird! isn't it? 321 raise ctypes.WinError(success) 322 return lpResult.value 323 324def FindExecutableW(lpFile, lpDirectory = None): 325 _FindExecutableW = windll.shell32.FindExecutableW 326 _FindExecutableW.argtypes = [LPWSTR, LPWSTR, LPWSTR] 327 _FindExecutableW.restype = HINSTANCE 328 329 lpResult = ctypes.create_unicode_buffer(MAX_PATH) 330 success = _FindExecutableW(lpFile, lpDirectory, lpResult) 331 success = ctypes.cast(success, ctypes.c_void_p) 332 success = success.value 333 if not success > 32: # weird! isn't it? 334 raise ctypes.WinError(success) 335 return lpResult.value 336 337FindExecutable = GuessStringType(FindExecutableA, FindExecutableW) 338 339# HRESULT SHGetFolderPath( 340# __in HWND hwndOwner, 341# __in int nFolder, 342# __in HANDLE hToken, 343# __in DWORD dwFlags, 344# __out LPTSTR pszPath 345# ); 346def SHGetFolderPathA(nFolder, hToken = None, dwFlags = SHGFP_TYPE_CURRENT): 347 _SHGetFolderPathA = windll.shell32.SHGetFolderPathA # shfolder.dll in older win versions 348 _SHGetFolderPathA.argtypes = [HWND, ctypes.c_int, HANDLE, DWORD, LPSTR] 349 _SHGetFolderPathA.restype = HRESULT 350 _SHGetFolderPathA.errcheck = RaiseIfNotZero # S_OK == 0 351 352 pszPath = ctypes.create_string_buffer(MAX_PATH + 1) 353 _SHGetFolderPathA(None, nFolder, hToken, dwFlags, pszPath) 354 return pszPath.value 355 356def SHGetFolderPathW(nFolder, hToken = None, dwFlags = SHGFP_TYPE_CURRENT): 357 _SHGetFolderPathW = windll.shell32.SHGetFolderPathW # shfolder.dll in older win versions 358 _SHGetFolderPathW.argtypes = [HWND, ctypes.c_int, HANDLE, DWORD, LPWSTR] 359 _SHGetFolderPathW.restype = HRESULT 360 _SHGetFolderPathW.errcheck = RaiseIfNotZero # S_OK == 0 361 362 pszPath = ctypes.create_unicode_buffer(MAX_PATH + 1) 363 _SHGetFolderPathW(None, nFolder, hToken, dwFlags, pszPath) 364 return pszPath.value 365 366SHGetFolderPath = DefaultStringType(SHGetFolderPathA, SHGetFolderPathW) 367 368# BOOL IsUserAnAdmin(void); 369def IsUserAnAdmin(): 370 # Supposedly, IsUserAnAdmin() is deprecated in Vista. 371 # But I tried it on Windows 7 and it works just fine. 372 _IsUserAnAdmin = windll.shell32.IsUserAnAdmin 373 _IsUserAnAdmin.argtypes = [] 374 _IsUserAnAdmin.restype = bool 375 return _IsUserAnAdmin() 376 377#============================================================================== 378# This calculates the list of exported symbols. 379_all = set(vars().keys()).difference(_all) 380__all__ = [_x for _x in _all if not _x.startswith('_')] 381__all__.sort() 382#============================================================================== 383