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 <limits.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <rosrtl/recmutex.h>
|
||||
#include <../recmutex/recmutex.h>
|
||||
#include <roscfg.h>
|
||||
#include <tcpip.h>
|
||||
#include <loopback.h>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <ddk/ntddk.h>
|
||||
#include <rosrtl/recmutex.h>
|
||||
#include "recmutex.h"
|
||||
|
||||
VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
|
||||
RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
|
|
@ -8,7 +8,6 @@
|
|||
<library>ip</library>
|
||||
<library>oskittcp</library>
|
||||
<library>ndis</library>
|
||||
<library>rosrtl</library>
|
||||
<library>pseh</library>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
|
@ -18,6 +17,9 @@
|
|||
<directory name="datalink">
|
||||
<file>lan.c</file>
|
||||
</directory>
|
||||
<directory name="recmutex">
|
||||
<file>recmutex.c</file>
|
||||
</directory>
|
||||
<directory name="tcpip">
|
||||
<file>buffer.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">
|
||||
<xi:include href="riched20/riched20.xml" />
|
||||
</directory>
|
||||
<directory name="rosrtl">
|
||||
<xi:include href="rosrtl/rosrtl.xml" />
|
||||
</directory>
|
||||
<directory name="rossym">
|
||||
<xi:include href="rossym/rossym.xml" />
|
||||
</directory>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<define name="ADNS_JGAA_WIN32" />
|
||||
<define name="__USE_W32API" />
|
||||
<library>adns</library>
|
||||
<library>rosrtl</library>
|
||||
<library>ntdll</library>
|
||||
<library>kernel32</library>
|
||||
<library>user32</library>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<define name="WINVER">0x0600</define>
|
||||
<define name="_WIN32_WINNT">0x0501</define>
|
||||
<library>ntdll</library>
|
||||
<library>rosrtl</library>
|
||||
<library>kernel32</library>
|
||||
<library>advapi32</library>
|
||||
<directory name="include">
|
||||
|
|
|
@ -118,7 +118,6 @@
|
|||
<define name="WINVER">0x0500</define>
|
||||
<library>kernel32_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<library>intrlck</library>
|
||||
<library>ntdll</library>
|
||||
<linkerflag>-lgcc</linkerflag>
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
<library>regtests</library>
|
||||
<library>kernel32_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<library>ntdll</library>
|
||||
<library>msvcrt</library>
|
||||
<linkerflag>-lgcc</linkerflag>
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<define name="_WIN32_WINNT">0x0502</define>
|
||||
<define name="_NTOSKRNL_" />
|
||||
<library>rtl</library>
|
||||
<library>rosrtl</library>
|
||||
<library>intrlck</library>
|
||||
<library>string</library>
|
||||
<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$
|
||||
*
|
||||
* FILE: ntoskrnl/rtl/qsort.c
|
||||
* NOTE: Adapted from CygWin newlib 2000-03-12.
|
||||
*/
|
||||
/*
|
||||
FUNCTION
|
||||
<<qsort>>---sort an array
|
||||
|
||||
INDEX
|
||||
qsort
|
||||
|
||||
ANSI_SYNOPSIS
|
||||
#include <stdlib.h>
|
||||
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
|
||||
int (*<[compar]>)(const void *, const void *) );
|
||||
|
||||
TRAD_SYNOPSIS
|
||||
#include <stdlib.h>
|
||||
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
|
||||
char *<[base]>;
|
||||
size_t <[nmemb]>;
|
||||
size_t <[size]>;
|
||||
int (*<[compar]>)();
|
||||
|
||||
DESCRIPTION
|
||||
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
|
||||
<[size]> describes the size of each element of the array.
|
||||
|
||||
You must supply a pointer to a comparison function, using the argument
|
||||
shown as <[compar]>. (This permits sorting objects of unknown
|
||||
properties.) Define the comparison function to accept two arguments,
|
||||
each a pointer to an element of the array starting at <[base]>. The
|
||||
result of <<(*<[compar]>)>> must be negative if the first argument is
|
||||
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
|
||||
``greater than'' refer to whatever arbitrary ordering is appropriate).
|
||||
|
||||
The array is sorted in place; that is, when <<qsort>> returns, the
|
||||
array elements beginning at <[base]> have been reordered.
|
||||
|
||||
RETURNS
|
||||
<<qsort>> does not return a result.
|
||||
|
||||
PORTABILITY
|
||||
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
/* FIXME: these types should be from the default includes */
|
||||
|
||||
typedef int (* _pfunccmp_t) (char *, char *);
|
||||
typedef int size_t;
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||
long i = (n) / sizeof (TYPE); \
|
||||
register TYPE *pi = (TYPE *) (parmi); \
|
||||
register TYPE *pj = (TYPE *) (parmj); \
|
||||
do { \
|
||||
register TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
|
||||
static inline void
|
||||
swapfunc (
|
||||
char * a,
|
||||
char * b,
|
||||
int n,
|
||||
int swaptype
|
||||
)
|
||||
{
|
||||
if(swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b); \
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
|
||||
static inline char *
|
||||
med3 (
|
||||
char * a,
|
||||
char * b,
|
||||
char * c,
|
||||
_pfunccmp_t cmp
|
||||
)
|
||||
{
|
||||
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 ? a : c ));
|
||||
}
|
||||
|
||||
|
||||
/* EXPORTED */
|
||||
void
|
||||
qsort (
|
||||
void * a,
|
||||
size_t n,
|
||||
size_t es,
|
||||
_pfunccmp_t cmp
|
||||
)
|
||||
{
|
||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
int d, r, swaptype, swap_cnt;
|
||||
|
||||
loop: SWAPINIT(a, es);
|
||||
swap_cnt = 0;
|
||||
if (n < 7)
|
||||
{
|
||||
for ( pm = (char *) a + es;
|
||||
pm < (char *) a + n * es;
|
||||
pm += es
|
||||
)
|
||||
{
|
||||
for ( pl = pm;
|
||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es
|
||||
)
|
||||
{
|
||||
swap(pl, pl - es);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
pm = (char *) a + (n / 2) * es;
|
||||
if (n > 7)
|
||||
{
|
||||
pl = (char *) a;
|
||||
pn = (char *) a + (n - 1) * es;
|
||||
if (n > 40)
|
||||
{
|
||||
d = (n / 8) * es;
|
||||
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
||||
pm = med3(pm - d, pm, pm + d, cmp);
|
||||
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
||||
}
|
||||
pm = med3(pl, pm, pn, cmp);
|
||||
}
|
||||
swap(a, pm);
|
||||
pa = pb = (char *) a + es;
|
||||
|
||||
pc = pd = (char *) a + (n - 1) * es;
|
||||
for (;;)
|
||||
{
|
||||
while (pb <= pc && (r = cmp(pb, a)) <= 0)
|
||||
{
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
}
|
||||
while (pb <= pc && (r = cmp(pc, a)) >= 0)
|
||||
{
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
swap(pb, pc);
|
||||
swap_cnt = 1;
|
||||
pb += es;
|
||||
pc -= es;
|
||||
}
|
||||
if (swap_cnt == 0) /* Switch to insertion sort */
|
||||
{
|
||||
for ( pm = (char *) a + es;
|
||||
pm < (char *) a + n * es;
|
||||
pm += es
|
||||
)
|
||||
{
|
||||
for ( pl = pm;
|
||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es
|
||||
)
|
||||
{
|
||||
swap(pl, pl - es);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pn = (char *) a + n * es;
|
||||
r = min(pa - (char *)a, pb - pa);
|
||||
vecswap(a, pb - r, r);
|
||||
r = min(pd - pc, pn - pd - es);
|
||||
vecswap(pb, pn - r, r);
|
||||
if ((r = pb - pa) > es)
|
||||
{
|
||||
qsort(a, r / es, es, cmp);
|
||||
}
|
||||
if ((r = pd - pc) > es)
|
||||
{
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
n = r / es;
|
||||
goto loop;
|
||||
}
|
||||
/* qsort(pn - r, r / es, es, cmp);*/
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
/* $Id: qsort.c 12852 2005-01-06 13:58:04Z mf $
|
||||
*
|
||||
* FILE: ntoskrnl/rtl/qsort.c
|
||||
* NOTE: Adapted from CygWin newlib 2000-03-12.
|
||||
*/
|
||||
/*
|
||||
FUNCTION
|
||||
<<qsort>>---sort an array
|
||||
|
||||
INDEX
|
||||
qsort
|
||||
|
||||
ANSI_SYNOPSIS
|
||||
#include <stdlib.h>
|
||||
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
|
||||
int (*<[compar]>)(const void *, const void *) );
|
||||
|
||||
TRAD_SYNOPSIS
|
||||
#include <stdlib.h>
|
||||
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
|
||||
char *<[base]>;
|
||||
size_t <[nmemb]>;
|
||||
size_t <[size]>;
|
||||
int (*<[compar]>)();
|
||||
|
||||
DESCRIPTION
|
||||
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
|
||||
<[size]> describes the size of each element of the array.
|
||||
|
||||
You must supply a pointer to a comparison function, using the argument
|
||||
shown as <[compar]>. (This permits sorting objects of unknown
|
||||
properties.) Define the comparison function to accept two arguments,
|
||||
each a pointer to an element of the array starting at <[base]>. The
|
||||
result of <<(*<[compar]>)>> must be negative if the first argument is
|
||||
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
|
||||
``greater than'' refer to whatever arbitrary ordering is appropriate).
|
||||
|
||||
The array is sorted in place; that is, when <<qsort>> returns, the
|
||||
array elements beginning at <[base]> have been reordered.
|
||||
|
||||
RETURNS
|
||||
<<qsort>> does not return a result.
|
||||
|
||||
PORTABILITY
|
||||
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
/* FIXME: these types should be from the default includes */
|
||||
|
||||
typedef int (* _pfunccmp_t) (char *, char *);
|
||||
typedef int size_t;
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||
long i = (n) / sizeof (TYPE); \
|
||||
register TYPE *pi = (TYPE *) (parmi); \
|
||||
register TYPE *pj = (TYPE *) (parmj); \
|
||||
do { \
|
||||
register TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
|
||||
static inline void
|
||||
swapfunc (
|
||||
char * a,
|
||||
char * b,
|
||||
int n,
|
||||
int swaptype
|
||||
)
|
||||
{
|
||||
if(swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b); \
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
|
||||
static inline char *
|
||||
med3 (
|
||||
char * a,
|
||||
char * b,
|
||||
char * c,
|
||||
_pfunccmp_t cmp
|
||||
)
|
||||
{
|
||||
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 ? a : c ));
|
||||
}
|
||||
|
||||
|
||||
/* EXPORTED */
|
||||
void
|
||||
qsort (
|
||||
void * a,
|
||||
size_t n,
|
||||
size_t es,
|
||||
_pfunccmp_t cmp
|
||||
)
|
||||
{
|
||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
int d, r, swaptype, swap_cnt;
|
||||
|
||||
loop: SWAPINIT(a, es);
|
||||
swap_cnt = 0;
|
||||
if (n < 7)
|
||||
{
|
||||
for ( pm = (char *) a + es;
|
||||
pm < (char *) a + n * es;
|
||||
pm += es
|
||||
)
|
||||
{
|
||||
for ( pl = pm;
|
||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es
|
||||
)
|
||||
{
|
||||
swap(pl, pl - es);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
pm = (char *) a + (n / 2) * es;
|
||||
if (n > 7)
|
||||
{
|
||||
pl = (char *) a;
|
||||
pn = (char *) a + (n - 1) * es;
|
||||
if (n > 40)
|
||||
{
|
||||
d = (n / 8) * es;
|
||||
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
||||
pm = med3(pm - d, pm, pm + d, cmp);
|
||||
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
||||
}
|
||||
pm = med3(pl, pm, pn, cmp);
|
||||
}
|
||||
swap(a, pm);
|
||||
pa = pb = (char *) a + es;
|
||||
|
||||
pc = pd = (char *) a + (n - 1) * es;
|
||||
for (;;)
|
||||
{
|
||||
while (pb <= pc && (r = cmp(pb, a)) <= 0)
|
||||
{
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
}
|
||||
while (pb <= pc && (r = cmp(pc, a)) >= 0)
|
||||
{
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
swap(pb, pc);
|
||||
swap_cnt = 1;
|
||||
pb += es;
|
||||
pc -= es;
|
||||
}
|
||||
if (swap_cnt == 0) /* Switch to insertion sort */
|
||||
{
|
||||
for ( pm = (char *) a + es;
|
||||
pm < (char *) a + n * es;
|
||||
pm += es
|
||||
)
|
||||
{
|
||||
for ( pl = pm;
|
||||
pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es
|
||||
)
|
||||
{
|
||||
swap(pl, pl - es);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pn = (char *) a + n * es;
|
||||
r = min(pa - (char *)a, pb - pa);
|
||||
vecswap(a, pb - r, r);
|
||||
r = min(pd - pc, pn - pd - es);
|
||||
vecswap(pb, pn - r, r);
|
||||
if ((r = pb - pa) > es)
|
||||
{
|
||||
qsort(a, r / es, es, cmp);
|
||||
}
|
||||
if ((r = pd - pc) > es)
|
||||
{
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
n = r / es;
|
||||
goto loop;
|
||||
}
|
||||
/* qsort(pn - r, r / es, es, cmp);*/
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
|
@ -37,6 +37,7 @@
|
|||
<file>nls.c</file>
|
||||
<file>ppb.c</file>
|
||||
<file>process.c</file>
|
||||
<file>qsort.c</file>
|
||||
<file>random.c</file>
|
||||
<file>registry.c</file>
|
||||
<file>sd.c</file>
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<library>wine</library>
|
||||
<library>ntdll</library>
|
||||
<library>gdi32</library>
|
||||
<library>rosrtl</library>
|
||||
<library>kernel32</library>
|
||||
<library>advapi32</library>
|
||||
<directory name="include">
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<library>kjs</library>
|
||||
<library>pseh</library>
|
||||
<library>rtl</library>
|
||||
<library>rosrtl</library>
|
||||
<library>rossym</library>
|
||||
<library>string</library>
|
||||
<library>wdmguid</library>
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<library>regtests</library>
|
||||
<library>win32k_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<directory name="tests">
|
||||
<file>DIB_24BPP_ColorFill-performance.c</file>
|
||||
</directory>
|
||||
|
|
|
@ -132,7 +132,6 @@
|
|||
<importlibrary definition="win32k.def" />
|
||||
<library>win32k_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>freetype</library>
|
||||
|
|
Loading…
Reference in a new issue