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
22 #include "wine/port.h"
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
32 #ifdef HAVE_SYS_POLL_H
41 #include "wine/server.h"
42 #include "wine/unicode.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(win32
);
49 /* check if current version is NT or Win95 */
50 inline static int is_version_nt(void)
52 return !(GetVersion() & 0x80000000);
56 /***********************************************************************
57 * InitializeCriticalSection (KERNEL32.@)
59 void WINAPI
InitializeCriticalSection( CRITICAL_SECTION
*crit
)
61 NTSTATUS ret
= RtlInitializeCriticalSection( crit
);
62 if (ret
) RtlRaiseStatus( ret
);
65 /***********************************************************************
66 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
68 BOOL WINAPI
InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION
*crit
, DWORD spincount
)
70 NTSTATUS ret
= RtlInitializeCriticalSectionAndSpinCount( crit
, spincount
);
71 if (ret
) RtlRaiseStatus( ret
);
75 /***********************************************************************
76 * SetCriticalSectionSpinCount (KERNEL32.@)
77 * This function is available on NT4SP3 or later, but not Win98
80 DWORD WINAPI
SetCriticalSectionSpinCount( CRITICAL_SECTION
*crit
, DWORD spincount
)
82 ULONG_PTR oldspincount
= crit
->SpinCount
;
83 if(spincount
) FIXME("critsection=%p: spincount=%ld not supported\n", crit
, spincount
);
84 crit
->SpinCount
= spincount
;
88 /***********************************************************************
89 * MakeCriticalSectionGlobal (KERNEL32.@)
91 void WINAPI
MakeCriticalSectionGlobal( CRITICAL_SECTION
*crit
)
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
);
100 /***********************************************************************
101 * ReinitializeCriticalSection (KERNEL32.@)
103 void WINAPI
ReinitializeCriticalSection( CRITICAL_SECTION
*crit
)
105 if ( !crit
->LockSemaphore
)
106 RtlInitializeCriticalSection( crit
);
110 /***********************************************************************
111 * UninitializeCriticalSection (KERNEL32.@)
113 void WINAPI
UninitializeCriticalSection( CRITICAL_SECTION
*crit
)
115 RtlDeleteCriticalSection( crit
);
119 /***********************************************************************
120 * CreateEventA (KERNEL32.@)
122 HANDLE WINAPI
CreateEventA( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
123 BOOL initial_state
, LPCSTR name
)
125 WCHAR buffer
[MAX_PATH
];
127 if (!name
) return CreateEventW( sa
, manual_reset
, initial_state
, NULL
);
129 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
131 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
134 return CreateEventW( sa
, manual_reset
, initial_state
, buffer
);
138 /***********************************************************************
139 * CreateEventW (KERNEL32.@)
141 HANDLE WINAPI
CreateEventW( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
142 BOOL initial_state
, LPCWSTR name
)
145 DWORD len
= name
? strlenW(name
) : 0;
148 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
151 /* one buggy program needs this
152 * ("Van Dale Groot woordenboek der Nederlandse taal")
154 if (sa
&& IsBadReadPtr(sa
,sizeof(SECURITY_ATTRIBUTES
)))
156 ERR("Bad security attributes pointer %p\n",sa
);
157 SetLastError( ERROR_INVALID_PARAMETER
);
160 SERVER_START_REQ( create_event
)
162 req
->manual_reset
= manual_reset
;
163 req
->initial_state
= initial_state
;
164 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
165 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
167 wine_server_call_err( req
);
175 /***********************************************************************
176 * CreateW32Event (KERNEL.457)
178 HANDLE WINAPI
WIN16_CreateEvent( BOOL manual_reset
, BOOL initial_state
)
180 return CreateEventA( NULL
, manual_reset
, initial_state
, NULL
);
184 /***********************************************************************
185 * OpenEventA (KERNEL32.@)
187 HANDLE WINAPI
OpenEventA( DWORD access
, BOOL inherit
, LPCSTR name
)
189 WCHAR buffer
[MAX_PATH
];
191 if (!name
) return OpenEventW( access
, inherit
, NULL
);
193 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
195 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
198 return OpenEventW( access
, inherit
, buffer
);
202 /***********************************************************************
203 * OpenEventW (KERNEL32.@)
205 HANDLE WINAPI
OpenEventW( DWORD access
, BOOL inherit
, LPCWSTR name
)
208 DWORD len
= name
? strlenW(name
) : 0;
211 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
214 if (!is_version_nt()) access
= EVENT_ALL_ACCESS
;
216 SERVER_START_REQ( open_event
)
218 req
->access
= access
;
219 req
->inherit
= inherit
;
220 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
221 wine_server_call_err( req
);
229 /***********************************************************************
232 * Execute an event operation (set,reset,pulse).
234 static BOOL
EVENT_Operation( HANDLE handle
, enum event_op op
)
237 SERVER_START_REQ( event_op
)
239 req
->handle
= handle
;
241 ret
= !wine_server_call_err( req
);
248 /***********************************************************************
249 * PulseEvent (KERNEL32.@)
251 BOOL WINAPI
PulseEvent( HANDLE handle
)
253 return EVENT_Operation( handle
, PULSE_EVENT
);
257 /***********************************************************************
258 * SetW32Event (KERNEL.458)
259 * SetEvent (KERNEL32.@)
261 BOOL WINAPI
SetEvent( HANDLE handle
)
263 return EVENT_Operation( handle
, SET_EVENT
);
267 /***********************************************************************
268 * ResetW32Event (KERNEL.459)
269 * ResetEvent (KERNEL32.@)
271 BOOL WINAPI
ResetEvent( HANDLE handle
)
273 return EVENT_Operation( handle
, RESET_EVENT
);
277 /***********************************************************************
278 * NOTE: The Win95 VWin32_Event routines given below are really low-level
279 * routines implemented directly by VWin32. The user-mode libraries
280 * implement Win32 synchronisation routines on top of these low-level
281 * primitives. We do it the other way around here :-)
284 /***********************************************************************
285 * VWin32_EventCreate (KERNEL.442)
287 HANDLE WINAPI
VWin32_EventCreate(VOID
)
289 HANDLE hEvent
= CreateEventA( NULL
, FALSE
, 0, NULL
);
290 return ConvertToGlobalHandle( hEvent
);
293 /***********************************************************************
294 * VWin32_EventDestroy (KERNEL.443)
296 VOID WINAPI
VWin32_EventDestroy(HANDLE event
)
298 CloseHandle( event
);
301 /***********************************************************************
302 * VWin32_EventWait (KERNEL.450)
304 VOID WINAPI
VWin32_EventWait(HANDLE event
)
308 ReleaseThunkLock( &mutex_count
);
309 WaitForSingleObject( event
, INFINITE
);
310 RestoreThunkLock( mutex_count
);
313 /***********************************************************************
314 * VWin32_EventSet (KERNEL.451)
315 * KERNEL_479 (KERNEL.479)
317 VOID WINAPI
VWin32_EventSet(HANDLE event
)
324 /***********************************************************************
325 * CreateMutexA (KERNEL32.@)
327 HANDLE WINAPI
CreateMutexA( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCSTR name
)
329 WCHAR buffer
[MAX_PATH
];
331 if (!name
) return CreateMutexW( sa
, owner
, NULL
);
333 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
335 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
338 return CreateMutexW( sa
, owner
, buffer
);
342 /***********************************************************************
343 * CreateMutexW (KERNEL32.@)
345 HANDLE WINAPI
CreateMutexW( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCWSTR name
)
348 DWORD len
= name
? strlenW(name
) : 0;
351 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
354 SERVER_START_REQ( create_mutex
)
357 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
358 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
360 wine_server_call_err( req
);
368 /***********************************************************************
369 * OpenMutexA (KERNEL32.@)
371 HANDLE WINAPI
OpenMutexA( DWORD access
, BOOL inherit
, LPCSTR name
)
373 WCHAR buffer
[MAX_PATH
];
375 if (!name
) return OpenMutexW( access
, inherit
, NULL
);
377 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
379 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
382 return OpenMutexW( access
, inherit
, buffer
);
386 /***********************************************************************
387 * OpenMutexW (KERNEL32.@)
389 HANDLE WINAPI
OpenMutexW( DWORD access
, BOOL inherit
, LPCWSTR name
)
392 DWORD len
= name
? strlenW(name
) : 0;
395 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
398 if (!is_version_nt()) access
= MUTEX_ALL_ACCESS
;
400 SERVER_START_REQ( open_mutex
)
402 req
->access
= access
;
403 req
->inherit
= inherit
;
404 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
405 wine_server_call_err( req
);
413 /***********************************************************************
414 * ReleaseMutex (KERNEL32.@)
416 BOOL WINAPI
ReleaseMutex( HANDLE handle
)
419 SERVER_START_REQ( release_mutex
)
421 req
->handle
= handle
;
422 ret
= !wine_server_call_err( req
);
434 /***********************************************************************
435 * CreateSemaphoreA (KERNEL32.@)
437 HANDLE WINAPI
CreateSemaphoreA( SECURITY_ATTRIBUTES
*sa
, LONG initial
, LONG max
, LPCSTR name
)
439 WCHAR buffer
[MAX_PATH
];
441 if (!name
) return CreateSemaphoreW( sa
, initial
, max
, NULL
);
443 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
445 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
448 return CreateSemaphoreW( sa
, initial
, max
, buffer
);
452 /***********************************************************************
453 * CreateSemaphoreW (KERNEL32.@)
455 HANDLE WINAPI
CreateSemaphoreW( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
456 LONG max
, LPCWSTR name
)
459 DWORD len
= name
? strlenW(name
) : 0;
461 /* Check parameters */
463 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
465 SetLastError( ERROR_INVALID_PARAMETER
);
470 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
474 SERVER_START_REQ( create_semaphore
)
476 req
->initial
= (unsigned int)initial
;
477 req
->max
= (unsigned int)max
;
478 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
479 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
481 wine_server_call_err( req
);
489 /***********************************************************************
490 * OpenSemaphoreA (KERNEL32.@)
492 HANDLE WINAPI
OpenSemaphoreA( DWORD access
, BOOL inherit
, LPCSTR name
)
494 WCHAR buffer
[MAX_PATH
];
496 if (!name
) return OpenSemaphoreW( access
, inherit
, NULL
);
498 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
500 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
503 return OpenSemaphoreW( access
, inherit
, buffer
);
507 /***********************************************************************
508 * OpenSemaphoreW (KERNEL32.@)
510 HANDLE WINAPI
OpenSemaphoreW( DWORD access
, BOOL inherit
, LPCWSTR name
)
513 DWORD len
= name
? strlenW(name
) : 0;
516 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
519 if (!is_version_nt()) access
= SEMAPHORE_ALL_ACCESS
;
521 SERVER_START_REQ( open_semaphore
)
523 req
->access
= access
;
524 req
->inherit
= inherit
;
525 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
526 wine_server_call_err( req
);
534 /***********************************************************************
535 * ReleaseSemaphore (KERNEL32.@)
537 BOOL WINAPI
ReleaseSemaphore( HANDLE handle
, LONG count
, LONG
*previous
)
539 NTSTATUS status
= NtReleaseSemaphore( handle
, count
, previous
);
540 if (status
) SetLastError( RtlNtStatusToDosError(status
) );
550 /***********************************************************************
551 * CreateWaitableTimerA (KERNEL32.@)
553 HANDLE WINAPI
CreateWaitableTimerA( SECURITY_ATTRIBUTES
*sa
, BOOL manual
, LPCSTR name
)
555 WCHAR buffer
[MAX_PATH
];
557 if (!name
) return CreateWaitableTimerW( sa
, manual
, NULL
);
559 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
561 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
564 return CreateWaitableTimerW( sa
, manual
, buffer
);
568 /***********************************************************************
569 * CreateWaitableTimerW (KERNEL32.@)
571 HANDLE WINAPI
CreateWaitableTimerW( SECURITY_ATTRIBUTES
*sa
, BOOL manual
, LPCWSTR name
)
577 OBJECT_ATTRIBUTES oa
;
579 if (name
) RtlInitUnicodeString(&us
, name
);
580 if (sa
&& (sa
->nLength
>= sizeof(*sa
)) && sa
->bInheritHandle
)
582 InitializeObjectAttributes(&oa
, name
? &us
: NULL
, attr
,
583 NULL
/* FIXME */, NULL
/* FIXME */);
584 status
= NtCreateTimer(&handle
, TIMER_ALL_ACCESS
, &oa
,
585 manual
? NotificationTimer
: SynchronizationTimer
);
587 if (status
!= STATUS_SUCCESS
)
589 SetLastError( RtlNtStatusToDosError(status
) );
596 /***********************************************************************
597 * OpenWaitableTimerA (KERNEL32.@)
599 HANDLE WINAPI
OpenWaitableTimerA( DWORD access
, BOOL inherit
, LPCSTR name
)
601 WCHAR buffer
[MAX_PATH
];
603 if (!name
) return OpenWaitableTimerW( access
, inherit
, NULL
);
605 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
607 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
610 return OpenWaitableTimerW( access
, inherit
, buffer
);
614 /***********************************************************************
615 * OpenWaitableTimerW (KERNEL32.@)
617 HANDLE WINAPI
OpenWaitableTimerW( DWORD access
, BOOL inherit
, LPCWSTR name
)
623 OBJECT_ATTRIBUTES oa
;
625 if (inherit
) attr
|= OBJ_INHERIT
;
627 if (name
) RtlInitUnicodeString(&us
, name
);
628 InitializeObjectAttributes(&oa
, name
? &us
: NULL
, attr
, NULL
/* FIXME */, NULL
/* FIXME */);
629 status
= NtOpenTimer(&handle
, access
, &oa
);
630 if (status
!= STATUS_SUCCESS
)
632 SetLastError( RtlNtStatusToDosError(status
) );
639 /***********************************************************************
640 * SetWaitableTimer (KERNEL32.@)
642 BOOL WINAPI
SetWaitableTimer( HANDLE handle
, const LARGE_INTEGER
*when
, LONG period
,
643 PTIMERAPCROUTINE callback
, LPVOID arg
, BOOL resume
)
645 NTSTATUS status
= NtSetTimer(handle
, when
, callback
, arg
, resume
, period
, NULL
);
647 if (status
!= STATUS_SUCCESS
)
649 SetLastError( RtlNtStatusToDosError(status
) );
650 if (status
!= STATUS_TIMER_RESUME_IGNORED
) return FALSE
;
656 /***********************************************************************
657 * CancelWaitableTimer (KERNEL32.@)
659 BOOL WINAPI
CancelWaitableTimer( HANDLE handle
)
663 status
= NtCancelTimer(handle
, NULL
);
664 if (status
!= STATUS_SUCCESS
)
666 SetLastError( RtlNtStatusToDosError(status
) );
673 /***********************************************************************
674 * CreateTimerQueue (KERNEL32.@)
676 HANDLE WINAPI
CreateTimerQueue(void)
679 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
684 /***********************************************************************
685 * DeleteTimerQueueEx (KERNEL32.@)
687 BOOL WINAPI
DeleteTimerQueueEx(HANDLE TimerQueue
, HANDLE CompletionEvent
)
689 FIXME("(%p, %p): stub\n", TimerQueue
, CompletionEvent
);
690 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
694 /***********************************************************************
695 * CreateTimerQueueTimer (KERNEL32.@)
697 * Creates a timer-queue timer. This timer expires at the specified due
698 * time (in ms), then after every specified period (in ms). When the timer
699 * expires, the callback function is called.
702 * nonzero on success or zero on faillure
707 BOOL WINAPI
CreateTimerQueueTimer( PHANDLE phNewTimer
, HANDLE TimerQueue
,
708 WAITORTIMERCALLBACK Callback
, PVOID Parameter
,
709 DWORD DueTime
, DWORD Period
, ULONG Flags
)
712 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
716 /***********************************************************************
717 * DeleteTimerQueueTimer (KERNEL32.@)
719 * Cancels a timer-queue timer.
722 * nonzero on success or zero on faillure
727 BOOL WINAPI
DeleteTimerQueueTimer( HANDLE TimerQueue
, HANDLE Timer
,
728 HANDLE CompletionEvent
)
731 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
741 /***********************************************************************
742 * CreateNamedPipeA (KERNEL32.@)
744 HANDLE WINAPI
CreateNamedPipeA( LPCSTR name
, DWORD dwOpenMode
,
745 DWORD dwPipeMode
, DWORD nMaxInstances
,
746 DWORD nOutBufferSize
, DWORD nInBufferSize
,
747 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
749 WCHAR buffer
[MAX_PATH
];
751 if (!name
) return CreateNamedPipeW( NULL
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
752 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
754 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
756 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
757 return INVALID_HANDLE_VALUE
;
759 return CreateNamedPipeW( buffer
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
760 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
764 /***********************************************************************
765 * CreateNamedPipeW (KERNEL32.@)
767 HANDLE WINAPI
CreateNamedPipeW( LPCWSTR name
, DWORD dwOpenMode
,
768 DWORD dwPipeMode
, DWORD nMaxInstances
,
769 DWORD nOutBufferSize
, DWORD nInBufferSize
,
770 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
774 static const WCHAR leadin
[] = {'\\','\\','.','\\','P','I','P','E','\\'};
776 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
777 debugstr_w(name
), dwOpenMode
, dwPipeMode
, nMaxInstances
,
778 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
782 SetLastError( ERROR_PATH_NOT_FOUND
);
783 return INVALID_HANDLE_VALUE
;
788 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
789 return INVALID_HANDLE_VALUE
;
791 if (strncmpiW(name
, leadin
, sizeof(leadin
)/sizeof(leadin
[0])))
793 SetLastError( ERROR_INVALID_NAME
);
794 return INVALID_HANDLE_VALUE
;
796 SERVER_START_REQ( create_named_pipe
)
798 req
->openmode
= dwOpenMode
;
799 req
->pipemode
= dwPipeMode
;
800 req
->maxinstances
= nMaxInstances
;
801 req
->outsize
= nOutBufferSize
;
802 req
->insize
= nInBufferSize
;
803 req
->timeout
= nDefaultTimeOut
;
804 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
806 if (!wine_server_call_err( req
)) ret
= reply
->handle
;
807 else ret
= INVALID_HANDLE_VALUE
;
814 /***********************************************************************
815 * PeekNamedPipe (KERNEL32.@)
817 BOOL WINAPI
PeekNamedPipe( HANDLE hPipe
, LPVOID lpvBuffer
, DWORD cbBuffer
,
818 LPDWORD lpcbRead
, LPDWORD lpcbAvail
, LPDWORD lpcbMessage
)
823 fd
= FILE_GetUnixHandle(hPipe
, GENERIC_READ
);
824 if (fd
== -1) return FALSE
;
826 if (ioctl(fd
,FIONREAD
, &avail
) != 0)
828 TRACE("FIONREAD failed reason: %s\n",strerror(errno
));
832 if (!avail
) /* check for closed pipe */
834 struct pollfd pollfd
;
836 pollfd
.events
= POLLIN
;
838 switch (poll( &pollfd
, 1, 0 ))
842 case 1: /* got something */
843 if (!(pollfd
.revents
& (POLLHUP
| POLLERR
))) break;
844 TRACE("POLLHUP | POLLERR\n");
848 SetLastError(ERROR_BROKEN_PIPE
);
853 TRACE(" 0x%08x bytes available\n", avail
);
854 if (!lpvBuffer
&& lpcbAvail
)
859 #endif /* defined(FIONREAD) */
861 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
862 FIXME("function not implemented\n");
866 /***********************************************************************
867 * SYNC_CompletePipeOverlapped (Internal)
869 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped
, DWORD result
)
871 TRACE("for %p result %08lx\n",overlapped
,result
);
874 overlapped
->Internal
= result
;
875 SetEvent(overlapped
->hEvent
);
879 /***********************************************************************
880 * WaitNamedPipeA (KERNEL32.@)
882 BOOL WINAPI
WaitNamedPipeA (LPCSTR name
, DWORD nTimeOut
)
884 WCHAR buffer
[MAX_PATH
];
886 if (!name
) return WaitNamedPipeW( NULL
, nTimeOut
);
888 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
890 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
893 return WaitNamedPipeW( buffer
, nTimeOut
);
897 /***********************************************************************
898 * WaitNamedPipeW (KERNEL32.@)
900 BOOL WINAPI
WaitNamedPipeW (LPCWSTR name
, DWORD nTimeOut
)
902 DWORD len
= name
? strlenW(name
) : 0;
908 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
912 TRACE("%s 0x%08lx\n",debugstr_w(name
),nTimeOut
);
914 memset(&ov
,0,sizeof(ov
));
915 ov
.hEvent
= CreateEventA( NULL
, 0, 0, NULL
);
919 SERVER_START_REQ( wait_named_pipe
)
921 req
->timeout
= nTimeOut
;
922 req
->overlapped
= &ov
;
923 req
->func
= SYNC_CompletePipeOverlapped
;
924 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
925 ret
= !wine_server_call_err( req
);
931 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
933 SetLastError(ov
.Internal
);
934 ret
= (ov
.Internal
==STATUS_SUCCESS
);
937 CloseHandle(ov
.hEvent
);
942 /***********************************************************************
943 * SYNC_ConnectNamedPipe (Internal)
945 static BOOL
SYNC_ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
952 overlapped
->Internal
= STATUS_PENDING
;
954 SERVER_START_REQ( connect_named_pipe
)
957 req
->overlapped
= overlapped
;
958 req
->func
= SYNC_CompletePipeOverlapped
;
959 ret
= !wine_server_call_err( req
);
966 /***********************************************************************
967 * ConnectNamedPipe (KERNEL32.@)
969 BOOL WINAPI
ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
974 TRACE("(%p,%p)\n",hPipe
, overlapped
);
978 if(SYNC_ConnectNamedPipe(hPipe
,overlapped
))
979 SetLastError( ERROR_IO_PENDING
);
983 memset(&ov
,0,sizeof(ov
));
984 ov
.hEvent
= CreateEventA(NULL
,0,0,NULL
);
988 ret
=SYNC_ConnectNamedPipe(hPipe
, &ov
);
991 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
993 SetLastError(ov
.Internal
);
994 ret
= (ov
.Internal
==STATUS_SUCCESS
);
998 CloseHandle(ov
.hEvent
);
1003 /***********************************************************************
1004 * DisconnectNamedPipe (KERNEL32.@)
1006 BOOL WINAPI
DisconnectNamedPipe(HANDLE hPipe
)
1010 TRACE("(%p)\n",hPipe
);
1012 SERVER_START_REQ( disconnect_named_pipe
)
1014 req
->handle
= hPipe
;
1015 ret
= !wine_server_call_err( req
);
1016 if (ret
&& reply
->fd
!= -1) close( reply
->fd
);
1023 /***********************************************************************
1024 * TransactNamedPipe (KERNEL32.@)
1026 BOOL WINAPI
TransactNamedPipe(
1027 HANDLE hPipe
, LPVOID lpInput
, DWORD dwInputSize
, LPVOID lpOutput
,
1028 DWORD dwOutputSize
, LPDWORD lpBytesRead
, LPOVERLAPPED lpOverlapped
)
1030 FIXME("%p %p %ld %p %ld %p %p\n",
1031 hPipe
, lpInput
, dwInputSize
, lpOutput
,
1032 dwOutputSize
, lpBytesRead
, lpOverlapped
);
1038 /***********************************************************************
1039 * GetNamedPipeInfo (KERNEL32.@)
1041 BOOL WINAPI
GetNamedPipeInfo(
1042 HANDLE hNamedPipe
, LPDWORD lpFlags
, LPDWORD lpOutputBufferSize
,
1043 LPDWORD lpInputBufferSize
, LPDWORD lpMaxInstances
)
1047 TRACE("%p %p %p %p %p\n", hNamedPipe
, lpFlags
,
1048 lpOutputBufferSize
, lpInputBufferSize
, lpMaxInstances
);
1050 SERVER_START_REQ( get_named_pipe_info
)
1052 req
->handle
= hNamedPipe
;
1053 ret
= !wine_server_call_err( req
);
1054 if(lpFlags
) *lpFlags
= reply
->flags
;
1055 if(lpOutputBufferSize
) *lpOutputBufferSize
= reply
->outsize
;
1056 if(lpInputBufferSize
) *lpInputBufferSize
= reply
->outsize
;
1057 if(lpMaxInstances
) *lpMaxInstances
= reply
->maxinstances
;
1064 /***********************************************************************
1065 * GetNamedPipeHandleStateA (KERNEL32.@)
1067 BOOL WINAPI
GetNamedPipeHandleStateA(
1068 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
1069 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
1070 LPSTR lpUsername
, DWORD nUsernameMaxSize
)
1072 FIXME("%p %p %p %p %p %p %ld\n",
1073 hNamedPipe
, lpState
, lpCurInstances
,
1074 lpMaxCollectionCount
, lpCollectDataTimeout
,
1075 lpUsername
, nUsernameMaxSize
);
1080 /***********************************************************************
1081 * GetNamedPipeHandleStateW (KERNEL32.@)
1083 BOOL WINAPI
GetNamedPipeHandleStateW(
1084 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
1085 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
1086 LPWSTR lpUsername
, DWORD nUsernameMaxSize
)
1088 FIXME("%p %p %p %p %p %p %ld\n",
1089 hNamedPipe
, lpState
, lpCurInstances
,
1090 lpMaxCollectionCount
, lpCollectDataTimeout
,
1091 lpUsername
, nUsernameMaxSize
);
1096 /***********************************************************************
1097 * SetNamedPipeHandleState (KERNEL32.@)
1099 BOOL WINAPI
SetNamedPipeHandleState(
1100 HANDLE hNamedPipe
, LPDWORD lpMode
, LPDWORD lpMaxCollectionCount
,
1101 LPDWORD lpCollectDataTimeout
)
1103 FIXME("%p %p %p %p\n",
1104 hNamedPipe
, lpMode
, lpMaxCollectionCount
, lpCollectDataTimeout
);
1108 /***********************************************************************
1109 * CallNamedPipeA (KERNEL32.@)
1111 BOOL WINAPI
CallNamedPipeA(
1112 LPCSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
1113 LPVOID lpOutput
, DWORD lpOutputSize
,
1114 LPDWORD lpBytesRead
, DWORD nTimeout
)
1116 FIXME("%s %p %ld %p %ld %p %ld\n",
1117 debugstr_a(lpNamedPipeName
), lpInput
, lpInputSize
,
1118 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
1122 /***********************************************************************
1123 * CallNamedPipeW (KERNEL32.@)
1125 BOOL WINAPI
CallNamedPipeW(
1126 LPCWSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
1127 LPVOID lpOutput
, DWORD lpOutputSize
,
1128 LPDWORD lpBytesRead
, DWORD nTimeout
)
1130 FIXME("%s %p %ld %p %ld %p %ld\n",
1131 debugstr_w(lpNamedPipeName
), lpInput
, lpInputSize
,
1132 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
1136 /******************************************************************
1137 * CreatePipe (KERNEL32.@)
1140 BOOL WINAPI
CreatePipe( PHANDLE hReadPipe
, PHANDLE hWritePipe
,
1141 LPSECURITY_ATTRIBUTES sa
, DWORD size
)
1143 static unsigned index
= 0;
1146 unsigned in_index
= index
;
1148 *hReadPipe
= *hWritePipe
= INVALID_HANDLE_VALUE
;
1149 /* generate a unique pipe name (system wide) */
1152 sprintf(name
, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index
);
1153 hr
= CreateNamedPipeA(name
, PIPE_ACCESS_INBOUND
,
1154 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, size
, size
,
1155 NMPWAIT_USE_DEFAULT_WAIT
, sa
);
1156 } while (hr
== INVALID_HANDLE_VALUE
&& index
!= in_index
);
1157 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1158 if (hr
== INVALID_HANDLE_VALUE
) return FALSE
;
1160 hw
= CreateFileA(name
, GENERIC_WRITE
, 0, sa
, OPEN_EXISTING
, 0, 0);
1161 if (hw
== INVALID_HANDLE_VALUE
)
1175 /***********************************************************************
1176 * InterlockedCompareExchange (KERNEL32.@)
1178 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1179 __ASM_GLOBAL_FUNC(InterlockedCompareExchange
,
1180 "movl 12(%esp),%eax\n\t"
1181 "movl 8(%esp),%ecx\n\t"
1182 "movl 4(%esp),%edx\n\t"
1183 "lock; cmpxchgl %ecx,(%edx)\n\t"
1186 /***********************************************************************
1187 * InterlockedExchange (KERNEL32.@)
1189 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1190 __ASM_GLOBAL_FUNC(InterlockedExchange
,
1191 "movl 8(%esp),%eax\n\t"
1192 "movl 4(%esp),%edx\n\t"
1193 "lock; xchgl %eax,(%edx)\n\t"
1196 /***********************************************************************
1197 * InterlockedExchangeAdd (KERNEL32.@)
1199 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1200 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd
,
1201 "movl 8(%esp),%eax\n\t"
1202 "movl 4(%esp),%edx\n\t"
1203 "lock; xaddl %eax,(%edx)\n\t"
1206 /***********************************************************************
1207 * InterlockedIncrement (KERNEL32.@)
1209 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1210 __ASM_GLOBAL_FUNC(InterlockedIncrement
,
1211 "movl 4(%esp),%edx\n\t"
1213 "lock; xaddl %eax,(%edx)\n\t"
1217 /***********************************************************************
1218 * InterlockedDecrement (KERNEL32.@)
1220 __ASM_GLOBAL_FUNC(InterlockedDecrement
,
1221 "movl 4(%esp),%edx\n\t"
1223 "lock; xaddl %eax,(%edx)\n\t"
1227 #else /* __i386__ */
1229 /***********************************************************************
1230 * InterlockedCompareExchange (KERNEL32.@)
1232 LONG WINAPI
InterlockedCompareExchange( PLONG dest
, LONG xchg
, LONG compare
)
1234 return interlocked_cmpxchg( dest
, xchg
, compare
);
1237 /***********************************************************************
1238 * InterlockedExchange (KERNEL32.@)
1240 LONG WINAPI
InterlockedExchange( PLONG dest
, LONG val
)
1242 return interlocked_xchg( dest
, val
);
1245 /***********************************************************************
1246 * InterlockedExchangeAdd (KERNEL32.@)
1248 LONG WINAPI
InterlockedExchangeAdd( PLONG dest
, LONG incr
)
1250 return interlocked_xchg_add( dest
, incr
);
1253 /***********************************************************************
1254 * InterlockedIncrement (KERNEL32.@)
1256 LONG WINAPI
InterlockedIncrement( PLONG dest
)
1258 return interlocked_xchg_add( dest
, 1 ) + 1;
1261 /***********************************************************************
1262 * InterlockedDecrement (KERNEL32.@)
1264 LONG WINAPI
InterlockedDecrement( PLONG dest
)
1266 return interlocked_xchg_add( dest
, -1 ) - 1;
1269 #endif /* __i386__ */