Mercurial > mplayer.hg
annotate loader/registry.c @ 16787:c690b2733127
further sync by Emfox Zhou < emfoxzhou == at == gmail == dot == com >
author | diego |
---|---|
date | Mon, 17 Oct 2005 14:37:01 +0000 |
parents | f5537cc95b02 |
children | 0783dd397f74 |
rev | line source |
---|---|
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
1 /* |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
2 * Modified for use with MPlayer, detailed CVS changelog at |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
3 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
4 * $Id$ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
5 */ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
6 |
3465 | 7 #include "config.h" |
1 | 8 |
9 #include <stdio.h> | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
10 #include <stdlib.h> |
1 | 11 #include <fcntl.h> |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
12 #include <unistd.h> |
1 | 13 #include <pwd.h> |
14 #include <sys/types.h> | |
15 | |
7386 | 16 #include "wine/winbase.h" |
17 #include "wine/winreg.h" | |
18 #include "wine/winnt.h" | |
19 #include "wine/winerror.h" | |
1 | 20 |
3465 | 21 #include "ext.h" |
22 #include "registry.h" | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
23 |
128 | 24 //#undef TRACE |
25 //#define TRACE printf | |
3128 | 26 |
4384 | 27 extern char *get_path ( char * ); |
3134 | 28 |
4384 | 29 // ...can be set before init_registry() call |
30 char* regpathname = NULL; | |
3134 | 31 |
4384 | 32 static char* localregpathname = NULL; |
3134 | 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 | |
1 | 42 struct reg_value |
43 { | |
44 int type; | |
45 char* name; | |
46 int len; | |
47 char* value; | |
48 }; | |
49 | |
3134 | 50 static struct reg_value* regs = NULL; |
51 static int reg_size; | |
52 static reg_handle_t* head = NULL; | |
1 | 53 |
54 #define DIR -25 | |
55 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
56 static void create_registry(void); |
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
57 static void open_registry(void); |
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
58 static void save_registry(void); |
3128 | 59 static void init_registry(void); |
1 | 60 |
61 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
62 static void create_registry(void){ |
1 | 63 if(regs) |
64 { | |
65 printf("Logic error: create_registry() called with existing registry\n"); | |
66 save_registry(); | |
67 return; | |
3128 | 68 } |
1 | 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; | |
3134 | 78 head = 0; |
1 | 79 save_registry(); |
80 } | |
3134 | 81 |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
82 static void open_registry(void) |
1 | 83 { |
84 int fd; | |
85 int i; | |
3128 | 86 unsigned int len; |
1 | 87 if(regs) |
88 { | |
89 printf("Multiple open_registry(>\n"); | |
90 return; | |
91 } | |
3134 | 92 fd = open(localregpathname, O_RDONLY); |
3128 | 93 if (fd == -1) |
1 | 94 { |
95 printf("Creating new registry\n"); | |
96 create_registry(); | |
97 return; | |
3128 | 98 } |
1 | 99 read(fd, ®_size, 4); |
100 regs=(struct reg_value*)malloc(reg_size*sizeof(struct reg_value)); | |
3134 | 101 head = 0; |
1 | 102 for(i=0; i<reg_size; i++) |
103 { | |
104 read(fd,®s[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,®s[i].len,4); | |
115 regs[i].value=(char*)malloc(regs[i].len+1); | |
116 if(regs[i].value==0) | |
117 { | |
3134 | 118 free(regs[i].name); |
1 | 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 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
130 static void save_registry(void) |
1 | 131 { |
3128 | 132 int fd, i; |
133 if (!regs) | |
134 init_registry(); | |
3134 | 135 fd = open(localregpathname, O_WRONLY | O_CREAT, 00666); |
3128 | 136 if (fd == -1) |
1 | 137 { |
3128 | 138 printf("Failed to open registry file '%s' for writing.\n", |
3134 | 139 localregpathname); |
3128 | 140 return; |
1 | 141 } |
142 write(fd, ®_size, 4); | |
143 for(i=0; i<reg_size; i++) | |
144 { | |
3128 | 145 unsigned len=strlen(regs[i].name); |
1 | 146 write(fd, ®s[i].type, 4); |
147 write(fd, &len, 4); | |
148 write(fd, regs[i].name, len); | |
149 write(fd, ®s[i].len, 4); | |
150 write(fd, regs[i].value, regs[i].len); | |
151 } | |
152 close(fd); | |
153 } | |
3134 | 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 } | |
3465 | 178 |
179 if (localregpathname && localregpathname != regpathname) | |
3134 | 180 free(localregpathname); |
3465 | 181 localregpathname = 0; |
3134 | 182 } |
183 | |
184 | |
1 | 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; | |
3128 | 216 } |
1 | 217 static int generate_handle() |
218 { | |
7386 | 219 static unsigned int zz=249; |
1 | 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 } | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
263 static struct reg_value* insert_reg_value(int handle, const char* name, int type, const void* value, int len) |
1 | 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)); | |
3134 | 280 //regs=(struct reg_value*)my_realloc(regs, sizeof(struct reg_value)*(reg_size+1)); |
1 | 281 v=regs+reg_size; |
282 reg_size++; | |
283 } | |
284 else | |
285 //replacing old one | |
286 { | |
3134 | 287 free(v->value); |
288 free(v->name); | |
1 | 289 } |
7386 | 290 TRACE("RegInsert '%s' %p v:%d len:%d\n", name, value, *(int*)value, len); |
1 | 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); | |
3134 | 297 free(fullname); |
1 | 298 save_registry(); |
299 return v; | |
300 } | |
301 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
302 static void init_registry(void) |
1 | 303 { |
3128 | 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 | |
3465 | 308 #ifdef MPLAYER |
309 regpathname = get_path("registry"); | |
310 localregpathname = regpathname; | |
3128 | 311 #else |
3465 | 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 | |
3134 | 317 if (localregpathname == 0) |
3128 | 318 { |
3134 | 319 const char* pthn = regpathname; |
320 if (!regpathname) | |
321 { | |
3465 | 322 // avifile - for now reading data from user's home |
3134 | 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"); | |
3128 | 331 } |
340 | 332 #endif |
3128 | 333 |
1 | 334 open_registry(); |
335 insert_handle(HKEY_LOCAL_MACHINE, "HKLM"); | |
336 insert_handle(HKEY_CURRENT_USER, "HKCU"); | |
337 } | |
3128 | 338 |
1 | 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 | |
9965 | 359 long __stdcall RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey) |
1 | 360 { |
361 char* full_name; | |
362 reg_handle_t* t; | |
363 struct reg_value* v; | |
364 TRACE("Opening key %s\n", subkey); | |
3128 | 365 |
1 | 366 if(!regs) |
367 init_registry() | |
3128 | 368 ; |
1 | 369 /* t=find_handle_2(key, subkey); |
3128 | 370 |
1 | 371 if(t==0) |
372 return -1; | |
373 | |
374 if(t==(reg_handle_t*)-1) | |
375 return -1; | |
3128 | 376 */ |
377 full_name=build_keyname(key, subkey); | |
1 | 378 if(!full_name) |
379 return -1; | |
3128 | 380 TRACE("Opening key Fullname %s\n", full_name); |
381 v=find_value_by_name(full_name); | |
1 | 382 |
383 t=insert_handle(generate_handle(), full_name); | |
384 *newkey=t->handle; | |
385 free(full_name); | |
3128 | 386 |
1 | 387 return 0; |
3128 | 388 } |
9965 | 389 long __stdcall RegCloseKey(long key) |
1 | 390 { |
7386 | 391 reg_handle_t *handle; |
392 if(key==(long)HKEY_LOCAL_MACHINE) | |
1 | 393 return 0; |
7386 | 394 if(key==(long)HKEY_CURRENT_USER) |
1 | 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; | |
3128 | 409 } |
410 | |
9965 | 411 long __stdcall RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count) |
1 | 412 { |
7386 | 413 struct reg_value* t; |
414 char* c; | |
415 TRACE("Querying value %s\n", value); | |
416 if(!regs) | |
417 init_registry(); | |
3465 | 418 |
7386 | 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; | |
1 | 437 } |
438 else | |
439 { | |
7386 | 440 *count=t->len; |
441 } | |
1 | 442 return 0; |
3128 | 443 } |
9965 | 444 long __stdcall RegCreateKeyExA(long key, const char* name, long reserved, |
3128 | 445 void* classs, long options, long security, |
446 void* sec_attr, int* newkey, int* status) | |
1 | 447 { |
7386 | 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(); | |
3465 | 454 |
7386 | 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 } | |
1 | 467 |
7386 | 468 t=insert_handle(generate_handle(), fullname); |
469 *newkey=t->handle; | |
470 free(fullname); | |
471 return 0; | |
1 | 472 } |
1416 | 473 |
3128 | 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 | |
9965 | 487 long __stdcall RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, |
1416 | 488 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count) |
489 { | |
3128 | 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) | |
1416 | 495 { |
3128 | 496 struct reg_value* v=find_value_by_name(t->name); |
497 if (v) | |
1416 | 498 { |
3128 | 499 memcpy(data, v->value, (v->len < *count) ? v->len : *count); |
500 if(*count < v->len) | |
501 *count = v->len; | |
502 if (type) | |
1416 | 503 *type = v->type; |
504 //printf("Found handle %s\n", v->name); | |
3128 | 505 return 0; |
1416 | 506 } |
507 } | |
3128 | 508 return ERROR_NO_MORE_ITEMS; |
1416 | 509 } |
510 | |
9965 | 511 long __stdcall RegSetValueExA(long key, const char* name, long v1, long v2, const void* data, long size) |
1 | 512 { |
513 struct reg_value* t; | |
514 char* c; | |
7386 | 515 TRACE("Request to set value %s %d\n", name, *(const int*)data); |
1 | 516 if(!regs) |
3465 | 517 init_registry(); |
518 | |
1 | 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; | |
3128 | 525 } |
3465 | 526 |
9965 | 527 long __stdcall RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName, |
3465 | 528 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass, |
529 LPFILETIME lpftLastWriteTime) | |
530 { | |
531 return ERROR_NO_MORE_ITEMS; | |
532 } |