]> git.sesse.net Git - vlc/blob - libs/loader/registry.c
967f52fadffffd62eb2daaf7531b68d0661249db
[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         free(t->name);
183         t=t->prev;
184         free(f);
185     }
186     head = 0;
187     if (regs)
188     {
189         int i;
190         for(i=0; i<reg_size; i++)
191         {
192             free(regs[i].name);
193             free(regs[i].value);
194         }
195         free(regs);
196         regs = 0;
197     }
198
199     if (localregpathname != regpathname)
200         free(localregpathname);
201     localregpathname = 0;
202 }
203
204
205 static reg_handle_t* find_handle_by_name(const char* name)
206 {
207         reg_handle_t* t;
208         for(t=head; t; t=t->prev)
209         {
210                 if(!strcmp(t->name, name))
211                 {
212                         return t;
213                 }
214         }
215         return 0;
216 }
217 static struct reg_value* find_value_by_name(const char* name)
218 {
219         int i;
220         for(i=0; i<reg_size; i++)
221                 if(!strcmp(regs[i].name, name))
222                         return regs+i;
223         return 0;
224 }
225 static reg_handle_t* find_handle(int handle)
226 {
227         reg_handle_t* t;
228         for(t=head; t; t=t->prev)
229         {
230                 if(t->handle==handle)
231                 {
232                         return t;
233                 }
234         }
235         return 0;
236 }
237 static int generate_handle()
238 {
239         static unsigned int zz=249;
240         zz++;
241         while((zz==HKEY_LOCAL_MACHINE) || (zz==HKEY_CURRENT_USER))
242                 zz++;
243         return zz;
244 }
245
246 static reg_handle_t* insert_handle(long handle, const char* name)
247 {
248         reg_handle_t* t;
249         t=(reg_handle_t*)malloc(sizeof(reg_handle_t));
250         if(head==0)
251         {
252                 t->prev=0;
253         }
254         else
255         {
256                 head->next=t;
257                 t->prev=head;
258         }
259         t->next=0;
260         t->name=(char*)malloc(strlen(name)+1);
261         strcpy(t->name, name);
262         t->handle=handle;
263         head=t;
264         return t;
265 }
266 static char* build_keyname(long key, const char* subkey)
267 {
268         char* full_name;
269         reg_handle_t* t;
270         if((t=find_handle(key))==0)
271         {
272                 TRACE("Invalid key\n");
273                 return NULL;
274         }
275         if(subkey==NULL)
276                 subkey="<default>";
277         full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
278         strcpy(full_name, t->name);
279         strcat(full_name, "\\");
280         strcat(full_name, subkey);
281         return full_name;
282 }
283 static struct reg_value* insert_reg_value(int handle, const char* name, int type, const void* value, int len)
284 {
285         reg_handle_t* t;
286         struct reg_value* v;
287         char* fullname;
288         if((fullname=build_keyname(handle, name))==NULL)
289         {
290                 TRACE("Invalid handle\n");
291                 return NULL;
292         }
293
294         if((v=find_value_by_name(fullname))==0)
295         //creating new value in registry
296         {
297                 if(regs==0)
298                     create_registry();
299                 regs=(struct reg_value*)realloc(regs, sizeof(struct reg_value)*(reg_size+1));
300                 //regs=(struct reg_value*)my_realloc(regs, sizeof(struct reg_value)*(reg_size+1));
301                 v=regs+reg_size;
302                 reg_size++;
303         }
304         else
305         //replacing old one
306         {
307             free(v->value);
308             free(v->name);
309         }
310         TRACE("RegInsert '%s'  %p  v:%d  len:%d\n", name, value, *(int*)value, len);
311         v->type=type;
312         v->len=len;
313         v->value=(char*)malloc(len);
314         memcpy(v->value, value, len);
315         v->name=(char*)malloc(strlen(fullname)+1);
316         strcpy(v->name, fullname);
317         free(fullname);
318         save_registry();
319         return v;
320 }
321
322 static void init_registry(void)
323 {
324         TRACE("Initializing registry\n");
325         // can't be free-ed - it's static and probably thread
326         // unsafe structure which is stored in glibc
327
328 #ifdef MPLAYER
329         regpathname = get_path("registry");
330         localregpathname = regpathname;
331 #else
332         // regpathname is an external pointer
333         //
334         // registry.c is holding its own internal pointer
335         // localregpathname  - which is being allocate/deallocated
336
337         if (localregpathname == 0)
338         {
339             const char* pthn = regpathname;
340             if (!regpathname)
341             {
342                 // avifile - for now reading data from user's home
343                 struct passwd* pwent;
344                 pwent = getpwuid(geteuid());
345                 pthn = pwent->pw_dir;
346             }
347
348             localregpathname = (char*)malloc(strlen(pthn)+20);
349             strcpy(localregpathname, pthn);
350             strcat(localregpathname, "/.registry");
351         }
352 #endif
353
354         open_registry();
355         insert_handle(HKEY_LOCAL_MACHINE, "HKLM");
356         insert_handle(HKEY_CURRENT_USER, "HKCU");
357 }
358
359 static reg_handle_t* find_handle_2(long key, const char* subkey)
360 {
361         char* full_name;
362         reg_handle_t* t;
363         if((t=find_handle(key))==0)
364         {
365                 TRACE("Invalid key\n");
366                 return (reg_handle_t*)-1;
367         }
368         if(subkey==NULL)
369                 return t;
370         full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
371         strcpy(full_name, t->name);
372         strcat(full_name, "\\");
373         strcat(full_name, subkey);
374         t=find_handle_by_name(full_name);
375         free(full_name);
376         return t;
377 }
378
379 long __stdcall RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
380 {
381     char* full_name;
382     reg_handle_t* t;
383     struct reg_value* v;
384     TRACE("Opening key %s\n", subkey);
385
386     if(!regs)
387         init_registry()
388 ;
389 /*      t=find_handle_2(key, subkey);
390
391         if(t==0)
392                 return -1;
393
394         if(t==(reg_handle_t*)-1)
395                 return -1;
396 */
397     full_name=build_keyname(key, subkey);
398     if(!full_name)
399         return -1;
400     TRACE("Opening key Fullname %s\n", full_name);
401     v=find_value_by_name(full_name);
402
403     t=insert_handle(generate_handle(), full_name);
404     *newkey=t->handle;
405     free(full_name);
406
407     return 0;
408 }
409 long __stdcall RegCloseKey(long key)
410 {
411     reg_handle_t *handle;
412     if(key==(long)HKEY_LOCAL_MACHINE)
413         return 0;
414     if(key==(long)HKEY_CURRENT_USER)
415         return 0;
416     handle=find_handle(key);
417     if(handle==0)
418         return 0;
419     if(handle->prev)
420         handle->prev->next=handle->next;
421     if(handle->next)
422         handle->next->prev=handle->prev;
423     free(handle->name);
424     if(handle==head)
425         head=head->prev;
426     free(handle);
427     return 1;
428 }
429
430 long __stdcall RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
431 {
432     struct reg_value* t;
433     char* c;
434     TRACE("Querying value %s\n", value);
435     if(!regs)
436         init_registry();
437
438     c=build_keyname(key, value);
439     if (!c)
440         return 1;
441     t=find_value_by_name(c);
442     free(c);
443     if (t==0)
444         return 2;
445     if (type)
446         *type=t->type;
447     if (data)
448     {
449         memcpy(data, t->value, (t->len<*count)?t->len:*count);
450         TRACE("returning %d bytes: %d\n", t->len, *(int*)data);
451     }
452     if(*count<t->len)
453     {
454         *count=t->len;
455         return ERROR_MORE_DATA;
456     }
457     else
458     {
459         *count=t->len;
460     }
461     return 0;
462 }
463 long __stdcall RegCreateKeyExA(long key, const char* name, long reserved,
464                      void* classs, long options, long security,
465                      void* sec_attr, int* newkey, int* status)
466 {
467     reg_handle_t* t;
468     char* fullname;
469     struct reg_value* v;
470     //        TRACE("Creating/Opening key %s\n", name);
471     if(!regs)
472         init_registry();
473
474     fullname=build_keyname(key, name);
475     if (!fullname)
476         return 1;
477     TRACE("Creating/Opening key %s\n", fullname);
478     v=find_value_by_name(fullname);
479     if(v==0)
480     {
481         int qw=45708;
482         v=insert_reg_value(key, name, DIR, &qw, 4);
483         if (status) *status=REG_CREATED_NEW_KEY;
484         //              return 0;
485     }
486
487     t=insert_handle(generate_handle(), fullname);
488     *newkey=t->handle;
489     free(fullname);
490     return 0;
491 }
492
493 /*
494 LONG RegEnumValue(
495   HKEY hKey,              // handle to key to query
496   DWORD dwIndex,          // index of value to query
497   LPTSTR lpValueName,     // address of buffer for value string
498   LPDWORD lpcbValueName,  // address for size of value buffer
499   LPDWORD lpReserved,     // reserved
500   LPDWORD lpType,         // address of buffer for type code
501   LPBYTE lpData,          // address of buffer for value data
502   LPDWORD lpcbData        // address for size of data buffer
503 );
504 */
505
506 long __stdcall RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
507                    LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
508 {
509     // currenly just made to support MSZH & ZLIB
510     //printf("Reg Enum 0x%x %d  %s %d   data: %p %d  %d >%s<\n", hkey, index,
511     //       value, *val_count, data, *count, reg_size, data);
512     reg_handle_t* t = find_handle(hkey);
513     if (t && index < 10)
514     {
515         struct reg_value* v=find_value_by_name(t->name);
516         if (v)
517         {
518             memcpy(data, v->value, (v->len < *count) ? v->len : *count);
519             if(*count < v->len)
520                 *count = v->len;
521             if (type)
522                 *type = v->type;
523             //printf("Found handle  %s\n", v->name);
524             return 0;
525         }
526     }
527     return ERROR_NO_MORE_ITEMS;
528 }
529
530 long __stdcall RegSetValueExA(long key, const char* name, long v1, long v2, const void* data, long size)
531 {
532     struct reg_value* t;
533     char* c;
534     TRACE("Request to set value %s %d\n", name, *(const int*)data);
535     if(!regs)
536         init_registry();
537
538     c=build_keyname(key, name);
539     if(c==NULL)
540         return 1;
541     insert_reg_value(key, name, v2, data, size);
542     free(c);
543     return 0;
544 }
545
546 long __stdcall RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
547                    LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
548                    LPFILETIME lpftLastWriteTime)
549 {
550     return ERROR_NO_MORE_ITEMS;
551 }