Handle texture addressing the D3D7 way.
[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  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "winerror.h"
29 #include "winternl.h"
30 #include "winreg.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
35
36
37 static RTL_CRITICAL_SECTION peb_lock = CRITICAL_SECTION_INIT("peb_lock");
38
39 /*
40  *      resource functions
41  */
42
43 /***********************************************************************
44  *           RtlInitializeResource      (NTDLL.@)
45  *
46  * xxxResource() functions implement multiple-reader-single-writer lock.
47  * The code is based on information published in WDJ January 1999 issue.
48  */
49 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
50 {
51     if( rwl )
52     {
53         rwl->iNumberActive = 0;
54         rwl->uExclusiveWaiters = 0;
55         rwl->uSharedWaiters = 0;
56         rwl->hOwningThreadId = 0;
57         rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
58         RtlInitializeCriticalSection( &rwl->rtlCS );
59         NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, 0, NULL, 0, 65535 );
60         NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, 0, NULL, 0, 65535 );
61     }
62 }
63
64
65 /***********************************************************************
66  *           RtlDeleteResource          (NTDLL.@)
67  */
68 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
69 {
70     if( rwl )
71     {
72         RtlEnterCriticalSection( &rwl->rtlCS );
73         if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
74             MESSAGE("Deleting active MRSW lock (%p), expect failure\n", rwl );
75         rwl->hOwningThreadId = 0;
76         rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
77         rwl->iNumberActive = 0;
78         NtClose( rwl->hExclusiveReleaseSemaphore );
79         NtClose( rwl->hSharedReleaseSemaphore );
80         RtlLeaveCriticalSection( &rwl->rtlCS );
81         RtlDeleteCriticalSection( &rwl->rtlCS );
82     }
83 }
84
85
86 /***********************************************************************
87  *          RtlAcquireResourceExclusive (NTDLL.@)
88  */
89 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
90 {
91     BYTE retVal = 0;
92     if( !rwl ) return 0;
93
94 start:
95     RtlEnterCriticalSection( &rwl->rtlCS );
96     if( rwl->iNumberActive == 0 ) /* lock is free */
97     {
98         rwl->iNumberActive = -1;
99         retVal = 1;
100     }
101     else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
102     {
103          if( rwl->hOwningThreadId == (HANDLE)GetCurrentThreadId() )
104          {
105              retVal = 1;
106              rwl->iNumberActive--;
107              goto done;
108          }
109 wait:
110          if( fWait )
111          {
112              rwl->uExclusiveWaiters++;
113
114              RtlLeaveCriticalSection( &rwl->rtlCS );
115              if( WaitForSingleObject( rwl->hExclusiveReleaseSemaphore, INFINITE ) == WAIT_FAILED )
116                  goto done;
117              goto start; /* restart the acquisition to avoid deadlocks */
118          }
119     }
120     else  /* one or more shared locks are in progress */
121          if( fWait )
122              goto wait;
123
124     if( retVal == 1 )
125         rwl->hOwningThreadId = (HANDLE)GetCurrentThreadId();
126 done:
127     RtlLeaveCriticalSection( &rwl->rtlCS );
128     return retVal;
129 }
130
131 /***********************************************************************
132  *          RtlAcquireResourceShared    (NTDLL.@)
133  */
134 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
135 {
136     DWORD dwWait = WAIT_FAILED;
137     BYTE retVal = 0;
138     if( !rwl ) return 0;
139
140 start:
141     RtlEnterCriticalSection( &rwl->rtlCS );
142     if( rwl->iNumberActive < 0 )
143     {
144         if( rwl->hOwningThreadId == (HANDLE)GetCurrentThreadId() )
145         {
146             rwl->iNumberActive--;
147             retVal = 1;
148             goto done;
149         }
150
151         if( fWait )
152         {
153             rwl->uSharedWaiters++;
154             RtlLeaveCriticalSection( &rwl->rtlCS );
155             if( (dwWait = WaitForSingleObject( rwl->hSharedReleaseSemaphore, INFINITE )) == WAIT_FAILED )
156                 goto done;
157             goto start;
158         }
159     }
160     else
161     {
162         if( dwWait != WAIT_OBJECT_0 ) /* otherwise RtlReleaseResource() has already done it */
163             rwl->iNumberActive++;
164         retVal = 1;
165     }
166 done:
167     RtlLeaveCriticalSection( &rwl->rtlCS );
168     return retVal;
169 }
170
171
172 /***********************************************************************
173  *           RtlReleaseResource         (NTDLL.@)
174  */
175 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
176 {
177     RtlEnterCriticalSection( &rwl->rtlCS );
178
179     if( rwl->iNumberActive > 0 ) /* have one or more readers */
180     {
181         if( --rwl->iNumberActive == 0 )
182         {
183             if( rwl->uExclusiveWaiters )
184             {
185 wake_exclusive:
186                 rwl->uExclusiveWaiters--;
187                 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
188             }
189         }
190     }
191     else
192     if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
193     {
194         if( ++rwl->iNumberActive == 0 )
195         {
196             rwl->hOwningThreadId = 0;
197             if( rwl->uExclusiveWaiters )
198                 goto wake_exclusive;
199             else
200                 if( rwl->uSharedWaiters )
201                 {
202                     UINT n = rwl->uSharedWaiters;
203                     rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
204                                                                * all queued readers have done their thing */
205                     rwl->uSharedWaiters = 0;
206                     NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
207                 }
208         }
209     }
210     RtlLeaveCriticalSection( &rwl->rtlCS );
211 }
212
213
214 /***********************************************************************
215  *           RtlDumpResource            (NTDLL.@)
216  */
217 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
218 {
219     if( rwl )
220     {
221         MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
222                 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
223         if( rwl->iNumberActive )
224             MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
225     }
226 }
227
228 /*
229  *      misc functions
230  */
231
232 /******************************************************************************
233  *      DbgPrint        [NTDLL.@]
234  */
235 void WINAPIV DbgPrint(LPCSTR fmt, ...)
236 {
237        char buf[512];
238        va_list args;
239
240        va_start(args, fmt);
241        vsprintf(buf,fmt, args);
242        va_end(args);
243
244         MESSAGE("DbgPrint says: %s",buf);
245         /* hmm, raise exception? */
246 }
247
248 /******************************************************************************
249  *  RtlAcquirePebLock           [NTDLL.@]
250  */
251 VOID WINAPI RtlAcquirePebLock(void)
252 {
253     RtlEnterCriticalSection( &peb_lock );
254 }
255
256 /******************************************************************************
257  *  RtlReleasePebLock           [NTDLL.@]
258  */
259 VOID WINAPI RtlReleasePebLock(void)
260 {
261     RtlLeaveCriticalSection( &peb_lock );
262 }
263
264 /******************************************************************************
265  *  RtlIntegerToChar    [NTDLL.@]
266  */
267 DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
268         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
269         return 0;
270 }
271 /******************************************************************************
272  *  RtlSetEnvironmentVariable           [NTDLL.@]
273  */
274 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
275         FIXME("(0x%08lx,%s,%s),stub!\n",x1,debugstr_w(key->Buffer),debugstr_w(val->Buffer));
276         return 0;
277 }
278
279 /******************************************************************************
280  *  RtlNewSecurityObject                [NTDLL.@]
281  */
282 DWORD WINAPI RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
283         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6);
284         return 0;
285 }
286
287 /******************************************************************************
288  *  RtlDeleteSecurityObject             [NTDLL.@]
289  */
290 DWORD WINAPI RtlDeleteSecurityObject(DWORD x1) {
291         FIXME("(0x%08lx),stub!\n",x1);
292         return 0;
293 }
294
295 /**************************************************************************
296  *                 RtlNormalizeProcessParams            [NTDLL.@]
297  */
298 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
299 {
300     FIXME("(%p), stub\n",x);
301     return x;
302 }
303
304 /**************************************************************************
305  *                 RtlGetNtProductType                  [NTDLL.@]
306  */
307 BOOLEAN WINAPI RtlGetNtProductType(LPDWORD type)
308 {
309     FIXME("(%p): stub\n", type);
310     *type=3; /* dunno. 1 for client, 3 for server? */
311     return 1;
312 }
313
314 /**************************************************************************
315  *                 _chkstk                              [NTDLL.@]
316  *
317  * Glorified "enter xxxx".
318  */
319 void WINAPI NTDLL_chkstk( CONTEXT86 *context )
320 {
321     context->Esp -= context->Eax;
322 }
323
324 /**************************************************************************
325  *                 _alloca_probe                        [NTDLL.@]
326  *
327  * Glorified "enter xxxx".
328  */
329 void WINAPI NTDLL_alloca_probe( CONTEXT86 *context )
330 {
331     context->Esp -= context->Eax;
332 }
333
334 /**************************************************************************
335  *                 RtlDosPathNameToNtPathName_U         [NTDLL.@]
336  *
337  * szwDosPath: a fully qualified DOS path name
338  * ntpath:     pointer to a UNICODE_STRING to hold the converted
339  *              path name
340  *
341  * FIXME: Should we not allocate the ntpath buffer under some
342  *         circumstances?
343  *        Are the conversions static? (always prepend '\??\' ?)
344  *        Not really sure about the last two arguments.
345  */
346 BOOLEAN  WINAPI RtlDosPathNameToNtPathName_U(
347         LPWSTR szwDosPath,PUNICODE_STRING ntpath,
348         DWORD x2,DWORD x3)
349 {
350     ULONG length;
351     UNICODE_STRING pathprefix;
352     WCHAR szPrefix[] = { '\\', '?', '?', '\\', 0 };
353
354     FIXME("(%s,%p,%08lx,%08lx) partial stub\n",
355         debugstr_w(szwDosPath),ntpath,x2,x3);
356
357     if ( !szwDosPath )
358         return FALSE;
359
360     if ( !szwDosPath[0] )
361         return FALSE;
362  
363     if ( szwDosPath[1]!= ':' )
364         return FALSE;
365
366     length = strlenW(szwDosPath) * sizeof (WCHAR) + sizeof szPrefix;
367  
368     ntpath->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, length);
369     ntpath->Length = 0;
370     ntpath->MaximumLength = length;
371
372     if ( !ntpath->Buffer )
373         return FALSE;
374
375     RtlInitUnicodeString( &pathprefix, szPrefix );
376     RtlCopyUnicodeString( ntpath, &pathprefix );
377     RtlAppendUnicodeToString( ntpath, szwDosPath );
378
379     return TRUE;
380 }
381
382
383 /******************************************************************************
384  *  RtlCreateEnvironment                [NTDLL.@]
385  */
386 DWORD WINAPI RtlCreateEnvironment(DWORD x1,DWORD x2) {
387         FIXME("(0x%08lx,0x%08lx),stub!\n",x1,x2);
388         return 0;
389 }
390
391
392 /******************************************************************************
393  *  RtlDestroyEnvironment               [NTDLL.@]
394  */
395 DWORD WINAPI RtlDestroyEnvironment(DWORD x) {
396         FIXME("(0x%08lx),stub!\n",x);
397         return 0;
398 }
399
400 /******************************************************************************
401  *  RtlQueryEnvironmentVariable_U               [NTDLL.@]
402  */
403 DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
404         FIXME("(0x%08lx,%s,%p),stub!\n",x1,debugstr_w(key->Buffer),val);
405         return 0;
406 }
407 /******************************************************************************
408  *  RtlInitializeGenericTable           [NTDLL.@]
409  */
410 DWORD WINAPI RtlInitializeGenericTable(void)
411 {
412         FIXME("\n");
413         return 0;
414 }
415
416 /******************************************************************************
417  *  RtlCopyMemory   [NTDLL]
418  *
419  */
420 #undef RtlCopyMemory
421 VOID WINAPI RtlCopyMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
422 {
423     memcpy(Destination, Source, Length);
424 }
425
426 /******************************************************************************
427  *  RtlMoveMemory   [NTDLL.@]
428  */
429 #undef RtlMoveMemory
430 VOID WINAPI RtlMoveMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
431 {
432     memmove(Destination, Source, Length);
433 }
434
435 /******************************************************************************
436  *  RtlFillMemory   [NTDLL.@]
437  */
438 #undef RtlFillMemory
439 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
440 {
441     memset(Destination, Fill, Length);
442 }
443
444 /******************************************************************************
445  *  RtlZeroMemory   [NTDLL.@]
446  */
447 #undef RtlZeroMemory
448 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
449 {
450     memset(Destination, 0, Length);
451 }
452
453 /******************************************************************************
454  *  RtlCompareMemory   [NTDLL.@]
455  */
456 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
457 {
458     int i;
459     for(i=0; (i<Length) && (((LPBYTE)Source1)[i]==((LPBYTE)Source2)[i]); i++);
460     return i;
461 }
462
463 /******************************************************************************
464  *  RtlAssert                           [NTDLL.@]
465  *
466  * Not implemented in non-debug versions.
467  */
468 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
469 {
470         FIXME("(%p,%p,0x%08lx,0x%08lx),stub\n",x1,x2,x3,x4);
471 }
472
473 /******************************************************************************
474  *  RtlGetNtVersionNumbers       [NTDLL.@]
475  *
476  * Introduced in Windows XP (NT5.1)
477  */
478 void WINAPI RtlGetNtVersionNumbers(LPDWORD major, LPDWORD minor, LPDWORD build)
479 {
480         OSVERSIONINFOEXW versionInfo;
481         versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
482         GetVersionExW((OSVERSIONINFOW*)&versionInfo);
483
484         if (major)
485         {
486                 *major = versionInfo.dwMajorVersion;
487         }
488
489         if (minor)
490         {
491                 *minor = versionInfo.dwMinorVersion;
492         }
493
494         if (build)
495         {
496                 /* FIXME: Does anybody know the real formula? */
497                 *build = (0xF0000000 | versionInfo.dwBuildNumber);
498         }
499 }
500
501 /*************************************************************************
502  * RtlFillMemoryUlong   [NTDLL.@]
503  *
504  * Fill memory with a 32 bit (dword) value.
505  *
506  * PARAMS
507  *  lpDest  [I] Bitmap pointer
508  *  ulCount [I] Number of dwords to write
509  *  ulValue [I] Value to fill with
510  *
511  * RETURNS
512  *  Nothing.
513  */
514 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
515 {
516   TRACE("(%p,%ld,%ld)\n", lpDest, ulCount, ulValue);
517
518   while(ulCount--)
519     *lpDest++ = ulValue;
520 }
521
522 /*************************************************************************
523  * RtlGetLongestNtPathLength    [NTDLL.@]
524  *
525  * Get the longest allowed path length
526  *
527  * PARAMS
528  *  None.
529  *
530  * RETURNS
531  *  The longest allowed path length (277 characters under Win2k).
532  */
533 DWORD WINAPI RtlGetLongestNtPathLength(void)
534 {
535   TRACE("()\n");
536   return 277;
537 }