- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[wine] / dlls / ntdll / rtl.c
1 /*
2  * NT basis DLL
3  * 
4  * This file contains the Rtl* API functions. These should be implementable.
5  * 
6  * Copyright 1996-1998 Marcus Meissner
7  *                1999 Alex Korobka
8  */
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <ctype.h>
14 #include <math.h>
15 #include "windef.h"
16 #include "winbase.h"
17 #include "wine/winestring.h"
18 #include "file.h"
19 #include "stackframe.h"
20 #include "winnls.h"
21 #include "ntdll.h"
22 #include "debugstr.h"
23 #include "heap.h"
24 #include "ntdef.h"
25 #include "winreg.h"
26
27 #include "debug.h"
28
29 /* fixme: move to windef.h*/
30 typedef BOOL32 *LPBOOL;   
31 /**************************************************************************
32  *                 RtlLengthRequiredSid                 [NTDLL.427]
33  */
34 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
35 {
36         return sizeof(DWORD)*nrofsubauths+sizeof(SID);
37 }
38
39 /**************************************************************************
40  *                 RtlLengthSid                         [NTDLL.429]
41  */
42 DWORD WINAPI RtlLengthSid(PSID sid)
43 {       TRACE(ntdll,"sid=%p\n",sid);
44         if (!sid)
45           return FALSE; 
46         return sizeof(DWORD)*sid->SubAuthorityCount+sizeof(SID);
47 }
48
49 /**************************************************************************
50  *                 RtlCreateAcl                         [NTDLL.306]
51  *
52  * NOTES
53  *    This should return NTSTATUS
54  */
55 DWORD WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
56 {
57         if (rev!=ACL_REVISION)
58                 return STATUS_INVALID_PARAMETER;
59         if (size<sizeof(ACL))
60                 return STATUS_BUFFER_TOO_SMALL;
61         if (size>0xFFFF)
62                 return STATUS_INVALID_PARAMETER;
63
64         memset(acl,'\0',sizeof(ACL));
65         acl->AclRevision        = rev;
66         acl->AclSize            = size;
67         acl->AceCount           = 0;
68         return 0;
69 }
70
71 /**************************************************************************
72  *                 RtlFirstFreeAce                      [NTDLL.370]
73  * looks for the AceCount+1 ACE, and if it is still within the alloced
74  * ACL, return a pointer to it
75  */
76 BOOL32 WINAPI RtlFirstFreeAce(
77         PACL acl,
78         LPACE_HEADER *x)
79 {
80         LPACE_HEADER    ace;
81         int             i;
82
83         *x = 0;
84         ace = (LPACE_HEADER)(acl+1);
85         for (i=0;i<acl->AceCount;i++) {
86                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
87                         return 0;
88                 ace = (LPACE_HEADER)(((BYTE*)ace)+ace->AceSize);
89         }
90         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
91                 return 0;
92         *x = ace;
93         return 1;
94 }
95
96 /**************************************************************************
97  *                 RtlAddAce                            [NTDLL.260]
98  */
99 NTSTATUS WINAPI RtlAddAce(
100         PACL acl,
101         DWORD rev,
102         DWORD xnrofaces,
103         LPACE_HEADER acestart,
104         DWORD acelen)
105 {
106         LPACE_HEADER    ace,targetace;
107         int             nrofaces;
108
109         if (acl->AclRevision != ACL_REVISION)
110                 return STATUS_INVALID_PARAMETER;
111         if (!RtlFirstFreeAce(acl,&targetace))
112                 return STATUS_INVALID_PARAMETER;
113         nrofaces=0;ace=acestart;
114         while (((DWORD)ace-(DWORD)acestart)<acelen) {
115                 nrofaces++;
116                 ace = (LPACE_HEADER)(((BYTE*)ace)+ace->AceSize);
117         }
118         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
119                 return STATUS_INVALID_PARAMETER;
120         memcpy((LPBYTE)targetace,acestart,acelen);
121         acl->AceCount+=nrofaces;
122         return STATUS_SUCCESS;
123 }
124
125 /**************************************************************************
126  *                 RtlCreateSecurityDescriptor          [NTDLL.313]
127  *
128  * RETURNS:
129  *  0 success, 
130  *  STATUS_INVALID_OWNER, STATUS_PRIVILEGE_NOT_HELD, STATUS_NO_INHERITANCE,
131  *  STATUS_NO_MEMORY 
132  */
133 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
134         PSECURITY_DESCRIPTOR lpsd,
135         DWORD rev)
136 {
137         if (rev!=SECURITY_DESCRIPTOR_REVISION)
138                 return STATUS_UNKNOWN_REVISION;
139         memset(lpsd,'\0',sizeof(*lpsd));
140         lpsd->Revision = SECURITY_DESCRIPTOR_REVISION;
141         return STATUS_SUCCESS;
142 }
143
144 /**************************************************************************
145  *                 RtlSetDaclSecurityDescriptor         [NTDLL.483]
146  */
147 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
148         PSECURITY_DESCRIPTOR lpsd,
149         BOOL32 daclpresent,
150         PACL dacl,
151         BOOL32 dacldefaulted )
152 {
153         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
154                 return STATUS_UNKNOWN_REVISION;
155         if (lpsd->Control & SE_SELF_RELATIVE)
156                 return STATUS_INVALID_SECURITY_DESCR;
157         if (!daclpresent) 
158         {       lpsd->Control &= ~SE_DACL_PRESENT;
159                 return TRUE;
160         }
161         lpsd->Control |= SE_DACL_PRESENT;
162         lpsd->Dacl = dacl;
163         if (dacldefaulted)
164                 lpsd->Control |= SE_DACL_DEFAULTED;
165         else
166                 lpsd->Control &= ~SE_DACL_DEFAULTED;
167
168         return STATUS_SUCCESS;
169 }
170
171 /**************************************************************************
172  *                 RtlSetSaclSecurityDescriptor         [NTDLL.488]
173  */
174 DWORD  WINAPI RtlSetSaclSecurityDescriptor (
175         PSECURITY_DESCRIPTOR lpsd,
176         BOOL32 saclpresent,
177         PACL sacl,
178         BOOL32 sacldefaulted)
179 {
180         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
181                 return STATUS_UNKNOWN_REVISION;
182         if (lpsd->Control & SE_SELF_RELATIVE)
183                 return STATUS_INVALID_SECURITY_DESCR;
184         if (!saclpresent) {
185                 lpsd->Control &= ~SE_SACL_PRESENT;
186                 return 0;
187         }
188         lpsd->Control |= SE_SACL_PRESENT;
189         lpsd->Sacl = sacl;
190         if (sacldefaulted)
191                 lpsd->Control |= SE_SACL_DEFAULTED;
192         else
193                 lpsd->Control &= ~SE_SACL_DEFAULTED;
194         return STATUS_SUCCESS;
195 }
196
197 /**************************************************************************
198  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.487]
199  */
200 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
201         PSECURITY_DESCRIPTOR lpsd,
202         PSID owner,
203         BOOL32 ownerdefaulted)
204 {
205         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
206                 return STATUS_UNKNOWN_REVISION;
207         if (lpsd->Control & SE_SELF_RELATIVE)
208                 return STATUS_INVALID_SECURITY_DESCR;
209
210         lpsd->Owner = owner;
211         if (ownerdefaulted)
212                 lpsd->Control |= SE_OWNER_DEFAULTED;
213         else
214                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
215         return STATUS_SUCCESS;
216 }
217
218 /**************************************************************************
219  *                 RtlSetGroupSecurityDescriptor                [NTDLL.485]
220  */
221 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
222         PSECURITY_DESCRIPTOR lpsd,
223         PSID group,
224         BOOL32 groupdefaulted)
225 {
226         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
227                 return STATUS_UNKNOWN_REVISION;
228         if (lpsd->Control & SE_SELF_RELATIVE)
229                 return STATUS_INVALID_SECURITY_DESCR;
230
231         lpsd->Group = group;
232         if (groupdefaulted)
233                 lpsd->Control |= SE_GROUP_DEFAULTED;
234         else
235                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
236         return STATUS_SUCCESS;
237 }
238
239
240 /**************************************************************************
241  *                 RtlNormalizeProcessParams            [NTDLL.441]
242  */
243 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
244 {
245     FIXME(ntdll,"(%p), stub\n",x);
246     return x;
247 }
248
249 /**************************************************************************
250  *                 RtlInitializeSid                     [NTDLL.410]
251  */
252 DWORD WINAPI RtlInitializeSid(PSID PSID,PSID_IDENTIFIER_AUTHORITY PSIDauth,
253                               DWORD c)
254 {
255         BYTE    a = c&0xff;
256
257         if (a>=SID_MAX_SUB_AUTHORITIES)
258                 return a;
259         PSID->SubAuthorityCount = a;
260         PSID->Revision           = SID_REVISION;
261         memcpy(&(PSID->IdentifierAuthority),PSIDauth,sizeof(SID_IDENTIFIER_AUTHORITY));
262         return STATUS_SUCCESS;
263 }
264
265 /**************************************************************************
266  *                 RtlSubAuthoritySid                   [NTDLL.497]
267  */
268 LPDWORD WINAPI RtlSubAuthoritySid(PSID PSID,DWORD nr)
269 {
270         return &(PSID->SubAuthority[nr]);
271 }
272
273 /**************************************************************************
274  *                 RtlSubAuthorityCountSid              [NTDLL.496]
275  */
276 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID PSID)
277 {
278         return ((LPBYTE)PSID)+1;
279 }
280
281 /**************************************************************************
282  *                 RtlCopySid                           [NTDLL.302]
283  */
284 DWORD WINAPI RtlCopySid(DWORD len,PSID to,PSID from)
285 {       if (!from)
286                 return 0;
287         if (len<(from->SubAuthorityCount*4+8))
288                 return STATUS_BUFFER_TOO_SMALL;
289         memmove(to,from,from->SubAuthorityCount*4+8);
290         return STATUS_SUCCESS;
291 }
292
293 /**************************************************************************
294  *                 RtlAnsiStringToUnicodeString         [NTDLL.269]
295  */
296 DWORD /* NTSTATUS */ 
297 WINAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING uni,PANSI_STRING ansi,BOOL32 doalloc)
298 {
299         DWORD   unilen = (ansi->Length+1)*sizeof(WCHAR);
300
301         if (unilen>0xFFFF)
302                 return STATUS_INVALID_PARAMETER_2;
303         uni->Length = unilen;
304         if (doalloc) {
305                 uni->MaximumLength = unilen;
306                 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,unilen);
307                 if (!uni->Buffer)
308                         return STATUS_NO_MEMORY;
309         }
310         if (unilen>uni->MaximumLength)
311                 return STATUS_BUFFER_OVERFLOW;
312         lstrcpynAtoW(uni->Buffer,ansi->Buffer,unilen/2);
313         return STATUS_SUCCESS;
314 }
315
316 /**************************************************************************
317  *                 RtlOemStringToUnicodeString          [NTDLL.447]
318  */
319 DWORD /* NTSTATUS */ 
320 WINAPI RtlOemStringToUnicodeString(PUNICODE_STRING uni,PSTRING ansi,BOOL32 doalloc)
321 {
322         DWORD   unilen = (ansi->Length+1)*sizeof(WCHAR);
323
324         if (unilen>0xFFFF)
325                 return STATUS_INVALID_PARAMETER_2;
326         uni->Length = unilen;
327         if (doalloc) {
328                 uni->MaximumLength = unilen;
329                 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,unilen);
330                 if (!uni->Buffer)
331                         return STATUS_NO_MEMORY;
332         }
333         if (unilen>uni->MaximumLength)
334                 return STATUS_BUFFER_OVERFLOW;
335         lstrcpynAtoW(uni->Buffer,ansi->Buffer,unilen/2);
336         return STATUS_SUCCESS;
337 }
338 /**************************************************************************
339  *                 RtlMultiByteToUnicodeN               [NTDLL.436]
340  * FIXME: multibyte support
341  */
342 DWORD /* NTSTATUS */ 
343 WINAPI RtlMultiByteToUnicodeN(LPWSTR unistr,DWORD unilen,LPDWORD reslen,LPSTR oemstr,DWORD oemlen)
344 {
345         DWORD   len;
346         LPWSTR  x;
347
348         len = oemlen;
349         if (unilen/2 < len)
350                 len = unilen/2;
351         x=(LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
352         lstrcpynAtoW(x,oemstr,len+1);
353         memcpy(unistr,x,len*2);
354         if (reslen) *reslen = len*2;
355         return 0;
356 }
357
358 /**************************************************************************
359  *                 RtlOemToUnicodeN                     [NTDLL.448]
360  */
361 DWORD /* NTSTATUS */ 
362 WINAPI RtlOemToUnicodeN(LPWSTR unistr,DWORD unilen,LPDWORD reslen,LPSTR oemstr,DWORD oemlen)
363 {
364         DWORD   len;
365         LPWSTR  x;
366
367         len = oemlen;
368         if (unilen/2 < len)
369                 len = unilen/2;
370         x=(LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
371         lstrcpynAtoW(x,oemstr,len+1);
372         memcpy(unistr,x,len*2);
373         if (reslen) *reslen = len*2;
374         return 0;
375 }
376
377 /**************************************************************************
378  *                 RtlInitAnsiString                    [NTDLL.399]
379  */
380 VOID WINAPI RtlInitAnsiString(PANSI_STRING target,LPCSTR source)
381 {
382         target->Length = target->MaximumLength = 0;
383         target->Buffer = (LPSTR)source;
384         if (!source)
385                 return;
386         target->MaximumLength = lstrlen32A(target->Buffer);
387         target->Length = target->MaximumLength+1;
388 }
389 /**************************************************************************
390  *                 RtlInitString                        [NTDLL.402]
391  */
392 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
393 {
394         target->Length = target->MaximumLength = 0;
395         target->Buffer = (LPSTR)source;
396         if (!source)
397                 return;
398         target->MaximumLength = lstrlen32A(target->Buffer);
399         target->Length = target->MaximumLength+1;
400 }
401
402 /**************************************************************************
403  *                 RtlInitUnicodeString                 [NTDLL.403]
404  */
405 VOID WINAPI RtlInitUnicodeString(PUNICODE_STRING target,LPCWSTR source)
406 {
407         target->Length = target->MaximumLength = 0;
408         target->Buffer = (LPWSTR)source;
409         if (!source)
410                 return;
411         target->MaximumLength = lstrlen32W(target->Buffer)*2;
412         target->Length = target->MaximumLength+2;
413 }
414
415 /**************************************************************************
416  *                 RtlFreeUnicodeString                 [NTDLL.377]
417  */
418 VOID WINAPI RtlFreeUnicodeString(PUNICODE_STRING str)
419 {
420         if (str->Buffer)
421                 HeapFree(GetProcessHeap(),0,str->Buffer);
422 }
423
424 /**************************************************************************
425  * RtlFreeAnsiString [NTDLL.373]
426  */
427 VOID WINAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
428 {
429     if( AnsiString->Buffer )
430         HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
431 }
432
433
434 /**************************************************************************
435  *                 RtlUnicodeToOemN                     [NTDLL.515]
436  */
437 DWORD /* NTSTATUS */ 
438 WINAPI RtlUnicodeToOemN(LPSTR oemstr,DWORD oemlen,LPDWORD reslen,LPWSTR unistr,DWORD unilen)
439 {
440         DWORD   len;
441         LPSTR   x;
442
443         len = oemlen;
444         if (unilen/2 < len)
445                 len = unilen/2;
446         x=(LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+1);
447         lstrcpynWtoA(x,unistr,len+1);
448         memcpy(oemstr,x,len);
449         if (reslen) *reslen = len;
450         return 0;
451 }
452
453 /**************************************************************************
454  *                 RtlUnicodeStringToOemString          [NTDLL.511]
455  */
456 DWORD /* NTSTATUS */ 
457 WINAPI RtlUnicodeStringToOemString(PANSI_STRING oem,PUNICODE_STRING uni,BOOL32 alloc)
458 {
459         if (alloc) {
460                 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
461                 oem->MaximumLength = uni->Length/2+1;
462         }
463         oem->Length = uni->Length/2;
464         lstrcpynWtoA(oem->Buffer,uni->Buffer,uni->Length/2+1);
465         return 0;
466 }
467
468 /**************************************************************************
469  *                 RtlUnicodeStringToAnsiString         [NTDLL.507]
470  */
471 DWORD /* NTSTATUS */ 
472 WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING oem,PUNICODE_STRING uni,BOOL32 alloc)
473 {
474         if (alloc) {
475                 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
476                 oem->MaximumLength = uni->Length/2+1;
477         }
478         oem->Length = uni->Length/2;
479         lstrcpynWtoA(oem->Buffer,uni->Buffer,uni->Length/2+1);
480         return 0;
481 }
482
483 /**************************************************************************
484  *                 RtlEqualUnicodeString                [NTDLL]
485  */
486 DWORD WINAPI RtlEqualUnicodeString(PUNICODE_STRING s1,PUNICODE_STRING s2,DWORD x) {
487         FIXME(ntdll,"(%s,%s,%ld),stub!\n",debugstr_w(s1->Buffer),debugstr_w(s2->Buffer),x);
488         return 0;
489         if (s1->Length != s2->Length)
490                 return 1;
491         return !lstrncmp32W(s1->Buffer,s2->Buffer,s1->Length/2);
492 }
493
494 /**************************************************************************
495  *                 RtlNtStatusToDosErro                 [NTDLL.442]
496  */
497 DWORD WINAPI RtlNtStatusToDosError(DWORD error)
498 {
499     FIXME(ntdll, "(%lx): map STATUS_ to ERROR_\n",error);
500     return error;
501 }
502
503 /**************************************************************************
504  *                 RtlGetNtProductType                  [NTDLL.390]
505  */
506 BOOL32 WINAPI RtlGetNtProductType(LPDWORD type)
507 {
508     FIXME(ntdll, "(%p): stub\n", type);
509     *type=3; /* dunno. 1 for client, 3 for server? */
510     return 1;
511 }
512
513 /**************************************************************************
514  *                 RtlUpcaseUnicodeString               [NTDLL.520]
515  */
516 DWORD WINAPI RtlUpcaseUnicodeString(PUNICODE_STRING dest,PUNICODE_STRING src,BOOL32 doalloc)
517 {
518         LPWSTR  s,t;
519         DWORD   i,len;
520
521         len = src->Length;
522         if (doalloc) {
523                 dest->MaximumLength = len; 
524                 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len);
525                 if (!dest->Buffer)
526                         return STATUS_NO_MEMORY;
527
528         }
529         if (dest->MaximumLength < len)
530                 return STATUS_BUFFER_OVERFLOW;
531         s=dest->Buffer;t=src->Buffer;
532         /* len is in bytes */
533         for (i=0;i<len/2;i++)
534                 s[i] = towupper(t[i]);
535         return STATUS_SUCCESS;
536 }
537
538 /**************************************************************************
539  *                 RtlxOemStringToUnicodeSize           [NTDLL.549]
540  */
541 UINT32 WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
542 {
543         return str->Length*2+2;
544 }
545
546 /**************************************************************************
547  *                 RtlxAnsiStringToUnicodeSize          [NTDLL.548]
548  */
549 UINT32 WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
550 {
551         return str->Length*2+2;
552 }
553
554 /**************************************************************************
555  *                 RtlIsTextUnicode                     [NTDLL.417]
556  *
557  *      Apply various feeble heuristics to guess whether
558  *      the text buffer contains Unicode.
559  *      FIXME: should implement more tests.
560  */
561 DWORD WINAPI RtlIsTextUnicode(LPVOID buf, DWORD len, DWORD *pf)
562 {
563         LPWSTR s = buf;
564         DWORD flags = -1, out_flags = 0;
565
566         if (!len)
567                 goto out;
568         if (pf)
569                 flags = *pf;
570         /*
571          * Apply various tests to the text string. According to the
572          * docs, each test "passed" sets the corresponding flag in
573          * the output flags. But some of the tests are mutually
574          * exclusive, so I don't see how you could pass all tests ...
575          */
576
577         /* Check for an odd length ... pass if even. */
578         if (!(len & 1))
579                 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
580
581         /* Check for the special unicode marker byte. */
582         if (*s == 0xFEFF)
583                 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
584
585         /*
586          * Check whether the string passed all of the tests.
587          */
588         flags &= ITU_IMPLEMENTED_TESTS;
589         if ((out_flags & flags) != flags)
590                 len = 0;
591 out:
592         if (pf)
593                 *pf = out_flags;
594         return len;
595 }
596
597 /**************************************************************************
598  *                 RtlDosPathNameToNtPathName_U         [NTDLL.338]
599  *
600  * FIXME: convert to UNC or whatever is expected here
601  */
602 BOOL32  WINAPI RtlDosPathNameToNtPathName_U(
603         LPWSTR from,PUNICODE_STRING us,DWORD x2,DWORD x3)
604 {
605         LPSTR   fromA = HEAP_strdupWtoA(GetProcessHeap(),0,from);
606
607         FIXME(ntdll,"(%s,%p,%08lx,%08lx)\n",fromA,us,x2,x3);
608         if (us)
609                 RtlInitUnicodeString(us,HEAP_strdupW(GetProcessHeap(),0,from));
610         return TRUE;
611 }
612
613 /**************************************************************************
614  *                 NTDLL_chkstk                         [NTDLL.862]
615  *                 NTDLL_alloca_probe                           [NTDLL.861]
616  * Glorified "enter xxxx".
617  */
618 REGS_ENTRYPOINT(NTDLL_chkstk)
619 {
620     ESP_reg(context) -= EAX_reg(context);
621 }
622 REGS_ENTRYPOINT(NTDLL_alloca_probe)
623 {
624     ESP_reg(context) -= EAX_reg(context);
625 }
626
627 /******************************************************************************
628  * RtlTimeToElapsedTimeFields [NTDLL.502]
629  */
630 DWORD WINAPI RtlTimeToElapsedTimeFields( DWORD x1, DWORD x2 )
631 {
632     FIXME(ntdll,"(%lx,%lx): stub\n",x1,x2);
633     return 0;
634 }
635
636
637 /******************************************************************************
638  * RtlExtendedLargeIntegerDivide [NTDLL.359]
639  */
640 INT32 WINAPI RtlExtendedLargeIntegerDivide(
641         LARGE_INTEGER dividend,
642         DWORD divisor,
643         LPDWORD rest
644 ) {
645 #if SIZEOF_LONG_LONG==8
646         long long x1 = *(long long*)&dividend;
647
648         if (*rest)
649                 *rest = x1 % divisor;
650         return x1/divisor;
651 #else
652         FIXME(ntdll,"((%d<<32)+%d,%d,%p), implement this using normal integer arithmetic!\n",dividend.HighPart,dividend.LowPart,divisor,rest);
653         return 0;
654 #endif
655 }
656
657 /******************************************************************************
658  * RtlExtendedLargeIntegerMultiply [NTDLL.359]
659  * Note: This even works, since gcc returns 64bit values in eax/edx just like
660  * the caller expects. However... The relay code won't grok this I think.
661  */
662 long long /*LARGE_INTEGER*/ 
663 WINAPI RtlExtendedIntegerMultiply(
664         LARGE_INTEGER factor1,INT32 factor2
665 ) {
666 #if SIZEOF_LONG_LONG==8
667         return (*(long long*)&factor1)*factor2;
668 #else
669         FIXME(ntdll,"((%d<<32)+%d,%ld), implement this using normal integer arithmetic!\n",factor1.HighPart,factor1.LowPart,factor2);
670         return 0;
671 #endif
672 }
673
674 /******************************************************************************
675  *  RtlFormatCurrentUserKeyPath         [NTDLL.371] 
676  */
677 DWORD WINAPI RtlFormatCurrentUserKeyPath(DWORD x)
678 {
679     FIXME(ntdll,"(0x%08lx): stub\n",x);
680     return 1;
681 }
682
683 /******************************************************************************
684  *  RtlOpenCurrentUser          [NTDLL] 
685  */
686 DWORD WINAPI RtlOpenCurrentUser(DWORD x1, DWORD *x2)
687 {
688 /* Note: this is not the correct solution, 
689  * But this works pretty good on wine and NT4.0 binaries
690  */
691         if  ( x1 == 0x2000000 )  {
692                 *x2 = HKEY_CURRENT_USER; 
693                 return TRUE;
694         }
695                 
696         return FALSE;
697 }
698 /******************************************************************************
699  *  RtlAllocateAndInitializeSid         [NTDLL.265] 
700  *
701  */
702 BOOL32 WINAPI RtlAllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,DWORD nSubAuthorityCount,
703                 DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD x7,DWORD x8,DWORD x9,DWORD x10, PSID pSid) 
704 {       FIXME(ntdll,"(%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p),stub!\n",
705                 pIdentifierAuthority,nSubAuthorityCount,x3,x4,x5,x6,x7,x8,x9,x10,pSid);
706         return 0;
707 }
708 /******************************************************************************
709  *  RtlEqualSid         [NTDLL.352] 
710  *
711  */
712 DWORD WINAPI RtlEqualSid(DWORD x1,DWORD x2) {   
713         FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n", x1,x2);
714         return TRUE;
715 }
716
717 /******************************************************************************
718  *  RtlFreeSid          [NTDLL.376] 
719  */
720 DWORD WINAPI RtlFreeSid(DWORD x1) 
721 {       FIXME(ntdll,"(0x%08lx),stub!\n", x1);
722         return TRUE;
723 }
724
725 /******************************************************************************
726  *  RtlGetDaclSecurityDescriptor                [NTDLL] 
727  *
728  * NOTES: seems to be like GetSecurityDescriptorDacl (js)
729  */
730 DWORD WINAPI RtlGetDaclSecurityDescriptor(
731         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
732         OUT LPBOOL lpbDaclPresent,
733         OUT PACL *pDacl,
734         OUT LPBOOL lpbDaclDefaulted)
735 {       DWORD ret = 0;
736
737         TRACE(ntdll,"(%p,%p,%p,%p)\n",
738         pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
739
740         if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
741           return STATUS_UNKNOWN_REVISION ;
742
743         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & pSecurityDescriptor->Control) ? 1 : 0) )
744         {
745           if ( SE_SELF_RELATIVE & pSecurityDescriptor->Control)
746           { *pDacl = (PACL) ((LPBYTE)pSecurityDescriptor + (DWORD)pSecurityDescriptor->Dacl);
747           }
748           else
749           { *pDacl = pSecurityDescriptor->Dacl;
750           }
751         }
752
753         *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & pSecurityDescriptor->Control ) ? 1 : 0);
754         
755         return ret;
756 }
757
758 /******************************************************************************
759  *  RtlCreateEnvironment                [NTDLL] 
760  */
761 DWORD WINAPI RtlCreateEnvironment(DWORD x1,DWORD x2) {
762         FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n",x1,x2);
763         return 0;
764 }
765
766
767 /******************************************************************************
768  *  RtlDestroyEnvironment               [NTDLL] 
769  */
770 DWORD WINAPI RtlDestroyEnvironment(DWORD x) {
771         FIXME(ntdll,"(0x%08lx),stub!\n",x);
772         return 0;
773 }
774
775 /******************************************************************************
776  *  RtlQueryEnvironmentVariable_U               [NTDLL] 
777  */
778 DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
779         FIXME(ntdll,"(0x%08lx,%s,%p),stub!\n",x1,debugstr_w(key->Buffer),val);
780         return 0;
781 }
782
783 /******************************************************************************
784  *  RtlSetEnvironmentVariable           [NTDLL] 
785  */
786 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
787         FIXME(ntdll,"(0x%08lx,%s,%s),stub!\n",x1,debugstr_w(key->Buffer),debugstr_w(val->Buffer));
788         return 0;
789 }
790
791 /******************************************************************************
792  *  RtlNewSecurityObject                [NTDLL] 
793  */
794 DWORD WINAPI RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
795         FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6);
796         return 0;
797 }
798
799 /******************************************************************************
800  *  RtlDeleteSecurityObject             [NTDLL] 
801  */
802 DWORD WINAPI RtlDeleteSecurityObject(DWORD x1) {
803         FIXME(ntdll,"(0x%08lx),stub!\n",x1);
804         return 0;
805 }
806
807 /******************************************************************************
808  *  RtlToTimeInSecondsSince1980         [NTDLL] 
809  */
810 BOOL32 WINAPI RtlTimeToSecondsSince1980(LPFILETIME ft,LPDWORD timeret) {
811         /* 1980 = 1970+10*365 days +  29. februar 1972 + 29.februar 1976 */
812         *timeret = DOSFS_FileTimeToUnixTime(ft,NULL) - (10*365+2)*24*3600;
813         return 1;
814 }
815
816 /******************************************************************************
817  *  RtlToTimeInSecondsSince1970         [NTDLL] 
818  */
819 BOOL32 WINAPI RtlTimeToSecondsSince1970(LPFILETIME ft,LPDWORD timeret) {
820         *timeret = DOSFS_FileTimeToUnixTime(ft,NULL);
821         return 1;
822 }
823
824 /******************************************************************************
825  *  RtlAcquirePebLock           [NTDLL] 
826  */
827 VOID WINAPI RtlAcquirePebLock(void) {
828         FIXME(ntdll,"()\n");
829         /* enter critical section ? */
830 }
831
832 /******************************************************************************
833  *  RtlReleasePebLock           [NTDLL] 
834  */
835 VOID WINAPI RtlReleasePebLock(void) {
836         FIXME(ntdll,"()\n");
837         /* leave critical section ? */
838 }
839
840 /******************************************************************************
841  *  RtlAddAccessAllowedAce              [NTDLL] 
842  */
843 DWORD WINAPI RtlAddAccessAllowedAce(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
844         FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
845         return 0;
846 }
847
848 /******************************************************************************
849  *  RtlGetAce           [NTDLL] 
850  */
851 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce ) {
852         FIXME(ntdll,"(%p,%ld,%p),stub!\n",pAcl,dwAceIndex,pAce);
853         return 0;
854 }
855
856 /******************************************************************************
857  *  RtlAdjustPrivilege          [NTDLL] 
858  */
859 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
860         FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
861         return 0;
862 }
863
864 /******************************************************************************
865  *  RtlIntegerToChar    [NTDLL] 
866  */
867 DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
868         FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
869         return 0;
870 }
871 /******************************************************************************
872  *  RtlSystemTimeToLocalTime    [NTDLL] 
873  */
874 DWORD WINAPI RtlSystemTimeToLocalTime(DWORD x1,DWORD x2) {
875         FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n",x1,x2);
876         return 0;
877 }
878 /******************************************************************************
879  *  RtlTimeToTimeFields         [NTDLL] 
880  */
881 DWORD WINAPI RtlTimeToTimeFields(DWORD x1,DWORD x2) {
882         FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n",x1,x2);
883         return 0;
884 }
885 /******************************************************************************
886  *      RtlCompareUnicodeString [NTDLL] 
887  */
888 NTSTATUS WINAPI RtlCompareUnicodeString(
889         PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive) 
890 {
891         FIXME(ntdll,"(%s,%s,0x%08x),stub!\n",debugstr_w(String1->Buffer),debugstr_w(String1->Buffer),CaseInSensitive);
892         return 0;
893 }
894
895 /******************************************************************************
896  *      DbgPrint        [NTDLL] 
897  */
898 void __cdecl DbgPrint(LPCSTR fmt,LPVOID args) {
899         char buf[512];
900
901         wvsprintf32A(buf,fmt,&args);
902         MSG("DbgPrint says: %s",buf);
903         /* hmm, raise exception? */
904 }
905 DWORD NtRaiseException ( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,CONST ULONG_PTR *lpArguments)
906 {       FIXME(ntdll,"0x%08lx 0x%08lx 0x%08lx %p\n", dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
907         return 0;
908 }
909
910 DWORD RtlRaiseException ( DWORD x)
911 {       FIXME(ntdll, "0x%08lx\n", x);
912         return 0;
913 }
914
915 /***********************************************************************
916  *           RtlInitializeResource      (NTDLL.409)
917  *
918  * xxxResource() functions implement multiple-reader-single-writer lock.
919  * The code is based on information published in WDJ January 1999 issue.
920  */
921 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
922 {
923     if( rwl )
924     {
925         rwl->iNumberActive = 0;
926         rwl->uExclusiveWaiters = 0;
927         rwl->uSharedWaiters = 0;
928         rwl->hOwningThreadId = 0;
929         rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
930         InitializeCriticalSection( &rwl->rtlCS );
931         rwl->hExclusiveReleaseSemaphore = CreateSemaphore32A( NULL, 0, 65535, NULL );
932         rwl->hSharedReleaseSemaphore = CreateSemaphore32A( NULL, 0, 65535, NULL );
933     }
934 }
935
936
937 /***********************************************************************
938  *           RtlDeleteResource          (NTDLL.330)
939  */
940 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
941 {
942     if( rwl )
943     {
944         EnterCriticalSection( &rwl->rtlCS );
945         if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
946             MSG("Deleting active MRSW lock (%p), expect failure\n", rwl );
947         rwl->hOwningThreadId = 0;
948         rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
949         rwl->iNumberActive = 0;
950         CloseHandle( rwl->hExclusiveReleaseSemaphore );
951         CloseHandle( rwl->hSharedReleaseSemaphore );
952         LeaveCriticalSection( &rwl->rtlCS );
953         DeleteCriticalSection( &rwl->rtlCS );
954     }
955 }
956
957
958 /***********************************************************************
959  *          RtlAcquireResourceExclusive (NTDLL.256)
960  */
961 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
962 {
963     BYTE retVal = 0;
964     if( !rwl ) return 0;
965
966 start:
967     EnterCriticalSection( &rwl->rtlCS );
968     if( rwl->iNumberActive == 0 ) /* lock is free */
969     {
970         rwl->iNumberActive = -1;
971         retVal = 1;
972     }
973     else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
974     {
975          if( rwl->hOwningThreadId == GetCurrentThreadId() )
976          {
977              retVal = 1;
978              rwl->iNumberActive--;
979              goto done;
980          }
981 wait:
982          if( fWait )
983          {
984              rwl->uExclusiveWaiters++;
985
986              LeaveCriticalSection( &rwl->rtlCS );
987              if( WaitForSingleObject( rwl->hExclusiveReleaseSemaphore, INFINITE32 ) == WAIT_FAILED )
988                  goto done;
989              goto start; /* restart the acquisition to avoid deadlocks */
990          }
991     }
992     else  /* one or more shared locks are in progress */
993          if( fWait )
994              goto wait;
995          
996     if( retVal == 1 )
997         rwl->hOwningThreadId = GetCurrentThreadId();
998 done:
999     LeaveCriticalSection( &rwl->rtlCS );
1000     return retVal;
1001 }
1002
1003 /***********************************************************************
1004  *          RtlAcquireResourceShared    (NTDLL.257)
1005  */
1006 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
1007 {
1008     DWORD dwWait = WAIT_FAILED;
1009     BYTE retVal = 0;
1010     if( !rwl ) return 0;
1011
1012 start:
1013     EnterCriticalSection( &rwl->rtlCS );
1014     if( rwl->iNumberActive < 0 )
1015     {
1016         if( rwl->hOwningThreadId == GetCurrentThreadId() )
1017         {
1018             rwl->iNumberActive--;
1019             retVal = 1;
1020             goto done;
1021         }
1022         
1023         if( fWait )
1024         {
1025             rwl->uSharedWaiters++;
1026             LeaveCriticalSection( &rwl->rtlCS );
1027             if( (dwWait = WaitForSingleObject( rwl->hSharedReleaseSemaphore, INFINITE32 )) == WAIT_FAILED )
1028                 goto done;
1029             goto start;
1030         }
1031     }
1032     else 
1033     {
1034         if( dwWait != WAIT_OBJECT_0 ) /* otherwise RtlReleaseResource() has already done it */
1035             rwl->iNumberActive++;
1036         retVal = 1;
1037     }
1038 done:
1039     LeaveCriticalSection( &rwl->rtlCS );
1040     return retVal;
1041 }
1042
1043
1044 /***********************************************************************
1045  *           RtlReleaseResource         (NTDLL.471)
1046  */
1047 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
1048 {
1049     EnterCriticalSection( &rwl->rtlCS );
1050
1051     if( rwl->iNumberActive > 0 ) /* have one or more readers */
1052     {
1053         if( --rwl->iNumberActive == 0 )
1054         {
1055             if( rwl->uExclusiveWaiters )
1056             {
1057 wake_exclusive:
1058                 rwl->uExclusiveWaiters--;
1059                 ReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
1060             }
1061         }
1062     }
1063     else 
1064     if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
1065     {
1066         if( ++rwl->iNumberActive == 0 )
1067         {
1068             rwl->hOwningThreadId = 0;
1069             if( rwl->uExclusiveWaiters )
1070                 goto wake_exclusive;
1071             else
1072                 if( rwl->uSharedWaiters )
1073                 {
1074                     UINT32 n = rwl->uSharedWaiters;
1075                     rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
1076                                                                * all queued readers have done their thing */
1077                     rwl->uSharedWaiters = 0;
1078                     ReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
1079                 }
1080         }
1081     }
1082     LeaveCriticalSection( &rwl->rtlCS );
1083 }
1084
1085
1086 /***********************************************************************
1087  *           RtlDumpResource            (NTDLL.340)
1088  */
1089 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
1090 {
1091     if( rwl )
1092     {
1093         MSG("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",  
1094                 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
1095         if( rwl->iNumberActive )
1096             MSG("\towner thread = %08x\n", rwl->hOwningThreadId );
1097     }
1098 }
1099