mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 15:52:57 +00:00
Window classes/Atom fixes
svn path=/trunk/; revision=6881
This commit is contained in:
parent
b2c247faf1
commit
419d47d89f
5 changed files with 117 additions and 147 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: class.c,v 1.39 2003/11/11 20:28:21 gvg Exp $
|
/* $Id: class.c,v 1.40 2003/12/07 10:31:21 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS user32.dll
|
* PROJECT: ReactOS user32.dll
|
||||||
|
@ -353,21 +353,7 @@ GetClassNameW(
|
||||||
LPWSTR lpClassName,
|
LPWSTR lpClassName,
|
||||||
int nMaxCount)
|
int nMaxCount)
|
||||||
{
|
{
|
||||||
int result;
|
return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
|
||||||
LPWSTR ClassNameW;
|
|
||||||
|
|
||||||
if(!lpClassName)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ClassNameW = HEAP_alloc ( (nMaxCount+1) * sizeof(WCHAR) );
|
|
||||||
|
|
||||||
result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
|
|
||||||
|
|
||||||
RtlCopyMemory ( lpClassName, ClassNameW, result );
|
|
||||||
|
|
||||||
HEAP_free ( ClassNameW );
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: atom.c,v 1.7 2003/10/28 17:43:42 navaraf Exp $
|
/* $Id: atom.c,v 1.8 2003/12/07 10:31:21 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -578,6 +578,7 @@ RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
|
||||||
{
|
{
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PRTL_ATOM_ENTRY AtomEntry;
|
PRTL_ATOM_ENTRY AtomEntry;
|
||||||
|
WCHAR TempAtomName[12];
|
||||||
|
|
||||||
if (Atom == 0)
|
if (Atom == 0)
|
||||||
{
|
{
|
||||||
|
@ -596,10 +597,19 @@ RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
|
||||||
*PinCount = 1;
|
*PinCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0))
|
Length = swprintf(TempAtomName, L"#%lu", (ULONG)Atom);
|
||||||
|
|
||||||
|
if (NameLength != NULL)
|
||||||
{
|
{
|
||||||
Length = swprintf(AtomName, L"#%lu", (ULONG)Atom);
|
|
||||||
*NameLength = Length * sizeof(WCHAR);
|
*NameLength = Length * sizeof(WCHAR);
|
||||||
|
if (AtomName != NULL && *NameLength >= Length)
|
||||||
|
{
|
||||||
|
wcscpy(AtomName, TempAtomName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -629,17 +639,18 @@ RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
|
||||||
*PinCount = (ULONG)AtomEntry->Locked;
|
*PinCount = (ULONG)AtomEntry->Locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((AtomName != NULL) && (NameLength != NULL))
|
if (NameLength != NULL)
|
||||||
{
|
{
|
||||||
if (*NameLength < AtomEntry->Name.Length)
|
*NameLength = AtomEntry->Name.Length;
|
||||||
|
if (AtomName != NULL && *NameLength >= AtomEntry->Name.Length)
|
||||||
{
|
{
|
||||||
*NameLength = AtomEntry->Name.Length;
|
memcpy(AtomName, AtomEntry->Name.Buffer, AtomEntry->Name.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
RtlpUnlockAtomTable(AtomTable);
|
RtlpUnlockAtomTable(AtomTable);
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(AtomName, AtomEntry->Name.Buffer, AtomEntry->Name.Length);
|
|
||||||
*NameLength = AtomEntry->Name.Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlpUnlockAtomTable(AtomTable);
|
RtlpUnlockAtomTable(AtomTable);
|
||||||
|
|
|
@ -21,7 +21,7 @@ typedef struct _WNDCLASS_OBJECT
|
||||||
HCURSOR hCursor;
|
HCURSOR hCursor;
|
||||||
HBRUSH hbrBackground;
|
HBRUSH hbrBackground;
|
||||||
PUNICODE_STRING lpszMenuName;
|
PUNICODE_STRING lpszMenuName;
|
||||||
PUNICODE_STRING lpszClassName;
|
RTL_ATOM Atom;
|
||||||
HICON hIconSm;
|
HICON hIconSm;
|
||||||
BOOL Unicode;
|
BOOL Unicode;
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
|
@ -36,7 +36,7 @@ CleanupClassImpl(VOID);
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
||||||
LPWSTR ClassName);
|
LPCWSTR ClassName);
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
ClassReferenceClassByAtom(PWNDCLASS_OBJECT *Class,
|
ClassReferenceClassByAtom(PWNDCLASS_OBJECT *Class,
|
||||||
|
@ -44,7 +44,7 @@ ClassReferenceClassByAtom(PWNDCLASS_OBJECT *Class,
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
|
ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
|
||||||
LPWSTR ClassNameOrAtom);
|
LPCWSTR ClassNameOrAtom);
|
||||||
PWNDCLASS_OBJECT FASTCALL
|
PWNDCLASS_OBJECT FASTCALL
|
||||||
IntCreateClass(CONST WNDCLASSEXW *lpwcx,
|
IntCreateClass(CONST WNDCLASSEXW *lpwcx,
|
||||||
BOOL bUnicodeClass,
|
BOOL bUnicodeClass,
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: class.c,v 1.41 2003/11/24 16:15:00 gvg Exp $
|
/* $Id: class.c,v 1.42 2003/12/07 10:31:21 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -71,7 +71,7 @@ ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
|
||||||
{
|
{
|
||||||
Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
|
Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
|
||||||
|
|
||||||
if (Current->lpszClassName == (PUNICODE_STRING)(ULONG)Atom)
|
if (Current->Atom == Atom)
|
||||||
{
|
{
|
||||||
*Class = Current;
|
*Class = Current;
|
||||||
ObmReferenceObject(Current);
|
ObmReferenceObject(Current);
|
||||||
|
@ -88,7 +88,7 @@ ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
||||||
PWSTR ClassName)
|
LPCWSTR ClassName)
|
||||||
{
|
{
|
||||||
PWINSTATION_OBJECT WinStaObject;
|
PWINSTATION_OBJECT WinStaObject;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -111,7 +111,7 @@ ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
|
Status = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
|
||||||
ClassName,
|
(LPWSTR)ClassName,
|
||||||
&ClassAtom);
|
&ClassAtom);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -128,7 +128,7 @@ ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
|
ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
|
||||||
LPWSTR ClassNameOrAtom)
|
LPCWSTR ClassNameOrAtom)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -152,112 +152,85 @@ ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD STDCALL
|
DWORD STDCALL
|
||||||
NtUserGetClassInfo(HINSTANCE hInst,
|
NtUserGetClassInfo(HINSTANCE hInstance, LPCWSTR lpClassName,
|
||||||
LPCWSTR str,
|
LPWNDCLASSEXW lpWndClassEx, BOOL Ansi, DWORD unknown3)
|
||||||
LPWNDCLASSEXW wcex,
|
|
||||||
BOOL Ansi,
|
|
||||||
DWORD unknown3)
|
|
||||||
{
|
{
|
||||||
PWNDCLASS_OBJECT Class;
|
PWNDCLASS_OBJECT Class;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
Status = ClassReferenceClassByNameOrAtom(&Class,(LPWSTR)str);
|
|
||||||
if (!NT_SUCCESS(Status))
|
Status = ClassReferenceClassByNameOrAtom(&Class, lpClassName);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
SetLastNtError(Status);
|
{
|
||||||
return 0;
|
SetLastNtError(Status);
|
||||||
}
|
return 0;
|
||||||
wcex->cbSize = sizeof(LPWNDCLASSEXW);
|
}
|
||||||
wcex->style = Class->style;
|
lpWndClassEx->cbSize = sizeof(LPWNDCLASSEXW);
|
||||||
if (Ansi)
|
lpWndClassEx->style = Class->style;
|
||||||
{
|
if (Ansi)
|
||||||
wcex->lpfnWndProc = Class->lpfnWndProcA;
|
lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
|
||||||
}
|
else
|
||||||
else
|
lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
|
||||||
{
|
lpWndClassEx->cbClsExtra = Class->cbClsExtra;
|
||||||
wcex->lpfnWndProc = Class->lpfnWndProcW;
|
lpWndClassEx->cbWndExtra = Class->cbWndExtra;
|
||||||
}
|
lpWndClassEx->hInstance = Class->hInstance;
|
||||||
wcex->cbClsExtra = Class->cbClsExtra;
|
lpWndClassEx->hIcon = Class->hIcon;
|
||||||
wcex->cbWndExtra = Class->cbWndExtra;
|
lpWndClassEx->hCursor = Class->hCursor;
|
||||||
wcex->hInstance = Class->hInstance;
|
lpWndClassEx->hbrBackground = Class->hbrBackground;
|
||||||
wcex->hIcon = Class->hIcon;
|
if (Class->lpszMenuName)
|
||||||
wcex->hCursor = Class->hCursor;
|
{
|
||||||
wcex->hbrBackground = Class->hbrBackground;
|
if (!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
|
||||||
if(Class->lpszMenuName)
|
RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, Class->lpszMenuName);
|
||||||
{
|
|
||||||
if(!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
|
|
||||||
RtlCopyUnicodeString((PUNICODE_STRING)wcex->lpszMenuName, Class->lpszMenuName);
|
|
||||||
else
|
else
|
||||||
wcex->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
|
lpWndClassEx->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wcex->lpszMenuName = (LPCWSTR)NULL;
|
lpWndClassEx->lpszMenuName = (LPCWSTR)NULL;
|
||||||
if(Class->lpszClassName)
|
lpWndClassEx->lpszClassName = lpClassName;
|
||||||
{
|
lpWndClassEx->hIconSm = Class->hIconSm;
|
||||||
if(!IS_ATOM((LPCWSTR)Class->lpszClassName))
|
|
||||||
RtlCopyUnicodeString((PUNICODE_STRING)wcex->lpszClassName, Class->lpszClassName);
|
return Class->Atom;
|
||||||
else
|
|
||||||
wcex->lpszClassName = (LPCWSTR)Class->lpszClassName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
wcex->lpszClassName = (LPCWSTR)NULL;
|
|
||||||
wcex->hIconSm = Class->hIconSm;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG FASTCALL
|
ULONG FASTCALL
|
||||||
IntGetClassName(struct _WINDOW_OBJECT *WindowObject,
|
IntGetClassName(struct _WINDOW_OBJECT *WindowObject, LPWSTR lpClassName,
|
||||||
LPWSTR lpClassName,
|
ULONG nMaxCount)
|
||||||
ULONG nMaxCount)
|
|
||||||
{
|
{
|
||||||
ULONG length;
|
ULONG Length;
|
||||||
LPWSTR name;
|
LPWSTR Name;
|
||||||
BOOL free;
|
PWINSTATION_OBJECT WinStaObject;
|
||||||
PWINSTATION_OBJECT WinStaObject;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
if (IS_ATOM(WindowObject->Class->lpszClassName))
|
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
|
||||||
{
|
KernelMode, 0, &WinStaObject);
|
||||||
DPRINT("About to open window station handle (0x%X)\n",
|
if (!NT_SUCCESS(Status))
|
||||||
PROCESS_WINDOW_STATION());
|
{
|
||||||
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
|
DPRINT("Validation of window station handle (0x%X) failed\n",
|
||||||
KernelMode,
|
PROCESS_WINDOW_STATION());
|
||||||
0,
|
return 0;
|
||||||
&WinStaObject);
|
}
|
||||||
if (!NT_SUCCESS(Status))
|
Length = 0;
|
||||||
{
|
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
|
||||||
DPRINT("Validation of window station handle (0x%X) failed\n",
|
WindowObject->Class->Atom, NULL, NULL, Name, &Length);
|
||||||
PROCESS_WINDOW_STATION());
|
Name = ExAllocatePool(NonPagedPool, Length + sizeof(UNICODE_NULL));
|
||||||
return((RTL_ATOM)0);
|
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
|
||||||
}
|
WindowObject->Class->Atom, NULL, NULL, Name, &Length);
|
||||||
length = 0;
|
if (!NT_SUCCESS(Status))
|
||||||
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
|
{
|
||||||
name = ExAllocatePool(PagedPool,length+sizeof(WCHAR));
|
DPRINT("IntGetClassName: RtlQueryAtomInAtomTable failed\n");
|
||||||
free = TRUE;
|
return 0;
|
||||||
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
|
}
|
||||||
if (!NT_SUCCESS(Status))
|
Length /= sizeof(WCHAR);
|
||||||
{
|
if (Length > nMaxCount)
|
||||||
DPRINT("Validation of window station handle (0x%X) failed\n",
|
{
|
||||||
PROCESS_WINDOW_STATION());
|
Length = nMaxCount;
|
||||||
return((RTL_ATOM)0);
|
}
|
||||||
}
|
wcsncpy(lpClassName, Name, Length);
|
||||||
ObDereferenceObject(WinStaObject);
|
/* FIXME: Check buffer size before doing this! */
|
||||||
}
|
*(lpClassName + Length) = 0;
|
||||||
else
|
ExFreePool(Name);
|
||||||
{
|
ObDereferenceObject(WinStaObject);
|
||||||
name = WindowObject->Class->lpszClassName->Buffer;
|
|
||||||
length = WindowObject->Class->lpszClassName->Length / sizeof(WCHAR);
|
return Length;
|
||||||
free = FALSE;
|
|
||||||
}
|
|
||||||
if (length > nMaxCount)
|
|
||||||
{
|
|
||||||
length = nMaxCount;
|
|
||||||
}
|
|
||||||
*(lpClassName+length) = 0;
|
|
||||||
wcsncpy(lpClassName,name,length);
|
|
||||||
if (free)
|
|
||||||
{
|
|
||||||
ExFreePool(name);
|
|
||||||
}
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD STDCALL
|
DWORD STDCALL
|
||||||
|
@ -266,18 +239,18 @@ NtUserGetClassName (
|
||||||
LPWSTR lpClassName,
|
LPWSTR lpClassName,
|
||||||
ULONG nMaxCount)
|
ULONG nMaxCount)
|
||||||
{
|
{
|
||||||
PWINDOW_OBJECT WindowObject;
|
PWINDOW_OBJECT WindowObject;
|
||||||
LONG Ret;
|
LONG Length;
|
||||||
|
|
||||||
WindowObject = IntGetWindowObject(hWnd);
|
WindowObject = IntGetWindowObject(hWnd);
|
||||||
if (WindowObject == NULL)
|
if (WindowObject == NULL)
|
||||||
{
|
{
|
||||||
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Ret = IntGetClassName(WindowObject, lpClassName, nMaxCount);
|
Length = IntGetClassName(WindowObject, lpClassName, nMaxCount);
|
||||||
IntReleaseWindowObject(WindowObject);
|
IntReleaseWindowObject(WindowObject);
|
||||||
return(Ret);
|
return Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD STDCALL
|
DWORD STDCALL
|
||||||
|
@ -326,7 +299,7 @@ IntCreateClass(CONST WNDCLASSEXW *lpwcx,
|
||||||
ClassObject->hbrBackground = lpwcx->hbrBackground;
|
ClassObject->hbrBackground = lpwcx->hbrBackground;
|
||||||
ClassObject->Unicode = bUnicodeClass;
|
ClassObject->Unicode = bUnicodeClass;
|
||||||
ClassObject->hIconSm = lpwcx->hIconSm;
|
ClassObject->hIconSm = lpwcx->hIconSm;
|
||||||
ClassObject->lpszClassName = (PUNICODE_STRING)(ULONG)Atom;
|
ClassObject->Atom = Atom;
|
||||||
if (wpExtra == 0) {
|
if (wpExtra == 0) {
|
||||||
if (bUnicodeClass)
|
if (bUnicodeClass)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: window.c,v 1.150 2003/12/02 19:58:54 navaraf Exp $
|
/* $Id: window.c,v 1.151 2003/12/07 10:31:22 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -3106,7 +3106,7 @@ static BOOL IsStaticClass(PWINDOW_OBJECT Window)
|
||||||
BOOL rc = FALSE;
|
BOOL rc = FALSE;
|
||||||
|
|
||||||
ASSERT(0 != Window->Class);
|
ASSERT(0 != Window->Class);
|
||||||
ASSERT(0 != Window->Class->lpszClassName);
|
ASSERT(0 != Window->Class->Atom);
|
||||||
|
|
||||||
DbgPrint("FIXME: Update IsStatic to really check if a window is a static\n");
|
DbgPrint("FIXME: Update IsStatic to really check if a window is a static\n");
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue