Remove duplicate code by using Nt* functions for PulseEvent,
[wine.git] / dlls / kernel / sync.c
blobe7aeabdf75f7ec1969868bbf9ac3e44f23e69946
1 /*
2 * Kernel synchronization objects
4 * Copyright 1998 Alexandre Julliard
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
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 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38 #include <stdarg.h>
39 #include <stdio.h>
41 #include "ntstatus.h"
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winnls.h"
46 #include "winreg.h"
47 #include "winternl.h"
49 #include "wine/server.h"
50 #include "wine/unicode.h"
51 #include "wine/winbase16.h"
52 #include "kernel_private.h"
54 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(sync);
58 /* check if current version is NT or Win95 */
59 inline static int is_version_nt(void)
61 return !(GetVersion() & 0x80000000);
65 /***********************************************************************
66 * Sleep (KERNEL32.@)
68 VOID WINAPI Sleep( DWORD timeout )
70 SleepEx( timeout, FALSE );
73 /******************************************************************************
74 * SleepEx (KERNEL32.@)
76 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
78 NTSTATUS status;
80 if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
81 else
83 LARGE_INTEGER time;
85 time.QuadPart = timeout * (ULONGLONG)10000;
86 time.QuadPart = -time.QuadPart;
87 status = NtDelayExecution( alertable, &time );
89 if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
90 return status;
94 /***********************************************************************
95 * WaitForSingleObject (KERNEL32.@)
97 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
99 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
103 /***********************************************************************
104 * WaitForSingleObjectEx (KERNEL32.@)
106 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
107 BOOL alertable )
109 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
113 /***********************************************************************
114 * WaitForMultipleObjects (KERNEL32.@)
116 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
117 BOOL wait_all, DWORD timeout )
119 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
123 /***********************************************************************
124 * WaitForMultipleObjectsEx (KERNEL32.@)
126 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
127 BOOL wait_all, DWORD timeout,
128 BOOL alertable )
130 NTSTATUS status;
131 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
132 int i;
134 if (count >= MAXIMUM_WAIT_OBJECTS)
136 SetLastError(ERROR_INVALID_PARAMETER);
137 return WAIT_FAILED;
139 for (i = 0; i < count; i++)
141 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
142 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
143 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
144 hloc[i] = GetStdHandle( (DWORD)handles[i] );
145 else
146 hloc[i] = handles[i];
148 /* yes, even screen buffer console handles are waitable, and are
149 * handled as a handle to the console itself !!
151 if (is_console_handle(hloc[i]))
153 if (!VerifyConsoleIoHandle(hloc[i]))
155 return FALSE;
157 hloc[i] = GetConsoleInputWaitHandle();
161 if (timeout == INFINITE)
163 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
165 else
167 LARGE_INTEGER time;
169 time.QuadPart = timeout * (ULONGLONG)10000;
170 time.QuadPart = -time.QuadPart;
171 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
174 if (HIWORD(status)) /* is it an error code? */
176 SetLastError( RtlNtStatusToDosError(status) );
177 status = WAIT_FAILED;
179 return status;
183 /***********************************************************************
184 * WaitForSingleObject (KERNEL.460)
186 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
188 DWORD retval, mutex_count;
190 ReleaseThunkLock( &mutex_count );
191 retval = WaitForSingleObject( handle, timeout );
192 RestoreThunkLock( mutex_count );
193 return retval;
196 /***********************************************************************
197 * WaitForMultipleObjects (KERNEL.461)
199 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
200 BOOL wait_all, DWORD timeout )
202 DWORD retval, mutex_count;
204 ReleaseThunkLock( &mutex_count );
205 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
206 RestoreThunkLock( mutex_count );
207 return retval;
210 /***********************************************************************
211 * WaitForMultipleObjectsEx (KERNEL.495)
213 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
214 BOOL wait_all, DWORD timeout, BOOL alertable )
216 DWORD retval, mutex_count;
218 ReleaseThunkLock( &mutex_count );
219 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
220 RestoreThunkLock( mutex_count );
221 return retval;
224 /***********************************************************************
225 * RegisterWaitForSingleObject (KERNEL32.@)
227 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
228 WAITORTIMERCALLBACK Callback, PVOID Context,
229 ULONG dwMilliseconds, ULONG dwFlags)
231 FIXME("%p %p %p %p %ld %ld\n",
232 phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
233 return FALSE;
236 /***********************************************************************
237 * RegisterWaitForSingleObjectEx (KERNEL32.@)
239 BOOL WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject,
240 WAITORTIMERCALLBACK Callback, PVOID Context,
241 ULONG dwMilliseconds, ULONG dwFlags )
243 FIXME("%p %p %p %ld %ld\n",
244 hObject,Callback,Context,dwMilliseconds,dwFlags);
245 return FALSE;
248 /***********************************************************************
249 * UnregisterWait (KERNEL32.@)
251 BOOL WINAPI UnregisterWait( HANDLE WaitHandle )
253 FIXME("%p\n",WaitHandle);
254 return FALSE;
257 /***********************************************************************
258 * UnregisterWaitEx (KERNEL32.@)
260 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
262 FIXME("%p %p\n",WaitHandle, CompletionEvent);
263 return FALSE;
266 /***********************************************************************
267 * SignalObjectAndWait (KERNEL32.@)
269 * Allows to atomically signal any of the synchro objects (semaphore,
270 * mutex, event) and wait on another.
272 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
274 FIXME("(%p %p %ld %d): stub\n", hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable);
275 return WAIT_OBJECT_0;
279 /***********************************************************************
280 * InitializeCriticalSection (KERNEL32.@)
282 * Initialise a critical section before use.
284 * PARAMS
285 * crit [O] Critical section to initialise.
287 * RETURNS
288 * Nothing. If the function fails an exception is raised.
290 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
292 NTSTATUS ret = RtlInitializeCriticalSection( crit );
293 if (ret) RtlRaiseStatus( ret );
296 /***********************************************************************
297 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
299 * Initialise a critical section with a spin count.
301 * PARAMS
302 * crit [O] Critical section to initialise.
303 * spincount [I] Number of times to spin upon contention.
305 * RETURNS
306 * Success: TRUE.
307 * Failure: Nothing. If the function fails an exception is raised.
309 * NOTES
310 * spincount is ignored on uni-processor systems.
312 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
314 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
315 if (ret) RtlRaiseStatus( ret );
316 return !ret;
319 /***********************************************************************
320 * SetCriticalSectionSpinCount (KERNEL32.@)
322 * Set the spin count for a critical section.
324 * PARAMS
325 * crit [O] Critical section to set the spin count for.
326 * spincount [I] Number of times to spin upon contention.
328 * RETURNS
329 * The previous spin count value of crit.
331 * NOTES
332 * This function is available on NT4SP3 or later, but not Win98.
334 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
336 ULONG_PTR oldspincount = crit->SpinCount;
337 if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
338 crit->SpinCount = spincount;
339 return oldspincount;
342 /***********************************************************************
343 * MakeCriticalSectionGlobal (KERNEL32.@)
345 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
347 /* let's assume that only one thread at a time will try to do this */
348 HANDLE sem = crit->LockSemaphore;
349 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
350 crit->LockSemaphore = ConvertToGlobalHandle( sem );
351 if (crit->DebugInfo)
353 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
354 crit->DebugInfo = NULL;
359 /***********************************************************************
360 * ReinitializeCriticalSection (KERNEL32.@)
362 * Initialise an already used critical section.
364 * PARAMS
365 * crit [O] Critical section to initialise.
367 * RETURNS
368 * Nothing.
370 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
372 if ( !crit->LockSemaphore )
373 RtlInitializeCriticalSection( crit );
377 /***********************************************************************
378 * UninitializeCriticalSection (KERNEL32.@)
380 * UnInitialise a critical section after use.
382 * PARAMS
383 * crit [O] Critical section to uninitialise (destroy).
385 * RETURNS
386 * Nothing.
388 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
390 RtlDeleteCriticalSection( crit );
394 /***********************************************************************
395 * CreateEventA (KERNEL32.@)
397 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
398 BOOL initial_state, LPCSTR name )
400 WCHAR buffer[MAX_PATH];
402 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
404 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
406 SetLastError( ERROR_FILENAME_EXCED_RANGE );
407 return 0;
409 return CreateEventW( sa, manual_reset, initial_state, buffer );
413 /***********************************************************************
414 * CreateEventW (KERNEL32.@)
416 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
417 BOOL initial_state, LPCWSTR name )
419 HANDLE ret;
420 DWORD len = name ? strlenW(name) : 0;
421 if (len >= MAX_PATH)
423 SetLastError( ERROR_FILENAME_EXCED_RANGE );
424 return 0;
426 /* one buggy program needs this
427 * ("Van Dale Groot woordenboek der Nederlandse taal")
429 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
431 ERR("Bad security attributes pointer %p\n",sa);
432 SetLastError( ERROR_INVALID_PARAMETER);
433 return 0;
435 SERVER_START_REQ( create_event )
437 req->manual_reset = manual_reset;
438 req->initial_state = initial_state;
439 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
440 wine_server_add_data( req, name, len * sizeof(WCHAR) );
441 SetLastError(0);
442 wine_server_call_err( req );
443 ret = reply->handle;
445 SERVER_END_REQ;
446 return ret;
450 /***********************************************************************
451 * CreateW32Event (KERNEL.457)
453 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
455 return CreateEventA( NULL, manual_reset, initial_state, NULL );
459 /***********************************************************************
460 * OpenEventA (KERNEL32.@)
462 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
464 WCHAR buffer[MAX_PATH];
466 if (!name) return OpenEventW( access, inherit, NULL );
468 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
470 SetLastError( ERROR_FILENAME_EXCED_RANGE );
471 return 0;
473 return OpenEventW( access, inherit, buffer );
477 /***********************************************************************
478 * OpenEventW (KERNEL32.@)
480 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
482 HANDLE ret;
483 DWORD len = name ? strlenW(name) : 0;
484 if (len >= MAX_PATH)
486 SetLastError( ERROR_FILENAME_EXCED_RANGE );
487 return 0;
489 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
491 SERVER_START_REQ( open_event )
493 req->access = access;
494 req->inherit = inherit;
495 wine_server_add_data( req, name, len * sizeof(WCHAR) );
496 wine_server_call_err( req );
497 ret = reply->handle;
499 SERVER_END_REQ;
500 return ret;
503 /***********************************************************************
504 * PulseEvent (KERNEL32.@)
506 BOOL WINAPI PulseEvent( HANDLE handle )
508 NTSTATUS status;
510 if ((status = NtPulseEvent( handle, NULL )))
511 SetLastError( RtlNtStatusToDosError(status) );
512 return !status;
516 /***********************************************************************
517 * SetW32Event (KERNEL.458)
518 * SetEvent (KERNEL32.@)
520 BOOL WINAPI SetEvent( HANDLE handle )
522 NTSTATUS status;
524 if ((status = NtSetEvent( handle, NULL )))
525 SetLastError( RtlNtStatusToDosError(status) );
526 return !status;
530 /***********************************************************************
531 * ResetW32Event (KERNEL.459)
532 * ResetEvent (KERNEL32.@)
534 BOOL WINAPI ResetEvent( HANDLE handle )
536 NTSTATUS status;
538 if ((status = NtResetEvent( handle, NULL )))
539 SetLastError( RtlNtStatusToDosError(status) );
540 return !status;
544 /***********************************************************************
545 * NOTE: The Win95 VWin32_Event routines given below are really low-level
546 * routines implemented directly by VWin32. The user-mode libraries
547 * implement Win32 synchronisation routines on top of these low-level
548 * primitives. We do it the other way around here :-)
551 /***********************************************************************
552 * VWin32_EventCreate (KERNEL.442)
554 HANDLE WINAPI VWin32_EventCreate(VOID)
556 HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
557 return ConvertToGlobalHandle( hEvent );
560 /***********************************************************************
561 * VWin32_EventDestroy (KERNEL.443)
563 VOID WINAPI VWin32_EventDestroy(HANDLE event)
565 CloseHandle( event );
568 /***********************************************************************
569 * VWin32_EventWait (KERNEL.450)
571 VOID WINAPI VWin32_EventWait(HANDLE event)
573 DWORD mutex_count;
575 ReleaseThunkLock( &mutex_count );
576 WaitForSingleObject( event, INFINITE );
577 RestoreThunkLock( mutex_count );
580 /***********************************************************************
581 * VWin32_EventSet (KERNEL.451)
582 * KERNEL_479 (KERNEL.479)
584 VOID WINAPI VWin32_EventSet(HANDLE event)
586 SetEvent( event );
591 /***********************************************************************
592 * CreateMutexA (KERNEL32.@)
594 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
596 WCHAR buffer[MAX_PATH];
598 if (!name) return CreateMutexW( sa, owner, NULL );
600 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
602 SetLastError( ERROR_FILENAME_EXCED_RANGE );
603 return 0;
605 return CreateMutexW( sa, owner, buffer );
609 /***********************************************************************
610 * CreateMutexW (KERNEL32.@)
612 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
614 HANDLE ret;
615 DWORD len = name ? strlenW(name) : 0;
616 if (len >= MAX_PATH)
618 SetLastError( ERROR_FILENAME_EXCED_RANGE );
619 return 0;
621 SERVER_START_REQ( create_mutex )
623 req->owned = owner;
624 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
625 wine_server_add_data( req, name, len * sizeof(WCHAR) );
626 SetLastError(0);
627 wine_server_call_err( req );
628 ret = reply->handle;
630 SERVER_END_REQ;
631 return ret;
635 /***********************************************************************
636 * OpenMutexA (KERNEL32.@)
638 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
640 WCHAR buffer[MAX_PATH];
642 if (!name) return OpenMutexW( access, inherit, NULL );
644 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
646 SetLastError( ERROR_FILENAME_EXCED_RANGE );
647 return 0;
649 return OpenMutexW( access, inherit, buffer );
653 /***********************************************************************
654 * OpenMutexW (KERNEL32.@)
656 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
658 HANDLE ret;
659 DWORD len = name ? strlenW(name) : 0;
660 if (len >= MAX_PATH)
662 SetLastError( ERROR_FILENAME_EXCED_RANGE );
663 return 0;
665 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
667 SERVER_START_REQ( open_mutex )
669 req->access = access;
670 req->inherit = inherit;
671 wine_server_add_data( req, name, len * sizeof(WCHAR) );
672 wine_server_call_err( req );
673 ret = reply->handle;
675 SERVER_END_REQ;
676 return ret;
680 /***********************************************************************
681 * ReleaseMutex (KERNEL32.@)
683 BOOL WINAPI ReleaseMutex( HANDLE handle )
685 BOOL ret;
686 SERVER_START_REQ( release_mutex )
688 req->handle = handle;
689 ret = !wine_server_call_err( req );
691 SERVER_END_REQ;
692 return ret;
697 * Semaphores
701 /***********************************************************************
702 * CreateSemaphoreA (KERNEL32.@)
704 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
706 WCHAR buffer[MAX_PATH];
708 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
710 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
712 SetLastError( ERROR_FILENAME_EXCED_RANGE );
713 return 0;
715 return CreateSemaphoreW( sa, initial, max, buffer );
719 /***********************************************************************
720 * CreateSemaphoreW (KERNEL32.@)
722 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
723 LONG max, LPCWSTR name )
725 HANDLE ret;
726 DWORD len = name ? strlenW(name) : 0;
728 /* Check parameters */
730 if ((max <= 0) || (initial < 0) || (initial > max))
732 SetLastError( ERROR_INVALID_PARAMETER );
733 return 0;
735 if (len >= MAX_PATH)
737 SetLastError( ERROR_FILENAME_EXCED_RANGE );
738 return 0;
741 SERVER_START_REQ( create_semaphore )
743 req->initial = (unsigned int)initial;
744 req->max = (unsigned int)max;
745 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
746 wine_server_add_data( req, name, len * sizeof(WCHAR) );
747 SetLastError(0);
748 wine_server_call_err( req );
749 ret = reply->handle;
751 SERVER_END_REQ;
752 return ret;
756 /***********************************************************************
757 * OpenSemaphoreA (KERNEL32.@)
759 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
761 WCHAR buffer[MAX_PATH];
763 if (!name) return OpenSemaphoreW( access, inherit, NULL );
765 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
767 SetLastError( ERROR_FILENAME_EXCED_RANGE );
768 return 0;
770 return OpenSemaphoreW( access, inherit, buffer );
774 /***********************************************************************
775 * OpenSemaphoreW (KERNEL32.@)
777 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
779 HANDLE ret;
780 DWORD len = name ? strlenW(name) : 0;
781 if (len >= MAX_PATH)
783 SetLastError( ERROR_FILENAME_EXCED_RANGE );
784 return 0;
786 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
788 SERVER_START_REQ( open_semaphore )
790 req->access = access;
791 req->inherit = inherit;
792 wine_server_add_data( req, name, len * sizeof(WCHAR) );
793 wine_server_call_err( req );
794 ret = reply->handle;
796 SERVER_END_REQ;
797 return ret;
801 /***********************************************************************
802 * ReleaseSemaphore (KERNEL32.@)
804 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
806 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
807 if (status) SetLastError( RtlNtStatusToDosError(status) );
808 return !status;
813 * Timers
817 /***********************************************************************
818 * CreateWaitableTimerA (KERNEL32.@)
820 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
822 WCHAR buffer[MAX_PATH];
824 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
826 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
828 SetLastError( ERROR_FILENAME_EXCED_RANGE );
829 return 0;
831 return CreateWaitableTimerW( sa, manual, buffer );
835 /***********************************************************************
836 * CreateWaitableTimerW (KERNEL32.@)
838 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
840 HANDLE handle;
841 NTSTATUS status;
842 UNICODE_STRING us;
843 DWORD attr = 0;
844 OBJECT_ATTRIBUTES oa;
846 if (name) RtlInitUnicodeString(&us, name);
847 if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
848 attr |= OBJ_INHERIT;
849 InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
850 NULL /* FIXME */, NULL /* FIXME */);
851 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
852 manual ? NotificationTimer : SynchronizationTimer);
854 if (status != STATUS_SUCCESS)
856 SetLastError( RtlNtStatusToDosError(status) );
857 return 0;
859 return handle;
863 /***********************************************************************
864 * OpenWaitableTimerA (KERNEL32.@)
866 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
868 WCHAR buffer[MAX_PATH];
870 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
872 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
874 SetLastError( ERROR_FILENAME_EXCED_RANGE );
875 return 0;
877 return OpenWaitableTimerW( access, inherit, buffer );
881 /***********************************************************************
882 * OpenWaitableTimerW (KERNEL32.@)
884 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
886 NTSTATUS status;
887 ULONG attr = 0;
888 UNICODE_STRING us;
889 HANDLE handle;
890 OBJECT_ATTRIBUTES oa;
892 if (inherit) attr |= OBJ_INHERIT;
894 if (name) RtlInitUnicodeString(&us, name);
895 InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
896 status = NtOpenTimer(&handle, access, &oa);
897 if (status != STATUS_SUCCESS)
899 SetLastError( RtlNtStatusToDosError(status) );
900 return 0;
902 return handle;
906 /***********************************************************************
907 * SetWaitableTimer (KERNEL32.@)
909 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
910 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
912 NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
914 if (status != STATUS_SUCCESS)
916 SetLastError( RtlNtStatusToDosError(status) );
917 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
919 return TRUE;
923 /***********************************************************************
924 * CancelWaitableTimer (KERNEL32.@)
926 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
928 NTSTATUS status;
930 status = NtCancelTimer(handle, NULL);
931 if (status != STATUS_SUCCESS)
933 SetLastError( RtlNtStatusToDosError(status) );
934 return FALSE;
936 return TRUE;
940 /***********************************************************************
941 * CreateTimerQueue (KERNEL32.@)
943 HANDLE WINAPI CreateTimerQueue(void)
945 FIXME("stub\n");
946 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
947 return NULL;
951 /***********************************************************************
952 * DeleteTimerQueueEx (KERNEL32.@)
954 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
956 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
957 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
958 return 0;
961 /***********************************************************************
962 * CreateTimerQueueTimer (KERNEL32.@)
964 * Creates a timer-queue timer. This timer expires at the specified due
965 * time (in ms), then after every specified period (in ms). When the timer
966 * expires, the callback function is called.
968 * RETURNS
969 * nonzero on success or zero on faillure
971 * BUGS
972 * Unimplemented
974 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
975 WAITORTIMERCALLBACK Callback, PVOID Parameter,
976 DWORD DueTime, DWORD Period, ULONG Flags )
978 FIXME("stub\n");
979 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
980 return TRUE;
983 /***********************************************************************
984 * DeleteTimerQueueTimer (KERNEL32.@)
986 * Cancels a timer-queue timer.
988 * RETURNS
989 * nonzero on success or zero on faillure
991 * BUGS
992 * Unimplemented
994 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
995 HANDLE CompletionEvent )
997 FIXME("stub\n");
998 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
999 return TRUE;
1004 * Pipes
1008 /***********************************************************************
1009 * CreateNamedPipeA (KERNEL32.@)
1011 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1012 DWORD dwPipeMode, DWORD nMaxInstances,
1013 DWORD nOutBufferSize, DWORD nInBufferSize,
1014 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1016 WCHAR buffer[MAX_PATH];
1018 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1019 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1021 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1023 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1024 return INVALID_HANDLE_VALUE;
1026 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1027 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1031 /***********************************************************************
1032 * CreateNamedPipeW (KERNEL32.@)
1034 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1035 DWORD dwPipeMode, DWORD nMaxInstances,
1036 DWORD nOutBufferSize, DWORD nInBufferSize,
1037 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1039 HANDLE ret;
1040 DWORD len;
1041 static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
1043 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1044 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1045 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1047 if (!name)
1049 SetLastError( ERROR_PATH_NOT_FOUND );
1050 return INVALID_HANDLE_VALUE;
1052 len = strlenW(name);
1053 if (len >= MAX_PATH)
1055 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1056 return INVALID_HANDLE_VALUE;
1058 if (strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0])))
1060 SetLastError( ERROR_INVALID_NAME );
1061 return INVALID_HANDLE_VALUE;
1063 SERVER_START_REQ( create_named_pipe )
1065 req->openmode = dwOpenMode;
1066 req->pipemode = dwPipeMode;
1067 req->maxinstances = nMaxInstances;
1068 req->outsize = nOutBufferSize;
1069 req->insize = nInBufferSize;
1070 req->timeout = nDefaultTimeOut;
1071 req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1072 wine_server_add_data( req, name, len * sizeof(WCHAR) );
1073 SetLastError(0);
1074 if (!wine_server_call_err( req )) ret = reply->handle;
1075 else ret = INVALID_HANDLE_VALUE;
1077 SERVER_END_REQ;
1078 return ret;
1082 /***********************************************************************
1083 * PeekNamedPipe (KERNEL32.@)
1085 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1086 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1088 #ifdef FIONREAD
1089 int avail=0, fd, ret, flags;
1091 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, NULL, &flags );
1092 if (ret)
1094 SetLastError( RtlNtStatusToDosError(ret) );
1095 return FALSE;
1097 if (flags & FD_FLAG_RECV_SHUTDOWN)
1099 wine_server_release_fd( hPipe, fd );
1100 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1101 return FALSE;
1104 if (ioctl(fd,FIONREAD, &avail ) != 0)
1106 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1107 wine_server_release_fd( hPipe, fd );
1108 return FALSE;
1110 if (!avail) /* check for closed pipe */
1112 struct pollfd pollfd;
1113 pollfd.fd = fd;
1114 pollfd.events = POLLIN;
1115 pollfd.revents = 0;
1116 switch (poll( &pollfd, 1, 0 ))
1118 case 0:
1119 break;
1120 case 1: /* got something */
1121 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1122 TRACE("POLLHUP | POLLERR\n");
1123 /* fall through */
1124 case -1:
1125 wine_server_release_fd( hPipe, fd );
1126 SetLastError(ERROR_BROKEN_PIPE);
1127 return FALSE;
1130 TRACE(" 0x%08x bytes available\n", avail );
1131 ret = TRUE;
1132 if (lpcbAvail)
1133 *lpcbAvail = avail;
1134 if (lpcbRead)
1135 *lpcbRead = 0;
1136 if (avail && lpvBuffer)
1138 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1139 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1140 if (readbytes < 0)
1142 WARN("failed to peek socket (%d)\n", errno);
1143 ret = FALSE;
1145 else if (lpcbRead)
1146 *lpcbRead = readbytes;
1148 wine_server_release_fd( hPipe, fd );
1149 return ret;
1150 #endif /* defined(FIONREAD) */
1152 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1153 FIXME("function not implemented\n");
1154 return FALSE;
1157 /***********************************************************************
1158 * SYNC_CompletePipeOverlapped (Internal)
1160 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1162 TRACE("for %p result %08lx\n",overlapped,result);
1163 if(!overlapped)
1164 return;
1165 overlapped->Internal = result;
1166 SetEvent(overlapped->hEvent);
1170 /***********************************************************************
1171 * WaitNamedPipeA (KERNEL32.@)
1173 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1175 WCHAR buffer[MAX_PATH];
1177 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1179 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1181 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1182 return 0;
1184 return WaitNamedPipeW( buffer, nTimeOut );
1188 /***********************************************************************
1189 * WaitNamedPipeW (KERNEL32.@)
1191 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1193 DWORD len = name ? strlenW(name) : 0;
1194 BOOL ret;
1195 OVERLAPPED ov;
1197 if (len >= MAX_PATH)
1199 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1200 return FALSE;
1203 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1205 memset(&ov,0,sizeof(ov));
1206 ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
1207 if (!ov.hEvent)
1208 return FALSE;
1210 SERVER_START_REQ( wait_named_pipe )
1212 req->timeout = nTimeOut;
1213 req->overlapped = &ov;
1214 req->func = SYNC_CompletePipeOverlapped;
1215 wine_server_add_data( req, name, len * sizeof(WCHAR) );
1216 ret = !wine_server_call_err( req );
1218 SERVER_END_REQ;
1220 if(ret)
1222 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1224 SetLastError(ov.Internal);
1225 ret = (ov.Internal==STATUS_SUCCESS);
1228 CloseHandle(ov.hEvent);
1229 return ret;
1233 /***********************************************************************
1234 * SYNC_ConnectNamedPipe (Internal)
1236 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1238 BOOL ret;
1240 if(!overlapped)
1241 return FALSE;
1243 overlapped->Internal = STATUS_PENDING;
1245 SERVER_START_REQ( connect_named_pipe )
1247 req->handle = hPipe;
1248 req->overlapped = overlapped;
1249 req->func = SYNC_CompletePipeOverlapped;
1250 ret = !wine_server_call_err( req );
1252 SERVER_END_REQ;
1254 return ret;
1257 /***********************************************************************
1258 * ConnectNamedPipe (KERNEL32.@)
1260 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1262 OVERLAPPED ov;
1263 BOOL ret;
1265 TRACE("(%p,%p)\n",hPipe, overlapped);
1267 if(overlapped)
1269 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1270 SetLastError( ERROR_IO_PENDING );
1271 return FALSE;
1274 memset(&ov,0,sizeof(ov));
1275 ov.hEvent = CreateEventA(NULL,0,0,NULL);
1276 if (!ov.hEvent)
1277 return FALSE;
1279 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1280 if(ret)
1282 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1284 SetLastError(ov.Internal);
1285 ret = (ov.Internal==STATUS_SUCCESS);
1289 CloseHandle(ov.hEvent);
1291 return ret;
1294 /***********************************************************************
1295 * DisconnectNamedPipe (KERNEL32.@)
1297 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1299 BOOL ret;
1301 TRACE("(%p)\n",hPipe);
1303 SERVER_START_REQ( disconnect_named_pipe )
1305 req->handle = hPipe;
1306 ret = !wine_server_call_err( req );
1307 if (ret && reply->fd != -1) close( reply->fd );
1309 SERVER_END_REQ;
1311 return ret;
1314 /***********************************************************************
1315 * TransactNamedPipe (KERNEL32.@)
1317 BOOL WINAPI TransactNamedPipe(
1318 HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1319 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1321 FIXME("%p %p %ld %p %ld %p %p\n",
1322 hPipe, lpInput, dwInputSize, lpOutput,
1323 dwOutputSize, lpBytesRead, lpOverlapped);
1324 if(lpBytesRead)
1325 *lpBytesRead=0;
1326 return FALSE;
1329 /***********************************************************************
1330 * GetNamedPipeInfo (KERNEL32.@)
1332 BOOL WINAPI GetNamedPipeInfo(
1333 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1334 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1336 BOOL ret;
1338 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1339 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1341 SERVER_START_REQ( get_named_pipe_info )
1343 req->handle = hNamedPipe;
1344 ret = !wine_server_call_err( req );
1345 if(lpFlags) *lpFlags = reply->flags;
1346 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1347 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1348 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1350 SERVER_END_REQ;
1352 return ret;
1355 /***********************************************************************
1356 * GetNamedPipeHandleStateA (KERNEL32.@)
1358 BOOL WINAPI GetNamedPipeHandleStateA(
1359 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1360 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1361 LPSTR lpUsername, DWORD nUsernameMaxSize)
1363 FIXME("%p %p %p %p %p %p %ld\n",
1364 hNamedPipe, lpState, lpCurInstances,
1365 lpMaxCollectionCount, lpCollectDataTimeout,
1366 lpUsername, nUsernameMaxSize);
1368 return FALSE;
1371 /***********************************************************************
1372 * GetNamedPipeHandleStateW (KERNEL32.@)
1374 BOOL WINAPI GetNamedPipeHandleStateW(
1375 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1376 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1377 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1379 FIXME("%p %p %p %p %p %p %ld\n",
1380 hNamedPipe, lpState, lpCurInstances,
1381 lpMaxCollectionCount, lpCollectDataTimeout,
1382 lpUsername, nUsernameMaxSize);
1384 return FALSE;
1387 /***********************************************************************
1388 * SetNamedPipeHandleState (KERNEL32.@)
1390 BOOL WINAPI SetNamedPipeHandleState(
1391 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1392 LPDWORD lpCollectDataTimeout)
1394 FIXME("%p %p %p %p\n",
1395 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1396 return FALSE;
1399 /***********************************************************************
1400 * CallNamedPipeA (KERNEL32.@)
1402 BOOL WINAPI CallNamedPipeA(
1403 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1404 LPVOID lpOutput, DWORD lpOutputSize,
1405 LPDWORD lpBytesRead, DWORD nTimeout)
1407 FIXME("%s %p %ld %p %ld %p %ld\n",
1408 debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1409 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1410 return FALSE;
1413 /***********************************************************************
1414 * CallNamedPipeW (KERNEL32.@)
1416 BOOL WINAPI CallNamedPipeW(
1417 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1418 LPVOID lpOutput, DWORD lpOutputSize,
1419 LPDWORD lpBytesRead, DWORD nTimeout)
1421 FIXME("%s %p %ld %p %ld %p %ld\n",
1422 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1423 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1424 return FALSE;
1427 /******************************************************************
1428 * CreatePipe (KERNEL32.@)
1431 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1432 LPSECURITY_ATTRIBUTES sa, DWORD size )
1434 static unsigned index = 0;
1435 char name[64];
1436 HANDLE hr, hw;
1437 unsigned in_index = index;
1439 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1440 /* generate a unique pipe name (system wide) */
1443 sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1444 hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND,
1445 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1446 NMPWAIT_USE_DEFAULT_WAIT, sa);
1447 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1448 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1449 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1451 hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1452 if (hw == INVALID_HANDLE_VALUE)
1454 CloseHandle(hr);
1455 return FALSE;
1458 *hReadPipe = hr;
1459 *hWritePipe = hw;
1460 return TRUE;
1464 /******************************************************************************
1465 * CreateMailslotA [KERNEL32.@]
1467 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1468 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1470 DWORD len;
1471 HANDLE handle;
1472 LPWSTR name = NULL;
1474 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1475 nMaxMessageSize, lReadTimeout, sa);
1477 if( lpName )
1479 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1480 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1481 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1484 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1486 if( name )
1487 HeapFree( GetProcessHeap(), 0, name );
1489 return handle;
1493 /******************************************************************************
1494 * CreateMailslotW [KERNEL32.@]
1496 * Create a mailslot with specified name.
1498 * PARAMS
1499 * lpName [I] Pointer to string for mailslot name
1500 * nMaxMessageSize [I] Maximum message size
1501 * lReadTimeout [I] Milliseconds before read time-out
1502 * sa [I] Pointer to security structure
1504 * RETURNS
1505 * Success: Handle to mailslot
1506 * Failure: INVALID_HANDLE_VALUE
1508 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1509 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1511 FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1512 nMaxMessageSize, lReadTimeout, sa);
1513 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1514 return INVALID_HANDLE_VALUE;
1518 /******************************************************************************
1519 * GetMailslotInfo [KERNEL32.@]
1521 * Retrieve information about a mailslot.
1523 * PARAMS
1524 * hMailslot [I] Mailslot handle
1525 * lpMaxMessageSize [O] Address of maximum message size
1526 * lpNextSize [O] Address of size of next message
1527 * lpMessageCount [O] Address of number of messages
1528 * lpReadTimeout [O] Address of read time-out
1530 * RETURNS
1531 * Success: TRUE
1532 * Failure: FALSE
1534 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1535 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1536 LPDWORD lpReadTimeout )
1538 FIXME("(%p): stub\n",hMailslot);
1539 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1540 return FALSE;
1544 /******************************************************************************
1545 * SetMailslotInfo [KERNEL32.@]
1547 * Set the read timeout of a mailslot.
1549 * PARAMS
1550 * hMailslot [I] Mailslot handle
1551 * dwReadTimeout [I] Timeout in milliseconds.
1553 * RETURNS
1554 * Success: TRUE
1555 * Failure: FALSE
1557 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1559 FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1560 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1561 return FALSE;
1565 /******************************************************************************
1566 * CreateIoCompletionPort (KERNEL32.@)
1568 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1569 DWORD dwCompletionKey, DWORD dwNumberOfConcurrentThreads)
1571 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1572 hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads);
1573 return NULL;
1577 /******************************************************************************
1578 * GetQueuedCompletionStatus (KERNEL32.@)
1580 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1581 LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped,
1582 DWORD dwMilliseconds )
1584 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1585 CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds);
1586 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1587 return FALSE;
1590 /******************************************************************************
1591 * CreateJobObjectW (KERNEL32.@)
1593 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1595 FIXME("%p %s\n", attr, debugstr_w(name) );
1596 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1597 return 0;
1600 /******************************************************************************
1601 * CreateJobObjectA (KERNEL32.@)
1603 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1605 LPWSTR str = NULL;
1606 UINT len;
1607 HANDLE r;
1609 TRACE("%p %s\n", attr, debugstr_a(name) );
1611 if( name )
1613 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1614 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1615 if( !str )
1617 SetLastError( ERROR_OUTOFMEMORY );
1618 return 0;
1620 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1623 r = CreateJobObjectW( attr, str );
1625 if( str )
1626 HeapFree( GetProcessHeap(), 0, str );
1628 return r;
1631 /******************************************************************************
1632 * AssignProcessToJobObject (KERNEL32.@)
1634 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1636 FIXME("%p %p\n", hJob, hProcess);
1637 return TRUE;
1640 #ifdef __i386__
1642 /***********************************************************************
1643 * InterlockedCompareExchange (KERNEL32.@)
1645 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1646 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1647 "movl 12(%esp),%eax\n\t"
1648 "movl 8(%esp),%ecx\n\t"
1649 "movl 4(%esp),%edx\n\t"
1650 "lock; cmpxchgl %ecx,(%edx)\n\t"
1651 "ret $12");
1653 /***********************************************************************
1654 * InterlockedExchange (KERNEL32.@)
1656 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1657 __ASM_GLOBAL_FUNC(InterlockedExchange,
1658 "movl 8(%esp),%eax\n\t"
1659 "movl 4(%esp),%edx\n\t"
1660 "lock; xchgl %eax,(%edx)\n\t"
1661 "ret $8");
1663 /***********************************************************************
1664 * InterlockedExchangeAdd (KERNEL32.@)
1666 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1667 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1668 "movl 8(%esp),%eax\n\t"
1669 "movl 4(%esp),%edx\n\t"
1670 "lock; xaddl %eax,(%edx)\n\t"
1671 "ret $8");
1673 /***********************************************************************
1674 * InterlockedIncrement (KERNEL32.@)
1676 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1677 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1678 "movl 4(%esp),%edx\n\t"
1679 "movl $1,%eax\n\t"
1680 "lock; xaddl %eax,(%edx)\n\t"
1681 "incl %eax\n\t"
1682 "ret $4");
1684 /***********************************************************************
1685 * InterlockedDecrement (KERNEL32.@)
1687 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1688 "movl 4(%esp),%edx\n\t"
1689 "movl $-1,%eax\n\t"
1690 "lock; xaddl %eax,(%edx)\n\t"
1691 "decl %eax\n\t"
1692 "ret $4");
1694 #else /* __i386__ */
1696 /***********************************************************************
1697 * InterlockedCompareExchange (KERNEL32.@)
1699 * Atomically swap one value with another.
1701 * PARAMS
1702 * dest [I/O] The value to replace
1703 * xchq [I] The value to be swapped
1704 * compare [I] The value to compare to dest
1706 * RETURNS
1707 * The resulting value of dest.
1709 * NOTES
1710 * dest is updated only if it is equal to compare, otherwise no swap is done.
1712 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1714 return interlocked_cmpxchg( dest, xchg, compare );
1717 /***********************************************************************
1718 * InterlockedExchange (KERNEL32.@)
1720 * Atomically swap one value with another.
1722 * PARAMS
1723 * dest [I/O] The value to replace
1724 * val [I] The value to be swapped
1726 * RETURNS
1727 * The resulting value of dest.
1729 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1731 return interlocked_xchg( dest, val );
1734 /***********************************************************************
1735 * InterlockedExchangeAdd (KERNEL32.@)
1737 * Atomically add one value to another.
1739 * PARAMS
1740 * dest [I/O] The value to add to
1741 * incr [I] The value to be added
1743 * RETURNS
1744 * The resulting value of dest.
1746 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1748 return interlocked_xchg_add( dest, incr );
1751 /***********************************************************************
1752 * InterlockedIncrement (KERNEL32.@)
1754 * Atomically increment a value.
1756 * PARAMS
1757 * dest [I/O] The value to increment
1759 * RETURNS
1760 * The resulting value of dest.
1762 LONG WINAPI InterlockedIncrement( PLONG dest )
1764 return interlocked_xchg_add( dest, 1 ) + 1;
1767 /***********************************************************************
1768 * InterlockedDecrement (KERNEL32.@)
1770 * Atomically decrement a value.
1772 * PARAMS
1773 * dest [I/O] The value to decrement
1775 * RETURNS
1776 * The resulting value of dest.
1778 LONG WINAPI InterlockedDecrement( PLONG dest )
1780 return interlocked_xchg_add( dest, -1 ) - 1;
1783 #endif /* __i386__ */