ntdll: Update the TEB and PEB structures for newer Windows versions.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0e4d22bd8d
commit
0bf52b09f2
|
@ -304,9 +304,10 @@ struct kernel_thread_data
|
|||
WORD htask16; /* Win16 task handle */
|
||||
DWORD sys_count[4]; /* syslevel mutex entry counters */
|
||||
struct tagSYSLEVEL *sys_mutex[4]; /* syslevel mutex pointers */
|
||||
void *pad[45]; /* change this if you add fields! */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct kernel_thread_data) <= sizeof(((TEB *)0)->SystemReserved1) );
|
||||
|
||||
static inline struct kernel_thread_data *kernel_get_thread_data(void)
|
||||
{
|
||||
return (struct kernel_thread_data *)NtCurrentTeb()->SystemReserved1;
|
||||
|
|
|
@ -113,6 +113,7 @@ extern enum loadorder get_load_order( const WCHAR *app_name, const UNICODE_STRIN
|
|||
/* thread private data, stored in NtCurrentTeb()->GdiTebBatch */
|
||||
struct ntdll_thread_data
|
||||
{
|
||||
void *cpu_data[16]; /* reserved for CPU-specific data */
|
||||
struct debug_info *debug_info; /* info for debugstr functions */
|
||||
void *start_stack; /* stack for thread startup */
|
||||
int request_fd; /* fd for sending server requests */
|
||||
|
|
|
@ -78,12 +78,13 @@ struct x86_thread_data
|
|||
/* the ntdll_thread_data structure follows here */
|
||||
};
|
||||
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||
C_ASSERT( sizeof(struct x86_thread_data) <= sizeof( ((struct ntdll_thread_data *)0)->cpu_data ));
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||
|
||||
static inline struct x86_thread_data *x86_thread_data(void)
|
||||
{
|
||||
return (struct x86_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||
return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
|
||||
}
|
||||
|
||||
struct ldt_copy *__wine_ldt_copy = NULL;
|
||||
|
|
|
@ -880,7 +880,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
"push {r4-r12,lr}\n\t"
|
||||
/* store exit frame */
|
||||
"ldr r4, [sp, #40]\n\t" /* teb */
|
||||
"str sp, [r4, #0x1d4]\n\t" /* teb->SystemReserved2 */
|
||||
"str sp, [r4, #0x1d4]\n\t" /* teb->GdiTebBatch */
|
||||
/* switch to thread stack */
|
||||
"ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */
|
||||
"sub sp, r4, #0x1000\n\t"
|
||||
|
@ -899,7 +899,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );
|
||||
__ASM_GLOBAL_FUNC( call_thread_exit_func,
|
||||
".arm\n\t"
|
||||
"ldr r3, [r2, #0x1d4]\n\t" /* teb->SystemReserved2 */
|
||||
"ldr r3, [r2, #0x1d4]\n\t" /* teb->GdiTebBatch */
|
||||
"mov ip, #0\n\t"
|
||||
"str ip, [r2, #0x1d4]\n\t"
|
||||
"cmp r3, ip\n\t"
|
||||
|
|
|
@ -118,16 +118,16 @@ static pthread_key_t teb_key;
|
|||
|
||||
struct arm64_thread_data
|
||||
{
|
||||
void *exit_frame; /* exit frame pointer */
|
||||
CONTEXT *context; /* context to set with SIGUSR2 */
|
||||
void *exit_frame; /* 02f0 exit frame pointer */
|
||||
CONTEXT *context; /* 02f8 context to set with SIGUSR2 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct arm64_thread_data) <= sizeof(((TEB *)0)->SystemReserved2) );
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct arm64_thread_data, exit_frame ) == 0x300 );
|
||||
C_ASSERT( sizeof(struct arm64_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, exit_frame ) == 0x2f0 );
|
||||
|
||||
static inline struct arm64_thread_data *arm64_thread_data(void)
|
||||
{
|
||||
return (struct arm64_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||
return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
|
||||
}
|
||||
|
||||
|
||||
|
@ -932,7 +932,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
"mov x18, x4\n\t" /* teb */
|
||||
/* store exit frame */
|
||||
"mov x29, sp\n\t"
|
||||
"str x29, [x4, #0x300]\n\t" /* arm64_thread_data()->exit_frame */
|
||||
"str x29, [x4, #0x2f0]\n\t" /* arm64_thread_data()->exit_frame */
|
||||
/* switch to thread stack */
|
||||
"ldr x5, [x4, #8]\n\t" /* teb->Tib.StackBase */
|
||||
"sub sp, x5, #0x1000\n\t"
|
||||
|
@ -971,8 +971,8 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );
|
||||
__ASM_GLOBAL_FUNC( call_thread_exit_func,
|
||||
"stp x29, x30, [sp,#-16]!\n\t"
|
||||
"ldr x3, [x2, #0x300]\n\t" /* arm64_thread_data()->exit_frame */
|
||||
"str xzr, [x2, #0x300]\n\t"
|
||||
"ldr x3, [x2, #0x2f0]\n\t" /* arm64_thread_data()->exit_frame */
|
||||
"str xzr, [x2, #0x2f0]\n\t"
|
||||
"cbz x3, 1f\n\t"
|
||||
"mov sp, x3\n"
|
||||
"1:\tldp x29, x30, [sp], #16\n\t"
|
||||
|
|
|
@ -487,12 +487,13 @@ struct x86_thread_data
|
|||
/* the ntdll_thread_data structure follows here */
|
||||
};
|
||||
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||
C_ASSERT( sizeof(struct x86_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||
|
||||
static inline struct x86_thread_data *x86_thread_data(void)
|
||||
{
|
||||
return (struct x86_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||
return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
|
||||
}
|
||||
|
||||
static inline WORD get_cs(void) { WORD res; __asm__( "movw %%cs,%0" : "=r" (res) ); return res; }
|
||||
|
@ -567,7 +568,7 @@ static void wine_sigacthandler( int signal, siginfo_t *siginfo, void *sigcontext
|
|||
|
||||
__asm__ __volatile__("mov %ss,%ax; mov %ax,%ds; mov %ax,%es");
|
||||
|
||||
thread_data = (struct x86_thread_data *)get_current_teb()->SystemReserved2;
|
||||
thread_data = (struct x86_thread_data *)get_current_teb()->GdiTebBatch;
|
||||
set_fs( thread_data->fs );
|
||||
set_gs( thread_data->gs );
|
||||
|
||||
|
@ -615,7 +616,7 @@ static inline void *init_handler( const ucontext_t *sigcontext )
|
|||
|
||||
#ifndef __sun /* see above for Solaris handling */
|
||||
{
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
|
||||
set_fs( thread_data->fs );
|
||||
set_gs( thread_data->gs );
|
||||
}
|
||||
|
@ -2044,7 +2045,7 @@ void signal_init_threading(void)
|
|||
*/
|
||||
NTSTATUS signal_alloc_thread( TEB *teb )
|
||||
{
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
|
||||
|
||||
if (!gdt_fs_sel)
|
||||
{
|
||||
|
@ -2086,7 +2087,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
|
|||
*/
|
||||
void signal_free_thread( TEB *teb )
|
||||
{
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
|
||||
sigset_t sigset;
|
||||
|
||||
if (gdt_fs_sel) return;
|
||||
|
@ -2103,7 +2104,7 @@ void signal_free_thread( TEB *teb )
|
|||
void signal_init_thread( TEB *teb )
|
||||
{
|
||||
const WORD fpu_cw = 0x27f;
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
|
||||
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
|
||||
|
||||
ldt_set_fs( thread_data->fs, teb );
|
||||
thread_data->gs = get_gs();
|
||||
|
|
|
@ -242,21 +242,21 @@ C_ASSERT( sizeof(struct stack_layout) == 0x630 ); /* Should match the size in ca
|
|||
|
||||
struct amd64_thread_data
|
||||
{
|
||||
DWORD_PTR dr0; /* debug registers */
|
||||
DWORD_PTR dr0; /* 02f0 debug registers */
|
||||
DWORD_PTR dr1;
|
||||
DWORD_PTR dr2;
|
||||
DWORD_PTR dr3;
|
||||
DWORD_PTR dr6;
|
||||
DWORD_PTR dr7;
|
||||
void *exit_frame; /* exit frame pointer */
|
||||
void *exit_frame; /* 0320 exit frame pointer */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((TEB *)0)->SystemReserved2) );
|
||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct amd64_thread_data, exit_frame ) == 0x330 );
|
||||
C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, exit_frame ) == 0x320 );
|
||||
|
||||
static inline struct amd64_thread_data *amd64_thread_data(void)
|
||||
{
|
||||
return (struct amd64_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||
return (struct amd64_thread_data *)ntdll_get_thread_data()->cpu_data;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2479,7 +2479,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
__ASM_CFI(".cfi_rel_offset %r15,8\n\t")
|
||||
/* store exit frame */
|
||||
"movq %gs:0x30,%rax\n\t"
|
||||
"movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */
|
||||
"movq %rsp,0x320(%rax)\n\t" /* amd64_thread_data()->exit_frame */
|
||||
/* switch to thread stack */
|
||||
"movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */
|
||||
"leaq -0x1000(%rax),%rsp\n\t"
|
||||
|
@ -2503,7 +2503,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
__ASM_GLOBAL_FUNC( signal_exit_thread,
|
||||
/* fetch exit frame */
|
||||
"movq %gs:0x30,%rax\n\t"
|
||||
"movq 0x330(%rax),%rdx\n\t" /* amd64_thread_data()->exit_frame */
|
||||
"movq 0x320(%rax),%rdx\n\t" /* amd64_thread_data()->exit_frame */
|
||||
"testq %rdx,%rdx\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"jmp *%rsi\n"
|
||||
|
|
|
@ -51,6 +51,7 @@ struct debug_info
|
|||
/* thread private data, stored in NtCurrentTeb()->GdiTebBatch */
|
||||
struct ntdll_thread_data
|
||||
{
|
||||
void *cpu_data[16]; /* reserved for CPU-specific data */
|
||||
struct debug_info *debug_info; /* info for debugstr functions */
|
||||
void *start_stack; /* stack for thread startup */
|
||||
int request_fd; /* fd for sending server requests */
|
||||
|
|
|
@ -2570,6 +2570,8 @@ static void init_teb( TEB *teb, PEB *peb )
|
|||
teb->Tib.Self = &teb->Tib;
|
||||
teb->Tib.ExceptionList = (void *)~0ul;
|
||||
teb->Tib.StackBase = (void *)~0ul;
|
||||
teb->ActivationContextStackPointer = &teb->ActivationContextStack;
|
||||
InitializeListHead( &teb->ActivationContextStack.FrameListCache );
|
||||
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||
thread_data->request_fd = -1;
|
||||
|
|
|
@ -233,10 +233,11 @@ typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME
|
|||
|
||||
typedef struct _ACTIVATION_CONTEXT_STACK
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG NextCookieSequenceNumber;
|
||||
RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
|
||||
LIST_ENTRY FrameListCache;
|
||||
ULONG Flags;
|
||||
ULONG NextCookieSequenceNumber;
|
||||
ULONG_PTR StackId;
|
||||
} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK;
|
||||
|
||||
typedef struct _TEB_ACTIVE_FRAME_CONTEXT
|
||||
|
@ -340,6 +341,18 @@ typedef struct _PEB
|
|||
LIST_ENTRY FlsListHead; /* 210/328 */
|
||||
PRTL_BITMAP FlsBitmap; /* 218/338 */
|
||||
ULONG FlsBitmapBits[4]; /* 21c/340 */
|
||||
ULONG FlsHighIndex; /* 22c/350 */
|
||||
PVOID WerRegistrationData; /* 230/358 */
|
||||
PVOID WerShipAssertPtr; /* 234/360 */
|
||||
PVOID pUnused; /* 238/368 */
|
||||
PVOID pImageHeaderHash; /* 23c/370 */
|
||||
ULONG TracingFlags; /* 240/378 */
|
||||
ULONGLONG CsrServerReadOnlySharedMemoryBase; /* 248/380 */
|
||||
ULONG TppWorkerpListLock; /* 250/388 */
|
||||
LIST_ENTRY TppWorkerpList; /* 254/390 */
|
||||
PVOID WaitOnAddressHashTable [0x80]; /* 25c/3a0 */
|
||||
PVOID TelemetryCoverageHeader; /* 45c/7a0 */
|
||||
ULONG CloudFileFlags; /* 460/7a8 */
|
||||
} PEB, *PPEB;
|
||||
|
||||
|
||||
|
@ -358,27 +371,44 @@ typedef struct _TEB
|
|||
ULONG CountOfOwnedCriticalSections; /* 038/006c */
|
||||
PVOID CsrClientThread; /* 03c/0070 */
|
||||
PVOID Win32ThreadInfo; /* 040/0078 */
|
||||
ULONG Win32ClientInfo[31]; /* 044/0080 used for user32 private data in Wine */
|
||||
ULONG User32Reserved[26]; /* 044/0080 */
|
||||
ULONG UserReserved[5]; /* 0ac/00e8 */
|
||||
PVOID WOW32Reserved; /* 0c0/0100 */
|
||||
ULONG CurrentLocale; /* 0c4/0108 */
|
||||
ULONG FpSoftwareStatusRegister; /* 0c8/010c */
|
||||
PVOID SystemReserved1[54]; /* 0cc/0110 used for kernel32 private data in Wine */
|
||||
PVOID ReservedForDebuggerInstrumentation[16]; /* 0cc/0110 */
|
||||
#ifdef _WIN64
|
||||
PVOID SystemReserved1[30]; /* /0190 */
|
||||
#else
|
||||
PVOID SystemReserved1[26]; /* 10c/ used for krnl386 private data in Wine */
|
||||
#endif
|
||||
char PlaceholderCompatibilityMode; /* 174/0280 */
|
||||
char PlaceholderReserved[11]; /* 175/0281 */
|
||||
DWORD ProxiedProcessId; /* 180/028c */
|
||||
ACTIVATION_CONTEXT_STACK ActivationContextStack; /* 184/0290 */
|
||||
UCHAR WorkingOnBehalfOfTicket[8]; /* 19c/02b8 */
|
||||
LONG ExceptionCode; /* 1a4/02c0 */
|
||||
ACTIVATION_CONTEXT_STACK ActivationContextStack; /* 1a8/02c8 */
|
||||
BYTE SpareBytes1[24]; /* 1bc/02e8 */
|
||||
PVOID SystemReserved2[10]; /* 1d4/0300 used for ntdll platform-specific private data in Wine */
|
||||
GDI_TEB_BATCH GdiTebBatch; /* 1fc/0350 used for ntdll private data in Wine */
|
||||
HANDLE gdiRgn; /* 6dc/0838 */
|
||||
HANDLE gdiPen; /* 6e0/0840 */
|
||||
HANDLE gdiBrush; /* 6e4/0848 */
|
||||
CLIENT_ID RealClientId; /* 6e8/0850 */
|
||||
HANDLE GdiCachedProcessHandle; /* 6f0/0860 */
|
||||
ULONG GdiClientPID; /* 6f4/0868 */
|
||||
ULONG GdiClientTID; /* 6f8/086c */
|
||||
PVOID GdiThreadLocaleInfo; /* 6fc/0870 */
|
||||
ULONG UserReserved[5]; /* 700/0878 */
|
||||
PVOID glDispatchTable[280]; /* 714/0890 */
|
||||
PVOID glReserved1[26]; /* b74/1150 */
|
||||
ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; /* 1a8/02c8 */
|
||||
ULONG_PTR InstrumentationCallbackSp; /* 1ac/02d0 */
|
||||
ULONG_PTR InstrumentationCallbackPreviousPc; /* 1b0/02d8 */
|
||||
ULONG_PTR InstrumentationCallbackPreviousSp; /* 1b4/02e0 */
|
||||
#ifdef _WIN64
|
||||
ULONG TxFsContext; /* /02e8 */
|
||||
BOOLEAN InstrumentationCallbackDisabled; /* /02ec */
|
||||
#else
|
||||
BOOLEAN InstrumentationCallbackDisabled; /* 1b8/ */
|
||||
BYTE SpareBytes1[23]; /* 1b9/ */
|
||||
ULONG TxFsContext; /* 1d0/ */
|
||||
#endif
|
||||
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 used for ntdll private data in Wine */
|
||||
CLIENT_ID RealClientId; /* 6b4/07d8 */
|
||||
HANDLE GdiCachedProcessHandle; /* 6bc/07e8 */
|
||||
ULONG GdiClientPID; /* 6c0/07f0 */
|
||||
ULONG GdiClientTID; /* 6c4/07f4 */
|
||||
PVOID GdiThreadLocaleInfo; /* 6c8/07f8 */
|
||||
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 used for user32 private data in Wine */
|
||||
PVOID glDispatchTable[233]; /* 7c4/09f0 */
|
||||
PVOID glReserved1[29]; /* b68/1138 */
|
||||
PVOID glReserved2; /* bdc/1220 */
|
||||
PVOID glSectionInfo; /* be0/1228 */
|
||||
PVOID glSection; /* be4/1230 */
|
||||
|
@ -386,8 +416,8 @@ typedef struct _TEB
|
|||
PVOID glCurrentRC; /* bec/1240 */
|
||||
PVOID glContext; /* bf0/1248 */
|
||||
ULONG LastStatusValue; /* bf4/1250 */
|
||||
UNICODE_STRING StaticUnicodeString; /* bf8/1258 used by advapi32 */
|
||||
WCHAR StaticUnicodeBuffer[261]; /* c00/1268 used by advapi32 */
|
||||
UNICODE_STRING StaticUnicodeString; /* bf8/1258 */
|
||||
WCHAR StaticUnicodeBuffer[261]; /* c00/1268 */
|
||||
PVOID DeallocationStack; /* e0c/1478 */
|
||||
PVOID TlsSlots[64]; /* e10/1480 */
|
||||
LIST_ENTRY TlsLinks; /* f10/1680 */
|
||||
|
@ -417,6 +447,21 @@ typedef struct _TEB
|
|||
PVOID CurrentTransactionHandle; /* fac/17b8 */
|
||||
TEB_ACTIVE_FRAME *ActiveFrame; /* fb0/17c0 */
|
||||
PVOID *FlsSlots; /* fb4/17c8 */
|
||||
PVOID PreferredLanguages; /* fb8/17d0 */
|
||||
PVOID UserPrefLanguages; /* fbc/17d8 */
|
||||
PVOID MergedPrefLanguages; /* fc0/17e0 */
|
||||
ULONG MuiImpersonation; /* fc4/17e8 */
|
||||
USHORT CrossTebFlags; /* fc8/17ec */
|
||||
USHORT SameTebFlags; /* fca/17ee */
|
||||
PVOID TxnScopeEnterCallback; /* fcc/17f0 */
|
||||
PVOID TxnScopeExitCallback; /* fd0/17f8 */
|
||||
PVOID TxnScopeContext; /* fd4/1800 */
|
||||
ULONG LockCount; /* fd8/1808 */
|
||||
LONG WowTebOffset; /* fdc/180c */
|
||||
PVOID ResourceRetValue; /* fe0/1810 */
|
||||
PVOID ReservedForWdf; /* fe4/1818 */
|
||||
ULONGLONG ReservedForCrt; /* fe8/1820 */
|
||||
GUID EffectiveContainerId; /* ff0/1828 */
|
||||
} TEB, *PTEB;
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue