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