Minor updates of Slovenian translations.
[wine] / dlls / kernel / sync.c
1 /*
2  * Kernel synchronization objects
3  *
4  * Copyright 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <string.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <errno.h>
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
31 #endif
32 #ifdef HAVE_SYS_POLL_H
33 #include <sys/poll.h>
34 #endif
35 #include <stdio.h>
36
37 #include "winbase.h"
38 #include "winerror.h"
39 #include "winnls.h"
40
41 #include "wine/server.h"
42 #include "wine/unicode.h"
43 #include "file.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(win32);
48
49 /* check if current version is NT or Win95 */
50 inline static int is_version_nt(void)
51 {
52     return !(GetVersion() & 0x80000000);
53 }
54
55
56 /***********************************************************************
57  *           InitializeCriticalSection   (KERNEL32.@)
58  */
59 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
60 {
61     NTSTATUS ret = RtlInitializeCriticalSection( crit );
62     if (ret) RtlRaiseStatus( ret );
63 }
64
65 /***********************************************************************
66  *           InitializeCriticalSectionAndSpinCount   (KERNEL32.@)
67  */
68 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
69 {
70     NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
71     if (ret) RtlRaiseStatus( ret );
72     return !ret;
73 }
74
75 /***********************************************************************
76  *           SetCriticalSectionSpinCount   (KERNEL32.@)
77  * This function is available on NT4SP3 or later, but not Win98
78  * It is SMP related
79  */
80 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
81 {
82     ULONG_PTR oldspincount = crit->SpinCount;
83     if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
84     crit->SpinCount = spincount;
85     return oldspincount;
86 }
87
88 /***********************************************************************
89  *           MakeCriticalSectionGlobal   (KERNEL32.@)
90  */
91 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
92 {
93     /* let's assume that only one thread at a time will try to do this */
94     HANDLE sem = crit->LockSemaphore;
95     if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
96     crit->LockSemaphore = ConvertToGlobalHandle( sem );
97     if (crit->DebugInfo)
98     {
99         RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
100         crit->DebugInfo = NULL;
101     }
102 }
103
104
105 /***********************************************************************
106  *           ReinitializeCriticalSection   (KERNEL32.@)
107  */
108 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
109 {
110     if ( !crit->LockSemaphore )
111         RtlInitializeCriticalSection( crit );
112 }
113
114
115 /***********************************************************************
116  *           UninitializeCriticalSection   (KERNEL32.@)
117  */
118 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
119 {
120     RtlDeleteCriticalSection( crit );
121 }
122
123
124 /***********************************************************************
125  *           CreateEventA    (KERNEL32.@)
126  */
127 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
128                             BOOL initial_state, LPCSTR name )
129 {
130     WCHAR buffer[MAX_PATH];
131
132     if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
133
134     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
135     {
136         SetLastError( ERROR_FILENAME_EXCED_RANGE );
137         return 0;
138     }
139     return CreateEventW( sa, manual_reset, initial_state, buffer );
140 }
141
142
143 /***********************************************************************
144  *           CreateEventW    (KERNEL32.@)
145  */
146 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
147                             BOOL initial_state, LPCWSTR name )
148 {
149     HANDLE ret;
150     DWORD len = name ? strlenW(name) : 0;
151     if (len >= MAX_PATH)
152     {
153         SetLastError( ERROR_FILENAME_EXCED_RANGE );
154         return 0;
155     }
156     /* one buggy program needs this
157      * ("Van Dale Groot woordenboek der Nederlandse taal")
158      */
159     if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
160     {
161         ERR("Bad security attributes pointer %p\n",sa);
162         SetLastError( ERROR_INVALID_PARAMETER);
163         return 0;
164     }
165     SERVER_START_REQ( create_event )
166     {
167         req->manual_reset = manual_reset;
168         req->initial_state = initial_state;
169         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
170         wine_server_add_data( req, name, len * sizeof(WCHAR) );
171         SetLastError(0);
172         wine_server_call_err( req );
173         ret = reply->handle;
174     }
175     SERVER_END_REQ;
176     return ret;
177 }
178
179
180 /***********************************************************************
181  *           CreateW32Event    (KERNEL.457)
182  */
183 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
184 {
185     return CreateEventA( NULL, manual_reset, initial_state, NULL );
186 }
187
188
189 /***********************************************************************
190  *           OpenEventA    (KERNEL32.@)
191  */
192 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
193 {
194     WCHAR buffer[MAX_PATH];
195
196     if (!name) return OpenEventW( access, inherit, NULL );
197
198     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
199     {
200         SetLastError( ERROR_FILENAME_EXCED_RANGE );
201         return 0;
202     }
203     return OpenEventW( access, inherit, buffer );
204 }
205
206
207 /***********************************************************************
208  *           OpenEventW    (KERNEL32.@)
209  */
210 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
211 {
212     HANDLE ret;
213     DWORD len = name ? strlenW(name) : 0;
214     if (len >= MAX_PATH)
215     {
216         SetLastError( ERROR_FILENAME_EXCED_RANGE );
217         return 0;
218     }
219     if (!is_version_nt()) access = EVENT_ALL_ACCESS;
220
221     SERVER_START_REQ( open_event )
222     {
223         req->access  = access;
224         req->inherit = inherit;
225         wine_server_add_data( req, name, len * sizeof(WCHAR) );
226         wine_server_call_err( req );
227         ret = reply->handle;
228     }
229     SERVER_END_REQ;
230     return ret;
231 }
232
233
234 /***********************************************************************
235  *           EVENT_Operation
236  *
237  * Execute an event operation (set,reset,pulse).
238  */
239 static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
240 {
241     BOOL ret;
242     SERVER_START_REQ( event_op )
243     {
244         req->handle = handle;
245         req->op     = op;
246         ret = !wine_server_call_err( req );
247     }
248     SERVER_END_REQ;
249     return ret;
250 }
251
252
253 /***********************************************************************
254  *           PulseEvent    (KERNEL32.@)
255  */
256 BOOL WINAPI PulseEvent( HANDLE handle )
257 {
258     return EVENT_Operation( handle, PULSE_EVENT );
259 }
260
261
262 /***********************************************************************
263  *           SetW32Event (KERNEL.458)
264  *           SetEvent    (KERNEL32.@)
265  */
266 BOOL WINAPI SetEvent( HANDLE handle )
267 {
268     return EVENT_Operation( handle, SET_EVENT );
269 }
270
271
272 /***********************************************************************
273  *           ResetW32Event (KERNEL.459)
274  *           ResetEvent    (KERNEL32.@)
275  */
276 BOOL WINAPI ResetEvent( HANDLE handle )
277 {
278     return EVENT_Operation( handle, RESET_EVENT );
279 }
280
281
282 /***********************************************************************
283  * NOTE: The Win95 VWin32_Event routines given below are really low-level
284  *       routines implemented directly by VWin32. The user-mode libraries
285  *       implement Win32 synchronisation routines on top of these low-level
286  *       primitives. We do it the other way around here :-)
287  */
288
289 /***********************************************************************
290  *       VWin32_EventCreate     (KERNEL.442)
291  */
292 HANDLE WINAPI VWin32_EventCreate(VOID)
293 {
294     HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
295     return ConvertToGlobalHandle( hEvent );
296 }
297
298 /***********************************************************************
299  *       VWin32_EventDestroy    (KERNEL.443)
300  */
301 VOID WINAPI VWin32_EventDestroy(HANDLE event)
302 {
303     CloseHandle( event );
304 }
305
306 /***********************************************************************
307  *       VWin32_EventWait       (KERNEL.450)
308  */
309 VOID WINAPI VWin32_EventWait(HANDLE event)
310 {
311     DWORD mutex_count;
312
313     ReleaseThunkLock( &mutex_count );
314     WaitForSingleObject( event, INFINITE );
315     RestoreThunkLock( mutex_count );
316 }
317
318 /***********************************************************************
319  *       VWin32_EventSet        (KERNEL.451)
320  *       KERNEL_479             (KERNEL.479)
321  */
322 VOID WINAPI VWin32_EventSet(HANDLE event)
323 {
324     SetEvent( event );
325 }
326
327
328
329 /***********************************************************************
330  *           CreateMutexA   (KERNEL32.@)
331  */
332 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
333 {
334     WCHAR buffer[MAX_PATH];
335
336     if (!name) return CreateMutexW( sa, owner, NULL );
337
338     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
339     {
340         SetLastError( ERROR_FILENAME_EXCED_RANGE );
341         return 0;
342     }
343     return CreateMutexW( sa, owner, buffer );
344 }
345
346
347 /***********************************************************************
348  *           CreateMutexW   (KERNEL32.@)
349  */
350 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
351 {
352     HANDLE ret;
353     DWORD len = name ? strlenW(name) : 0;
354     if (len >= MAX_PATH)
355     {
356         SetLastError( ERROR_FILENAME_EXCED_RANGE );
357         return 0;
358     }
359     SERVER_START_REQ( create_mutex )
360     {
361         req->owned   = owner;
362         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
363         wine_server_add_data( req, name, len * sizeof(WCHAR) );
364         SetLastError(0);
365         wine_server_call_err( req );
366         ret = reply->handle;
367     }
368     SERVER_END_REQ;
369     return ret;
370 }
371
372
373 /***********************************************************************
374  *           OpenMutexA   (KERNEL32.@)
375  */
376 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
377 {
378     WCHAR buffer[MAX_PATH];
379
380     if (!name) return OpenMutexW( access, inherit, NULL );
381
382     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
383     {
384         SetLastError( ERROR_FILENAME_EXCED_RANGE );
385         return 0;
386     }
387     return OpenMutexW( access, inherit, buffer );
388 }
389
390
391 /***********************************************************************
392  *           OpenMutexW   (KERNEL32.@)
393  */
394 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
395 {
396     HANDLE ret;
397     DWORD len = name ? strlenW(name) : 0;
398     if (len >= MAX_PATH)
399     {
400         SetLastError( ERROR_FILENAME_EXCED_RANGE );
401         return 0;
402     }
403     if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
404
405     SERVER_START_REQ( open_mutex )
406     {
407         req->access  = access;
408         req->inherit = inherit;
409         wine_server_add_data( req, name, len * sizeof(WCHAR) );
410         wine_server_call_err( req );
411         ret = reply->handle;
412     }
413     SERVER_END_REQ;
414     return ret;
415 }
416
417
418 /***********************************************************************
419  *           ReleaseMutex   (KERNEL32.@)
420  */
421 BOOL WINAPI ReleaseMutex( HANDLE handle )
422 {
423     BOOL ret;
424     SERVER_START_REQ( release_mutex )
425     {
426         req->handle = handle;
427         ret = !wine_server_call_err( req );
428     }
429     SERVER_END_REQ;
430     return ret;
431 }
432
433
434 /*
435  * Semaphores
436  */
437
438
439 /***********************************************************************
440  *           CreateSemaphoreA   (KERNEL32.@)
441  */
442 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
443 {
444     WCHAR buffer[MAX_PATH];
445
446     if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
447
448     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
449     {
450         SetLastError( ERROR_FILENAME_EXCED_RANGE );
451         return 0;
452     }
453     return CreateSemaphoreW( sa, initial, max, buffer );
454 }
455
456
457 /***********************************************************************
458  *           CreateSemaphoreW   (KERNEL32.@)
459  */
460 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
461                                     LONG max, LPCWSTR name )
462 {
463     HANDLE ret;
464     DWORD len = name ? strlenW(name) : 0;
465
466     /* Check parameters */
467
468     if ((max <= 0) || (initial < 0) || (initial > max))
469     {
470         SetLastError( ERROR_INVALID_PARAMETER );
471         return 0;
472     }
473     if (len >= MAX_PATH)
474     {
475         SetLastError( ERROR_FILENAME_EXCED_RANGE );
476         return 0;
477     }
478
479     SERVER_START_REQ( create_semaphore )
480     {
481         req->initial = (unsigned int)initial;
482         req->max     = (unsigned int)max;
483         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
484         wine_server_add_data( req, name, len * sizeof(WCHAR) );
485         SetLastError(0);
486         wine_server_call_err( req );
487         ret = reply->handle;
488     }
489     SERVER_END_REQ;
490     return ret;
491 }
492
493
494 /***********************************************************************
495  *           OpenSemaphoreA   (KERNEL32.@)
496  */
497 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
498 {
499     WCHAR buffer[MAX_PATH];
500
501     if (!name) return OpenSemaphoreW( access, inherit, NULL );
502
503     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
504     {
505         SetLastError( ERROR_FILENAME_EXCED_RANGE );
506         return 0;
507     }
508     return OpenSemaphoreW( access, inherit, buffer );
509 }
510
511
512 /***********************************************************************
513  *           OpenSemaphoreW   (KERNEL32.@)
514  */
515 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
516 {
517     HANDLE ret;
518     DWORD len = name ? strlenW(name) : 0;
519     if (len >= MAX_PATH)
520     {
521         SetLastError( ERROR_FILENAME_EXCED_RANGE );
522         return 0;
523     }
524     if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
525
526     SERVER_START_REQ( open_semaphore )
527     {
528         req->access  = access;
529         req->inherit = inherit;
530         wine_server_add_data( req, name, len * sizeof(WCHAR) );
531         wine_server_call_err( req );
532         ret = reply->handle;
533     }
534     SERVER_END_REQ;
535     return ret;
536 }
537
538
539 /***********************************************************************
540  *           ReleaseSemaphore   (KERNEL32.@)
541  */
542 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
543 {
544     NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
545     if (status) SetLastError( RtlNtStatusToDosError(status) );
546     return !status;
547 }
548
549
550 /*
551  * Timers
552  */
553
554
555 /***********************************************************************
556  *           CreateWaitableTimerA    (KERNEL32.@)
557  */
558 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
559 {
560     WCHAR buffer[MAX_PATH];
561
562     if (!name) return CreateWaitableTimerW( sa, manual, NULL );
563
564     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
565     {
566         SetLastError( ERROR_FILENAME_EXCED_RANGE );
567         return 0;
568     }
569     return CreateWaitableTimerW( sa, manual, buffer );
570 }
571
572
573 /***********************************************************************
574  *           CreateWaitableTimerW    (KERNEL32.@)
575  */
576 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
577 {
578     HANDLE              handle;
579     NTSTATUS            status;
580     UNICODE_STRING      us;
581     DWORD               attr = 0;
582     OBJECT_ATTRIBUTES   oa;
583
584     if (name) RtlInitUnicodeString(&us, name);
585     if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
586         attr |= OBJ_INHERIT;
587     InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
588                                NULL /* FIXME */, NULL /* FIXME */);
589     status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
590                            manual ? NotificationTimer : SynchronizationTimer);
591
592     if (status != STATUS_SUCCESS)
593     {
594         SetLastError( RtlNtStatusToDosError(status) );
595         return 0;
596     }
597     return handle;
598 }
599
600
601 /***********************************************************************
602  *           OpenWaitableTimerA    (KERNEL32.@)
603  */
604 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
605 {
606     WCHAR buffer[MAX_PATH];
607
608     if (!name) return OpenWaitableTimerW( access, inherit, NULL );
609
610     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
611     {
612         SetLastError( ERROR_FILENAME_EXCED_RANGE );
613         return 0;
614     }
615     return OpenWaitableTimerW( access, inherit, buffer );
616 }
617
618
619 /***********************************************************************
620  *           OpenWaitableTimerW    (KERNEL32.@)
621  */
622 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
623 {
624     NTSTATUS            status;
625     ULONG               attr = 0;
626     UNICODE_STRING      us;
627     HANDLE              handle;
628     OBJECT_ATTRIBUTES   oa;
629
630     if (inherit) attr |= OBJ_INHERIT;
631
632     if (name) RtlInitUnicodeString(&us, name);
633     InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
634     status = NtOpenTimer(&handle, access, &oa);
635     if (status != STATUS_SUCCESS)
636     {
637         SetLastError( RtlNtStatusToDosError(status) );
638         return 0;
639     }
640     return handle;
641 }
642
643
644 /***********************************************************************
645  *           SetWaitableTimer    (KERNEL32.@)
646  */
647 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
648                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
649 {
650     NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
651
652     if (status != STATUS_SUCCESS)
653     {
654         SetLastError( RtlNtStatusToDosError(status) );
655         if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
656     }
657     return TRUE;
658 }
659
660
661 /***********************************************************************
662  *           CancelWaitableTimer    (KERNEL32.@)
663  */
664 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
665 {
666     NTSTATUS status;
667
668     status = NtCancelTimer(handle, NULL);
669     if (status != STATUS_SUCCESS)
670     {
671         SetLastError( RtlNtStatusToDosError(status) );
672         return FALSE;
673     }
674     return TRUE;
675 }
676
677
678 /***********************************************************************
679  *           CreateTimerQueue  (KERNEL32.@)
680  */
681 HANDLE WINAPI CreateTimerQueue(void)
682 {
683     FIXME("stub\n");
684     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
685     return NULL;
686 }
687
688
689 /***********************************************************************
690  *           DeleteTimerQueueEx  (KERNEL32.@)
691  */
692 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
693 {
694     FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
695     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
696     return 0;
697 }
698
699 /***********************************************************************
700  *           CreateTimerQueueTimer  (KERNEL32.@)
701  *
702  * Creates a timer-queue timer. This timer expires at the specified due
703  * time (in ms), then after every specified period (in ms). When the timer
704  * expires, the callback function is called.
705  *
706  * RETURNS
707  *   nonzero on success or zero on faillure
708  *
709  * BUGS
710  *   Unimplemented
711  */
712 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
713                                    WAITORTIMERCALLBACK Callback, PVOID Parameter,
714                                    DWORD DueTime, DWORD Period, ULONG Flags )
715 {
716     FIXME("stub\n");
717     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
718     return TRUE;
719 }
720
721 /***********************************************************************
722  *           DeleteTimerQueueTimer  (KERNEL32.@)
723  *
724  * Cancels a timer-queue timer.
725  *
726  * RETURNS
727  *   nonzero on success or zero on faillure
728  *
729  * BUGS
730  *   Unimplemented
731  */
732 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
733                                    HANDLE CompletionEvent )
734 {
735     FIXME("stub\n");
736     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
737     return TRUE;
738 }
739
740
741 /*
742  * Pipes
743  */
744
745
746 /***********************************************************************
747  *           CreateNamedPipeA   (KERNEL32.@)
748  */
749 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
750                                 DWORD dwPipeMode, DWORD nMaxInstances,
751                                 DWORD nOutBufferSize, DWORD nInBufferSize,
752                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
753 {
754     WCHAR buffer[MAX_PATH];
755
756     if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
757                                         nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
758
759     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
760     {
761         SetLastError( ERROR_FILENAME_EXCED_RANGE );
762         return INVALID_HANDLE_VALUE;
763     }
764     return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
765                              nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
766 }
767
768
769 /***********************************************************************
770  *           CreateNamedPipeW   (KERNEL32.@)
771  */
772 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
773                                 DWORD dwPipeMode, DWORD nMaxInstances,
774                                 DWORD nOutBufferSize, DWORD nInBufferSize,
775                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
776 {
777     HANDLE ret;
778     DWORD len;
779     static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
780
781     TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
782           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
783           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
784
785     if (!name)
786     {
787         SetLastError( ERROR_PATH_NOT_FOUND );
788         return INVALID_HANDLE_VALUE;
789     }
790     len = strlenW(name);
791     if (len >= MAX_PATH)
792     {
793         SetLastError( ERROR_FILENAME_EXCED_RANGE );
794         return INVALID_HANDLE_VALUE;
795     }
796     if (strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0])))
797     {
798         SetLastError( ERROR_INVALID_NAME );
799         return INVALID_HANDLE_VALUE;
800     }
801     SERVER_START_REQ( create_named_pipe )
802     {
803         req->openmode = dwOpenMode;
804         req->pipemode = dwPipeMode;
805         req->maxinstances = nMaxInstances;
806         req->outsize = nOutBufferSize;
807         req->insize = nInBufferSize;
808         req->timeout = nDefaultTimeOut;
809         wine_server_add_data( req, name, len * sizeof(WCHAR) );
810         SetLastError(0);
811         if (!wine_server_call_err( req )) ret = reply->handle;
812         else ret = INVALID_HANDLE_VALUE;
813     }
814     SERVER_END_REQ;
815     return ret;
816 }
817
818
819 /***********************************************************************
820  *           PeekNamedPipe   (KERNEL32.@)
821  */
822 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
823                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
824 {
825 #ifdef FIONREAD
826     int avail=0,fd;
827
828     fd = FILE_GetUnixHandle(hPipe, GENERIC_READ);
829     if (fd == -1) return FALSE;
830
831     if (ioctl(fd,FIONREAD, &avail ) != 0)
832     {
833         TRACE("FIONREAD failed reason: %s\n",strerror(errno));
834         close(fd);
835         return FALSE;
836     }
837     if (!avail)  /* check for closed pipe */
838     {
839         struct pollfd pollfd;
840         pollfd.fd = fd;
841         pollfd.events = POLLIN;
842         pollfd.revents = 0;
843         switch (poll( &pollfd, 1, 0 ))
844         {
845         case 0:
846             break;
847         case 1:  /* got something */
848             if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
849             TRACE("POLLHUP | POLLERR\n");
850             /* fall through */
851         case -1:
852             close(fd);
853             SetLastError(ERROR_BROKEN_PIPE);
854             return FALSE;
855         }
856     }
857     close(fd);
858     TRACE(" 0x%08x bytes available\n", avail );
859     if (!lpvBuffer && lpcbAvail)
860       {
861         *lpcbAvail= avail;
862         return TRUE;
863       }
864 #endif /* defined(FIONREAD) */
865
866     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
867     FIXME("function not implemented\n");
868     return FALSE;
869 }
870
871 /***********************************************************************
872  *           SYNC_CompletePipeOverlapped   (Internal)
873  */
874 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
875 {
876     TRACE("for %p result %08lx\n",overlapped,result);
877     if(!overlapped)
878         return;
879     overlapped->Internal = result;
880     SetEvent(overlapped->hEvent);
881 }
882
883
884 /***********************************************************************
885  *           WaitNamedPipeA   (KERNEL32.@)
886  */
887 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
888 {
889     WCHAR buffer[MAX_PATH];
890
891     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
892
893     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
894     {
895         SetLastError( ERROR_FILENAME_EXCED_RANGE );
896         return 0;
897     }
898     return WaitNamedPipeW( buffer, nTimeOut );
899 }
900
901
902 /***********************************************************************
903  *           WaitNamedPipeW   (KERNEL32.@)
904  */
905 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
906 {
907     DWORD len = name ? strlenW(name) : 0;
908     BOOL ret;
909     OVERLAPPED ov;
910
911     if (len >= MAX_PATH)
912     {
913         SetLastError( ERROR_FILENAME_EXCED_RANGE );
914         return FALSE;
915     }
916
917     TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
918
919     memset(&ov,0,sizeof(ov));
920     ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
921     if (!ov.hEvent)
922         return FALSE;
923
924     SERVER_START_REQ( wait_named_pipe )
925     {
926         req->timeout = nTimeOut;
927         req->overlapped = &ov;
928         req->func = SYNC_CompletePipeOverlapped;
929         wine_server_add_data( req, name, len * sizeof(WCHAR) );
930         ret = !wine_server_call_err( req );
931     }
932     SERVER_END_REQ;
933
934     if(ret)
935     {
936         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
937         {
938             SetLastError(ov.Internal);
939             ret = (ov.Internal==STATUS_SUCCESS);
940         }
941     }
942     CloseHandle(ov.hEvent);
943     return ret;
944 }
945
946
947 /***********************************************************************
948  *           SYNC_ConnectNamedPipe   (Internal)
949  */
950 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
951 {
952     BOOL ret;
953
954     if(!overlapped)
955         return FALSE;
956
957     overlapped->Internal = STATUS_PENDING;
958
959     SERVER_START_REQ( connect_named_pipe )
960     {
961         req->handle = hPipe;
962         req->overlapped = overlapped;
963         req->func = SYNC_CompletePipeOverlapped;
964         ret = !wine_server_call_err( req );
965     }
966     SERVER_END_REQ;
967
968     return ret;
969 }
970
971 /***********************************************************************
972  *           ConnectNamedPipe   (KERNEL32.@)
973  */
974 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
975 {
976     OVERLAPPED ov;
977     BOOL ret;
978
979     TRACE("(%p,%p)\n",hPipe, overlapped);
980
981     if(overlapped)
982     {
983         if(SYNC_ConnectNamedPipe(hPipe,overlapped))
984             SetLastError( ERROR_IO_PENDING );
985         return FALSE;
986     }
987
988     memset(&ov,0,sizeof(ov));
989     ov.hEvent = CreateEventA(NULL,0,0,NULL);
990     if (!ov.hEvent)
991         return FALSE;
992
993     ret=SYNC_ConnectNamedPipe(hPipe, &ov);
994     if(ret)
995     {
996         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
997         {
998             SetLastError(ov.Internal);
999             ret = (ov.Internal==STATUS_SUCCESS);
1000         }
1001     }
1002
1003     CloseHandle(ov.hEvent);
1004
1005     return ret;
1006 }
1007
1008 /***********************************************************************
1009  *           DisconnectNamedPipe   (KERNEL32.@)
1010  */
1011 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1012 {
1013     BOOL ret;
1014
1015     TRACE("(%p)\n",hPipe);
1016
1017     SERVER_START_REQ( disconnect_named_pipe )
1018     {
1019         req->handle = hPipe;
1020         ret = !wine_server_call_err( req );
1021         if (ret && reply->fd != -1) close( reply->fd );
1022     }
1023     SERVER_END_REQ;
1024
1025     return ret;
1026 }
1027
1028 /***********************************************************************
1029  *           TransactNamedPipe   (KERNEL32.@)
1030  */
1031 BOOL WINAPI TransactNamedPipe(
1032     HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1033     DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1034 {
1035     FIXME("%p %p %ld %p %ld %p %p\n",
1036           hPipe, lpInput, dwInputSize, lpOutput,
1037           dwOutputSize, lpBytesRead, lpOverlapped);
1038     if(lpBytesRead)
1039         *lpBytesRead=0;
1040     return FALSE;
1041 }
1042
1043 /***********************************************************************
1044  *           GetNamedPipeInfo   (KERNEL32.@)
1045  */
1046 BOOL WINAPI GetNamedPipeInfo(
1047     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1048     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1049 {
1050     BOOL ret;
1051
1052     TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1053           lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1054
1055     SERVER_START_REQ( get_named_pipe_info )
1056     {
1057         req->handle = hNamedPipe;
1058         ret = !wine_server_call_err( req );
1059         if(lpFlags) *lpFlags = reply->flags;
1060         if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1061         if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1062         if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1063     }
1064     SERVER_END_REQ;
1065
1066     return ret;
1067 }
1068
1069 /***********************************************************************
1070  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1071  */
1072 BOOL WINAPI GetNamedPipeHandleStateA(
1073     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1074     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1075     LPSTR lpUsername, DWORD nUsernameMaxSize)
1076 {
1077     FIXME("%p %p %p %p %p %p %ld\n",
1078           hNamedPipe, lpState, lpCurInstances,
1079           lpMaxCollectionCount, lpCollectDataTimeout,
1080           lpUsername, nUsernameMaxSize);
1081
1082     return FALSE;
1083 }
1084
1085 /***********************************************************************
1086  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1087  */
1088 BOOL WINAPI GetNamedPipeHandleStateW(
1089     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1090     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1091     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1092 {
1093     FIXME("%p %p %p %p %p %p %ld\n",
1094           hNamedPipe, lpState, lpCurInstances,
1095           lpMaxCollectionCount, lpCollectDataTimeout,
1096           lpUsername, nUsernameMaxSize);
1097
1098     return FALSE;
1099 }
1100
1101 /***********************************************************************
1102  *           SetNamedPipeHandleState  (KERNEL32.@)
1103  */
1104 BOOL WINAPI SetNamedPipeHandleState(
1105     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1106     LPDWORD lpCollectDataTimeout)
1107 {
1108     FIXME("%p %p %p %p\n",
1109           hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1110     return FALSE;
1111 }
1112
1113 /***********************************************************************
1114  *           CallNamedPipeA  (KERNEL32.@)
1115  */
1116 BOOL WINAPI CallNamedPipeA(
1117     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1118     LPVOID lpOutput, DWORD lpOutputSize,
1119     LPDWORD lpBytesRead, DWORD nTimeout)
1120 {
1121     FIXME("%s %p %ld %p %ld %p %ld\n",
1122            debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1123            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1124     return FALSE;
1125 }
1126
1127 /***********************************************************************
1128  *           CallNamedPipeW  (KERNEL32.@)
1129  */
1130 BOOL WINAPI CallNamedPipeW(
1131     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1132     LPVOID lpOutput, DWORD lpOutputSize,
1133     LPDWORD lpBytesRead, DWORD nTimeout)
1134 {
1135     FIXME("%s %p %ld %p %ld %p %ld\n",
1136            debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1137            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1138     return FALSE;
1139 }
1140
1141 /******************************************************************
1142  *              CreatePipe (KERNEL32.@)
1143  *
1144  */
1145 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1146                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1147 {
1148     static unsigned  index = 0;
1149     char        name[64];
1150     HANDLE      hr, hw;
1151     unsigned    in_index = index;
1152
1153     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1154     /* generate a unique pipe name (system wide) */
1155     do
1156     {
1157         sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1158         hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, 
1159                               PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size, 
1160                               NMPWAIT_USE_DEFAULT_WAIT, sa);
1161     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1162     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1163     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1164
1165     hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1166     if (hw == INVALID_HANDLE_VALUE) 
1167     {
1168         CloseHandle(hr);
1169         return FALSE;
1170     }
1171
1172     *hReadPipe = hr;
1173     *hWritePipe = hw;
1174     return TRUE;
1175 }
1176
1177
1178 #ifdef __i386__
1179
1180 /***********************************************************************
1181  *              InterlockedCompareExchange (KERNEL32.@)
1182  */
1183 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1184 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1185                   "movl 12(%esp),%eax\n\t"
1186                   "movl 8(%esp),%ecx\n\t"
1187                   "movl 4(%esp),%edx\n\t"
1188                   "lock; cmpxchgl %ecx,(%edx)\n\t"
1189                   "ret $12");
1190
1191 /***********************************************************************
1192  *              InterlockedExchange (KERNEL32.@)
1193  */
1194 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1195 __ASM_GLOBAL_FUNC(InterlockedExchange,
1196                   "movl 8(%esp),%eax\n\t"
1197                   "movl 4(%esp),%edx\n\t"
1198                   "lock; xchgl %eax,(%edx)\n\t"
1199                   "ret $8");
1200
1201 /***********************************************************************
1202  *              InterlockedExchangeAdd (KERNEL32.@)
1203  */
1204 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1205 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1206                   "movl 8(%esp),%eax\n\t"
1207                   "movl 4(%esp),%edx\n\t"
1208                   "lock; xaddl %eax,(%edx)\n\t"
1209                   "ret $8");
1210
1211 /***********************************************************************
1212  *              InterlockedIncrement (KERNEL32.@)
1213  */
1214 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1215 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1216                   "movl 4(%esp),%edx\n\t"
1217                   "movl $1,%eax\n\t"
1218                   "lock; xaddl %eax,(%edx)\n\t"
1219                   "incl %eax\n\t"
1220                   "ret $4");
1221
1222 /***********************************************************************
1223  *              InterlockedDecrement (KERNEL32.@)
1224  */
1225 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1226                   "movl 4(%esp),%edx\n\t"
1227                   "movl $-1,%eax\n\t"
1228                   "lock; xaddl %eax,(%edx)\n\t"
1229                   "decl %eax\n\t"
1230                   "ret $4");
1231
1232 #else  /* __i386__ */
1233
1234 /***********************************************************************
1235  *              InterlockedCompareExchange (KERNEL32.@)
1236  */
1237 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1238 {
1239     return interlocked_cmpxchg( dest, xchg, compare );
1240 }
1241
1242 /***********************************************************************
1243  *              InterlockedExchange (KERNEL32.@)
1244  */
1245 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1246 {
1247     return interlocked_xchg( dest, val );
1248 }
1249
1250 /***********************************************************************
1251  *              InterlockedExchangeAdd (KERNEL32.@)
1252  */
1253 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1254 {
1255     return interlocked_xchg_add( dest, incr );
1256 }
1257
1258 /***********************************************************************
1259  *              InterlockedIncrement (KERNEL32.@)
1260  */
1261 LONG WINAPI InterlockedIncrement( PLONG dest )
1262 {
1263     return interlocked_xchg_add( dest, 1 ) + 1;
1264 }
1265
1266 /***********************************************************************
1267  *              InterlockedDecrement (KERNEL32.@)
1268  */
1269 LONG WINAPI InterlockedDecrement( PLONG dest )
1270 {
1271     return interlocked_xchg_add( dest, -1 ) - 1;
1272 }
1273
1274 #endif  /* __i386__ */