Mercurial > mplayer.hg
annotate loader/registry.c @ 30811:50e0f6942e43
Implement Win32 mutexes.
Implement Win32 mutexes; they used to just be mapped on top of events, which
is not the same thing at all.
The implementation is pretty much the obvious one, similar to the
current critical section implementation and the semaphore implementation;
a single lock count protected by a pthread mutex, and an event lockers can
sleep on to know when the mutex is available.
Also make CreateMutexA and ReleaseMutex available even if QuickTime codecs
support is not configured.
author | sesse |
---|---|
date | Sat, 06 Mar 2010 10:13:37 +0000 |
parents | 9fc9d1e788aa |
children | 76a13038105e |
rev | line source |
---|---|
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
1 /* |
18783 | 2 * Modified for use with MPlayer, detailed changelog at |
3 * http://svn.mplayerhq.hu/mplayer/trunk/ | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
4 */ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
9965
diff
changeset
|
5 |
3465 | 6 #include "config.h" |
21261
a2e02e6b6379
Rename config.h --> debug.h and include config.h explicitly.
diego
parents:
18889
diff
changeset
|
7 #include "debug.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 |
28233
bfb8ccb245a9
#include the appropriate header instead of using local declarations.
diego
parents:
28051
diff
changeset
|
24 #include "get_path.h" |
bfb8ccb245a9
#include the appropriate header instead of using local declarations.
diego
parents:
28051
diff
changeset
|
25 |
128 | 26 //#undef TRACE |
27 //#define TRACE printf | |
3128 | 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 } |
18878 | 69 regs=malloc(3*sizeof(struct reg_value)); |
1 | 70 regs[0].type=regs[1].type=DIR; |
18878 | 71 regs[0].name=malloc(5); |
1 | 72 strcpy(regs[0].name, "HKLM"); |
18878 | 73 regs[1].name=malloc(5); |
1 | 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); |
18878 | 100 regs=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); | |
18878 | 106 regs[i].name=malloc(len+1); |
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); | |
18878 | 115 regs[i].value=malloc(regs[i].len+1); |
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 | |
25807
3cd1d60e7225
Disable unused functions find_handle_2, find_handle_by_name, fixes the warning:
diego
parents:
24387
diff
changeset
|
185 #if 0 |
1 | 186 static reg_handle_t* find_handle_by_name(const char* name) |
187 { | |
188 reg_handle_t* t; | |
189 for(t=head; t; t=t->prev) | |
190 { | |
191 if(!strcmp(t->name, name)) | |
192 { | |
193 return t; | |
194 } | |
195 } | |
196 return 0; | |
197 } | |
25807
3cd1d60e7225
Disable unused functions find_handle_2, find_handle_by_name, fixes the warning:
diego
parents:
24387
diff
changeset
|
198 #endif |
1 | 199 static struct reg_value* find_value_by_name(const char* name) |
200 { | |
201 int i; | |
202 for(i=0; i<reg_size; i++) | |
203 if(!strcmp(regs[i].name, name)) | |
204 return regs+i; | |
205 return 0; | |
206 } | |
207 static reg_handle_t* find_handle(int handle) | |
208 { | |
209 reg_handle_t* t; | |
210 for(t=head; t; t=t->prev) | |
211 { | |
212 if(t->handle==handle) | |
213 { | |
214 return t; | |
215 } | |
216 } | |
217 return 0; | |
3128 | 218 } |
29212
eda346733b8c
Add missing 'void' to parameterless function declarations.
diego
parents:
28233
diff
changeset
|
219 static int generate_handle(void) |
1 | 220 { |
7386 | 221 static unsigned int zz=249; |
1 | 222 zz++; |
223 while((zz==HKEY_LOCAL_MACHINE) || (zz==HKEY_CURRENT_USER)) | |
224 zz++; | |
225 return zz; | |
226 } | |
227 | |
228 static reg_handle_t* insert_handle(long handle, const char* name) | |
229 { | |
230 reg_handle_t* t; | |
18878 | 231 t=malloc(sizeof(reg_handle_t)); |
1 | 232 if(head==0) |
233 { | |
234 t->prev=0; | |
235 } | |
236 else | |
237 { | |
238 head->next=t; | |
239 t->prev=head; | |
240 } | |
241 t->next=0; | |
18878 | 242 t->name=malloc(strlen(name)+1); |
1 | 243 strcpy(t->name, name); |
244 t->handle=handle; | |
245 head=t; | |
246 return t; | |
247 } | |
248 static char* build_keyname(long key, const char* subkey) | |
249 { | |
250 char* full_name; | |
251 reg_handle_t* t; | |
252 if((t=find_handle(key))==0) | |
253 { | |
254 TRACE("Invalid key\n"); | |
255 return NULL; | |
256 } | |
257 if(subkey==NULL) | |
258 subkey="<default>"; | |
18878 | 259 full_name=malloc(strlen(t->name)+strlen(subkey)+10); |
1 | 260 strcpy(full_name, t->name); |
261 strcat(full_name, "\\"); | |
262 strcat(full_name, subkey); | |
263 return full_name; | |
264 } | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
265 static struct reg_value* insert_reg_value(int handle, const char* name, int type, const void* value, int len) |
1 | 266 { |
267 struct reg_value* v; | |
268 char* fullname; | |
269 if((fullname=build_keyname(handle, name))==NULL) | |
270 { | |
271 TRACE("Invalid handle\n"); | |
272 return NULL; | |
273 } | |
274 | |
275 if((v=find_value_by_name(fullname))==0) | |
276 //creating new value in registry | |
277 { | |
278 if(regs==0) | |
279 create_registry(); | |
30702 | 280 regs = realloc(regs, sizeof(struct reg_value) * (reg_size +1 )); |
3134 | 281 //regs=(struct reg_value*)my_realloc(regs, sizeof(struct reg_value)*(reg_size+1)); |
1 | 282 v=regs+reg_size; |
283 reg_size++; | |
284 } | |
285 else | |
286 //replacing old one | |
287 { | |
3134 | 288 free(v->value); |
289 free(v->name); | |
1 | 290 } |
7386 | 291 TRACE("RegInsert '%s' %p v:%d len:%d\n", name, value, *(int*)value, len); |
1 | 292 v->type=type; |
293 v->len=len; | |
18878 | 294 v->value=malloc(len); |
1 | 295 memcpy(v->value, value, len); |
18878 | 296 v->name=malloc(strlen(fullname)+1); |
1 | 297 strcpy(v->name, fullname); |
3134 | 298 free(fullname); |
1 | 299 save_registry(); |
300 return v; | |
301 } | |
302 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
340
diff
changeset
|
303 static void init_registry(void) |
1 | 304 { |
3128 | 305 TRACE("Initializing registry\n"); |
306 // can't be free-ed - it's static and probably thread | |
307 // unsafe structure which is stored in glibc | |
308 | |
3465 | 309 regpathname = get_path("registry"); |
310 localregpathname = regpathname; | |
3128 | 311 |
1 | 312 open_registry(); |
313 insert_handle(HKEY_LOCAL_MACHINE, "HKLM"); | |
314 insert_handle(HKEY_CURRENT_USER, "HKCU"); | |
315 } | |
3128 | 316 |
25807
3cd1d60e7225
Disable unused functions find_handle_2, find_handle_by_name, fixes the warning:
diego
parents:
24387
diff
changeset
|
317 #if 0 |
1 | 318 static reg_handle_t* find_handle_2(long key, const char* subkey) |
319 { | |
320 char* full_name; | |
321 reg_handle_t* t; | |
322 if((t=find_handle(key))==0) | |
323 { | |
324 TRACE("Invalid key\n"); | |
325 return (reg_handle_t*)-1; | |
326 } | |
327 if(subkey==NULL) | |
328 return t; | |
18878 | 329 full_name=malloc(strlen(t->name)+strlen(subkey)+10); |
1 | 330 strcpy(full_name, t->name); |
331 strcat(full_name, "\\"); | |
332 strcat(full_name, subkey); | |
333 t=find_handle_by_name(full_name); | |
334 free(full_name); | |
335 return t; | |
336 } | |
25807
3cd1d60e7225
Disable unused functions find_handle_2, find_handle_by_name, fixes the warning:
diego
parents:
24387
diff
changeset
|
337 #endif |
1 | 338 |
9965 | 339 long __stdcall RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey) |
1 | 340 { |
341 char* full_name; | |
342 reg_handle_t* t; | |
343 struct reg_value* v; | |
344 TRACE("Opening key %s\n", subkey); | |
3128 | 345 |
1 | 346 if(!regs) |
347 init_registry() | |
3128 | 348 ; |
1 | 349 /* t=find_handle_2(key, subkey); |
3128 | 350 |
1 | 351 if(t==0) |
352 return -1; | |
353 | |
354 if(t==(reg_handle_t*)-1) | |
355 return -1; | |
3128 | 356 */ |
357 full_name=build_keyname(key, subkey); | |
1 | 358 if(!full_name) |
359 return -1; | |
3128 | 360 TRACE("Opening key Fullname %s\n", full_name); |
361 v=find_value_by_name(full_name); | |
1 | 362 |
363 t=insert_handle(generate_handle(), full_name); | |
364 *newkey=t->handle; | |
365 free(full_name); | |
3128 | 366 |
1 | 367 return 0; |
3128 | 368 } |
9965 | 369 long __stdcall RegCloseKey(long key) |
1 | 370 { |
7386 | 371 reg_handle_t *handle; |
372 if(key==(long)HKEY_LOCAL_MACHINE) | |
1 | 373 return 0; |
7386 | 374 if(key==(long)HKEY_CURRENT_USER) |
1 | 375 return 0; |
376 handle=find_handle(key); | |
377 if(handle==0) | |
378 return 0; | |
379 if(handle->prev) | |
380 handle->prev->next=handle->next; | |
381 if(handle->next) | |
382 handle->next->prev=handle->prev; | |
383 if(handle->name) | |
384 free(handle->name); | |
385 if(handle==head) | |
386 head=head->prev; | |
387 free(handle); | |
30219
f08c45c46433
Fix RegCloseKey to not return an error on success.
reimar
parents:
29212
diff
changeset
|
388 return 0; |
3128 | 389 } |
390 | |
9965 | 391 long __stdcall RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count) |
1 | 392 { |
7386 | 393 struct reg_value* t; |
394 char* c; | |
395 TRACE("Querying value %s\n", value); | |
396 if(!regs) | |
397 init_registry(); | |
3465 | 398 |
7386 | 399 c=build_keyname(key, value); |
400 if (!c) | |
401 return 1; | |
402 t=find_value_by_name(c); | |
403 free(c); | |
404 if (t==0) | |
405 return 2; | |
406 if (type) | |
407 *type=t->type; | |
408 if (data) | |
409 { | |
410 memcpy(data, t->value, (t->len<*count)?t->len:*count); | |
411 TRACE("returning %d bytes: %d\n", t->len, *(int*)data); | |
412 } | |
413 if(*count<t->len) | |
414 { | |
415 *count=t->len; | |
416 return ERROR_MORE_DATA; | |
1 | 417 } |
418 else | |
419 { | |
7386 | 420 *count=t->len; |
421 } | |
1 | 422 return 0; |
3128 | 423 } |
9965 | 424 long __stdcall RegCreateKeyExA(long key, const char* name, long reserved, |
3128 | 425 void* classs, long options, long security, |
426 void* sec_attr, int* newkey, int* status) | |
1 | 427 { |
7386 | 428 reg_handle_t* t; |
429 char* fullname; | |
430 struct reg_value* v; | |
431 // TRACE("Creating/Opening key %s\n", name); | |
432 if(!regs) | |
433 init_registry(); | |
3465 | 434 |
7386 | 435 fullname=build_keyname(key, name); |
436 if (!fullname) | |
437 return 1; | |
438 TRACE("Creating/Opening key %s\n", fullname); | |
439 v=find_value_by_name(fullname); | |
440 if(v==0) | |
441 { | |
442 int qw=45708; | |
443 v=insert_reg_value(key, name, DIR, &qw, 4); | |
444 if (status) *status=REG_CREATED_NEW_KEY; | |
445 // return 0; | |
446 } | |
1 | 447 |
7386 | 448 t=insert_handle(generate_handle(), fullname); |
449 *newkey=t->handle; | |
450 free(fullname); | |
451 return 0; | |
1 | 452 } |
1416 | 453 |
3128 | 454 /* |
455 LONG RegEnumValue( | |
456 HKEY hKey, // handle to key to query | |
457 DWORD dwIndex, // index of value to query | |
458 LPTSTR lpValueName, // address of buffer for value string | |
459 LPDWORD lpcbValueName, // address for size of value buffer | |
460 LPDWORD lpReserved, // reserved | |
461 LPDWORD lpType, // address of buffer for type code | |
462 LPBYTE lpData, // address of buffer for value data | |
463 LPDWORD lpcbData // address for size of data buffer | |
464 ); | |
465 */ | |
466 | |
9965 | 467 long __stdcall RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, |
1416 | 468 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count) |
469 { | |
3128 | 470 // currenly just made to support MSZH & ZLIB |
471 //printf("Reg Enum 0x%x %d %s %d data: %p %d %d >%s<\n", hkey, index, | |
472 // value, *val_count, data, *count, reg_size, data); | |
473 reg_handle_t* t = find_handle(hkey); | |
474 if (t && index < 10) | |
1416 | 475 { |
3128 | 476 struct reg_value* v=find_value_by_name(t->name); |
477 if (v) | |
1416 | 478 { |
3128 | 479 memcpy(data, v->value, (v->len < *count) ? v->len : *count); |
480 if(*count < v->len) | |
481 *count = v->len; | |
482 if (type) | |
1416 | 483 *type = v->type; |
484 //printf("Found handle %s\n", v->name); | |
3128 | 485 return 0; |
1416 | 486 } |
487 } | |
3128 | 488 return ERROR_NO_MORE_ITEMS; |
1416 | 489 } |
490 | |
9965 | 491 long __stdcall RegSetValueExA(long key, const char* name, long v1, long v2, const void* data, long size) |
1 | 492 { |
493 char* c; | |
7386 | 494 TRACE("Request to set value %s %d\n", name, *(const int*)data); |
1 | 495 if(!regs) |
3465 | 496 init_registry(); |
497 | |
1 | 498 c=build_keyname(key, name); |
499 if(c==NULL) | |
500 return 1; | |
501 insert_reg_value(key, name, v2, data, size); | |
502 free(c); | |
503 return 0; | |
3128 | 504 } |
3465 | 505 |
9965 | 506 long __stdcall RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName, |
3465 | 507 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass, |
508 LPFILETIME lpftLastWriteTime) | |
509 { | |
510 return ERROR_NO_MORE_ITEMS; | |
511 } |