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