Example #1
0
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
Example #2
0
    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()
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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)
Example #7
0
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
Example #8
0
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 {}
Example #9
0
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 {}
Example #10
0
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
Example #11
0
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
Example #12
0
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
Example #13
0
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
    }