mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- Remove ROSRTL. The era is over. Thanks to Filip for his help during the last month.
svn path=/trunk/; revision=16731
This commit is contained in:
parent
1e8c8e3fe6
commit
f3622d33aa
32 changed files with 272 additions and 1904 deletions
|
@ -1,7 +1,7 @@
|
||||||
#include <roscfg.h>
|
#include <roscfg.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <rosrtl/recmutex.h>
|
#include <../recmutex/recmutex.h>
|
||||||
#include <roscfg.h>
|
#include <roscfg.h>
|
||||||
#include <tcpip.h>
|
#include <tcpip.h>
|
||||||
#include <loopback.h>
|
#include <loopback.h>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <rosrtl/recmutex.h>
|
#include "recmutex.h"
|
||||||
|
|
||||||
VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
|
VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
|
||||||
RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
|
RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
|
|
@ -8,7 +8,6 @@
|
||||||
<library>ip</library>
|
<library>ip</library>
|
||||||
<library>oskittcp</library>
|
<library>oskittcp</library>
|
||||||
<library>ndis</library>
|
<library>ndis</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
|
@ -18,6 +17,9 @@
|
||||||
<directory name="datalink">
|
<directory name="datalink">
|
||||||
<file>lan.c</file>
|
<file>lan.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
|
<directory name="recmutex">
|
||||||
|
<file>recmutex.c</file>
|
||||||
|
</directory>
|
||||||
<directory name="tcpip">
|
<directory name="tcpip">
|
||||||
<file>buffer.c</file>
|
<file>buffer.c</file>
|
||||||
<file>bug.c</file>
|
<file>bug.c</file>
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosCreateUserThread
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
IN BOOLEAN CreateSuspended,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL,
|
|
||||||
IN PVOID StartAddress,
|
|
||||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
|
||||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
IN ULONG_PTR * Parameters
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS CDECL RtlRosCreateUserThreadVa
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
IN BOOLEAN CreateSuspended,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL,
|
|
||||||
IN PVOID StartAddress,
|
|
||||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
|
||||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
...
|
|
||||||
);
|
|
||||||
|
|
||||||
__declspec(noreturn) VOID NTAPI RtlRosExitUserThread
|
|
||||||
(
|
|
||||||
IN NTSTATUS Status
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosInitializeContext
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
OUT PCONTEXT ThreadContext,
|
|
||||||
IN PVOID ThreadStartAddress,
|
|
||||||
IN PINITIAL_TEB InitialTeb,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
IN ULONG_PTR *Parameters
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosCreateStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
OUT PINITIAL_TEB InitialTeb,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosDeleteStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN PINITIAL_TEB InitialTeb
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosFreeUserThreadStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN HANDLE ThreadHandle
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosSwitchStackForExit
|
|
||||||
(
|
|
||||||
IN PVOID StackBase,
|
|
||||||
IN SIZE_T StackSize,
|
|
||||||
IN VOID (NTAPI * ExitRoutine)(ULONG_PTR Parameter),
|
|
||||||
IN ULONG_PTR Parameter
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Private functions - for ROSRTL internal use only */
|
|
||||||
NTSTATUS NTAPI RtlpRosGetStackLimits
|
|
||||||
(
|
|
||||||
IN PINITIAL_TEB InitialTeb,
|
|
||||||
OUT PVOID * StackBase,
|
|
||||||
OUT PVOID * StackLimit
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlpRosValidateLinearUserStack
|
|
||||||
(
|
|
||||||
IN PVOID StackBase,
|
|
||||||
IN PVOID StackLimit,
|
|
||||||
IN BOOLEAN Direction
|
|
||||||
);
|
|
||||||
|
|
||||||
#define RtlpRosValidateTopDownUserStack(__B__, __L__) \
|
|
||||||
(RtlpRosValidateLinearUserStack((__B__), (__L__), FALSE))
|
|
||||||
|
|
||||||
#define RtlpRosValidateDownTopUserStack(__B__, __L__) \
|
|
||||||
(RtlpRosValidateLinearUserStack((__B__), (__L__), TRUE))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -214,9 +214,6 @@
|
||||||
<directory name="riched20">
|
<directory name="riched20">
|
||||||
<xi:include href="riched20/riched20.xml" />
|
<xi:include href="riched20/riched20.xml" />
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="rosrtl">
|
|
||||||
<xi:include href="rosrtl/rosrtl.xml" />
|
|
||||||
</directory>
|
|
||||||
<directory name="rossym">
|
<directory name="rossym">
|
||||||
<xi:include href="rossym/rossym.xml" />
|
<xi:include href="rossym/rossym.xml" />
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<define name="ADNS_JGAA_WIN32" />
|
<define name="ADNS_JGAA_WIN32" />
|
||||||
<define name="__USE_W32API" />
|
<define name="__USE_W32API" />
|
||||||
<library>adns</library>
|
<library>adns</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<library>kernel32</library>
|
<library>kernel32</library>
|
||||||
<library>user32</library>
|
<library>user32</library>
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<define name="WINVER">0x0600</define>
|
<define name="WINVER">0x0600</define>
|
||||||
<define name="_WIN32_WINNT">0x0501</define>
|
<define name="_WIN32_WINNT">0x0501</define>
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>kernel32</library>
|
<library>kernel32</library>
|
||||||
<library>advapi32</library>
|
<library>advapi32</library>
|
||||||
<directory name="include">
|
<directory name="include">
|
||||||
|
|
|
@ -118,7 +118,6 @@
|
||||||
<define name="WINVER">0x0500</define>
|
<define name="WINVER">0x0500</define>
|
||||||
<library>kernel32_base</library>
|
<library>kernel32_base</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>intrlck</library>
|
<library>intrlck</library>
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<linkerflag>-lgcc</linkerflag>
|
<linkerflag>-lgcc</linkerflag>
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
<library>regtests</library>
|
<library>regtests</library>
|
||||||
<library>kernel32_base</library>
|
<library>kernel32_base</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<library>msvcrt</library>
|
<library>msvcrt</library>
|
||||||
<linkerflag>-lgcc</linkerflag>
|
<linkerflag>-lgcc</linkerflag>
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<define name="_WIN32_WINNT">0x0502</define>
|
<define name="_WIN32_WINNT">0x0502</define>
|
||||||
<define name="_NTOSKRNL_" />
|
<define name="_NTOSKRNL_" />
|
||||||
<library>rtl</library>
|
<library>rtl</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>intrlck</library>
|
<library>intrlck</library>
|
||||||
<library>string</library>
|
<library>string</library>
|
||||||
<linkerflag>-lgcc</linkerflag>
|
<linkerflag>-lgcc</linkerflag>
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* MakeSureDirectoryPathExistsExA
|
|
||||||
*
|
|
||||||
* If a dir is at the end and the path ends with a backslash, FileAtEnd
|
|
||||||
* is ignored. If the path doesn't end with a backslash, FileAtEnd is
|
|
||||||
* used to determine if the last part of the path is a file name or a
|
|
||||||
* directory.
|
|
||||||
*
|
|
||||||
* Path may be absolute or relative to current dir.
|
|
||||||
*/
|
|
||||||
BOOL STDCALL MakeSureDirectoryPathExistsExA(LPCSTR DirPath, BOOL FileAtEnd)
|
|
||||||
{
|
|
||||||
char Path[MAX_PATH];
|
|
||||||
char *SlashPos = Path;
|
|
||||||
char Slash;
|
|
||||||
BOOL bRes;
|
|
||||||
|
|
||||||
strcpy(Path, DirPath);
|
|
||||||
|
|
||||||
while((SlashPos=strpbrk(SlashPos+1,"\\/")))
|
|
||||||
{
|
|
||||||
Slash = *SlashPos;
|
|
||||||
*SlashPos = 0;
|
|
||||||
|
|
||||||
bRes = CreateDirectoryA(Path, NULL);
|
|
||||||
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*SlashPos = Slash;
|
|
||||||
|
|
||||||
if (*(SlashPos+1) == 0) return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FileAtEnd)
|
|
||||||
{
|
|
||||||
bRes = CreateDirectoryA(Path, NULL);
|
|
||||||
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* MakeSureDirectoryPathExistsExW
|
|
||||||
*
|
|
||||||
* If a dir is at the end and the path ends with a backslash, FileAtEnd
|
|
||||||
* is ignored. If the path doesn't end with a backslash, FileAtEnd is
|
|
||||||
* used to determine if the last part of the path is a file name or a
|
|
||||||
* directory.
|
|
||||||
*
|
|
||||||
* Path may be absolute or relative to current dir.
|
|
||||||
*/
|
|
||||||
BOOL STDCALL MakeSureDirectoryPathExistsExW(LPCWSTR DirPath, BOOL FileAtEnd)
|
|
||||||
{
|
|
||||||
WCHAR Path[MAX_PATH];
|
|
||||||
WCHAR *SlashPos = Path;
|
|
||||||
WCHAR Slash;
|
|
||||||
BOOL bRes;
|
|
||||||
|
|
||||||
wcscpy(Path, DirPath);
|
|
||||||
|
|
||||||
while((SlashPos=wcspbrk(SlashPos+1,L"\\/")))
|
|
||||||
{
|
|
||||||
Slash = *SlashPos;
|
|
||||||
*SlashPos = 0;
|
|
||||||
|
|
||||||
bRes = CreateDirectoryW(Path, NULL);
|
|
||||||
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*SlashPos = Slash;
|
|
||||||
|
|
||||||
if (*(SlashPos+1) == 0) return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FileAtEnd)
|
|
||||||
{
|
|
||||||
bRes = CreateDirectoryW(Path, NULL);
|
|
||||||
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#include <ddk/ntifs.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <rosrtl/sparse.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to convert a file to a sparse file
|
|
||||||
*
|
|
||||||
* IN HANDLE hFile -> Handle to the file to be converted
|
|
||||||
*
|
|
||||||
* Returns TRUE on success.
|
|
||||||
* Returns FALSE on failure, use GetLastError() to get extended error information.
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
STDCALL
|
|
||||||
SetFileSparse(HANDLE hFile)
|
|
||||||
{
|
|
||||||
DWORD BytesRet;
|
|
||||||
return DeviceIoControl(hFile,
|
|
||||||
FSCTL_SET_SPARSE,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&BytesRet,
|
|
||||||
NULL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to fill a specified range of a file with zeroes.
|
|
||||||
*
|
|
||||||
* IN HANDLE hFile -> Handle to the file.
|
|
||||||
* IN PLARGE_INTEGER pliFileOffset -> Points to a LARGE_INTEGER structure that indicates the file offset of the start of the range in bytes.
|
|
||||||
* IN PLARGE_INTEGER pliBeyondFinalZero -> Points to a LARGE_INTEGER structure that indicates the the offset to the first byte beyond the last zeroed byte.
|
|
||||||
*
|
|
||||||
* Returns TRUE on success.
|
|
||||||
* Returns FALSE on failure, use GetLastError() to get extended error information.
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
STDCALL
|
|
||||||
ZeroFileData(HANDLE hFile,
|
|
||||||
PLARGE_INTEGER pliFileOffset,
|
|
||||||
PLARGE_INTEGER pliBeyondFinalZero)
|
|
||||||
{
|
|
||||||
DWORD BytesRet;
|
|
||||||
FILE_ZERO_DATA_INFORMATION fzdi;
|
|
||||||
|
|
||||||
if(!pliFileOffset || !pliBeyondFinalZero)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
fzdi.FileOffset = *pliFileOffset;
|
|
||||||
fzdi.BeyondFinalZero = *pliBeyondFinalZero;
|
|
||||||
|
|
||||||
return DeviceIoControl(hFile,
|
|
||||||
FSCTL_SET_ZERO_DATA,
|
|
||||||
&fzdi,
|
|
||||||
sizeof(FILE_ZERO_DATA_INFORMATION),
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&BytesRet,
|
|
||||||
NULL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to determine the allocated ranges of a sparse file
|
|
||||||
*
|
|
||||||
* IN HANDLE hFile -> Handle to the file.
|
|
||||||
* IN PLARGE_INTEGER pliFileOffset -> Points to a LARGE_INTEGER structure that indicates the portion of the file to search for allocated ranges.
|
|
||||||
* IN PLARGE_INTEGER pliLength -> Points to a LARGE_INTEGER structure that indicates it's size.
|
|
||||||
* OUT PFILE_ALLOCATED_RANGE_BUFFER lpAllocatedRanges -> Points to a buffer that receives an array of FILE_ALLOCATED_RANGE_BUFFER structures.
|
|
||||||
* IN DWORD dwBufferSize -> Size of the output buffer.
|
|
||||||
*
|
|
||||||
* Returns a nonzero value on success.
|
|
||||||
* Returns zero on failure, use GetLastError() to get extended error information.
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
STDCALL
|
|
||||||
QueryAllocatedFileRanges(HANDLE hFile,
|
|
||||||
PLARGE_INTEGER pliFileOffset,
|
|
||||||
PLARGE_INTEGER pliLength,
|
|
||||||
PFILE_ALLOCATED_RANGE_BUFFER lpAllocatedRanges,
|
|
||||||
DWORD dwBufferSize)
|
|
||||||
{
|
|
||||||
DWORD BytesRet;
|
|
||||||
FILE_ALLOCATED_RANGE_BUFFER farb;
|
|
||||||
|
|
||||||
if(!pliFileOffset || !pliLength || !lpAllocatedRanges || !dwBufferSize)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
farb.FileOffset = *pliFileOffset;
|
|
||||||
farb.Length = *pliLength;
|
|
||||||
|
|
||||||
if(DeviceIoControl(hFile,
|
|
||||||
FSCTL_QUERY_ALLOCATED_RANGES,
|
|
||||||
&farb,
|
|
||||||
sizeof(FILE_ALLOCATED_RANGE_BUFFER),
|
|
||||||
lpAllocatedRanges,
|
|
||||||
dwBufferSize,
|
|
||||||
&BytesRet,
|
|
||||||
NULL) != 0)
|
|
||||||
{
|
|
||||||
return BytesRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,148 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <rosrtl/devmode.h>
|
|
||||||
|
|
||||||
#define SIZEOF_DEVMODEA_300 124
|
|
||||||
#define SIZEOF_DEVMODEA_400 148
|
|
||||||
#define SIZEOF_DEVMODEA_500 156
|
|
||||||
#define SIZEOF_DEVMODEW_300 188
|
|
||||||
#define SIZEOF_DEVMODEW_400 212
|
|
||||||
#define SIZEOF_DEVMODEW_500 220
|
|
||||||
|
|
||||||
void
|
|
||||||
RosRtlDevModeA2W ( LPDEVMODEW pW, const LPDEVMODEA pA )
|
|
||||||
{
|
|
||||||
#define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, (LPSTR)pA->f, len, pW->f, len )
|
|
||||||
#define COPYN(f) pW->f = pA->f
|
|
||||||
COPYS(dmDeviceName, CCHDEVICENAME );
|
|
||||||
COPYN(dmSpecVersion);
|
|
||||||
COPYN(dmDriverVersion);
|
|
||||||
switch ( pA->dmSize )
|
|
||||||
{
|
|
||||||
case SIZEOF_DEVMODEA_300:
|
|
||||||
pW->dmSize = SIZEOF_DEVMODEW_300;
|
|
||||||
break;
|
|
||||||
case SIZEOF_DEVMODEA_400:
|
|
||||||
pW->dmSize = SIZEOF_DEVMODEW_400;
|
|
||||||
break;
|
|
||||||
case SIZEOF_DEVMODEA_500:
|
|
||||||
default: /* FIXME what to do??? */
|
|
||||||
pW->dmSize = SIZEOF_DEVMODEW_500;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
COPYN(dmDriverExtra);
|
|
||||||
COPYN(dmFields);
|
|
||||||
COPYN(dmPosition.x);
|
|
||||||
COPYN(dmPosition.y);
|
|
||||||
COPYN(dmScale);
|
|
||||||
COPYN(dmCopies);
|
|
||||||
COPYN(dmDefaultSource);
|
|
||||||
COPYN(dmPrintQuality);
|
|
||||||
COPYN(dmColor);
|
|
||||||
COPYN(dmDuplex);
|
|
||||||
COPYN(dmYResolution);
|
|
||||||
COPYN(dmTTOption);
|
|
||||||
COPYN(dmCollate);
|
|
||||||
COPYS(dmFormName,CCHFORMNAME);
|
|
||||||
COPYN(dmLogPixels);
|
|
||||||
COPYN(dmBitsPerPel);
|
|
||||||
COPYN(dmPelsWidth);
|
|
||||||
COPYN(dmPelsHeight);
|
|
||||||
COPYN(dmDisplayFlags); // aka dmNup
|
|
||||||
COPYN(dmDisplayFrequency);
|
|
||||||
|
|
||||||
if ( pA->dmSize <= SIZEOF_DEVMODEA_300 )
|
|
||||||
return; // we're done with 0x300 fields
|
|
||||||
|
|
||||||
COPYN(dmICMMethod);
|
|
||||||
COPYN(dmICMIntent);
|
|
||||||
COPYN(dmMediaType);
|
|
||||||
COPYN(dmDitherType);
|
|
||||||
COPYN(dmReserved1);
|
|
||||||
COPYN(dmReserved2);
|
|
||||||
|
|
||||||
if ( pA->dmSize <= SIZEOF_DEVMODEA_400 )
|
|
||||||
return; // we're done with 0x400 fields
|
|
||||||
|
|
||||||
COPYN(dmPanningWidth);
|
|
||||||
COPYN(dmPanningHeight);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
#undef COPYN
|
|
||||||
#undef COPYS
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
RosRtlDevModeW2A( LPDEVMODEA pA, const LPDEVMODEW pW )
|
|
||||||
{
|
|
||||||
#define COPYS(f,len) WideCharToMultiByte( CP_THREAD_ACP, 0, pW->f, len, (LPSTR)pA->f, len, NULL, NULL )
|
|
||||||
#define COPYN(f) pA->f = pW->f
|
|
||||||
COPYS(dmDeviceName, CCHDEVICENAME );
|
|
||||||
COPYN(dmSpecVersion);
|
|
||||||
COPYN(dmDriverVersion);
|
|
||||||
switch ( pW->dmSize )
|
|
||||||
{
|
|
||||||
case SIZEOF_DEVMODEW_300:
|
|
||||||
pA->dmSize = SIZEOF_DEVMODEA_300;
|
|
||||||
break;
|
|
||||||
case SIZEOF_DEVMODEW_400:
|
|
||||||
pA->dmSize = SIZEOF_DEVMODEA_400;
|
|
||||||
break;
|
|
||||||
case SIZEOF_DEVMODEW_500:
|
|
||||||
default: /* FIXME what to do??? */
|
|
||||||
pA->dmSize = SIZEOF_DEVMODEA_500;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
COPYN(dmDriverExtra);
|
|
||||||
COPYN(dmFields);
|
|
||||||
COPYN(dmPosition.x);
|
|
||||||
COPYN(dmPosition.y);
|
|
||||||
COPYN(dmScale);
|
|
||||||
COPYN(dmCopies);
|
|
||||||
COPYN(dmDefaultSource);
|
|
||||||
COPYN(dmPrintQuality);
|
|
||||||
COPYN(dmColor);
|
|
||||||
COPYN(dmDuplex);
|
|
||||||
COPYN(dmYResolution);
|
|
||||||
COPYN(dmTTOption);
|
|
||||||
COPYN(dmCollate);
|
|
||||||
COPYS(dmFormName,CCHFORMNAME);
|
|
||||||
COPYN(dmLogPixels);
|
|
||||||
COPYN(dmBitsPerPel);
|
|
||||||
COPYN(dmPelsWidth);
|
|
||||||
COPYN(dmPelsHeight);
|
|
||||||
COPYN(dmDisplayFlags); // aka dmNup
|
|
||||||
COPYN(dmDisplayFrequency);
|
|
||||||
|
|
||||||
if ( pW->dmSize <= SIZEOF_DEVMODEW_300 )
|
|
||||||
return; // we're done with 0x300 fields
|
|
||||||
|
|
||||||
COPYN(dmICMMethod);
|
|
||||||
COPYN(dmICMIntent);
|
|
||||||
COPYN(dmMediaType);
|
|
||||||
COPYN(dmDitherType);
|
|
||||||
COPYN(dmReserved1);
|
|
||||||
COPYN(dmReserved2);
|
|
||||||
|
|
||||||
if ( pW->dmSize <= SIZEOF_DEVMODEW_400 )
|
|
||||||
return; // we're done with 0x400 fields
|
|
||||||
|
|
||||||
COPYN(dmPanningWidth);
|
|
||||||
COPYN(dmPanningHeight);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
#undef COPYN
|
|
||||||
#undef COPYS
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef SIZEOF_DEVMODEA_300
|
|
||||||
#undef SIZEOF_DEVMODEA_400
|
|
||||||
#undef SIZEOF_DEVMODEA_500
|
|
||||||
#undef SIZEOF_DEVMODEW_300
|
|
||||||
#undef SIZEOF_DEVMODEW_400
|
|
||||||
#undef SIZEOF_DEVMODEW_500
|
|
||||||
#endif
|
|
|
@ -1,55 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <rosrtl/logfont.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
RosRtlLogFontA2W ( LPLOGFONTW pW, const LOGFONTA *pA )
|
|
||||||
{
|
|
||||||
#define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, pA->f, len, pW->f, len )
|
|
||||||
#define COPYN(f) pW->f = pA->f
|
|
||||||
|
|
||||||
COPYN(lfHeight);
|
|
||||||
COPYN(lfWidth);
|
|
||||||
COPYN(lfEscapement);
|
|
||||||
COPYN(lfOrientation);
|
|
||||||
COPYN(lfWeight);
|
|
||||||
COPYN(lfItalic);
|
|
||||||
COPYN(lfUnderline);
|
|
||||||
COPYN(lfStrikeOut);
|
|
||||||
COPYN(lfCharSet);
|
|
||||||
COPYN(lfOutPrecision);
|
|
||||||
COPYN(lfClipPrecision);
|
|
||||||
COPYN(lfQuality);
|
|
||||||
COPYN(lfPitchAndFamily);
|
|
||||||
COPYS(lfFaceName,LF_FACESIZE);
|
|
||||||
|
|
||||||
#undef COPYN
|
|
||||||
#undef COPYS
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RosRtlLogFontW2A ( LPLOGFONTA pA, const LOGFONTW *pW )
|
|
||||||
{
|
|
||||||
#define COPYS(f,len) WideCharToMultiByte ( CP_THREAD_ACP, 0, pW->f, len, pA->f, len, NULL, NULL )
|
|
||||||
#define COPYN(f) pA->f = pW->f
|
|
||||||
|
|
||||||
COPYN(lfHeight);
|
|
||||||
COPYN(lfWidth);
|
|
||||||
COPYN(lfEscapement);
|
|
||||||
COPYN(lfOrientation);
|
|
||||||
COPYN(lfWeight);
|
|
||||||
COPYN(lfItalic);
|
|
||||||
COPYN(lfUnderline);
|
|
||||||
COPYN(lfStrikeOut);
|
|
||||||
COPYN(lfCharSet);
|
|
||||||
COPYN(lfOutPrecision);
|
|
||||||
COPYN(lfClipPrecision);
|
|
||||||
COPYN(lfQuality);
|
|
||||||
COPYN(lfPitchAndFamily);
|
|
||||||
COPYS(lfFaceName,LF_FACESIZE);
|
|
||||||
|
|
||||||
#undef COPYN
|
|
||||||
#undef COPYS
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,79 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
#include <rosrtl/string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility function to read a value from the registry more easily.
|
|
||||||
*
|
|
||||||
* IN PUNICODE_STRING KeyName -> Name of key to open
|
|
||||||
* IN PUNICODE_STRING ValueName -> Name of value to open
|
|
||||||
* OUT PUNICODE_STRING ReturnedValue -> String contained in registry
|
|
||||||
*
|
|
||||||
* Returns NTSTATUS
|
|
||||||
*/
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RosReadRegistryValue( PUNICODE_STRING KeyName,
|
|
||||||
PUNICODE_STRING ValueName,
|
|
||||||
PUNICODE_STRING ReturnedValue ) {
|
|
||||||
NTSTATUS Status;
|
|
||||||
HANDLE KeyHandle;
|
|
||||||
OBJECT_ATTRIBUTES KeyAttributes;
|
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
|
|
||||||
ULONG Length = 0;
|
|
||||||
ULONG ResLength = 0;
|
|
||||||
UNICODE_STRING Temp;
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL, NULL);
|
|
||||||
Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
|
|
||||||
if( !NT_SUCCESS(Status) ) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&ResLength);
|
|
||||||
|
|
||||||
if( Status != STATUS_BUFFER_TOO_SMALL ) {
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResLength += sizeof( *KeyValuePartialInfo );
|
|
||||||
KeyValuePartialInfo =
|
|
||||||
RtlAllocateHeap(GetProcessHeap(), 0, ResLength);
|
|
||||||
Length = ResLength;
|
|
||||||
|
|
||||||
if( !KeyValuePartialInfo ) {
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
|
|
||||||
(PVOID)KeyValuePartialInfo,
|
|
||||||
Length,
|
|
||||||
&ResLength);
|
|
||||||
|
|
||||||
if( !NT_SUCCESS(Status) ) {
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
RtlFreeHeap(GetProcessHeap(),0,KeyValuePartialInfo);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Temp.Length = Temp.MaximumLength = KeyValuePartialInfo->DataLength;
|
|
||||||
Temp.Buffer = (PWCHAR)KeyValuePartialInfo->Data;
|
|
||||||
|
|
||||||
/* At this point, KeyValuePartialInfo->Data contains the key data */
|
|
||||||
RtlInitUnicodeString(ReturnedValue,L"");
|
|
||||||
RosAppendUnicodeString(ReturnedValue,&Temp,FALSE);
|
|
||||||
|
|
||||||
RtlFreeHeap(GetProcessHeap(),0,KeyValuePartialInfo);
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
<module name="rosrtl" type="staticlibrary">
|
|
||||||
<define name="__USE_W32API" />
|
|
||||||
<directory name="file">
|
|
||||||
<file>sparse.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="misc">
|
|
||||||
<file>devmode.c</file>
|
|
||||||
<file>logfont.c</file>
|
|
||||||
<file>qsort.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="recmutex">
|
|
||||||
<file>recmutex.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="registry">
|
|
||||||
<file>registry.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="string">
|
|
||||||
<file>append.c</file>
|
|
||||||
<file>resstr.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="thread">
|
|
||||||
<directory name="i386">
|
|
||||||
<file>context.c</file>
|
|
||||||
<file>stackexit.S</file>
|
|
||||||
</directory>
|
|
||||||
<file>create.c</file>
|
|
||||||
<file>exit.c</file>
|
|
||||||
<file>linearstack.c</file>
|
|
||||||
<file>priv.c</file>
|
|
||||||
<file>stack.c</file>
|
|
||||||
</directory>
|
|
||||||
</module>
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to copy and append two unicode strings.
|
|
||||||
*
|
|
||||||
* IN OUT PUNICODE_STRING ResultFirst -> First string and result
|
|
||||||
* IN PUNICODE_STRING Second -> Second string to append
|
|
||||||
* IN BOOL Deallocate -> TRUE: Deallocate First string before
|
|
||||||
* overwriting.
|
|
||||||
*
|
|
||||||
* Returns NTSTATUS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RosAppendUnicodeString(PUNICODE_STRING ResultFirst,
|
|
||||||
PUNICODE_STRING Second,
|
|
||||||
BOOL Deallocate) {
|
|
||||||
NTSTATUS Status;
|
|
||||||
PWSTR new_string =
|
|
||||||
RtlAllocateHeap(GetProcessHeap(),0,
|
|
||||||
(ResultFirst->Length + Second->Length + sizeof(WCHAR)));
|
|
||||||
if( !new_string ) {
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
memcpy( new_string, ResultFirst->Buffer,
|
|
||||||
ResultFirst->Length );
|
|
||||||
memcpy( new_string + ResultFirst->Length / sizeof(WCHAR),
|
|
||||||
Second->Buffer,
|
|
||||||
Second->Length );
|
|
||||||
if( Deallocate ) RtlFreeUnicodeString(ResultFirst);
|
|
||||||
ResultFirst->Length += Second->Length;
|
|
||||||
ResultFirst->MaximumLength = ResultFirst->Length;
|
|
||||||
new_string[ResultFirst->Length / sizeof(WCHAR)] = 0;
|
|
||||||
Status = RtlCreateUnicodeString(ResultFirst,new_string) ?
|
|
||||||
STATUS_SUCCESS : STATUS_NO_MEMORY;
|
|
||||||
RtlFreeHeap(GetProcessHeap(),0,new_string);
|
|
||||||
return Status;
|
|
||||||
}
|
|
|
@ -1,224 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to measure the length of a string resource
|
|
||||||
*
|
|
||||||
* IN HINSTANCE hInst -> Instance of the module
|
|
||||||
* IN UINT uID -> ID of the string to measure
|
|
||||||
*
|
|
||||||
* Returns the number of characters not including the null-terminator.
|
|
||||||
* Returns -1 on failure.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
RosLenOfStrResource(HINSTANCE hInst, UINT uID)
|
|
||||||
{
|
|
||||||
HRSRC hrSrc;
|
|
||||||
HGLOBAL hRes;
|
|
||||||
LPWSTR lpName, lpStr;
|
|
||||||
|
|
||||||
if(hInst == NULL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There are always blocks of 16 strings */
|
|
||||||
lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
|
|
||||||
|
|
||||||
/* Find the string table block */
|
|
||||||
if((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) &&
|
|
||||||
(hRes = LoadResource(hInst, hrSrc)) &&
|
|
||||||
(lpStr = LockResource(hRes)))
|
|
||||||
{
|
|
||||||
UINT x;
|
|
||||||
|
|
||||||
/* Find the string we're looking for */
|
|
||||||
uID &= 0xF; /* position in the block, same as % 16 */
|
|
||||||
for(x = 0; x < uID; x++)
|
|
||||||
{
|
|
||||||
lpStr += (*lpStr) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Found the string */
|
|
||||||
return (int)(*lpStr);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate and load a string from the string table
|
|
||||||
*
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
* IN HINSTANCE hInst -> Instance of the module
|
|
||||||
* IN UINT uID -> ID of the string to measure
|
|
||||||
*
|
|
||||||
* Returns the number of characters not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
RosAllocAndLoadStringA(LPSTR *lpTarget, HINSTANCE hInst, UINT uID)
|
|
||||||
{
|
|
||||||
int ln;
|
|
||||||
|
|
||||||
ln = RosLenOfStrResource(hInst, uID);
|
|
||||||
if(ln++ > 0)
|
|
||||||
{
|
|
||||||
(*lpTarget) = (LPSTR)LocalAlloc(LMEM_FIXED, ln * sizeof(CHAR));
|
|
||||||
if((*lpTarget) != NULL)
|
|
||||||
{
|
|
||||||
int Ret;
|
|
||||||
if(!(Ret = LoadStringA(hInst, uID, *lpTarget, ln)))
|
|
||||||
{
|
|
||||||
LocalFree((HLOCAL)(*lpTarget));
|
|
||||||
}
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate and load a string from the string table
|
|
||||||
*
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
* IN HINSTANCE hInst -> Instance of the module
|
|
||||||
* IN UINT uID -> ID of the string to measure
|
|
||||||
*
|
|
||||||
* Returns the number of characters not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
RosAllocAndLoadStringW(LPWSTR *lpTarget, HINSTANCE hInst, UINT uID)
|
|
||||||
{
|
|
||||||
int ln;
|
|
||||||
|
|
||||||
ln = RosLenOfStrResource(hInst, uID);
|
|
||||||
if(ln++ > 0)
|
|
||||||
{
|
|
||||||
(*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED, ln * sizeof(WCHAR));
|
|
||||||
if((*lpTarget) != NULL)
|
|
||||||
{
|
|
||||||
int Ret;
|
|
||||||
if(!(Ret = LoadStringW(hInst, uID, *lpTarget, ln)))
|
|
||||||
{
|
|
||||||
LocalFree((HLOCAL)(*lpTarget));
|
|
||||||
}
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate memory and format a string
|
|
||||||
*
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
* IN LPSTR lpFormat -> String which is to be formatted with the arguments given
|
|
||||||
*
|
|
||||||
* Returns the number of characters in lpTarget not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
RosFormatStrA(LPSTR *lpTarget, LPSTR lpFormat, ...)
|
|
||||||
{
|
|
||||||
DWORD Ret;
|
|
||||||
va_list lArgs;
|
|
||||||
|
|
||||||
va_start(lArgs, lpFormat);
|
|
||||||
/* let's use FormatMessage to format it because it has the ability to allocate
|
|
||||||
memory automatically */
|
|
||||||
Ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
||||||
lpFormat, 0, 0, (LPSTR)lpTarget, 0, &lArgs);
|
|
||||||
va_end(lArgs);
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate memory and format a string
|
|
||||||
*
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
* IN LPSTR lpFormat -> String which is to be formatted with the arguments given
|
|
||||||
*
|
|
||||||
* Returns the number of characters in lpTarget not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
RosFormatStrW(LPWSTR *lpTarget, LPWSTR lpFormat, ...)
|
|
||||||
{
|
|
||||||
DWORD Ret;
|
|
||||||
va_list lArgs;
|
|
||||||
|
|
||||||
va_start(lArgs, lpFormat);
|
|
||||||
/* let's use FormatMessage to format it because it has the ability to allocate
|
|
||||||
memory automatically */
|
|
||||||
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
||||||
lpFormat, 0, 0, (LPWSTR)lpTarget, 0, &lArgs);
|
|
||||||
va_end(lArgs);
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate memory, load a string from the resources and format it
|
|
||||||
*
|
|
||||||
* IN HINSTANCE hInst -> Instance of the module
|
|
||||||
* IN UINT uID -> ID of the string to measure
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
*
|
|
||||||
* Returns the number of characters in lpTarget not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
RosLoadAndFormatStrA(HINSTANCE hInst, UINT uID, LPSTR *lpTarget, ...)
|
|
||||||
{
|
|
||||||
DWORD Ret = 0;
|
|
||||||
LPSTR lpFormat;
|
|
||||||
va_list lArgs;
|
|
||||||
|
|
||||||
if(RosAllocAndLoadStringA(&lpFormat, hInst, uID) > 0)
|
|
||||||
{
|
|
||||||
va_start(lArgs, lpTarget);
|
|
||||||
/* let's use FormatMessage to format it because it has the ability to allocate
|
|
||||||
memory automatically */
|
|
||||||
Ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
||||||
lpFormat, 0, 0, (LPSTR)lpTarget, 0, &lArgs);
|
|
||||||
va_end(lArgs);
|
|
||||||
|
|
||||||
LocalFree((HLOCAL)lpFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to allocate memory, load a string from the resources and format it
|
|
||||||
*
|
|
||||||
* IN HINSTANCE hInst -> Instance of the module
|
|
||||||
* IN UINT uID -> ID of the string to measure
|
|
||||||
* OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated
|
|
||||||
*
|
|
||||||
* Returns the number of characters in lpTarget not including the null-terminator.
|
|
||||||
* Returns 0 on failure. Use LocalFree() to free the memory allocated.
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
RosLoadAndFormatStrW(HINSTANCE hInst, UINT uID, LPWSTR *lpTarget, ...)
|
|
||||||
{
|
|
||||||
DWORD Ret = 0;
|
|
||||||
LPWSTR lpFormat;
|
|
||||||
va_list lArgs;
|
|
||||||
|
|
||||||
if(RosAllocAndLoadStringW(&lpFormat, hInst, uID) > 0)
|
|
||||||
{
|
|
||||||
va_start(lArgs, lpTarget);
|
|
||||||
/* let's use FormatMessage to format it because it has the ability to allocate
|
|
||||||
memory automatically */
|
|
||||||
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
||||||
lpFormat, 0, 0, (LPWSTR)lpTarget, 0, &lArgs);
|
|
||||||
va_end(lArgs);
|
|
||||||
|
|
||||||
LocalFree((HLOCAL)lpFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
RtlRosCreateUserThread
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
IN BOOLEAN CreateSuspended,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL,
|
|
||||||
IN PVOID StartAddress,
|
|
||||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
|
||||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
IN ULONG_PTR * Parameters
|
|
||||||
)
|
|
||||||
{
|
|
||||||
INITIAL_TEB usUserInitialTeb;
|
|
||||||
CONTEXT ctxInitialContext;
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
HANDLE hThread;
|
|
||||||
CLIENT_ID cidClientId;
|
|
||||||
|
|
||||||
if(ThreadHandle == NULL) ThreadHandle = &hThread;
|
|
||||||
if(ClientId == NULL) ClientId = &cidClientId;
|
|
||||||
|
|
||||||
/* allocate the stack for the thread */
|
|
||||||
nErrCode = RtlRosCreateStack
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&usUserInitialTeb,
|
|
||||||
StackZeroBits,
|
|
||||||
StackReserve,
|
|
||||||
StackCommit
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
|
||||||
|
|
||||||
/* initialize the registers and stack for the thread */
|
|
||||||
nErrCode = RtlRosInitializeContext
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&ctxInitialContext,
|
|
||||||
StartAddress,
|
|
||||||
&usUserInitialTeb,
|
|
||||||
ParameterCount,
|
|
||||||
Parameters
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
|
||||||
|
|
||||||
/* create the thread object */
|
|
||||||
nErrCode = NtCreateThread
|
|
||||||
(
|
|
||||||
ThreadHandle,
|
|
||||||
THREAD_ALL_ACCESS,
|
|
||||||
ObjectAttributes,
|
|
||||||
ProcessHandle,
|
|
||||||
ClientId,
|
|
||||||
&ctxInitialContext,
|
|
||||||
&usUserInitialTeb,
|
|
||||||
CreateSuspended
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
l_Fail:
|
|
||||||
ASSERT(!NT_SUCCESS(nErrCode));
|
|
||||||
|
|
||||||
/* deallocate the stack */
|
|
||||||
RtlRosDeleteStack(ProcessHandle, &usUserInitialTeb);
|
|
||||||
|
|
||||||
return nErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS CDECL
|
|
||||||
RtlRosCreateUserThreadVa
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
IN BOOLEAN CreateSuspended,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL,
|
|
||||||
IN PVOID StartAddress,
|
|
||||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
|
||||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
...
|
|
||||||
)
|
|
||||||
{
|
|
||||||
va_list vaArgs;
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
|
|
||||||
va_start(vaArgs, ParameterCount);
|
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME: this code makes several non-portable assumptions:
|
|
||||||
- all parameters are passed on the stack
|
|
||||||
- the stack is a contiguous array of cells as large as an ULONG_PTR
|
|
||||||
- the stack grows downwards
|
|
||||||
|
|
||||||
This happens to work on the Intel x86, but is likely to bomb horribly on most
|
|
||||||
other platforms
|
|
||||||
*/
|
|
||||||
nErrCode = RtlRosCreateUserThread
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
ObjectAttributes,
|
|
||||||
CreateSuspended,
|
|
||||||
StackZeroBits,
|
|
||||||
StackReserve,
|
|
||||||
StackCommit,
|
|
||||||
StartAddress,
|
|
||||||
ThreadHandle,
|
|
||||||
ClientId,
|
|
||||||
ParameterCount,
|
|
||||||
(ULONG_PTR *)vaArgs
|
|
||||||
);
|
|
||||||
|
|
||||||
va_end(vaArgs);
|
|
||||||
|
|
||||||
return nErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,40 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
static VOID NTAPI RtlRosExitUserThread_Stage2
|
|
||||||
(
|
|
||||||
IN ULONG_PTR Status
|
|
||||||
)
|
|
||||||
{
|
|
||||||
RtlRosFreeUserThreadStack(NtCurrentProcess(), NtCurrentThread());
|
|
||||||
NtTerminateThread(NtCurrentThread(), Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(noreturn) VOID NTAPI RtlRosExitUserThread
|
|
||||||
(
|
|
||||||
IN NTSTATUS Status
|
|
||||||
)
|
|
||||||
{
|
|
||||||
RtlRosSwitchStackForExit
|
|
||||||
(
|
|
||||||
NtCurrentTeb()->StaticUnicodeBuffer,
|
|
||||||
sizeof(NtCurrentTeb()->StaticUnicodeBuffer),
|
|
||||||
RtlRosExitUserThread_Stage2,
|
|
||||||
Status
|
|
||||||
);
|
|
||||||
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,91 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
RtlRosInitializeContext
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
OUT PCONTEXT Context,
|
|
||||||
IN PVOID StartAddress,
|
|
||||||
IN PINITIAL_TEB InitialTeb,
|
|
||||||
IN ULONG ParameterCount,
|
|
||||||
IN ULONG_PTR * Parameters
|
|
||||||
)
|
|
||||||
{
|
|
||||||
static PVOID s_pRetAddr = (PVOID)0xDEADBEEF;
|
|
||||||
|
|
||||||
ULONG nDummy;
|
|
||||||
SIZE_T nParamsSize = ParameterCount * sizeof(ULONG_PTR);
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
PVOID pStackBase;
|
|
||||||
PVOID pStackLimit;
|
|
||||||
|
|
||||||
/* Intel x86: linear top-down stack, all parameters passed on the stack */
|
|
||||||
/* get the stack base and limit */
|
|
||||||
nErrCode = RtlpRosGetStackLimits(InitialTeb, &pStackBase, &pStackLimit);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
|
|
||||||
/* validate the stack */
|
|
||||||
nErrCode = RtlpRosValidateTopDownUserStack(pStackBase, pStackLimit);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
|
|
||||||
/* too many parameters */
|
|
||||||
if((nParamsSize + sizeof(ULONG_PTR)) > (SIZE_T)((ULONG_PTR)pStackBase - (ULONG_PTR)pStackLimit))
|
|
||||||
return STATUS_STACK_OVERFLOW;
|
|
||||||
|
|
||||||
memset(Context, 0, sizeof(CONTEXT));
|
|
||||||
|
|
||||||
/* initialize the context */
|
|
||||||
Context->ContextFlags = CONTEXT_FULL;
|
|
||||||
Context->FloatSave.ControlWord = FLOAT_SAVE_CONTROL;
|
|
||||||
Context->FloatSave.StatusWord = FLOAT_SAVE_STATUS;
|
|
||||||
Context->FloatSave.TagWord = FLOAT_SAVE_TAG;
|
|
||||||
Context->FloatSave.DataSelector = FLOAT_SAVE_DATA;
|
|
||||||
Context->Eip = (ULONG_PTR)StartAddress;
|
|
||||||
Context->SegGs = USER_DS;
|
|
||||||
Context->SegFs = TEB_SELECTOR;
|
|
||||||
Context->SegEs = USER_DS;
|
|
||||||
Context->SegDs = USER_DS;
|
|
||||||
Context->SegCs = USER_CS;
|
|
||||||
Context->SegSs = USER_DS;
|
|
||||||
Context->Esp = (ULONG_PTR)pStackBase - (nParamsSize + sizeof(ULONG_PTR));
|
|
||||||
Context->EFlags = ((ULONG_PTR)1 << 1) | ((ULONG_PTR)1 << 9);
|
|
||||||
|
|
||||||
/* write the parameters */
|
|
||||||
nErrCode = NtWriteVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
((PUCHAR)pStackBase) - nParamsSize,
|
|
||||||
Parameters,
|
|
||||||
nParamsSize,
|
|
||||||
&nDummy
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
|
|
||||||
/* write the return address */
|
|
||||||
return NtWriteVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
((PUCHAR)pStackBase) - (nParamsSize + sizeof(ULONG_PTR)),
|
|
||||||
&s_pRetAddr,
|
|
||||||
sizeof(s_pRetAddr),
|
|
||||||
&nDummy
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,13 +0,0 @@
|
||||||
.globl _RtlRosSwitchStackForExit@16
|
|
||||||
|
|
||||||
_RtlRosSwitchStackForExit@16:
|
|
||||||
movl 0x10(%esp), %edx /* Parameter */
|
|
||||||
movl 0xC(%esp), %eax /* ExitRoutine */
|
|
||||||
movl 0x8(%esp), %ecx /* StackSize */
|
|
||||||
movl 0x4(%esp), %esp /* StackBase */
|
|
||||||
addl %ecx, %esp
|
|
||||||
subl $0x4, %esp
|
|
||||||
pushl %edx
|
|
||||||
call *%eax
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,38 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlpRosValidateLinearUserStack
|
|
||||||
(
|
|
||||||
IN PVOID StackBase,
|
|
||||||
IN PVOID StackLimit,
|
|
||||||
IN BOOLEAN Direction
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* the stack has a null or negative (relatively to its direction) length */
|
|
||||||
/*
|
|
||||||
Direction: TRUE for down-top, FALSE for top-down
|
|
||||||
|
|
||||||
Direction == TRUE and positive stack size: OK
|
|
||||||
Direction == TRUE and negative stack size: error
|
|
||||||
Direction == FALSE and positive stack size: error
|
|
||||||
Direction == FALSE and negative stack size: OK
|
|
||||||
*/
|
|
||||||
if
|
|
||||||
(
|
|
||||||
StackBase == StackLimit ||
|
|
||||||
(Direction ^ ((PCHAR)StackBase < (PCHAR)StackLimit))
|
|
||||||
)
|
|
||||||
return STATUS_BAD_INITIAL_STACK;
|
|
||||||
|
|
||||||
/* valid stack */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,122 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#include <rosrtl/priv.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to copy and enable thread privileges
|
|
||||||
*
|
|
||||||
* OUT HANDLE *hPreviousToken -> Pointer to a variable that receives the previous token handle
|
|
||||||
* IN LUID *Privileges -> Points to an array of privileges to be enabled
|
|
||||||
* IN DWORD PrivilegeCount -> Number of the privileges in the array
|
|
||||||
*
|
|
||||||
* Returns TRUE on success and copies the thread token (if any) handle that was active before impersonation.
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
RosEnableThreadPrivileges(HANDLE *hPreviousToken,
|
|
||||||
LUID *Privileges,
|
|
||||||
DWORD PrivilegeCount)
|
|
||||||
{
|
|
||||||
HANDLE hToken;
|
|
||||||
|
|
||||||
if(hPreviousToken == NULL ||
|
|
||||||
Privileges == NULL || PrivilegeCount == 0)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Just open the thread token, we'll duplicate the handle later */
|
|
||||||
if(OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE, FALSE, &hToken))
|
|
||||||
{
|
|
||||||
PTOKEN_PRIVILEGES privs;
|
|
||||||
PLUID_AND_ATTRIBUTES la;
|
|
||||||
HANDLE hNewToken;
|
|
||||||
BOOL Ret;
|
|
||||||
|
|
||||||
/* duplicate the token handle */
|
|
||||||
if(!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE, NULL, SecurityImpersonation,
|
|
||||||
TokenImpersonation, &hNewToken))
|
|
||||||
{
|
|
||||||
CloseHandle(hToken);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate the required space for the privilege list */
|
|
||||||
privs = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, sizeof(TOKEN_PRIVILEGES) +
|
|
||||||
((PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES)));
|
|
||||||
if(privs == NULL)
|
|
||||||
{
|
|
||||||
CloseHandle(hNewToken);
|
|
||||||
CloseHandle(hToken);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build the privilege list */
|
|
||||||
privs->PrivilegeCount = PrivilegeCount;
|
|
||||||
for(la = privs->Privileges; PrivilegeCount-- > 0; la++)
|
|
||||||
{
|
|
||||||
la->Luid = *(Privileges++);
|
|
||||||
la->Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable the token privileges */
|
|
||||||
if(!AdjustTokenPrivileges(hNewToken, FALSE, privs, 0, NULL, NULL))
|
|
||||||
{
|
|
||||||
LocalFree((HLOCAL)privs);
|
|
||||||
CloseHandle(hNewToken);
|
|
||||||
CloseHandle(hToken);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we don't need the privileges list anymore */
|
|
||||||
LocalFree((HLOCAL)privs);
|
|
||||||
|
|
||||||
/* Perform the impersonation */
|
|
||||||
Ret = SetThreadToken(NULL, hNewToken);
|
|
||||||
|
|
||||||
if(Ret)
|
|
||||||
{
|
|
||||||
/* only copy the previous token handle on success */
|
|
||||||
*hPreviousToken = hToken;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We don't return the previous token handle on failure, so close it here */
|
|
||||||
CloseHandle(hToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't need the handle to the new token anymore */
|
|
||||||
CloseHandle(hNewToken);
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility to reset the thread privileges previously changed with RosEnableThreadPrivileges()
|
|
||||||
*
|
|
||||||
* IN HANDLE hToken -> Handle of the thread token to be restored
|
|
||||||
*
|
|
||||||
* Returns TRUE on success.
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
RosResetThreadPrivileges(HANDLE hToken)
|
|
||||||
{
|
|
||||||
if(hToken != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
BOOL Ret;
|
|
||||||
|
|
||||||
/* Set the previous token handle */
|
|
||||||
Ret = SetThreadToken(NULL, hToken);
|
|
||||||
|
|
||||||
/* We don't need the handle anymore, close it */
|
|
||||||
CloseHandle(hToken);
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,271 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ndk/ntndk.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
#define ROUNDUP(a,b) ((((a)+(b)-1)/(b))*(b))
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosCreateStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
OUT PINITIAL_TEB InitialTeb,
|
|
||||||
IN LONG StackZeroBits,
|
|
||||||
IN OUT PULONG StackReserve OPTIONAL,
|
|
||||||
IN OUT PULONG StackCommit OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* FIXME: read the defaults from the executable image */
|
|
||||||
ULONG_PTR nStackReserve = 0x100000;
|
|
||||||
/* FIXME: when we finally have exception handling, make this PAGE_SIZE */
|
|
||||||
ULONG_PTR nStackCommit = 0x100000;
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
|
|
||||||
if(*StackReserve == 0) StackReserve = &nStackReserve;
|
|
||||||
else *StackReserve = ROUNDUP(*StackReserve, PAGE_SIZE);
|
|
||||||
|
|
||||||
if(*StackCommit == 0) StackCommit = &nStackCommit;
|
|
||||||
else *StackCommit = ROUNDUP(*StackCommit, PAGE_SIZE);
|
|
||||||
#if 0
|
|
||||||
/* the stack commit size must be equal to or less than the reserve size */
|
|
||||||
if(*StackCommit > *StackReserve) *StackCommit = *StackReserve;
|
|
||||||
#else
|
|
||||||
/* FIXME: no SEH, no guard pages */
|
|
||||||
*StackCommit = *StackReserve;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* FIXME: this code assumes a stack growing downwards */
|
|
||||||
/* fixed stack */
|
|
||||||
if(*StackCommit == *StackReserve)
|
|
||||||
{
|
|
||||||
InitialTeb->StackBase = NULL;
|
|
||||||
InitialTeb->StackLimit = NULL;
|
|
||||||
InitialTeb->AllocatedStackBase = NULL;
|
|
||||||
|
|
||||||
InitialTeb->PreviousStackLimit = NULL;
|
|
||||||
|
|
||||||
/* allocate the stack */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->PreviousStackLimit),
|
|
||||||
StackZeroBits,
|
|
||||||
StackReserve,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
|
||||||
|
|
||||||
/* store the highest (first) address of the stack */
|
|
||||||
InitialTeb->PreviousStackBase =
|
|
||||||
(PUCHAR)(InitialTeb->PreviousStackLimit) + *StackReserve;
|
|
||||||
|
|
||||||
*StackCommit = *StackReserve;
|
|
||||||
}
|
|
||||||
/* expandable stack */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ULONG_PTR nGuardSize = PAGE_SIZE;
|
|
||||||
PVOID pGuardBase;
|
|
||||||
|
|
||||||
DPRINT("Expandable stack\n");
|
|
||||||
|
|
||||||
InitialTeb->PreviousStackBase = NULL;
|
|
||||||
InitialTeb->PreviousStackLimit = NULL;
|
|
||||||
|
|
||||||
InitialTeb->AllocatedStackBase = NULL;
|
|
||||||
|
|
||||||
/* reserve the stack */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->AllocatedStackBase),
|
|
||||||
StackZeroBits,
|
|
||||||
StackReserve,
|
|
||||||
MEM_RESERVE,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
|
||||||
|
|
||||||
DPRINT("Reserved %08X bytes\n", *StackReserve);
|
|
||||||
|
|
||||||
/* expandable stack base - the highest address of the stack */
|
|
||||||
InitialTeb->StackBase =
|
|
||||||
(PUCHAR)(InitialTeb->AllocatedStackBase) + *StackReserve;
|
|
||||||
|
|
||||||
/* expandable stack limit - the lowest committed address of the stack */
|
|
||||||
InitialTeb->StackLimit =
|
|
||||||
(PUCHAR)(InitialTeb->StackBase) - *StackCommit;
|
|
||||||
|
|
||||||
DPRINT("Stack commit %p\n", InitialTeb->StackBase);
|
|
||||||
DPRINT("Stack commit max %p\n", InitialTeb->StackLimit);
|
|
||||||
DPRINT("Stack reserved %p\n", InitialTeb->AllocatedStackBase);
|
|
||||||
|
|
||||||
/* commit as much stack as requested */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->StackLimit),
|
|
||||||
0,
|
|
||||||
StackCommit,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
|
||||||
|
|
||||||
ASSERT((*StackReserve - *StackCommit) >= PAGE_SIZE);
|
|
||||||
ASSERT((*StackReserve - *StackCommit) % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
pGuardBase = (PUCHAR)(InitialTeb->StackLimit) - PAGE_SIZE;
|
|
||||||
|
|
||||||
DPRINT("Guard base %p\n", InitialTeb->StackBase);
|
|
||||||
|
|
||||||
/* set up the guard page */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&pGuardBase,
|
|
||||||
0,
|
|
||||||
&nGuardSize,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE | PAGE_GUARD
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
|
||||||
|
|
||||||
DPRINT("Guard base %p\n", InitialTeb->StackBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
|
||||||
/* deallocate the stack */
|
|
||||||
l_Cleanup:
|
|
||||||
RtlRosDeleteStack(ProcessHandle, InitialTeb);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
l_Fail:
|
|
||||||
ASSERT(!NT_SUCCESS(nErrCode));
|
|
||||||
return nErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosDeleteStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN PINITIAL_TEB InitialTeb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PVOID pStackLowest = NULL;
|
|
||||||
ULONG_PTR nSize;
|
|
||||||
|
|
||||||
if(InitialTeb->StackLimit)
|
|
||||||
pStackLowest = InitialTeb->PreviousStackLimit;
|
|
||||||
else if(InitialTeb->AllocatedStackBase)
|
|
||||||
pStackLowest = InitialTeb->AllocatedStackBase;
|
|
||||||
|
|
||||||
/* free the stack, if it was allocated */
|
|
||||||
if(pStackLowest != NULL)
|
|
||||||
return NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlRosFreeUserThreadStack
|
|
||||||
(
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
IN HANDLE ThreadHandle
|
|
||||||
)
|
|
||||||
{
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
ULONG nSize = 0;
|
|
||||||
PVOID pStackBase;
|
|
||||||
|
|
||||||
if(ThreadHandle == NtCurrentThread())
|
|
||||||
pStackBase = NtCurrentTeb()->DeallocationStack;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
THREAD_BASIC_INFORMATION tbiInfo;
|
|
||||||
ULONG nDummy;
|
|
||||||
|
|
||||||
/* query basic information about the thread */
|
|
||||||
nErrCode = NtQueryInformationThread
|
|
||||||
(
|
|
||||||
ThreadHandle,
|
|
||||||
ThreadBasicInformation,
|
|
||||||
&tbiInfo,
|
|
||||||
sizeof(tbiInfo),
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
if(tbiInfo.TebBaseAddress == NULL) return STATUS_ACCESS_VIOLATION;
|
|
||||||
|
|
||||||
/* read the base address of the stack to be deallocated */
|
|
||||||
nErrCode = NtReadVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&((PTEB)tbiInfo.TebBaseAddress)->DeallocationStack,
|
|
||||||
&pStackBase,
|
|
||||||
sizeof(pStackBase),
|
|
||||||
&nDummy
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
if(pStackBase == NULL) return STATUS_ACCESS_VIOLATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* deallocate the stack */
|
|
||||||
nErrCode = NtFreeVirtualMemory(ProcessHandle, &pStackBase, &nSize, MEM_RELEASE);
|
|
||||||
|
|
||||||
return nErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI RtlpRosGetStackLimits
|
|
||||||
(
|
|
||||||
IN PINITIAL_TEB InitialTeb,
|
|
||||||
OUT PVOID * StackBase,
|
|
||||||
OUT PVOID * StackLimit
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* fixed-size stack */
|
|
||||||
if(InitialTeb->PreviousStackBase && InitialTeb->PreviousStackLimit)
|
|
||||||
{
|
|
||||||
*StackBase = InitialTeb->PreviousStackBase;
|
|
||||||
*StackLimit = InitialTeb->PreviousStackLimit;
|
|
||||||
}
|
|
||||||
/* expandable stack */
|
|
||||||
else if(InitialTeb->StackBase && InitialTeb->StackLimit)
|
|
||||||
{
|
|
||||||
*StackBase = InitialTeb->StackBase;
|
|
||||||
*StackLimit = InitialTeb->StackLimit;
|
|
||||||
}
|
|
||||||
/* can't determine the type of stack: failure */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("Invalid user-mode stack\n");
|
|
||||||
return STATUS_BAD_INITIAL_STACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* valid stack */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,266 +1,266 @@
|
||||||
/* $Id$
|
/* $Id: qsort.c 12852 2005-01-06 13:58:04Z mf $
|
||||||
*
|
*
|
||||||
* FILE: ntoskrnl/rtl/qsort.c
|
* FILE: ntoskrnl/rtl/qsort.c
|
||||||
* NOTE: Adapted from CygWin newlib 2000-03-12.
|
* NOTE: Adapted from CygWin newlib 2000-03-12.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
FUNCTION
|
FUNCTION
|
||||||
<<qsort>>---sort an array
|
<<qsort>>---sort an array
|
||||||
|
|
||||||
INDEX
|
INDEX
|
||||||
qsort
|
qsort
|
||||||
|
|
||||||
ANSI_SYNOPSIS
|
ANSI_SYNOPSIS
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
|
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
|
||||||
int (*<[compar]>)(const void *, const void *) );
|
int (*<[compar]>)(const void *, const void *) );
|
||||||
|
|
||||||
TRAD_SYNOPSIS
|
TRAD_SYNOPSIS
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
|
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
|
||||||
char *<[base]>;
|
char *<[base]>;
|
||||||
size_t <[nmemb]>;
|
size_t <[nmemb]>;
|
||||||
size_t <[size]>;
|
size_t <[size]>;
|
||||||
int (*<[compar]>)();
|
int (*<[compar]>)();
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
|
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
|
||||||
<[size]> describes the size of each element of the array.
|
<[size]> describes the size of each element of the array.
|
||||||
|
|
||||||
You must supply a pointer to a comparison function, using the argument
|
You must supply a pointer to a comparison function, using the argument
|
||||||
shown as <[compar]>. (This permits sorting objects of unknown
|
shown as <[compar]>. (This permits sorting objects of unknown
|
||||||
properties.) Define the comparison function to accept two arguments,
|
properties.) Define the comparison function to accept two arguments,
|
||||||
each a pointer to an element of the array starting at <[base]>. The
|
each a pointer to an element of the array starting at <[base]>. The
|
||||||
result of <<(*<[compar]>)>> must be negative if the first argument is
|
result of <<(*<[compar]>)>> must be negative if the first argument is
|
||||||
less than the second, zero if the two arguments match, and positive if
|
less than the second, zero if the two arguments match, and positive if
|
||||||
the first argument is greater than the second (where ``less than'' and
|
the first argument is greater than the second (where ``less than'' and
|
||||||
``greater than'' refer to whatever arbitrary ordering is appropriate).
|
``greater than'' refer to whatever arbitrary ordering is appropriate).
|
||||||
|
|
||||||
The array is sorted in place; that is, when <<qsort>> returns, the
|
The array is sorted in place; that is, when <<qsort>> returns, the
|
||||||
array elements beginning at <[base]> have been reordered.
|
array elements beginning at <[base]> have been reordered.
|
||||||
|
|
||||||
RETURNS
|
RETURNS
|
||||||
<<qsort>> does not return a result.
|
<<qsort>> does not return a result.
|
||||||
|
|
||||||
PORTABILITY
|
PORTABILITY
|
||||||
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
|
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1992, 1993
|
* Copyright (c) 1992, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
* must display the following acknowledgement:
|
* must display the following acknowledgement:
|
||||||
* This product includes software developed by the University of
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#define inline
|
#define inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FIXME: these types should be from the default includes */
|
/* FIXME: these types should be from the default includes */
|
||||||
|
|
||||||
typedef int (* _pfunccmp_t) (char *, char *);
|
typedef int (* _pfunccmp_t) (char *, char *);
|
||||||
typedef int size_t;
|
typedef int size_t;
|
||||||
|
|
||||||
#define min(a,b) ((a)<(b)?(a):(b))
|
#define min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||||
*/
|
*/
|
||||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||||
long i = (n) / sizeof (TYPE); \
|
long i = (n) / sizeof (TYPE); \
|
||||||
register TYPE *pi = (TYPE *) (parmi); \
|
register TYPE *pi = (TYPE *) (parmi); \
|
||||||
register TYPE *pj = (TYPE *) (parmj); \
|
register TYPE *pj = (TYPE *) (parmj); \
|
||||||
do { \
|
do { \
|
||||||
register TYPE t = *pi; \
|
register TYPE t = *pi; \
|
||||||
*pi++ = *pj; \
|
*pi++ = *pj; \
|
||||||
*pj++ = t; \
|
*pj++ = t; \
|
||||||
} while (--i > 0); \
|
} while (--i > 0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
swapfunc (
|
swapfunc (
|
||||||
char * a,
|
char * a,
|
||||||
char * b,
|
char * b,
|
||||||
int n,
|
int n,
|
||||||
int swaptype
|
int swaptype
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if(swaptype <= 1)
|
if(swaptype <= 1)
|
||||||
swapcode(long, a, b, n)
|
swapcode(long, a, b, n)
|
||||||
else
|
else
|
||||||
swapcode(char, a, b, n)
|
swapcode(char, a, b, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define swap(a, b) \
|
#define swap(a, b) \
|
||||||
if (swaptype == 0) { \
|
if (swaptype == 0) { \
|
||||||
long t = *(long *)(a); \
|
long t = *(long *)(a); \
|
||||||
*(long *)(a) = *(long *)(b); \
|
*(long *)(a) = *(long *)(b); \
|
||||||
*(long *)(b) = t; \
|
*(long *)(b) = t; \
|
||||||
} else \
|
} else \
|
||||||
swapfunc(a, b, es, swaptype)
|
swapfunc(a, b, es, swaptype)
|
||||||
|
|
||||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
med3 (
|
med3 (
|
||||||
char * a,
|
char * a,
|
||||||
char * b,
|
char * b,
|
||||||
char * c,
|
char * c,
|
||||||
_pfunccmp_t cmp
|
_pfunccmp_t cmp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return cmp(a, b) < 0 ?
|
return cmp(a, b) < 0 ?
|
||||||
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
|
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
|
||||||
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
|
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EXPORTED */
|
/* EXPORTED */
|
||||||
void
|
void
|
||||||
qsort (
|
qsort (
|
||||||
void * a,
|
void * a,
|
||||||
size_t n,
|
size_t n,
|
||||||
size_t es,
|
size_t es,
|
||||||
_pfunccmp_t cmp
|
_pfunccmp_t cmp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||||
int d, r, swaptype, swap_cnt;
|
int d, r, swaptype, swap_cnt;
|
||||||
|
|
||||||
loop: SWAPINIT(a, es);
|
loop: SWAPINIT(a, es);
|
||||||
swap_cnt = 0;
|
swap_cnt = 0;
|
||||||
if (n < 7)
|
if (n < 7)
|
||||||
{
|
{
|
||||||
for ( pm = (char *) a + es;
|
for ( pm = (char *) a + es;
|
||||||
pm < (char *) a + n * es;
|
pm < (char *) a + n * es;
|
||||||
pm += es
|
pm += es
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for ( pl = pm;
|
for ( pl = pm;
|
||||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||||
pl -= es
|
pl -= es
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
swap(pl, pl - es);
|
swap(pl, pl - es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pm = (char *) a + (n / 2) * es;
|
pm = (char *) a + (n / 2) * es;
|
||||||
if (n > 7)
|
if (n > 7)
|
||||||
{
|
{
|
||||||
pl = (char *) a;
|
pl = (char *) a;
|
||||||
pn = (char *) a + (n - 1) * es;
|
pn = (char *) a + (n - 1) * es;
|
||||||
if (n > 40)
|
if (n > 40)
|
||||||
{
|
{
|
||||||
d = (n / 8) * es;
|
d = (n / 8) * es;
|
||||||
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
||||||
pm = med3(pm - d, pm, pm + d, cmp);
|
pm = med3(pm - d, pm, pm + d, cmp);
|
||||||
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
||||||
}
|
}
|
||||||
pm = med3(pl, pm, pn, cmp);
|
pm = med3(pl, pm, pn, cmp);
|
||||||
}
|
}
|
||||||
swap(a, pm);
|
swap(a, pm);
|
||||||
pa = pb = (char *) a + es;
|
pa = pb = (char *) a + es;
|
||||||
|
|
||||||
pc = pd = (char *) a + (n - 1) * es;
|
pc = pd = (char *) a + (n - 1) * es;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
while (pb <= pc && (r = cmp(pb, a)) <= 0)
|
while (pb <= pc && (r = cmp(pb, a)) <= 0)
|
||||||
{
|
{
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
{
|
{
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pa, pb);
|
swap(pa, pb);
|
||||||
pa += es;
|
pa += es;
|
||||||
}
|
}
|
||||||
pb += es;
|
pb += es;
|
||||||
}
|
}
|
||||||
while (pb <= pc && (r = cmp(pc, a)) >= 0)
|
while (pb <= pc && (r = cmp(pc, a)) >= 0)
|
||||||
{
|
{
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
{
|
{
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pc, pd);
|
swap(pc, pd);
|
||||||
pd -= es;
|
pd -= es;
|
||||||
}
|
}
|
||||||
pc -= es;
|
pc -= es;
|
||||||
}
|
}
|
||||||
if (pb > pc)
|
if (pb > pc)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
swap(pb, pc);
|
swap(pb, pc);
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
pb += es;
|
pb += es;
|
||||||
pc -= es;
|
pc -= es;
|
||||||
}
|
}
|
||||||
if (swap_cnt == 0) /* Switch to insertion sort */
|
if (swap_cnt == 0) /* Switch to insertion sort */
|
||||||
{
|
{
|
||||||
for ( pm = (char *) a + es;
|
for ( pm = (char *) a + es;
|
||||||
pm < (char *) a + n * es;
|
pm < (char *) a + n * es;
|
||||||
pm += es
|
pm += es
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for ( pl = pm;
|
for ( pl = pm;
|
||||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||||
pl -= es
|
pl -= es
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
swap(pl, pl - es);
|
swap(pl, pl - es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pn = (char *) a + n * es;
|
pn = (char *) a + n * es;
|
||||||
r = min(pa - (char *)a, pb - pa);
|
r = min(pa - (char *)a, pb - pa);
|
||||||
vecswap(a, pb - r, r);
|
vecswap(a, pb - r, r);
|
||||||
r = min(pd - pc, pn - pd - es);
|
r = min(pd - pc, pn - pd - es);
|
||||||
vecswap(pb, pn - r, r);
|
vecswap(pb, pn - r, r);
|
||||||
if ((r = pb - pa) > es)
|
if ((r = pb - pa) > es)
|
||||||
{
|
{
|
||||||
qsort(a, r / es, es, cmp);
|
qsort(a, r / es, es, cmp);
|
||||||
}
|
}
|
||||||
if ((r = pd - pc) > es)
|
if ((r = pd - pc) > es)
|
||||||
{
|
{
|
||||||
/* Iterate rather than recurse to save stack space */
|
/* Iterate rather than recurse to save stack space */
|
||||||
a = pn - r;
|
a = pn - r;
|
||||||
n = r / es;
|
n = r / es;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
/* qsort(pn - r, r / es, es, cmp);*/
|
/* qsort(pn - r, r / es, es, cmp);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
|
@ -37,6 +37,7 @@
|
||||||
<file>nls.c</file>
|
<file>nls.c</file>
|
||||||
<file>ppb.c</file>
|
<file>ppb.c</file>
|
||||||
<file>process.c</file>
|
<file>process.c</file>
|
||||||
|
<file>qsort.c</file>
|
||||||
<file>random.c</file>
|
<file>random.c</file>
|
||||||
<file>registry.c</file>
|
<file>registry.c</file>
|
||||||
<file>sd.c</file>
|
<file>sd.c</file>
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
<library>wine</library>
|
<library>wine</library>
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<library>gdi32</library>
|
<library>gdi32</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>kernel32</library>
|
<library>kernel32</library>
|
||||||
<library>advapi32</library>
|
<library>advapi32</library>
|
||||||
<directory name="include">
|
<directory name="include">
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<library>kjs</library>
|
<library>kjs</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>rtl</library>
|
<library>rtl</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>rossym</library>
|
<library>rossym</library>
|
||||||
<library>string</library>
|
<library>string</library>
|
||||||
<library>wdmguid</library>
|
<library>wdmguid</library>
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<library>regtests</library>
|
<library>regtests</library>
|
||||||
<library>win32k_base</library>
|
<library>win32k_base</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<directory name="tests">
|
<directory name="tests">
|
||||||
<file>DIB_24BPP_ColorFill-performance.c</file>
|
<file>DIB_24BPP_ColorFill-performance.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -132,7 +132,6 @@
|
||||||
<importlibrary definition="win32k.def" />
|
<importlibrary definition="win32k.def" />
|
||||||
<library>win32k_base</library>
|
<library>win32k_base</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>rosrtl</library>
|
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
<library>freetype</library>
|
<library>freetype</library>
|
||||||
|
|
Loading…
Reference in a new issue