* fhandler.cc (fhandler_base::open): Fix typo in comment.

(fhandler_base::close): Move call to del_my_locks from here...
	* fhandler_disk_file.cc (fhandler_disk_file::open): ...to here.
	* flock.cc (struct lockfattr_t): New type.
	(lockf_t::close_lock_obj): New method, use throughout.
	(lockf_t::create_lock_obj_attr): New method.
	(lockf_t::create_lock_obj): Use create_lock_obj_attr method.  Handle
	STATUS_OBJECT_NAME_COLLISION in F_FLOCK case gracefully.  Add lengthy
	comments to explain why and how.
	(lockf_t::open_lock_obj): Use create_lock_obj_attr method.
	(lockf_t::del_lock_obj): Call NtSetEvent rather than SetEvent for
	symmetry.
	(fhandler_disk_file::lock): Define n only where it's used.  Call
	need_fork_fixup only if call was successful.  Handle EINTR and
	ECANCELED return values from lf_setlock.
	(lf_setlock): Drop WAIT_UNLOCKED and WAIT_PROC_EXITED.  Don't wait
	for event object handle count to become <= 1 in F_LOCK case.
	Simplify WFMO return value handling.  Don't handle signal and cancel
	events here; just return with appropriate error code instead.
	(lf_getblock): Ignore locks for which the handle can't be opened.
	Use IsEventSignalled.
	* ntdll.h (STATUS_INVALID_INFO_CLASS): Undef if defined elsewhere to
	make sure the definition is casted to NTSTATUS.
	(STATUS_INVALID_HANDLE): Define and ditto.
	(STATUS_OBJECT_NAME_COLLISION): Define.
	(NtSetEvent): Declare.
This commit is contained in:
Corinna Vinschen 2011-08-27 20:01:29 +00:00
parent 477215fe7d
commit f4ec874328
5 changed files with 165 additions and 98 deletions

View File

@ -1,3 +1,32 @@
2011-08-27 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base::open): Fix typo in comment.
(fhandler_base::close): Move call to del_my_locks from here...
* fhandler_disk_file.cc (fhandler_disk_file::open): ...to here.
* flock.cc (struct lockfattr_t): New type.
(lockf_t::close_lock_obj): New method, use throughout.
(lockf_t::create_lock_obj_attr): New method.
(lockf_t::create_lock_obj): Use create_lock_obj_attr method. Handle
STATUS_OBJECT_NAME_COLLISION in F_FLOCK case gracefully. Add lengthy
comments to explain why and how.
(lockf_t::open_lock_obj): Use create_lock_obj_attr method.
(lockf_t::del_lock_obj): Call NtSetEvent rather than SetEvent for
symmetry.
(fhandler_disk_file::lock): Define n only where it's used. Call
need_fork_fixup only if call was successful. Handle EINTR and
ECANCELED return values from lf_setlock.
(lf_setlock): Drop WAIT_UNLOCKED and WAIT_PROC_EXITED. Don't wait
for event object handle count to become <= 1 in F_LOCK case.
Simplify WFMO return value handling. Don't handle signal and cancel
events here; just return with appropriate error code instead.
(lf_getblock): Ignore locks for which the handle can't be opened.
Use IsEventSignalled.
* ntdll.h (STATUS_INVALID_INFO_CLASS): Undef if defined elsewhere to
make sure the definition is casted to NTSTATUS.
(STATUS_INVALID_HANDLE): Define and ditto.
(STATUS_OBJECT_NAME_COLLISION): Define.
(NtSetEvent): Declare.
2011-08-25 Rafal Zwierz <rzwierz@googlemail.com> 2011-08-25 Rafal Zwierz <rzwierz@googlemail.com>
* cygthread.cc (cygthread::simplestub): Notify that the thread has * cygthread.cc (cygthread::simplestub): Notify that the thread has

View File

@ -672,7 +672,7 @@ fhandler_base::open (int flags, mode_t mode)
status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi, status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi,
FileEndOfFileInformation); FileEndOfFileInformation);
/* In theory, truncating the file should never fail, since the opened /* In theory, truncating the file should never fail, since the opened
handle has FILE_READ_DATA permissions, which is all you need to handle has FILE_WRITE_DATA permissions, which is all you need to
be allowed to truncate a file. Better safe than sorry. */ be allowed to truncate a file. Better safe than sorry. */
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
@ -1130,10 +1130,6 @@ fhandler_base::close ()
int res = -1; int res = -1;
syscall_printf ("closing '%s' handle %p", get_name (), get_handle ()); syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
/* Delete all POSIX locks on the file. Delete all flock locks on the
file if this is the last reference to this file. */
if (unique_id)
del_my_locks (on_close);
if (nohandle () || CloseHandle (get_handle ())) if (nohandle () || CloseHandle (get_handle ()))
res = 0; res = 0;
else else

View File

@ -1380,8 +1380,12 @@ fhandler_disk_file::open (int flags, mode_t mode)
int int
fhandler_disk_file::close () fhandler_disk_file::close ()
{ {
/* Close extra pread/pwrite handle, if it exists. */
if (prw_handle) if (prw_handle)
NtClose (prw_handle); NtClose (prw_handle);
/* Delete all POSIX locks on the file. Delete all flock locks on the
file if this is the last reference to this file. */
del_my_locks (on_close);
return fhandler_base::close (); return fhandler_base::close ();
} }

View File

@ -106,6 +106,7 @@
#include "sigproc.h" #include "sigproc.h"
#include "cygtls.h" #include "cygtls.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include "miscfuncs.h"
#include "ntdll.h" #include "ntdll.h"
#include <sys/queue.h> #include <sys/queue.h>
#include <wchar.h> #include <wchar.h>
@ -212,21 +213,29 @@ get_obj_handle_count (HANDLE h)
return hdl_cnt; return hdl_cnt;
} }
/* Helper struct to construct a local OBJECT_ATTRIBUTES on the stack. */
struct lockfattr_t
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING uname;
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
};
/* Per lock class. */ /* Per lock class. */
class lockf_t class lockf_t
{ {
public: public:
short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */ short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */ short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
_off64_t lf_start; /* Byte # of the start of the lock */ _off64_t lf_start; /* Byte # of the start of the lock */
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */ _off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
long long lf_id; /* Cygwin PID for POSIX locks, a unique id per long long lf_id; /* Cygwin PID for POSIX locks, a unique id per
file table entry for BSD flock locks. */ file table entry for BSD flock locks. */
DWORD lf_wid; /* Win PID of the resource holding the lock */ DWORD lf_wid; /* Win PID of the resource holding the lock */
class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */ class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */
class inode_t *lf_inode; /* Back pointer to the inode_t */ class inode_t *lf_inode; /* Back pointer to the inode_t */
class lockf_t *lf_next; /* Pointer to the next lock on this inode_t */ class lockf_t *lf_next; /* Pointer to the next lock on this inode_t */
HANDLE lf_obj; /* Handle to the lock event object. */ HANDLE lf_obj; /* Handle to the lock event object. */
lockf_t () lockf_t ()
: lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0), : lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0),
@ -251,8 +260,12 @@ class lockf_t
void operator delete (void *p) void operator delete (void *p)
{ cfree (p); } { cfree (p); }
POBJECT_ATTRIBUTES create_lock_obj_attr (lockfattr_t *attr,
ULONG flags);
void create_lock_obj (); void create_lock_obj ();
bool open_lock_obj (); bool open_lock_obj ();
void close_lock_obj () { NtClose (lf_obj); lf_obj = NULL; }
void del_lock_obj (HANDLE fhdl, bool signal = false); void del_lock_obj (HANDLE fhdl, bool signal = false);
}; };
@ -542,47 +555,72 @@ inode_t::get_all_locks_list ()
return i_all_lf; return i_all_lf;
} }
/* Create the lock object name. The name is constructed from the lock
properties which identify it uniquely, all values in hex. */
POBJECT_ATTRIBUTES
lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
{
__small_swprintf (attr->name, L"%02x-%01x-%016X-%016X-%016X-%08x",
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, lf_end,
lf_id, lf_wid);
RtlInitCountedUnicodeString (&attr->uname, attr->name,
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
InitializeObjectAttributes (&attr->attr, &attr->uname, flags, lf_inode->i_dir,
everyone_sd (FLOCK_EVENT_ACCESS));
return &attr->attr;
}
/* Create the lock event object in the file's subdir in the NT global /* Create the lock event object in the file's subdir in the NT global
namespace. The name is constructed from the lock properties which namespace. */
identify it uniquely, all values in hex. See the __small_swprintf
call right at the start. */
void void
lockf_t::create_lock_obj () lockf_t::create_lock_obj ()
{ {
WCHAR name[LOCK_OBJ_NAME_LEN + 1]; lockfattr_t attr;
UNICODE_STRING uname;
OBJECT_ATTRIBUTES attr;
NTSTATUS status; NTSTATUS status;
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x", do
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, {
lf_end, lf_id, lf_wid); status = NtCreateEvent (&lf_obj, CYG_EVENT_ACCESS,
RtlInitCountedUnicodeString (&uname, name, create_lock_obj_attr (&attr, OBJ_INHERIT),
LOCK_OBJ_NAME_LEN * sizeof (WCHAR)); NotificationEvent, FALSE);
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, lf_inode->i_dir, if (!NT_SUCCESS (status))
everyone_sd (FLOCK_EVENT_ACCESS)); {
status = NtCreateEvent (&lf_obj, CYG_EVENT_ACCESS, &attr, if (status != STATUS_OBJECT_NAME_COLLISION || (lf_flags & F_POSIX))
NotificationEvent, FALSE); api_fatal ("NtCreateEvent(lock): %p", status);
if (!NT_SUCCESS (status)) /* If we get a STATUS_OBJECT_NAME_COLLISION in the F_FLOCK case, the
api_fatal ("NtCreateEvent(lock): %p", status); event still exists because some other process is waiting for it
in lf_setlock. If so, open the event and check the signal state.
If we can't open it, it has been closed in the meantime, so just
try again. If we can open it and the object is not signalled,
it's surely a bug in the code somewhere. Otherwise, close the
event and retry to create an event with another name. */
if (open_lock_obj ())
{
if (!IsEventSignalled (lf_obj))
api_fatal ("NtCreateEvent(lock): %p", status);
close_lock_obj ();
/* Change the lf_wid member to generate another name for the
event, so as not to colide with the still-in-use event.
Changing lf_wid is ok, because the Windows PID is not used
for synchronization in the F_FLOCK case.
What we do here is to increment the highest byte in lf_wid. */
lf_wid = ((lf_wid & 0xff000000) + (1 << 24))
| (lf_wid & 0xffffff);
}
}
}
while (!NT_SUCCESS (status));
} }
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */ /* Open a lock event object for SYNCHRONIZE access (to wait for it). */
bool bool
lockf_t::open_lock_obj () lockf_t::open_lock_obj ()
{ {
WCHAR name[LOCK_OBJ_NAME_LEN + 1]; lockfattr_t attr;
UNICODE_STRING uname;
OBJECT_ATTRIBUTES attr;
NTSTATUS status; NTSTATUS status;
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x", status = NtOpenEvent (&lf_obj, FLOCK_EVENT_ACCESS,
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, create_lock_obj_attr (&attr, 0));
lf_end, lf_id, lf_wid);
RtlInitCountedUnicodeString (&uname, name,
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
InitializeObjectAttributes (&attr, &uname, 0, lf_inode->i_dir, NULL);
status = NtOpenEvent (&lf_obj, FLOCK_EVENT_ACCESS, &attr);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
SetLastError (RtlNtStatusToDosError (status)); SetLastError (RtlNtStatusToDosError (status));
@ -591,9 +629,9 @@ lockf_t::open_lock_obj ()
return lf_obj != NULL; return lf_obj != NULL;
} }
/* Close a lock event handle. The important thing here is to signal it /* Delete a lock event handle. The important thing here is to signal it
before closing the handle. This way all threads waiting for this before closing the handle. This way all threads waiting for this lock
lock can wake up. */ can wake up. */
void void
lockf_t::del_lock_obj (HANDLE fhdl, bool signal) lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
{ {
@ -608,9 +646,8 @@ lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
handle/descriptor to the same FILE_OBJECT/file table entry. */ handle/descriptor to the same FILE_OBJECT/file table entry. */
if ((lf_flags & F_POSIX) || signal if ((lf_flags & F_POSIX) || signal
|| (fhdl && get_obj_handle_count (fhdl) <= 1)) || (fhdl && get_obj_handle_count (fhdl) <= 1))
SetEvent (lf_obj); NtSetEvent (lf_obj, NULL);
NtClose (lf_obj); close_lock_obj ();
lf_obj = NULL;
} }
} }
@ -643,7 +680,6 @@ int
fhandler_disk_file::lock (int a_op, struct __flock64 *fl) fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
{ {
_off64_t start, end, oadd; _off64_t start, end, oadd;
lockf_t *n;
int error = 0; int error = 0;
short a_flags = fl->l_type & (F_POSIX | F_FLOCK); short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
@ -758,13 +794,14 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
end = start + oadd; end = start + oadd;
} }
restart: /* Entry point after a restartable signal came in. */
inode_t *node = inode_t::get (get_dev (), get_ino (), true); inode_t *node = inode_t::get (get_dev (), get_ino (), true);
if (!node) if (!node)
{ {
set_errno (ENOLCK); set_errno (ENOLCK);
return -1; return -1;
} }
need_fork_fixup (true);
/* Unlock the fd table which has been locked in fcntl_worker/lock_worker, /* Unlock the fd table which has been locked in fcntl_worker/lock_worker,
otherwise a blocking F_SETLKW never wakes up on a signal. */ otherwise a blocking F_SETLKW never wakes up on a signal. */
@ -844,7 +881,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
} }
for (lock = clean; lock != NULL; ) for (lock = clean; lock != NULL; )
{ {
n = lock->lf_next; lockf_t *n = lock->lf_next;
lock->del_lock_obj (get_handle (), a_op == F_UNLCK); lock->del_lock_obj (get_handle (), a_op == F_UNLCK);
delete lock; delete lock;
lock = n; lock = n;
@ -859,12 +896,23 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
} }
else else
node->UNLOCK (); node->UNLOCK ();
if (error) switch (error)
{ {
set_errno (error); case 0: /* All is well. */
return -1; need_fork_fixup (true);
return 0;
case EINTR: /* Signal came in. */
if (_my_tls.call_signal_handler ())
goto restart;
break;
case ECANCELED: /* The thread has been sent a cancellation request. */
pthread::static_cancel_self ();
/*NOTREACHED*/
default:
break;
} }
return 0; set_errno (error);
return -1;
} }
/* /*
@ -961,10 +1009,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
HANDLE cancel_event = pthread::get_cancel_event (); HANDLE cancel_event = pthread::get_cancel_event ();
int wait_count = 0; int wait_count = 0;
/* The lock is always the first object. */ /* The lock event is always the first object, all other wait objects
const DWORD WAIT_UNLOCKED = WAIT_OBJECT_0; are variable. */
/* All other wait objects are variable. */
DWORD WAIT_PROC_EXITED = WAIT_TIMEOUT + 1;
DWORD WAIT_SIGNAL_ARRIVED = WAIT_TIMEOUT + 1; DWORD WAIT_SIGNAL_ARRIVED = WAIT_TIMEOUT + 1;
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1; DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
@ -985,7 +1031,6 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
HANDLE w4[4] = { obj, proc, signal_arrived, cancel_event }; HANDLE w4[4] = { obj, proc, signal_arrived, cancel_event };
wait_count = 3; wait_count = 3;
WAIT_PROC_EXITED = WAIT_OBJECT_0 + 1;
WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 2; WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 2;
if (cancel_event) if (cancel_event)
{ {
@ -1012,45 +1057,34 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
node->UNLOCK (); node->UNLOCK ();
/* Unfortunately, since BSD flock locks are not attached to a /* Unfortunately, since BSD flock locks are not attached to a
specific process, we can't recognize an abandoned lock by specific process, we can't recognize an abandoned lock by
sync'ing with a process. We have to find out if we're the only sync'ing with a process. We have to make sure we're the only
process left accessing this event object. */ process left accessing this event object, or that the event
do object is in a signalled state. */
{ ret = WaitForMultipleObjects (wait_count, w4, FALSE, 100L);
ret = WaitForMultipleObjects (wait_count, w4, FALSE, 100L);
}
while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1);
/* There's a good chance that the above loop is left with
ret == WAIT_TIMEOUT if another process closes the file handle
associated with this lock. This is for all practical purposes
equivalent to a signalled lock object. */
if (ret == WAIT_TIMEOUT)
ret = WAIT_OBJECT_0;
} }
node->LOCK (); node->LOCK ();
node->unwait (); node->unwait ();
NtClose (obj); NtClose (obj);
SetThreadPriority (GetCurrentThread (), old_prio); SetThreadPriority (GetCurrentThread (), old_prio);
if (ret == WAIT_UNLOCKED) if (ret == WAIT_SIGNAL_ARRIVED)
; /* The lock object has been set to signalled. */
else if (ret == WAIT_PROC_EXITED)
; /* For POSIX locks, the process holding the lock has exited. */
else if (ret == WAIT_SIGNAL_ARRIVED)
{ {
/* A signal came in. */ /* A signal came in. */
if (!_my_tls.call_signal_handler ()) lock->lf_next = *clean;
return EINTR; *clean = lock;
return EINTR;
} }
else if (ret == WAIT_THREAD_CANCELED) else if (ret == WAIT_THREAD_CANCELED)
{ {
/* The thread has been sent a cancellation request. */ /* The thread has been sent a cancellation request. */
pthread::static_cancel_self (); lock->lf_next = *clean;
*clean = lock;
return ECANCELED;
} }
else else
{ /* The lock object has been set to signalled or ...
system_printf ("Shouldn't happen! ret = %lu, error: %lu\n", for POSIX locks, the process holding the lock has exited, or ...
ret, GetLastError ()); Just a timeout. Just retry. */
return geterrno_from_win_error (); continue;
}
} }
allow_others_to_sync (); allow_others_to_sync ();
/* /*
@ -1268,7 +1302,7 @@ lf_getlock (lockf_t *lock, inode_t *node, struct __flock64 *fl)
if ((block = lf_getblock (lock, node))) if ((block = lf_getblock (lock, node)))
{ {
if (block->lf_obj) if (block->lf_obj)
NtClose (block->lf_obj); block->close_lock_obj ();
fl->l_type = block->lf_type; fl->l_type = block->lf_type;
fl->l_whence = SEEK_SET; fl->l_whence = SEEK_SET;
fl->l_start = block->lf_start; fl->l_start = block->lf_start;
@ -1296,8 +1330,6 @@ lf_getblock (lockf_t *lock, inode_t *node)
lockf_t **prev, *overlap; lockf_t **prev, *overlap;
lockf_t *lf = node->get_all_locks_list (); lockf_t *lf = node->get_all_locks_list ();
int ovcase; int ovcase;
NTSTATUS status;
EVENT_BASIC_INFORMATION ebi;
prev = lock->lf_head; prev = lock->lf_head;
while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap))) while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap)))
@ -1308,17 +1340,18 @@ lf_getblock (lockf_t *lock, inode_t *node)
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
{ {
/* Open the event object for synchronization. */ /* Open the event object for synchronization. */
if (!overlap->open_lock_obj () || (overlap->lf_flags & F_POSIX)) if (overlap->open_lock_obj ())
return overlap; {
/* In case of BSD flock locks, check if the event object is /* If we found a POSIX lock, it will block us. */
signalled. If so, the overlap doesn't actually exist anymore. if (overlap->lf_flags & F_POSIX)
There are just a few open handles left. */ return overlap;
status = NtQueryEvent (overlap->lf_obj, EventBasicInformation, /* In case of BSD flock locks, check if the event object is
&ebi, sizeof ebi, NULL); signalled. If so, the overlap doesn't actually exist anymore.
if (!NT_SUCCESS (status) || ebi.SignalState == 0) There are just a few open handles left. */
return overlap; if (!IsEventSignalled (overlap->lf_obj))
NtClose (overlap->lf_obj); return overlap;
overlap->lf_obj = NULL; overlap->close_lock_obj ();
}
} }
/* /*
* Nope, point to the next one on the list and * Nope, point to the next one on the list and

View File

@ -15,13 +15,16 @@
#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000) #define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005) #define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006) #define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
#ifndef STATUS_INVALID_INFO_CLASS #ifdef STATUS_INVALID_INFO_CLASS /* Defined as unsigned value in subauth.h */
/* Some w32api header file defines this so we need to conditionalize this #undef STATUS_INVALID_INFO_CLASS
define to avoid warnings. */
#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
#endif #endif
#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xc0000002) #define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xc0000002)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#ifdef STATUS_INVALID_HANDLE /* Defined as unsigned value in winbase.h */
#undef STATUS_INVALID_HANDLE
#endif
#define STATUS_INVALID_HANDLE ((NTSTATUS) 0xc0000008)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d) #define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
#define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f) #define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010) #define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
@ -32,6 +35,7 @@
#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xc0000024) #define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xc0000024)
#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xc0000033) #define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xc0000033)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xc0000035)
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A) #define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043) #define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xc000004f) #define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xc000004f)
@ -1210,6 +1214,7 @@ extern "C"
PULONG); PULONG);
NTSTATUS NTAPI NtRollbackTransaction (HANDLE, BOOLEAN); NTSTATUS NTAPI NtRollbackTransaction (HANDLE, BOOLEAN);
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG); NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
NTSTATUS NTAPI NtSetEvent (HANDLE, PULONG);
NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
FILE_INFORMATION_CLASS); FILE_INFORMATION_CLASS);
NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREAD_INFORMATION_CLASS, NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREAD_INFORMATION_CLASS,