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