wine  6.0.1
About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs.
  Fossies Dox: wine-6.0.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sync.c
Go to the documentation of this file.
1 /*
2  * Process synchronisation
3  *
4  * Copyright 1996, 1997, 1998 Marcus Meissner
5  * Copyright 1997, 1999 Alexandre Julliard
6  * Copyright 1999, 2000 Juergen Schmied
7  * Copyright 2003 Eric Pouech
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #if 0
25 #pragma makedep unix
26 #endif
27 
28 #include "config.h"
29 #include "wine/port.h"
30 
31 #include <assert.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <signal.h>
35 #ifdef HAVE_SYS_SYSCALL_H
36 #include <sys/syscall.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
40 #endif
41 #ifdef HAVE_POLL_H
42 #include <poll.h>
43 #endif
44 #ifdef HAVE_SYS_POLL_H
45 # include <sys/poll.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50 #ifdef HAVE_SCHED_H
51 # include <sched.h>
52 #endif
53 #include <string.h>
54 #include <stdarg.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <time.h>
58 #ifdef __APPLE__
59 # include <mach/mach.h>
60 # include <mach/task.h>
61 # include <mach/semaphore.h>
62 # include <mach/mach_time.h>
63 #endif
64 
65 #include "ntstatus.h"
66 #define WIN32_NO_STATUS
67 #define NONAMELESSUNION
68 #include "windef.h"
69 #include "winternl.h"
70 #include "ddk/wdm.h"
71 #include "wine/server.h"
72 #include "wine/exception.h"
73 #include "wine/debug.h"
74 #include "unix_private.h"
75 
77 
79 
81 
82 static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER;
83 
84 /* return a monotonic time counter, in Win32 ticks */
85 static inline ULONGLONG monotonic_counter(void)
86 {
87  struct timeval now;
88 #ifdef __APPLE__
89  static mach_timebase_info_data_t timebase;
90 
91  if (!timebase.denom) mach_timebase_info( &timebase );
92 #ifdef HAVE_MACH_CONTINUOUS_TIME
93  if (&mach_continuous_time != NULL)
94  return mach_continuous_time() * timebase.numer / timebase.denom / 100;
95 #endif
96  return mach_absolute_time() * timebase.numer / timebase.denom / 100;
97 #elif defined(HAVE_CLOCK_GETTIME)
98  struct timespec ts;
99 #ifdef CLOCK_MONOTONIC_RAW
100  if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts ))
101  return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100;
102 #endif
103  if (!clock_gettime( CLOCK_MONOTONIC, &ts ))
104  return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100;
105 #endif
106  gettimeofday( &now, 0 );
107  return ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10 - server_start_time;
108 }
109 
110 
111 #ifdef __linux__
112 
113 #define FUTEX_WAIT 0
114 #define FUTEX_WAKE 1
115 #define FUTEX_WAIT_BITSET 9
116 #define FUTEX_WAKE_BITSET 10
117 
118 static int futex_private = 128;
119 
120 static inline int futex_wait( const int *addr, int val, struct timespec *timeout )
121 {
122  return syscall( __NR_futex, addr, FUTEX_WAIT | futex_private, val, timeout, 0, 0 );
123 }
124 
125 static inline int futex_wake( const int *addr, int val )
126 {
127  return syscall( __NR_futex, addr, FUTEX_WAKE | futex_private, val, NULL, 0, 0 );
128 }
129 
130 static inline int futex_wait_bitset( const int *addr, int val, struct timespec *timeout, int mask )
131 {
132  return syscall( __NR_futex, addr, FUTEX_WAIT_BITSET | futex_private, val, timeout, 0, mask );
133 }
134 
135 static inline int futex_wake_bitset( const int *addr, int val, int mask )
136 {
137  return syscall( __NR_futex, addr, FUTEX_WAKE_BITSET | futex_private, val, NULL, 0, mask );
138 }
139 
140 static inline int use_futexes(void)
141 {
142  static int supported = -1;
143 
144  if (supported == -1)
145  {
146  futex_wait( &supported, 10, NULL );
147  if (errno == ENOSYS)
148  {
149  futex_private = 0;
150  futex_wait( &supported, 10, NULL );
151  }
152  supported = (errno != ENOSYS);
153  }
154  return supported;
155 }
156 
157 static int *get_futex(void **ptr)
158 {
159  if (sizeof(void *) == 8)
160  return (int *)((((ULONG_PTR)ptr) + 3) & ~3);
161  else if (!(((ULONG_PTR)ptr) & 3))
162  return (int *)ptr;
163  else
164  return NULL;
165 }
166 
167 static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout )
168 {
170  timeout_t diff;
171 
172  if (timeout->QuadPart > 0)
173  {
175  diff = timeout->QuadPart - now.QuadPart;
176  }
177  else
178  diff = -timeout->QuadPart;
179 
180  timespec->tv_sec = diff / TICKSPERSEC;
181  timespec->tv_nsec = (diff % TICKSPERSEC) * 100;
182 }
183 
184 #endif
185 
186 
187 static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
188 {
189  switch (size)
190  {
191  case 1:
192  return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
193  case 2:
194  return (*(const USHORT *)addr == *(const USHORT *)cmp);
195  case 4:
196  return (*(const ULONG *)addr == *(const ULONG *)cmp);
197  case 8:
198  return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
199  }
200 
201  return FALSE;
202 }
203 
204 
205 /* create a struct security_descriptor and contained information in one contiguous piece of memory */
207  data_size_t *ret_len )
208 {
209  unsigned int len = sizeof(**ret);
210  SID *owner = NULL, *group = NULL;
211  ACL *dacl = NULL, *sacl = NULL;
213 
214  *ret = NULL;
215  *ret_len = 0;
216 
217  if (!attr) return STATUS_SUCCESS;
218 
219  if (attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER;
220 
221  if ((sd = attr->SecurityDescriptor))
222  {
223  len += sizeof(struct security_descriptor);
225  if (sd->Control & SE_SELF_RELATIVE)
226  {
228  if (rel->Owner) owner = (PSID)((BYTE *)rel + rel->Owner);
229  if (rel->Group) group = (PSID)((BYTE *)rel + rel->Group);
230  if ((sd->Control & SE_SACL_PRESENT) && rel->Sacl) sacl = (PSID)((BYTE *)rel + rel->Sacl);
231  if ((sd->Control & SE_DACL_PRESENT) && rel->Dacl) dacl = (PSID)((BYTE *)rel + rel->Dacl);
232  }
233  else
234  {
235  owner = sd->Owner;
236  group = sd->Group;
237  if (sd->Control & SE_SACL_PRESENT) sacl = sd->Sacl;
238  if (sd->Control & SE_DACL_PRESENT) dacl = sd->Dacl;
239  }
240 
241  if (owner) len += offsetof( SID, SubAuthority[owner->SubAuthorityCount] );
242  if (group) len += offsetof( SID, SubAuthority[group->SubAuthorityCount] );
243  if (sacl) len += sacl->AclSize;
244  if (dacl) len += dacl->AclSize;
245 
246  /* fix alignment for the Unicode name that follows the structure */
247  len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
248  }
249 
250  if (attr->ObjectName)
251  {
252  if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID;
253  len += attr->ObjectName->Length;
254  }
255  else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID;
256 
257  len = (len + 3) & ~3; /* DWORD-align the entire structure */
258 
259  if (!(*ret = calloc( len, 1 ))) return STATUS_NO_MEMORY;
260 
261  (*ret)->rootdir = wine_server_obj_handle( attr->RootDirectory );
262  (*ret)->attributes = attr->Attributes;
263 
264  if (attr->SecurityDescriptor)
265  {
266  struct security_descriptor *descr = (struct security_descriptor *)(*ret + 1);
267  unsigned char *ptr = (unsigned char *)(descr + 1);
268 
269  descr->control = sd->Control & ~~SE_SELF_RELATIVE;
270  if (owner) descr->owner_len = offsetof( SID, SubAuthority[owner->SubAuthorityCount] );
271  if (group) descr->group_len = offsetof( SID, SubAuthority[group->SubAuthorityCount] );
272  if (sacl) descr->sacl_len = sacl->AclSize;
273  if (dacl) descr->dacl_len = dacl->AclSize;
274 
275  memcpy( ptr, owner, descr->owner_len );
276  ptr += descr->owner_len;
277  memcpy( ptr, group, descr->group_len );
278  ptr += descr->group_len;
279  memcpy( ptr, sacl, descr->sacl_len );
280  ptr += descr->sacl_len;
281  memcpy( ptr, dacl, descr->dacl_len );
282  (*ret)->sd_len = (sizeof(*descr) + descr->owner_len + descr->group_len + descr->sacl_len +
283  descr->dacl_len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
284  }
285 
286  if (attr->ObjectName)
287  {
288  unsigned char *ptr = (unsigned char *)(*ret + 1) + (*ret)->sd_len;
289  (*ret)->name_len = attr->ObjectName->Length;
290  memcpy( ptr, attr->ObjectName->Buffer, (*ret)->name_len );
291  }
292 
293  *ret_len = len;
294  return STATUS_SUCCESS;
295 }
296 
297 
299 {
300  if (!attr || attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER;
301 
302  if (attr->ObjectName)
303  {
304  if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID;
305  }
306  else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID;
307 
308  return STATUS_SUCCESS;
309 }
310 
311 
312 /******************************************************************************
313  * NtCreateSemaphore (NTDLL.@)
314  */
316  LONG initial, LONG max )
317 {
318  NTSTATUS ret;
320  struct object_attributes *objattr;
321 
322  if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
323  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
324 
326  {
327  req->access = access;
328  req->initial = initial;
329  req->max = max;
330  wine_server_add_data( req, objattr, len );
331  ret = wine_server_call( req );
332  *handle = wine_server_ptr_handle( reply->handle );
333  }
335 
336  free( objattr );
337  return ret;
338 }
339 
340 
341 /******************************************************************************
342  * NtOpenSemaphore (NTDLL.@)
343  */
345 {
346  NTSTATUS ret;
347 
348  if ((ret = validate_open_object_attributes( attr ))) return ret;
349 
350  SERVER_START_REQ( open_semaphore )
351  {
352  req->access = access;
353  req->attributes = attr->Attributes;
354  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
355  if (attr->ObjectName)
356  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
357  ret = wine_server_call( req );
358  *handle = wine_server_ptr_handle( reply->handle );
359  }
361  return ret;
362 }
363 
364 
365 /******************************************************************************
366  * NtQuerySemaphore (NTDLL.@)
367  */
369  void *info, ULONG len, ULONG *ret_len )
370 {
371  NTSTATUS ret;
373 
374  TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
375 
376  if (class != SemaphoreBasicInformation)
377  {
378  FIXME("(%p,%d,%u) Unknown class\n", handle, class, len);
380  }
381 
383 
384  SERVER_START_REQ( query_semaphore )
385  {
386  req->handle = wine_server_obj_handle( handle );
387  if (!(ret = wine_server_call( req )))
388  {
389  out->CurrentCount = reply->current;
390  out->MaximumCount = reply->max;
391  if (ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION);
392  }
393  }
395  return ret;
396 }
397 
398 
399 /******************************************************************************
400  * NtReleaseSemaphore (NTDLL.@)
401  */
402 NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous )
403 {
404  NTSTATUS ret;
405 
407  {
408  req->handle = wine_server_obj_handle( handle );
409  req->count = count;
410  if (!(ret = wine_server_call( req )))
411  {
412  if (previous) *previous = reply->prev_count;
413  }
414  }
416  return ret;
417 }
418 
419 
420 /**************************************************************************
421  * NtCreateEvent (NTDLL.@)
422  */
425 {
426  NTSTATUS ret;
428  struct object_attributes *objattr;
429 
430  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
431 
433  {
434  req->access = access;
435  req->manual_reset = (type == NotificationEvent);
436  req->initial_state = state;
437  wine_server_add_data( req, objattr, len );
438  ret = wine_server_call( req );
439  *handle = wine_server_ptr_handle( reply->handle );
440  }
442 
443  free( objattr );
444  return ret;
445 }
446 
447 
448 /******************************************************************************
449  * NtOpenEvent (NTDLL.@)
450  */
452 {
453  NTSTATUS ret;
454 
455  if ((ret = validate_open_object_attributes( attr ))) return ret;
456 
457  SERVER_START_REQ( open_event )
458  {
459  req->access = access;
460  req->attributes = attr->Attributes;
461  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
462  if (attr->ObjectName)
463  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
464  ret = wine_server_call( req );
465  *handle = wine_server_ptr_handle( reply->handle );
466  }
468  return ret;
469 }
470 
471 
472 /******************************************************************************
473  * NtSetEvent (NTDLL.@)
474  */
475 NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
476 {
477  NTSTATUS ret;
478 
480  {
481  req->handle = wine_server_obj_handle( handle );
482  req->op = SET_EVENT;
483  ret = wine_server_call( req );
484  if (!ret && prev_state) *prev_state = reply->state;
485  }
487  return ret;
488 }
489 
490 
491 /******************************************************************************
492  * NtResetEvent (NTDLL.@)
493  */
494 NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
495 {
496  NTSTATUS ret;
497 
499  {
500  req->handle = wine_server_obj_handle( handle );
501  req->op = RESET_EVENT;
502  ret = wine_server_call( req );
503  if (!ret && prev_state) *prev_state = reply->state;
504  }
506  return ret;
507 }
508 
509 
510 /******************************************************************************
511  * NtClearEvent (NTDLL.@)
512  */
514 {
515  /* FIXME: same as NtResetEvent ??? */
516  return NtResetEvent( handle, NULL );
517 }
518 
519 
520 /******************************************************************************
521  * NtPulseEvent (NTDLL.@)
522  */
523 NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
524 {
525  NTSTATUS ret;
526 
528  {
529  req->handle = wine_server_obj_handle( handle );
530  req->op = PULSE_EVENT;
531  ret = wine_server_call( req );
532  if (!ret && prev_state) *prev_state = reply->state;
533  }
535  return ret;
536 }
537 
538 
539 /******************************************************************************
540  * NtQueryEvent (NTDLL.@)
541  */
543  void *info, ULONG len, ULONG *ret_len )
544 {
545  NTSTATUS ret;
547 
548  TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
549 
550  if (class != EventBasicInformation)
551  {
552  FIXME("(%p, %d, %d) Unknown class\n",
553  handle, class, len);
555  }
556 
558 
559  SERVER_START_REQ( query_event )
560  {
561  req->handle = wine_server_obj_handle( handle );
562  if (!(ret = wine_server_call( req )))
563  {
564  out->EventType = reply->manual_reset ? NotificationEvent : SynchronizationEvent;
565  out->EventState = reply->state;
566  if (ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION);
567  }
568  }
570  return ret;
571 }
572 
573 
574 /******************************************************************************
575  * NtCreateMutant (NTDLL.@)
576  */
578  BOOLEAN owned )
579 {
580  NTSTATUS ret;
582  struct object_attributes *objattr;
583 
584  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
585 
587  {
588  req->access = access;
589  req->owned = owned;
590  wine_server_add_data( req, objattr, len );
591  ret = wine_server_call( req );
592  *handle = wine_server_ptr_handle( reply->handle );
593  }
595 
596  free( objattr );
597  return ret;
598 }
599 
600 
601 /**************************************************************************
602  * NtOpenMutant (NTDLL.@)
603  */
605 {
606  NTSTATUS ret;
607 
608  if ((ret = validate_open_object_attributes( attr ))) return ret;
609 
610  SERVER_START_REQ( open_mutex )
611  {
612  req->access = access;
613  req->attributes = attr->Attributes;
614  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
615  if (attr->ObjectName)
616  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
617  ret = wine_server_call( req );
618  *handle = wine_server_ptr_handle( reply->handle );
619  }
621  return ret;
622 }
623 
624 
625 /**************************************************************************
626  * NtReleaseMutant (NTDLL.@)
627  */
628 NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
629 {
630  NTSTATUS ret;
631 
632  SERVER_START_REQ( release_mutex )
633  {
634  req->handle = wine_server_obj_handle( handle );
635  ret = wine_server_call( req );
636  if (prev_count) *prev_count = 1 - reply->prev_count;
637  }
639  return ret;
640 }
641 
642 
643 /******************************************************************
644  * NtQueryMutant (NTDLL.@)
645  */
647  void *info, ULONG len, ULONG *ret_len )
648 {
649  NTSTATUS ret;
651 
652  TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
653 
654  if (class != MutantBasicInformation)
655  {
656  FIXME( "(%p, %d, %d) Unknown class\n", handle, class, len );
658  }
659 
661 
662  SERVER_START_REQ( query_mutex )
663  {
664  req->handle = wine_server_obj_handle( handle );
665  if (!(ret = wine_server_call( req )))
666  {
667  out->CurrentCount = 1 - reply->count;
668  out->OwnedByCaller = reply->owned;
669  out->AbandonedState = reply->abandoned;
670  if (ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION);
671  }
672  }
674  return ret;
675 }
676 
677 
678 /**************************************************************************
679  * NtCreateJobObject (NTDLL.@)
680  */
682 {
683  NTSTATUS ret;
685  struct object_attributes *objattr;
686 
687  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
688 
690  {
691  req->access = access;
692  wine_server_add_data( req, objattr, len );
693  ret = wine_server_call( req );
694  *handle = wine_server_ptr_handle( reply->handle );
695  }
697  free( objattr );
698  return ret;
699 }
700 
701 
702 /**************************************************************************
703  * NtOpenJobObject (NTDLL.@)
704  */
706 {
707  NTSTATUS ret;
708 
709  if ((ret = validate_open_object_attributes( attr ))) return ret;
710 
711  SERVER_START_REQ( open_job )
712  {
713  req->access = access;
714  req->attributes = attr->Attributes;
715  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
716  if (attr->ObjectName)
717  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
718  ret = wine_server_call( req );
719  *handle = wine_server_ptr_handle( reply->handle );
720  }
722  return ret;
723 }
724 
725 
726 /**************************************************************************
727  * NtTerminateJobObject (NTDLL.@)
728  */
730 {
731  NTSTATUS ret;
732 
733  TRACE( "(%p, %d)\n", handle, status );
734 
736  {
737  req->handle = wine_server_obj_handle( handle );
738  req->status = status;
739  ret = wine_server_call( req );
740  }
742 
743  return ret;
744 }
745 
746 
747 /**************************************************************************
748  * NtQueryInformationJobObject (NTDLL.@)
749  */
751  ULONG len, ULONG *ret_len )
752 {
753  NTSTATUS ret;
754 
755  TRACE( "semi-stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
756 
757  if (class >= MaxJobObjectInfoClass) return STATUS_INVALID_PARAMETER;
758 
759  switch (class)
760  {
762  {
764 
765  if (len < sizeof(*accounting)) return STATUS_INFO_LENGTH_MISMATCH;
767  {
768  req->handle = wine_server_obj_handle( handle );
769  if (!(ret = wine_server_call( req )))
770  {
771  memset( accounting, 0, sizeof(*accounting) );
772  accounting->TotalProcesses = reply->total_processes;
773  accounting->ActiveProcesses = reply->active_processes;
774  }
775  }
777  if (ret_len) *ret_len = sizeof(*accounting);
778  return ret;
779  }
781  {
783 
784  if (len < sizeof(*process)) return STATUS_INFO_LENGTH_MISMATCH;
785  memset( process, 0, sizeof(*process) );
786  if (ret_len) *ret_len = sizeof(*process);
787  return STATUS_SUCCESS;
788  }
790  {
791  JOBOBJECT_EXTENDED_LIMIT_INFORMATION *extended_limit = info;
792 
793  if (len < sizeof(*extended_limit)) return STATUS_INFO_LENGTH_MISMATCH;
794  memset( extended_limit, 0, sizeof(*extended_limit) );
795  if (ret_len) *ret_len = sizeof(*extended_limit);
796  return STATUS_SUCCESS;
797  }
799  {
801 
802  if (len < sizeof(*basic_limit)) return STATUS_INFO_LENGTH_MISMATCH;
803  memset( basic_limit, 0, sizeof(*basic_limit) );
804  if (ret_len) *ret_len = sizeof(*basic_limit);
805  return STATUS_SUCCESS;
806  }
807  default:
808  return STATUS_NOT_IMPLEMENTED;
809  }
810 }
811 
812 
813 /**************************************************************************
814  * NtSetInformationJobObject (NTDLL.@)
815  */
817 {
820  ULONG info_size = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
822 
823  TRACE( "(%p, %u, %p, %u)\n", handle, class, info, len );
824 
825  if (class >= MaxJobObjectInfoClass) return STATUS_INVALID_PARAMETER;
826 
827  switch (class)
828  {
829 
831  info_size = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
833  /* fall through */
835  if (len != info_size) return STATUS_INVALID_PARAMETER;
836  basic_limit = info;
837  if (basic_limit->LimitFlags & ~limit_flags) return STATUS_INVALID_PARAMETER;
838  SERVER_START_REQ( set_job_limits )
839  {
840  req->handle = wine_server_obj_handle( handle );
841  req->limit_flags = basic_limit->LimitFlags;
842  status = wine_server_call( req );
843  }
845  break;
848  SERVER_START_REQ( set_job_completion_port )
849  {
851  req->job = wine_server_obj_handle( handle );
852  req->port = wine_server_obj_handle( port_info->CompletionPort );
853  req->key = wine_server_client_ptr( port_info->CompletionKey );
854  status = wine_server_call( req );
855  }
857  break;
860  /* fall through */
861  default:
862  FIXME( "stub: %p %u %p %u\n", handle, class, info, len );
863  }
864  return status;
865 }
866 
867 
868 /**************************************************************************
869  * NtIsProcessInJob (NTDLL.@)
870  */
872 {
874 
875  TRACE( "(%p %p)\n", job, process );
876 
877  SERVER_START_REQ( process_in_job )
878  {
879  req->job = wine_server_obj_handle( job );
880  req->process = wine_server_obj_handle( process );
881  status = wine_server_call( req );
882  }
884  return status;
885 }
886 
887 
888 /**************************************************************************
889  * NtAssignProcessToJobObject (NTDLL.@)
890  */
892 {
894 
895  TRACE( "(%p %p)\n", job, process );
896 
897  SERVER_START_REQ( assign_job )
898  {
899  req->job = wine_server_obj_handle( job );
900  req->process = wine_server_obj_handle( process );
901  status = wine_server_call( req );
902  }
904  return status;
905 }
906 
907 
908 /**************************************************************************
909  * NtCreateDirectoryObject (NTDLL.@)
910  */
912 {
913  NTSTATUS ret;
915  struct object_attributes *objattr;
916 
917  if (!handle) return STATUS_ACCESS_VIOLATION;
918 
919  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
920 
922  {
923  req->access = access;
924  wine_server_add_data( req, objattr, len );
925  ret = wine_server_call( req );
926  *handle = wine_server_ptr_handle( reply->handle );
927  }
929  free( objattr );
930  return ret;
931 }
932 
933 
934 /**************************************************************************
935  * NtOpenDirectoryObject (NTDLL.@)
936  */
938 {
939  NTSTATUS ret;
940 
941  if (!handle) return STATUS_ACCESS_VIOLATION;
942  if ((ret = validate_open_object_attributes( attr ))) return ret;
943 
944  SERVER_START_REQ( open_directory )
945  {
946  req->access = access;
947  req->attributes = attr->Attributes;
948  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
949  if (attr->ObjectName)
950  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
951  ret = wine_server_call( req );
952  *handle = wine_server_ptr_handle( reply->handle );
953  }
955  return ret;
956 }
957 
958 
959 /**************************************************************************
960  * NtQueryDirectoryObject (NTDLL.@)
961  */
963  ULONG size, BOOLEAN single_entry, BOOLEAN restart,
964  ULONG *context, ULONG *ret_size )
965 {
966  NTSTATUS ret;
967 
968  if (restart) *context = 0;
969 
970  if (single_entry)
971  {
972  if (size <= sizeof(*buffer) + 2 * sizeof(WCHAR)) return STATUS_BUFFER_OVERFLOW;
973 
974  SERVER_START_REQ( get_directory_entry )
975  {
976  req->handle = wine_server_obj_handle( handle );
977  req->index = *context;
978  wine_server_set_reply( req, buffer + 1, size - sizeof(*buffer) - 2*sizeof(WCHAR) );
979  if (!(ret = wine_server_call( req )))
980  {
981  buffer->ObjectName.Buffer = (WCHAR *)(buffer + 1);
982  buffer->ObjectName.Length = reply->name_len;
983  buffer->ObjectName.MaximumLength = reply->name_len + sizeof(WCHAR);
984  buffer->ObjectTypeName.Buffer = (WCHAR *)(buffer + 1) + reply->name_len/sizeof(WCHAR) + 1;
985  buffer->ObjectTypeName.Length = wine_server_reply_size( reply ) - reply->name_len;
986  buffer->ObjectTypeName.MaximumLength = buffer->ObjectTypeName.Length + sizeof(WCHAR);
987  /* make room for the terminating null */
988  memmove( buffer->ObjectTypeName.Buffer, buffer->ObjectTypeName.Buffer - 1,
989  buffer->ObjectTypeName.Length );
990  buffer->ObjectName.Buffer[buffer->ObjectName.Length/sizeof(WCHAR)] = 0;
991  buffer->ObjectTypeName.Buffer[buffer->ObjectTypeName.Length/sizeof(WCHAR)] = 0;
992  (*context)++;
993  }
994  }
996  if (ret_size)
997  *ret_size = buffer->ObjectName.MaximumLength + buffer->ObjectTypeName.MaximumLength + sizeof(*buffer);
998  }
999  else
1000  {
1001  FIXME("multiple entries not implemented\n");
1002  ret = STATUS_NOT_IMPLEMENTED;
1003  }
1004  return ret;
1005 }
1006 
1007 
1008 /**************************************************************************
1009  * NtCreateSymbolicLinkObject (NTDLL.@)
1010  */
1013 {
1014  NTSTATUS ret;
1015  data_size_t len;
1016  struct object_attributes *objattr;
1017 
1018  if (!handle || !attr || !target) return STATUS_ACCESS_VIOLATION;
1019  if (!target->Buffer) return STATUS_INVALID_PARAMETER;
1020 
1021  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
1022 
1024  {
1025  req->access = access;
1026  wine_server_add_data( req, objattr, len );
1027  wine_server_add_data( req, target->Buffer, target->Length );
1028  ret = wine_server_call( req );
1029  *handle = wine_server_ptr_handle( reply->handle );
1030  }
1032  free( objattr );
1033  return ret;
1034 }
1035 
1036 
1037 /**************************************************************************
1038  * NtOpenSymbolicLinkObject (NTDLL.@)
1039  */
1041  const OBJECT_ATTRIBUTES *attr )
1042 {
1043  NTSTATUS ret;
1044 
1045  if (!handle) return STATUS_ACCESS_VIOLATION;
1046  if ((ret = validate_open_object_attributes( attr ))) return ret;
1047 
1048  SERVER_START_REQ( open_symlink )
1049  {
1050  req->access = access;
1051  req->attributes = attr->Attributes;
1052  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
1053  if (attr->ObjectName)
1054  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
1055  ret = wine_server_call( req );
1056  *handle = wine_server_ptr_handle( reply->handle );
1057  }
1059  return ret;
1060 }
1061 
1062 
1063 /**************************************************************************
1064  * NtQuerySymbolicLinkObject (NTDLL.@)
1065  */
1067 {
1068  NTSTATUS ret;
1069 
1070  if (!target) return STATUS_ACCESS_VIOLATION;
1071 
1072  SERVER_START_REQ( query_symlink )
1073  {
1074  req->handle = wine_server_obj_handle( handle );
1075  if (target->MaximumLength >= sizeof(WCHAR))
1076  wine_server_set_reply( req, target->Buffer, target->MaximumLength - sizeof(WCHAR) );
1077  if (!(ret = wine_server_call( req )))
1078  {
1079  target->Length = wine_server_reply_size(reply);
1080  target->Buffer[target->Length / sizeof(WCHAR)] = 0;
1081  if (length) *length = reply->total + sizeof(WCHAR);
1082  }
1083  else if (length && ret == STATUS_BUFFER_TOO_SMALL) *length = reply->total + sizeof(WCHAR);
1084  }
1086  return ret;
1087 }
1088 
1089 
1090 /**************************************************************************
1091  * NtMakeTemporaryObject (NTDLL.@)
1092  */
1094 {
1095  NTSTATUS ret;
1096 
1097  TRACE("%p\n", handle);
1098 
1099  SERVER_START_REQ( make_temporary )
1100  {
1101  req->handle = wine_server_obj_handle( handle );
1102  ret = wine_server_call( req );
1103  }
1105  return ret;
1106 }
1107 
1108 
1109 /**************************************************************************
1110  * NtCreateTimer (NTDLL.@)
1111  */
1113  TIMER_TYPE type )
1114 {
1115  NTSTATUS ret;
1116  data_size_t len;
1117  struct object_attributes *objattr;
1118 
1120 
1121  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
1122 
1124  {
1125  req->access = access;
1126  req->manual = (type == NotificationTimer);
1127  wine_server_add_data( req, objattr, len );
1128  ret = wine_server_call( req );
1129  *handle = wine_server_ptr_handle( reply->handle );
1130  }
1132 
1133  free( objattr );
1134  return ret;
1135 
1136 }
1137 
1138 
1139 /**************************************************************************
1140  * NtOpenTimer (NTDLL.@)
1141  */
1143 {
1144  NTSTATUS ret;
1145 
1146  if ((ret = validate_open_object_attributes( attr ))) return ret;
1147 
1148  SERVER_START_REQ( open_timer )
1149  {
1150  req->access = access;
1151  req->attributes = attr->Attributes;
1152  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
1153  if (attr->ObjectName)
1154  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
1155  ret = wine_server_call( req );
1156  *handle = wine_server_ptr_handle( reply->handle );
1157  }
1159  return ret;
1160 }
1161 
1162 
1163 /**************************************************************************
1164  * NtSetTimer (NTDLL.@)
1165  */
1167  void *arg, BOOLEAN resume, ULONG period, BOOLEAN *state )
1168 {
1169  NTSTATUS ret = STATUS_SUCCESS;
1170 
1171  TRACE( "(%p,%p,%p,%p,%08x,0x%08x,%p)\n", handle, when, callback, arg, resume, period, state );
1172 
1174  {
1175  req->handle = wine_server_obj_handle( handle );
1176  req->period = period;
1177  req->expire = when->QuadPart;
1178  req->callback = wine_server_client_ptr( callback );
1179  req->arg = wine_server_client_ptr( arg );
1180  ret = wine_server_call( req );
1181  if (state) *state = reply->signaled;
1182  }
1184 
1185  /* set error but can still succeed */
1186  if (resume && ret == STATUS_SUCCESS) return STATUS_TIMER_RESUME_IGNORED;
1187  return ret;
1188 }
1189 
1190 
1191 /**************************************************************************
1192  * NtCancelTimer (NTDLL.@)
1193  */
1195 {
1196  NTSTATUS ret;
1197 
1199  {
1200  req->handle = wine_server_obj_handle( handle );
1201  ret = wine_server_call( req );
1202  if (state) *state = reply->signaled;
1203  }
1205  return ret;
1206 }
1207 
1208 
1209 /******************************************************************************
1210  * NtQueryTimer (NTDLL.@)
1211  */
1213  void *info, ULONG len, ULONG *ret_len )
1214 {
1215  TIMER_BASIC_INFORMATION *basic_info = info;
1216  NTSTATUS ret;
1218 
1219  TRACE( "(%p,%d,%p,0x%08x,%p)\n", handle, class, info, len, ret_len );
1220 
1221  switch (class)
1222  {
1223  case TimerBasicInformation:
1225 
1226  SERVER_START_REQ( get_timer_info )
1227  {
1228  req->handle = wine_server_obj_handle( handle );
1229  ret = wine_server_call(req);
1230  /* convert server time to absolute NTDLL time */
1231  basic_info->RemainingTime.QuadPart = reply->when;
1232  basic_info->TimerState = reply->signaled;
1233  }
1235 
1236  /* convert into relative time */
1237  if (basic_info->RemainingTime.QuadPart > 0) NtQuerySystemTime( &now );
1238  else
1239  {
1241  basic_info->RemainingTime.QuadPart = -basic_info->RemainingTime.QuadPart;
1242  }
1243 
1244  if (now.QuadPart > basic_info->RemainingTime.QuadPart)
1245  basic_info->RemainingTime.QuadPart = 0;
1246  else
1247  basic_info->RemainingTime.QuadPart -= now.QuadPart;
1248 
1249  if (ret_len) *ret_len = sizeof(TIMER_BASIC_INFORMATION);
1250  return ret;
1251  }
1252 
1253  FIXME( "Unhandled class %d\n", class );
1255 }
1256 
1257 
1258 /******************************************************************
1259  * NtWaitForMultipleObjects (NTDLL.@)
1260  */
1262  BOOLEAN alertable, const LARGE_INTEGER *timeout )
1263 {
1266 
1267  if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
1268 
1269  if (alertable) flags |= SELECT_ALERTABLE;
1270  select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
1271  for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
1272  return server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout );
1273 }
1274 
1275 
1276 /******************************************************************
1277  * NtWaitForSingleObject (NTDLL.@)
1278  */
1279 NTSTATUS WINAPI NtWaitForSingleObject( HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout )
1280 {
1281  return NtWaitForMultipleObjects( 1, &handle, FALSE, alertable, timeout );
1282 }
1283 
1284 
1285 /******************************************************************
1286  * NtSignalAndWaitForSingleObject (NTDLL.@)
1287  */
1289  BOOLEAN alertable, const LARGE_INTEGER *timeout )
1290 {
1293 
1294  if (!signal) return STATUS_INVALID_HANDLE;
1295 
1296  if (alertable) flags |= SELECT_ALERTABLE;
1297  select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT;
1298  select_op.signal_and_wait.wait = wine_server_obj_handle( wait );
1299  select_op.signal_and_wait.signal = wine_server_obj_handle( signal );
1300  return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout );
1301 }
1302 
1303 
1304 /******************************************************************
1305  * NtYieldExecution (NTDLL.@)
1306  */
1308 {
1309 #ifdef HAVE_SCHED_YIELD
1310  sched_yield();
1311  return STATUS_SUCCESS;
1312 #else
1314 #endif
1315 }
1316 
1317 
1318 /******************************************************************
1319  * NtDelayExecution (NTDLL.@)
1320  */
1322 {
1323  /* if alertable, we need to query the server */
1324  if (alertable) return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
1325 
1326  if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
1327  {
1328  for (;;) select( 0, NULL, NULL, NULL, NULL );
1329  }
1330  else
1331  {
1333  timeout_t when, diff;
1334 
1335  if ((when = timeout->QuadPart) < 0)
1336  {
1337  NtQuerySystemTime( &now );
1338  when = now.QuadPart - when;
1339  }
1340 
1341  /* Note that we yield after establishing the desired timeout */
1342  NtYieldExecution();
1343  if (!when) return STATUS_SUCCESS;
1344 
1345  for (;;)
1346  {
1347  struct timeval tv;
1348  NtQuerySystemTime( &now );
1349  diff = (when - now.QuadPart + 9) / 10;
1350  if (diff <= 0) break;
1351  tv.tv_sec = diff / 1000000;
1352  tv.tv_usec = diff % 1000000;
1353  if (select( 0, NULL, NULL, NULL, &tv ) != -1) break;
1354  }
1355  }
1356  return STATUS_SUCCESS;
1357 }
1358 
1359 
1360 /******************************************************************************
1361  * NtQueryPerformanceCounter (NTDLL.@)
1362  */
1364 {
1365  counter->QuadPart = monotonic_counter();
1366  if (frequency) frequency->QuadPart = TICKSPERSEC;
1367  return STATUS_SUCCESS;
1368 }
1369 
1370 
1371 /***********************************************************************
1372  * NtQuerySystemTime (NTDLL.@)
1373  */
1375 {
1376 #ifdef HAVE_CLOCK_GETTIME
1377  struct timespec ts;
1378  static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */
1379 
1380  if (clock_id == CLOCK_MONOTONIC)
1381  {
1382 #ifdef CLOCK_REALTIME_COARSE
1383  struct timespec res;
1384 
1385  /* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */
1386  if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000)
1387  clock_id = CLOCK_REALTIME_COARSE;
1388  else
1389 #endif /* CLOCK_REALTIME_COARSE */
1390  clock_id = CLOCK_REALTIME;
1391  }
1392 
1393  if (!clock_gettime( clock_id, &ts ))
1394  {
1395  time->QuadPart = ticks_from_time_t( ts.tv_sec ) + (ts.tv_nsec + 50) / 100;
1396  }
1397  else
1398 #endif /* HAVE_CLOCK_GETTIME */
1399  {
1400  struct timeval now;
1401 
1402  gettimeofday( &now, 0 );
1403  time->QuadPart = ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10;
1404  }
1405  return STATUS_SUCCESS;
1406 }
1407 
1408 
1409 /***********************************************************************
1410  * NtSetSystemTime (NTDLL.@)
1411  */
1413 {
1415  LONGLONG diff;
1416 
1417  NtQuerySystemTime( &now );
1418  if (old) *old = now;
1419  diff = new->QuadPart - now.QuadPart;
1420  if (diff > -TICKSPERSEC / 2 && diff < TICKSPERSEC / 2) return STATUS_SUCCESS;
1421  ERR( "not allowed: difference %d ms\n", (int)(diff / 10000) );
1423 }
1424 
1425 
1426 /***********************************************************************
1427  * NtQueryTimerResolution (NTDLL.@)
1428  */
1429 NTSTATUS WINAPI NtQueryTimerResolution( ULONG *min_res, ULONG *max_res, ULONG *current_res )
1430 {
1431  FIXME( "(%p,%p,%p), stub!\n", min_res, max_res, current_res );
1432  return STATUS_NOT_IMPLEMENTED;
1433 }
1434 
1435 
1436 /***********************************************************************
1437  * NtSetTimerResolution (NTDLL.@)
1438  */
1440 {
1441  FIXME( "(%u,%u,%p), stub!\n", res, set, current_res );
1442  return STATUS_NOT_IMPLEMENTED;
1443 }
1444 
1445 
1446 /******************************************************************************
1447  * NtSetIntervalProfile (NTDLL.@)
1448  */
1450 {
1451  FIXME( "%u,%d\n", interval, source );
1452  return STATUS_SUCCESS;
1453 }
1454 
1455 
1456 /******************************************************************************
1457  * NtGetTickCount (NTDLL.@)
1458  */
1460 {
1461  /* note: we ignore TickCountMultiplier */
1462  return user_shared_data->u.TickCount.LowPart;
1463 }
1464 
1465 
1466 /******************************************************************************
1467  * RtlGetSystemTimePrecise (NTDLL.@)
1468  */
1470 {
1471  struct timeval now;
1472 #ifdef HAVE_CLOCK_GETTIME
1473  struct timespec ts;
1474 
1475  if (!clock_gettime( CLOCK_REALTIME, &ts ))
1476  return ticks_from_time_t( ts.tv_sec ) + (ts.tv_nsec + 50) / 100;
1477 #endif
1478  gettimeofday( &now, 0 );
1479  return ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10;
1480 }
1481 
1482 
1483 /******************************************************************************
1484  * NtCreateKeyedEvent (NTDLL.@)
1485  */
1487  const OBJECT_ATTRIBUTES *attr, ULONG flags )
1488 {
1489  NTSTATUS ret;
1490  data_size_t len;
1491  struct object_attributes *objattr;
1492 
1493  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
1494 
1496  {
1497  req->access = access;
1498  wine_server_add_data( req, objattr, len );
1499  ret = wine_server_call( req );
1500  *handle = wine_server_ptr_handle( reply->handle );
1501  }
1503 
1504  free( objattr );
1505  return ret;
1506 }
1507 
1508 
1509 /******************************************************************************
1510  * NtOpenKeyedEvent (NTDLL.@)
1511  */
1513 {
1514  NTSTATUS ret;
1515 
1516  if ((ret = validate_open_object_attributes( attr ))) return ret;
1517 
1518  SERVER_START_REQ( open_keyed_event )
1519  {
1520  req->access = access;
1521  req->attributes = attr->Attributes;
1522  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
1523  if (attr->ObjectName)
1524  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
1525  ret = wine_server_call( req );
1526  *handle = wine_server_ptr_handle( reply->handle );
1527  }
1529  return ret;
1530 }
1531 
1532 /******************************************************************************
1533  * NtWaitForKeyedEvent (NTDLL.@)
1534  */
1536  BOOLEAN alertable, const LARGE_INTEGER *timeout )
1537 {
1540 
1541  if (!handle) handle = keyed_event;
1542  if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1;
1543  if (alertable) flags |= SELECT_ALERTABLE;
1544  select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
1545  select_op.keyed_event.handle = wine_server_obj_handle( handle );
1546  select_op.keyed_event.key = wine_server_client_ptr( key );
1547  return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
1548 }
1549 
1550 
1551 /******************************************************************************
1552  * NtReleaseKeyedEvent (NTDLL.@)
1553  */
1555  BOOLEAN alertable, const LARGE_INTEGER *timeout )
1556 {
1559 
1560  if (!handle) handle = keyed_event;
1561  if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1;
1562  if (alertable) flags |= SELECT_ALERTABLE;
1563  select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE;
1564  select_op.keyed_event.handle = wine_server_obj_handle( handle );
1565  select_op.keyed_event.key = wine_server_client_ptr( key );
1566  return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
1567 }
1568 
1569 
1570 /***********************************************************************
1571  * NtCreateIoCompletion (NTDLL.@)
1572  */
1574  ULONG threads )
1575 {
1576  NTSTATUS status;
1577  data_size_t len;
1578  struct object_attributes *objattr;
1579 
1580  TRACE( "(%p, %x, %p, %d)\n", handle, access, attr, threads );
1581 
1582  if (!handle) return STATUS_INVALID_PARAMETER;
1583  if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
1584 
1586  {
1587  req->access = access;
1588  req->concurrent = threads;
1589  wine_server_add_data( req, objattr, len );
1590  if (!(status = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
1591  }
1593 
1594  free( objattr );
1595  return status;
1596 }
1597 
1598 
1599 /***********************************************************************
1600  * NtOpenIoCompletion (NTDLL.@)
1601  */
1603 {
1604  NTSTATUS status;
1605 
1606  if (!handle) return STATUS_INVALID_PARAMETER;
1608 
1609  SERVER_START_REQ( open_completion )
1610  {
1611  req->access = access;
1612  req->attributes = attr->Attributes;
1613  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
1614  if (attr->ObjectName)
1615  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
1616  status = wine_server_call( req );
1617  *handle = wine_server_ptr_handle( reply->handle );
1618  }
1620  return status;
1621 }
1622 
1623 
1624 /***********************************************************************
1625  * NtSetIoCompletion (NTDLL.@)
1626  */
1628  NTSTATUS status, SIZE_T count )
1629 {
1630  NTSTATUS ret;
1631 
1632  TRACE( "(%p, %lx, %lx, %x, %lx)\n", handle, key, value, status, count );
1633 
1635  {
1636  req->handle = wine_server_obj_handle( handle );
1637  req->ckey = key;
1638  req->cvalue = value;
1639  req->status = status;
1640  req->information = count;
1641  ret = wine_server_call( req );
1642  }
1644  return ret;
1645 }
1646 
1647 
1648 /***********************************************************************
1649  * NtRemoveIoCompletion (NTDLL.@)
1650  */
1652  IO_STATUS_BLOCK *io, LARGE_INTEGER *timeout )
1653 {
1654  NTSTATUS status;
1655 
1656  TRACE( "(%p, %p, %p, %p, %p)\n", handle, key, value, io, timeout );
1657 
1658  for (;;)
1659  {
1660  SERVER_START_REQ( remove_completion )
1661  {
1662  req->handle = wine_server_obj_handle( handle );
1663  if (!(status = wine_server_call( req )))
1664  {
1665  *key = reply->ckey;
1666  *value = reply->cvalue;
1667  io->Information = reply->information;
1668  io->u.Status = reply->status;
1669  }
1670  }
1672  if (status != STATUS_PENDING) return status;
1673  status = NtWaitForSingleObject( handle, FALSE, timeout );
1674  if (status != WAIT_OBJECT_0) return status;
1675  }
1676 }
1677 
1678 
1679 /***********************************************************************
1680  * NtRemoveIoCompletionEx (NTDLL.@)
1681  */
1683  ULONG *written, LARGE_INTEGER *timeout, BOOLEAN alertable )
1684 {
1685  NTSTATUS status;
1686  ULONG i = 0;
1687 
1688  TRACE( "%p %p %u %p %p %u\n", handle, info, count, written, timeout, alertable );
1689 
1690  for (;;)
1691  {
1692  while (i < count)
1693  {
1694  SERVER_START_REQ( remove_completion )
1695  {
1696  req->handle = wine_server_obj_handle( handle );
1697  if (!(status = wine_server_call( req )))
1698  {
1699  info[i].CompletionKey = reply->ckey;
1700  info[i].CompletionValue = reply->cvalue;
1701  info[i].IoStatusBlock.Information = reply->information;
1702  info[i].IoStatusBlock.u.Status = reply->status;
1703  }
1704  }
1706  if (status != STATUS_SUCCESS) break;
1707  ++i;
1708  }
1709  if (i || status != STATUS_PENDING)
1710  {
1712  break;
1713  }
1714  status = NtWaitForSingleObject( handle, alertable, timeout );
1715  if (status != WAIT_OBJECT_0) break;
1716  }
1717  *written = i ? i : 1;
1718  return status;
1719 }
1720 
1721 
1722 /***********************************************************************
1723  * NtQueryIoCompletion (NTDLL.@)
1724  */
1726  void *buffer, ULONG len, ULONG *ret_len )
1727 {
1728  NTSTATUS status;
1729 
1730  TRACE( "(%p, %d, %p, 0x%x, %p)\n", handle, class, buffer, len, ret_len );
1731 
1732  if (!buffer) return STATUS_INVALID_PARAMETER;
1733 
1734  switch (class)
1735  {
1737  {
1738  ULONG *info = buffer;
1739  if (ret_len) *ret_len = sizeof(*info);
1740  if (len == sizeof(*info))
1741  {
1742  SERVER_START_REQ( query_completion )
1743  {
1744  req->handle = wine_server_obj_handle( handle );
1745  if (!(status = wine_server_call( req ))) *info = reply->depth;
1746  }
1748  }
1750  break;
1751  }
1752  default:
1753  return STATUS_INVALID_PARAMETER;
1754  }
1755  return status;
1756 }
1757 
1758 
1759 /***********************************************************************
1760  * NtCreateSection (NTDLL.@)
1761  */
1763  const LARGE_INTEGER *size, ULONG protect,
1764  ULONG sec_flags, HANDLE file )
1765 {
1766  NTSTATUS ret;
1767  unsigned int file_access;
1768  data_size_t len;
1769  struct object_attributes *objattr;
1770 
1771  switch (protect & 0xff)
1772  {
1773  case PAGE_READONLY:
1774  case PAGE_EXECUTE_READ:
1775  case PAGE_WRITECOPY:
1777  file_access = FILE_READ_DATA;
1778  break;
1779  case PAGE_READWRITE:
1781  if (sec_flags & SEC_IMAGE) file_access = FILE_READ_DATA;
1782  else file_access = FILE_READ_DATA | FILE_WRITE_DATA;
1783  break;
1784  case PAGE_EXECUTE:
1785  case PAGE_NOACCESS:
1786  file_access = 0;
1787  break;
1788  default:
1790  }
1791 
1792  if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
1793 
1795  {
1796  req->access = access;
1797  req->flags = sec_flags;
1798  req->file_handle = wine_server_obj_handle( file );
1799  req->file_access = file_access;
1800  req->size = size ? size->QuadPart : 0;
1801  wine_server_add_data( req, objattr, len );
1802  ret = wine_server_call( req );
1803  *handle = wine_server_ptr_handle( reply->handle );
1804  }
1806 
1807  free( objattr );
1808  return ret;
1809 }
1810 
1811 
1812 /***********************************************************************
1813  * NtOpenSection (NTDLL.@)
1814  */
1816 {
1817  NTSTATUS ret;
1818 
1819  if ((ret = validate_open_object_attributes( attr ))) return ret;
1820 
1821  SERVER_START_REQ( open_mapping )
1822  {
1823  req->access = access;
1824  req->attributes = attr->Attributes;
1825  req->rootdir = wine_server_obj_handle( attr->RootDirectory );
1826  if (attr->ObjectName)
1827  wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
1828  ret = wine_server_call( req );
1829  *handle = wine_server_ptr_handle( reply->handle );
1830  }
1832  return ret;
1833 }
1834 
1835 
1836 /***********************************************************************
1837  * NtCreatePort (NTDLL.@)
1838  */
1840  ULONG data_len, ULONG *reserved )
1841 {
1842  FIXME( "(%p,%p,%u,%u,%p),stub!\n", handle, attr, info_len, data_len, reserved );
1843  return STATUS_NOT_IMPLEMENTED;
1844 }
1845 
1846 
1847 /***********************************************************************
1848  * NtConnectPort (NTDLL.@)
1849  */
1852  void *info, ULONG *info_len )
1853 {
1854  FIXME( "(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n", handle, debugstr_us(name), qos,
1855  write, read, max_len, info, info_len );
1856  if (info && info_len) TRACE("msg = %s\n", debugstr_an( info, *info_len ));
1857  return STATUS_NOT_IMPLEMENTED;
1858 }
1859 
1860 
1861 /***********************************************************************
1862  * NtSecureConnectPort (NTDLL.@)
1863  */
1866  ULONG *max_len, void *info, ULONG *info_len )
1867 {
1868  FIXME( "(%p,%s,%p,%p,%p,%p,%p,%p,%p),stub!\n", handle, debugstr_us(name), qos,
1869  write, sid, read, max_len, info, info_len );
1870  return STATUS_NOT_IMPLEMENTED;
1871 }
1872 
1873 
1874 /***********************************************************************
1875  * NtListenPort (NTDLL.@)
1876  */
1878 {
1879  FIXME("(%p,%p),stub!\n", handle, msg );
1880  return STATUS_NOT_IMPLEMENTED;
1881 }
1882 
1883 
1884 /***********************************************************************
1885  * NtAcceptConnectPort (NTDLL.@)
1886  */
1889 {
1890  FIXME("(%p,%u,%p,%d,%p,%p),stub!\n", handle, id, msg, accept, write, read );
1891  return STATUS_NOT_IMPLEMENTED;
1892 }
1893 
1894 
1895 /***********************************************************************
1896  * NtCompleteConnectPort (NTDLL.@)
1897  */
1899 {
1900  FIXME( "(%p),stub!\n", handle );
1901  return STATUS_NOT_IMPLEMENTED;
1902 }
1903 
1904 
1905 /***********************************************************************
1906  * NtRegisterThreadTerminatePort (NTDLL.@)
1907  */
1909 {
1910  FIXME( "(%p),stub!\n", handle );
1911  return STATUS_NOT_IMPLEMENTED;
1912 }
1913 
1914 
1915 /***********************************************************************
1916  * NtRequestWaitReplyPort (NTDLL.@)
1917  */
1919 {
1920  FIXME( "(%p,%p,%p),stub!\n", handle, msg_in, msg_out );
1921  if (msg_in)
1922  TRACE("datasize %u msgsize %u type %u ranges %u client %p/%p msgid %lu size %lu data %s\n",
1923  msg_in->DataSize, msg_in->MessageSize, msg_in->MessageType, msg_in->VirtualRangesOffset,
1924  msg_in->ClientId.UniqueProcess, msg_in->ClientId.UniqueThread, msg_in->MessageId,
1925  msg_in->SectionSize, debugstr_an( (const char *)msg_in->Data, msg_in->DataSize ));
1926  return STATUS_NOT_IMPLEMENTED;
1927 }
1928 
1929 
1930 /***********************************************************************
1931  * NtReplyWaitReceivePort (NTDLL.@)
1932  */
1934 {
1935  FIXME("(%p,%p,%p,%p),stub!\n", handle, id, reply, msg );
1936  return STATUS_NOT_IMPLEMENTED;
1937 }
1938 
1939 
1940 #define MAX_ATOM_LEN 255
1941 #define IS_INTATOM(x) (((ULONG_PTR)(x) >> 16) == 0)
1942 
1943 static NTSTATUS is_integral_atom( const WCHAR *atomstr, ULONG len, RTL_ATOM *ret_atom )
1944 {
1945  RTL_ATOM atom;
1946 
1947  if ((ULONG_PTR)atomstr >> 16)
1948  {
1949  const WCHAR* ptr = atomstr;
1950  if (!len) return STATUS_OBJECT_NAME_INVALID;
1951 
1952  if (*ptr++ == '#')
1953  {
1954  atom = 0;
1955  while (ptr < atomstr + len && *ptr >= '0' && *ptr <= '9')
1956  {
1957  atom = atom * 10 + *ptr++ - '0';
1958  }
1959  if (ptr > atomstr + 1 && ptr == atomstr + len) goto done;
1960  }
1962  return STATUS_MORE_ENTRIES;
1963  }
1964  else atom = LOWORD( atomstr );
1965 done:
1966  if (!atom || atom >= MAXINTATOM) return STATUS_INVALID_PARAMETER;
1967  *ret_atom = atom;
1968  return STATUS_SUCCESS;
1969 }
1970 
1972 {
1973  char tmp[16];
1974  int ret = sprintf( tmp, "#%u", atom );
1975 
1976  len /= sizeof(WCHAR);
1977  if (len)
1978  {
1979  if (len <= ret) ret = len - 1;
1980  ascii_to_unicode( buffer, tmp, ret );
1981  buffer[ret] = 0;
1982  }
1983  return ret * sizeof(WCHAR);
1984 }
1985 
1986 
1987 /***********************************************************************
1988  * NtAddAtom (NTDLL.@)
1989  */
1991 {
1992  NTSTATUS status = is_integral_atom( name, length / sizeof(WCHAR), atom );
1993 
1994  if (status == STATUS_MORE_ENTRIES)
1995  {
1997  {
1998  wine_server_add_data( req, name, length );
1999  req->table = 0;
2000  status = wine_server_call( req );
2001  *atom = reply->atom;
2002  }
2004  }
2005  TRACE( "%s -> %x\n", debugstr_wn(name, length/sizeof(WCHAR)), status == STATUS_SUCCESS ? *atom : 0 );
2006  return status;
2007 }
2008 
2009 
2010 /***********************************************************************
2011  * NtDeleteAtom (NTDLL.@)
2012  */
2014 {
2015  NTSTATUS status;
2016 
2018  {
2019  req->atom = atom;
2020  req->table = 0;
2021  status = wine_server_call( req );
2022  }
2024  return status;
2025 }
2026 
2027 
2028 /***********************************************************************
2029  * NtFindAtom (NTDLL.@)
2030  */
2032 {
2033  NTSTATUS status = is_integral_atom( name, length / sizeof(WCHAR), atom );
2034 
2035  if (status == STATUS_MORE_ENTRIES)
2036  {
2038  {
2039  wine_server_add_data( req, name, length );
2040  req->table = 0;
2041  status = wine_server_call( req );
2042  *atom = reply->atom;
2043  }
2045  }
2046  TRACE( "%s -> %x\n", debugstr_wn(name, length/sizeof(WCHAR)), status == STATUS_SUCCESS ? *atom : 0 );
2047  return status;
2048 }
2049 
2050 
2051 /***********************************************************************
2052  * NtQueryInformationAtom (NTDLL.@)
2053  */
2055  void *ptr, ULONG size, ULONG *retsize )
2056 {
2057  NTSTATUS status;
2058 
2059  switch (class)
2060  {
2061  case AtomBasicInformation:
2062  {
2063  ULONG name_len;
2064  ATOM_BASIC_INFORMATION *abi = ptr;
2065 
2067  name_len = size - sizeof(ATOM_BASIC_INFORMATION);
2068 
2069  if (atom < MAXINTATOM)
2070  {
2071  if (atom)
2072  {
2073  abi->NameLength = integral_atom_name( abi->Name, name_len, atom );
2075  abi->ReferenceCount = 1;
2076  abi->Pinned = 1;
2077  }
2079  }
2080  else
2081  {
2082  SERVER_START_REQ( get_atom_information )
2083  {
2084  req->atom = atom;
2085  if (name_len) wine_server_set_reply( req, abi->Name, name_len );
2086  status = wine_server_call( req );
2087  if (status == STATUS_SUCCESS)
2088  {
2089  name_len = wine_server_reply_size( reply );
2090  if (name_len)
2091  {
2092  abi->NameLength = name_len;
2093  abi->Name[name_len / sizeof(WCHAR)] = 0;
2094  }
2095  else
2096  {
2097  name_len = reply->total;
2098  abi->NameLength = name_len;
2100  }
2101  abi->ReferenceCount = reply->count;
2102  abi->Pinned = reply->pinned;
2103  }
2104  else name_len = 0;
2105  }
2107  }
2108  TRACE( "%x -> %s (%u)\n", atom, debugstr_wn(abi->Name, abi->NameLength / sizeof(WCHAR)), status );
2109  if (retsize) *retsize = sizeof(ATOM_BASIC_INFORMATION) + name_len;
2110  break;
2111  }
2112 
2113  default:
2114  FIXME( "Unsupported class %u\n", class );
2116  break;
2117  }
2118  return status;
2119 }
2120 
2121 
2122 #ifdef __linux__
2123 
2125 {
2126  int val;
2127  struct timespec timespec;
2128 
2129  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2130 
2131  timespec.tv_sec = timeout;
2132  timespec.tv_nsec = 0;
2133  while ((val = InterlockedCompareExchange( (int *)&crit->LockSemaphore, 0, 1 )) != 1)
2134  {
2135  /* note: this may wait longer than specified in case of signals or */
2136  /* multiple wake-ups, but that shouldn't be a problem */
2137  if (futex_wait( (int *)&crit->LockSemaphore, val, &timespec ) == -1 && errno == ETIMEDOUT)
2138  return STATUS_TIMEOUT;
2139  }
2140  return STATUS_WAIT_0;
2141 }
2142 
2144 {
2145  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2146 
2147  *(int *)&crit->LockSemaphore = 1;
2148  futex_wake( (int *)&crit->LockSemaphore, 1 );
2149  return STATUS_SUCCESS;
2150 }
2151 
2153 {
2154  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2155  return STATUS_SUCCESS;
2156 }
2157 
2158 #elif defined(__APPLE__)
2159 
2160 static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
2161 {
2162  semaphore_t ret = *(int *)&crit->LockSemaphore;
2163  if (!ret)
2164  {
2165  semaphore_t sem;
2166  if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) return 0;
2167  if (!(ret = InterlockedCompareExchange( (int *)&crit->LockSemaphore, sem, 0 )))
2168  ret = sem;
2169  else
2170  semaphore_destroy( mach_task_self(), sem ); /* somebody beat us to it */
2171  }
2172  return ret;
2173 }
2174 
2176 {
2177  mach_timespec_t timespec;
2178  semaphore_t sem = get_mach_semaphore( crit );
2179 
2180  timespec.tv_sec = timeout;
2181  timespec.tv_nsec = 0;
2182  for (;;)
2183  {
2184  switch( semaphore_timedwait( sem, timespec ))
2185  {
2186  case KERN_SUCCESS:
2187  return STATUS_WAIT_0;
2188  case KERN_ABORTED:
2189  continue; /* got a signal, restart */
2190  case KERN_OPERATION_TIMED_OUT:
2191  return STATUS_TIMEOUT;
2192  default:
2193  return STATUS_INVALID_HANDLE;
2194  }
2195  }
2196 }
2197 
2199 {
2200  semaphore_t sem = get_mach_semaphore( crit );
2201  semaphore_signal( sem );
2202  return STATUS_SUCCESS;
2203 }
2204 
2206 {
2207  semaphore_destroy( mach_task_self(), *(int *)&crit->LockSemaphore );
2208  return STATUS_SUCCESS;
2209 }
2210 
2211 #else /* __APPLE__ */
2212 
2214 {
2215  return STATUS_NOT_IMPLEMENTED;
2216 }
2217 
2219 {
2220  return STATUS_NOT_IMPLEMENTED;
2221 }
2222 
2224 {
2225  return STATUS_NOT_IMPLEMENTED;
2226 }
2227 
2228 #endif
2229 
2230 
2231 #ifdef __linux__
2232 
2233 /* Futex-based SRW lock implementation:
2234  *
2235  * Since we can rely on the kernel to release all threads and don't need to
2236  * worry about NtReleaseKeyedEvent(), we can simplify the layout a bit. The
2237  * layout looks like this:
2238  *
2239  * 31 - Exclusive lock bit, set if the resource is owned exclusively.
2240  * 30-16 - Number of exclusive waiters. Unlike the fallback implementation,
2241  * this does not include the thread owning the lock, or shared threads
2242  * waiting on the lock.
2243  * 15 - Does this lock have any shared waiters? We use this as an
2244  * optimization to avoid unnecessary FUTEX_WAKE_BITSET calls when
2245  * releasing an exclusive lock.
2246  * 14-0 - Number of shared owners. Unlike the fallback implementation, this
2247  * does not include the number of shared threads waiting on the lock.
2248  * Thus the state [1, x, >=1] will never occur.
2249  */
2250 
2251 #define SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT 0x80000000
2252 #define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK 0x7fff0000
2253 #define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC 0x00010000
2254 #define SRWLOCK_FUTEX_SHARED_WAITERS_BIT 0x00008000
2255 #define SRWLOCK_FUTEX_SHARED_OWNERS_MASK 0x00007fff
2256 #define SRWLOCK_FUTEX_SHARED_OWNERS_INC 0x00000001
2257 
2258 /* Futex bitmasks; these are independent from the bits in the lock itself. */
2259 #define SRWLOCK_FUTEX_BITSET_EXCLUSIVE 1
2260 #define SRWLOCK_FUTEX_BITSET_SHARED 2
2261 
2263 {
2264  int old, new, *futex;
2265  NTSTATUS ret;
2266 
2267  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2268 
2269  if (!(futex = get_futex( &lock->Ptr )))
2270  return STATUS_NOT_IMPLEMENTED;
2271 
2272  do
2273  {
2274  old = *futex;
2275 
2276  if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
2277  && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
2278  {
2279  /* Not locked exclusive or shared. We can try to grab it. */
2280  new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
2281  ret = STATUS_SUCCESS;
2282  }
2283  else
2284  {
2285  new = old;
2286  ret = STATUS_TIMEOUT;
2287  }
2288  } while (InterlockedCompareExchange( futex, new, old ) != old);
2289 
2290  return ret;
2291 }
2292 
2294 {
2295  int old, new, *futex;
2296  BOOLEAN wait;
2297 
2298  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2299 
2300  if (!(futex = get_futex( &lock->Ptr )))
2301  return STATUS_NOT_IMPLEMENTED;
2302 
2303  /* Atomically increment the exclusive waiter count. */
2304  do
2305  {
2306  old = *futex;
2307  new = old + SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
2308  assert(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
2309  } while (InterlockedCompareExchange( futex, new, old ) != old);
2310 
2311  for (;;)
2312  {
2313  do
2314  {
2315  old = *futex;
2316 
2317  if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
2318  && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
2319  {
2320  /* Not locked exclusive or shared. We can try to grab it. */
2321  new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
2322  assert(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
2323  new -= SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
2324  wait = FALSE;
2325  }
2326  else
2327  {
2328  new = old;
2329  wait = TRUE;
2330  }
2331  } while (InterlockedCompareExchange( futex, new, old ) != old);
2332 
2333  if (!wait)
2334  return STATUS_SUCCESS;
2335 
2336  futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
2337  }
2338 
2339  return STATUS_SUCCESS;
2340 }
2341 
2343 {
2344  int new, old, *futex;
2345  NTSTATUS ret;
2346 
2347  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2348 
2349  if (!(futex = get_futex( &lock->Ptr )))
2350  return STATUS_NOT_IMPLEMENTED;
2351 
2352  do
2353  {
2354  old = *futex;
2355 
2356  if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
2357  && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
2358  {
2359  /* Not locked exclusive, and no exclusive waiters. We can try to
2360  * grab it. */
2361  new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
2362  assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
2363  ret = STATUS_SUCCESS;
2364  }
2365  else
2366  {
2367  new = old;
2368  ret = STATUS_TIMEOUT;
2369  }
2370  } while (InterlockedCompareExchange( futex, new, old ) != old);
2371 
2372  return ret;
2373 }
2374 
2376 {
2377  int old, new, *futex;
2378  BOOLEAN wait;
2379 
2380  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2381 
2382  if (!(futex = get_futex( &lock->Ptr )))
2383  return STATUS_NOT_IMPLEMENTED;
2384 
2385  for (;;)
2386  {
2387  do
2388  {
2389  old = *futex;
2390 
2391  if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
2392  && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
2393  {
2394  /* Not locked exclusive, and no exclusive waiters. We can try
2395  * to grab it. */
2396  new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
2397  assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
2398  wait = FALSE;
2399  }
2400  else
2401  {
2402  new = old | SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
2403  wait = TRUE;
2404  }
2405  } while (InterlockedCompareExchange( futex, new, old ) != old);
2406 
2407  if (!wait)
2408  return STATUS_SUCCESS;
2409 
2410  futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_SHARED );
2411  }
2412 
2413  return STATUS_SUCCESS;
2414 }
2415 
2417 {
2418  int old, new, *futex;
2419 
2420  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2421 
2422  if (!(futex = get_futex( &lock->Ptr )))
2423  return STATUS_NOT_IMPLEMENTED;
2424 
2425  do
2426  {
2427  old = *futex;
2428 
2429  if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT))
2430  {
2431  ERR("Lock %p is not owned exclusive! (%#x)\n", lock, *futex);
2433  }
2434 
2435  new = old & ~~SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
2436 
2437  if (!(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
2438  new &= ~~SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
2439  } while (InterlockedCompareExchange( futex, new, old ) != old);
2440 
2441  if (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)
2442  futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
2443  else if (old & SRWLOCK_FUTEX_SHARED_WAITERS_BIT)
2444  futex_wake_bitset( futex, INT_MAX, SRWLOCK_FUTEX_BITSET_SHARED );
2445 
2446  return STATUS_SUCCESS;
2447 }
2448 
2450 {
2451  int old, new, *futex;
2452 
2453  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2454 
2455  if (!(futex = get_futex( &lock->Ptr )))
2456  return STATUS_NOT_IMPLEMENTED;
2457 
2458  do
2459  {
2460  old = *futex;
2461 
2462  if (old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
2463  {
2464  ERR("Lock %p is owned exclusive! (%#x)\n", lock, *futex);
2466  }
2467  else if (!(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
2468  {
2469  ERR("Lock %p is not owned shared! (%#x)\n", lock, *futex);
2471  }
2472 
2473  new = old - SRWLOCK_FUTEX_SHARED_OWNERS_INC;
2474  } while (InterlockedCompareExchange( futex, new, old ) != old);
2475 
2476  /* Optimization: only bother waking if there are actually exclusive waiters. */
2477  if (!(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK) && (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
2478  futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
2479 
2480  return STATUS_SUCCESS;
2481 }
2482 
2483 NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
2484 {
2485  const char *value_ptr;
2486  int aligned_value, *futex;
2487  struct timespec timespec;
2488  int ret;
2489 
2490  if (!use_futexes())
2491  return STATUS_NOT_IMPLEMENTED;
2492 
2493  if (!(futex = get_futex( &variable->Ptr )))
2494  return STATUS_NOT_IMPLEMENTED;
2495 
2496  value_ptr = (const char *)&value;
2497  value_ptr += ((ULONG_PTR)futex) - ((ULONG_PTR)&variable->Ptr);
2498  aligned_value = *(int *)value_ptr;
2499 
2500  if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
2501  {
2502  timespec_from_timeout( &timespec, timeout );
2503  ret = futex_wait( futex, aligned_value, &timespec );
2504  }
2505  else
2506  ret = futex_wait( futex, aligned_value, NULL );
2507 
2508  if (ret == -1 && errno == ETIMEDOUT)
2509  return STATUS_TIMEOUT;
2510  return STATUS_WAIT_0;
2511 }
2512 
2514 {
2515  int *futex;
2516 
2517  if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
2518 
2519  if (!(futex = get_futex( &variable->Ptr )))
2520  return STATUS_NOT_IMPLEMENTED;
2521 
2522  InterlockedIncrement( futex );
2523  futex_wake( futex, count );
2524  return STATUS_SUCCESS;
2525 }
2526 
2527 
2528 /* We can't map addresses to futex directly, because an application can wait on
2529  * 8 bytes, and we can't pass all 8 as the compare value to futex(). Instead we
2530  * map all addresses to a small fixed table of futexes. This may result in
2531  * spurious wakes, but the application is already expected to handle those. */
2532 
2533 static int addr_futex_table[256];
2534 
2535 static inline int *hash_addr( const void *addr )
2536 {
2537  ULONG_PTR val = (ULONG_PTR)addr;
2538 
2539  return &addr_futex_table[(val >> 2) & 255];
2540 }
2541 
2542 static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
2543  const LARGE_INTEGER *timeout )
2544 {
2545  int *futex;
2546  int val;
2547  struct timespec timespec;
2548  int ret;
2549 
2550  if (!use_futexes())
2551  return STATUS_NOT_IMPLEMENTED;
2552 
2553  futex = hash_addr( addr );
2554 
2555  /* We must read the previous value of the futex before checking the value
2556  * of the address being waited on. That way, if we receive a wake between
2557  * now and waiting on the futex, we know that val will have changed.
2558  * Use an atomic load so that memory accesses are ordered between this read
2559  * and the increment below. */
2560  val = InterlockedCompareExchange( futex, 0, 0 );
2561  if (!compare_addr( addr, cmp, size ))
2562  return STATUS_SUCCESS;
2563 
2564  if (timeout)
2565  {
2566  timespec_from_timeout( &timespec, timeout );
2567  ret = futex_wait( futex, val, &timespec );
2568  }
2569  else
2570  ret = futex_wait( futex, val, NULL );
2571 
2572  if (ret == -1 && errno == ETIMEDOUT)
2573  return STATUS_TIMEOUT;
2574  return STATUS_SUCCESS;
2575 }
2576 
2577 static inline NTSTATUS fast_wake_addr( const void *addr )
2578 {
2579  int *futex;
2580 
2581  if (!use_futexes())
2582  return STATUS_NOT_IMPLEMENTED;
2583 
2584  futex = hash_addr( addr );
2585 
2586  InterlockedIncrement( futex );
2587 
2588  futex_wake( futex, INT_MAX );
2589  return STATUS_SUCCESS;
2590 }
2591 
2592 #else
2593 
2595 {
2596  return STATUS_NOT_IMPLEMENTED;
2597 }
2598 
2600 {
2601  return STATUS_NOT_IMPLEMENTED;
2602 }
2603 
2605 {
2606  return STATUS_NOT_IMPLEMENTED;
2607 }
2608 
2610 {
2611  return STATUS_NOT_IMPLEMENTED;
2612 }
2613 
2615 {
2616  return STATUS_NOT_IMPLEMENTED;
2617 }
2618 
2620 {
2621  return STATUS_NOT_IMPLEMENTED;
2622 }
2623 
2625 {
2626  return STATUS_NOT_IMPLEMENTED;
2627 }
2628 
2629 NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
2630 {
2631  return STATUS_NOT_IMPLEMENTED;
2632 }
2633 
2634 static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
2635  const LARGE_INTEGER *timeout )
2636 {
2637  return STATUS_NOT_IMPLEMENTED;
2638 }
2639 
2640 static inline NTSTATUS fast_wake_addr( const void *addr )
2641 {
2642  return STATUS_NOT_IMPLEMENTED;
2643 }
2644 
2645 #endif
2646 
2647 
2648 /***********************************************************************
2649  * RtlWaitOnAddress (NTDLL.@)
2650  */
2651 NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
2652  const LARGE_INTEGER *timeout )
2653 {
2655  NTSTATUS ret;
2656  timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
2657 
2658  if (size != 1 && size != 2 && size != 4 && size != 8)
2659  return STATUS_INVALID_PARAMETER;
2660 
2661  if ((ret = fast_wait_addr( addr, cmp, size, timeout )) != STATUS_NOT_IMPLEMENTED)
2662  return ret;
2663 
2664  mutex_lock( &addr_mutex );
2665  if (!compare_addr( addr, cmp, size ))
2666  {
2668  return STATUS_SUCCESS;
2669  }
2670 
2671  if (abs_timeout < 0)
2672  {
2674 
2676  abs_timeout -= now.QuadPart;
2677  }
2678 
2679  select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
2680  select_op.keyed_event.handle = wine_server_obj_handle( keyed_event );
2681  select_op.keyed_event.key = wine_server_client_ptr( addr );
2682 
2683  return server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE,
2684  abs_timeout, NULL, &addr_mutex, NULL );
2685 }
2686 
2687 /***********************************************************************
2688  * RtlWakeAddressAll (NTDLL.@)
2689  */
2690 void WINAPI RtlWakeAddressAll( const void *addr )
2691 {
2692  if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
2693 
2694  mutex_lock( &addr_mutex );
2695  while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
2697 }
2698 
2699 /***********************************************************************
2700  * RtlWakeAddressSingle (NTDLL.@)
2701  */
2702 void WINAPI RtlWakeAddressSingle( const void *addr )
2703 {
2704  if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
2705 
2706  mutex_lock( &addr_mutex );
2707  NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
2709 }
static LPCSTR debugstr_us(const UNICODE_STRING *us)
Definition: lsa.c:47
#define assert(_expr)
Definition: assert.h:32
static BOOL create_job(const WCHAR *job_name, const AT_INFO *info)
Definition: atsvc.c:757
unsigned long long ULONG64
Definition: basetsd.h:99
unsigned long ULONG_PTR
Definition: basetsd.h:130
ULONG_PTR SIZE_T
Definition: basetsd.h:264
LONG NTSTATUS
Definition: bcrypt.h:40
#define WINAPI
Definition: bcrypt.h:23
Definition: type.pm:7
#define ERR(...)
Definition: cocoa_app.h:61
DWORD mask
Definition: fontdlg.c:120
static struct completion * create_completion(struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent, const struct security_descriptor *sd)
Definition: completion.c:134
static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant, const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index, BOOL is_pointer)
Definition: shader.c:1062
void mutex_unlock(mutex *this)
Definition: misc.c:298
void mutex_lock(mutex *this)
Definition: misc.c:290
void * memcpy(void *dst, const void *src, size_t n)
Definition: string.c:2580
void * memset(void *dst, int c, size_t n)
Definition: string.c:2588
void * memmove(void *dst, const void *src, size_t n)
Definition: string.c:2481
static void add_completion(HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async)
Definition: file.c:4922
unsigned int server_select(const select_op_t *select_op, data_size_t size, UINT flags, timeout_t abs_timeout, CONTEXT *context, pthread_mutex_t *mutex, user_apc_t *user_apc)
Definition: server.c:604
unsigned int server_wait(const select_op_t *select_op, data_size_t size, UINT flags, const LARGE_INTEGER *timeout)
Definition: server.c:690
timeout_t server_start_time
Definition: server.c:110
unsigned int wine_server_call(void *req_ptr)
Definition: server.c:283
static BOOL get_job_info(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
Definition: info.c:8081
unsigned int UINT
Definition: dxgicommon.idl:20
long BOOL
Definition: dxgitype.idl:24
static const char * debugstr_wn(const WCHAR *wstr, unsigned int n)
Definition: emf.c:48
#define ENOSYS
Definition: errno.h:60
#define ETIMEDOUT
Definition: errno.h:105
#define errno
Definition: errno.h:120
NTSTATUS status
Definition: except.c:81
int signal
Definition: except.c:82
#define WINE_DEFAULT_DEBUG_CHANNEL(ch)
Definition: debug.h:499
static HINF handles[16384]
Definition: infparse.c:48
static int access(const char *path, int mode)
Definition: io.h:110
static int read(int fd, void *buf, unsigned int size)
Definition: io.h:123
static int write(int fd, const void *buf, unsigned int size)
Definition: io.h:134
BYTE flags
Definition: ioports.c:48
static void set_timer(unsigned timer)
Definition: ioports.c:159
static struct mapping_info * create_mapping(LPCWSTR name, BOOL rw)
Definition: resource.c:696
static const struct _KUSER_SHARED_DATA * user_shared_data
Definition: sync.c:45
struct version_info info
Definition: version.c:140
#define INT_MAX
Definition: limits.h:26
static const char * ts(int t)
Definition: macro.lex.l:135
#define max(a, b)
Definition: minmax.h:25
static void size_t len
static UINT create_directory(MSIPACKAGE *package, const WCHAR *dir)
Definition: files.c:466
#define TICKSPERSEC
Definition: ios.c:35
void * calloc(size_t count, size_t size)
Definition: heap.c:386
void free(void *ptr)
Definition: heap.c:412
static struct mutex * create_mutex(struct object *root, const struct unicode_str *name, unsigned int attr, int owned, const struct security_descriptor *sd)
Definition: mutex.c:104
void * buffer
Definition: ntddk.h:198
enum _TIMER_TYPE TIMER_TYPE
@ NotificationEvent
Definition: ntdef.h:29
@ SynchronizationEvent
Definition: ntdef.h:30
enum _EVENT_TYPE EVENT_TYPE
@ SynchronizationTimer
Definition: ntdef.h:35
@ NotificationTimer
Definition: ntdef.h:34
void RtlWakeAddressAll(const void *addr)
Definition: sync.c:546
void RtlWakeAddressSingle(const void *addr)
Definition: sync.c:554
NTSTATUS RtlWaitOnAddress(const void *addr, const void *cmp, SIZE_T size, const LARGE_INTEGER *timeout)
Definition: sync.c:537
NTSTATUS NtQueryInformationAtom(RTL_ATOM atom, ATOM_INFORMATION_CLASS class, void *ptr, ULONG size, ULONG *retsize)
Definition: sync.c:2054
NTSTATUS NtDelayExecution(BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1321
NTSTATUS NtIsProcessInJob(HANDLE process, HANDLE job)
Definition: sync.c:871
NTSTATUS NtCreateDirectoryObject(HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr)
Definition: sync.c:911
static NTSTATUS fast_wait_addr(const void *addr, const void *cmp, SIZE_T size, const LARGE_INTEGER *timeout)
Definition: sync.c:2634
HANDLE keyed_event
Definition: sync.c:78
static NTSTATUS validate_open_object_attributes(const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:298
NTSTATUS NtQueryTimer(HANDLE handle, TIMER_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:1212
NTSTATUS alloc_object_attributes(const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, data_size_t *ret_len)
Definition: sync.c:206
NTSTATUS NtClearEvent(HANDLE handle)
Definition: sync.c:513
NTSTATUS NtRemoveIoCompletion(HANDLE handle, ULONG_PTR *key, ULONG_PTR *value, IO_STATUS_BLOCK *io, LARGE_INTEGER *timeout)
Definition: sync.c:1651
NTSTATUS NtReleaseKeyedEvent(HANDLE handle, const void *key, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1554
NTSTATUS NtOpenMutant(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:604
NTSTATUS NtMakeTemporaryObject(HANDLE handle)
Definition: sync.c:1093
NTSTATUS NtYieldExecution(void)
Definition: sync.c:1307
static BOOL compare_addr(const void *addr, const void *cmp, SIZE_T size)
Definition: sync.c:187
NTSTATUS fast_RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *crit)
Definition: sync.c:2218
NTSTATUS fast_RtlTryAcquireSRWLockShared(RTL_SRWLOCK *lock)
Definition: sync.c:2604
NTSTATUS NtRequestWaitReplyPort(HANDLE handle, LPC_MESSAGE *msg_in, LPC_MESSAGE *msg_out)
Definition: sync.c:1918
NTSTATUS NtCreateKeyedEvent(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, ULONG flags)
Definition: sync.c:1486
NTSTATUS NtSignalAndWaitForSingleObject(HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1288
NTSTATUS NtOpenTimer(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:1142
NTSTATUS fast_RtlpWaitForCriticalSection(RTL_CRITICAL_SECTION *crit, int timeout)
Definition: sync.c:2213
NTSTATUS NtCreateSymbolicLinkObject(HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, UNICODE_STRING *target)
Definition: sync.c:1011
NTSTATUS NtListenPort(HANDLE handle, LPC_MESSAGE *msg)
Definition: sync.c:1877
NTSTATUS NtQuerySemaphore(HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:368
NTSTATUS NtOpenKeyedEvent(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:1512
NTSTATUS NtCompleteConnectPort(HANDLE handle)
Definition: sync.c:1898
NTSTATUS NtSetSystemTime(const LARGE_INTEGER *new, LARGE_INTEGER *old)
Definition: sync.c:1412
NTSTATUS NtCreateIoCompletion(HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, ULONG threads)
Definition: sync.c:1573
NTSTATUS NtOpenSymbolicLinkObject(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:1040
static const LARGE_INTEGER zero_timeout
Definition: sync.c:80
#define MAX_ATOM_LEN
Definition: sync.c:1940
NTSTATUS fast_RtlDeleteCriticalSection(RTL_CRITICAL_SECTION *crit)
Definition: sync.c:2223
NTSTATUS NtFindAtom(const WCHAR *name, ULONG length, RTL_ATOM *atom)
Definition: sync.c:2031
NTSTATUS NtWaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1261
NTSTATUS NtResetEvent(HANDLE handle, LONG *prev_state)
Definition: sync.c:494
NTSTATUS NtOpenSection(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:1815
NTSTATUS NtReleaseMutant(HANDLE handle, LONG *prev_count)
Definition: sync.c:628
NTSTATUS NtQueryInformationJobObject(HANDLE handle, JOBOBJECTINFOCLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:750
NTSTATUS NtAssignProcessToJobObject(HANDLE job, HANDLE process)
Definition: sync.c:891
NTSTATUS NtPulseEvent(HANDLE handle, LONG *prev_state)
Definition: sync.c:523
NTSTATUS NtOpenIoCompletion(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:1602
NTSTATUS fast_RtlReleaseSRWLockShared(RTL_SRWLOCK *lock)
Definition: sync.c:2619
NTSTATUS NtQuerySymbolicLinkObject(HANDLE handle, UNICODE_STRING *target, ULONG *length)
Definition: sync.c:1066
NTSTATUS fast_RtlAcquireSRWLockShared(RTL_SRWLOCK *lock)
Definition: sync.c:2609
NTSTATUS NtCreatePort(HANDLE *handle, OBJECT_ATTRIBUTES *attr, ULONG info_len, ULONG data_len, ULONG *reserved)
Definition: sync.c:1839
NTSTATUS NtOpenEvent(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:451
NTSTATUS NtCreateJobObject(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:681
NTSTATUS fast_RtlReleaseSRWLockExclusive(RTL_SRWLOCK *lock)
Definition: sync.c:2614
NTSTATUS NtRegisterThreadTerminatePort(HANDLE handle)
Definition: sync.c:1908
static ULONGLONG monotonic_counter(void)
Definition: sync.c:85
NTSTATUS NtOpenSemaphore(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:344
static NTSTATUS is_integral_atom(const WCHAR *atomstr, ULONG len, RTL_ATOM *ret_atom)
Definition: sync.c:1943
NTSTATUS NtTerminateJobObject(HANDLE handle, NTSTATUS status)
Definition: sync.c:729
NTSTATUS NtAddAtom(const WCHAR *name, ULONG length, RTL_ATOM *atom)
Definition: sync.c:1990
NTSTATUS NtDeleteAtom(RTL_ATOM atom)
Definition: sync.c:2013
NTSTATUS NtConnectPort(HANDLE *handle, UNICODE_STRING *name, SECURITY_QUALITY_OF_SERVICE *qos, LPC_SECTION_WRITE *write, LPC_SECTION_READ *read, ULONG *max_len, void *info, ULONG *info_len)
Definition: sync.c:1850
NTSTATUS NtCreateSemaphore(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
Definition: sync.c:315
NTSTATUS fast_wait_cv(RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout)
Definition: sync.c:2629
NTSTATUS NtRemoveIoCompletionEx(HANDLE handle, FILE_IO_COMPLETION_INFORMATION *info, ULONG count, ULONG *written, LARGE_INTEGER *timeout, BOOLEAN alertable)
Definition: sync.c:1682
NTSTATUS NtSecureConnectPort(HANDLE *handle, UNICODE_STRING *name, SECURITY_QUALITY_OF_SERVICE *qos, LPC_SECTION_WRITE *write, PSID sid, LPC_SECTION_READ *read, ULONG *max_len, void *info, ULONG *info_len)
Definition: sync.c:1864
NTSTATUS NtCreateMutant(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, BOOLEAN owned)
Definition: sync.c:577
NTSTATUS NtCancelTimer(HANDLE handle, BOOLEAN *state)
Definition: sync.c:1194
NTSTATUS NtQueryPerformanceCounter(LARGE_INTEGER *counter, LARGE_INTEGER *frequency)
Definition: sync.c:1363
static ULONG integral_atom_name(WCHAR *buffer, ULONG len, RTL_ATOM atom)
Definition: sync.c:1971
NTSTATUS NtQueryIoCompletion(HANDLE handle, IO_COMPLETION_INFORMATION_CLASS class, void *buffer, ULONG len, ULONG *ret_len)
Definition: sync.c:1725
NTSTATUS fast_RtlAcquireSRWLockExclusive(RTL_SRWLOCK *lock)
Definition: sync.c:2599
NTSTATUS NtAcceptConnectPort(HANDLE *handle, ULONG id, LPC_MESSAGE *msg, BOOLEAN accept, LPC_SECTION_WRITE *write, LPC_SECTION_READ *read)
Definition: sync.c:1887
NTSTATUS NtSetIntervalProfile(ULONG interval, KPROFILE_SOURCE source)
Definition: sync.c:1449
NTSTATUS NtCreateEvent(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN state)
Definition: sync.c:423
NTSTATUS NtQuerySystemTime(LARGE_INTEGER *time)
Definition: sync.c:1374
NTSTATUS NtSetTimerResolution(ULONG res, BOOLEAN set, ULONG *current_res)
Definition: sync.c:1439
NTSTATUS NtCreateTimer(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, TIMER_TYPE type)
Definition: sync.c:1112
NTSTATUS NtSetEvent(HANDLE handle, LONG *prev_state)
Definition: sync.c:475
LONGLONG RtlGetSystemTimePrecise(void)
Definition: sync.c:1469
NTSTATUS NtQueryTimerResolution(ULONG *min_res, ULONG *max_res, ULONG *current_res)
Definition: sync.c:1429
NTSTATUS NtCreateSection(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, const LARGE_INTEGER *size, ULONG protect, ULONG sec_flags, HANDLE file)
Definition: sync.c:1762
NTSTATUS NtOpenDirectoryObject(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:937
NTSTATUS NtWaitForSingleObject(HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1279
static pthread_mutex_t addr_mutex
Definition: sync.c:82
NTSTATUS NtSetInformationJobObject(HANDLE handle, JOBOBJECTINFOCLASS class, void *info, ULONG len)
Definition: sync.c:816
NTSTATUS NtWaitForKeyedEvent(HANDLE handle, const void *key, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1535
NTSTATUS NtQueryDirectoryObject(HANDLE handle, DIRECTORY_BASIC_INFORMATION *buffer, ULONG size, BOOLEAN single_entry, BOOLEAN restart, ULONG *context, ULONG *ret_size)
Definition: sync.c:962
NTSTATUS NtReplyWaitReceivePort(HANDLE handle, ULONG *id, LPC_MESSAGE *reply, LPC_MESSAGE *msg)
Definition: sync.c:1933
NTSTATUS fast_RtlTryAcquireSRWLockExclusive(RTL_SRWLOCK *lock)
Definition: sync.c:2594
NTSTATUS NtSetTimer(HANDLE handle, const LARGE_INTEGER *when, PTIMER_APC_ROUTINE callback, void *arg, BOOLEAN resume, ULONG period, BOOLEAN *state)
Definition: sync.c:1166
NTSTATUS NtQueryEvent(HANDLE handle, EVENT_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:542
NTSTATUS NtReleaseSemaphore(HANDLE handle, ULONG count, ULONG *previous)
Definition: sync.c:402
NTSTATUS NtOpenJobObject(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
Definition: sync.c:705
ULONG NtGetTickCount(void)
Definition: sync.c:1459
NTSTATUS fast_RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *variable, int count)
Definition: sync.c:2624
static NTSTATUS fast_wake_addr(const void *addr)
Definition: sync.c:2640
NTSTATUS NtQueryMutant(HANDLE handle, MUTANT_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:646
NTSTATUS NtSetIoCompletion(HANDLE handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count)
Definition: sync.c:1627
static void ascii_to_unicode(WCHAR *dst, const char *src, size_t len)
Definition: ntdll_misc.h:125
PSecurityUserData *typedef PSECPKG_EXTENDED_INFORMATION *typedef ULONG
Definition: ntsecpkg.h:377
#define STATUS_TIMEOUT
Definition: ntstatus.h:47
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:218
#define STATUS_WAIT_0
Definition: ntstatus.h:36
#define STATUS_UNKNOWN_REVISION
Definition: ntstatus.h:298
#define STATUS_INVALID_PARAMETER
Definition: ntstatus.h:223
#define STATUS_PRIVILEGE_NOT_HELD
Definition: ntstatus.h:307
#define STATUS_PENDING
Definition: ntstatus.h:48
#define STATUS_NO_MEMORY
Definition: ntstatus.h:233
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:215
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:212
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:279
#define STATUS_MORE_ENTRIES
Definition: ntstatus.h:50
#define STATUS_NO_YIELD_PERFORMED
Definition: ntstatus.h:123
#define STATUS_BUFFER_TOO_SMALL
Definition: ntstatus.h:245
#define STATUS_INFO_LENGTH_MISMATCH
Definition: ntstatus.h:214
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:213
#define STATUS_BUFFER_OVERFLOW
Definition: ntstatus.h:157
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:449
#define STATUS_RESOURCE_NOT_OWNED
Definition: ntstatus.h:731
#define STATUS_TIMER_RESUME_IGNORED
Definition: ntstatus.h:124
#define STATUS_SUCCESS
Definition: ntstatus.h:30
#define STATUS_OBJECT_NAME_INVALID
Definition: ntstatus.h:261
struct object * create_symlink(struct object *root, const struct unicode_str *name, unsigned int attr, const struct unicode_str *target, const struct security_descriptor *sd)
Definition: symlink.c:139
static ALenum ALfloat value
Definition: openal.c:51
HKEY key
Definition: registrar.c:33
struct max_sid sid
Definition: security.c:87
static int semaphore_signal(struct object *obj, unsigned int access)
Definition: semaphore.c:161
static int release_semaphore(struct semaphore *sem, unsigned int count, unsigned int *prev)
Definition: semaphore.c:101
static struct semaphore * create_semaphore(struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int initial, unsigned int max, const struct security_descriptor *sd)
Definition: semaphore.c:78
static atom_t find_atom(struct atom_table *table, const struct unicode_str *str)
Definition: atom.c:274
static void delete_atom(struct atom_table *table, atom_t atom, int if_pinned)
Definition: atom.c:258
static atom_t add_atom(struct atom_table *table, const struct unicode_str *str)
Definition: atom.c:216
struct event * create_event(struct object *root, const struct unicode_str *name, unsigned int attr, int manual_reset, int initial_state, const struct security_descriptor *sd)
Definition: event.c:115
struct keyed_event * create_keyed_event(struct object *root, const struct unicode_str *name, unsigned int attr, const struct security_descriptor *sd)
Definition: event.c:218
static void terminate_job(struct job *job, int exit_code)
Definition: process.c:271
DWORD SubAuthority[5]
Definition: token.c:81
#define SERVER_END_REQ
Definition: server.h:137
static HANDLE wine_server_ptr_handle(obj_handle_t handle)
Definition: server.h:106
static void wine_server_add_data(void *req_ptr, const void *ptr, data_size_t size)
Definition: server.h:73
static void wine_server_set_reply(void *req_ptr, void *ptr, data_size_t max_size)
Definition: server.h:85
#define SERVER_START_REQ(type)
Definition: server.h:126
static client_ptr_t wine_server_client_ptr(const void *ptr)
Definition: server.h:112
static obj_handle_t wine_server_obj_handle(HANDLE handle)
Definition: server.h:93
static data_size_t wine_server_reply_size(const void *reply)
Definition: server.h:67
select_op
@ SELECT_SIGNAL_AND_WAIT
@ SELECT_KEYED_EVENT_WAIT
@ SELECT_KEYED_EVENT_RELEASE
@ SELECT_WAIT
@ SELECT_WAIT_ALL
long long timeout_t
#define SELECT_INTERRUPTIBLE
event_op
@ SET_EVENT
@ PULSE_EVENT
@ RESET_EVENT
#define TIMEOUT_INFINITE
#define SELECT_ALERTABLE
unsigned int data_size_t
#define offsetof(s, m)
Definition: stddef.h:28
SECURITY_DESCRIPTOR_CONTROL Control
Definition: winnt.h:4594
Definition: winnt.h:4397
WORD AclSize
Definition: winnt.h:4400
HANDLE UniqueThread
Definition: winternl.h:134
HANDLE UniqueProcess
Definition: winternl.h:133
NTSTATUS Status
Definition: winternl.h:1470
ULONG_PTR Information
Definition: winternl.h:1474
ULONG_PTR SectionSize
Definition: winternl.h:2493
USHORT VirtualRangesOffset
Definition: winternl.h:2490
USHORT DataSize
Definition: winternl.h:2487
UCHAR Data[1]
Definition: winternl.h:2494
USHORT MessageSize
Definition: winternl.h:2488
CLIENT_ID ClientId
Definition: winternl.h:2491
USHORT MessageType
Definition: winternl.h:2489
ULONG_PTR MessageId
Definition: winternl.h:2492
HANDLE LockSemaphore
Definition: winnt.h:6213
PVOID Ptr
Definition: winnt.h:6224
Definition: winnt.h:4369
BYTE SubAuthorityCount
Definition: winnt.h:4371
LARGE_INTEGER RemainingTime
Definition: winternl.h:1428
USHORT Length
Definition: ntsecapi.h:154
USHORT MaximumLength
Definition: ntsecapi.h:155
Definition: cookie.c:202
Definition: fci.c:123
Definition: token.c:125
Definition: ticket.c:73
Definition: msg.c:61
Definition: name.c:36
data_size_t name_len
Definition: wrctypes.h:93
Definition: ticket.c:41
static time_t time(time_t *t)
Definition: time.h:105
static int cancel_timer(struct timer *timer)
Definition: timer.c:148
static struct timer * create_timer(struct object *root, const struct unicode_str *name, unsigned int attr, int manual, const struct security_descriptor *sd)
Definition: timer.c:86
#define NULL
Definition: ungif.h:66
#define TRUE
Definition: ungif.h:59
#define FALSE
Definition: ungif.h:62
LONGLONG QuadPart
Definition: winnt.h:4948
obj_handle_t handles[64]
Definition: pdh_main.c:90
static ULONGLONG ticks_from_time_t(time_t time)
Definition: unix_private.h:256
BATCH_CONTEXT * context
Definition: wcmdmain.c:38
int sprintf(char *str, const char *format,...)
Definition: wcs.c:1532
YY_BUFFER_STATE state
Definition: parser.l:85
time_t now
Definition: widl.c:161
#define WAIT_OBJECT_0
Definition: winbase.h:1175
#define MAXINTATOM
Definition: winbase.h:495
#define LOWORD(l)
Definition: windef.h:362
#define CDECL
Definition: windef.h:198
unsigned char BYTE
Definition: windef.h:250
unsigned char UCHAR
Definition: windef.h:238
unsigned int DWORD
Definition: windef.h:261
unsigned short USHORT
Definition: windef.h:239
DWORD ACCESS_MASK
Definition: winnt.h:4351
#define JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS
Definition: winnt.h:6591
#define PAGE_WRITECOPY
Definition: winnt.h:771
#define PAGE_READONLY
Definition: winnt.h:769
#define FILE_WRITE_DATA
Definition: winnt.h:5502
BYTE BOOLEAN
Definition: winnt.h:453
#define FILE_READ_DATA
Definition: winnt.h:5500
#define JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS
Definition: winnt.h:6590
#define PAGE_READWRITE
Definition: winnt.h:770
#define PAGE_EXECUTE_READ
Definition: winnt.h:773
unsigned short WCHAR
Definition: winnt.h:468
#define PAGE_EXECUTE
Definition: winnt.h:772
enum _JOBOBJECTINFOCLASS JOBOBJECTINFOCLASS
#define SE_SELF_RELATIVE
Definition: winnt.h:4575
#define SEC_IMAGE
Definition: winnt.h:795
#define MAXIMUM_WAIT_OBJECTS
Definition: winnt.h:2665
PVOID PSID
Definition: winnt.h:4259
int LONG
Definition: winnt.h:459
#define SE_SACL_PRESENT
Definition: winnt.h:4566
#define SECURITY_DESCRIPTOR_REVISION
Definition: winnt.h:4424
@ JobObjectAssociateCompletionPortInformation
Definition: winnt.h:6492
@ JobObjectBasicLimitInformation
Definition: winnt.h:6487
@ JobObjectBasicAccountingInformation
Definition: winnt.h:6486
@ JobObjectExtendedLimitInformation
Definition: winnt.h:6494
@ JobObjectBasicUIRestrictions
Definition: winnt.h:6489
@ JobObjectBasicProcessIdList
Definition: winnt.h:6488
@ MaxJobObjectInfoClass
Definition: winnt.h:6496
struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION JOBOBJECT_EXTENDED_LIMIT_INFORMATION
#define PAGE_EXECUTE_WRITECOPY
Definition: winnt.h:775
unsigned long long ULONGLONG
Definition: winnt.h:485
signed long long LONGLONG
Definition: winnt.h:484
struct _JOBOBJECT_BASIC_LIMIT_INFORMATION JOBOBJECT_BASIC_LIMIT_INFORMATION
#define PAGE_NOACCESS
Definition: winnt.h:768
#define SE_DACL_PRESENT
Definition: winnt.h:4564
#define PAGE_EXECUTE_READWRITE
Definition: winnt.h:774
#define select
Definition: winsock.h:81
#define timeval
Definition: winsock.h:80
struct _SEMAPHORE_BASIC_INFORMATION SEMAPHORE_BASIC_INFORMATION
enum _IO_COMPLETION_INFORMATION_CLASS IO_COMPLETION_INFORMATION_CLASS
@ TimerBasicInformation
Definition: winternl.h:1423
struct _ATOM_BASIC_INFORMATION ATOM_BASIC_INFORMATION
struct _TIMER_BASIC_INFORMATION TIMER_BASIC_INFORMATION
void(* PTIMER_APC_ROUTINE)(PVOID, ULONG, LONG)
Definition: winternl.h:2408
enum _KPROFILE_SOURCE KPROFILE_SOURCE
enum _MUTANT_INFORMATION_CLASS MUTANT_INFORMATION_CLASS
unsigned short RTL_ATOM
Definition: winternl.h:2143
enum _ATOM_INFORMATION_CLASS ATOM_INFORMATION_CLASS
enum _EVENT_INFORMATION_CLASS EVENT_INFORMATION_CLASS
struct _EVENT_BASIC_INFORMATION EVENT_BASIC_INFORMATION
@ SemaphoreBasicInformation
Definition: winternl.h:2420
@ MutantBasicInformation
Definition: winternl.h:1412
@ EventBasicInformation
Definition: winternl.h:2411
enum _SEMAPHORE_INFORMATION_CLASS SEMAPHORE_INFORMATION_CLASS
enum _TIMER_INFORMATION_CLASS TIMER_INFORMATION_CLASS
@ IoCompletionBasicInformation
Definition: winternl.h:2575
struct _MUTANT_BASIC_INFORMATION MUTANT_BASIC_INFORMATION
@ AtomBasicInformation
Definition: winternl.h:2152