mirror of
https://github.com/reactos/reactos.git
synced 2024-10-04 08:25:53 +00:00
Fixed ANSI <--> Unicode conversions
svn path=/trunk/; revision=1065
This commit is contained in:
parent
6088637c5e
commit
ef5f880bac
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
/* $Id: event.c,v 1.7 2000/03/16 21:50:11 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/synch/event.c
|
||||
|
@ -10,7 +11,6 @@
|
|||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <kernel32/kernel32.h>
|
||||
|
@ -45,11 +45,15 @@ WINBOOL STDCALL ResetEvent(HANDLE hEvent)
|
|||
|
||||
|
||||
|
||||
HANDLE STDCALL CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
WINBOOL bManualReset,
|
||||
WINBOOL bInitialState,
|
||||
LPCWSTR lpName)
|
||||
{
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateEventW (
|
||||
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
WINBOOL bManualReset,
|
||||
WINBOOL bInitialState,
|
||||
LPCWSTR lpName
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
HANDLE hEvent;
|
||||
UNICODE_STRING EventNameString;
|
||||
|
@ -57,15 +61,15 @@ HANDLE STDCALL CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
|
|||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
if (lpName != NULL)
|
||||
{
|
||||
{
|
||||
PtrObjectAttributes = &ObjectAttributes;
|
||||
ObjectAttributes.Attributes = 0;
|
||||
if (lpEventAttributes != NULL)
|
||||
if (lpEventAttributes != NULL)
|
||||
{
|
||||
ObjectAttributes.SecurityDescriptor =
|
||||
lpEventAttributes->lpSecurityDescriptor;
|
||||
if ( lpEventAttributes->bInheritHandle == TRUE )
|
||||
ObjectAttributes.Attributes |= OBJ_INHERIT;
|
||||
ObjectAttributes.Attributes |= OBJ_INHERIT;
|
||||
}
|
||||
|
||||
EventNameString.Buffer = (WCHAR *)lpName;
|
||||
|
@ -76,7 +80,7 @@ HANDLE STDCALL CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
|
|||
else
|
||||
{
|
||||
PtrObjectAttributes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT( "Calling NtCreateEvent\n" );
|
||||
errCode = NtCreateEvent(&hEvent,
|
||||
|
@ -85,23 +89,23 @@ HANDLE STDCALL CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
|
|||
bManualReset,
|
||||
bInitialState);
|
||||
DPRINT( "Called\n" );
|
||||
if (!NT_SUCCESS(errCode))
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
SetLastError(RtlNtStatusToDosError(errCode));
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
return hEvent;
|
||||
}
|
||||
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
OpenEventW(
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCWSTR lpName
|
||||
)
|
||||
OpenEventW (
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCWSTR lpName
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING EventNameString;
|
||||
|
@ -110,86 +114,105 @@ OpenEventW(
|
|||
|
||||
if(lpName == NULL) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ObjectAttributes.Attributes = 0;
|
||||
ObjectAttributes.SecurityDescriptor = NULL;
|
||||
ObjectAttributes.SecurityDescriptor = NULL;
|
||||
EventNameString.Buffer = (WCHAR *)lpName;
|
||||
EventNameString.Length = lstrlenW(lpName)*sizeof(WCHAR);
|
||||
EventNameString.MaximumLength = EventNameString.Length;
|
||||
ObjectAttributes.ObjectName = &EventNameString;
|
||||
|
||||
|
||||
if (bInheritHandle == TRUE )
|
||||
ObjectAttributes.Attributes |= OBJ_INHERIT;
|
||||
|
||||
|
||||
errCode = NtOpenEvent(hEvent,dwDesiredAccess,&ObjectAttributes);
|
||||
if ( !NT_SUCCESS(errCode) ) {
|
||||
errCode = NtOpenEvent(hEvent,dwDesiredAccess,&ObjectAttributes);
|
||||
if ( !NT_SUCCESS(errCode) ) {
|
||||
SetLastError(RtlNtStatusToDosError(errCode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return hEvent;
|
||||
}
|
||||
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateEventA(
|
||||
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
WINBOOL bManualReset,
|
||||
WINBOOL bInitialState,
|
||||
LPCSTR lpName
|
||||
)
|
||||
{
|
||||
int i;
|
||||
WCHAR EventNameW[MAX_PATH];
|
||||
i = 0;
|
||||
if( lpName )
|
||||
while ((*lpName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
EventNameW[i] = *lpName;
|
||||
lpName++;
|
||||
i++;
|
||||
}
|
||||
EventNameW[i] = 0;
|
||||
|
||||
return CreateEventW( lpEventAttributes, bManualReset, bInitialState, lpName ? EventNameW : 0 );
|
||||
CreateEventA (
|
||||
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
WINBOOL bManualReset,
|
||||
WINBOOL bInitialState,
|
||||
LPCSTR lpName
|
||||
)
|
||||
{
|
||||
UNICODE_STRING EventNameU;
|
||||
ANSI_STRING EventName;
|
||||
HANDLE EventHandle;
|
||||
|
||||
RtlInitUnicodeString (&EventNameU, NULL);
|
||||
|
||||
if (lpName)
|
||||
{
|
||||
RtlInitAnsiString (&EventName,
|
||||
(LPSTR)lpName);
|
||||
RtlAnsiStringToUnicodeString (&EventNameU,
|
||||
&EventName,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
EventHandle = CreateEventW (lpEventAttributes,
|
||||
bManualReset,
|
||||
bInitialState,
|
||||
EventNameU.Buffer);
|
||||
|
||||
if (lpName)
|
||||
RtlFreeUnicodeString (&EventNameU);
|
||||
|
||||
return EventHandle;
|
||||
}
|
||||
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
OpenEventA(
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCSTR lpName
|
||||
)
|
||||
OpenEventA (
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCSTR lpName
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
WCHAR EventNameW[MAX_PATH];
|
||||
|
||||
|
||||
|
||||
i = 0;
|
||||
while ((*lpName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
EventNameW[i] = *lpName;
|
||||
lpName++;
|
||||
i++;
|
||||
}
|
||||
EventNameW[i] = 0;
|
||||
|
||||
|
||||
return OpenEventW(dwDesiredAccess,bInheritHandle,EventNameW);
|
||||
UNICODE_STRING EventNameU;
|
||||
ANSI_STRING EventName;
|
||||
HANDLE EventHandle;
|
||||
|
||||
RtlInitUnicodeString (&EventNameU, NULL);
|
||||
|
||||
if (lpName)
|
||||
{
|
||||
RtlInitAnsiString (&EventName,
|
||||
(LPSTR)lpName);
|
||||
RtlAnsiStringToUnicodeString (&EventNameU,
|
||||
&EventName,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
EventHandle = OpenEventW (dwDesiredAccess,
|
||||
bInheritHandle,
|
||||
EventNameU.Buffer);
|
||||
|
||||
if (lpName)
|
||||
RtlFreeUnicodeString (&EventNameU);
|
||||
|
||||
return EventHandle;
|
||||
}
|
||||
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
PulseEvent(
|
||||
HANDLE hEvent
|
||||
)
|
||||
PulseEvent (
|
||||
HANDLE hEvent
|
||||
)
|
||||
{
|
||||
ULONG Count;
|
||||
NTSTATUS errCode;
|
||||
|
@ -200,3 +223,5 @@ PulseEvent(
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
/* $Id: timer.c,v 1.4 2000/03/16 21:50:11 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: lib/kernel32/mem/timer.c
|
||||
|
@ -13,11 +14,12 @@
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
|
||||
HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes,
|
||||
WINBOOL bManualReset,
|
||||
LPWSTR lpTimerName)
|
||||
HANDLE
|
||||
CreateWaitableTimerW (
|
||||
LPSECURITY_ATTRIBUTES lpTimerAttributes,
|
||||
WINBOOL bManualReset,
|
||||
LPWSTR lpTimerName
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
HANDLE TimerHandle;
|
||||
|
@ -47,32 +49,39 @@ HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes,
|
|||
}
|
||||
|
||||
|
||||
HANDLE CreateWaitableTimerA(
|
||||
LPSECURITY_ATTRIBUTES lpTimerAttributes,
|
||||
WINBOOL bManualReset,
|
||||
LPCSTR lpTimerName
|
||||
)
|
||||
HANDLE
|
||||
CreateWaitableTimerA (
|
||||
LPSECURITY_ATTRIBUTES lpTimerAttributes,
|
||||
WINBOOL bManualReset,
|
||||
LPCSTR lpTimerName
|
||||
)
|
||||
{
|
||||
WCHAR NameW[MAX_PATH];
|
||||
ULONG i = 0;
|
||||
UNICODE_STRING TimerNameU;
|
||||
ANSI_STRING TimerName;
|
||||
HANDLE TimerHandle;
|
||||
|
||||
while ((*lpTimerName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
NameW[i] = *lpTimerName;
|
||||
lpTimerName++;
|
||||
i++;
|
||||
}
|
||||
NameW[i] = 0;
|
||||
return CreateWaitableTimerW(lpTimerAttributes,
|
||||
bManualReset,
|
||||
NameW);
|
||||
RtlInitAnsiString (&TimerName,
|
||||
(LPSTR)lpTimerName);
|
||||
RtlAnsiStringToUnicodeString (&TimerNameU,
|
||||
&TimerName,
|
||||
TRUE);
|
||||
|
||||
TimerHandle = CreateWaitableTimerW (lpTimerAttributes,
|
||||
bManualReset,
|
||||
TimerNameU.Buffer);
|
||||
|
||||
RtlFreeUnicodeString (&TimerNameU);
|
||||
|
||||
return TimerHandle;
|
||||
}
|
||||
|
||||
HANDLE OpenWaitableTimerW(
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCWSTR lpTimerName
|
||||
)
|
||||
|
||||
HANDLE
|
||||
OpenWaitableTimerW (
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCWSTR lpTimerName
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
|
||||
|
@ -83,10 +92,9 @@ HANDLE OpenWaitableTimerW(
|
|||
|
||||
if ( bInheritHandle )
|
||||
Attributes = OBJ_INHERIT;
|
||||
|
||||
|
||||
RtlInitUnicodeString(&UnicodeName, lpTimerName);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
RtlInitUnicodeString(&UnicodeName, lpTimerName);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&UnicodeName,
|
||||
Attributes,
|
||||
NULL,
|
||||
|
@ -96,38 +104,46 @@ HANDLE OpenWaitableTimerW(
|
|||
&TimerHandle,
|
||||
dwDesiredAccess,
|
||||
&ObjectAttributes
|
||||
);
|
||||
);
|
||||
|
||||
return TimerHandle;
|
||||
return TimerHandle;
|
||||
}
|
||||
|
||||
HANDLE OpenWaitableTimerA(
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCSTR lpTimerName
|
||||
)
|
||||
{
|
||||
WCHAR NameW[MAX_PATH];
|
||||
ULONG i = 0;
|
||||
|
||||
while ((*lpTimerName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
NameW[i] = *lpTimerName;
|
||||
lpTimerName++;
|
||||
i++;
|
||||
}
|
||||
NameW[i] = 0;
|
||||
return OpenWaitableTimerW(dwDesiredAccess, bInheritHandle,(LPCWSTR) NameW);
|
||||
HANDLE
|
||||
OpenWaitableTimerA (
|
||||
DWORD dwDesiredAccess,
|
||||
WINBOOL bInheritHandle,
|
||||
LPCSTR lpTimerName
|
||||
)
|
||||
{
|
||||
UNICODE_STRING TimerNameU;
|
||||
ANSI_STRING TimerName;
|
||||
HANDLE TimerHandle;
|
||||
|
||||
RtlInitAnsiString (&TimerName,
|
||||
(LPSTR)lpTimerName);
|
||||
RtlAnsiStringToUnicodeString (&TimerNameU,
|
||||
&TimerName,
|
||||
TRUE);
|
||||
|
||||
TimerHandle = OpenWaitableTimerW (dwDesiredAccess,
|
||||
bInheritHandle,
|
||||
TimerNameU.Buffer);
|
||||
|
||||
RtlFreeUnicodeString (&TimerNameU);
|
||||
|
||||
return TimerHandle;
|
||||
}
|
||||
|
||||
|
||||
WINBOOL SetWaitableTimer(
|
||||
HANDLE hTimer,
|
||||
LARGE_INTEGER *pDueTime,
|
||||
LONG lPeriod,
|
||||
PTIMERAPCROUTINE pfnCompletionRoutine,
|
||||
LPVOID lpArgToCompletionRoutine,
|
||||
WINBOOL fResume
|
||||
HANDLE hTimer,
|
||||
LARGE_INTEGER *pDueTime,
|
||||
LONG lPeriod,
|
||||
PTIMERAPCROUTINE pfnCompletionRoutine,
|
||||
LPVOID lpArgToCompletionRoutine,
|
||||
WINBOOL fResume
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
|
@ -141,7 +157,7 @@ WINBOOL SetWaitableTimer(
|
|||
SetLastError(RtlNtStatusToDosError(errCode));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WINBOOL CancelWaitableTimer(HANDLE hTimer)
|
||||
|
@ -157,6 +173,7 @@ WINBOOL CancelWaitableTimer(HANDLE hTimer)
|
|||
SetLastError(RtlNtStatusToDosError(errCode));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
/* $Id: wait.c,v 1.10 2000/03/16 21:50:11 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/synch/wait.c
|
||||
|
@ -14,31 +15,34 @@
|
|||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateSemaphoreA(
|
||||
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
|
||||
LONG lInitialCount,
|
||||
LONG lMaximumCount,
|
||||
LPCSTR lpName
|
||||
)
|
||||
CreateSemaphoreA (
|
||||
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
|
||||
LONG lInitialCount,
|
||||
LONG lMaximumCount,
|
||||
LPCSTR lpName
|
||||
)
|
||||
{
|
||||
WCHAR NameW[MAX_PATH];
|
||||
ULONG i = 0;
|
||||
UNICODE_STRING NameU;
|
||||
ANSI_STRING Name;
|
||||
HANDLE Handle;
|
||||
|
||||
while ((*lpName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
NameW[i] = *lpName;
|
||||
lpName++;
|
||||
i++;
|
||||
}
|
||||
NameW[i] = 0;
|
||||
return CreateSemaphoreW(
|
||||
lpSemaphoreAttributes,
|
||||
lInitialCount,
|
||||
lMaximumCount,
|
||||
NameW
|
||||
);
|
||||
RtlInitAnsiString (&Name,
|
||||
lpName);
|
||||
RtlAnsiStringToUnicodeString (&NameU,
|
||||
&Name,
|
||||
TRUE);
|
||||
|
||||
Handle = CreateSemaphoreW (lpSemaphoreAttributes,
|
||||
lInitialCount,
|
||||
lMaximumCount,
|
||||
NameU.Buffer);
|
||||
|
||||
RtlFreeUnicodeString (&NameU);
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateSemaphoreW(
|
||||
|
@ -89,37 +93,39 @@ CreateSemaphoreW(
|
|||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateMutexA(
|
||||
LPSECURITY_ATTRIBUTES lpMutexAttributes,
|
||||
WINBOOL bInitialOwner,
|
||||
LPCSTR lpName
|
||||
)
|
||||
CreateMutexA (
|
||||
LPSECURITY_ATTRIBUTES lpMutexAttributes,
|
||||
WINBOOL bInitialOwner,
|
||||
LPCSTR lpName
|
||||
)
|
||||
{
|
||||
WCHAR NameW[MAX_PATH];
|
||||
ULONG i = 0;
|
||||
UNICODE_STRING NameU;
|
||||
ANSI_STRING Name;
|
||||
HANDLE Handle;
|
||||
|
||||
while ((*lpName)!=0 && i < MAX_PATH)
|
||||
{
|
||||
NameW[i] = *lpName;
|
||||
lpName++;
|
||||
i++;
|
||||
}
|
||||
NameW[i] = 0;
|
||||
RtlInitAnsiString (&Name,
|
||||
lpName);
|
||||
RtlAnsiStringToUnicodeString (&NameU,
|
||||
&Name,
|
||||
TRUE);
|
||||
|
||||
return CreateMutexW(
|
||||
lpMutexAttributes,
|
||||
bInitialOwner,
|
||||
NameW
|
||||
);
|
||||
Handle = CreateMutexW (lpMutexAttributes,
|
||||
bInitialOwner,
|
||||
NameU.Buffer);
|
||||
|
||||
RtlFreeUnicodeString (&NameU);
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateMutexW(
|
||||
LPSECURITY_ATTRIBUTES lpMutexAttributes,
|
||||
WINBOOL bInitialOwner,
|
||||
LPCWSTR lpName
|
||||
)
|
||||
CreateMutexW (
|
||||
LPSECURITY_ATTRIBUTES lpMutexAttributes,
|
||||
WINBOOL bInitialOwner,
|
||||
LPCWSTR lpName
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS errCode;
|
||||
|
@ -156,19 +162,21 @@ CreateMutexW(
|
|||
}
|
||||
|
||||
|
||||
DWORD
|
||||
DWORD
|
||||
STDCALL
|
||||
WaitForSingleObject(HANDLE hHandle,
|
||||
DWORD dwMilliseconds)
|
||||
WaitForSingleObject (
|
||||
HANDLE hHandle,
|
||||
DWORD dwMilliseconds
|
||||
)
|
||||
{
|
||||
return WaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
|
||||
return WaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
WaitForSingleObjectEx(HANDLE hHandle,
|
||||
DWORD dwMilliseconds,
|
||||
DWORD dwMilliseconds,
|
||||
BOOL bAlertable)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
|
@ -205,7 +213,7 @@ WaitForSingleObjectEx(HANDLE hHandle,
|
|||
}
|
||||
|
||||
|
||||
DWORD
|
||||
DWORD
|
||||
STDCALL
|
||||
WaitForMultipleObjects(DWORD nCount,
|
||||
CONST HANDLE *lpHandles,
|
||||
|
@ -216,7 +224,7 @@ WaitForMultipleObjects(DWORD nCount,
|
|||
}
|
||||
|
||||
|
||||
DWORD
|
||||
DWORD
|
||||
STDCALL
|
||||
WaitForMultipleObjectsEx(DWORD nCount,
|
||||
CONST HANDLE *lpHandles,
|
||||
|
@ -238,7 +246,7 @@ WaitForMultipleObjectsEx(DWORD nCount,
|
|||
Time.QuadPart = -10000 * dwMilliseconds;
|
||||
TimePtr = &Time;
|
||||
}
|
||||
|
||||
|
||||
errCode = NtWaitForMultipleObjects (nCount,
|
||||
(PHANDLE)lpHandles,
|
||||
(CINT)bWaitAll,
|
||||
|
@ -262,4 +270,3 @@ WaitForMultipleObjectsEx(DWORD nCount,
|
|||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
|
Loading…
Reference in a new issue