[RTL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 6 Jan 2010 00:39:07 +0000 (00:39 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 6 Jan 2010 00:39:07 +0000 (00:39 +0000)
Merge from amd64 branch
35738,37004,37308,37324,37330,37331,37332,37370,37419,37424,37425,37428,37473,37492,37844,37911,37987,40604,41006,43686,43951,43953,43980,43993,44001,44289,44295,44296,44428,44966,44967,44968

- Implement amd64 specific RTL functions: RtlLookupFunctionTable, RtlLookupFunctionEntry, RtlCaptureContext, RtlVirtualUnwind, RtlWalkFrameChain, RtlGetCallersAddress, RtlRaiseException (Timo Kreuzer)
- Implement amd64 asm functions: RtlCompareMemory, DebugService, RtlInterlockedPopEntrySList, RtlInterlockedPushEntrySList and RtlInterlockedFlushSList (Timo Kreuzer)
- Don't use double in rtl's sprintf / swprintf, use double_t union instead. (Stefan Ginsberg)

svn path=/trunk/; revision=44970

12 files changed:
reactos/lib/rtl/amd64/debug_asm.S [new file with mode: 0644]
reactos/lib/rtl/amd64/except_asm.S [new file with mode: 0644]
reactos/lib/rtl/amd64/rtlmem.S [new file with mode: 0644]
reactos/lib/rtl/amd64/slist.S [new file with mode: 0644]
reactos/lib/rtl/amd64/stubs.c [new file with mode: 0644]
reactos/lib/rtl/amd64/unwind.c [new file with mode: 0644]
reactos/lib/rtl/exception.c
reactos/lib/rtl/rtl.rbuild
reactos/lib/rtl/rtlp.h
reactos/lib/rtl/slist.c
reactos/lib/rtl/sprintf.c
reactos/lib/rtl/swprintf.c

diff --git a/reactos/lib/rtl/amd64/debug_asm.S b/reactos/lib/rtl/amd64/debug_asm.S
new file mode 100644 (file)
index 0000000..82c9647
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * COPYRIGHT:         See COPYING in the top level directory
+ * PROJECT:           ReactOS Run-Time Library
+ * PURPOSE:           Debug Routines
+ * FILE:              lib/rtl/i386/debug.S
+ * PROGRAMER:         Alex Ionescu (alex@relsoft.net)
+ */
+
+.intel_syntax noprefix
+
+/* GLOBALS ****************************************************************/
+
+.globl _DbgBreakPoint
+.globl _DbgBreakPointWithStatus
+.globl _DbgUserBreakPoint
+.globl _DebugService
+.globl _DebugService2
+.globl _DbgBreakPointNoBugCheck
+.globl _RtlpBreakWithStatusInstruction
+
+/* FUNCTIONS ***************************************************************/
+
+.func DbgBreakPointNoBugCheck
+_DbgBreakPointNoBugCheck:
+    int 3
+    ret
+.endfunc
+
+.func DbgBreakPoint
+_DbgBreakPoint:
+_DbgUserBreakPoint:
+    int 3
+    ret
+.endfunc
+
+.func DbgBreakPointWithStatus
+_DbgBreakPointWithStatus:
+    mov eax, ecx
+
+_RtlpBreakWithStatusInstruction:
+    int 3
+    ret
+.endfunc
+
+.func DebugService2
+_DebugService2:
+    ret
+    /* Call the interrupt */
+//    mov eax, [rbp+8]
+//    int 0x2D
+//    int 3
+
+.endfunc
+
+/******************************************************************************
+ * NTSTATUS NTAPI DebugService(
+ *     IN ULONG Service,    // <rcx> = [rsp + 8]
+ *     IN PVOID Buffer,     // <rdx> = [rsp + 16]
+ *     IN ULONG Length,     // <r8>  = [rsp + 24]
+ *     IN PVOID Argument1,  // <r9>  = [rsp + 32]
+ *     IN PVOID Argument2); //         [rsp + 40]
+ */
+.func DebugService
+_DebugService:
+
+    /* Prepare registers for interrupt */
+    mov eax, ecx       // Service
+    mov rcx, rdx       // Buffer
+    mov edx, r8d       // Length
+    mov r8, r9         // Argument1
+    mov r9, [rsp + 40] // Argument2
+
+    /* Call the Interrupt */
+    int 0x2D
+    int 3
+
+   /* Return */
+    ret
+.endfunc
diff --git a/reactos/lib/rtl/amd64/except_asm.S b/reactos/lib/rtl/amd64/except_asm.S
new file mode 100644 (file)
index 0000000..2937335
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Runtime Library (RTL)
+ * FILE:            lib/rtl/amd64/except_asm.S
+ * PURPOSE:         Exception support for AMD64
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ndk/asm.h>
+.intel_syntax noprefix
+
+/* FUNCTIONS *****************************************************************/
+
+/* 
+ * VOID NTAPI
+ * RtlCaptureContext(
+ *     PCONTEXT ContextRecord); <rcx>
+ */
+.func RtlCaptureContext
+.global _RtlCaptureContext
+_RtlCaptureContext:
+    .cfi_startproc
+
+    /* Push rflags */
+    pushfq
+    .cfi_adjust_cfa_offset 8
+
+    /* Save the basic register context */
+    mov [rcx + CONTEXT_Rax], rax
+    mov [rcx + CONTEXT_Rcx], rcx
+    mov [rcx + CONTEXT_Rdx], rdx
+
+    /* Load rflags into rax */
+    mov rax, [rsp]
+
+    mov [rcx + CONTEXT_Rbx], rbx
+    mov [rcx + CONTEXT_Rsi], rsi
+    mov [rcx + CONTEXT_Rdi], rdi
+
+    /* Store rflags */
+    mov [rcx + CONTEXT_EFlags], rax
+
+    mov [rcx + CONTEXT_Rbp], rbp
+    mov [rcx + CONTEXT_R8], r8
+    mov [rcx + CONTEXT_R9], r9
+
+    /* Load former stack pointer in rax */
+    lea rax, [rsp + 0x10]
+
+    mov [rcx + CONTEXT_R10], r10
+    mov [rcx + CONTEXT_R11], r11
+    mov [rcx + CONTEXT_R12], r12
+
+    /* Store stack pointer */
+    mov [rcx + CONTEXT_Rsp], rax
+
+    mov [rcx + CONTEXT_R13], r13
+    mov [rcx + CONTEXT_R14], r14
+    mov [rcx + CONTEXT_R15], r15
+
+    /* Load return address in rax */
+    mov rax, [rsp + 8]
+
+    /* Safe segment selectors */
+    mov [rcx + CONTEXT_SegCs], cs
+    mov [rcx + CONTEXT_SegDs], ds
+    mov [rcx + CONTEXT_SegEs], es
+    mov [rcx + CONTEXT_SegFs], fs
+    mov [rcx + CONTEXT_SegGs], gs
+    mov [rcx + CONTEXT_SegSs], ss
+
+    /* Store return address */
+    mov [rcx + CONTEXT_Rip], rax
+
+    /* Safe xmm registers */
+    movdqa [rcx + CONTEXT_Xmm0], xmm0
+    movdqa [rcx + CONTEXT_Xmm1], xmm1
+    movdqa [rcx + CONTEXT_Xmm2], xmm2
+    movdqa [rcx + CONTEXT_Xmm3], xmm3
+    movdqa [rcx + CONTEXT_Xmm4], xmm4
+    movdqa [rcx + CONTEXT_Xmm5], xmm5
+    movdqa [rcx + CONTEXT_Xmm6], xmm6
+    movdqa [rcx + CONTEXT_Xmm7], xmm7
+    movdqa [rcx + CONTEXT_Xmm8], xmm8
+    movdqa [rcx + CONTEXT_Xmm9], xmm9
+    movdqa [rcx + CONTEXT_Xmm10], xmm10
+    movdqa [rcx + CONTEXT_Xmm11], xmm11
+    movdqa [rcx + CONTEXT_Xmm12], xmm12
+    movdqa [rcx + CONTEXT_Xmm13], xmm13
+    movdqa [rcx + CONTEXT_Xmm14], xmm14
+    movdqa [rcx + CONTEXT_Xmm15], xmm15
+
+    /* Cleanup stack and return */
+    add rsp, 8
+    ret
+    .cfi_endproc
+.endfunc
+
diff --git a/reactos/lib/rtl/amd64/rtlmem.S b/reactos/lib/rtl/amd64/rtlmem.S
new file mode 100644 (file)
index 0000000..8115473
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * COPYRIGHT:         See COPYING in the top level directory
+ * PROJECT:           ReactOS Run-Time Library
+ * PURPOSE:           Memory functions for amd64
+ * FILE:              lib/rtl/i386/rtlswap.S
+ * PROGRAMER:         Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ndk/amd64/asmmacro.S>
+
+/* FUNCTIONS *****************************************************************/
+.intel_syntax noprefix
+
+/* SIZE_T 
+ * RtlCompareMemory(
+ *   IN CONST VOID *Source1, <rcx>
+ *   IN CONST VOID *Source2, <rdx>
+ *   IN SIZE_T  Length <r8>
+ * );
+ */
+.proc RtlCompareMemory
+
+    /* Save registers */
+    push rsi
+    .pushreg rsi
+    push rdi
+    .pushreg rdi
+
+    /* Setup registers for compare */
+    mov rsi, rcx
+    mov rdi, rdx
+
+    /* Clear direction flag */
+    cli
+
+    /* Get number of qwords */
+    mov rcx, r8
+    shr rcx, 3
+    jz 2f
+
+    /* Compare qwords */
+    repe cmpsq
+    jnz 4f
+
+2:  /* Compare rest */
+    mov rcx, r8
+    and rcx, 7
+    jz 3f
+
+    repe cmpsb
+    jnz 5f
+
+3:  /* All equal */
+    /* Return the full count */
+    mov rax, rcx
+    jmp 6f
+
+4:  /* Not equal after comparing qwords */
+    /* Compare the last qword */
+    sub rsi, 8
+    sub rdi, 8
+    mov rcx, 8
+    repe cmpsb
+
+5:  /* Not equal after comparing bytes */
+    /* Return difference */
+    sub rdi, rdx
+    dec rdi
+    mov rax, rdi
+
+6:  /* Cleanup and return */
+    pop rdi
+    pop rsi
+    ret
+.endproc
+
diff --git a/reactos/lib/rtl/amd64/slist.S b/reactos/lib/rtl/amd64/slist.S
new file mode 100644 (file)
index 0000000..3488fb5
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/rtl/amd64/interlck.S
+ * PURPOSE:         Rtl Interlocked Functions for amd64
+ * PROGRAMMERS:     Timo Kreuzer
+ */
+
+#include <ndk/asm.h>
+#include <ndk/amd64/asmmacro.S>
+.intel_syntax noprefix
+
+#define SLIST8A_DEPTH_MASK       0x000000000000FFFF
+#define SLIST8A_DEPTH_INC        0x0000000000000001
+#define SLIST8A_SEQUENCE_MASK    0x0000000001FF0000
+#define SLIST8A_SEQUENCE_INC     0x0000000000010000
+#define SLIST8A_NEXTENTRY_MASK   0xFFFFFFFFFE000000
+#define SLIST8A_NEXTENTRY_SHIFT  21
+#define SLIST8B_HEADERTYPE_MASK  0x0000000000000001
+#define SLIST8B_INIT_MASK        0x0000000000000002
+#define SLIST8B_REGION_MASK      0xE000000000000000
+#define SLIST8_POINTER_MASK      0x000007FFFFFFFFF0
+
+#define SLIST16A_DEPTH_MASK      0x000000000000FFFF
+#define SLIST16A_DEPTH_INC       0x0000000000000001
+#define SLIST16A_SEQUENCE_MASK   0xFFFFFFFFFFFF0000
+#define SLIST16A_SEQUENCE_INC    0x0000000000010000
+#define SLIST16B_HEADERTYPE_MASK 0x0000000000000001
+#define SLIST16B_INIT_MASK       0x0000000000000002
+#define SLIST16B_NEXTENTY_MASK   0xFFFFFFFFFFFFFFF0
+
+
+/* FUNCTIONS ****************************************************************/
+
+.global _ExpInterlockedPopEntrySList
+.global _ExpInterlockedPopEntrySListResume
+.global _ExpInterlockedPopEntrySListFault
+.global _ExpInterlockedPopEntrySListEnd
+.global _ExpInterlockedPopEntrySListResume16
+.global _ExpInterlockedPopEntrySListFault16
+.global _ExpInterlockedPopEntrySListEnd16
+.global _ExpInterlockedPushEntrySList
+.global _ExpInterlockedFlushSList
+
+/* PSLIST_ENTRY
+ * NTAPI
+ * RtlInterlockedPopEntrySList(
+ *     IN PSLIST_HEADER ListHead);
+ */
+.proc RtlInterlockedPopEntrySList
+_ExpInterlockedPopEntrySList:
+
+    /* Load ListHead->Region into rdx */
+    mov rdx, [rcx + 8]
+
+    /* Load ListHead->Alignment into rax */
+    mov rax, [rcx]
+
+    /* Check what kind of header this is */
+    test rdx, SLIST8B_HEADERTYPE_MASK
+    jnz _RtlInterlockedPopEntrySList16
+
+    /* We have an 8 byte header */
+
+_ExpInterlockedPopEntrySListResume:
+
+    /* Check if ListHead->NextEntry is NULL */
+    mov r9, rax
+    and r9, SLIST8A_NEXTENTRY_MASK
+    jz _RtlInterlockedPopEntrySListEmpty
+
+    /* Copy Depth and Sequence number and adjust Depth */
+    lea r8, [rax - SLIST8A_DEPTH_INC]
+    and r8, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK
+
+    /* Create a pointer template from rcx in rdx */
+    mov rdx, ~SLIST8_POINTER_MASK
+    and rdx, rcx
+
+    /* Shift the NextEntry pointer */
+    shr r9, SLIST8A_NEXTENTRY_SHIFT
+
+    /* Combine to new pointer in rdx */
+    or rdx, r9
+
+_ExpInterlockedPopEntrySListFault:
+
+    /* Load the next NextEntry pointer to r9 */
+    mov r9, [rdx]
+
+    /* Shift bits in place */
+    shl r9, SLIST8A_NEXTENTRY_SHIFT
+
+    /* Combine into r8 */
+    or r8, r9
+
+_ExpInterlockedPopEntrySListEnd:
+
+    /* If [rcx] equals rax, exchange it with r8 */
+    lock cmpxchg [rcx], r8
+
+    /* If not equal, retry with rax, being the content of [rcx] now */
+    jnz _ExpInterlockedPopEntrySListResume
+
+    /* Shift the pointer bits in place */
+    and rax, SLIST8A_NEXTENTRY_MASK
+    shr rax, SLIST8A_NEXTENTRY_SHIFT
+
+    /* Use rcx as pointer template */
+    mov rdx, ~SLIST8_POINTER_MASK
+    and rdx, rcx
+
+    /* Combine result and return */
+    or rax, rdx
+    ret
+
+_RtlInterlockedPopEntrySListEmpty:
+    xor rax, rax
+    ret
+
+_RtlInterlockedPopEntrySList16:
+    /* This is a 16 byte header */
+
+    /* Save rbx */
+    push rbx
+
+    /* Copy rcx to r8, as we need rcx for the exchange */
+    mov r8, rcx
+
+_ExpInterlockedPopEntrySListResume16:
+
+    /* Check if ListHead->NextEntry is NULL */
+    mov r9, rdx
+    and r9, SLIST16B_NEXTENTY_MASK
+    jz _RtlInterlockedPopEntrySListEmpty16
+
+_ExpInterlockedPopEntrySListFault16:
+
+    /* Get next pointer */
+    mov rcx, [r9]
+
+    /* Set ListHead->HeaderType = 1 and  ListHead->Init = 1 */
+    or rcx, 0x3
+
+    /* Copy Depth and Sequence number and adjust Depth */
+    lea rbx, [rax - SLIST16A_DEPTH_INC]
+
+_ExpInterlockedPopEntrySListEnd16:
+
+    /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
+    lock cmpxchg16b [r8]
+
+    /* If not equal, retry with rdx:rax, being the content of [r8] now */
+    jnz _ExpInterlockedPopEntrySListResume16
+
+    /* Copy the old NextEntry pointer to rax */
+    mov rax, rdx
+    and rax, SLIST16B_NEXTENTY_MASK
+
+    /* Return */
+    pop rbx
+    ret
+
+_RtlInterlockedPopEntrySListEmpty16:
+    xor rax, rax
+    pop rbx
+    ret
+
+.endproc
+
+
+/* PSLIST_ENTRY
+ * NTAPI
+ * RtlInterlockedPushEntrySList(
+ *     IN PSLIST_HEADER ListHead,
+ *     IN PSLIST_ENTRY ListEntry);
+ */
+.proc RtlInterlockedPushEntrySList
+_ExpInterlockedPushEntrySList:
+
+    /* Load ListHead->Alignment into rax */
+    mov rax, [rcx]
+
+    /* Load ListHead->Region into rdx */
+    mov r9, [rcx + 8]
+
+    /* Check what kind of header this is */
+    test r9, SLIST8B_HEADERTYPE_MASK
+    jnz _RtlInterlockedPushEntrySList16
+
+    /* We have an 8 byte header */
+
+_RtlInterlockedPushEntrySListLoop:
+
+    /* Get ListHead->NextEntry */
+    mov r8, rax
+    and r8, SLIST8A_NEXTENTRY_MASK
+    jz _RtlInterlockedPushEntrySListEmpty
+
+    /* Shift the NextEntry pointer */
+    shr r8, SLIST8A_NEXTENTRY_SHIFT
+
+    /* Create a pointer template from rcx in rdx */
+    mov r9, ~SLIST8_POINTER_MASK
+    and r9, rcx
+
+    /* Combine to new pointer and save as ListEntry->NextEntry */
+    or r8, r9
+
+_RtlInterlockedPushEntrySListEmpty:
+    /* Store the NextEntry pointer in the new ListEntry */
+    mov [rdx], r8
+
+    /* Shift and mask the new ListEntry pointer */
+    mov r8, rdx
+    shl r8, SLIST8A_NEXTENTRY_SHIFT
+    and r8, SLIST8A_NEXTENTRY_MASK
+
+    /* Copy and adjust depth and sequence number */
+    lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC]
+    and r9, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK
+
+    /* Combine to exchange value in r8 */
+    or r8, r9
+
+    /* Save the NextEntry in r9 */
+    mov r9, [rdx]
+
+    /* If [rcx] equals rax, exchange it with r8 */
+    lock cmpxchg [rcx], r8
+
+    /* If not equal, retry with rax, being the content of [rcx] now */
+    jnz _RtlInterlockedPushEntrySListLoop
+
+    /* Return the old NextEntry pointer */
+    mov rax, r9
+    ret
+
+_RtlInterlockedPushEntrySList16:
+    /* This is a 16 byte header */
+
+    /* Save rbx */
+    push rbx
+
+    /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */
+    mov r8, rcx
+    mov r9, rdx
+
+    /* Set ListHead->HeaderType = 1 and  ListHead->Init = 1 */
+    mov rcx, rdx
+    or rcx, 0x3
+
+    mov rdx, [r8 + 8]
+
+_RtlInterlockedPushEntrySListLoop16:
+
+    /* Move ListHead->NextEntry to rbx */
+    mov rbx, rdx
+    and rbx, SLIST16B_NEXTENTY_MASK
+
+    /* Store next pointer in ListEntry->NextEntry */
+    mov [r9], rbx
+
+    /* Copy Depth and Sequence number and adjust Depth */
+    lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC]
+
+    /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
+    lock cmpxchg16b [r8]
+
+    /* If not equal, retry with rdx:rax, being the content of [r8] now */
+    jnz _RtlInterlockedPushEntrySListLoop16
+
+    /* Copy the old NextEntry pointer to rax */
+    mov rax, rdx
+    and rax, SLIST16B_NEXTENTY_MASK
+
+    /* Return */
+    pop rbx
+    ret
+
+.endproc
+
+/* PSLIST_ENTRY
+ * NTAPI
+ * RtlInterlockedFlushSList(
+ *     IN PSINGLE_LIST_ENTRY ListHead);
+ */
+.proc RtlInterlockedFlushSList
+_ExpInterlockedFlushSList:
+
+    /* Load ListHead->Region into rdx */
+    mov rax, [rcx + 8]
+
+    /* Check what kind of header this is */
+    test rax, SLIST8B_HEADERTYPE_MASK
+    jnz _RtlInterlockedFlushSList16
+
+    /* We have an 8 byte header */
+
+_RtlInterlockedFlushSListLoop:
+
+    /* Zero ListHead->Alignment */ 
+    xor r8, r8
+
+    /* If [rcx] equals rax, exchange it with r8 */
+    lock cmpxchg [rcx], r8
+
+    /* If not equal, retry with rax, being the content of [rcx] now */
+    jnz _RtlInterlockedFlushSListLoop
+
+    /* Use rcx as pointer template */
+    mov rdx, ~SLIST8_POINTER_MASK
+    or rdx, rcx
+
+    /* Combine result and return */
+    or rax, rdx
+    ret
+
+_RtlInterlockedFlushSList16:
+    /* We have a 16 byte header */
+    push rbx
+
+    mov rdx, [rcx + 8]
+    xor rbx, rbx
+    mov rcx, 0x3
+
+_RtlInterlockedFlushSListLoop16:
+
+    /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
+    lock cmpxchg16b [r8]
+
+    /* If not equal, retry with rdx:rax, being the content of [r8] now */
+    jnz _RtlInterlockedFlushSListLoop16
+
+    /* Copy the old NextEntry pointer to rax */
+    mov rax, rdx
+    and rax, SLIST16B_NEXTENTY_MASK
+
+    /* Return */
+    pop rbx
+    ret
+
+.endproc
diff --git a/reactos/lib/rtl/amd64/stubs.c b/reactos/lib/rtl/amd64/stubs.c
new file mode 100644 (file)
index 0000000..6fae4e9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * COPYRIGHT:         See COPYING in the top level directory
+ * PROJECT:           ReactOS Run-Time Library
+ * PURPOSE:           AMD64 stubs
+ * FILE:              lib/rtl/amd64/stubs.c
+ * PROGRAMMERS:        Stefan Ginsberg (stefan.ginsberg@reactos.org)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <rtl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+RtlInitializeContext(IN HANDLE ProcessHandle,
+                     OUT PCONTEXT ThreadContext,
+                     IN PVOID ThreadStartParam  OPTIONAL,
+                     IN PTHREAD_START_ROUTINE ThreadStartAddress,
+                     IN PINITIAL_TEB InitialTeb)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+/*
+ * @unimplemented
+ */
+PVOID
+NTAPI
+RtlpGetExceptionAddress(VOID)
+{
+    UNIMPLEMENTED;
+    return NULL;
+}
+
+/*
+ * @unimplemented
+ */
+BOOLEAN
+NTAPI
+RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
+                     IN PCONTEXT Context)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
diff --git a/reactos/lib/rtl/amd64/unwind.c b/reactos/lib/rtl/amd64/unwind.c
new file mode 100644 (file)
index 0000000..914317f
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * PURPOSE:         Unwinding related functions
+ * PROGRAMMER:      Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <rtl.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#define UNWIND_HISTORY_TABLE_NONE 0
+#define UNWIND_HISTORY_TABLE_GLOBAL 1
+#define UNWIND_HISTORY_TABLE_LOCAL 2
+
+#define UWOP_PUSH_NONVOL 0
+#define UWOP_ALLOC_LARGE 1
+#define UWOP_ALLOC_SMALL 2
+#define UWOP_SET_FPREG 3
+#define UWOP_SAVE_NONVOL 4
+#define UWOP_SAVE_NONVOL_FAR 5
+#define UWOP_SAVE_XMM 6
+#define UWOP_SAVE_XMM_FAR 7
+#define UWOP_SAVE_XMM128 8
+#define UWOP_SAVE_XMM128_FAR 9
+#define UWOP_PUSH_MACHFRAME 10
+
+#define UNW_FLAG_NHANDLER 0
+#define UNW_FLAG_EHANDLER 1
+#define UNW_FLAG_UHANDLER 2
+#define UNW_FLAG_CHAININFO 4
+
+typedef unsigned char UBYTE;
+
+typedef union _UNWIND_CODE
+{
+    struct
+    {
+        UBYTE CodeOffset;
+        UBYTE UnwindOp:4;
+        UBYTE OpInfo:4;
+    };
+    USHORT FrameOffset;
+} UNWIND_CODE, *PUNWIND_CODE;
+
+typedef struct _UNWIND_INFO
+{
+    UBYTE Version:3;
+    UBYTE Flags:5;
+    UBYTE SizeOfProlog;
+    UBYTE CountOfCodes;
+    UBYTE FrameRegister:4;
+    UBYTE FrameOffset:4;
+    UNWIND_CODE UnwindCode[1];
+/*    union {
+        OPTIONAL ULONG ExceptionHandler;
+        OPTIONAL ULONG FunctionEntry;
+    };
+    OPTIONAL ULONG ExceptionData[]; 
+*/
+} UNWIND_INFO, *PUNWIND_INFO;
+
+/* FUNCTIONS *****************************************************************/
+
+/*! RtlLookupFunctionTable
+ * \brief Locates the table of RUNTIME_FUNCTION entries for a code address.
+ * \param ControlPc
+ *            Address of the code, for which the table should be searched.
+ * \param ImageBase 
+ *            Pointer to a DWORD64 that receives the base address of the
+ *            corresponding executable image.
+ * \param Length
+ *            Pointer to an ULONG that receives the number of table entries
+ *            present in the table.
+ */
+PRUNTIME_FUNCTION
+NTAPI
+RtlLookupFunctionTable(
+    IN DWORD64 ControlPc,
+    OUT PDWORD64 ImageBase,
+    OUT PULONG Length)
+{
+    PVOID Table;
+    ULONG Size;
+
+    /* Find corresponding file header from code address */
+    if (!RtlPcToFileHeader((PVOID)ControlPc, (PVOID*)ImageBase))
+    {
+        /* Nothing found */
+        return NULL;
+    }
+
+    /* Locate the exception directory */
+    Table = RtlImageDirectoryEntryToData((PVOID)*ImageBase,
+                                         TRUE,
+                                         IMAGE_DIRECTORY_ENTRY_EXCEPTION,
+                                         &Size);
+
+    /* Return the number of entries */
+    *Length = Size / sizeof(RUNTIME_FUNCTION);
+
+    /* Return the address of the table */
+    return Table;
+}
+
+/*! RtlLookupFunctionEntry
+ * \brief Locates the RUNTIME_FUNCTION entry corresponding to a code address.
+ * \ref http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx
+ * \todo Implement HistoryTable
+ */
+PRUNTIME_FUNCTION
+NTAPI
+RtlLookupFunctionEntry(
+    IN DWORD64 ControlPc,
+    OUT PDWORD64 ImageBase,
+    OUT PUNWIND_HISTORY_TABLE HistoryTable)
+{
+    PRUNTIME_FUNCTION FunctionTable, FunctionEntry;
+    ULONG TableLength;
+    ULONG IndexLo, IndexHi, IndexMid;
+
+    /* Find the corresponding table */
+    FunctionTable = RtlLookupFunctionTable(ControlPc, ImageBase, &TableLength);
+
+    /* Fail, if no table is found */
+    if (!FunctionTable)
+    {
+        return NULL;
+    }
+
+    /* Use relative virtual address */
+    ControlPc -= *ImageBase;
+
+    /* Do a binary search */
+    IndexLo = 0;
+    IndexHi = TableLength;
+    while (IndexHi > IndexLo)
+    {
+        IndexMid = (IndexLo + IndexHi) / 2;
+        FunctionEntry = &FunctionTable[IndexMid];
+
+        if (ControlPc < FunctionEntry->BeginAddress)
+        {
+            /* Continue search in lower half */
+            IndexHi = IndexMid;
+        }
+        else if (ControlPc >= FunctionEntry->EndAddress)
+        {
+            /* Continue search in upper half */
+            IndexLo = IndexMid + 1;
+        }
+        else
+        {
+            /* ControlPc is within limits, return entry */
+            return FunctionEntry;
+        }
+    }
+
+    /* Nothing found, return NULL */
+    return NULL;
+}
+
+BOOLEAN
+NTAPI
+RtlAddFunctionTable(
+    IN PRUNTIME_FUNCTION FunctionTable,
+    IN DWORD EntryCount,
+    IN DWORD64 BaseAddress)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+RtlDeleteFunctionTable(
+    IN PRUNTIME_FUNCTION FunctionTable)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+RtlInstallFunctionTableCallback(
+    IN DWORD64 TableIdentifier,
+    IN DWORD64 BaseAddress,
+    IN DWORD Length,
+    IN PGET_RUNTIME_FUNCTION_CALLBACK Callback,
+    IN PVOID Context,
+    IN PCWSTR OutOfProcessCallbackDll)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+void
+FORCEINLINE
+SetReg(PCONTEXT Context, BYTE Reg, DWORD64 Value)
+{
+    ((DWORD64*)(&Context->Rax))[Reg] = Value;
+}
+
+DWORD64
+FORCEINLINE
+GetReg(PCONTEXT Context, BYTE Reg)
+{
+    return ((DWORD64*)(&Context->Rax))[Reg];
+}
+
+void
+FORCEINLINE
+PopReg(PCONTEXT Context, BYTE Reg)
+{
+    DWORD64 Value = *(DWORD64*)Context->Rsp;
+    Context->Rsp += 8;
+    SetReg(Context, Reg, Value);
+}
+
+/*! RtlpTryToUnwindEpilog
+ * \brief Helper function that tries to unwind epilog instructions.
+ * \return TRUE if we have been in an epilog and it could be unwound.
+ *         FALSE if the instructions were not allowed for an epilog.
+ * \ref
+ *  http://msdn.microsoft.com/en-us/library/8ydc79k6(VS.80).aspx
+ *  http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx
+ * \todo
+ *  - Test and compare with Windows behaviour
+ */
+BOOLEAN
+static
+inline
+RtlpTryToUnwindEpilog(
+    PCONTEXT Context,
+    ULONG64 ImageBase,
+    PRUNTIME_FUNCTION FunctionEntry)
+{
+    CONTEXT LocalContext;
+    BYTE *InstrPtr;
+    DWORD Instr;
+    BYTE Reg, Mod;
+    ULONG64 EndAddress;
+
+    /* Make a local copy of the context */
+    LocalContext = *Context;
+
+    InstrPtr = (BYTE*)LocalContext.Rip;
+
+    /* Check if first instruction of epilog is "add rsp, x" */
+    Instr = *(DWORD*)InstrPtr;
+    if ( (Instr & 0x00fffdff) == 0x00c48148 )
+    {
+        if ( (Instr & 0x0000ff00) == 0x8300 )
+        {
+            /* This is "add rsp, 0x??" */
+            LocalContext.Rsp += Instr >> 24;
+            InstrPtr += 4;
+        }
+        else
+        {
+            /* This is "add rsp, 0x???????? */
+            LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
+            InstrPtr += 7;
+        }
+    }
+    /* Check if first instruction of epilog is "lea rsp, ..." */
+    else if ( (Instr & 0x38fffe) == 0x208d48 )
+    {
+        /* Get the register */
+        Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
+
+        LocalContext.Rsp = GetReg(&LocalContext, Reg);
+
+        /* Get adressing mode */
+        Mod = (Instr >> 22) & 0x3;
+        if (Mod == 0)
+        {
+            /* No displacement */
+            InstrPtr += 3;
+        }
+        else if (Mod == 1)
+        {
+            /* 1 byte displacement */
+            LocalContext.Rsp += Instr >> 24;
+            InstrPtr += 4;
+        }
+        else if (Mod == 2)
+        {
+            /* 4 bytes displacement */
+            LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
+            InstrPtr += 7;
+        }
+    }
+
+    /* Loop the following instructions */
+    EndAddress = FunctionEntry->EndAddress + ImageBase;
+    while((DWORD64)InstrPtr < EndAddress)
+    {
+        Instr = *(DWORD*)InstrPtr;
+
+        /* Check for a simple pop */
+        if ( (Instr & 0xf8) == 0x58 )
+        {
+            /* Opcode pops a basic register from stack */
+            Reg = Instr & 0x7;
+            PopReg(&LocalContext, Reg);
+            InstrPtr++;
+            continue;
+        }
+
+        /* Check for REX + pop */
+        if ( (Instr & 0xf8fb) == 0x5841 )
+        {
+            /* Opcode is pop r8 .. r15 */
+            Reg = (Instr & 0x7) + 8;
+            PopReg(&LocalContext, Reg);
+            InstrPtr += 2;
+            continue;
+        }
+
+        /* Check for retn / retf */
+        if ( (Instr & 0xf7) == 0xc3 )
+        {
+            /* We are finished */
+            break;
+        }
+
+        /* Opcode not allowed for Epilog */
+        return FALSE;
+    }
+
+    /* Unwind is finished, pop new Rip from Stack */
+    LocalContext.Rip = *(DWORD64*)LocalContext.Rsp;
+    LocalContext.Rsp += sizeof(DWORD64);
+
+    *Context = LocalContext;
+    return TRUE;
+}
+
+
+PEXCEPTION_ROUTINE
+NTAPI
+RtlVirtualUnwind(
+    IN ULONG HandlerType,
+    IN ULONG64 ImageBase,
+    IN ULONG64 ControlPc,
+    IN PRUNTIME_FUNCTION FunctionEntry,
+    IN OUT PCONTEXT Context,
+    OUT PVOID *HandlerData,
+    OUT PULONG64 EstablisherFrame,
+    IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
+{
+    PUNWIND_INFO UnwindInfo;
+    ULONG CodeOffset;
+    ULONG i;
+    UNWIND_CODE UnwindCode;
+    BYTE Reg;
+
+    /* Use relative virtual address */
+    ControlPc -= ImageBase;
+
+    /* Sanity checks */
+    if ( (ControlPc < FunctionEntry->BeginAddress) ||
+         (ControlPc >= FunctionEntry->EndAddress) )
+    {
+        return NULL;
+    }
+
+    /* Get a pointer to the unwind info */
+    UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
+
+    /* Calculate relative offset to function start */
+    CodeOffset = ControlPc - FunctionEntry->BeginAddress;
+
+    /* Check if we are in the function epilog and try to finish it */
+    if (CodeOffset > UnwindInfo->SizeOfProlog)
+    {
+        if (RtlpTryToUnwindEpilog(Context, ImageBase, FunctionEntry))
+        {
+            /* There's no exception routine */
+            return NULL;
+        }
+    }
+
+    /* Skip all Ops with an offset greater than the current Offset */
+    i = 0;
+    while (i < UnwindInfo->CountOfCodes &&
+           CodeOffset < UnwindInfo->UnwindCode[i].CodeOffset)
+    {
+        UnwindCode = UnwindInfo->UnwindCode[i];
+        switch (UnwindCode.UnwindOp)
+        {
+            case UWOP_SAVE_NONVOL:
+            case UWOP_SAVE_XMM:
+            case UWOP_SAVE_XMM128:
+                i += 2;
+                break;
+
+            case UWOP_SAVE_NONVOL_FAR:
+            case UWOP_SAVE_XMM_FAR:
+            case UWOP_SAVE_XMM128_FAR:
+                i += 3;
+                break;
+
+            case UWOP_ALLOC_LARGE:
+                i += UnwindCode.OpInfo ? 3 : 2;
+                break;
+
+            default:
+                i++;
+        }
+    }
+
+    /* Process the left Ops */
+    while (i < UnwindInfo->CountOfCodes)
+    {
+        UnwindCode = UnwindInfo->UnwindCode[i];
+        switch (UnwindCode.UnwindOp)
+        {
+            case UWOP_PUSH_NONVOL:
+                Reg = UnwindCode.OpInfo;
+                SetReg(Context, Reg, *(DWORD64*)Context->Rsp);
+                Context->Rsp += sizeof(DWORD64);
+                i++;
+                break;
+
+            case UWOP_ALLOC_LARGE:
+                if (UnwindCode.OpInfo)
+                {
+                    ULONG Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i+1]);
+                    Context->Rsp += Offset;
+                    i += 3;
+                }
+                else
+                {
+                    USHORT Offset = UnwindInfo->UnwindCode[i+1].FrameOffset;
+                    Context->Rsp += Offset * 8;
+                    i += 2;
+                }
+                break;
+
+            case UWOP_ALLOC_SMALL:
+                Context->Rsp += (UnwindCode.OpInfo + 1) * 8;
+                i++;
+                break;
+
+            case UWOP_SET_FPREG:
+                i++;
+                break;
+
+            case UWOP_SAVE_NONVOL:
+                i += 2;
+                break;
+
+            case UWOP_SAVE_NONVOL_FAR:
+                i += 3;
+                break;
+
+            case UWOP_SAVE_XMM:
+                i += 2;
+                break;
+
+            case UWOP_SAVE_XMM_FAR:
+                i += 3;
+                break;
+
+            case UWOP_SAVE_XMM128:
+                i += 2;
+                break;
+
+            case UWOP_SAVE_XMM128_FAR:
+                i += 3;
+                break;
+
+            case UWOP_PUSH_MACHFRAME:
+                i += 1;
+                break;
+        }
+    }
+
+    /* Unwind is finished, pop new Rip from Stack */
+    Context->Rip = *(DWORD64*)Context->Rsp;
+    Context->Rsp += sizeof(DWORD64);
+
+    return 0;
+}
+
+VOID
+NTAPI
+RtlUnwindEx(
+   IN ULONG64 TargetFrame,
+   IN ULONG64 TargetIp,
+   IN PEXCEPTION_RECORD ExceptionRecord,
+   IN PVOID ReturnValue,
+   OUT PCONTEXT OriginalContext,
+   IN PUNWIND_HISTORY_TABLE HistoryTable)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+VOID
+NTAPI
+RtlUnwind(
+  IN PVOID TargetFrame,
+  IN PVOID TargetIp,
+  IN PEXCEPTION_RECORD ExceptionRecord,
+  IN PVOID ReturnValue)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+ULONG
+NTAPI
+RtlWalkFrameChain(OUT PVOID *Callers,
+                  IN ULONG Count,
+                  IN ULONG Flags)
+{
+    CONTEXT Context;
+    ULONG64 ControlPc, ImageBase, EstablisherFrame;
+    ULONG64 StackLow, StackHigh;
+    PVOID HandlerData;
+    INT i;
+    PRUNTIME_FUNCTION FunctionEntry;
+
+    DPRINT("Enter RtlWalkFrameChain\n");
+
+    /* Capture the current Context */
+    RtlCaptureContext(&Context);
+    ControlPc = Context.Rip;
+
+    /* Get the stack limits */
+    RtlpGetStackLimits(&StackLow, &StackHigh);
+
+    /* Check if we want the user-mode stack frame */
+    if (Flags == 1)
+    {
+    }
+
+    /* Loop the frames */
+    for (i = 0; i < Count; i++)
+    {
+        /* Lookup the FunctionEntry for the current ControlPc */
+        FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
+
+        /* Is this a leaf function? */
+        if (!FunctionEntry)
+        {
+            Context.Rip = *(DWORD64*)Context.Rsp;
+            Context.Rsp += sizeof(DWORD64);
+            DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
+        }
+        else
+        {
+            RtlVirtualUnwind(0,
+                             ImageBase,
+                             ControlPc,
+                             FunctionEntry,
+                             &Context,
+                             &HandlerData,
+                             &EstablisherFrame,
+                             NULL);
+            DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
+        }
+
+        /* Check if new Rip is valid */
+        if (!Context.Rip)
+        {
+            break;
+        }
+
+        /* Check, if we have left our stack */
+        if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
+        {
+            break;
+        }
+
+        /* Save this frame and continue with new Rip */
+        ControlPc = Context.Rip;
+        Callers[i] = (PVOID)ControlPc;
+    }
+
+    DPRINT("RtlWalkFrameChain returns %ld\n", i);
+    return i;
+}
+
+/*! RtlGetCallersAddress
+ * \ref http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Debug/RtlGetCallersAddress.html
+ */
+#undef RtlGetCallersAddress
+VOID
+NTAPI
+RtlGetCallersAddress(
+    OUT PVOID *CallersAddress,
+    OUT PVOID *CallersCaller )
+{
+    PVOID Callers[4];
+    ULONG Number;
+
+    /* Get callers:
+     * RtlWalkFrameChain -> RtlGetCallersAddress -> x -> y */
+    Number = RtlWalkFrameChain(Callers, 4, 0);
+
+    if (CallersAddress)
+    {
+        *CallersAddress = (Number >= 3) ? Callers[2] : NULL;
+    }
+    if (CallersCaller)
+    {
+        *CallersCaller = (Number == 4) ? Callers[3] : NULL;
+    }
+
+    return;
+}
+
+// FIXME: move to different file
+VOID
+NTAPI
+RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
+{
+    CONTEXT Context;
+    NTSTATUS Status = STATUS_INVALID_DISPOSITION;
+    ULONG64 ImageBase;
+    PRUNTIME_FUNCTION FunctionEntry;
+    PVOID HandlerData;
+    ULONG64 EstablisherFrame;
+
+    /* Capture the context */
+    RtlCaptureContext(&Context);
+
+    /* Get the function entry for this function */
+    FunctionEntry = RtlLookupFunctionEntry(Context.Rip,
+                                           &ImageBase,
+                                           NULL);
+
+    /* Check if we found it */
+    if (FunctionEntry)
+    {
+        /* Unwind to the caller of this function */
+        RtlVirtualUnwind(UNW_FLAG_NHANDLER,
+                         ImageBase,
+                         Context.Rip,
+                         FunctionEntry,
+                         &Context,
+                         &HandlerData,
+                         &EstablisherFrame,
+                         NULL);
+
+        /* Save the exception address */
+        ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
+
+        /* Write the context flag */
+        Context.ContextFlags = CONTEXT_FULL;
+
+        /* Check if user mode debugger is active */
+        if (RtlpCheckForActiveDebugger())
+        {
+            /* Raise an exception immediately */
+            Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
+        }
+        else
+        {
+            /* Dispatch the exception and check if we should continue */
+            if (!RtlDispatchException(ExceptionRecord, &Context))
+            {
+                /* Raise the exception */
+                Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
+            }
+            else
+            {
+                /* Continue, go back to previous context */
+                Status = ZwContinue(&Context, FALSE);
+            }
+        }
+    }
+
+    /* If we returned, raise a status */
+    RtlRaiseStatus(Status);
+}
+
index d4462e3..e0970d1 100644 (file)
@@ -17,7 +17,7 @@
 
 /* FUNCTIONS ***************************************************************/
 
-#if !defined(_M_IX86)
+#if !defined(_M_IX86) && !defined(_M_AMD64)
 
 /*
  * @implemented
@@ -63,6 +63,10 @@ RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
     RtlRaiseStatus(Status);
 }
 
+#endif
+
+#if !defined(_M_IX86)
+
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4717) // RtlRaiseStatus is recursive by design
index d51f02d..6d89eeb 100644 (file)
                <file>mem.c</file>
                <file>memgen.c</file>
        </if>
+       <if property="ARCH" value="amd64">
+               <directory name="amd64">
+                       <file>debug_asm.S</file>
+                       <file>except_asm.S</file>
+                       <file>slist.S</file>
+                       <file>unwind.c</file>
+                       <file>stubs.c</file>
+               </directory>
+               <file>mem.c</file>
+               <file>memgen.c</file>
+       </if>
        <directory name="austin">
                <file>avl.c</file>
                <file>tree.c</file>
index 0ae62d2..f998f5a 100644 (file)
@@ -32,10 +32,12 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
 #define ROUND_UP(n, align) \
     ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
 
+#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
+
 VOID
 NTAPI
-RtlpGetStackLimits(PULONG_PTR StackBase,
-                   PULONG_PTR StackLimit);
+RtlpGetStackLimits(PULONG_PTR LowLimit,
+                   PULONG_PTR HighLimit);
 
 PEXCEPTION_REGISTRATION_RECORD
 NTAPI
index 1eef23d..4d291ab 100644 (file)
@@ -20,7 +20,10 @@ NTAPI
 RtlInitializeSListHead(IN PSLIST_HEADER ListHead)
 {
 #ifdef _WIN64
-    UNIMPLEMENTED;
+    ListHead->Alignment = 0;
+    ListHead->Region = 0;
+    ListHead->Header8.Init = 1;
+    // ListHead->Header8.HeaderType = 1; // FIXME: depending on cmpxchg16b support?
 #else
     ListHead->Alignment = 0;
 #endif
@@ -31,8 +34,25 @@ NTAPI
 RtlFirstEntrySList(IN const SLIST_HEADER *ListHead)
 {
 #ifdef _WIN64
-    UNIMPLEMENTED;
-    return NULL;
+    if (ListHead->Header8.HeaderType)
+    {
+        return (PVOID)(ListHead->Region & ~0xF);
+    }
+    else
+    {
+        union {
+            PVOID P;
+            struct {
+                ULONG64 Reserved:4;
+                ULONG64 NextEntry:39;
+                ULONG64 Reserved2:21;
+            } Bits;
+        } Pointer;
+
+        Pointer.P = (PVOID)ListHead;
+        Pointer.Bits.NextEntry = ListHead->Header8.NextEntry;
+        return Pointer.P;
+    }
 #else
     return ListHead->Next.Next;
 #endif
@@ -43,8 +63,8 @@ NTAPI
 RtlQueryDepthSList(IN PSLIST_HEADER ListHead)
 {
 #ifdef _WIN64
-    UNIMPLEMENTED;
-    return 0;
+    return ListHead->Header8.HeaderType ? 
+        ListHead->Header16.Sequence : ListHead->Header8.Sequence;
 #else
     return ListHead->Depth;
 #endif
index 252de8d..c6d651a 100644 (file)
 #define SPECIAL        32              /* 0x */
 #define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
 #define REMOVEHEX      256             /* use 256 as remve 0x frim BASE 16  */
-typedef struct {
-    unsigned int mantissal:32;
-    unsigned int mantissah:20;
-    unsigned int exponent:11;
-    unsigned int sign:1;
+typedef union {
+    struct {
+        unsigned int mantissal:32;
+        unsigned int mantissah:20;
+        unsigned int exponent:11;
+        unsigned int sign:1;
+    };
+    long long AsLongLong;
 } double_t;
 
+/* We depend on this being true */
+C_ASSERT(sizeof(double_t) == sizeof(double));
+
 static
 __inline
 int
-_isinf(double __x)
+_isinf(double_t x)
 {
-       union
-       {
-               double*   __x;
-               double_t*   x;
-       } x;
-
-       x.__x = &__x;
-       return ( x.x->exponent == 0x7ff  && ( x.x->mantissah == 0 && x.x->mantissal == 0 ));
+       return ( x.exponent == 0x7ff  && ( x.mantissah == 0 && x.mantissal == 0 ));
 }
 
 static
 __inline
 int
-_isnan(double __x)
+_isnan(double_t x)
 {
-       union
-       {
-               double*   __x;
-               double_t*   x;
-       } x;
-       x.__x = &__x;
-       return ( x.x->exponent == 0x7ff  && ( x.x->mantissah != 0 || x.x->mantissal != 0 ));
+       return ( x.exponent == 0x7ff  && ( x.mantissah != 0 || x.mantissal != 0 ));
 }
 
 
@@ -180,14 +173,13 @@ number(char * buf, char * end, long long num, int base, int size, int precision,
 }
 
 static char *
-numberf(char * buf, char * end, double num, int base, int size, int precision, int type)
+numberf(char * buf, char * end, double_t num, int base, int size, int precision, int type)
 {
        char c,sign,tmp[66];
        const char *digits;
        const char *small_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
        const char *large_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int i;
-       long long x;
 
     /* FIXME
        the float version of number is direcly copy of number
@@ -201,9 +193,9 @@ numberf(char * buf, char * end, double num, int base, int size, int precision, i
        c = (type & ZEROPAD) ? '0' : ' ';
        sign = 0;
        if (type & SIGN) {
-               if (num < 0) {
+               if (num.sign) {
                        sign = '-';
-                       num = -num;
+                       num.sign = 0;
                        size--;
                } else if (type & PLUS) {
                        sign = '+';
@@ -220,15 +212,11 @@ numberf(char * buf, char * end, double num, int base, int size, int precision, i
                        size--;
        }
        i = 0;
-       if (num == 0)
+       if (num.AsLongLong == 0)
                tmp[i++] = '0';
-       else while (num != 0)
+       else while (num.AsLongLong != 0)
     {
-        x = num;
-               tmp[i++] = digits[do_div(&x,base)];
-#ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4
-               num=x;
-#endif
+               tmp[i++] = digits[do_div(&num.AsLongLong,base)];
     }
        if (i > precision)
                precision = i;
@@ -389,7 +377,7 @@ int __cdecl _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args)
 {
        int len;
        unsigned long long num;
-       double _double;
+       double_t _double;
 
        int base;
        char *str, *end;
@@ -600,7 +588,7 @@ int __cdecl _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args)
                case 'f':
                case 'g':
                case 'G':
-          _double = (double)va_arg(args, double);
+          _double = va_arg(args, double_t);
          if ( _isnan(_double) ) {
             s = "Nan";
             len = 3;
@@ -631,7 +619,7 @@ int __cdecl _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args)
          } else {
             if ( precision == -1 )
                precision = 6;
-                       str = numberf(str, end, (int)_double, base, field_width, precision, flags);
+                       str = numberf(str, end, _double, base, field_width, precision, flags);
          }
 
           continue;
index e47d49a..8ac75ca 100644 (file)
 #define SPECIAL        32              /* 0x */
 #define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
 #define REMOVEHEX      256             /* use 256 as remve 0x frim BASE 16  */
-typedef struct {
-    unsigned int mantissal:32;
-    unsigned int mantissah:20;
-    unsigned int exponent:11;
-    unsigned int sign:1;
+typedef union {
+    struct {
+        unsigned int mantissal:32;
+        unsigned int mantissah:20;
+        unsigned int exponent:11;
+        unsigned int sign:1;
+    };
+    long long AsLongLong;
 } double_t;
 
+/* We depend on this being true */
+C_ASSERT(sizeof(double_t) == sizeof(double));
+
 static
 __inline
 int
-_isinf(double __x)
+_isinf(double_t x)
 {
-       union
-       {
-               double*   __x;
-               double_t*   x;
-       } x;
-
-       x.__x = &__x;
-       return ( x.x->exponent == 0x7ff  && ( x.x->mantissah == 0 && x.x->mantissal == 0 ));
+       return ( x.exponent == 0x7ff  && ( x.mantissah == 0 && x.mantissal == 0 ));
 }
 
 static
 __inline
 int
-_isnan(double __x)
+_isnan(double_t x)
 {
-       union
-       {
-               double*   __x;
-               double_t*   x;
-       } x;
-       x.__x = &__x;
-       return ( x.x->exponent == 0x7ff  && ( x.x->mantissah != 0 || x.x->mantissal != 0 ));
+       return ( x.exponent == 0x7ff  && ( x.mantissah != 0 || x.mantissal != 0 ));
 }
 
 
@@ -179,14 +172,13 @@ number(wchar_t * buf, wchar_t * end, long long num, int base, int size, int prec
 }
 
 static wchar_t *
-numberf(wchar_t * buf, wchar_t * end, double num, int base, int size, int precision, int type)
+numberf(wchar_t * buf, wchar_t * end, double_t num, int base, int size, int precision, int type)
 {
        wchar_t c, sign, tmp[66];
        const wchar_t *digits;
        const wchar_t *small_digits = L"0123456789abcdefghijklmnopqrstuvwxyz";
        const wchar_t *large_digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int i;
-       long long x;
 
     /* FIXME
        the float version of number is direcly copy of number
@@ -201,9 +193,9 @@ numberf(wchar_t * buf, wchar_t * end, double num, int base, int size, int precis
        c = (type & ZEROPAD) ? L'0' : L' ';
        sign = 0;
        if (type & SIGN) {
-               if (num < 0) {
+               if (num.sign) {
                        sign = L'-';
-                       num = -num;
+                       num.sign = 0;
                        size--;
                } else if (type & PLUS) {
                        sign = L'+';
@@ -220,15 +212,11 @@ numberf(wchar_t * buf, wchar_t * end, double num, int base, int size, int precis
                        size--;
        }
        i = 0;
-       if (num == 0)
+       if (num.AsLongLong == 0)
                tmp[i++] = L'0';
-       else while (num != 0)
+       else while (num.AsLongLong != 0)
        {
-        x = num;
-               tmp[i++] = digits[do_div(&x,base)];
-#ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4
-               num = x;
-#endif
+               tmp[i++] = digits[do_div(&num.AsLongLong,base)];
     }
        if (i > precision)
                precision = i;
@@ -394,7 +382,7 @@ int __cdecl _vsnwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, va_list ar
        const char *s;
        const wchar_t *sw;
        const wchar_t *ss;
-       double _double;
+       double_t _double;
 
        int flags;              /* flags to number() */
 
@@ -597,7 +585,7 @@ int __cdecl _vsnwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, va_list ar
                case 'f':
                case 'g':
                case 'G':
-          _double = (double)va_arg(args, double);
+          _double = va_arg(args, double_t);
 
          if ( _isnan(_double) ) {
             ss = L"Nan";