]> git.sesse.net Git - vlc/blob - loader/registry.c
* Fix the Mac OS X Resources MAKE_DIST (untested)
[vlc] / loader / registry.c
1 /*
2  * Modified for use with MPlayer, detailed CVS changelog at
3  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
4  * $Id$
5  */
6
7 #include "config.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <pwd.h>
14 #include <sys/types.h>
15
16 #include "wine/winbase.h"
17 #include "wine/winreg.h"
18 #include "wine/winnt.h"
19 #include "wine/winerror.h"
20
21 #include "ext.h"
22 #include "registry.h"
23
24 //#undef TRACE
25 //#define TRACE printf
26
27 extern char *get_path ( char * );
28
29 // ...can be set before init_registry() call
30 char* regpathname = NULL;
31
32 static char* localregpathname = NULL;
33
34 typedef struct reg_handle_s
35 {
36         int handle;
37         char* name;
38         struct reg_handle_s* next;
39         struct reg_handle_s* prev;
40 } reg_handle_t;
41
42 struct reg_value
43 {
44         int type;
45         char* name;
46         int len;
47         char* value;
48 };
49
50 static struct reg_value* regs = NULL;
51 static int reg_size;
52 static reg_handle_t* head = NULL;
53
54 #define DIR -25
55
56 static void create_registry(void);
57 static void open_registry(void);
58 static void save_registry(void);
59 static void init_registry(void);
60
61
62 static void create_registry(void){
63     if(regs)
64     {
65         printf("Logic error: create_registry() called with existing registry\n");
66         save_registry();
67         return;
68     }
69     regs=(struct reg_value*)malloc(3*sizeof(struct reg_value));
70     regs[0].type=regs[1].type=DIR;
71     regs[0].name=(char*)malloc(5);
72     strcpy(regs[0].name, "HKLM");
73     regs[1].name=(char*)malloc(5);
74     strcpy(regs[1].name, "HKCU");
75     regs[0].value=regs[1].value=NULL;
76     regs[0].len=regs[1].len=0;
77     reg_size=2;
78     head = 0;
79     save_registry();
80 }
81
82 static void open_registry(void)
83 {
84         int fd;
85         int i;
86         unsigned int len;
87         if(regs)
88         {
89                 printf("Multiple open_registry(>\n");
90                 return;
91         }
92         fd = open(localregpathname, O_RDONLY);
93         if (fd == -1)
94         {
95             printf("Creating new registry\n");
96             create_registry();
97             return;
98         }
99         read(fd, &reg_size, 4);
100         regs=(struct reg_value*)malloc(reg_size*sizeof(struct reg_value));
101         head = 0;
102         for(i=0; i<reg_size; i++)
103         {
104                 read(fd,&regs[i].type,4);
105                 read(fd,&len,4);
106                 regs[i].name=(char*)malloc(len+1);
107                 if(regs[i].name==0)
108                 {
109                         reg_size=i+1;
110                         goto error;
111                 }
112                 read(fd, regs[i].name, len);
113                 regs[i].name[len]=0;
114                 read(fd,&regs[i].len,4);
115                 regs[i].value=(char*)malloc(regs[i].len+1);
116                 if(regs[i].value==0)
117                 {
118                         free(regs[i].name);
119                         reg_size=i+1;
120                         goto error;
121                 }
122                 read(fd, regs[i].value, regs[i].len);
123                 regs[i].value[regs[i].len]=0;
124         }
125 error:
126         close(fd);
127         return;
128 }
129
130 static void save_registry(void)
131 {
132         int fd, i;
133         if (!regs)
134                 init_registry();
135         fd = open(localregpathname, O_WRONLY | O_CREAT, 00666);
136         if (fd == -1)
137         {
138             printf("Failed to open registry file '%s' for writing.\n",
139                    localregpathname);
140             return;
141         }
142         write(fd, &reg_size, 4);
143         for(i=0; i<reg_size; i++)
144         {
145                 unsigned len=strlen(regs[i].name);
146                 write(fd, &regs[i].type, 4);
147                 write(fd, &len, 4);
148                 write(fd, regs[i].name, len);
149                 write(fd, &regs[i].len, 4);
150                 write(fd, regs[i].value, regs[i].len);
151         }
152         close(fd);
153 }
154
155 void free_registry(void)
156 {
157     reg_handle_t* t = head;
158     while (t)
159     {
160         reg_handle_t* f = t;
161         if (t->name)
162             free(t->name);
163         t=t->prev;
164         free(f);
165     }
166     head = 0;
167     if (regs)
168     {
169         int i;
170         for(i=0; i<reg_size; i++)
171         {
172             free(regs[i].name);
173             free(regs[i].value);
174         }
175         free(regs);
176         regs = 0;
177     }
178
179     if (localregpathname && localregpathname != regpathname)
180         free(localregpathname);
181     localregpathname = 0;
182 }
183
184
185 static reg_handle_t* find_handle_by_name(const char* name)
186 {
187         reg_handle_t* t;
188         for(t=head; t; t=t->prev)
189         {
190                 if(!strcmp(t->name, name))
191                 {
192                         return t;
193                 }
194         }
195         return 0;
196 }
197 static struct reg_value* find_value_by_name(const char* name)
198 {
199         int i;
200         for(i=0; i<reg_size; i++)
201                 if(!strcmp(regs[i].name, name))
202                         return regs+i;
203         return 0;
204 }
205 static reg_handle_t* find_handle(int handle)
206 {
207         reg_handle_t* t;
208         for(t=head; t; t=t->prev)
209         {
210                 if(t->handle==handle)
211                 {
212                         return t;
213                 }
214         }
215         return 0;
216 }
217 static int generate_handle()
218 {
219         static unsigned int zz=249;
220         zz++;
221         while((zz==HKEY_LOCAL_MACHINE) || (zz==HKEY_CURRENT_USER))
222                 zz++;
223         return zz;
224 }
225
226 static reg_handle_t* insert_handle(long handle, const char* name)
227 {
228         reg_handle_t* t;
229         t=(reg_handle_t*)malloc(sizeof(reg_handle_t));
230         if(head==0)
231         {
232                 t->prev=0;
233         }
234         else
235         {
236                 head->next=t;
237                 t->prev=head;
238         }
239         t->next=0;
240         t->name=(char*)malloc(strlen(name)+1);
241         strcpy(t->name, name);
242         t->handle=handle;
243         head=t;
244         return t;
245 }
246 static char* build_keyname(long key, const char* subkey)
247 {
248         char* full_name;
249         reg_handle_t* t;
250         if((t=find_handle(key))==0)
251         {
252                 TRACE("Invalid key\n");
253                 return NULL;
254         }
255         if(subkey==NULL)
256                 subkey="<default>";
257         full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
258         strcpy(full_name, t->name);
259         strcat(full_name, "\\");
260         strcat(full_name, subkey);
261         return full_name;
262 }
263 static struct reg_value* insert_reg_value(int handle, const char* name, int type, const void* value, int len)
264 {
265         reg_handle_t* t;
266         struct reg_value* v;
267         char* fullname;
268         if((fullname=build_keyname(handle, name))==NULL)
269         {
270                 TRACE("Invalid handle\n");
271                 return NULL;
272         }
273
274         if((v=find_value_by_name(fullname))==0)
275         //creating new value in registry
276         {
277                 if(regs==0)
278                     create_registry();
279                 regs=(struct reg_value*)realloc(regs, sizeof(struct reg_value)*(reg_size+1));
280                 //regs=(struct reg_value*)my_realloc(regs, sizeof(struct reg_value)*(reg_size+1));
281                 v=regs+reg_size;
282                 reg_size++;
283         }
284         else
285         //replacing old one
286         {
287             free(v->value);
288             free(v->name);
289         }
290         TRACE("RegInsert '%s'  %p  v:%d  len:%d\n", name, value, *(int*)value, len);
291         v->type=type;
292         v->len=len;
293         v->value=(char*)malloc(len);
294         memcpy(v->value, value, len);
295         v->name=(char*)malloc(strlen(fullname)+1);
296         strcpy(v->name, fullname);
297         free(fullname);
298         save_registry();
299         return v;
300 }
301
302 static void init_registry(void)
303 {
304         TRACE("Initializing registry\n");
305         // can't be free-ed - it's static and probably thread
306         // unsafe structure which is stored in glibc
307
308 #ifdef MPLAYER
309         regpathname = get_path("registry");
310         localregpathname = regpathname;
311 #else
312         // regpathname is an external pointer
313         //
314         // registry.c is holding it's own internal pointer
315         // localregpathname  - which is being allocate/deallocated
316
317         if (localregpathname == 0)
318         {
319             const char* pthn = regpathname;
320             if (!regpathname)
321             {
322                 // avifile - for now reading data from user's home
323                 struct passwd* pwent;
324                 pwent = getpwuid(geteuid());
325                 pthn = pwent->pw_dir;
326             }
327
328             localregpathname = (char*)malloc(strlen(pthn)+20);
329             strcpy(localregpathname, pthn);
330             strcat(localregpathname, "/.registry");
331         }
332 #endif
333
334         open_registry();
335         insert_handle(HKEY_LOCAL_MACHINE, "HKLM");
336         insert_handle(HKEY_CURRENT_USER, "HKCU");
337 }
338
339 static reg_handle_t* find_handle_2(long key, const char* subkey)
340 {
341         char* full_name;
342         reg_handle_t* t;
343         if((t=find_handle(key))==0)
344         {
345                 TRACE("Invalid key\n");
346                 return (reg_handle_t*)-1;
347         }
348         if(subkey==NULL)
349                 return t;
350         full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
351         strcpy(full_name, t->name);
352         strcat(full_name, "\\");
353         strcat(full_name, subkey);
354         t=find_handle_by_name(full_name);
355         free(full_name);
356         return t;
357 }
358
359 long __stdcall RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
360 {
361     char* full_name;
362     reg_handle_t* t;
363     struct reg_value* v;
364     TRACE("Opening key %s\n", subkey);
365
366     if(!regs)
367         init_registry()
368 ;
369 /*      t=find_handle_2(key, subkey);
370
371         if(t==0)
372                 return -1;
373
374         if(t==(reg_handle_t*)-1)
375                 return -1;
376 */
377     full_name=build_keyname(key, subkey);
378     if(!full_name)
379         return -1;
380     TRACE("Opening key Fullname %s\n", full_name);
381     v=find_value_by_name(full_name);
382
383     t=insert_handle(generate_handle(), full_name);
384     *newkey=t->handle;
385     free(full_name);
386
387     return 0;
388 }
389 long __stdcall RegCloseKey(long key)
390 {
391     reg_handle_t *handle;
392     if(key==(long)HKEY_LOCAL_MACHINE)
393         return 0;
394     if(key==(long)HKEY_CURRENT_USER)
395         return 0;
396     handle=find_handle(key);
397     if(handle==0)
398         return 0;
399     if(handle->prev)
400         handle->prev->next=handle->next;
401     if(handle->next)
402         handle->next->prev=handle->prev;
403     if(handle->name)
404         free(handle->name);
405     if(handle==head)
406         head=head->prev;
407     free(handle);
408     return 1;
409 }
410
411 long __stdcall RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
412 {
413     struct reg_value* t;
414     char* c;
415     TRACE("Querying value %s\n", value);
416     if(!regs)
417         init_registry();
418
419     c=build_keyname(key, value);
420     if (!c)
421         return 1;
422     t=find_value_by_name(c);
423     free(c);
424     if (t==0)
425         return 2;
426     if (type)
427         *type=t->type;
428     if (data)
429     {
430         memcpy(data, t->value, (t->len<*count)?t->len:*count);
431         TRACE("returning %d bytes: %d\n", t->len, *(int*)data);
432     }
433     if(*count<t->len)
434     {
435         *count=t->len;
436         return ERROR_MORE_DATA;
437     }
438     else
439     {
440         *count=t->len;
441     }
442     return 0;
443 }
444 long __stdcall RegCreateKeyExA(long key, const char* name, long reserved,
445                      void* classs, long options, long security,
446                      void* sec_attr, int* newkey, int* status)
447 {
448     reg_handle_t* t;
449     char* fullname;
450     struct reg_value* v;
451     //        TRACE("Creating/Opening key %s\n", name);
452     if(!regs)
453         init_registry();
454
455     fullname=build_keyname(key, name);
456     if (!fullname)
457         return 1;
458     TRACE("Creating/Opening key %s\n", fullname);
459     v=find_value_by_name(fullname);
460     if(v==0)
461     {
462         int qw=45708;
463         v=insert_reg_value(key, name, DIR, &qw, 4);
464         if (status) *status=REG_CREATED_NEW_KEY;
465         //              return 0;
466     }
467
468     t=insert_handle(generate_handle(), fullname);
469     *newkey=t->handle;
470     free(fullname);
471     return 0;
472 }
473
474 /*
475 LONG RegEnumValue(
476   HKEY hKey,              // handle to key to query
477   DWORD dwIndex,          // index of value to query
478   LPTSTR lpValueName,     // address of buffer for value string
479   LPDWORD lpcbValueName,  // address for size of value buffer
480   LPDWORD lpReserved,     // reserved
481   LPDWORD lpType,         // address of buffer for type code
482   LPBYTE lpData,          // address of buffer for value data
483   LPDWORD lpcbData        // address for size of data buffer
484 );
485 */
486
487 long __stdcall RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
488                    LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
489 {
490     // currenly just made to support MSZH & ZLIB
491     //printf("Reg Enum 0x%x %d  %s %d   data: %p %d  %d >%s<\n", hkey, index,
492     //       value, *val_count, data, *count, reg_size, data);
493     reg_handle_t* t = find_handle(hkey);
494     if (t && index < 10)
495     {
496         struct reg_value* v=find_value_by_name(t->name);
497         if (v)
498         {
499             memcpy(data, v->value, (v->len < *count) ? v->len : *count);
500             if(*count < v->len)
501                 *count = v->len;
502             if (type)
503                 *type = v->type;
504             //printf("Found handle  %s\n", v->name);
505             return 0;
506         }
507     }
508     return ERROR_NO_MORE_ITEMS;
509 }
510
511 long __stdcall RegSetValueExA(long key, const char* name, long v1, long v2, const void* data, long size)
512 {
513     struct reg_value* t;
514     char* c;
515     TRACE("Request to set value %s %d\n", name, *(const int*)data);
516     if(!regs)
517         init_registry();
518
519     c=build_keyname(key, name);
520     if(c==NULL)
521         return 1;
522     insert_reg_value(key, name, v2, data, size);
523     free(c);
524     return 0;
525 }
526
527 long __stdcall RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
528                    LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
529                    LPFILETIME lpftLastWriteTime)
530 {
531     return ERROR_NO_MORE_ITEMS;
532 }