~allsymes/vineyard/fixes

« back to all changes in this revision

Viewing changes to python-wine/wine/_registry.py

  • Committer: Christian Dannie Storgaard
  • Date: 2010-02-17 22:04:59 UTC
  • Revision ID: cybolic@gmail.com-20100217220459-tg3owv2zl8wx5g9o
Rewrote registry file parser, doesn't fall over any more and is faster. Fixed various bugs in vineyard-preferences. Completed the functionality for adding unlisted programs. Added the files for exe-helper (probably doesn't work right now, doesn't detect paths right).

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
# Christian Dannie Storgaard <cybolic@gmail.com>
8
8
 
9
9
import os
10
 
import util
 
10
import util, parsers
11
11
 
12
12
import subprocess
13
13
 
14
14
import logging
15
15
 
16
16
class Registry:
17
 
        def __init__(self):
18
 
                self.registryCache = None
19
 
                self.logging = logging.getLogger("python-wine.programs")
20
 
                self.debug = self.logging.debug
21
 
                self.error = self.logging.error
22
 
        
23
 
        def __branch_to_dict(self, branch, dict):
24
 
                parents = []
25
 
                for path in filter(len, branch.split('\\')):
26
 
                        pathname = 'dict%s' % ''.join([ '[\'%s\']' % i for i in parents ])
27
 
                        if path not in eval(pathname) or type(eval(pathname)) != type({}):
28
 
                                exec('%s[\'%s\'] = {}' % (pathname, path))
29
 
                        parents.append(path)
30
 
                return dict
31
 
        
32
 
        def __set_branch_values(self, branch, dict, items):
33
 
                # Make sure the dict keys exist
34
 
                dict = self.__branch_to_dict(branch, dict)
35
 
                # Set the value
36
 
                pathname = 'dict%s' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\')) ])
37
 
                for key, value in items.iteritems():
38
 
                        try:
39
 
                                exec ('%s[\'%s\'] = value' % (pathname, key.replace('\\', '\\\\').replace("'", '\\')))
40
 
                        except ValueError:
41
 
                                self.error("Error in registry! Pathname: %s\tKey: %s\tValue: %s" % (pathname, key, value))
42
 
                return dict
43
 
        
44
 
        def _writeRegistry(self, registrycontent):
45
 
                regfilename = util.tempname('vineyard-setregistry-', '.reg')
46
 
                regfile = open(regfilename, "w")
47
 
                regfile.write(registrycontent)
48
 
                regfile.close()
49
 
                returnvalue = subprocess.call(["regedit", regfilename], env=os.environ)
50
 
                #os.remove(regfilename)
51
 
                return returnvalue
52
 
        
53
 
        def __get_branch(self, branch=None, quiet=True):
54
 
                self._initWine()
55
 
                if branch == None:
56
 
                        process = subprocess.Popen(["regedit", "/E", "-"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)
57
 
                        branch = ''
58
 
                else:
59
 
                        process = subprocess.Popen(["regedit", "/E", "-", branch], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)
60
 
                registry = ''
61
 
                buffer = process.stdout.readline()
62
 
                while buffer != '':
63
 
                        registry += buffer
64
 
                        buffer = process.stdout.readline()
65
 
                #if process.returncode and not quiet:
66
 
                if registry == '' or registry.strip() == 'Success':
67
 
                        if not quiet:
68
 
                                self.error("Warning: Registry branch '%s' doesn't exist." % branch)
69
 
                        return ''
70
 
                return registry
71
 
        
72
 
        def __get_branch_as_dict(self, branch=None):
73
 
                registry = self.__get_branch(branch)
74
 
                
75
 
                if not registry:
76
 
                        return None
77
 
                
78
 
                registry_dict = {}
79
 
                
80
 
                path = None
81
 
                values = {}
82
 
                registrysplit = filter(len, [ i.strip() for i in registry.split("\r\n") ])+ ['[]']
83
 
                for linenr in range(len(registrysplit)):
84
 
                        line = registrysplit[linenr]
85
 
                        original_value = None
86
 
                        if line.startswith('['):
87
 
                                """ If line is section header """
88
 
                                # Set the values of the last section, if any
89
 
                                if path != None:
90
 
                                        registry_dict = self.__set_branch_values(path, registry_dict, values)
91
 
                                # Get the section path and start a new section values dict
92
 
                                path = ':'.join(line[1:].split(']')[:-1])
93
 
                                values = {}
94
 
                        elif line.startswith('"') or line.startswith('@'):
95
 
                                """ If line is key/value """
96
 
                                key = line.split('=')[0].replace('"','')
97
 
                                value = "=".join(line.split('=')[1:]).strip()
98
 
                                value_is_string = True
99
 
                                value_type = value.split(':')[0].lower()
100
 
                                """ If value is multi-line """
101
 
                                if value.strip().endswith('\\'):
102
 
                                        value = "%s%s" % (value.strip()[:-1], registrysplit[linenr+1].strip())
103
 
                                        linenr += 2
104
 
                                        while value.strip().endswith('\\'):
105
 
                                                value = value[:-1] + registrysplit[linenr].strip()
106
 
                                                linenr += 1
107
 
                                        if value.endswith('\\'):
108
 
                                                value = value[:-1]
109
 
                                """ See what type of value this is.
110
 
                                    For more info, see http://technet.microsoft.com/en-us/library/bb727154.aspx
111
 
                                """
112
 
                                if value_type.startswith('hex(2)'):
113
 
                                        """ Expanded String """
114
 
                                        try:
115
 
                                                new_value = util.hextoutf8(value)
116
 
                                                original_value = value
117
 
                                                value = new_value
118
 
                                        except UnicodeDecodeError:
119
 
                                                # This won't convert, it's probably an actual hex value, and not just stored as one
120
 
                                                #print "Error in path \"%s\", string:" % path, value
121
 
                                                value_is_string = False
122
 
                                                print "Couldn't read registry! This is a serious error, please report this error along with this text at https://bugs.launchpad.net/vineyard"
123
 
                                                print path, key, value_type, value
124
 
                                                exit(0)
125
 
                                elif value_type.startswith('hex(7)'):
126
 
                                        """ Multi String """
127
 
                                        value_is_string = False
128
 
                                        try:
129
 
                                                value = filter(len, util.hextoutf8(value).split('\x00'))
130
 
                                        except TypeError:
131
 
                                                print "Couldn't read registry! This is a serious error, please report this error along with this text at https://bugs.launchpad.net/vineyard"
132
 
                                                print path, key, value_type, value
133
 
                                                exit(0)
134
 
                                elif value_type.startswith('hex'):
135
 
                                        """ HEX Value """
136
 
                                        value_is_string = False
137
 
                                        value = value
138
 
                                elif value_type.startswith('dword'):
139
 
                                        value_is_string = False
140
 
                                elif value_type.startswith('null'):
141
 
                                        value_is_string = False
142
 
                                        value = None
143
 
                                elif value_type.startswith('quote') or value.startswith('str') or value.startswith('str(2)'):
144
 
                                        value = value
145
 
                                if value_is_string:
146
 
                                        if value.strip().startswith('"') and value.replace('\x00','').strip().endswith('"'):
147
 
                                                value = '"'.join(value.strip().split('"')[1:-1])
148
 
                                        
149
 
                                        try:
150
 
                                                #value = value.encode('utf-8').decode('string_escape').decode('utf-8').replace('\\\\', '\\').replace('\\\\', '\\').replace('\x00','')
151
 
                                                if type(value) == list:
152
 
                                                        value = [ util.stringtoutf8(i) for i in value ]
153
 
                                                else:
154
 
                                                        value = util.stringtoutf8(value)
155
 
                                        except UnicodeDecodeError:
156
 
                                                print "Couldn't read registry! This is a serious error, please report this error along with this text at https://bugs.launchpad.net/vineyard"
157
 
                                                print path, key, value_type, value.encode('hex')
158
 
                                                exit(0)
159
 
                                values[key] = value
160
 
                                if original_value:
161
 
                                        values['_%s' % key] = original_value
162
 
                return registry_dict
163
 
        
164
 
        def __branchpath_in_dict(self, dict, branch):
165
 
                try:
166
 
                        self.__get_dict_from_branchpath(dict, branch)
167
 
                        return True
168
 
                except:
169
 
                        return False
170
 
        
171
 
        def __get_dict_from_branchpath(self, dict, branch):
172
 
                try:
173
 
                        return eval('dict%s' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\'))]))
174
 
                except NameError:
175
 
                        return False
176
 
        
177
 
        def __set_dict_from_branchpath(self, dict, branch, value):
178
 
                exec('dict%s = value' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\'))]))
179
 
                return dict
180
 
        
181
 
        def get(self, branch=None, findkey=None, quiet=True):
182
 
                if findkey:
183
 
                        fullbranch = '%s\\%s' % (branch, findkey)
184
 
                else:
185
 
                        fullbranch = branch
186
 
                
187
 
                reg = self.__get_branch_as_dict(branch)
188
 
                
189
 
                if reg == None:
190
 
                        reg = {}
191
 
                else:
192
 
                        reg = self.__get_dict_from_branchpath(reg, branch)
193
 
                        
194
 
                if findkey:
195
 
                        if findkey in reg:
196
 
                                retvalue = reg[findkey]
197
 
                        else:
198
 
                                retvalue = None
199
 
                else:
200
 
                        retvalue = reg
201
 
                
202
 
                return retvalue
203
 
 
204
 
        def set(self, branches):
205
 
                # Set registry values
206
 
                # Branches should be a dict similar to:
207
 
                # {
208
 
                #  'HKEY_CURRENT_USER\\Software\\Wine':
209
 
                #   {"Version": "winnt"},
210
 
                # 'HKEY_USERS\\S-1-5-4\\Control Panel\\Desktop':
211
 
                #   {"FontSmoothing": "2"}
212
 
                # }
213
 
                self._initWine()
214
 
                
215
 
                registry = "REGEDIT4\n"
216
 
 
217
 
                definedbranches = []
218
 
                for b in sorted(branches.keys()):
219
 
                        branchwalk = b.split('\\')
220
 
                        for i in range(len(branchwalk)-1):
221
 
                                branch = "\n[%s\\%s]\n" % (branchwalk[0], '\\'.join(branchwalk[1:i+2]))
222
 
                                if branch not in definedbranches:
223
 
                                        registry += branch
224
 
                                        definedbranches.append(branch)
225
 
                        # Add the values
226
 
                        for key,value in sorted(branches[b].iteritems()):
227
 
                                if value == '-' or value == None:
228
 
                                        registry += "\"%s\"=-\n" % str(key).encode('utf-8').encode('string_escape')
229
 
                                elif str(value).startswith('hex:') or str(value).startswith('dword:'):
230
 
                                        registry += "\"%s\"=%s\n" % (str(key).encode('utf-8').encode('string_escape'), str(value))
231
 
                                else:
232
 
                                        try:
233
 
                                                registry += "\"%s\"=\"%s\"\n" % (str(key).encode('utf-8').encode('string_escape'), str(value).encode('utf-8').encode('string_escape').replace('"', '\\"'))
234
 
                                        except TypeError:
235
 
                                                print "Error:",key,value
236
 
                registry += "\n"
237
 
                self._writeRegistry(registry)
238
 
        
239
 
        def _initWine(self):
240
 
                self._wineprocess = subprocess.Popen("wineserver -p10", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)
 
17
    def __init__(self):
 
18
        self.registryCache = None
 
19
        self.logging = logging.getLogger("python-wine.programs")
 
20
        self.debug = self.logging.debug
 
21
        self.error = self.logging.error
 
22
    
 
23
    def __branch_to_dict(self, branch, dict):
 
24
        parents = []
 
25
        for path in filter(len, branch.split('\\')):
 
26
            pathname = 'dict%s' % ''.join([ '[\'%s\']' % i for i in parents ])
 
27
            if path not in eval(pathname) or type(eval(pathname)) != type({}):
 
28
                exec('%s[\'%s\'] = {}' % (pathname, path))
 
29
            parents.append(path)
 
30
        return dict
 
31
    
 
32
    def __set_branch_values(self, branch, dict, items):
 
33
        # Make sure the dict keys exist
 
34
        dict = self.__branch_to_dict(branch, dict)
 
35
        # Set the value
 
36
        pathname = 'dict%s' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\')) ])
 
37
        for key, value in items.iteritems():
 
38
            try:
 
39
                exec ('%s[\'%s\'] = value' % (pathname, key.replace('\\', '\\\\').replace("'", '\\')))
 
40
            except ValueError:
 
41
                self.error("Error in registry! Pathname: %s\tKey: %s\tValue: %s" % (pathname, key, value))
 
42
        return dict
 
43
    
 
44
    def _writeRegistry(self, registrycontent):
 
45
        regfilename = util.tempname('vineyard-setregistry-', '.reg')
 
46
        regfile = open(regfilename, "w")
 
47
        regfile.write(registrycontent)
 
48
        regfile.close()
 
49
        returnvalue = subprocess.call(["regedit", regfilename], env=os.environ)
 
50
        #os.remove(regfilename)
 
51
        return returnvalue
 
52
    
 
53
    def __get_branch(self, branch=None, quiet=True):
 
54
        if branch.startswith('HKEY_LOCAL_MACHINE') and branch != 'HKEY_LOCAL_MACHINE\\System\\MountedDevices':
 
55
            registry_file = open('%s/system.reg' % os.environ['WINEPREFIX'], 'r')
 
56
            registry = registry_file.read()
 
57
            registry_file.close()
 
58
            #print "Using system.reg file as registry."
 
59
            return ('HKEY_LOCAL_MACHINE', registry)
 
60
        elif branch.startswith('HKEY_CURRENT_USER'):
 
61
            registry_file = open('%s/user.reg' % os.environ['WINEPREFIX'], 'r')
 
62
            registry = registry_file.read()
 
63
            registry_file.close()
 
64
            #print "Using user.reg file as registry."
 
65
            return ('HKEY_CURRENT_USER', registry)
 
66
        elif branch.startswith('HKEY_USERS\\.Default'):
 
67
            registry_file = open('%s/userdef.reg' % os.environ['WINEPREFIX'], 'r')
 
68
            registry = registry_file.read()
 
69
            registry_file.close()
 
70
            #print "Using userdef.reg file as registry."
 
71
            return ('HKEY_USERS\\.Default', registry)
 
72
 
 
73
        #print "Using regedit to read registry."
 
74
        self._initWine()
 
75
        if branch == None:
 
76
            process = subprocess.Popen(["regedit", "/E", "-"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)
 
77
            branch = ''
 
78
        else:
 
79
            process = subprocess.Popen(["regedit", "/E", "-", branch], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)
 
80
        registry = ''
 
81
        buffer = process.stdout.readline()
 
82
        while buffer != '':
 
83
            registry += buffer
 
84
            buffer = process.stdout.readline()
 
85
        #if process.returncode and not quiet:
 
86
        if registry == '' or registry.strip() == 'Success':
 
87
            if not quiet:
 
88
                self.error("Warning: Registry branch '%s' doesn't exist." % branch)
 
89
            return ''
 
90
        return registry
 
91
    
 
92
    def __branchpath_in_dict(self, dict, branch):
 
93
        try:
 
94
            self.__get_dict_from_branchpath(dict, branch)
 
95
            return True
 
96
        except:
 
97
            return False
 
98
    
 
99
    def __get_dict_from_branchpath(self, dict, branch):
 
100
        try:
 
101
            return eval('dict%s' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\'))]))
 
102
        except NameError:
 
103
            return False
 
104
    
 
105
    def __set_dict_from_branchpath(self, dict, branch, value):
 
106
        exec('dict%s = value' % ''.join([ '[\'%s\']' % i for i in filter(len, branch.split('\\'))]))
 
107
        return dict
 
108
    
 
109
    def get(self, branch=None, findkey=None, quiet=True):
 
110
        if findkey:
 
111
            fullbranch = '%s\\%s' % (branch, findkey)
 
112
        else:
 
113
            fullbranch = branch
 
114
        
 
115
        #reg = self.__get_branch_as_dict(branch)
 
116
        branch_output = self.__get_branch(branch)
 
117
        if type(branch_output) == tuple:
 
118
            reg = parsers.parseRegistry(branch_output[1], branch_output[0])
 
119
        else:
 
120
            reg = parsers.parseRegistry(branch_output)
 
121
        
 
122
        if reg == None:
 
123
            reg = {}
 
124
        else:
 
125
            try:
 
126
                reg = self.__get_dict_from_branchpath(reg, branch)
 
127
            except KeyError:
 
128
                if findkey:
 
129
                    return None
 
130
                else:
 
131
                    return {}
 
132
            
 
133
        if findkey:
 
134
            if findkey in reg:
 
135
                retvalue = reg[findkey]
 
136
            else:
 
137
                retvalue = None
 
138
        else:
 
139
            retvalue = reg
 
140
        
 
141
        return retvalue
 
142
 
 
143
    def set(self, branches):
 
144
        # Set registry values
 
145
        # Branches should be a dict similar to:
 
146
        # {
 
147
        #  'HKEY_CURRENT_USER\\Software\\Wine':
 
148
        #   {"Version": "winnt"},
 
149
        # 'HKEY_USERS\\S-1-5-4\\Control Panel\\Desktop':
 
150
        #   {"FontSmoothing": "2"}
 
151
        # }
 
152
        self._initWine()
 
153
        
 
154
        registry = "REGEDIT4\n"
 
155
 
 
156
        definedbranches = []
 
157
        for b in sorted(branches.keys()):
 
158
            branchwalk = b.split('\\')
 
159
            for i in range(len(branchwalk)-1):
 
160
                branch = "\n[%s\\%s]\n" % (branchwalk[0], '\\'.join(branchwalk[1:i+2]))
 
161
                if branch not in definedbranches:
 
162
                    registry += branch
 
163
                    definedbranches.append(branch)
 
164
            # Add the values
 
165
            for key,value in sorted(branches[b].iteritems()):
 
166
                if value == '-' or value == None:
 
167
                    registry += "\"%s\"=-\n" % str(key).encode('utf-8').encode('string_escape')
 
168
                elif str(value).startswith('hex:') or str(value).startswith('dword:'):
 
169
                    registry += "\"%s\"=%s\n" % (str(key).encode('utf-8').encode('string_escape'), str(value))
 
170
                else:
 
171
                    try:
 
172
                        registry += "\"%s\"=\"%s\"\n" % (str(key).encode('utf-8').encode('string_escape'), str(value).encode('utf-8').encode('string_escape').replace('"', '\\"'))
 
173
                    except TypeError:
 
174
                        print "Error:",key,value
 
175
        registry += "\n"
 
176
        self._writeRegistry(registry)
 
177
    
 
178
    def _initWine(self):
 
179
        self._wineprocess = subprocess.Popen("wineserver -p10", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ)