def set(foldername, target): """Set the shellfolder "foldername" (one of the keys in FOLDER_REG_NAMES) to the directory "target".""" if foldername.lower() in FOLDER_REG_NAMES.keys(): # Camelcase the folder #foldername = " ".join([ i.capitalize() for i in foldername.split(" ") ]) #userpath = registry.get('HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment', 'APPDATA') #folderpath = "%s/drive_c/%s/%s" % (common.ENV['WINEPREFIX'], "/".join(userpath[3:].split("\\")[:-1]), foldername) folder_path = registry.get('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders', FOLDER_REG_NAMES[foldername.lower()]) # If the registy folder path is a symlink from inside the configuration, change the symlink if isinstance(folder_path, basestring) and ('\\windows\\' or '\\users\\' in folder_path): folder_path = util.wintounix(folder_path) try: os.remove(folder_path) except OSError: try: os.rmdir(folder_path) except OSError: print("Skipping %s, there are files in the directory" % os.path.basename(folder_path), file=sys.stderr) os.symlink(target, folder_path) # If not, it refers to a real directory, don't mess with it, set the registry info instead else: folder_path = target registry.set({'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders': {FOLDER_REG_NAMES[foldername.lower()]: folder_path}}) try: folders = CACHE['shellfolders'] except KeyError: folders = {} folders[foldername] = folder_path CACHE['shellfolders'] = folders
def __init__(self, command_arg, name=None, env=None, cwd=None, executable='wine', output_to_shell=False, use_log=True, cpu_limit=None): """ Run a program in a separate thread and monitor its state.""" if output_to_shell is True and use_log is True: raise ValueError("output_to_shell and use_log can't both be True") if env is None: env = common.ENV if name is None: #name = command_arg.split()[0].split('\\')[-1] if type(command_arg) in (str, unicode): programs.isolate_executable_from_command(command_arg) else: name = command_arg[0] try: name = util.get_program_name(util.wintounix(name)) except (IOError, TypeError): name = '' self.name = name print(executable) if executable is not None and len(executable): if executable == 'wine' and 'WINE' in env: executable = common.ENV['WINE'] if type(command_arg) in (__builtin__.list, tuple): command_arg = [executable] + command_arg else: command_arg = "%s '%s'" % (executable, command_arg) print(executable) if cpu_limit is not None and type(cpu_limit) is int and cpu_limit > 0: if common.which('taskset'): command_arg = ['taskset', str(cpu_limit)] + command_arg print("Limiting process to {0} CPUs.".format(cpu_limit)) else: print(("Couldn't limit process to {0} CPUs, " + "taskset isn't installed." ), file=sys.stderr) self.has_standard_output = True self.prefix = env.get('WINEPREFIX', None) self.child = command.run(command_arg, name = name, env = env, cwd = cwd, output_to_shell = output_to_shell, use_logfiles = use_log ) self.pid = self.child.pid self.start_time = self.child.start_time if use_log is True: self._create_info_file() RUNNING_PROGRAMS[self.child.log_filename_base] = self # Clean up RUNNING_PROGRAMS update_list()
def _get_theme_file_from_name(theme_name): if os.path.isfile(theme_name): theme_file = theme_name else: theme_file = None for test_path in [ util.wintounix( 'C:\\Windows\\Resources\\Themes\\%(name)s\\%(name)s.msstyles' % {'name': theme_name}), util.wintounix( 'C:\\Windows\\Resources\\Themes\\%s\\~.msstyles' % (theme_name)) ]: if os.path.isfile(test_path): theme_file = test_path if theme_file == None: raise OSError, "Theme file couldn't be found, tried \"%s\"" % theme_file return theme_file
def _get_theme_file_from_name(theme_name): if os.path.isfile(theme_name): theme_file = theme_name else: theme_file = None for test_path in [ util.wintounix( 'C:\\Windows\\Resources\\Themes\\%(name)s\\%(name)s.msstyles' % { 'name': theme_name } ), util.wintounix( 'C:\\Windows\\Resources\\Themes\\%s\\~.msstyles' % ( theme_name ) ) ]: if os.path.isfile(test_path): theme_file = test_path if theme_file == None: raise OSError, "Theme file couldn't be found, tried \"%s\"" % theme_file return theme_file
def _create_theme_dir(theme_name): path_full = util.wintounix( 'C:\\Windows\\resources\\themes\\{0}'.format(theme_name)) path_parts = path_full.split('/') path = path_parts[0] for path_part in path_parts[1:]: path = '/'.join([path, path_part]) print(path) if not os.path.isdir(path): print("Does not exist, creating...") if path == path_parts[-1] and os.path.exists(path): print("Is theme path and already exists, moving") shutil.move(path, '%s-old' % path) os.mkdir(path) return path
def _get_run_directory_from_possible_paths(possible_paths): run_in_path = None # Get the last file argument and also get the base path for run_in_path if len(possible_paths): for index, path in possible_paths: # Use the first existing path as the run_in_path variable # This ensures using the path to the executable, not the argument if util.path_exists(path): run_in_path = os.path.dirname(util.wintounix(path)) break last_file_arg = util.unixtowin(possible_paths[-1][1]) last_file_arg_index = possible_paths[-1][0] else: last_file_arg = None last_file_arg_index = None return (last_file_arg, last_file_arg_index, run_in_path)
def _create_theme_dir(theme_name): path_full = util.wintounix('C:\\Windows\\resources\\themes\\{0}'.format( theme_name )) path_parts = path_full.split('/') path = path_parts[0] for path_part in path_parts[1:]: path = '/'.join([path, path_part]) print(path) if not os.path.isdir(path): print("Does not exist, creating...") if path == path_parts[-1] and os.path.exists(path): print("Is theme path and already exists, moving") shutil.move(path, '%s-old' % path) os.mkdir(path) return path
def list_themes(): themes_path = util.wintounix('C:\\Windows\\Resources\\Themes\\') themes_list = {} if os.path.isdir(themes_path): for name in os.listdir(themes_path): try: info = get_theme_info(name) themes_list[name] = info except (TypeError, OSError): themes_list[name] = { 'name': name, 'description': '', 'copyright': '' } return themes_list else: return {}
def list_themes(): themes_path = util.wintounix('C:\\Windows\\Resources\\Themes\\') themes_list = {} if os.path.isdir(themes_path): for name in os.listdir(themes_path): try: info = get_theme_info(name) themes_list[name] = info except (TypeError, OSError): themes_list[name] = { 'name': name, 'description': '', 'copyright':'' } return themes_list else: return {}
def get(folder=None): """Get the path of the directory defined in "folder" (one of the keys in FOLDER_REG_NAMES).""" if folder == None: try: return CACHE['shellfolders'] except KeyError: pass else: folder = ' '.join((i.capitalize() for i in folder.split())) try: folders = CACHE['shellfolders'] return folders[folder] except KeyError: pass folders = {} """userpath = registry.get('HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment', 'APPDATA') for foldername in ["Desktop", "My Documents", "My Pictures", "My Music", "My Videos"]: if userpath: folders[foldername] = os.path.realpath("%s/drive_c/%s/%s" % (common.ENV['WINEPREFIX'], "/".join(userpath[3:].split("\\")[:-1]), foldername)) else: folders[foldername] = util.getRealHome()""" reg_folders = registry.get( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer', 'Shell Folders') for folder_name, reg_name in FOLDER_REG_NAMES.iteritems(): try: folder_path = os.readlink(util.wintounix(reg_folders[reg_name])) except (KeyError, OSError): folder_path = util.getRealHome() folder_name = ' '.join((i.capitalize() for i in folder_name.split())) folders[folder_name] = folder_path CACHE['shellfolders'] = folders if folder == None: return folders else: try: return folders[folder] except KeyError: return None
def set(foldername, target): """Set the shellfolder "foldername" (one of the keys in FOLDER_REG_NAMES) to the directory "target".""" if foldername.lower() in FOLDER_REG_NAMES.keys(): # Camelcase the folder #foldername = " ".join([ i.capitalize() for i in foldername.split(" ") ]) #userpath = registry.get('HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment', 'APPDATA') #folderpath = "%s/drive_c/%s/%s" % (common.ENV['WINEPREFIX'], "/".join(userpath[3:].split("\\")[:-1]), foldername) folder_path = registry.get( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders', FOLDER_REG_NAMES[foldername.lower()]) # If the registy folder path is a symlink from inside the configuration, change the symlink if isinstance(folder_path, basestring) and ('\\windows\\' or '\\users\\' in folder_path): folder_path = util.wintounix(folder_path) try: os.remove(folder_path) except OSError: try: os.rmdir(folder_path) except OSError: print("Skipping %s, there are files in the directory" % os.path.basename(folder_path), file=sys.stderr) os.symlink(target, folder_path) # If not, it refers to a real directory, don't mess with it, set the registry info instead else: folder_path = target registry.set({ 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders': { FOLDER_REG_NAMES[foldername.lower()]: folder_path } }) try: folders = CACHE['shellfolders'] except KeyError: folders = {} folders[foldername] = folder_path CACHE['shellfolders'] = folders
def get(folder=None): """Get the path of the directory defined in "folder" (one of the keys in FOLDER_REG_NAMES).""" if folder == None: try: return CACHE['shellfolders'] except KeyError: pass else: folder = ' '.join(( i.capitalize() for i in folder.split() )) try: folders = CACHE['shellfolders'] return folders[folder] except KeyError: pass folders = {} """userpath = registry.get('HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment', 'APPDATA') for foldername in ["Desktop", "My Documents", "My Pictures", "My Music", "My Videos"]: if userpath: folders[foldername] = os.path.realpath("%s/drive_c/%s/%s" % (common.ENV['WINEPREFIX'], "/".join(userpath[3:].split("\\")[:-1]), foldername)) else: folders[foldername] = util.getRealHome()""" reg_folders = registry.get('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer', 'Shell Folders') for folder_name, reg_name in FOLDER_REG_NAMES.iteritems(): try: folder_path = os.readlink(util.wintounix(reg_folders[reg_name])) except (KeyError, OSError): folder_path = util.getRealHome() folder_name = ' '.join(( i.capitalize() for i in folder_name.split() )) folders[folder_name] = folder_path CACHE['shellfolders'] = folders if folder == None: return folders else: try: return folders[folder] except KeyError: return None
def parse_command(command, env=None, run_in_path=None): """ Parse a command, outputting a dict containing executable, arguments, environment and so on. Commands that have better XDG replacements are replaced. command can be list (preferably) or string,""" run_in_path_override = run_in_path # If command is given as a string if type(command) in (str, unicode): if util.path_exists(command): command = [command] elif util.path_exists(util.unescape_string(command)): command = [util.unescape_string(command)] else: command = util.string_split( command, retain_defines=True, remove_escapes=True ) else: # This is a list, meaning it has to be preparsed, don't change it command = command[:] # make a copy, not a link # These variables are reported back in a dict wine_prefix = None # WINEPREFIX, will be set in environment executable = None # The executable to run, usually returns wine internal = False # If True, don't monitor since nothing should go wrong if env is None or type(env) is not dict: env = common.ENV.copy() # Self-explanatory - except that any 'env'-command will alter it run_in_path = None # Start the command in this path name = None # Name will be set to something explanatory, like "Console" # Remove double backslashes command = [ i.replace('\\\\', '\\') for i in command ] print("Command split to", command) # Move any env definitions to the env dict if command[0] == 'env': for index, arg in enumerate(command[1:]): if '=' in arg: key = arg.split('=')[0] value = '='.join(arg.split('=')[1:]) if len(value) and value[0] in ('"', "'"): value = value[1:-1] env[key] = value else: break command = command[1+index:] if command[0] == 'wine' or command[0] == common.ENV['WINE'] or re.search(r'/.*/wine$', command[0]) is not None: del command[0] executable = common.ENV['WINE'] if len(command) == 1: command[0] = util.string_remove_escapes(command[0]) # Find all file and directory paths in the command possible_paths = [] for index, i in enumerate(command): if i[1:3] == ':\\': possible_paths.append((index, i)) elif i[0] == '/': if os.path.exists(i): possible_paths.append((index, i)) elif os.path.exists(util.unescape_string(i)): possible_paths.append((index, util.unescape_string(i))) command[index] = util.unescape_string(i) #print("POSSIBLE PATHS:",possible_paths) last_file_arg, last_file_arg_index, run_in_path = ( _get_run_directory_from_possible_paths(possible_paths) ) print("possible paths: ",possible_paths) first_command = command[0].lower() #print("FIRST:",first_command) #print("LAST EXE:", last_file_arg) # Known, simple commands that don't require parsing if first_command in ('sh', 'env'): # Don't parse this command, it's shell magic executable = command[1] command = command[2:] name = "Shell command" elif first_command == 'winetricks': # Get the path for winetricks, if it exists winetricks = winetricks_installed() if winetricks: command[0] = winetricks internal = True # More advanced/troublesome commands else: command_lowercase = [ i.lower() for i in command ] # If internal command if ( first_command.split('.')[-1] in common.BUILTIN_EXECUTABLES ) or ( first_command[2:].startswith('\\windows\\command\\') and first_command.split('\\')[-1].split('.')[0] in common.BUILTIN_EXECUTABLES ): first_command_name = first_command.split('\\')[-1].split('.')[0] # Check for command being for a program that should be run in a command console if first_command_name == 'cmd': if len(command) > 1: name = "Console: {0}".format(command[1]) else: name = "Console" command = [ 'wineconsole', '--backend=user', 'cmd' ] + command[1:] elif first_command_name == 'regedit': name = "Regedit" internal = True # Override start.exe opening directories or URL, use xdg-open elif first_command_name == 'start': #print(command_lowercase) if '/unix' in command_lowercase: # This is already a unix path, don't convert # Select the argument after '/unix' path = command[ command_lowercase.index('/unix')+1 ] # Convert that argument to a UNIX path path = util.wintounix(util.unixtowin(util.string_remove_escapes(path))) else: if len(possible_paths): # This is supposedly a Windows path, use the grabbed path path = util.wintounix(possible_paths[0][1]) elif len(command) > 1: # We couldn't grab a path, use first argument path = command[1] else: # All is lost, assume 'start' is the actual command path = command[0] try: #link = parsers.read_lnk_file(path) link = binary.windows_link(path) if link and 'location' in link: path = link['location'] if 'work dir' in link: run_in_path_override = link['work dir'] except IOError: pass # Only use this path if it's actually a URL or directory if ( '://' in path[:8] or os.path.isdir(util.wintounix(path)) ): print("start.exe was asked to open a directory or URL, use xdg-open instead") executable = 'xdg-open' command = [path] run_in_path = None internal = True else: # This is a command that should be run, get run_in_path run_in_path = ( _get_run_directory_from_possible_paths( [(0, path)] ) )[2] # Check for supported file types if last_file_arg is not None: if last_file_arg.endswith('.cpl'): if not first_command.endswith('control'): command = ['control'] + command[1:] name = "Control Panel" internal = True elif last_file_arg.endswith('.lnk'): # This is a Windows shell link, read the target and open that directly try: #link = parsers.read_lnk_file(util.wintounix(last_file_arg)) link = binary.windows_link(util.wintounix(last_file_arg)) except: link = False if link: # Convert link to a unix path and back to deal with Wine's # inability to handle Windows "wildcards" (the tilde character) link_win = util.unixtowin(util.wintounix(link['location'])) link_unix = util.wintounix(link_win) if 'work dir' in link: run_in_path_override = util.wintounix(link['work dir']) # If the file type is not handled by Wine normally, # then open it with xdg-open if ( os.path.exists(link_unix) and util.file_get_mimetype(link_unix) not in common.WINDOWS_FORMATS ): print("Not normal Windows format, using xdg-open instead: ", util.file_get_mimetype(link_unix)) executable = 'xdg-open' command = [link_unix] run_in_path = None internal = True else: # Change the .lnk filename to the one it's pointing to command[last_file_arg_index] = link_win remaining_args = [ i.lower() for i in command if ( i != link_win and not i.lower().endswith('start') and not i.lower().endswith('start.exe') ) ] # This is just a call to a normal file, we can handle that if remaining_args == ['/unix']: if 'work dir' in link: parsed_command = parse_command( [link_win], env, run_in_path = util.wintounix(link['work dir']) ) else: parsed_command = parse_command( [link_win], env ) return parsed_command elif last_file_arg.endswith('.msi'): # This is a Windows Installer, run in and monitor it command = ['msiexec', '/i'] + command name = "Installer" elif last_file_arg.endswith('.url'): if last_file_arg[1:].startswith(':\\'): url_filename = util.wintounix(last_file_arg) with open(url_filename, 'r') as url_fileobj: url = url_fileobj.read() url = re.search(r'(?im)\[InternetShortcut\]\s+URL=(.*?)\s+?$', url) if url: #print("It checks out, run it.") # This is a URL, open it in a web browser, of course without monitoring it url = url.groups()[0] executable = 'xdg-open' command = [url] run_in_path = None internal = True for index, argument in enumerate(command): command[index] = util.enhance_windows_path( command[index] ) if run_in_path_override: run_in_path = run_in_path_override print("Run in", run_in_path) print("Env (changes):", util.dict_diff(os.environ, env)) print({ 'command': executable, 'arguments': command, 'internal': internal, 'prefix': wine_prefix, 'env': env, 'path': run_in_path, 'name': name # Debug variables ,'_possible_paths': possible_paths ,'_last_file': last_file_arg }) return { 'command': executable, 'arguments': command, 'internal': internal, 'prefix': wine_prefix, 'env': env, 'path': run_in_path, 'name': name # Debug variables ,'_possible_paths': possible_paths ,'_last_file': last_file_arg }