diff --git a/dlls/ntdll/error.c b/dlls/ntdll/error.c index 919863efcf7..1e072cfc35f 100644 --- a/dlls/ntdll/error.c +++ b/dlls/ntdll/error.c @@ -97,10 +97,20 @@ ULONG WINAPI RtlNtStatusToDosErrorNoTeb( NTSTATUS status ) */ ULONG WINAPI RtlNtStatusToDosError( NTSTATUS status ) { - /* FIXME: This function obviously does something with the Teb */ + NtCurrentTeb()->LastStatusValue = status; return RtlNtStatusToDosErrorNoTeb( status ); } +/********************************************************************** + * RtlGetLastNtStatus (NTDLL.@) + * + * Get the current per-thread status. + */ +NTSTATUS WINAPI RtlGetLastNtStatus(void) +{ + return NtCurrentTeb()->LastStatusValue; +} + /********************************************************************** * RtlGetLastWin32Error (NTDLL.@) * @@ -131,6 +141,19 @@ void WINAPI RtlSetLastWin32Error( DWORD err ) NtCurrentTeb()->LastErrorValue = err; } +/*********************************************************************** + * RtlSetLastWin32ErrorAndNtStatusFromNtStatus (NTDLL.@) + * + * Set the per-thread status and error values. + * + * PARAMS + * err [I] The new status value to set + */ +void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus( NTSTATUS status ) +{ + NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError( status ); +} + /* conversion tables */ static const DWORD table_00000102[32] = diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 7950c3e52d9..1d6b9c9b660 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -132,12 +132,6 @@ static HEAP *firstHeap; /* head of secondary heaps list */ static BOOL HEAP_IsRealArena( HEAP *heapPtr, DWORD flags, LPCVOID block, BOOL quiet ); -/* SetLastError for ntdll */ -inline static void set_status( NTSTATUS status ) -{ - NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError( status ); -} - /* mark a block of memory as free for debugging purposes */ static inline void mark_block_free( void *ptr, size_t size ) { @@ -1179,7 +1173,7 @@ BOOLEAN WINAPI RtlFreeHeap( HANDLE heap, ULONG flags, PVOID ptr ) if (!ptr) return TRUE; /* freeing a NULL ptr isn't an error in Win2k */ if (!heapPtr) { - set_status( STATUS_INVALID_HANDLE ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); return FALSE; } @@ -1189,7 +1183,7 @@ BOOLEAN WINAPI RtlFreeHeap( HANDLE heap, ULONG flags, PVOID ptr ) if (!HEAP_IsRealArena( heapPtr, HEAP_NO_SERIALIZE, ptr, QUIET )) { if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); - set_status( STATUS_INVALID_PARAMETER ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); TRACE("(%p,%08lx,%08lx): returning FALSE\n", heap, flags, (DWORD)ptr ); return FALSE; @@ -1234,7 +1228,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size if (!ptr) return NULL; if (!(heapPtr = HEAP_GetPtr( heap ))) { - set_status( STATUS_INVALID_HANDLE ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); return NULL; } @@ -1250,7 +1244,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size if (!HEAP_IsRealArena( heapPtr, HEAP_NO_SERIALIZE, ptr, QUIET )) { if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); - set_status( STATUS_INVALID_PARAMETER ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); TRACE("(%p,%08lx,%08lx,%08lx): returning NULL\n", heap, flags, (DWORD)ptr, size ); return NULL; @@ -1278,7 +1272,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size { if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); - set_status( STATUS_NO_MEMORY ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY ); return NULL; } HEAP_ShrinkBlock( subheap, pArena, size ); @@ -1294,7 +1288,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size { if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); - set_status( STATUS_NO_MEMORY ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY ); return NULL; } @@ -1429,7 +1423,7 @@ ULONG WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, PVOID ptr ) if (!heapPtr) { - set_status( STATUS_INVALID_HANDLE ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); return (ULONG)-1; } flags &= HEAP_NO_SERIALIZE; @@ -1437,7 +1431,7 @@ ULONG WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, PVOID ptr ) if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); if (!HEAP_IsRealArena( heapPtr, HEAP_NO_SERIALIZE, ptr, QUIET )) { - set_status( STATUS_INVALID_PARAMETER ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); ret = (ULONG)-1; } else diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index aab4c3e6e94..692d7e4e45d 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -450,6 +450,7 @@ @ stub RtlGetElementGenericTable @ stdcall RtlGetFullPathName_U(wstr long ptr ptr) @ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr) +@ stdcall RtlGetLastNtStatus() @ stdcall RtlGetLastWin32Error() @ stdcall RtlGetLongestNtPathLength() @ stub RtlGetNtGlobalFlags @@ -579,6 +580,7 @@ @ stdcall RtlSetEnvironmentVariable(ptr ptr ptr) @ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long) @ stub RtlSetInformationAcl +@ stdcall RtlSetLastWin32ErrorAndNtStatusFromNtStatus(long) @ stdcall RtlSetLastWin32Error(long) @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long) @ stdcall RtlSetSaclSecurityDescriptor(ptr long ptr long) diff --git a/include/thread.h b/include/thread.h index 210a96c1d5a..ed0bc815893 100644 --- a/include/thread.h +++ b/include/thread.h @@ -120,7 +120,8 @@ typedef struct _TEB /* here is plenty space for wine specific fields (don't forget to change pad6!!) */ /* the following are nt specific fields */ - DWORD pad6[624]; /* --n 238 */ + DWORD pad6[623]; /* --n 238 */ + ULONG LastStatusValue; /* -2- bf4 */ UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */ WCHAR StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */ PVOID DeallocationStack; /* -2- e0c Base of the stack */ diff --git a/include/winternl.h b/include/winternl.h index a00df1241b7..16e18a8b939 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -225,7 +225,8 @@ typedef struct _TEB BYTE __pad038[140]; /* 038 */ ULONG CurrentLocale; /* 0c4 */ BYTE __pad0c8[1752]; /* 0c8 */ - PVOID Reserved2[278]; /* 7a0 */ + PVOID Reserved2[277]; /* 7a0 */ + ULONG LastStatusValue; /* bf4 */ UNICODE_STRING StaticUnicodeString; /* bf8 used by advapi32 */ WCHAR StaticUnicodeBuffer[261]; /* c00 used by advapi32 */ PVOID DeallocationStack; /* e0c */ @@ -1573,6 +1574,7 @@ NTSTATUS WINAPI RtlGetCurrentDirectory_U(ULONG, LPWSTR); NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR,PBOOLEAN,PACL *,PBOOLEAN); ULONG WINAPI RtlGetFullPathName_U(PCWSTR,ULONG,PWSTR,PWSTR*); NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID *,PBOOLEAN); +NTSTATUS WINAPI RtlGetLastNtStatus(void); DWORD WINAPI RtlGetLastWin32Error(void); DWORD WINAPI RtlGetLongestNtPathLength(void); BOOLEAN WINAPI RtlGetNtProductType(LPDWORD); @@ -1669,6 +1671,7 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR*,PUNICODE_STRING,PUNICODE_STRIN NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN); NTSTATUS WINAPI RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN); void WINAPI RtlSetLastWin32Error(DWORD); +void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS); NTSTATUS WINAPI RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN); NTSTATUS WINAPI RtlSetTimeZoneInformation(const TIME_ZONE_INFORMATION*); ULONG WINAPI RtlSizeHeap(HANDLE,ULONG,PVOID);