diff --git a/reactos/apps/tests/hello/hello.c b/reactos/apps/tests/hello/hello.c new file mode 100644 index 00000000000..528184c51fe --- /dev/null +++ b/reactos/apps/tests/hello/hello.c @@ -0,0 +1,10 @@ +#include +#include +#include + + +void main() +{ + NtDisplayString("Shell Starting...\n"); + ExitThread(0); +} diff --git a/reactos/apps/tests/hello/makefile b/reactos/apps/tests/hello/makefile index 8a51bce7b7f..3733e54a9ad 100644 --- a/reactos/apps/tests/hello/makefile +++ b/reactos/apps/tests/hello/makefile @@ -1,7 +1,9 @@ -all: test.bin +all: hello.bin -test.bin: test.o - $(LD) -Ttext 0x10000 test.o ../../lib/ntdll/ntdll.a -o test.exe - $(OBJCOPY) -O binary test.exe test.bin +OBJECTS = ../common/crt0.o hello.o + +hello.bin: $(OBJECTS) + $(LD) -Ttext 0x10000 $(OBJECTS) ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a -o hello.exe + $(OBJCOPY) -O binary hello.exe hello.bin include ../../rules.mak diff --git a/reactos/apps/tests/hello/test.asm b/reactos/apps/tests/hello/test.asm deleted file mode 100644 index a5e9306b5fe..00000000000 --- a/reactos/apps/tests/hello/test.asm +++ /dev/null @@ -1,11 +0,0 @@ -BITS 32 - -EXTERN _NtDisplayString - -_main: - push dword _string - call _NtDisplayString -l1: - jmp l1 - -_string db 'Hello world from user mode!',0xa,0 diff --git a/reactos/apps/utils/shell/shell.c b/reactos/apps/utils/shell/shell.c index edf9111503a..44869213b83 100644 --- a/reactos/apps/utils/shell/shell.c +++ b/reactos/apps/utils/shell/shell.c @@ -1,176 +1,218 @@ - -#include - -#include -#include -#include - -void debug_printf(char* fmt, ...) -{ - va_list args; - char buffer[255]; - - va_start(args,fmt); - vsprintf(buffer,fmt,args); - OutputDebugStringA(buffer); - va_end(args); -} - -HANDLE KeyboardHandle; - -void ExecuteCd(char* cmdline) -{ - UCHAR Buffer[255]; - - debug_printf("ExecuteCd(cmdline %s)\n",cmdline); - - if (cmdline[0] != '\\' && - cmdline[1] != ':') - { - GetCurrentDirectoryA(255,Buffer); - } - else - { - Buffer[0] = 0; - } - debug_printf("Buffer %s\n",Buffer); - - lstrcatA(Buffer,cmdline); - - debug_printf("Buffer %s\n",Buffer); - - if (Buffer[lstrlenA(Buffer)-1] != '\\') - { - lstrcatA(Buffer,"\\"); - } - debug_printf("Buffer %s\n",Buffer); - - SetCurrentDirectoryA(Buffer); -} - -void ExecuteDir(char* cmdline) -{ -} - -void ExecuteType(char* cmdline) -{ - HANDLE FileHandle; - char c; - DWORD Result; - - FileHandle = CreateFile(cmdline, - FILE_GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL); - while (ReadFile(FileHandle, - &c, - 1, - &Result, - NULL)) - { - debug_printf("%c",c); - c = 0; - } -} - -void ExecuteCommand(char* line) -{ - char* cmd; - char* tail; - - if (line[1] == ':' && line[2] == 0) - { - line[2] = '\\'; - line[3] = 0; - SetCurrentDirectoryA(line); - return; - } - - tail = line; - while ((*tail)!=' ' && (*tail)!=0) - { - tail++; - } - if ((*tail)==' ') - { - *tail = 0; - tail++; - } - cmd = line; - - debug_printf("cmd '%s' tail '%s'\n",cmd,tail); - - if (cmd==NULL) - { - return; - } - if (strcmp(cmd,"cd")==0) - { - ExecuteCd(tail); - return; - } - if (strcmp(cmd,"dir")==0) - { - ExecuteDir(tail); - return; - } - if (strcmp(cmd,"type")==0) - { - ExecuteType(tail); - return; - } - debug_printf("Unknown command\n"); -} - -void ReadLine(char* line) -{ - KEY_EVENT_RECORD KeyEvent; - DWORD Result; - UCHAR CurrentDir[255]; - - GetCurrentDirectoryA(255,CurrentDir); - debug_printf(CurrentDir); - - do - { - ReadFile(KeyboardHandle, - &KeyEvent, - sizeof(KEY_EVENT_RECORD), - &Result, - NULL); - if (KeyEvent.bKeyDown && KeyEvent.AsciiChar != 0) - { - debug_printf("%c",KeyEvent.AsciiChar); - *line = KeyEvent.AsciiChar; - line++; - } - } while (!(KeyEvent.bKeyDown && KeyEvent.AsciiChar == '\n')); - line--; - *line = 0; -} - -void main() -{ - static char line[255]; - - NtDisplayString("Shell Starting...\n"); - - KeyboardHandle = CreateFile("Keyboard", - FILE_GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL); - - SetCurrentDirectoryA("C:\\"); - - for(;;) - { - ReadLine(line); - ExecuteCommand(line); - } -} + +#include + +#include +#include +#include + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + OutputDebugStringA(buffer); + va_end(args); +} + +HANDLE KeyboardHandle; + +void ExecuteCd(char* cmdline) +{ + UCHAR Buffer[255]; + + debug_printf("ExecuteCd(cmdline %s)\n",cmdline); + + if (cmdline[0] != '\\' && + cmdline[1] != ':') + { + GetCurrentDirectoryA(255,Buffer); + } + else + { + Buffer[0] = 0; + } + debug_printf("Buffer %s\n",Buffer); + + lstrcatA(Buffer,cmdline); + + debug_printf("Buffer %s\n",Buffer); + + if (Buffer[lstrlenA(Buffer)-1] != '\\') + { + lstrcatA(Buffer,"\\"); + } + debug_printf("Buffer %s\n",Buffer); + + SetCurrentDirectoryA(Buffer); +} + +void ExecuteDir(char* cmdline) +{ + HANDLE shandle; + WIN32_FIND_DATA FindData; + + shandle = FindFirstFile("*.*",&FindData); + + if (shandle==INVALID_HANDLE_VALUE) + { + return; + } + do + { + debug_printf("Scanning %s\n",FindData.cFileName); + } while(FindNextFile(shandle,&FindData)); +} + +void ExecuteType(char* cmdline) +{ + HANDLE FileHandle; + char c; + DWORD Result; + + FileHandle = CreateFile(cmdline, + FILE_GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + while (ReadFile(FileHandle, + &c, + 1, + &Result, + NULL)) + { + debug_printf("%c",c); + c = 0; + } +} + +int ExecuteProcess(char* name, char* cmdline) +{ + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + char arguments; + + memset(&StartupInfo,0,sizeof(StartupInfo)); + StartupInfo.cb = sizeof(STARTUPINFO); + StartupInfo.lpTitle = name; + + return(CreateProcessA(name, + cmdline, + NULL, + NULL, + TRUE, + CREATE_NEW_CONSOLE, + NULL, + NULL, + &StartupInfo, + &ProcessInformation)); +} + +void ExecuteCommand(char* line) +{ + char* cmd; + char* tail; + + if (line[1] == ':' && line[2] == 0) + { + line[2] = '\\'; + line[3] = 0; + SetCurrentDirectoryA(line); + return; + } + + tail = line; + while ((*tail)!=' ' && (*tail)!=0) + { + tail++; + } + if ((*tail)==' ') + { + *tail = 0; + tail++; + } + cmd = line; + + debug_printf("cmd '%s' tail '%s'\n",cmd,tail); + + if (cmd==NULL) + { + return; + } + if (strcmp(cmd,"cd")==0) + { + ExecuteCd(tail); + return; + } + if (strcmp(cmd,"dir")==0) + { + ExecuteDir(tail); + return; + } + if (strcmp(cmd,"type")==0) + { + ExecuteType(tail); + return; + } + if (ExecuteProcess(cmd,tail)) + { + debug_printf("Done ExecuteProcess\n"); + return; + } + debug_printf("Unknown command\n"); +} + +void ReadLine(char* line) +{ + KEY_EVENT_RECORD KeyEvent; + DWORD Result; + UCHAR CurrentDir[255]; + + GetCurrentDirectoryA(255,CurrentDir); + debug_printf(CurrentDir); + + do + { + ReadFile(KeyboardHandle, + &KeyEvent, + sizeof(KEY_EVENT_RECORD), + &Result, + NULL); + if (KeyEvent.bKeyDown && KeyEvent.AsciiChar != 0) + { + debug_printf("%c",KeyEvent.AsciiChar); + *line = KeyEvent.AsciiChar; + line++; + } + } while (!(KeyEvent.bKeyDown && KeyEvent.AsciiChar == '\n')); + line--; + *line = 0; +} + +void main() +{ + static char line[255]; + + KERNEL32_Init(); + + NtDisplayString("Shell Starting...\n"); + + KeyboardHandle = CreateFile("Keyboard", + FILE_GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + + SetCurrentDirectoryA("C:\\"); + + for(;;) + { + ReadLine(line); + ExecuteCommand(line); + } +} diff --git a/reactos/include/ddk/zw.h b/reactos/include/ddk/zw.h index 1fe5ae97d4f..3604f561a7e 100644 --- a/reactos/include/ddk/zw.h +++ b/reactos/include/ddk/zw.h @@ -486,12 +486,7 @@ NtContinue( IN CINT IrqLevel ); -NTSTATUS -STDCALL -ZwContinue( - IN PCONTEXT Context, - IN CINT IrqLevel - ); +NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel); /* diff --git a/reactos/lib/crtdll/stdlib/malloc.c b/reactos/lib/crtdll/stdlib/malloc.c index 571b97b7adc..f368203c6e8 100644 --- a/reactos/lib/crtdll/stdlib/malloc.c +++ b/reactos/lib/crtdll/stdlib/malloc.c @@ -1,31 +1,34 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/malloc.c + * PURPOSE: stdc memory allocation functions + * PROGRAMMER: ?? + */ + +/* INCLUDES ******************************************************************/ + #include #include +/* FUNCTIONS *****************************************************************/ + void* malloc(size_t size) { - return(HeapAlloc(GetProcessHeap(), - 0, - size)); + return(HeapAlloc(GetProcessHeap(), 0, size)); } void free(void* ptr) { - HeapFree(GetProcessHeap(), - 0, - ptr); + HeapFree(GetProcessHeap(), 0, ptr); } void* calloc(size_t nmemb, size_t size) { - return(HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - nmemb*size)); + return(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nmemb*size)); } void* realloc(void* ptr, size_t size) { - return(HeapReAlloc(GetProcessHeap(), - 0, - ptr, - size)); + return(HeapReAlloc(GetProcessHeap(), 0, ptr, size)); } diff --git a/reactos/lib/kernel32/file/cnotify.c b/reactos/lib/kernel32/file/cnotify.c new file mode 100644 index 00000000000..1c89e56fadf --- /dev/null +++ b/reactos/lib/kernel32/file/cnotify.c @@ -0,0 +1,68 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ +#include +#include + +WINBOOL +FindCloseChangeNotification( + HANDLE hChangeHandle + ) +{ + return FALSE; +} + +HANDLE +STDCALL +FindFirstChangeNotificationA( + LPCSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ) +{ + ULONG i; + + WCHAR PathNameW[MAX_PATH]; + + + + + i = 0; + while ((*lpPathName)!=0 && i < MAX_PATH) + { + PathNameW[i] = *lpPathName; + lpPathName++; + i++; + } + PathNameW[i] = 0; + return FindFirstChangeNotificationW(PathNameW, bWatchSubtree, dwNotifyFilter ); + +} + +HANDLE +STDCALL +FindFirstChangeNotificationW( + LPCWSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ) +{ + return NULL; +} + +WINBOOL +STDCALL +FindNextChangeNotification( + HANDLE hChangeHandle + ) +{ + return FALSE; +} + + diff --git a/reactos/lib/kernel32/file/find-bak.c b/reactos/lib/kernel32/file/find-bak.c new file mode 100644 index 00000000000..59858799b63 --- /dev/null +++ b/reactos/lib/kernel32/file/find-bak.c @@ -0,0 +1,450 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ +#include +#include +#include + +typedef enum _FINDEX_INFO_LEVELS +{ + FindExSearchNameMatch, + FindExSearchLimitToDirectories, + FindExSearchLimitToDevices, + +} FINDEX_INFO_LEVELS ; + +typedef enum _FINDEX_SEARCH_OPS +{ + FindExInfoStandard + +} FINDEX_SEARCH_OPS; + +int wcharicmp ( WCHAR char1, WCHAR char2 ); + +WINBOOL +mfs_regexp(LPCWSTR lpFileName,LPCWSTR lpFilter); + +HANDLE +STDCALL +FindFirstFileW( + LPCWSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData + ); + +WINBOOL +STDCALL +FindNextFileW( + HANDLE hFind, + LPWIN32_FIND_DATA lpFindFileData + ); + +HANDLE +STDCALL +FindFirstFileExA( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ); + +HANDLE +STDCALL +FindFirstFileExW( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ); + +typedef struct _FIND_FILE_INFO +{ + ULONG Offset; + PVOID SearchFilter; + WCHAR FileName[MAX_PATH]; + WCHAR PathName[MAX_PATH]; + FILE_DIRECTORY_INFORMATION *FileDirectory; +} FIND_FILE_INFO; + +typedef struct _WIN32_FIND_DATAW { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + WCHAR cFileName[ MAX_PATH ]; + WCHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATAW, *LPWIN32_FIND_DATAW, *PWIN32_FIND_DATAW; + + +WINBOOL +STDCALL +FindClose( + HANDLE hFind + ) +{ + + if ( hFind == NULL) + return FALSE; + + + HeapFree(GetProcessHeap(),0,((FIND_FILE_INFO *)hFind)->FileDirectory); + HeapFree(GetProcessHeap(),0,hFind); + return TRUE; +} + + +HANDLE +STDCALL +FindFirstFileA( + LPCSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData + ) +{ + WIN32_FIND_DATA FindFileDataW; + WCHAR FileNameW[MAX_PATH]; + ULONG i; + + i = 0; + while ((*lpFileName)!=0 && i < MAX_PATH) + { + FileNameW[i] = *lpFileName; + lpFileName++; + i++; + } + FileNameW[i] = 0; + FindFirstFileW(FileNameW,&FindFileDataW); + + // converteer FindFileDataW + +} + +HANDLE +STDCALL +FindFirstFileW( + LPCWSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData + ) +{ + return FindFirstFileExW(lpFileName,FindExInfoStandard,lpFindFileData,FindExSearchNameMatch,NULL,0); +} + +WINBOOL +STDCALL +FindNextFileA( + HANDLE hFind, + LPWIN32_FIND_DATA lpFindFileData + ) +{ + WIN32_FIND_DATA FindFileDataW; + FindNextFileW(hFind,&FindFileDataW); + // converteer FindFileDataW +} + +WINBOOL +STDCALL +FindNextFileW( + HANDLE hFind, + LPWIN32_FIND_DATA lpFindFileData + ) +{ + int i; + WCHAR *pNameRead; + WCHAR FileName[MAX_PATH]; + + FIND_FILE_INFO *FindPtr = hFind; + FILE_DIRECTORY_INFORMATION *FileDirectory; + + if ( FindPtr == NULL ) + return FALSE; + + /* Try to find a file */ + FileDirectory = FindPtr->Offset + FindPtr->FileDirectory; + while ( FileDirectory->NextEntryOffset != 0 ) { + + pNameRead = FileDirectory->FileName; + FindPtr->Offset += FileDirectory->NextEntryOffset; + for(i=0;iFileNameLength;i++) + dprintf("%c\n",(char)pNameRead[i]); + if (mfs_regexp(pNameRead, FindPtr->FileName)) + { + /* We found one! */ + if (FindPtr->PathName[0] != L'\0') + { + lstrcpyW(lpFindFileData->cFileName, FindPtr->PathName); + lstrcatW(lpFindFileData->cFileName, L"/"); + lstrcatW(lpFindFileData->cFileName, pNameRead); + } + else + + lstrcpyW(lpFindFileData->cFileName, pNameRead); + + + + lstrcpyW(lpFindFileData->cAlternateFileName, L""); + lpFindFileData->dwReserved0 = 0; + lpFindFileData->dwReserved1 = 0; + return TRUE; + } + FileDirectory = FindPtr->Offset + FindPtr->FileDirectory; + } + return FALSE; +} + + +HANDLE +STDCALL +FindFirstFileExA( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ) +{ + WCHAR FileNameW[MAX_PATH]; + WIN32_FIND_DATAW FindFileDataW; + FindFirstFileExW(FileNameW,fInfoLevelId,&FindFileDataW,fSearchOp,lpSearchFilter,dwAdditionalFlags); + // conerteer FindFileDataW + +} + +HANDLE +STDCALL +FindFirstFileExW( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ) +{ + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE FileHandle = NULL; + FIND_FILE_INFO *hFind; + WCHAR *FilePart; + UNICODE_STRING FileNameString, PathNameString; + OBJECT_ATTRIBUTES ObjectAttributes; + + + ACCESS_MASK DesiredAccess=FILE_READ_DATA; + + ULONG FileAttributes=FILE_ATTRIBUTE_DIRECTORY; + ULONG ShareAccess=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + ULONG CreateDisposition=FILE_OPEN; + ULONG CreateOptions=FILE_DIRECTORY_FILE; + + + hFind = HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,sizeof(FIND_FILE_INFO)); + + hFind->FileDirectory = HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,8192); + + + + /* Try to find a path and a filename in the passed filename */ + + lstrcpyW(hFind->PathName, lpFileName); + FilePart = wcsrchr(hFind->PathName, '\\'); + + if (FilePart == NULL){ + GetCurrentDirectory(MAX_PATH, hFind->PathName); + lstrcpyW(hFind->FileName, lpFileName); + } + else { + FilePart[0] = L'\0'; + lstrcpyW(hFind->FileName, &FilePart[1]); + } + + hFind->Offset = 0; + + + PathNameString.Length = lstrlenW(hFind->PathName)*sizeof(WCHAR); + PathNameString.Buffer = hFind->PathName; + PathNameString.MaximumLength = FileNameString.Length; + + + FileNameString.Length = lstrlenW(hFind->FileName)*sizeof(WCHAR); + FileNameString.Buffer = hFind->FileName; + FileNameString.MaximumLength = FileNameString.Length; + + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &PathNameString; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + + + + + + errCode = NtCreateFile( + &FileHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, // AllocationSize + FileAttributes, + ShareAccess, + CreateDisposition, + CreateOptions, + NULL, // EaBuffer + 0); // + + if ( !NT_SUCCESS(errCode) ) { + printf("%x\n",errCode); + return NULL; + } + + errCode = NtQueryDirectoryFile( + FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + hFind->FileDirectory, + 8192, + FileDirectoryInformation, + FALSE, + &FileNameString, + FALSE + ); + if ( !NT_SUCCESS(errCode) ) { + printf("%x\n",errCode); + return NULL; + } + + + + + if ( FindNextFileW(hFind,lpFindFileData) ) + return hFind; + else { + FindClose(hFind); + return NULL; + } + return NULL; +} + +/************************************************************************/ +WINBOOL +mfs_regexp(LPCWSTR lpFileName,LPCWSTR lpFilter) +{ + /* The following code is provided by Tarang and I trust him... + */ + LPWSTR lpTempFileName = (LPWSTR)lpFileName; + LPWSTR lpTempFilter = (LPWSTR)lpFilter; + WCHAR TempToken [ 2 ]; + WCHAR TempFilter [ 2 ]; + WINBOOL Matched = FALSE; + + if ( ( ! (LPWSTR)lpFileName ) || ( ! *(LPWSTR)lpFileName ) || + ( ! (LPWSTR)lpFilter ) || ( ! *(LPWSTR)lpFilter ) ) + return 0L; + + if ( ! lstrcmpW ( ( LPSTR )lpFilter, "*.*" ) ) + { + wsprintf ( TempFilter, "*" ); + lpTempFilter = TempFilter; + lpFilter = TempFilter; + } + + while ( ( lpTempFilter ) && ( *lpTempFilter ) && ( ! Matched ) ) + { + memset ( TempToken, 0, sizeof ( TempToken ) ); + switch ( *lpTempFilter ) + { + default: + if ( wcharicmp ( *lpTempFileName, *lpTempFilter ) ) + { + lpTempFileName = (LPWSTR)lpFileName; + lpTempFilter = wcspbrk ( lpTempFilter, L" ,;" ); + if ( lpTempFilter ) + lpTempFilter+=sizeof(WCHAR); + } + else + { + lpTempFilter+=sizeof(WCHAR); + lpTempFileName+=sizeof(WCHAR); + switch ( *lpTempFilter ) + { + default: + break; + + case L'\0': + case L' ': + case L',': + case L';': + if ( ! *lpTempFileName ) + Matched = TRUE; + break; + } + } + break; + + case L'?': + lpTempFilter+=sizeof(WCHAR); + lpTempFileName+=sizeof(WCHAR); + break; + + case L'*': + lpTempFilter += sizeof(WCHAR); + if ( ! ( TempToken [ 0 ] = *( lpTempFilter ) ) ) + Matched = TRUE; + else + { + lpTempFilter+=sizeof(WCHAR); + while ( ( lpTempFileName = wcspbrk ( lpTempFileName, TempToken ) ) && + ( ! Matched ) ) { + lpTempFileName+= sizeof(WCHAR); + Matched = mfs_regexp ( lpTempFileName, lpTempFilter ); + } + if ( ( ! lpTempFileName ) && ( ! Matched ) ) + { + lpTempFileName = (LPWSTR)lpFileName; + lpTempFilter = wcspbrk ( lpTempFilter, L" ,;" ); + if ( lpTempFilter ) + lpTempFilter+=sizeof(WCHAR); + } + } + break; + + case L'\0': + case L' ': + case L',': + case L';': + Matched = TRUE; + break; + } + } + + return (DWORD)Matched; + + +} + +int wcharicmp ( WCHAR char1, WCHAR char2 ) +{ + WCHAR Char1 = ( L'a' <= char1 ) && ( char1 <= L'z' ) ? + char1 - L'a' + L'A' : char1; + WCHAR Char2 = ( L'a' <= char2 ) && ( char2 <= L'z' ) ? + char2 - L'a' + L'A' : char2; + return ( Char2 - Char1 ); +} diff --git a/reactos/lib/kernel32/file/find.c b/reactos/lib/kernel32/file/find.c index bf2dbe79b24..61b0b5b88ef 100644 --- a/reactos/lib/kernel32/file/find.c +++ b/reactos/lib/kernel32/file/find.c @@ -1,521 +1,129 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/file/find.c - * PURPOSE: Find functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * UPDATE HISTORY: - * Created 01/11/98 - */ -#include -#include - -typedef enum _FINDEX_INFO_LEVELS -{ - FindExSearchNameMatch, - FindExSearchLimitToDirectories, - FindExSearchLimitToDevices, - -} FINDEX_INFO_LEVELS ; - -typedef enum _FINDEX_SEARCH_OPS -{ - FindExInfoStandard - -} FINDEX_SEARCH_OPS; - -int wcharicmp ( WCHAR char1, WCHAR char2 ); - -WINBOOL -mfs_regexp(LPCWSTR lpFileName,LPCWSTR lpFilter); - -HANDLE -STDCALL -FindFirstFileW( - LPWSTR lpFileName, - LPWIN32_FIND_DATA lpFindFileData - ); - -WINBOOL -STDCALL -FindNextFileW( - HANDLE hFind, - LPWIN32_FIND_DATA lpFindFileData - ); - -HANDLE -STDCALL -FindFirstFileExA( - LPCSTR lpFileName, - FINDEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFindFileData, - FINDEX_SEARCH_OPS fSearchOp, - LPVOID lpSearchFilter, - DWORD dwAdditionalFlags - ); - -HANDLE -STDCALL -FindFirstFileExW( - LPCWSTR lpFileName, - FINDEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFindFileData, - FINDEX_SEARCH_OPS fSearchOp, - LPVOID lpSearchFilter, - DWORD dwAdditionalFlags - ); - -typedef struct _FIND_FILE_INFO -{ - ULONG Offset; - PVOID SearchFilter; - WCHAR FileName[MAX_PATH]; - WCHAR PathName[MAX_PATH]; - FILE_DIRECTORY_INFORMATION *FileDirectory; -} FIND_FILE_INFO; - - -/* - -typedef struct _WIN32_FIND_DATAW { - DWORD dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - DWORD nFileSizeHigh; - DWORD nFileSizeLow; - DWORD dwReserved0; - DWORD dwReserved1; - WCHAR cFileName[ MAX_PATH ]; - WCHAR cAlternateFileName[ 14 ]; -} WIN32_FIND_DATAW, *LPWIN32_FIND_DATAW, *PWIN32_FIND_DATAW; -*/ - -WINBOOL -STDCALL -FindClose( - HANDLE hFind - ) -{ - - if ( hFind == NULL) - return FALSE; - - - HeapFree(GetProcessHeap(),0,((FIND_FILE_INFO *)hFind)->FileDirectory); - HeapFree(GetProcessHeap(),0,hFind); - return TRUE; -} - - -HANDLE -STDCALL -FindFirstFileA( - LPCSTR lpFileName, - LPWIN32_FIND_DATA lpFindFileData - ) -{ - WIN32_FIND_DATA FindFileDataW; - WCHAR FileNameW[MAX_PATH]; - ULONG i; - - i = 0; - while ((*lpFileName)!=0 && i < MAX_PATH) - { - FileNameW[i] = *lpFileName; - lpFileName++; - i++; - } - FileNameW[i] = 0; - FindFirstFileW(FileNameW,&FindFileDataW); - - // converteer FindFileDataW - -} - -HANDLE -STDCALL -FindFirstFileW( - LPWSTR lpFileName, - LPWIN32_FIND_DATA lpFindFileData - ) -{ - return FindFirstFileExW(lpFileName,FindExInfoStandard,lpFindFileData,FindExSearchNameMatch,NULL,0); -} - -WINBOOL -STDCALL -FindNextFileA( - HANDLE hFind, - LPWIN32_FIND_DATA lpFindFileData - ) -{ - WIN32_FIND_DATA FindFileDataW; - FindNextFileW(hFind,&FindFileDataW); - // converteer FindFileDataW -} - -WINBOOL -STDCALL -FindNextFileW( - HANDLE hFind, - LPWIN32_FIND_DATA lpFindFileData - ) -{ - int i; - WCHAR *pNameRead; - WCHAR FileName[MAX_PATH]; - - FIND_FILE_INFO *FindPtr = hFind; - FILE_DIRECTORY_INFORMATION *FileDirectory; - - if ( FindPtr == NULL ) - return FALSE; - - /* Try to find a file */ - FileDirectory = FindPtr->Offset + FindPtr->FileDirectory; - while ( FileDirectory->NextEntryOffset != 0 ) { - - pNameRead = FileDirectory->FileName; - FindPtr->Offset += FileDirectory->NextEntryOffset; - for(i=0;iFileNameLength;i++) - printf("%c\n",(char)pNameRead[i]); - if (mfs_regexp(pNameRead, FindPtr->FileName)) - { - /* We found one! */ - if (FindPtr->PathName[0] != L'\0') - { - lstrcpyW(lpFindFileData->cFileName, FindPtr->PathName); - lstrcatW(lpFindFileData->cFileName, L"/"); - lstrcatW(lpFindFileData->cFileName, pNameRead); - } - else - - lstrcpyW(lpFindFileData->cFileName, pNameRead); - - - - lstrcpyW(lpFindFileData->cAlternateFileName, L""); - lpFindFileData->dwReserved0 = 0; - lpFindFileData->dwReserved1 = 0; - return TRUE; - } - FileDirectory = FindPtr->Offset + FindPtr->FileDirectory; - } - return FALSE; -} - - -HANDLE -STDCALL -FindFirstFileExA( - LPCSTR lpFileName, - FINDEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFindFileData, - FINDEX_SEARCH_OPS fSearchOp, - LPVOID lpSearchFilter, - DWORD dwAdditionalFlags - ) -{ - WCHAR FileNameW[MAX_PATH]; - WIN32_FIND_DATAW FindFileDataW; - FindFirstFileExW(FileNameW,fInfoLevelId,&FindFileDataW,fSearchOp,lpSearchFilter,dwAdditionalFlags); - // conerteer FindFileDataW - -} - -HANDLE -STDCALL -FindFirstFileExW( - LPCWSTR lpFileName, - FINDEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFindFileData, - FINDEX_SEARCH_OPS fSearchOp, - LPVOID lpSearchFilter, - DWORD dwAdditionalFlags - ) -{ - NTSTATUS errCode; - IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle = NULL; - FIND_FILE_INFO *hFind; - WCHAR *FilePart; - UNICODE_STRING FileNameString, PathNameString; - OBJECT_ATTRIBUTES ObjectAttributes; - - - ACCESS_MASK DesiredAccess=FILE_READ_DATA; - - ULONG FileAttributes=FILE_ATTRIBUTE_DIRECTORY; - ULONG ShareAccess=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - ULONG CreateDisposition=FILE_OPEN; - ULONG CreateOptions=FILE_DIRECTORY_FILE; - - - hFind = HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,sizeof(FIND_FILE_INFO)); - - hFind->FileDirectory = HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,8192); - - - - /* Try to find a path and a filename in the passed filename */ - - lstrcpyW(hFind->PathName, lpFileName); - FilePart = wcsrchr(hFind->PathName, '\\'); - - if (FilePart == NULL){ - GetCurrentDirectory(MAX_PATH, hFind->PathName); - lstrcpyW(hFind->FileName, lpFileName); - } - else { - FilePart[0] = L'\0'; - lstrcpyW(hFind->FileName, &FilePart[1]); - } - - hFind->Offset = 0; - - - PathNameString.Length = lstrlenW(hFind->PathName)*sizeof(WCHAR); - PathNameString.Buffer = hFind->PathName; - PathNameString.MaximumLength = FileNameString.Length; - - - FileNameString.Length = lstrlenW(hFind->FileName)*sizeof(WCHAR); - FileNameString.Buffer = hFind->FileName; - FileNameString.MaximumLength = FileNameString.Length; - - - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = NULL; - ObjectAttributes.ObjectName = &PathNameString; - ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; - ObjectAttributes.SecurityDescriptor = NULL; - ObjectAttributes.SecurityQualityOfService = NULL; - - - - - - - errCode = NtCreateFile( - &FileHandle, - DesiredAccess, - &ObjectAttributes, - &IoStatusBlock, - NULL, // AllocationSize - FileAttributes, - ShareAccess, - CreateDisposition, - CreateOptions, - NULL, // EaBuffer - 0); // - - if ( !NT_SUCCESS(errCode) ) { - printf("%x\n",errCode); - return NULL; - } - - errCode = NtQueryDirectoryFile( - FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - hFind->FileDirectory, - 8192, - FileDirectoryInformation, - FALSE, - &FileNameString, - FALSE - ); - if ( !NT_SUCCESS(errCode) ) { - printf("%x\n",errCode); - return NULL; - } - - - - - if ( FindNextFileW(hFind,lpFindFileData) ) - return hFind; - else { - FindClose(hFind); - return NULL; - } - return NULL; -} - - -WINBOOL -FindCloseChangeNotification( - HANDLE hChangeHandle - ) -{ - return FALSE; -} - -HANDLE -STDCALL -FindFirstChangeNotificationA( - LPCSTR lpPathName, - WINBOOL bWatchSubtree, - DWORD dwNotifyFilter - ) -{ - ULONG i; - - WCHAR PathNameW[MAX_PATH]; - - - - - i = 0; - while ((*lpPathName)!=0 && i < MAX_PATH) - { - PathNameW[i] = *lpPathName; - lpPathName++; - i++; - } - PathNameW[i] = 0; - return FindFirstChangeNotificationW(PathNameW, bWatchSubtree, dwNotifyFilter ); - -} - -HANDLE -STDCALL -FindFirstChangeNotificationW( - LPCWSTR lpPathName, - WINBOOL bWatchSubtree, - DWORD dwNotifyFilter - ) -{ - return NULL; -} - -WINBOOL -STDCALL -FindNextChangeNotification( - HANDLE hChangeHandle - ) -{ - return FALSE; -} - - -/************************************************************************/ -WINBOOL -mfs_regexp(LPCWSTR lpFileName,LPCWSTR lpFilter) -{ - /* The following code is provided by Tarang and I trust him... - */ - LPWSTR lpTempFileName = (LPWSTR)lpFileName; - LPWSTR lpTempFilter = (LPWSTR)lpFilter; - WCHAR TempToken [ 2 ]; - WCHAR TempFilter [ 2 ]; - WINBOOL Matched = FALSE; - - if ( ( ! (LPWSTR)lpFileName ) || ( ! *(LPWSTR)lpFileName ) || - ( ! (LPWSTR)lpFilter ) || ( ! *(LPWSTR)lpFilter ) ) - return 0L; - - if ( ! lstrcmpW ( ( LPSTR )lpFilter, "*.*" ) ) - { - wsprintf ( TempFilter, "*" ); - lpTempFilter = TempFilter; - lpFilter = TempFilter; - } - - while ( ( lpTempFilter ) && ( *lpTempFilter ) && ( ! Matched ) ) - { - memset ( TempToken, 0, sizeof ( TempToken ) ); - switch ( *lpTempFilter ) - { - default: - if ( wcharicmp ( *lpTempFileName, *lpTempFilter ) ) - { - lpTempFileName = (LPWSTR)lpFileName; - lpTempFilter = wcspbrk ( lpTempFilter, L" ,;" ); - if ( lpTempFilter ) - lpTempFilter+=sizeof(WCHAR); - } - else - { - lpTempFilter+=sizeof(WCHAR); - lpTempFileName+=sizeof(WCHAR); - switch ( *lpTempFilter ) - { - default: - break; - - case L'\0': - case L' ': - case L',': - case L';': - if ( ! *lpTempFileName ) - Matched = TRUE; - break; - } - } - break; - - case L'?': - lpTempFilter+=sizeof(WCHAR); - lpTempFileName+=sizeof(WCHAR); - break; - - case L'*': - lpTempFilter += sizeof(WCHAR); - if ( ! ( TempToken [ 0 ] = *( lpTempFilter ) ) ) - Matched = TRUE; - else - { - lpTempFilter+=sizeof(WCHAR); - while ( ( lpTempFileName = wcspbrk ( lpTempFileName, TempToken ) ) && - ( ! Matched ) ) { - lpTempFileName+= sizeof(WCHAR); - Matched = mfs_regexp ( lpTempFileName, lpTempFilter ); - } - if ( ( ! lpTempFileName ) && ( ! Matched ) ) - { - lpTempFileName = (LPWSTR)lpFileName; - lpTempFilter = wcspbrk ( lpTempFilter, L" ,;" ); - if ( lpTempFilter ) - lpTempFilter+=sizeof(WCHAR); - } - } - break; - - case L'\0': - case L' ': - case L',': - case L';': - Matched = TRUE; - break; - } - } - - return (DWORD)Matched; - - -} - -int wcharicmp ( WCHAR char1, WCHAR char2 ) -{ - WCHAR Char1 = ( L'a' <= char1 ) && ( char1 <= L'z' ) ? - char1 - L'a' + L'A' : char1; - WCHAR Char2 = ( L'a' <= char2 ) && ( char2 <= L'z' ) ? - char2 - L'a' + L'A' : char2; - return ( Char2 - Char1 ); -} - - - - - - - - - - - - +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +/* TYPES ********************************************************************/ + +typedef struct _KERNEL32_FIND_FILE_DATA +{ + HANDLE DirectoryHandle; + FILE_DIRECTORY_INFORMATION FileInfo; +} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA; + +/* FUNCTIONS *****************************************************************/ + +HANDLE FindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) +{ + WCHAR lpFileNameW[MAX_PATH]; + ULONG i; + + i = 0; + while (lpFileName[i]!=0) + { + lpFileNameW[i] = lpFileName[i]; + i++; + } + + return(FindFirstFileW(lpFileNameW,lpFindFileData)); +} + +WINBOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) +{ + return(FindNextFileW(hFindFile, lpFindFileData)); +} + +BOOL FindClose(HANDLE hFindFile) +{ + PKERNEL32_FIND_FILE_DATA IData; + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + NtClose(IData->DirectoryHandle); + HeapFree(GetProcessHeap(), 0, IData); + return(TRUE); +} + +HANDLE STDCALL FindFirstFileW(LPCWSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData) +{ + WCHAR CurrentDirectory[MAX_PATH]; + WCHAR Pattern[MAX_PATH]; + WCHAR Directory[MAX_PATH]; + PWSTR End; + PKERNEL32_FIND_FILE_DATA IData; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DirectoryNameStr; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING PatternStr; + + dprintf("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n", + lpFileName, lpFindFileData); + + GetCurrentDirectoryW(MAX_PATH, CurrentDirectory); + Directory[0] = '\\'; + Directory[1] = '?'; + Directory[2] = '?'; + Directory[3] = '\\'; + Directory[4] = 0; + wcscat(Directory, CurrentDirectory); + wcscat(Directory, lpFileName); + End = wcschr(Directory, '\\'); + *End = 0; + + wcscpy(Pattern, End+1); + + dprintf("Directory %w End %w\n",Directory,End); + + IData = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(KERNEL32_FIND_FILE_DATA)); + + RtlInitUnicodeString(&DirectoryNameStr, Directory); + InitializeObjectAttributes(&ObjectAttributes, + &DirectoryNameStr, + 0, + NULL, + NULL); + + if (ZwOpenFile(&IData->DirectoryHandle, + FILE_TRAVERSE, + &ObjectAttributes, + &IoStatusBlock, + 0, + OPEN_EXISTING)!=STATUS_SUCCESS) + { + return(NULL); + } + + RtlInitUnicodeString(&PatternStr, Pattern); + + NtQueryDirectoryFile(IData->DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + (PVOID)&IData->FileInfo, + sizeof(IData->FileInfo), + FileDirectoryInformation, + TRUE, + &PatternStr, + FALSE); + + return(IData); +} + +WINBOOL STDCALL FindNextFileW(HANDLE hFindFile, + LPWIN32_FIND_DATA lpFindFileData) +{ +} diff --git a/reactos/lib/kernel32/file/find1.c b/reactos/lib/kernel32/file/find1.c new file mode 100644 index 00000000000..7dc6ed9d60e --- /dev/null +++ b/reactos/lib/kernel32/file/find1.c @@ -0,0 +1,124 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +/* TYPES ********************************************************************/ + +typedef struct _KERNEL32_FIND_FILE_DATA; +{ + HANDLE DirectoryHandle; + FILE_DIRECTORY_INFORMATION FileInfo; +} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA; + +/* FUNCTIONS *****************************************************************/ + +HANDLE FindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) +{ + WCHAR lpFileNameW[MAX_PATH]; + ULONG i; + + i = 0; + while (lpFileName[i]!=0) + { + lpFileName[i] = lpFileName[i]; + i++; + } + + return(FindFirstFileW(lpFileName,lpFindFileData)); +} + +BOOLEAN FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) +{ + return(FindNextFileW(hFindFile, lpFindFileData)); +} + +BOOL FindClose(HANDLE hFindFile) +{ + PKERNEL32_FIND_FILE_DATA IData; + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + NtClose(IData->DirectoryHandle); + HeapFree(IData); +} + +HANDLE STDCALL FindFirstFileW(LPCWSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData) +{ + WCHAR CurrentDirectory[MAX_PATH]; + WCHAR Pattern[MAX_PATH]; + WCHAR Directory[MAX_PATH]; + PWSTR End; + PKERNEL32_FIND_FILE_DATA IData; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DirectoryNameStr; + IO_STATUS_BLOCK IoStatusBlock; + + dprintf("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n", + lpFileName, lpFindFileData); + + GetCurrentDirectoryW(MAX_PATH, CurrentDirectory); + Directory[0] = '\\'; + Directory[1] = '?'; + Directory[2] = '?'; + Directory[3] = '\\'; + Directory[4] = 0; + wstrcat(Directory, CurrentDirectory); + wstrcat(Directory, lpFileName); + End = wstrchr(Directory, '\\'); + *End = 0; + + wstrcpy(Pattern, End+1); + + dprintf("Directory %w End %w\n",Directory,End); + + IData = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(KERNEL32_FIND_FILE_DATA)); + + RtlInitUnicodeString(&DirectoryNameStr, Directory); + InitializeObjectAttributes(&ObjectAttributes, + &DirectoryNameStr, + 0, + NULL, + NULL); + + if (ZwOpenFile(&IData->DirectoryHandle, + FILE_TRAVERSE, + &ObjectAttributes, + 0, + OPEN_EXISTING)!=STATUS_SUCCESS) + { + return(NULL); + } + + NtQueryDirectoryFile(IData->DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + &IData->FileInfo, + sizeof(IData->FileInfo), + FileDirectoryInformation, + TRUE, + Pattern, + FALSE); + + return(IData); +} + +WINBOOL STDCALL FindNextFileW(HANDLE hFindFile, + LPWIN32_FIND_DATA lpFindFileData) +{ +} diff --git a/reactos/lib/kernel32/internal/init.c b/reactos/lib/kernel32/internal/init.c new file mode 100644 index 00000000000..c95b261e570 --- /dev/null +++ b/reactos/lib/kernel32/internal/init.c @@ -0,0 +1,8 @@ +#include +#include +#include + +VOID KERNEL32_Init(VOID) +{ + __HeapInit(0, 4*1024*1024, 4*1024*1024); +} diff --git a/reactos/lib/kernel32/internal/vsprintf.c b/reactos/lib/kernel32/internal/vsprintf.c deleted file mode 100644 index e1ef386667a..00000000000 --- a/reactos/lib/kernel32/internal/vsprintf.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * linux/lib/vsprintf.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ -/* - * Wirzenius wrote this portably, Torvalds fucked it up :-) - */ - -/* - * Appropiated for the reactos kernel, March 1998 -- David Welch - */ - -#include - -#include -#include -#include - -unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) -{ - unsigned long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - -/* we use this so that we can do without the ctype library */ -#define is_digit(c) ((c) >= '0' && (c) <= '9') - -static int skip_atoi(const char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -#define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -static char * number(char * str, long num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[66]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; -} - -int vsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - unsigned long num; - int i, base; - char * str; - const char *s; - const short int* sw; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - - for (str=buf ; *fmt ; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 'w': - sw = va_arg(args,short int *); -// DPRINT("L %x\n",sw); - if (sw==NULL) - { -// CHECKPOINT; - s = ""; - while ((*s)!=0) - { - *str++ = *s++; - } -// CHECKPOINT; -// DbgPrint("str %x\n",str); - } - else - { - while ((*sw)!=0) - { - *str++ = (char)(*sw++); - } - } -// CHECKPOINT; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = ""; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'b': - base = 2; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - if (*fmt != '%') - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (qualifier == 'h') - if (flags & SIGN) - num = va_arg(args, short); - else - num = va_arg(args, unsigned short); - else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str-buf; -} - -int sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - -int wsprintfA(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - -int wsprintfW(unsigned short * buf, const unsigned short *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - //i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - - -unsigned short towupper(unsigned short w) -{ - if ( w < L'A' ) - return w + 'A'; - else - return w; -} - -char iswlower(unsigned short w) -{ - if ( w < L'A' ) - return 1; - else - return 0; -} - diff --git a/reactos/lib/kernel32/makefile b/reactos/lib/kernel32/makefile index b920e5dafcf..531b12fd6b6 100644 --- a/reactos/lib/kernel32/makefile +++ b/reactos/lib/kernel32/makefile @@ -6,17 +6,17 @@ MISC_OBJECTS = misc/error.o misc/atom.o misc/handle.o misc/env.o misc/dllmain.o FILE_OBJECTS = file/file.o file/curdir.o file/lfile.o file/dir.o \ file/iocompl.o file/volume.o file/deviceio.o file/dosdev.o \ - file/create.o + file/create.o file/find.o file/cnotify.o MEM_OBJECTS = mem/virtual.o mem/heap.o mem/utils.o THREAD_OBJECTS = thread/thread.o -PROCESS_OBJECTS = process/proc.o +PROCESS_OBJECTS = process/proc.o process/cmdline.o STRING_OBJECTS = string/lstring.o -INTERNAL_OBJECTS = internal/dprintf.o +INTERNAL_OBJECTS = internal/dprintf.o internal/init.o EXCEPT_OBJECTS = except/except.o @@ -29,7 +29,7 @@ OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \ kernel32.a: $(OBJECTS) - $(AR) vrcs kernel32.a $(OBJECTS) + $(AR) rcs kernel32.a $(OBJECTS) dummy: diff --git a/reactos/lib/kernel32/mem/heap.c b/reactos/lib/kernel32/mem/heap.c index 61acdab5c9e..053415ca6a5 100644 --- a/reactos/lib/kernel32/mem/heap.c +++ b/reactos/lib/kernel32/mem/heap.c @@ -44,7 +44,7 @@ static HEAP_BUCKET __HeapDefaultBuckets[]= { NULL, 256, 15, 4088 }, }; -PHEAP __ProcessHeap; +PHEAP __ProcessHeap = NULL; static BOOL __HeapCommit(PHEAP pheap, LPVOID start, LPVOID end); static BOOL __HeapDecommit(PHEAP pheap, LPVOID start, LPVOID end); @@ -61,8 +61,6 @@ static BOOL __HeapFreeFragment(PHEAP pheap, ULONG flags, LPVOID ptr); static PHEAP __HeapPrepare(LPVOID base, ULONG minsize, ULONG maxsize, ULONG flags); - - /********************************************************************* * __HeapCommit * * * @@ -625,7 +623,7 @@ PHEAP __HeapPrepare(LPVOID base, ULONG minsize, ULONG maxsize, ULONG flags) VOID WINAPI __HeapInit(LPVOID base, ULONG minsize, ULONG maxsize) { - VirtualAlloc(base,maxsize,MEM_RESERVE,PAGE_READWRITE); + base = VirtualAlloc(base,maxsize,MEM_RESERVE,PAGE_READWRITE); VirtualAlloc(base,PAGESIZE,MEM_COMMIT,PAGE_READWRITE); __HeapPrepare(base, minsize, maxsize, 0); diff --git a/reactos/lib/kernel32/process/cmdline.c b/reactos/lib/kernel32/process/cmdline.c new file mode 100644 index 00000000000..a764d852cb7 --- /dev/null +++ b/reactos/lib/kernel32/process/cmdline.c @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/proc/proc.c + * PURPOSE: Process functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#define UNICODE +#include +#include +#include +#include +#include +#include +#include + +/* GLOBALS ******************************************************************/ + +unsigned char CommandLineA[MAX_PATH]; + +/* FUNCTIONS ****************************************************************/ + +LPSTR STDCALL GetCommandLineA(VOID) +{ + WCHAR *CommandLineW; + ULONG i = 0; + + CommandLineW = GetCommandLineW(); + while ((CommandLineW[i])!=0 && i < MAX_PATH) + { + CommandLineA[i] = (unsigned char)CommandLineW[i]; + i++; + } + CommandLineA[i] = 0; + return CommandLineA; +} + +LPWSTR STDCALL GetCommandLineW(VOID) +{ + return GetCurrentPeb()->StartupInfo->CommandLine; +} + diff --git a/reactos/lib/kernel32/process/proc.c b/reactos/lib/kernel32/process/proc.c index 24208ab083d..401858aafe8 100644 --- a/reactos/lib/kernel32/process/proc.c +++ b/reactos/lib/kernel32/process/proc.c @@ -7,6 +7,9 @@ * UPDATE HISTORY: * Created 01/11/98 */ + +/* INCLUDES ****************************************************************/ + #define UNICODE #include #include @@ -16,6 +19,8 @@ #include #include +/* GLOBALS *****************************************************************/ + extern NT_PEB *CurrentPeb; extern NT_PEB Peb; @@ -23,10 +28,9 @@ WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; VOID RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle); -WINBOOL -STDCALL -GetProcessId(HANDLE hProcess, LPDWORD lpProcessId ); +/* FUNCTIONS ****************************************************************/ +WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId); NT_PEB *GetCurrentPeb(VOID) { @@ -46,304 +50,334 @@ HANDLE STDCALL GetCurrentThread(VOID) return (HANDLE)NtCurrentThread(); } -DWORD -STDCALL -GetCurrentProcessId(VOID) -{ - - return (DWORD)(GetTeb()->Cid).UniqueProcess; - - +DWORD STDCALL GetCurrentProcessId(VOID) +{ + return (DWORD)(GetTeb()->Cid).UniqueProcess; } -unsigned char CommandLineA[MAX_PATH]; - -LPSTR -STDCALL -GetCommandLineA( - VOID - ) +WINBOOL STDCALL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode ) { - WCHAR *CommandLineW; - ULONG i = 0; - - CommandLineW = GetCommandLineW(); - while ((CommandLineW[i])!=0 && i < MAX_PATH) - { - CommandLineA[i] = (unsigned char)CommandLineW[i]; - i++; - } - CommandLineA[i] = 0; - return CommandLineA; -} -LPWSTR -STDCALL -GetCommandLineW( - VOID - ) -{ - return GetCurrentPeb()->StartupInfo->CommandLine; -} - - -WINBOOL -STDCALL -GetExitCodeProcess( - HANDLE hProcess, - LPDWORD lpExitCode - ) -{ - NTSTATUS errCode; - PROCESS_BASIC_INFORMATION ProcessBasic; - ULONG BytesWritten; - - errCode = NtQueryInformationProcess(hProcess,ProcessBasicInformation,&ProcessBasic,sizeof(PROCESS_BASIC_INFORMATION),&BytesWritten); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - memcpy( lpExitCode ,&ProcessBasic.ExitStatus,sizeof(DWORD)); - return TRUE; - -} - -WINBOOL -STDCALL -GetProcessId( - HANDLE hProcess, - LPDWORD lpProcessId - ) -{ - NTSTATUS errCode; - PROCESS_BASIC_INFORMATION ProcessBasic; - ULONG BytesWritten; - - errCode = NtQueryInformationProcess(hProcess,ProcessBasicInformation,&ProcessBasic,sizeof(PROCESS_BASIC_INFORMATION),&BytesWritten); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD)); - return TRUE; - -} - -WINBOOL -STDCALL -CreateProcessA( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - WINBOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFO lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation - ) -{ - WCHAR ApplicationNameW[MAX_PATH]; - WCHAR CommandLineW[MAX_PATH]; - WCHAR CurrentDirectoryW[MAX_PATH]; - - - ULONG i; - - i = 0; - while ((*lpApplicationName)!=0 && i < MAX_PATH) - { - ApplicationNameW[i] = *lpApplicationName; - lpApplicationName++; - i++; - } - ApplicationNameW[i] = 0; - - - i = 0; - while ((*lpCommandLine)!=0 && i < MAX_PATH) - { - CommandLineW[i] = *lpCommandLine; - lpCommandLine++; - i++; - } - CommandLineW[i] = 0; - - i = 0; - while ((*lpCurrentDirectory)!=0 && i < MAX_PATH) - { - CurrentDirectoryW[i] = *lpCurrentDirectory; - lpCurrentDirectory++; - i++; - } - CurrentDirectoryW[i] = 0; - - return CreateProcessW(ApplicationNameW,CommandLineW, lpProcessAttributes,lpThreadAttributes, - bInheritHandles,dwCreationFlags,lpEnvironment,CurrentDirectoryW,lpStartupInfo, - lpProcessInformation); - - -} - - -WINBOOL -STDCALL -CreateProcessW( - LPCWSTR lpApplicationName, - LPWSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - WINBOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCWSTR lpCurrentDirectory, - LPSTARTUPINFO lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation - ) -{ - HANDLE hFile, hSection, hProcess, hThread; - KPRIORITY PriorityClass; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - BOOLEAN CreateSuspended; - - NTSTATUS errCode; - - UNICODE_STRING ApplicationNameString; - - - - LPTHREAD_START_ROUTINE lpStartAddress = NULL; - LPVOID lpParameter = NULL; - - hFile = NULL; - - ApplicationNameString.Length = lstrlenW(lpApplicationName)*sizeof(WCHAR); + NTSTATUS errCode; + PROCESS_BASIC_INFORMATION ProcessBasic; + ULONG BytesWritten; - ApplicationNameString.Buffer = (WCHAR *)lpApplicationName; - ApplicationNameString.MaximumLength = ApplicationNameString.Length; + errCode = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + memcpy( lpExitCode ,&ProcessBasic.ExitStatus,sizeof(DWORD)); + return TRUE; +} - - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = NULL; - - - - if ( lpProcessAttributes != NULL ) { - if ( lpProcessAttributes->bInheritHandle ) - ObjectAttributes.Attributes = OBJ_INHERIT; - else - ObjectAttributes.Attributes = 0; - ObjectAttributes.SecurityDescriptor = lpProcessAttributes->lpSecurityDescriptor; - } - ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; - - errCode = NtOpenFile(&hFile,(SYNCHRONIZE|FILE_EXECUTE), &ObjectAttributes, - &IoStatusBlock,(FILE_SHARE_DELETE|FILE_SHARE_READ),(FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE)); - - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - - errCode = NtCreateSection(&hSection,SECTION_ALL_ACCESS,NULL,NULL,PAGE_EXECUTE,SEC_IMAGE,hFile); - NtClose(hFile); - - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - - - if ( lpProcessAttributes != NULL ) { - if ( lpProcessAttributes->bInheritHandle ) - ObjectAttributes.Attributes = OBJ_INHERIT; - else - ObjectAttributes.Attributes = 0; - ObjectAttributes.SecurityDescriptor = lpProcessAttributes->lpSecurityDescriptor; - } - - errCode = NtCreateProcess(&hProcess,PROCESS_ALL_ACCESS, &ObjectAttributes,NtCurrentProcess(),bInheritHandles,hSection,NULL,NULL); - NtClose(hSection); - - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - - PriorityClass = NORMAL_PRIORITY_CLASS; - NtSetInformationProcess(hProcess,ProcessBasePriority,&PriorityClass,sizeof(KPRIORITY)); - - if ( ( dwCreationFlags & CREATE_SUSPENDED ) == CREATE_SUSPENDED) - CreateSuspended = TRUE; - else - CreateSuspended = FALSE; - - hThread = CreateRemoteThread( - hProcess, - lpThreadAttributes, - 4096, // 1 page ?? - lpStartAddress, - lpParameter, - CREATE_SUSPENDED, - &lpProcessInformation->dwThreadId - ); - - - if ( hThread == NULL ) - return FALSE; - - - - lpProcessInformation->hProcess = hProcess; - lpProcessInformation->hThread = hThread; - - - - - GetProcessId(hProcess,&lpProcessInformation->dwProcessId); - - - - return TRUE; - - - } - - - -HANDLE -STDCALL -OpenProcess( - DWORD dwDesiredAccess, - WINBOOL bInheritHandle, - DWORD dwProcessId - ) +WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId ) { + NTSTATUS errCode; + PROCESS_BASIC_INFORMATION ProcessBasic; + ULONG BytesWritten; + + errCode = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD)); + return TRUE; +} + +PWSTR InternalAnsiToUnicode(PWSTR Out, LPCSTR In, ULONG MaxLength) +{ + ULONG i; + + if (In == NULL) + { + return(NULL); + } + else + { + i = 0; + while ((*In)!=0 && i < MaxLength) + { + Out[i] = *In; + In++; + i++; + } + Out[i] = 0; + return(Out); + } +} + +WINBOOL STDCALL CreateProcessA(LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFO lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +/* + * FUNCTION: The CreateProcess function creates a new process and its + * primary thread. The new process executes the specified executable file + * ARGUMENTS: + * + * lpApplicationName = Pointer to name of executable module + * lpCommandLine = Pointer to command line string + * lpProcessAttributes = Process security attributes + * lpThreadAttributes = Thread security attributes + * bInheritHandles = Handle inheritance flag + * dwCreationFlags = Creation flags + * lpEnvironment = Pointer to new environment block + * lpCurrentDirectory = Pointer to current directory name + * lpStartupInfo = Pointer to startup info + * lpProcessInformation = Pointer to process information + */ +{ + WCHAR ApplicationNameW[MAX_PATH]; + WCHAR CommandLineW[MAX_PATH]; + WCHAR CurrentDirectoryW[MAX_PATH]; + PWSTR PApplicationNameW; + PWSTR PCommandLineW; + PWSTR PCurrentDirectoryW; + ULONG i; + + OutputDebugStringA("CreateProcessA\n"); + + PApplicationNameW = InternalAnsiToUnicode(ApplicationNameW, + lpApplicationName, + MAX_PATH); + PCommandLineW = InternalAnsiToUnicode(CommandLineW, + lpCommandLine, + MAX_PATH); + PCurrentDirectoryW = InternalAnsiToUnicode(CurrentDirectoryW, + lpCurrentDirectory, + MAX_PATH); + return CreateProcessW(PApplicationNameW, + PCommandLineW, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + PCurrentDirectoryW, + lpStartupInfo, + lpProcessInformation); +} - NTSTATUS errCode; - HANDLE ProcessHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId ; - - ClientId.UniqueProcess = (HANDLE)dwProcessId; - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = (HANDLE)NULL; - ObjectAttributes.SecurityDescriptor = NULL; - ObjectAttributes.SecurityQualityOfService = NULL; +WINBOOL STDCALL CreateProcessW(LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFO lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + HANDLE hFile, hSection, hProcess, hThread; + KPRIORITY PriorityClass; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + BOOLEAN CreateSuspended; + NTSTATUS errCode; + UNICODE_STRING ApplicationNameString; + LPTHREAD_START_ROUTINE lpStartAddress = NULL; + LPVOID lpParameter = NULL; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + WCHAR TempApplicationName[255]; + WCHAR TempFileName[255]; + WCHAR TempDirectoryName[255]; + ULONG i; + ULONG BaseAddress; + ULONG Size; + LARGE_INTEGER SectionOffset; + + dprintf("CreateProcessW(lpApplicationName '%w', lpCommandLine '%w')\n", + lpApplicationName,lpCommandLine); + + hFile = NULL; + + /* + * Find the application name + */ + TempApplicationName[0] = '\\'; + TempApplicationName[1] = '?'; + TempApplicationName[2] = '?'; + TempApplicationName[3] = '\\'; + TempApplicationName[4] = 0; + + dprintf("TempApplicationName '%w'\n",TempApplicationName); + + if (lpApplicationName != NULL) + { + wcscpy(TempFileName, lpApplicationName); - if ( bInheritHandle == TRUE ) - ObjectAttributes.Attributes = OBJ_INHERIT; - else - ObjectAttributes.Attributes = 0; + dprintf("TempFileName '%w'\n",TempFileName); + } + else + { + wcscpy(TempFileName, lpCommandLine); + + dprintf("TempFileName '%w'\n",TempFileName); + + for (i=0; TempFileName[i]!=' ' && TempFileName[i] != 0; i++); + TempFileName[i]=0; + + } + if (TempFileName[1] != ':') + { + GetCurrentDirectoryW(MAX_PATH,TempDirectoryName); + wcscat(TempApplicationName,TempDirectoryName); + } + wcscat(TempApplicationName,TempFileName); + + RtlInitUnicodeString(&ApplicationNameString, TempApplicationName); + + dprintf("ApplicationName %w\n",ApplicationNameString.Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &ApplicationNameString, + OBJ_CASE_INSENSITIVE, + NULL, + SecurityDescriptor); - errCode = NtOpenProcess ( &ProcessHandle, dwDesiredAccess, &ObjectAttributes, &ClientId); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return NULL; - } - return ProcessHandle; + /* + * Try to open the executable + */ + + errCode = NtOpenFile(&hFile, + SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE|FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE); + + if ( !NT_SUCCESS(errCode) ) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + + errCode = NtCreateSection(&hSection, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + hFile); + NtClose(hFile); + + if ( !NT_SUCCESS(errCode) ) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + + errCode = NtCreateProcess(&hProcess, + PROCESS_ALL_ACCESS, + NULL, + NtCurrentProcess(), + bInheritHandles, + NULL, + NULL, + NULL); + + BaseAddress = (PVOID)0x10000; + LARGE_INTEGER_QUAD_PART(SectionOffset) = 0; + Size = 0x10000; + NtMapViewOfSection(hSection, + hProcess, + &BaseAddress, + 0, + Size, + &SectionOffset, + &Size, + 0, + MEM_COMMIT, + PAGE_READWRITE); + + + NtClose(hSection); + + if ( !NT_SUCCESS(errCode) ) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + +#if 0 + PriorityClass = NORMAL_PRIORITY_CLASS; + NtSetInformationProcess(hProcess, + ProcessBasePriority, + &PriorityClass, + sizeof(KPRIORITY)); +#endif + dprintf("Creating thread for process\n"); + lpStartAddress = BaseAddress; + hThread = CreateRemoteThread(hProcess, + lpThreadAttributes, + 4096, // 1 page ?? + lpStartAddress, + lpParameter, + dwCreationFlags, + &lpProcessInformation->dwThreadId); + + if ( hThread == NULL ) + return FALSE; + + lpProcessInformation->hProcess = hProcess; + lpProcessInformation->hThread = hThread; + + GetProcessId(hProcess,&lpProcessInformation->dwProcessId); + + return TRUE; +} + + + +HANDLE STDCALL OpenProcess(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + DWORD dwProcessId) +{ + NTSTATUS errCode; + HANDLE ProcessHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId ; + + ClientId.UniqueProcess = (HANDLE)dwProcessId; + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = (HANDLE)NULL; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + if ( bInheritHandle == TRUE ) + ObjectAttributes.Attributes = OBJ_INHERIT; + else + ObjectAttributes.Attributes = 0; + + errCode = NtOpenProcess(&ProcessHandle, + dwDesiredAccess, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(errCode)) + { + SetLastError(RtlNtStatusToDosError(errCode)); + return NULL; + } + return ProcessHandle; } diff --git a/reactos/lib/kernel32/thread/thread.c b/reactos/lib/kernel32/thread/thread.c index a6e47ef9628..6595b603867 100644 --- a/reactos/lib/kernel32/thread/thread.c +++ b/reactos/lib/kernel32/thread/thread.c @@ -1,362 +1,379 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/thread/thread.c - * PURPOSE: Thread functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - Tls functions are modified from WINE - * UPDATE HISTORY: - * Created 01/11/98 - */ - -#include -#include -#include -#include - - -HANDLE -STDCALL -CreateThread( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - DWORD dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId - ) -{ - return CreateRemoteThread(NtCurrentProcess(),lpThreadAttributes,dwStackSize, - lpStartAddress,lpParameter,dwCreationFlags,lpThreadId); -} - - - - -HANDLE -STDCALL -CreateRemoteThread( - HANDLE hProcess, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - DWORD dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId - ) -{ - NTSTATUS errCode; - HANDLE ThreadHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId; - CONTEXT ThreadContext; - INITIAL_TEB InitialTeb; - BOOLEAN CreateSuspended = FALSE; - - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = NULL; - ObjectAttributes.ObjectName = NULL; - ObjectAttributes.Attributes = 0; - if ( lpThreadAttributes != NULL ) { - if ( lpThreadAttributes->bInheritHandle ) - ObjectAttributes.Attributes = OBJ_INHERIT; - ObjectAttributes.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor; - } - ObjectAttributes.SecurityQualityOfService = NULL; - - if ( ( dwCreationFlags & CREATE_SUSPENDED ) == CREATE_SUSPENDED ) - CreateSuspended = TRUE; - else - CreateSuspended = FALSE; - // fix context - GetThreadContext(NtCurrentThread(),&ThreadContext); - // fix teb [ stack context ] --> check the image file - - errCode = NtCreateThread( - &ThreadHandle, - THREAD_ALL_ACCESS, - &ObjectAttributes, - hProcess, - &ClientId, - &ThreadContext, - &InitialTeb, - CreateSuspended - ); - if ( lpThreadId != NULL ) - memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG)); - - return ThreadHandle; -} - -NT_TEB *GetTeb(VOID) -{ - return NULL; -} - -WINBOOL STDCALL -SwitchToThread(VOID ) -{ - NTSTATUS errCode; - errCode = NtYieldExecution(); - return TRUE; -} - -DWORD -STDCALL -GetCurrentThreadId() -{ - - return (DWORD)(GetTeb()->Cid).UniqueThread; -} - -VOID -STDCALL -ExitThread( - UINT uExitCode - ) -{ - NTSTATUS errCode; - - errCode = NtTerminateThread( - NtCurrentThread() , - uExitCode - ); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - } - return; -} - -WINBOOL -STDCALL -GetThreadTimes( - HANDLE hThread, - LPFILETIME lpCreationTime, - LPFILETIME lpExitTime, - LPFILETIME lpKernelTime, - LPFILETIME lpUserTime - ) -{ - NTSTATUS errCode; - KERNEL_USER_TIMES KernelUserTimes; - ULONG ReturnLength; - errCode = NtQueryInformationThread(hThread,ThreadTimes,&KernelUserTimes,sizeof(KERNEL_USER_TIMES),&ReturnLength); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME)); - memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME)); - memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME)); - memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME)); - return TRUE; - -} - - -WINBOOL -STDCALL GetThreadContext( - HANDLE hThread, - LPCONTEXT lpContext - ) -{ - NTSTATUS errCode; - errCode = NtGetContextThread(hThread,lpContext); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - return TRUE; -} - -WINBOOL -STDCALL -SetThreadContext( - HANDLE hThread, - CONST CONTEXT *lpContext - ) -{ - NTSTATUS errCode; - - errCode = NtSetContextThread(hThread,(void *)lpContext); - if (!NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - return TRUE; -} - - - -WINBOOL -STDCALL -GetExitCodeThread( - HANDLE hThread, - LPDWORD lpExitCode - ) -{ - NTSTATUS errCode; - THREAD_BASIC_INFORMATION ThreadBasic; - ULONG DataWritten; - errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - memcpy( lpExitCode ,&ThreadBasic.ExitStatus,sizeof(DWORD)); - return TRUE; - -} - - -DWORD -STDCALL -ResumeThread( - HANDLE hThread - ) -{ - NTSTATUS errCode; - ULONG PreviousResumeCount; - - errCode = NtResumeThread(hThread,&PreviousResumeCount ); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return -1; - } - return PreviousResumeCount; -} - -DWORD -STDCALL -SuspendThread( - HANDLE hThread - ) -{ - NTSTATUS errCode; - ULONG PreviousSuspendCount; - - errCode = NtSuspendThread(hThread,&PreviousSuspendCount ); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return -1; - } - return PreviousSuspendCount; -} - - -DWORD -STDCALL -SetThreadAffinityMask( - HANDLE hThread, - DWORD dwThreadAffinityMask - ) -{ - return 0; -} - - -WINBOOL -STDCALL -SetThreadPriority( - HANDLE hThread, - int nPriority - ) -{ - NTSTATUS errCode; - THREAD_BASIC_INFORMATION ThreadBasic; - ULONG DataWritten; - errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - ThreadBasic.BasePriority = nPriority; - errCode = NtSetInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION)); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return FALSE; - } - return TRUE; -} - - -int -STDCALL -GetThreadPriority( - HANDLE hThread - ) -{ - NTSTATUS errCode; - THREAD_BASIC_INFORMATION ThreadBasic; - ULONG DataWritten; - errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); - if ( !NT_SUCCESS(errCode) ) { - SetLastError(RtlNtStatusToDosError(errCode)); - return THREAD_PRIORITY_ERROR_RETURN; - } - return ThreadBasic.BasePriority; -} - - -/* (WIN32) Thread Local Storage ******************************************** */ - -DWORD STDCALL -TlsAlloc(VOID) -{ - DWORD dwTlsIndex = GetTeb()->dwTlsIndex; - - - void **TlsData = GetTeb()->TlsData; - - - if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) - { - TlsData[dwTlsIndex] = NULL; - return (dwTlsIndex++); - } - return (0xFFFFFFFFUL); -} - -WINBOOL STDCALL -TlsFree(DWORD dwTlsIndex) -{ - - return (TRUE); -} - -LPVOID STDCALL -TlsGetValue(DWORD dwTlsIndex) -{ - - - void **TlsData = GetTeb()->TlsData; - - - if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) - { - - SetLastError(NO_ERROR); - return (TlsData[dwTlsIndex]); - } - SetLastError(1); - return (NULL); -} - -WINBOOL STDCALL -TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) -{ - - - void **TlsData = GetTeb()->TlsData; - - - if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) - { - - TlsData[dwTlsIndex] = lpTlsValue; - return (TRUE); - } - return (FALSE); -} - -/*************************************************************/ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/thread/thread.c + * PURPOSE: Thread functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + Tls functions are modified from WINE + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include +#include +#include + +HANDLE +STDCALL +CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ) +{ + return CreateRemoteThread(NtCurrentProcess(),lpThreadAttributes,dwStackSize, + lpStartAddress,lpParameter,dwCreationFlags,lpThreadId); +} + + + + +HANDLE +STDCALL +CreateRemoteThread( + HANDLE hProcess, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ) +{ + NTSTATUS errCode; + HANDLE ThreadHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + CONTEXT ThreadContext; + INITIAL_TEB InitialTeb; + BOOLEAN CreateSuspended = FALSE; + ULONG BaseAddress; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + if ( lpThreadAttributes != NULL ) { + if ( lpThreadAttributes->bInheritHandle ) + ObjectAttributes.Attributes = OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor; + } + ObjectAttributes.SecurityQualityOfService = NULL; + + if ( ( dwCreationFlags & CREATE_SUSPENDED ) == CREATE_SUSPENDED ) + CreateSuspended = TRUE; + else + CreateSuspended = FALSE; + + BaseAddress = 0; + ZwAllocateVirtualMemory(hProcess, + &BaseAddress, + 0, + &dwStackSize, + MEM_COMMIT, + PAGE_READWRITE); + + + memset(&ThreadContext,0,sizeof(CONTEXT)); + ThreadContext.Eip = lpStartAddress; + ThreadContext.SegGs = USER_DS; + ThreadContext.SegFs = USER_DS; + ThreadContext.SegEs = USER_DS; + ThreadContext.SegDs = USER_DS; + ThreadContext.SegCs = USER_CS; + ThreadContext.SegSs = USER_DS; + ThreadContext.Esp = BaseAddress + dwStackSize; + ThreadContext.EFlags = (1<<1) + (1<<9); + + + errCode = NtCreateThread(&ThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + hProcess, + &ClientId, + &ThreadContext, + &InitialTeb, + CreateSuspended); + if ( lpThreadId != NULL ) + memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG)); + + return ThreadHandle; +} + +NT_TEB *GetTeb(VOID) +{ + return NULL; +} + +WINBOOL STDCALL +SwitchToThread(VOID ) +{ + NTSTATUS errCode; + errCode = NtYieldExecution(); + return TRUE; +} + +DWORD +STDCALL +GetCurrentThreadId() +{ + + return (DWORD)(GetTeb()->Cid).UniqueThread; +} + +VOID +STDCALL +ExitThread( + UINT uExitCode + ) +{ + NTSTATUS errCode; + + errCode = NtTerminateThread( + NtCurrentThread() , + uExitCode + ); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + } + return; +} + +WINBOOL +STDCALL +GetThreadTimes( + HANDLE hThread, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime + ) +{ + NTSTATUS errCode; + KERNEL_USER_TIMES KernelUserTimes; + ULONG ReturnLength; + errCode = NtQueryInformationThread(hThread,ThreadTimes,&KernelUserTimes,sizeof(KERNEL_USER_TIMES),&ReturnLength); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME)); + memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME)); + memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME)); + memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME)); + return TRUE; + +} + + +WINBOOL +STDCALL GetThreadContext( + HANDLE hThread, + LPCONTEXT lpContext + ) +{ + NTSTATUS errCode; + errCode = NtGetContextThread(hThread,lpContext); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + +WINBOOL +STDCALL +SetThreadContext( + HANDLE hThread, + CONST CONTEXT *lpContext + ) +{ + NTSTATUS errCode; + + errCode = NtSetContextThread(hThread,(void *)lpContext); + if (!NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + + +WINBOOL +STDCALL +GetExitCodeThread( + HANDLE hThread, + LPDWORD lpExitCode + ) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + memcpy( lpExitCode ,&ThreadBasic.ExitStatus,sizeof(DWORD)); + return TRUE; + +} + + +DWORD +STDCALL +ResumeThread( + HANDLE hThread + ) +{ + NTSTATUS errCode; + ULONG PreviousResumeCount; + + errCode = NtResumeThread(hThread,&PreviousResumeCount ); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return -1; + } + return PreviousResumeCount; +} + +DWORD +STDCALL +SuspendThread( + HANDLE hThread + ) +{ + NTSTATUS errCode; + ULONG PreviousSuspendCount; + + errCode = NtSuspendThread(hThread,&PreviousSuspendCount ); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return -1; + } + return PreviousSuspendCount; +} + + +DWORD +STDCALL +SetThreadAffinityMask( + HANDLE hThread, + DWORD dwThreadAffinityMask + ) +{ + return 0; +} + + +WINBOOL +STDCALL +SetThreadPriority( + HANDLE hThread, + int nPriority + ) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + ThreadBasic.BasePriority = nPriority; + errCode = NtSetInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION)); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + +int +STDCALL +GetThreadPriority( + HANDLE hThread + ) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return THREAD_PRIORITY_ERROR_RETURN; + } + return ThreadBasic.BasePriority; +} + + +/* (WIN32) Thread Local Storage ******************************************** */ + +DWORD STDCALL +TlsAlloc(VOID) +{ + DWORD dwTlsIndex = GetTeb()->dwTlsIndex; + + + void **TlsData = GetTeb()->TlsData; + + + if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) + { + TlsData[dwTlsIndex] = NULL; + return (dwTlsIndex++); + } + return (0xFFFFFFFFUL); +} + +WINBOOL STDCALL +TlsFree(DWORD dwTlsIndex) +{ + + return (TRUE); +} + +LPVOID STDCALL +TlsGetValue(DWORD dwTlsIndex) +{ + + + void **TlsData = GetTeb()->TlsData; + + + if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) + { + + SetLastError(NO_ERROR); + return (TlsData[dwTlsIndex]); + } + SetLastError(1); + return (NULL); +} + +WINBOOL STDCALL +TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) +{ + + + void **TlsData = GetTeb()->TlsData; + + + if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0])) + { + + TlsData[dwTlsIndex] = lpTlsValue; + return (TRUE); + } + return (FALSE); +} + +/*************************************************************/ diff --git a/reactos/lib/ntdll/makefile b/reactos/lib/ntdll/makefile index 38e499c924f..4100b9ee3b1 100644 --- a/reactos/lib/ntdll/makefile +++ b/reactos/lib/ntdll/makefile @@ -1,6 +1,7 @@ all: ntdll.a -OBJECTS = napi.o stubs/stubs.o string/wstring.o stdio/vsprintf.o +OBJECTS = napi.o stubs/stubs.o string/wstring.o stdio/vsprintf.o \ + rtl/unicode.o rtl/namespc.o ntdll.a: $(OBJECTS) $(AR) vcsr ntdll.a $(OBJECTS) diff --git a/reactos/lib/ntdll/string/wstring.c b/reactos/lib/ntdll/string/wstring.c index 239770793c5..2057bf5ab68 100644 --- a/reactos/lib/ntdll/string/wstring.c +++ b/reactos/lib/ntdll/string/wstring.c @@ -71,6 +71,7 @@ wchar_t* wcscpy(wchar_t* str1, const wchar_t* str2) s++; str2++; } + *s = 0; return(str1); } diff --git a/reactos/lib/ntdll/stubs/stubs.c b/reactos/lib/ntdll/stubs/stubs.c index 44e26d66088..3df7a08baa8 100644 --- a/reactos/lib/ntdll/stubs/stubs.c +++ b/reactos/lib/ntdll/stubs/stubs.c @@ -1,6 +1,6 @@ #include -#define STUB(x) void x(void) { NtDisplayString("NTDLL: Stub for "#x); } +#define STUB(x) void x(void) { NtDisplayString("NTDLL: Stub for "#x"\n"); } // ?Allocate@CBufferAllocator@@UAEPAXK@Z STUB(PropertyLengthAsVariant) @@ -78,12 +78,8 @@ STUB(RtlAllocateAndInitializeSid) STUB(RtlAllocateHandle) STUB(RtlAllocateHeap) STUB(RtlAnsiCharToUnicodeChar) -STUB(RtlAnsiStringToUnicodeSize) -STUB(RtlAnsiStringToUnicodeString) STUB(RtlAppendAsciizToString) STUB(RtlAppendStringToString) -STUB(RtlAppendUnicodeStringToString) -STUB(RtlAppendUnicodeToString) STUB(RtlApplyRXact) STUB(RtlApplyRXactNoFlush) STUB(RtlAreAllAccessesGranted) @@ -92,7 +88,6 @@ STUB(RtlAreBitsClear) STUB(RtlAreBitsSet) STUB(RtlAssert) STUB(RtlCaptureStackBackTrace) -STUB(RtlCharToInteger) STUB(RtlCheckRegistryKey) STUB(RtlClearAllBits) STUB(RtlClearBits) @@ -100,8 +95,6 @@ STUB(RtlClosePropertySet) STUB(RtlCompactHeap) STUB(RtlCompareMemory) STUB(RtlCompareMemoryUlong) -STUB(RtlCompareString) -STUB(RtlCompareUnicodeString) STUB(RtlCompressBuffer) STUB(RtlConsoleMultiByteToUnicodeN) STUB(RtlConvertExclusiveToShared) @@ -115,8 +108,6 @@ STUB(RtlCopyLuidAndAttributesArray) STUB(RtlCopySecurityDescriptor) STUB(RtlCopySid) STUB(RtlCopySidAndAttributesArray) -STUB(RtlCopyString) -STUB(RtlCopyUnicodeString) STUB(RtlCreateAcl) STUB(RtlCreateAndSetSD) STUB(RtlCreateAtomTable) @@ -173,8 +164,6 @@ STUB(RtlEqualDomainName) STUB(RtlEqualLuid) STUB(RtlEqualPrefixSid) STUB(RtlEqualSid) -STUB(RtlEqualString) -STUB(RtlEqualUnicodeString) STUB(RtlEraseUnicodeString) STUB(RtlExpandEnvironmentStrings_U) STUB(RtlExtendHeap) @@ -194,12 +183,10 @@ STUB(RtlFirstFreeAce) STUB(RtlFlushPropertySet) STUB(RtlFormatCurrentUserKeyPath) STUB(RtlFormatMessage) -STUB(RtlFreeAnsiString) STUB(RtlFreeHandle) STUB(RtlFreeHeap) STUB(RtlFreeOemString) STUB(RtlFreeSid) -STUB(RtlFreeUnicodeString) STUB(RtlFreeUserThreadStack) STUB(RtlGenerate8dot3Name) STUB(RtlGetAce) @@ -225,11 +212,8 @@ STUB(RtlImageNtHeader) STUB(RtlImageRvaToSection) STUB(RtlImageRvaToVa) STUB(RtlImpersonateSelf) -STUB(RtlInitAnsiString) STUB(RtlInitCodePageTable) STUB(RtlInitNlsTables) -STUB(RtlInitString) -STUB(RtlInitUnicodeString) STUB(RtlInitializeAtomPackage) STUB(RtlInitializeBitMap) STUB(RtlInitializeContext) @@ -242,7 +226,6 @@ STUB(RtlInitializeResource) STUB(RtlInitializeSid) STUB(RtlInsertElementGenericTable) STUB(RtlIntegerToChar) -STUB(RtlIntegerToUnicodeString) STUB(RtlIsDosDeviceName_U) STUB(RtlIsGenericTableEmpty) STUB(RtlIsNameLegalDOS8Dot3) @@ -353,9 +336,7 @@ STUB(RtlTimeToSecondsSince1980) STUB(RtlTimeToTimeFields) STUB(RtlTryEnterCriticalSection) STUB(RtlUnicodeStringToAnsiSize) -STUB(RtlUnicodeStringToAnsiString) STUB(RtlUnicodeStringToCountedOemString) -STUB(RtlUnicodeStringToInteger) STUB(RtlUnicodeStringToOemSize) STUB(RtlUnicodeStringToOemString) STUB(RtlUnicodeToCustomCPN) @@ -366,7 +347,6 @@ STUB(RtlUniform) STUB(RtlUnlockHeap) STUB(RtlUnwind) STUB(RtlUpcaseUnicodeChar) -STUB(RtlUpcaseUnicodeString) STUB(RtlUpcaseUnicodeStringToAnsiString) STUB(RtlUpcaseUnicodeStringToCountedOemString) STUB(RtlUpcaseUnicodeStringToOemString) @@ -374,7 +354,6 @@ STUB(RtlUpcaseUnicodeToCustomCPN) STUB(RtlUpcaseUnicodeToMultiByteN) STUB(RtlUpcaseUnicodeToOemN) STUB(RtlUpperChar) -STUB(RtlUpperString) STUB(RtlUsageHeap) STUB(RtlValidAcl) STUB(RtlValidSecurityDescriptor) diff --git a/reactos/loaders/boot/boot.bin b/reactos/loaders/boot/boot.bin deleted file mode 100644 index 5b532fa6c7c..00000000000 Binary files a/reactos/loaders/boot/boot.bin and /dev/null differ diff --git a/reactos/loaders/boot/osldr.bin b/reactos/loaders/boot/osldr.bin deleted file mode 100644 index 794732e5988..00000000000 Binary files a/reactos/loaders/boot/osldr.bin and /dev/null differ diff --git a/reactos/makefile_rex b/reactos/makefile_rex index 8cca82c2983..7ccf186e183 100644 --- a/reactos/makefile_rex +++ b/reactos/makefile_rex @@ -31,7 +31,7 @@ LOADERS = dos # Select the device drivers and filesystems you want # KERNEL_SERVICES = parallel keyboard null mouse serial sound ide test sdisk \ - minix vfat # ext2fs + minix vfat ext2 APPS = hello shell @@ -104,8 +104,8 @@ serial: dummy sound: dummy make -C services/dd/sound -ext2fs: dummy - make -C services/fs/ext2fs +ext2: dummy + make -C services/fs/ext2 # # Kernel loaders diff --git a/reactos/ntoskrnl/hal/x86/irqhand.asm b/reactos/ntoskrnl/hal/x86/irqhand.asm index 08ee0512071..eb6220b30e1 100644 --- a/reactos/ntoskrnl/hal/x86/irqhand.asm +++ b/reactos/ntoskrnl/hal/x86/irqhand.asm @@ -17,12 +17,14 @@ _irq_handler_%1: ; pusha push ds + push es ; ; Load DS ; mov ax,KERNEL_DS mov ds,ax + mov es,ax ; ; Mask the corresponding vector at the PIC @@ -43,6 +45,7 @@ _irq_handler_%1: ; Restore stack, registers and return to interrupted routine ; pop eax + pop es pop ds popa iret diff --git a/reactos/ntoskrnl/hal/x86/page.c b/reactos/ntoskrnl/hal/x86/page.c index 8eefec263e4..68dd2d60b89 100644 --- a/reactos/ntoskrnl/hal/x86/page.c +++ b/reactos/ntoskrnl/hal/x86/page.c @@ -223,11 +223,7 @@ BOOL is_page_present(unsigned int vaddr) * buffer from an irq. */ { -#if 0 - unsigned int* page_dir = physical_to_linear(current_task->cr3); -#else unsigned int* page_dir = get_page_directory(); -#endif unsigned int* page_tlb = NULL; /* diff --git a/reactos/ntoskrnl/hal/x86/thread.c b/reactos/ntoskrnl/hal/x86/thread.c index 980d67020e9..7d695049252 100644 --- a/reactos/ntoskrnl/hal/x86/thread.c +++ b/reactos/ntoskrnl/hal/x86/thread.c @@ -1,330 +1,330 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/hal/x86/thread.c - * PURPOSE: HAL multitasking functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 27/06/98: Created - */ - -/* INCLUDES ****************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -/* GLOBALS ***************************************************************/ - -VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext); -VOID PsBeginThreadWithContextInternal(VOID); - -#define FIRST_TSS_SELECTOR (KERNEL_DS + 0x8) -#define FIRST_TSS_OFFSET (FIRST_TSS_SELECTOR / 8) - -static char null_ldt[8]={0,}; -static unsigned int null_ldt_sel=0; -static PETHREAD FirstThread=NULL; - -/* FUNCTIONS **************************************************************/ - -void HalTaskSwitch(PKTHREAD thread) -/* - * FUNCTION: Switch tasks - * ARGUMENTS: - * thread = Thread to switch to - * NOTE: This function will not return until the current thread is scheduled - * again - */ -{ - DPRINT("Scheduling thread %x\n",thread); - DPRINT("Scheduling thread %x\n",thread->Context.nr); - DPRINT("previous task %x reserved1 %x esp0 %x ss0 %x\n", - thread->Context.previous_task,thread->Context.reserved1, - thread->Context.esp0,thread->Context.ss0); - DPRINT("reserved2 %x esp1 %x ss1 %x reserved3 %x esp2 %x ss2 %x\n", - thread->Context.reserved2,thread->Context.esp1,thread->Context.ss1, - thread->Context.reserved3,thread->Context.esp2,thread->Context.ss2); - DPRINT("reserved4 %x cr3 %x eip %x eflags %x eax %x\n", - thread->Context.reserved4,thread->Context.cr3,thread->Context.eip, - thread->Context.eflags,thread->Context.eax); - DPRINT("ecx %x edx %x ebx %x esp %x ebp %x esi %x\n", - thread->Context.ecx,thread->Context.edx,thread->Context.ebx, - thread->Context.esp,thread->Context.ebp,thread->Context.esi); - DPRINT("edi %x es %x reserved5 %x cs %x reserved6 %x\n", - thread->Context.edi,thread->Context.es,thread->Context.reserved5, - thread->Context.cs,thread->Context.reserved6); - DPRINT("ss %x reserved7 %x ds %x reserved8 %x fs %x\n", - thread->Context.ss,thread->Context.reserved7,thread->Context.ds, - thread->Context.reserved8,thread->Context.fs); - DPRINT("reserved9 %x gs %x reserved10 %x ldt %x reserved11 %x\n", - thread->Context.reserved9,thread->Context.gs, - thread->Context.reserved10,thread->Context.ldt, - thread->Context.reserved11); - DPRINT("trap %x iomap_base %x nr %x io_bitmap[0] %x\n", - thread->Context.trap,thread->Context.iomap_base, - thread->Context.nr,thread->Context.io_bitmap[0]); - DPRINT("&gdt[nr/8].a %.8x gdt[nr/8].a %.8x gdt[nr/8].b %.8x\n", - &(gdt[thread->Context.nr/8].a), - gdt[thread->Context.nr/8].a, - gdt[thread->Context.nr/8].b); - __asm__("pushfl\n\t" - "cli\n\t" - "ljmp %0\n\t" - "popfl\n\t" - : /* No outputs */ - : "m" (*(((unsigned char *)(&(thread->Context.nr)))-4) ) - : "ax","dx"); -} - -static unsigned int allocate_tss_descriptor(void) -/* - * FUNCTION: Allocates a slot within the GDT to describe a TSS - * RETURNS: The offset within the GDT of the slot allocated on succcess - * Zero on failure - */ -{ - unsigned int i; - for (i=0;i<16;i++) - { - if (gdt[FIRST_TSS_OFFSET + i].a==0 && - gdt[FIRST_TSS_OFFSET + i].b==0) - { - return(FIRST_TSS_OFFSET + i); - } - } - return(0); -} - -#define FLAG_NT (1<<14) -#define FLAG_VM (1<<17) -#define FLAG_IF (1<<9) -#define FLAG_IOPL ((1<<12)+(1<<13)) - -NTSTATUS KeValidateUserContext(PCONTEXT Context) -/* - * FUNCTION: Validates a processor context - * ARGUMENTS: - * Context = Context to validate - * RETURNS: Status - * NOTE: This only validates the context as not violating system security, it - * doesn't guararantee the thread won't crash at some point - * NOTE2: This relies on there only being two selectors which can access - * system space - */ -{ - if (Context->Eip >= KERNEL_BASE) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegCs == KERNEL_CS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegDs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegEs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegFs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegGs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if ((Context->EFlags & FLAG_IOPL) != 0 || - (Context->EFlags & FLAG_NT) || - (Context->EFlags & FLAG_VM) || - (!(Context->EFlags & FLAG_IF))) - { - return(STATUS_SUCCESS); - } - return(STATUS_SUCCESS); -} - -NTSTATUS HalInitTaskWithContext(PETHREAD Thread, PCONTEXT Context) -/* - * FUNCTION: Initialize a task with a user mode context - * ARGUMENTS: - * Thread = Thread to initialize - * Context = Processor context to initialize it with - * RETURNS: Status - */ -{ - unsigned int desc; - unsigned int length; - unsigned int base; - PVOID kernel_stack; - NTSTATUS Status; - PVOID stack_start; - - DPRINT("HalInitTaskWithContext(Thread %x, Context %x)\n", - Thread,Context); - - assert(sizeof(hal_thread_state)>=0x68); - - if ((Status=KeValidateUserContext(Context))!=STATUS_SUCCESS) - { - return(Status); - } - - desc = allocate_tss_descriptor(); - length = sizeof(hal_thread_state) - 1; - base = (unsigned int)(&(Thread->Tcb.Context)); - kernel_stack = ExAllocatePool(NonPagedPool,PAGESIZE); - - /* - * Setup a TSS descriptor - */ - gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); - gdt[desc].b = ((base & 0xff0000)>>16) | 0x8900 | (length & 0xf0000) - | (base & 0xff000000); - - stack_start = kernel_stack + 4096 - sizeof(CONTEXT); - memcpy(stack_start, Context, sizeof(CONTEXT)); - - /* - * Initialize the thread context - */ - memset(&Thread->Tcb.Context,0,sizeof(hal_thread_state)); - Thread->Tcb.Context.ldt = null_ldt_sel; - Thread->Tcb.Context.eflags = (1<<1) + (1<<9); - Thread->Tcb.Context.iomap_base = FIELD_OFFSET(hal_thread_state,io_bitmap); - Thread->Tcb.Context.esp0 = stack_start; - Thread->Tcb.Context.ss0 = KERNEL_DS; - Thread->Tcb.Context.esp = stack_start; - Thread->Tcb.Context.ss = KERNEL_DS; - Thread->Tcb.Context.cs = KERNEL_CS; - Thread->Tcb.Context.eip = PsBeginThreadWithContextInternal; - Thread->Tcb.Context.io_bitmap[0] = 0xff; - Thread->Tcb.Context.cr3 = - linear_to_physical(Thread->ThreadsProcess->Pcb.PageTableDirectory); - Thread->Tcb.Context.ds = KERNEL_DS; - Thread->Tcb.Context.es = KERNEL_DS; - Thread->Tcb.Context.fs = KERNEL_DS; - Thread->Tcb.Context.gs = KERNEL_DS; - - Thread->Tcb.Context.nr = desc * 8; - DPRINT("Allocated %x\n",desc*8); - - return(STATUS_SUCCESS); -} - -BOOLEAN HalInitTask(PETHREAD thread, PKSTART_ROUTINE fn, PVOID StartContext) -/* - * FUNCTION: Initializes the HAL portion of a thread object - * ARGUMENTS: - * thread = Object describes the thread - * fn = Entrypoint for the thread - * StartContext = parameter to pass to the thread entrypoint - * RETURNS: True if the function succeeded - */ -{ - unsigned int desc = allocate_tss_descriptor(); - unsigned int length = sizeof(hal_thread_state) - 1; - unsigned int base = (unsigned int)(&(thread->Tcb.Context)); - unsigned int* kernel_stack = ExAllocatePool(NonPagedPool,4096); - - DPRINT("HalInitTask(Thread %x, fn %x, StartContext %x)\n", - thread,fn,StartContext); - DPRINT("thread->ThreadsProcess %x\n",thread->ThreadsProcess); - - /* - * Make sure - */ - assert(sizeof(hal_thread_state)>=0x68); - - /* - * Setup a TSS descriptor - */ - gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); - gdt[desc].b = ((base & 0xff0000)>>16) | 0x8900 | (length & 0xf0000) - | (base & 0xff000000); - -// DPRINT("sizeof(descriptor) %d\n",sizeof(descriptor)); -// DPRINT("desc %d\n",desc); - DPRINT("&gdt[desc].a %.8x gdt[desc].a %.8x\ngdt[desc].b %.8x\n", - &(gdt[desc].a), - gdt[desc].a, - gdt[desc].b); - - /* - * Initialize the stack for the thread (including the two arguments to - * the general start routine). - */ - kernel_stack[1023] = (unsigned int)StartContext; - kernel_stack[1022] = (unsigned int)fn; - kernel_stack[1021] = NULL; - - /* - * Initialize the thread context - */ - memset(&thread->Tcb.Context,0,sizeof(hal_thread_state)); - thread->Tcb.Context.ldt = null_ldt_sel; - thread->Tcb.Context.eflags = (1<<1)+(1<<9); - thread->Tcb.Context.iomap_base = FIELD_OFFSET(hal_thread_state,io_bitmap); - thread->Tcb.Context.esp0 = &kernel_stack[1021]; - thread->Tcb.Context.ss0 = KERNEL_DS; - thread->Tcb.Context.esp = &kernel_stack[1021]; - thread->Tcb.Context.ss = KERNEL_DS; - thread->Tcb.Context.cs = KERNEL_CS; - thread->Tcb.Context.eip = (unsigned long)PsBeginThread; - thread->Tcb.Context.io_bitmap[0] = 0xff; - thread->Tcb.Context.cr3 = - linear_to_physical(thread->ThreadsProcess->Pcb.PageTableDirectory); - thread->Tcb.Context.ds = KERNEL_DS; - thread->Tcb.Context.es = KERNEL_DS; - thread->Tcb.Context.fs = KERNEL_DS; - thread->Tcb.Context.gs = KERNEL_DS; - thread->Tcb.Context.nr = desc * 8; - DPRINT("Allocated %x\n",desc*8); - - - return(TRUE); -} - -void HalInitFirstTask(PETHREAD thread) -/* - * FUNCTION: Called to setup the HAL portion of a thread object for the - * initial thread - */ -{ - unsigned int base; - unsigned int length; - unsigned int desc; - - memset(null_ldt,0,sizeof(null_ldt)); - desc = allocate_tss_descriptor(); - base = (unsigned int)&null_ldt; - length = sizeof(null_ldt) - 1; - gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); - gdt[desc].b = ((base & 0xff0000)>>16) | 0x8200 | (length & 0xf0000) - | (base & 0xff000000); - null_ldt_sel = desc*8; - - /* - * Initialize the thread context - */ - HalInitTask(thread,NULL,NULL); - - /* - * Load the task register - */ - __asm__("ltr %%ax" - : /* no output */ - : "a" (thread->Tcb.Context.nr)); - FirstThread = thread; -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/thread.c + * PURPOSE: HAL multitasking functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 27/06/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ***************************************************************/ + +VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext); +VOID PsBeginThreadWithContextInternal(VOID); + +#define FIRST_TSS_SELECTOR (KERNEL_DS + 0x8) +#define FIRST_TSS_OFFSET (FIRST_TSS_SELECTOR / 8) + +static char null_ldt[8]={0,}; +static unsigned int null_ldt_sel=0; +static PETHREAD FirstThread=NULL; + +/* FUNCTIONS **************************************************************/ + +void HalTaskSwitch(PKTHREAD thread) +/* + * FUNCTION: Switch tasks + * ARGUMENTS: + * thread = Thread to switch to + * NOTE: This function will not return until the current thread is scheduled + * again + */ +{ + DPRINT("Scheduling thread %x\n",thread); + DPRINT("Scheduling thread %x\n",thread->Context.nr); + DPRINT("previous task %x reserved1 %x esp0 %x ss0 %x\n", + thread->Context.previous_task,thread->Context.reserved1, + thread->Context.esp0,thread->Context.ss0); + DPRINT("reserved2 %x esp1 %x ss1 %x reserved3 %x esp2 %x ss2 %x\n", + thread->Context.reserved2,thread->Context.esp1,thread->Context.ss1, + thread->Context.reserved3,thread->Context.esp2,thread->Context.ss2); + DPRINT("reserved4 %x cr3 %x eip %x eflags %x eax %x\n", + thread->Context.reserved4,thread->Context.cr3,thread->Context.eip, + thread->Context.eflags,thread->Context.eax); + DPRINT("ecx %x edx %x ebx %x esp %x ebp %x esi %x\n", + thread->Context.ecx,thread->Context.edx,thread->Context.ebx, + thread->Context.esp,thread->Context.ebp,thread->Context.esi); + DPRINT("edi %x es %x reserved5 %x cs %x reserved6 %x\n", + thread->Context.edi,thread->Context.es,thread->Context.reserved5, + thread->Context.cs,thread->Context.reserved6); + DPRINT("ss %x reserved7 %x ds %x reserved8 %x fs %x\n", + thread->Context.ss,thread->Context.reserved7,thread->Context.ds, + thread->Context.reserved8,thread->Context.fs); + DPRINT("reserved9 %x gs %x reserved10 %x ldt %x reserved11 %x\n", + thread->Context.reserved9,thread->Context.gs, + thread->Context.reserved10,thread->Context.ldt, + thread->Context.reserved11); + DPRINT("trap %x iomap_base %x nr %x io_bitmap[0] %x\n", + thread->Context.trap,thread->Context.iomap_base, + thread->Context.nr,thread->Context.io_bitmap[0]); + DPRINT("&gdt[nr/8].a %.8x gdt[nr/8].a %.8x gdt[nr/8].b %.8x\n", + &(gdt[thread->Context.nr/8].a), + gdt[thread->Context.nr/8].a, + gdt[thread->Context.nr/8].b); + __asm__("pushfl\n\t" + "cli\n\t" + "ljmp %0\n\t" + "popfl\n\t" + : /* No outputs */ + : "m" (*(((unsigned char *)(&(thread->Context.nr)))-4) ) + : "ax","dx"); +} + +static unsigned int allocate_tss_descriptor(void) +/* + * FUNCTION: Allocates a slot within the GDT to describe a TSS + * RETURNS: The offset within the GDT of the slot allocated on succcess + * Zero on failure + */ +{ + unsigned int i; + for (i=0;i<16;i++) + { + if (gdt[FIRST_TSS_OFFSET + i].a==0 && + gdt[FIRST_TSS_OFFSET + i].b==0) + { + return(FIRST_TSS_OFFSET + i); + } + } + return(0); +} + +#define FLAG_NT (1<<14) +#define FLAG_VM (1<<17) +#define FLAG_IF (1<<9) +#define FLAG_IOPL ((1<<12)+(1<<13)) + +NTSTATUS KeValidateUserContext(PCONTEXT Context) +/* + * FUNCTION: Validates a processor context + * ARGUMENTS: + * Context = Context to validate + * RETURNS: Status + * NOTE: This only validates the context as not violating system security, it + * doesn't guararantee the thread won't crash at some point + * NOTE2: This relies on there only being two selectors which can access + * system space + */ +{ + if (Context->Eip >= KERNEL_BASE) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegCs == KERNEL_CS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegDs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegEs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegFs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegGs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if ((Context->EFlags & FLAG_IOPL) != 0 || + (Context->EFlags & FLAG_NT) || + (Context->EFlags & FLAG_VM) || + (!(Context->EFlags & FLAG_IF))) + { + return(STATUS_UNSUCCESSFUL); + } + return(STATUS_SUCCESS); +} + +NTSTATUS HalInitTaskWithContext(PETHREAD Thread, PCONTEXT Context) +/* + * FUNCTION: Initialize a task with a user mode context + * ARGUMENTS: + * Thread = Thread to initialize + * Context = Processor context to initialize it with + * RETURNS: Status + */ +{ + unsigned int desc; + unsigned int length; + unsigned int base; + PVOID kernel_stack; + NTSTATUS Status; + PVOID stack_start; + + DPRINT("HalInitTaskWithContext(Thread %x, Context %x)\n", + Thread,Context); + + assert(sizeof(hal_thread_state)>=0x68); + + if ((Status=KeValidateUserContext(Context))!=STATUS_SUCCESS) + { + return(Status); + } + + desc = allocate_tss_descriptor(); + length = sizeof(hal_thread_state) - 1; + base = (unsigned int)(&(Thread->Tcb.Context)); + kernel_stack = ExAllocatePool(NonPagedPool,PAGESIZE); + + /* + * Setup a TSS descriptor + */ + gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); + gdt[desc].b = ((base & 0xff0000)>>16) | 0x8900 | (length & 0xf0000) + | (base & 0xff000000); + + stack_start = kernel_stack + 4096 - sizeof(CONTEXT); + memcpy(stack_start, Context, sizeof(CONTEXT)); + + /* + * Initialize the thread context + */ + memset(&Thread->Tcb.Context,0,sizeof(hal_thread_state)); + Thread->Tcb.Context.ldt = null_ldt_sel; + Thread->Tcb.Context.eflags = (1<<1) + (1<<9); + Thread->Tcb.Context.iomap_base = FIELD_OFFSET(hal_thread_state,io_bitmap); + Thread->Tcb.Context.esp0 = stack_start; + Thread->Tcb.Context.ss0 = KERNEL_DS; + Thread->Tcb.Context.esp = stack_start; + Thread->Tcb.Context.ss = KERNEL_DS; + Thread->Tcb.Context.cs = KERNEL_CS; + Thread->Tcb.Context.eip = PsBeginThreadWithContextInternal; + Thread->Tcb.Context.io_bitmap[0] = 0xff; + Thread->Tcb.Context.cr3 = + linear_to_physical(Thread->ThreadsProcess->Pcb.PageTableDirectory); + Thread->Tcb.Context.ds = KERNEL_DS; + Thread->Tcb.Context.es = KERNEL_DS; + Thread->Tcb.Context.fs = KERNEL_DS; + Thread->Tcb.Context.gs = KERNEL_DS; + + Thread->Tcb.Context.nr = desc * 8; + DPRINT("Allocated %x\n",desc*8); + + return(STATUS_SUCCESS); +} + +BOOLEAN HalInitTask(PETHREAD thread, PKSTART_ROUTINE fn, PVOID StartContext) +/* + * FUNCTION: Initializes the HAL portion of a thread object + * ARGUMENTS: + * thread = Object describes the thread + * fn = Entrypoint for the thread + * StartContext = parameter to pass to the thread entrypoint + * RETURNS: True if the function succeeded + */ +{ + unsigned int desc = allocate_tss_descriptor(); + unsigned int length = sizeof(hal_thread_state) - 1; + unsigned int base = (unsigned int)(&(thread->Tcb.Context)); + unsigned int* kernel_stack = ExAllocatePool(NonPagedPool,4096); + + DPRINT("HalInitTask(Thread %x, fn %x, StartContext %x)\n", + thread,fn,StartContext); + DPRINT("thread->ThreadsProcess %x\n",thread->ThreadsProcess); + + /* + * Make sure + */ + assert(sizeof(hal_thread_state)>=0x68); + + /* + * Setup a TSS descriptor + */ + gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); + gdt[desc].b = ((base & 0xff0000)>>16) | 0x8900 | (length & 0xf0000) + | (base & 0xff000000); + +// DPRINT("sizeof(descriptor) %d\n",sizeof(descriptor)); +// DPRINT("desc %d\n",desc); + DPRINT("&gdt[desc].a %.8x gdt[desc].a %.8x\ngdt[desc].b %.8x\n", + &(gdt[desc].a), + gdt[desc].a, + gdt[desc].b); + + /* + * Initialize the stack for the thread (including the two arguments to + * the general start routine). + */ + kernel_stack[1023] = (unsigned int)StartContext; + kernel_stack[1022] = (unsigned int)fn; + kernel_stack[1021] = NULL; + + /* + * Initialize the thread context + */ + memset(&thread->Tcb.Context,0,sizeof(hal_thread_state)); + thread->Tcb.Context.ldt = null_ldt_sel; + thread->Tcb.Context.eflags = (1<<1)+(1<<9); + thread->Tcb.Context.iomap_base = FIELD_OFFSET(hal_thread_state,io_bitmap); + thread->Tcb.Context.esp0 = &kernel_stack[1021]; + thread->Tcb.Context.ss0 = KERNEL_DS; + thread->Tcb.Context.esp = &kernel_stack[1021]; + thread->Tcb.Context.ss = KERNEL_DS; + thread->Tcb.Context.cs = KERNEL_CS; + thread->Tcb.Context.eip = (unsigned long)PsBeginThread; + thread->Tcb.Context.io_bitmap[0] = 0xff; + thread->Tcb.Context.cr3 = + linear_to_physical(thread->ThreadsProcess->Pcb.PageTableDirectory); + thread->Tcb.Context.ds = KERNEL_DS; + thread->Tcb.Context.es = KERNEL_DS; + thread->Tcb.Context.fs = KERNEL_DS; + thread->Tcb.Context.gs = KERNEL_DS; + thread->Tcb.Context.nr = desc * 8; + DPRINT("Allocated %x\n",desc*8); + + + return(TRUE); +} + +void HalInitFirstTask(PETHREAD thread) +/* + * FUNCTION: Called to setup the HAL portion of a thread object for the + * initial thread + */ +{ + unsigned int base; + unsigned int length; + unsigned int desc; + + memset(null_ldt,0,sizeof(null_ldt)); + desc = allocate_tss_descriptor(); + base = (unsigned int)&null_ldt; + length = sizeof(null_ldt) - 1; + gdt[desc].a = (length & 0xffff) | ((base & 0xffff) << 16); + gdt[desc].b = ((base & 0xff0000)>>16) | 0x8200 | (length & 0xf0000) + | (base & 0xff000000); + null_ldt_sel = desc*8; + + /* + * Initialize the thread context + */ + HalInitTask(thread,NULL,NULL); + + /* + * Load the task register + */ + __asm__("ltr %%ax" + : /* no output */ + : "a" (thread->Tcb.Context.nr)); + FirstThread = thread; +} diff --git a/reactos/ntoskrnl/io/device.c b/reactos/ntoskrnl/io/device.c index 927fa993447..f731aa12426 100644 --- a/reactos/ntoskrnl/io/device.c +++ b/reactos/ntoskrnl/io/device.c @@ -125,7 +125,7 @@ NTSTATUS InitalizeLoadedDriver(PDRIVER_INITIALIZE entry) /* * Allocate memory for a driver object * NOTE: The object only becomes system visible once the associated - * device objects are intialized + * device objects are initialized */ DriverObject=ExAllocatePool(NonPagedPool,sizeof(DRIVER_OBJECT)); if (DriverObject==NULL) diff --git a/reactos/ntoskrnl/io/irp.c b/reactos/ntoskrnl/io/irp.c index cb24a61f599..e7108dc4190 100644 --- a/reactos/ntoskrnl/io/irp.c +++ b/reactos/ntoskrnl/io/irp.c @@ -1,308 +1,309 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/irp.c - * PURPOSE: Handle IRPs - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 24/05/98: Created - */ - -/* NOTES ******************************************************************* - * - * Layout of an IRP - * - * ################ - * # Headers # - * ################ - * # # - * # Variable # - * # length list # - * # of io stack # - * # locations # - * # # - * ################ - * - * - * - */ - -/* INCLUDES ****************************************************************/ - -#include -#include -#include - -//#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread) -/* - * FUNCTION: Returns a pointer to the device, representing a removable-media - * device, that is the target of the given thread's I/O request - */ -{ - UNIMPLEMENTED; -} - -VOID IoFreeIrp(PIRP Irp) -/* - * FUNCTION: Releases a caller allocated irp - * ARGUMENTS: - * Irp = Irp to free - */ -{ - ExFreePool(Irp); -} - -PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize) -/* - * FUNCTION: Allocates and initializes an irp to associated with a master irp - * ARGUMENTS: - * Irp = Master irp - * StackSize = Number of stack locations to be allocated in the irp - * RETURNS: The irp allocated - */ -{ - PIRP AssocIrp; - - AssocIrp = IoAllocateIrp(StackSize,FALSE); - UNIMPLEMENTED; -} - -VOID IoMarkIrpPending(PIRP Irp) -/* - * FUNCTION: Marks the specified irp, indicating further processing will - * be required by other driver routines - * ARGUMENTS: - * Irp = Irp to mark - */ -{ - DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n", - IoGetCurrentIrpStackLocation(Irp)); - IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED; - Irp->Tail.Overlay.Thread = KeGetCurrentThread(); - DPRINT("IoGetCurrentIrpStackLocation(Irp)->Control %x\n", - IoGetCurrentIrpStackLocation(Irp)->Control); - DPRINT("SL_PENDING_RETURNED %x\n",SL_PENDING_RETURNED); -} - -USHORT IoSizeOfIrp(CCHAR StackSize) -/* - * FUNCTION: Determines the size of an IRP - * ARGUMENTS: - * StackSize = number of stack locations in the IRP - * RETURNS: The size of the IRP in bytes - */ -{ - return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION))); -} - -VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize) -/* - * FUNCTION: Initalizes an irp allocated by the caller - * ARGUMENTS: - * Irp = IRP to initalize - * PacketSize = Size in bytes of the IRP - * StackSize = Number of stack locations in the IRP - */ -{ - assert(Irp!=NULL); - memset(Irp,0,PacketSize); - Irp->StackCount=StackSize; - Irp->CurrentLocation=StackSize; - Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp); -} - -PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp) -/* - * FUNCTION: Gets a pointer to the callers location in the I/O stack in - * the given IRP - * ARGUMENTS: - * Irp = Points to the IRP - * RETURNS: A pointer to the stack location - */ -{ - DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", - Irp, - Irp->CurrentLocation, - Irp->StackCount); - - return &Irp->Stack[Irp->CurrentLocation]; -} - - -VOID IoSetNextIrpStackLocation(PIRP Irp) -{ - Irp->CurrentLocation--; - Irp->Tail.Overlay.CurrentStackLocation--; -} - -PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp) -/* - * FUNCTION: Gives a higher level driver access to the next lower driver's - * I/O stack location - * ARGUMENTS: - * Irp = points to the irp - * RETURNS: A pointer to the stack location - */ -{ - DPRINT("IoGetNextIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", - Irp, - Irp->CurrentLocation, - Irp->StackCount); - - assert(Irp!=NULL); - DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation); - return(&Irp->Stack[Irp->CurrentLocation-1]); -} - -NTSTATUS IoCallDriver(PDEVICE_OBJECT DevObject, PIRP irp) -/* - * FUNCTION: Sends an IRP to the next lower driver - */ -{ - NTSTATUS Status; - PDRIVER_OBJECT drv = DevObject->DriverObject; - IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(irp); - - DPRINT("Deviceobject %x\n",DevObject); - DPRINT("Irp %x\n",irp); - - irp->Tail.Overlay.CurrentStackLocation--; - irp->CurrentLocation--; - - DPRINT("Io stack address %x\n",param); - DPRINT("Function %d Routine %x\n",param->MajorFunction, - drv->MajorFunction[param->MajorFunction]); - - Status = drv->MajorFunction[param->MajorFunction](DevObject,irp); - return Status; -} - -PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota) -/* - * FUNCTION: Allocates an IRP - * ARGUMENTS: - * StackSize = the size of the stack required for the irp - * ChargeQuota = Charge allocation to current threads quota - * RETURNS: Irp allocated - */ -{ - PIRP Irp; - - DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize, - ChargeQuota); - if (ChargeQuota) - { - Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize)); - } - else - { - Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize)); - } - - if (Irp==NULL) - { - return(NULL); - } - - Irp->StackCount=StackSize; - Irp->CurrentLocation=StackSize; - - DPRINT("Irp %x Irp->StackPtr %d\n",Irp,Irp->CurrentLocation); - return(Irp); -} - -VOID IoSetCompletionRoutine(PIRP Irp, - PIO_COMPLETION_ROUTINE CompletionRoutine, - PVOID Context, - BOOLEAN InvokeOnSuccess, - BOOLEAN InvokeOnError, - BOOLEAN InvokeOnCancel) -{ - IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp); - - param->CompletionRoutine=CompletionRoutine; - param->CompletionContext=Context; - if (InvokeOnSuccess) - { - param->Control = param->Control | SL_INVOKE_ON_SUCCESS; - } - if (InvokeOnError) - { - param->Control = param->Control | SL_INVOKE_ON_ERROR; - } - if (InvokeOnCancel) - { - param->Control = param->Control | SL_INVOKE_ON_CANCEL; - } -} - -VOID IopCompleteRequest(struct _KAPC* Apc, - PKNORMAL_ROUTINE* NormalRoutine, - PVOID* NormalContext, - PVOID* SystemArgument1, - PVOID* SystemArgument2) -{ - IoSecondStageCompletion((PIRP)(*NormalContext), - IO_NO_INCREMENT); -} - -VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) -/* - * FUNCTION: Indicates the caller has finished all processing for a given - * I/O request and is returning the given IRP to the I/O manager - * ARGUMENTS: - * Irp = Irp to be cancelled - * PriorityBoost = Increment by which to boost the priority of the - * thread making the request - */ -{ - unsigned int i; - NTSTATUS Status; - - DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n", - Irp,PriorityBoost); - - for (i=0;iStackCount;i++) - { - DPRINT("&Irp->Stack[i] %x\n",&Irp->Stack[i]); - if (Irp->Stack[i].CompletionRoutine!=NULL) - { - Status = Irp->Stack[i].CompletionRoutine( - Irp->Stack[i].DeviceObject, - Irp, - Irp->Stack[i].CompletionContext); - if (Status == STATUS_MORE_PROCESSING_REQUIRED) - { - return; - } - } - DPRINT("Irp->Stack[i].Control %x\n",Irp->Stack[i].Control); - if (Irp->Stack[i].Control & SL_PENDING_RETURNED) - { - DPRINT("Setting PendingReturned flag\n"); - Irp->PendingReturned = TRUE; - } - } - - if (Irp->PendingReturned) - { - KeInitializeApc(&Irp->Tail.Apc, - &Irp->Tail.Overlay.Thread->Tcb, - 0, - IopCompleteRequest, - NULL, - NULL, - 0, - Irp); - KeInsertQueueApc(&Irp->Tail.Apc,NULL,NULL,0); - } - else - { - IoSecondStageCompletion(Irp,PriorityBoost); - } -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/irp.c + * PURPOSE: Handle IRPs + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 24/05/98: Created + */ + +/* NOTES ******************************************************************* + * + * Layout of an IRP + * + * ################ + * # Headers # + * ################ + * # # + * # Variable # + * # length list # + * # of io stack # + * # locations # + * # # + * ################ + * + * + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread) +/* + * FUNCTION: Returns a pointer to the device, representing a removable-media + * device, that is the target of the given thread's I/O request + */ +{ + UNIMPLEMENTED; +} + +VOID IoFreeIrp(PIRP Irp) +/* + * FUNCTION: Releases a caller allocated irp + * ARGUMENTS: + * Irp = Irp to free + */ +{ + ExFreePool(Irp); +} + +PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize) +/* + * FUNCTION: Allocates and initializes an irp to associated with a master irp + * ARGUMENTS: + * Irp = Master irp + * StackSize = Number of stack locations to be allocated in the irp + * RETURNS: The irp allocated + */ +{ + PIRP AssocIrp; + + AssocIrp = IoAllocateIrp(StackSize,FALSE); + UNIMPLEMENTED; +} + +VOID IoMarkIrpPending(PIRP Irp) +/* + * FUNCTION: Marks the specified irp, indicating further processing will + * be required by other driver routines + * ARGUMENTS: + * Irp = Irp to mark + */ +{ + DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n", + IoGetCurrentIrpStackLocation(Irp)); + IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED; + Irp->Tail.Overlay.Thread = KeGetCurrentThread(); + DPRINT("IoGetCurrentIrpStackLocation(Irp)->Control %x\n", + IoGetCurrentIrpStackLocation(Irp)->Control); + DPRINT("SL_PENDING_RETURNED %x\n",SL_PENDING_RETURNED); +} + +USHORT IoSizeOfIrp(CCHAR StackSize) +/* + * FUNCTION: Determines the size of an IRP + * ARGUMENTS: + * StackSize = number of stack locations in the IRP + * RETURNS: The size of the IRP in bytes + */ +{ + return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION))); +} + +VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize) +/* + * FUNCTION: Initalizes an irp allocated by the caller + * ARGUMENTS: + * Irp = IRP to initalize + * PacketSize = Size in bytes of the IRP + * StackSize = Number of stack locations in the IRP + */ +{ + assert(Irp!=NULL); + memset(Irp,0,PacketSize); + Irp->StackCount=StackSize; + Irp->CurrentLocation=StackSize; + Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp); +} + +PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp) +/* + * FUNCTION: Gets a pointer to the callers location in the I/O stack in + * the given IRP + * ARGUMENTS: + * Irp = Points to the IRP + * RETURNS: A pointer to the stack location + */ +{ + DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", + Irp, + Irp->CurrentLocation, + Irp->StackCount); + + return &Irp->Stack[Irp->CurrentLocation]; +} + + +VOID IoSetNextIrpStackLocation(PIRP Irp) +{ + Irp->CurrentLocation--; + Irp->Tail.Overlay.CurrentStackLocation--; +} + +PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp) +/* + * FUNCTION: Gives a higher level driver access to the next lower driver's + * I/O stack location + * ARGUMENTS: + * Irp = points to the irp + * RETURNS: A pointer to the stack location + */ +{ + DPRINT("IoGetNextIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", + Irp, + Irp->CurrentLocation, + Irp->StackCount); + + assert(Irp!=NULL); + DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation); + return(&Irp->Stack[Irp->CurrentLocation-1]); +} + +NTSTATUS IoCallDriver(PDEVICE_OBJECT DevObject, PIRP irp) +/* + * FUNCTION: Sends an IRP to the next lower driver + */ +{ + NTSTATUS Status; + PDRIVER_OBJECT drv = DevObject->DriverObject; + IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(irp); + + DPRINT("Deviceobject %x\n",DevObject); + DPRINT("Irp %x\n",irp); + + irp->Tail.Overlay.CurrentStackLocation--; + irp->CurrentLocation--; + + DPRINT("Io stack address %x\n",param); + DPRINT("Function %d Routine %x\n",param->MajorFunction, + drv->MajorFunction[param->MajorFunction]); + + Status = drv->MajorFunction[param->MajorFunction](DevObject,irp); + return Status; +} + +PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota) +/* + * FUNCTION: Allocates an IRP + * ARGUMENTS: + * StackSize = the size of the stack required for the irp + * ChargeQuota = Charge allocation to current threads quota + * RETURNS: Irp allocated + */ +{ + PIRP Irp; + + DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize, + ChargeQuota); + if (ChargeQuota) + { + Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize)); + } + else + { + Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize)); + } + + if (Irp==NULL) + { + return(NULL); + } + + Irp->StackCount=StackSize; + Irp->CurrentLocation=StackSize; + + DPRINT("Irp %x Irp->StackPtr %d\n",Irp,Irp->CurrentLocation); + return(Irp); +} + +VOID IoSetCompletionRoutine(PIRP Irp, + PIO_COMPLETION_ROUTINE CompletionRoutine, + PVOID Context, + BOOLEAN InvokeOnSuccess, + BOOLEAN InvokeOnError, + BOOLEAN InvokeOnCancel) +{ + IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp); + + param->CompletionRoutine=CompletionRoutine; + param->CompletionContext=Context; + if (InvokeOnSuccess) + { + param->Control = param->Control | SL_INVOKE_ON_SUCCESS; + } + if (InvokeOnError) + { + param->Control = param->Control | SL_INVOKE_ON_ERROR; + } + if (InvokeOnCancel) + { + param->Control = param->Control | SL_INVOKE_ON_CANCEL; + } +} + +VOID IopCompleteRequest(struct _KAPC* Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +{ + IoSecondStageCompletion((PIRP)(*NormalContext), + IO_NO_INCREMENT); +} + +VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) +/* + * FUNCTION: Indicates the caller has finished all processing for a given + * I/O request and is returning the given IRP to the I/O manager + * ARGUMENTS: + * Irp = Irp to be cancelled + * PriorityBoost = Increment by which to boost the priority of the + * thread making the request + */ +{ + unsigned int i; + NTSTATUS Status; + + DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n", + Irp,PriorityBoost); + + for (i=0;iStackCount;i++) + { + DPRINT("&Irp->Stack[i] %x\n",&Irp->Stack[i]); + if (Irp->Stack[i].CompletionRoutine!=NULL) + { + Status = Irp->Stack[i].CompletionRoutine( + Irp->Stack[i].DeviceObject, + Irp, + Irp->Stack[i].CompletionContext); + if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + return; + } + } + DPRINT("Irp->Stack[i].Control %x\n",Irp->Stack[i].Control); + if (Irp->Stack[i].Control & SL_PENDING_RETURNED) + { + DPRINT("Setting PendingReturned flag\n"); + Irp->PendingReturned = TRUE; + } + } + + if (Irp->PendingReturned) + { + KeInitializeApc(&Irp->Tail.Apc, + &Irp->Tail.Overlay.Thread->Tcb, + 0, + IopCompleteRequest, + NULL, + NULL, + 0, + Irp); + KeInsertQueueApc(&Irp->Tail.Apc,NULL,NULL,0); + } + else + { + IoSecondStageCompletion(Irp,PriorityBoost); + } +} +>>>>>>> 1.7 diff --git a/reactos/ntoskrnl/io/page.c b/reactos/ntoskrnl/io/page.c index 158667a7df8..2f6b2fc8173 100644 --- a/reactos/ntoskrnl/io/page.c +++ b/reactos/ntoskrnl/io/page.c @@ -28,6 +28,9 @@ NTSTATUS IoPageRead(PFILE_OBJECT FileObject, PIO_STACK_LOCATION StackPtr; NTSTATUS Status; + DPRINT("IoPageRead(FileObject %x, Address %x)\n", + FileObject,Address); + KeInitializeEvent(&Event,NotificationEvent,FALSE); Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, FileObject->DeviceObject, diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 77c6d059a55..49722c66ca3 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -1,193 +1,178 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/main.c - * PURPOSE: Initalizes the kernel - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 28/05/98: Created - */ - -/* INCLUDES *****************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -void set_breakpoint(unsigned int i, unsigned int addr, unsigned int type, - unsigned int len) -/* - * FUNCTION: Sets a hardware breakpoint - * ARGUMENTS: - * i = breakpoint to set (0 to 3) - * addr = linear address to break on - * type = Type of access to break on - * len = length of the variable to watch - * NOTES: - * The variable to watch must be aligned to its length (i.e. a dword - * breakpoint must be aligned to a dword boundary) - * - * A fatal exception will be generated on the access to the variable. - * It is (at the moment) only really useful for catching undefined - * pointers if you know the variable effected but not the buggy - * routine. - * - * FIXME: Extend to call out to kernel debugger on breakpoint - * Add support for I/O breakpoints - * REFERENCES: See the i386 programmer manual for more details - */ -{ - unsigned int mask; - - if (i>3) - { - printk("Invalid breakpoint index at %s:%d\n",__FILE__,__LINE__); - return; - } - - /* - * Load the linear address - */ - switch (i) - { - case 0: - __asm("movl %0,%%db0\n\t" - : /* no outputs */ - : "d" (addr)); - break; - - case 1: - __asm__("movl %0,%%db1\n\t" - : /* no outputs */ - : "d" (addr)); - break; - - case 2: - __asm__("movl %0,%%db2\n\t" - : /* no outputs */ - : "d" (addr)); - break; - - case 3: - __asm__("movl %0,%%db3\n\t" - : /* no outputs */ - : "d" (addr)); - break; - } - - /* - * Setup mask for dr7 - */ - mask = (len<<(16 + 2 + i*4)) + (type<<(16 + i*4)) + (1<<(i*2)); - __asm__("movl %%db7,%%eax\n\t" - "orl %0,%%eax\n\t" - "movl %%eax,%%db7\n\t" - : /* no outputs */ - : "d" (mask) - : "ax"); -} - -extern int edata; -extern int end; - -asmlinkage void _main(boot_param* _bp) -/* - * FUNCTION: Called by the boot loader to start the kernel - * ARGUMENTS: - * _bp = Pointer to boot parameters initialized by the boot loader - * NOTE: The boot parameters are stored in low memory which will become - * invalid after the memory managment is initialized so we make a local copy. - */ -{ - unsigned int i; - unsigned int start; - unsigned int start1; - boot_param bp; - -// memset((void *)&edata,0,((int)&end)-((int)&edata)); - - /* - * Copy the parameters to a local buffer because lowmem will go away - */ - memcpy(&bp,_bp,sizeof(boot_param)); - - /* - * Initalize the console (before printing anything) - */ - HalInitConsole(&bp); - - DbgPrint("Starting ReactOS "KERNEL_VERSION"\n"); - - start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); - if (start < ((int)&end)) - { - DbgPrint("start %x end %x\n",start,(int)&end); - DbgPrint("Kernel booted incorrectly, aborting\n"); - DbgPrint("Reduce the amount of uninitialized data\n"); - for(;;); - } - DPRINT("MmGetPhysicalAddress(start) = %x\n",MmGetPhysicalAddress((void *)start)); - DPRINT("bp.module_length[0] %x PAGE_ROUND_UP(bp.module_length[0]) %x\n", - bp.module_length[0],PAGE_ROUND_UP(bp.module_length[0])); - start1 = start+PAGE_ROUND_UP(bp.module_length[1]); - DPRINT("bp.module_length[1] %x PAGE_ROUND_UP(bp.module_length[1]) %x\n", - bp.module_length[1],PAGE_ROUND_UP(bp.module_length[1])); - - DPRINT("start %x *start %x\n",start,*((unsigned int *)start)); - DPRINT("start1 %x *start1 %x\n",start1,*((unsigned int *)start1)); - - - /* - * Initalize various critical subsystems - */ - HalInit(&bp); - MmInitalize(&bp); - CHECKPOINT; - KeInit(); - CHECKPOINT; - ObInit(); - CHECKPOINT; - PsInit(); - CHECKPOINT; - IoInit(); - CHECKPOINT; - - /* - * Initalize services loaded at boot time - */ - DPRINT("%d files loaded\n",bp.nr_files); - - start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); - start1 = start+PAGE_ROUND_UP(bp.module_length[1]); -// DbgPrint("start1 %x *start1 %x\n",start1,*((unsigned int *)start1)); - for (i=1;i + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +void set_breakpoint(unsigned int i, unsigned int addr, unsigned int type, + unsigned int len) +/* + * FUNCTION: Sets a hardware breakpoint + * ARGUMENTS: + * i = breakpoint to set (0 to 3) + * addr = linear address to break on + * type = Type of access to break on + * len = length of the variable to watch + * NOTES: + * The variable to watch must be aligned to its length (i.e. a dword + * breakpoint must be aligned to a dword boundary) + * + * A fatal exception will be generated on the access to the variable. + * It is (at the moment) only really useful for catching undefined + * pointers if you know the variable effected but not the buggy + * routine. + * + * FIXME: Extend to call out to kernel debugger on breakpoint + * Add support for I/O breakpoints + * REFERENCES: See the i386 programmer manual for more details + */ +{ + unsigned int mask; + + if (i>3) + { + printk("Invalid breakpoint index at %s:%d\n",__FILE__,__LINE__); + return; + } + + /* + * Load the linear address + */ + switch (i) + { + case 0: + __asm("movl %0,%%db0\n\t" + : /* no outputs */ + : "d" (addr)); + break; + + case 1: + __asm__("movl %0,%%db1\n\t" + : /* no outputs */ + : "d" (addr)); + break; + + case 2: + __asm__("movl %0,%%db2\n\t" + : /* no outputs */ + : "d" (addr)); + break; + + case 3: + __asm__("movl %0,%%db3\n\t" + : /* no outputs */ + : "d" (addr)); + break; + } + + /* + * Setup mask for dr7 + */ + mask = (len<<(16 + 2 + i*4)) + (type<<(16 + i*4)) + (1<<(i*2)); + __asm__("movl %%db7,%%eax\n\t" + "orl %0,%%eax\n\t" + "movl %%eax,%%db7\n\t" + : /* no outputs */ + : "d" (mask) + : "ax"); +} + +extern int edata; +extern int end; + +asmlinkage void _main(boot_param* _bp) +/* + * FUNCTION: Called by the boot loader to start the kernel + * ARGUMENTS: + * _bp = Pointer to boot parameters initialized by the boot loader + * NOTE: The boot parameters are stored in low memory which will become + * invalid after the memory managment is initialized so we make a local copy. + */ +{ + unsigned int i; + unsigned int start; + unsigned int start1; + boot_param bp; + + memset((void *)&edata,0,((int)&end)-((int)&edata)); + + /* + * Copy the parameters to a local buffer because lowmem will go away + */ + memcpy(&bp,_bp,sizeof(boot_param)); + + /* + * Initalize the console (before printing anything) + */ + HalInitConsole(&bp); + + DbgPrint("Starting ReactOS "KERNEL_VERSION"\n"); + + start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); + if (start < ((int)&end)) + { + DbgPrint("start %x end %x\n",start,(int)&end); + DbgPrint("Kernel booted incorrectly, aborting\n"); + DbgPrint("Reduce the amount of uninitialized data\n"); + for(;;); + } + start1 = start+PAGE_ROUND_UP(bp.module_length[1]); + + + /* + * Initalize various critical subsystems + */ + HalInit(&bp); + MmInitalize(&bp); + KeInit(); + ObInit(); + PsInit(); + IoInit(); + + /* + * Initalize services loaded at boot time + */ + DPRINT("%d files loaded\n",bp.nr_files); + + start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); + start1 = start+PAGE_ROUND_UP(bp.module_length[1]); + for (i=1;i -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -#include - - -#if CHECKED -#define VALIDATE_POOL validate_kernel_pool() -#else -#define VALIDATE_POOL -#endif - -/* TYPES *******************************************************************/ - -#define BLOCK_HDR_MAGIC (0xdeadbeef) - -/* - * fields present at the start of a block (this is for internal use only) - */ -typedef struct _block_hdr -{ - ULONG magic; - unsigned int size; - struct _block_hdr* previous; - struct _block_hdr* next; - ULONG tag; -} block_hdr; - -/* GLOBALS *****************************************************************/ - -/* - * Memory managment initalized symbol for the base of the pool - */ -static unsigned int kernel_pool_base = 0; - -/* - * Pointer to the first block in the free list - */ -static block_hdr* free_list_head = NULL; -static block_hdr* used_list_head = NULL; -static unsigned int nr_free_blocks = 0; -unsigned int nr_used_blocks = 0; - -#define ALLOC_MAP_SIZE (NONPAGED_POOL_SIZE / PAGESIZE) - -/* - * One bit for each page in the kmalloc region - * If set then the page is used by a kmalloc block - */ -static unsigned int alloc_map[ALLOC_MAP_SIZE/32]={0,}; - -static unsigned int pool_free_mem = 0; - -unsigned int EiFreeNonPagedPool = 0; -unsigned int EiUsedNonPagedPool = 0; - -/* FUNCTIONS ***************************************************************/ - -VOID ExInitNonPagedPool(ULONG BaseAddress) -{ - kernel_pool_base=BaseAddress; -} - -static void validate_free_list(void) -/* - * FUNCTION: Validate the integrity of the list of free blocks - */ -{ - block_hdr* current=free_list_head; - unsigned int blocks_seen=0; - - while (current!=NULL) - { - unsigned int base_addr = (int)current; - - if (current->magic != BLOCK_HDR_MAGIC) - { - DbgPrint("Bad block magic (probable pool corruption)\n"); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - - if (base_addr < (kernel_pool_base) || - (base_addr+current->size) > - (kernel_pool_base)+NONPAGED_POOL_SIZE) - { - printk("Block %x found outside pool area\n",current); - printk("Size %d\n",current->size); - printk("Limits are %x %x\n",kernel_pool_base, - kernel_pool_base+NONPAGED_POOL_SIZE); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - blocks_seen++; - if (blocks_seen > nr_free_blocks) - { - printk("Too many blocks on list\n"); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } -// verify_for_write(base_addr,current->size); - if (current->next!=NULL&¤t->next->previous!=current) - { - printk("%s:%d:Break in list (current %x next %x " - "current->next->previous %x)\n", - __FILE__,__LINE__,current,current->next, - current->next->previous); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - current=current->next; - } -} - -static void validate_used_list(void) -/* - * FUNCTION: Validate the integrity of the list of used blocks - */ -{ - block_hdr* current=used_list_head; - unsigned int blocks_seen=0; - - while (current!=NULL) - { - unsigned int base_addr = (int)current; - - if (current->magic != BLOCK_HDR_MAGIC) - { - DbgPrint("Bad block magic (probable pool corruption)\n"); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - if (base_addr < (kernel_pool_base) || - (base_addr+current->size) > - (kernel_pool_base)+NONPAGED_POOL_SIZE) - { - printk("Block %x found outside pool area\n",current); - for(;;); - } - blocks_seen++; - if (blocks_seen > nr_used_blocks) - { - printk("Too many blocks on list\n"); - for(;;); - } - // verify_for_write(base_addr,current->size); - if (current->next!=NULL&¤t->next->previous!=current) - { - printk("Break in list (current %x next %x)\n", - current,current->next); - for(;;); - } - current=current->next; - } -} - -static void check_duplicates(block_hdr* blk) -/* - * FUNCTION: Check a block has no duplicates - * ARGUMENTS: - * blk = block to check - * NOTE: Bug checks if duplicates are found - */ -{ - unsigned int base = (int)blk; - unsigned int last = ((int)blk) + +sizeof(block_hdr) + blk->size; - - block_hdr* current=free_list_head; - while (current!=NULL) - { - if (current->magic != BLOCK_HDR_MAGIC) - { - DbgPrint("Bad block magic (probable pool corruption)\n"); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - - if ( (int)current > base && (int)current < last ) - { - printk("intersecting blocks on list\n"); - for(;;); - } - if ( (int)current < base && - ((int)current + current->size + sizeof(block_hdr)) - > base ) - { - printk("intersecting blocks on list\n"); - for(;;); - } - current=current->next; - } - current=used_list_head; - while (current!=NULL) - { - if ( (int)current > base && (int)current < last ) - { - printk("intersecting blocks on list\n"); - for(;;); - } - if ( (int)current < base && - ((int)current + current->size + sizeof(block_hdr)) - > base ) - { - printk("intersecting blocks on list\n"); - for(;;); - } - current=current->next; - } - -} - -static void validate_kernel_pool(void) -/* - * FUNCTION: Checks the integrity of the kernel memory heap - */ -{ - block_hdr* current=NULL; - - validate_free_list(); - validate_used_list(); - - current=free_list_head; - while (current!=NULL) - { - check_duplicates(current); - current=current->next; - } - current=used_list_head; - while (current!=NULL) - { - check_duplicates(current); - current=current->next; - } -} - -static void add_to_free_list(block_hdr* blk) -/* - * FUNCTION: add the block to the free list (internal) - */ -{ - blk->next=free_list_head; - blk->previous=NULL; - if (free_list_head!=NULL) - { - free_list_head->previous=blk; - } - free_list_head=blk; - nr_free_blocks++; -} - -static void add_to_used_list(block_hdr* blk) -/* - * FUNCTION: add the block to the used list (internal) - */ -{ - blk->next=used_list_head; - blk->previous=NULL; - if (used_list_head!=NULL) - { - used_list_head->previous=blk; - } - used_list_head=blk; - nr_used_blocks++; -} - - -static void remove_from_free_list(block_hdr* current) -{ - if (current->next==NULL&¤t->previous==NULL) - { - free_list_head=NULL; - } - else - { - if (current->next==NULL) - { - current->previous->next=NULL; - } - else if (current->previous==NULL) - { - current->next->previous=NULL; - free_list_head=current->next; - } - else - { - current->next->previous=current->previous; - current->previous->next=current->next; - } - } - nr_free_blocks--; -} - - -static void remove_from_used_list(block_hdr* current) -{ - if (current->next==NULL&¤t->previous==NULL) - { - used_list_head=NULL; - } - else - { - if (current->previous==NULL) - { - current->next->previous=NULL; - used_list_head=current->next; - } - else - { - current->previous->next=current->next; - } - if (current->next!=NULL) - { - current->next->previous=current->previous; - } - else - { - current->previous->next=NULL; - } - } - nr_used_blocks--; -} - - -inline static void* block_to_address(block_hdr* blk) -/* - * FUNCTION: Translate a block header address to the corresponding block - * address (internal) - */ -{ - return ( (void *) ((int)blk + sizeof(block_hdr)) ); -} - -inline static block_hdr* address_to_block(void* addr) -{ - return (block_hdr *) - ( ((int)addr) - sizeof(block_hdr) ); -} - -static unsigned int alloc_pool_region(unsigned int nr_pages) -/* - * FUNCTION: Allocates a region of pages within the nonpaged pool area - */ -{ - unsigned int start = 0; - unsigned int length = 0; - unsigned int i,j; - - OLD_DPRINT("alloc_pool_region(nr_pages = %d)\n",nr_pages); - - for (i=1; i(2*sizeof(block_hdr))) - { - used_blk = (struct _block_hdr *)start; - OLD_DPRINT("Creating block at %x\n",start); - used_blk->magic = BLOCK_HDR_MAGIC; - used_blk->size = size; - add_to_used_list(used_blk); - - free_blk = (block_hdr *)(start + sizeof(block_hdr) + size); - OLD_DPRINT("Creating block at %x\n",free_blk); - free_blk->magic = BLOCK_HDR_MAGIC; - free_blk->size = (nr_pages * PAGESIZE) -((sizeof(block_hdr)*2) + size); - add_to_free_list(free_blk); - - EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->size; - EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->size; - } - else - { - used_blk = (struct _block_hdr *)start; - used_blk->magic = BLOCK_HDR_MAGIC; - used_blk->size = nr_pages * PAGESIZE; - add_to_used_list(used_blk); - - EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->size; - } - - VALIDATE_POOL; - return(used_blk); -} - -static void* take_block(block_hdr* current, unsigned int size) -/* - * FUNCTION: Allocate a used block of least 'size' from the specified - * free block - * RETURNS: The address of the created memory block - */ -{ - /* - * If the block is much bigger than required then split it and - * return a pointer to the allocated section. If the difference - * between the sizes is marginal it makes no sense to have the - * extra overhead - */ - if (current->size > (1 + size + sizeof(block_hdr))) - { - block_hdr* free_blk; - - EiFreeNonPagedPool = EiFreeNonPagedPool - current->size; - - /* - * Replace the bigger block with a smaller block in the - * same position in the list - */ - free_blk = (block_hdr *)(((int)current) - + sizeof(block_hdr) + size); - free_blk->magic = BLOCK_HDR_MAGIC; - free_blk->next = current->next; - free_blk->previous = current->previous; - if (current->next) - { - current->next->previous = free_blk; - } - if (current->previous) - { - current->previous->next = free_blk; - } - free_blk->size = current->size - (sizeof(block_hdr) + size); - if (current==free_list_head) - { - free_list_head=free_blk; - } - - current->size=size; - add_to_used_list(current); - - EiUsedNonPagedPool = EiUsedNonPagedPool + current->size; - EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->size; - - VALIDATE_POOL; - return(block_to_address(current)); - } - - /* - * Otherwise allocate the whole block - */ - remove_from_free_list(current); - add_to_used_list(current); - - EiFreeNonPagedPool = EiFreeNonPagedPool - current->size; - EiUsedNonPagedPool = EiUsedNonPagedPool + current->size; - - VALIDATE_POOL; - return(block_to_address(current)); -} - -asmlinkage VOID ExFreePool(PVOID block) -/* - * FUNCTION: Releases previously allocated memory - * ARGUMENTS: - * block = block to free - */ -{ - block_hdr *blk = address_to_block(block); - - OLD_DPRINT("ExFreePool(block %x), size %d, caller %x\n", - block, - blk->size, - ((PULONG)&block)[-1]); - OLD_DPRINT("freeing block %x\n",blk); - - VALIDATE_POOL; - - if (blk->magic != BLOCK_HDR_MAGIC) - { - DbgPrint("ExFreePool of non-allocated address\n"); - for(;;); - return; - } - - /* - * Please don't change the order - */ - remove_from_used_list(blk); - add_to_free_list(blk); - - EiUsedNonPagedPool = EiUsedNonPagedPool - blk->size; - EiFreeNonPagedPool = EiFreeNonPagedPool + blk->size; - - VALIDATE_POOL; -} - -PVOID ExAllocateNonPagedPoolWithTag(ULONG type, ULONG size, ULONG Tag) -{ - block_hdr* current=NULL; - void* block; - - OLD_DPRINT("Blocks on free list %d\n",nr_free_blocks); - OLD_DPRINT("Blocks on used list %d\n",nr_used_blocks); - OLD_DPRINT("ExAllocateNonPagedPool(type %d, size %d)\n",type,size); - VALIDATE_POOL; - - /* - * accomodate this useful idiom - */ - if (size==0) - { - return(NULL); - } - - /* - * Look for an already created block of sufficent size - */ - current=free_list_head; - - while (current!=NULL) - { - OLD_DPRINT("current %x size %x next %x\n",current,current->size, - current->next); - if (current->magic != BLOCK_HDR_MAGIC) - { - DbgPrint("Bad block magic (probable pool corruption)\n"); - KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); - } - if (current->size>=size) - { - OLD_DPRINT("found block %x of size %d\n",current,size); - block=take_block(current,size); - memset(block,0,size); - return(block); - } - current=current->next; - } - - /* - * Otherwise create a new block - */ - block=block_to_address(grow_kernel_pool(size)); - memset(block,0,size); - - return block; -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pool.c + * PURPOSE: Implements the kernel memory pool + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 27/05/98: Created + * 10/06/98: Bug fixes by Iwan Fatahi (i_fatahi@hotmail.com) + * in take_block (if current bigger than required) + * in remove_from_used_list + * in ExFreePool + * 23/08/98: Fixes from Robert Bergkvist (fragdance@hotmail.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include + + +#if 0 +#define VALIDATE_POOL validate_kernel_pool() +#else +#define VALIDATE_POOL +#endif + +/* TYPES *******************************************************************/ + +#define BLOCK_HDR_MAGIC (0xdeadbeef) + +/* + * fields present at the start of a block (this is for internal use only) + */ +typedef struct _block_hdr +{ + ULONG magic; + ULONG size; + struct _block_hdr* previous; + struct _block_hdr* next; + ULONG tag; +} block_hdr; + +/* GLOBALS *****************************************************************/ + +/* + * Memory managment initalized symbol for the base of the pool + */ +static unsigned int kernel_pool_base = 0; + +/* + * Pointer to the first block in the free list + */ +static block_hdr* free_list_head = NULL; +static block_hdr* used_list_head = NULL; +static ULONG nr_free_blocks; +ULONG EiNrUsedBlocks = 0; + +#define ALLOC_MAP_SIZE (NONPAGED_POOL_SIZE / PAGESIZE) + +/* + * One bit for each page in the kmalloc region + * If set then the page is used by a kmalloc block + */ +static unsigned int alloc_map[ALLOC_MAP_SIZE/32]={0,}; + +static unsigned int pool_free_mem = 0; + +unsigned int EiFreeNonPagedPool = 0; +unsigned int EiUsedNonPagedPool = 0; + +/* FUNCTIONS ***************************************************************/ + +VOID ExInitNonPagedPool(ULONG BaseAddress) +{ + kernel_pool_base=BaseAddress; +} + +static void validate_free_list(void) +/* + * FUNCTION: Validate the integrity of the list of free blocks + */ +{ + block_hdr* current=free_list_head; + unsigned int blocks_seen=0; + + while (current!=NULL) + { + unsigned int base_addr = (int)current; + + if (current->magic != BLOCK_HDR_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption)\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + + if (base_addr < (kernel_pool_base) || + (base_addr+current->size) > + (kernel_pool_base)+NONPAGED_POOL_SIZE) + { + printk("Block %x found outside pool area\n",current); + printk("Size %d\n",current->size); + printk("Limits are %x %x\n",kernel_pool_base, + kernel_pool_base+NONPAGED_POOL_SIZE); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + blocks_seen++; + if (blocks_seen > nr_free_blocks) + { + printk("Too many blocks on list\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } +// verify_for_write(base_addr,current->size); + if (current->next!=NULL&¤t->next->previous!=current) + { + printk("%s:%d:Break in list (current %x next %x " + "current->next->previous %x)\n", + __FILE__,__LINE__,current,current->next, + current->next->previous); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + current=current->next; + } +} + +static void validate_used_list(void) +/* + * FUNCTION: Validate the integrity of the list of used blocks + */ +{ + block_hdr* current=used_list_head; + unsigned int blocks_seen=0; + + while (current!=NULL) + { + unsigned int base_addr = (int)current; + + if (current->magic != BLOCK_HDR_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption)\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + if (base_addr < (kernel_pool_base) || + (base_addr+current->size) > + (kernel_pool_base)+NONPAGED_POOL_SIZE) + { + printk("Block %x found outside pool area\n",current); + for(;;); + } + blocks_seen++; + if (blocks_seen > EiNrUsedBlocks) + { + printk("Too many blocks on list\n"); + for(;;); + } + // verify_for_write(base_addr,current->size); + if (current->next!=NULL&¤t->next->previous!=current) + { + printk("Break in list (current %x next %x)\n", + current,current->next); + for(;;); + } + current=current->next; + } +} + +static void check_duplicates(block_hdr* blk) +/* + * FUNCTION: Check a block has no duplicates + * ARGUMENTS: + * blk = block to check + * NOTE: Bug checks if duplicates are found + */ +{ + unsigned int base = (int)blk; + unsigned int last = ((int)blk) + +sizeof(block_hdr) + blk->size; + + block_hdr* current=free_list_head; + while (current!=NULL) + { + if (current->magic != BLOCK_HDR_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption)\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + + if ( (int)current > base && (int)current < last ) + { + printk("intersecting blocks on list\n"); + for(;;); + } + if ( (int)current < base && + ((int)current + current->size + sizeof(block_hdr)) + > base ) + { + printk("intersecting blocks on list\n"); + for(;;); + } + current=current->next; + } + current=used_list_head; + while (current!=NULL) + { + if ( (int)current > base && (int)current < last ) + { + printk("intersecting blocks on list\n"); + for(;;); + } + if ( (int)current < base && + ((int)current + current->size + sizeof(block_hdr)) + > base ) + { + printk("intersecting blocks on list\n"); + for(;;); + } + current=current->next; + } + +} + +static void validate_kernel_pool(void) +/* + * FUNCTION: Checks the integrity of the kernel memory heap + */ +{ + block_hdr* current=NULL; + + validate_free_list(); + validate_used_list(); + + current=free_list_head; + while (current!=NULL) + { + check_duplicates(current); + current=current->next; + } + current=used_list_head; + while (current!=NULL) + { + check_duplicates(current); + current=current->next; + } +} + +static void add_to_free_list(block_hdr* blk) +/* + * FUNCTION: add the block to the free list (internal) + */ +{ + blk->next=free_list_head; + blk->previous=NULL; + if (free_list_head!=NULL) + { + free_list_head->previous=blk; + } + free_list_head=blk; + nr_free_blocks++; +} + +static void add_to_used_list(block_hdr* blk) +/* + * FUNCTION: add the block to the used list (internal) + */ +{ + blk->next=used_list_head; + blk->previous=NULL; + if (used_list_head!=NULL) + { + used_list_head->previous=blk; + } + used_list_head=blk; + EiNrUsedBlocks++; +} + + +static void remove_from_free_list(block_hdr* current) +{ + if (current->next==NULL&¤t->previous==NULL) + { + free_list_head=NULL; + } + else + { + if (current->next==NULL) + { + current->previous->next=NULL; + } + else if (current->previous==NULL) + { + current->next->previous=NULL; + free_list_head=current->next; + } + else + { + current->next->previous=current->previous; + current->previous->next=current->next; + } + } + nr_free_blocks--; +} + + +static void remove_from_used_list(block_hdr* current) +{ + if (current->next==NULL&¤t->previous==NULL) + { + used_list_head=NULL; + } + else + { + if (current->previous==NULL) + { + current->next->previous=NULL; + used_list_head=current->next; + } + else + { + current->previous->next=current->next; + } + if (current->next!=NULL) + { + current->next->previous=current->previous; + } + else + { + current->previous->next=NULL; + } + } + EiNrUsedBlocks--; +} + + +inline static void* block_to_address(block_hdr* blk) +/* + * FUNCTION: Translate a block header address to the corresponding block + * address (internal) + */ +{ + return ( (void *) ((int)blk + sizeof(block_hdr)) ); +} + +inline static block_hdr* address_to_block(void* addr) +{ + return (block_hdr *) + ( ((int)addr) - sizeof(block_hdr) ); +} + +static unsigned int alloc_pool_region(unsigned int nr_pages) +/* + * FUNCTION: Allocates a region of pages within the nonpaged pool area + */ +{ + unsigned int start = 0; + unsigned int length = 0; + unsigned int i,j; + + OLD_DPRINT("alloc_pool_region(nr_pages = %d)\n",nr_pages); + + for (i=1; i(2*sizeof(block_hdr))) + { + used_blk = (struct _block_hdr *)start; + OLD_DPRINT("Creating block at %x\n",start); + used_blk->magic = BLOCK_HDR_MAGIC; + used_blk->size = size; + add_to_used_list(used_blk); + + free_blk = (block_hdr *)(start + sizeof(block_hdr) + size); + OLD_DPRINT("Creating block at %x\n",free_blk); + free_blk->magic = BLOCK_HDR_MAGIC; + free_blk->size = (nr_pages * PAGESIZE) -((sizeof(block_hdr)*2) + size); + add_to_free_list(free_blk); + + EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->size; + EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->size; + } + else + { + used_blk = (struct _block_hdr *)start; + used_blk->magic = BLOCK_HDR_MAGIC; + used_blk->size = nr_pages * PAGESIZE; + add_to_used_list(used_blk); + + EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->size; + } + + VALIDATE_POOL; + return(used_blk); +} + +static void* take_block(block_hdr* current, unsigned int size) +/* + * FUNCTION: Allocate a used block of least 'size' from the specified + * free block + * RETURNS: The address of the created memory block + */ +{ + /* + * If the block is much bigger than required then split it and + * return a pointer to the allocated section. If the difference + * between the sizes is marginal it makes no sense to have the + * extra overhead + */ + if (current->size > (1 + size + sizeof(block_hdr))) + { + block_hdr* free_blk; + + EiFreeNonPagedPool = EiFreeNonPagedPool - current->size; + + /* + * Replace the bigger block with a smaller block in the + * same position in the list + */ + free_blk = (block_hdr *)(((int)current) + + sizeof(block_hdr) + size); + free_blk->magic = BLOCK_HDR_MAGIC; + free_blk->next = current->next; + free_blk->previous = current->previous; + if (current->next) + { + current->next->previous = free_blk; + } + if (current->previous) + { + current->previous->next = free_blk; + } + free_blk->size = current->size - (sizeof(block_hdr) + size); + if (current==free_list_head) + { + free_list_head=free_blk; + } + + current->size=size; + add_to_used_list(current); + + EiUsedNonPagedPool = EiUsedNonPagedPool + current->size; + EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->size; + + VALIDATE_POOL; + return(block_to_address(current)); + } + + /* + * Otherwise allocate the whole block + */ + remove_from_free_list(current); + add_to_used_list(current); + + EiFreeNonPagedPool = EiFreeNonPagedPool - current->size; + EiUsedNonPagedPool = EiUsedNonPagedPool + current->size; + + VALIDATE_POOL; + return(block_to_address(current)); +} + +asmlinkage VOID ExFreePool(PVOID block) +/* + * FUNCTION: Releases previously allocated memory + * ARGUMENTS: + * block = block to free + */ +{ + block_hdr* blk=address_to_block(block); + OLD_DPRINT("(%s:%d) freeing block %x\n",__FILE__,__LINE__,blk); + +// DbgPrint("ExFreePool(block %x), size %d, caller %x\n",block,blk->size, +// ((PULONG)&block)[-1]); + + VALIDATE_POOL; + + if (blk->magic != BLOCK_HDR_MAGIC) + { + DbgPrint("ExFreePool of non-allocated address\n"); + for(;;); + return; + } + + /* + * Please don't change the order + */ + remove_from_used_list(blk); + add_to_free_list(blk); + + EiUsedNonPagedPool = EiUsedNonPagedPool - blk->size; + EiFreeNonPagedPool = EiFreeNonPagedPool + blk->size; + + VALIDATE_POOL; +} + +PVOID ExAllocateNonPagedPoolWithTag(ULONG type, ULONG size, ULONG Tag) +{ + block_hdr* current=NULL; + void* block; + +// DbgPrint("Blocks on free list %d\n",nr_free_blocks); +// DbgPrint("Blocks on used list %d\n",eiNrUsedblocks); +// OLD_DPRINT("ExAllocateNonPagedPool(type %d, size %d)\n",type,size); + VALIDATE_POOL; + + /* + * accomodate this useful idiom + */ + if (size==0) + { + return(NULL); + } + + /* + * Look for an already created block of sufficent size + */ + current=free_list_head; + + while (current!=NULL) + { + OLD_DPRINT("current %x size %x next %x\n",current,current->size, + current->next); + if (current->magic != BLOCK_HDR_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption)\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + if (current->size>=size) + { + OLD_DPRINT("found block %x of size %d\n",current,size); + block=take_block(current,size); + VALIDATE_POOL; + memset(block,0,size); + return(block); + } + current=current->next; + } + + /* + * Otherwise create a new block + */ + block=block_to_address(grow_kernel_pool(size)); + VALIDATE_POOL; + memset(block,0,size); + return(block); +} diff --git a/reactos/ntoskrnl/mm/pool.c b/reactos/ntoskrnl/mm/pool.c index e919b988ab4..d6b39442525 100644 --- a/reactos/ntoskrnl/mm/pool.c +++ b/reactos/ntoskrnl/mm/pool.c @@ -1,124 +1,118 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/pool.c - * PURPOSE: Implements the kernel memory pool - * PROGRAMMER: David Welch (welch@mcmail.com) - */ - -/* INCLUDES ****************************************************************/ - -#include -#include -#include - -#define NDEBUG -#include - -/* GLOBALS *****************************************************************/ - -#define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24)) - -/* FUNCTIONS ***************************************************************/ - -PVOID ExAllocatePool(POOL_TYPE PoolType, ULONG NumberOfBytes) -/* - * FUNCTION: Allocates pool memory of a specified type and returns a pointer - * to the allocated block. This routine is used for general purpose allocation - * of memory - * ARGUMENTS: - * PoolType - * Specifies the type of memory to allocate which can be one - * of the following: - * - * NonPagedPool - * NonPagedPoolMustSucceed - * NonPagedPoolCacheAligned - * NonPagedPoolCacheAlignedMustS - * PagedPool - * PagedPoolCacheAligned - * - * NumberOfBytes - * Specifies the number of bytes to allocate - * RETURNS: The allocated block on success - * NULL on failure - */ -{ - PVOID Block; - - OLD_DPRINT("ExAllocatePool(NumberOfBytes %d) caller %x\n", - NumberOfBytes, - ((PULONG)&PoolType)[-1]); - - Block = ExAllocatePoolWithTag(PoolType,NumberOfBytes,TAG_NONE); - - OLD_DPRINT("ExAllocatePool() = %x\n",Block); - - return Block; -} - -PVOID ExAllocatePoolWithTag(ULONG type, ULONG size, ULONG Tag) -{ - PVOID Block; - - if (type == NonPagedPoolCacheAligned || - type == NonPagedPoolCacheAlignedMustS) - { - UNIMPLEMENTED; - } - - switch(type) - { - case NonPagedPool: - case NonPagedPoolMustSucceed: - case NonPagedPoolCacheAligned: - case NonPagedPoolCacheAlignedMustS: - Block = ExAllocateNonPagedPoolWithTag(type,size,Tag); - break; - - case PagedPool: - case PagedPoolCacheAligned: - Block = ExAllocatePagedPoolWithTag(type,size,Tag); - break; - - default: - return(NULL); - }; - - if ((type==NonPagedPoolMustSucceed || type==NonPagedPoolCacheAlignedMustS) - && Block==NULL) - { - KeBugCheck(MUST_SUCCEED_POOL_EMPTY); - } - return(Block); -} - -PVOID ExAllocatePoolWithQuotaTag(POOL_TYPE PoolType, ULONG NumberOfBytes, - ULONG Tag) -{ - PVOID Block; - PKTHREAD current = KeGetCurrentThread(); - - Block = ExAllocatePoolWithTag(PoolType,NumberOfBytes,Tag); - switch(PoolType) - { - case NonPagedPool: - case NonPagedPoolMustSucceed: - case NonPagedPoolCacheAligned: - case NonPagedPoolCacheAlignedMustS: -// current->NPagedPoolQuota = current->NPagedPoolQuota - NumberOfBytes; - break; - - case PagedPool: - case PagedPoolCacheAligned: -// current->PagedPoolQuota = current->PagedPoolQuota - NumberOfBytes; - break; - }; - return(Block); -} - -PVOID ExAllocatePoolWithQuota(POOL_TYPE PoolType, ULONG NumberOfBytes) -{ - return(ExAllocatePoolWithQuotaTag(PoolType,NumberOfBytes,TAG_NONE)); -} - +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pool.c + * PURPOSE: Implements the kernel memory pool + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24)) + +/* FUNCTIONS ***************************************************************/ + +PVOID ExAllocatePool(POOL_TYPE PoolType, ULONG NumberOfBytes) +/* + * FUNCTION: Allocates pool memory of a specified type and returns a pointer + * to the allocated block. This routine is used for general purpose allocation + * of memory + * ARGUMENTS: + * PoolType + * Specifies the type of memory to allocate which can be one + * of the following: + * + * NonPagedPool + * NonPagedPoolMustSucceed + * NonPagedPoolCacheAligned + * NonPagedPoolCacheAlignedMustS + * PagedPool + * PagedPoolCacheAligned + * + * NumberOfBytes + * Specifies the number of bytes to allocate + * RETURNS: The allocated block on success + * NULL on failure + */ +{ + PVOID Block; +// DbgPrint("ExAllocatePool(NumberOfBytes %d) caller %x\n", +// NumberOfBytes,((PULONG)&PoolType)[-1]); + Block = ExAllocatePoolWithTag(PoolType,NumberOfBytes,TAG_NONE); +// DbgPrint("ExAllocatePool() = %x\n",Block); + return(Block); +} + +PVOID ExAllocatePoolWithTag(ULONG type, ULONG size, ULONG Tag) +{ + PVOID Block; + + if (type == NonPagedPoolCacheAligned || + type == NonPagedPoolCacheAlignedMustS) + { + UNIMPLEMENTED; + } + + switch(type) + { + case NonPagedPool: + case NonPagedPoolMustSucceed: + case NonPagedPoolCacheAligned: + case NonPagedPoolCacheAlignedMustS: + Block = ExAllocateNonPagedPoolWithTag(type,size,Tag); + break; + + case PagedPool: + case PagedPoolCacheAligned: + Block = ExAllocatePagedPoolWithTag(type,size,Tag); + break; + + default: + return(NULL); + }; + + if ((type==NonPagedPoolMustSucceed || type==NonPagedPoolCacheAlignedMustS) + && Block==NULL) + { + KeBugCheck(MUST_SUCCEED_POOL_EMPTY); + } + return(Block); +} + +PVOID ExAllocatePoolWithQuotaTag(POOL_TYPE PoolType, ULONG NumberOfBytes, + ULONG Tag) +{ + PVOID Block; + PKTHREAD current = KeGetCurrentThread(); + + Block = ExAllocatePoolWithTag(PoolType,NumberOfBytes,Tag); + switch(PoolType) + { + case NonPagedPool: + case NonPagedPoolMustSucceed: + case NonPagedPoolCacheAligned: + case NonPagedPoolCacheAlignedMustS: +// current->NPagedPoolQuota = current->NPagedPoolQuota - NumberOfBytes; + break; + + case PagedPool: + case PagedPoolCacheAligned: +// current->PagedPoolQuota = current->PagedPoolQuota - NumberOfBytes; + break; + }; + return(Block); +} + +PVOID ExAllocatePoolWithQuota(POOL_TYPE PoolType, ULONG NumberOfBytes) +{ + return(ExAllocatePoolWithQuotaTag(PoolType,NumberOfBytes,TAG_NONE)); +} diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index b42c776ecf5..006b97a1843 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -104,8 +104,8 @@ NTSTATUS STDCALL ZwCreateSection(OUT PHANDLE SectionHandle, PSECTION_OBJECT Section; NTSTATUS Status; - DPRINT("ZwCreateSection()\n"); - + DbgPrint("ZwCreateSection()\n"); + Section = ObGenericCreateObject(SectionHandle, DesiredAccess, ObjectAttributes, @@ -128,11 +128,13 @@ NTSTATUS STDCALL ZwCreateSection(OUT PHANDLE SectionHandle, NULL); if (Status != STATUS_SUCCESS) { + DPRINT("ZwCreateSection() = %x\n",Status); return(Status); } Section->AllocateAttributes = AllocationAttributes; + DPRINT("ZwCreateSection() = STATUS_SUCCESS\n"); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index 14a6834234f..5c0485b83c5 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -1,746 +1,746 @@ -/* - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/virtual.c - * PURPOSE: implementing the Virtualxxx section of the win32 api - * PROGRAMMER: David Welch - * UPDATE HISTORY: - * 09/4/98: Created - * 10/6/98: Corrections from Fatahi (i_fatahi@hotmail.com) - * 30/9/98: Implemented ZwxxxVirtualMemory functions - */ - -/* INCLUDE *****************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -/* TYPES *******************************************************************/ - -extern unsigned int etext; -extern unsigned int end; - -static MEMORY_AREA* kernel_text_desc = NULL; -static MEMORY_AREA* kernel_data_desc = NULL; -static MEMORY_AREA* kernel_param_desc = NULL; -static MEMORY_AREA* kernel_pool_desc = NULL; - -/* FUNCTIONS ****************************************************************/ - -void VirtualInit(boot_param* bp) -/* - * FUNCTION: Intialize the memory areas list - * ARGUMENTS: - * bp = Pointer to the boot parameters - * kernel_len = Length of the kernel - */ -{ - unsigned int kernel_len = bp->end_mem - bp->start_mem; - PVOID BaseAddress; - ULONG Length; - ULONG ParamLength = kernel_len; - - DPRINT("VirtualInit() %x\n",bp); - - MmInitMemoryAreas(); - ExInitNonPagedPool(KERNEL_BASE+ PAGE_ROUND_UP(kernel_len) + PAGESIZE); - - - /* - * Setup the system area descriptor list - */ - BaseAddress = (PVOID)KERNEL_BASE; - Length = PAGE_ROUND_UP(((ULONG)&etext)) - KERNEL_BASE; - ParamLength = ParamLength - Length; - MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, - Length,0,&kernel_text_desc); - - Length = PAGE_ROUND_UP(((ULONG)&end)) - PAGE_ROUND_UP(((ULONG)&etext)); - ParamLength = ParamLength - Length; - DPRINT("Length %x\n",Length); - BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&etext)); - MmCreateMemoryArea(KernelMode, - NULL, - MEMORY_AREA_SYSTEM, - &BaseAddress, - Length, - 0, - &kernel_data_desc); - - - BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&end)); - Length = ParamLength; - MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, - Length,0,&kernel_param_desc); - - BaseAddress = (PVOID)(KERNEL_BASE + PAGE_ROUND_UP(kernel_len) + PAGESIZE); - Length = NONPAGED_POOL_SIZE; - MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, - Length,0,&kernel_pool_desc); - -// MmDumpMemoryAreas(); - CHECKPOINT; - - MmInitSectionImplementation(); -} - -ULONG MmCommitedSectionHandleFault(MEMORY_AREA* MemoryArea, ULONG Address) -{ - set_page(Address,0x7,get_free_page()); - return(TRUE); -} - -NTSTATUS MmSectionHandleFault(MEMORY_AREA* MemoryArea, PVOID Address) -{ - LARGE_INTEGER Offset; - IO_STATUS_BLOCK IoStatus; - - DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n", - MemoryArea,Address); - - set_page((DWORD)Address,0x7,get_free_page()); - - LARGE_INTEGER_QUAD_PART(Offset) = (Address - MemoryArea->BaseAddress) + - MemoryArea->Data.SectionData.ViewOffset; - - DPRINT("MemoryArea->Data.SectionData.Section->FileObject %x\n", - MemoryArea->Data.SectionData.Section->FileObject); - - if (MemoryArea->Data.SectionData.Section->FileObject == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - IoPageRead(MemoryArea->Data.SectionData.Section->FileObject, - (PVOID)Address, - &Offset, - &IoStatus); - - DPRINT("Returning from MmSectionHandleFault()\n"); - - return(STATUS_SUCCESS); -} - -asmlinkage int page_fault_handler(unsigned int cs, - unsigned int eip) -/* - * FUNCTION: Handle a page fault - */ -{ - KPROCESSOR_MODE FaultMode; - MEMORY_AREA* MemoryArea; - KIRQL oldlvl; - ULONG stat; - - /* - * Get the address for the page fault - */ - unsigned int cr2; - __asm__("movl %%cr2,%0\n\t" : "=d" (cr2)); - DPRINT("Page fault at address %x with eip %x\n",cr2,eip); - - cr2 = PAGE_ROUND_DOWN(cr2); - - if (KeGetCurrentIrql()!=PASSIVE_LEVEL) - { - DbgPrint("Recursive page fault detected\n"); - return(0); -// KeBugCheck(0); - } - - KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); - - /* - * Find the memory area for the faulting address - */ - if (cr2>=KERNEL_BASE) - { - /* - * Check permissions - */ - if (cs!=KERNEL_CS) - { - printk("%s:%d\n",__FILE__,__LINE__); - return(0); - } - FaultMode = UserMode; - } - else - { - FaultMode = KernelMode; - } - - MemoryArea = MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),(PVOID)cr2); - if (MemoryArea==NULL) - { - printk("%s:%d\n",__FILE__,__LINE__); - return(0); - } - - switch (MemoryArea->Type) - { - case MEMORY_AREA_SYSTEM: - stat = 0; - break; - - case MEMORY_AREA_SECTION_VIEW_COMMIT: - if (MmSectionHandleFault(MemoryArea, (PVOID)cr2)==STATUS_SUCCESS) - { - stat=1; - } - else - { - stat = 0; - } - break; - - case MEMORY_AREA_COMMIT: - stat = MmCommitedSectionHandleFault(MemoryArea,cr2); - break; - - default: - stat = 0; - break; - } - if (stat) - { - KeLowerIrql(oldlvl); - } - return(stat); -} - -BOOLEAN MmIsNonPagedSystemAddressValid(PVOID VirtualAddress) -{ - UNIMPLEMENTED; -} - -BOOLEAN MmIsAddressValid(PVOID VirtualAddress) -/* - * FUNCTION: Checks whether the given address is valid for a read or write - * ARGUMENTS: - * VirtualAddress = address to check - * RETURNS: True if the access would be valid - * False if the access would cause a page fault - * NOTES: This function checks whether a byte access to the page would - * succeed. Is this realistic for RISC processors which don't - * allow byte granular access? - */ -{ - MEMORY_AREA* MemoryArea; - - MemoryArea = MmOpenMemoryAreaByAddress(PsGetCurrentProcess(), - VirtualAddress); - - if (MemoryArea == NULL) - { - return(FALSE); - } - return(TRUE); -} - -NTSTATUS -STDCALL -NtAllocateVirtualMemory( - IN HANDLE ProcessHandle, - IN OUT PVOID *BaseAddress, - IN ULONG ZeroBits, - IN OUT PULONG RegionSize, - IN ULONG AllocationType, - IN ULONG Protect - ) -{ - return(ZwAllocateVirtualMemory(ProcessHandle, - BaseAddress, - ZeroBits, - RegionSize, - AllocationType, - Protect)); -} - -NTSTATUS -STDCALL -ZwAllocateVirtualMemory( - IN HANDLE ProcessHandle, - IN OUT PVOID *BaseAddress, - IN ULONG ZeroBits, - IN OUT PULONG RegionSize, - IN ULONG AllocationType, - IN ULONG Protect - ) -/* - * FUNCTION: Allocates a block of virtual memory in the process address space - * ARGUMENTS: - * ProcessHandle = The handle of the process which owns the virtual memory - * BaseAddress = A pointer to the virtual memory allocated. If you - * supply a non zero value the system will try to - * allocate the memory at the address supplied. It round - * it down to a multiple of the page size. - * ZeroBits = (OPTIONAL) You can specify the number of high order bits - * that must be zero, ensuring that the memory will be - * allocated at a address below a certain value. - * RegionSize = The number of bytes to allocate - * AllocationType = Indicates the type of virtual memory you like to - * allocated, can be one of the values : MEM_COMMIT, - * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN - * Protect = Indicates the protection type of the pages allocated, can be - * a combination of PAGE_READONLY, PAGE_READWRITE, - * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD, - * PAGE_NOACCESS - * REMARKS: - * This function maps to the win32 VirtualAllocEx. Virtual memory is - * process based so the protocol starts with a ProcessHandle. I - * splitted the functionality of obtaining the actual address and - * specifying the start address in two parameters ( BaseAddress and - * StartAddress ) The NumberOfBytesAllocated specify the range and the - * AllocationType and ProctectionType map to the other two parameters. - * RETURNS: Status - */ -{ - PEPROCESS Process; - MEMORY_AREA* MemoryArea; - ULONG Type; - NTSTATUS Status; - - DPRINT("ZwAllocateVirtualMemory(ProcessHandle %x, *BaseAddress %x, " - "ZeroBits %d, RegionSize %d, AllocationType %x, Protect %x)\n", - ProcessHandle,*BaseAddress,ZeroBits,*RegionSize,AllocationType, - Protect); - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_OPERATION, - NULL, - UserMode, - (PVOID*)(&Process), - NULL); - if (Status != STATUS_SUCCESS) - { - DPRINT("ZwAllocateVirtualMemory() = %x\n",Status); - return(Status); - } - - if (AllocationType & MEM_RESERVE) - { - Type = MEMORY_AREA_RESERVE; - } - else - { - Type = MEMORY_AREA_COMMIT; - } - - if ((*BaseAddress) != 0) - { - MemoryArea = MmOpenMemoryAreaByAddress(Process, *BaseAddress); - - if (MemoryArea != NULL) - { - if (MemoryArea->BaseAddress == (*BaseAddress) && - MemoryArea->Length == *RegionSize) - { - MemoryArea->Type = Type; - MemoryArea->Attributes =Protect; - DPRINT("*BaseAddress %x\n",*BaseAddress); - return(STATUS_SUCCESS); - } - - MemoryArea = MmSplitMemoryArea(Process, - MemoryArea, - *BaseAddress, - *RegionSize, - Type, - Protect); - DPRINT("*BaseAddress %x\n",*BaseAddress); - return(STATUS_SUCCESS); - } - } - - //FIXME RegionSize should be passed as pointer - - - Status = MmCreateMemoryArea(UserMode, - Process, - Type, - BaseAddress, - *RegionSize, - Protect, - &MemoryArea); - - if (Status != STATUS_SUCCESS) - { - DPRINT("ZwAllocateVirtualMemory() = %x\n",Status); - return(Status); - } - - DPRINT("*BaseAddress %x\n",*BaseAddress); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtFlushVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN ULONG NumberOfBytesToFlush, - OUT PULONG NumberOfBytesFlushed OPTIONAL) -{ - return(ZwFlushVirtualMemory(ProcessHandle, - BaseAddress, - NumberOfBytesToFlush, - NumberOfBytesFlushed)); -} - -NTSTATUS STDCALL ZwFlushVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN ULONG NumberOfBytesToFlush, - OUT PULONG NumberOfBytesFlushed OPTIONAL) - -/* - * FUNCTION: Flushes virtual memory to file - * ARGUMENTS: - * ProcessHandle = Points to the process that allocated the virtual - * memory - * BaseAddress = Points to the memory address - * NumberOfBytesToFlush = Limits the range to flush, - * NumberOfBytesFlushed = Actual number of bytes flushed - * RETURNS: Status - */ -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID *BaseAddress, - IN PULONG RegionSize, - IN ULONG FreeType) -{ - return(ZwFreeVirtualMemory(ProcessHandle, - BaseAddress, - RegionSize, - FreeType)); -} - -NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID *BaseAddress, - IN PULONG RegionSize, - IN ULONG FreeType) - -/* - * FUNCTION: Frees a range of virtual memory - * ARGUMENTS: - * ProcessHandle = Points to the process that allocated the virtual - * memory - * BaseAddress = Points to the memory address, rounded down to a - * multiple of the pagesize - * RegionSize = Limits the range to free, rounded up to a multiple of - * the paging size - * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE - * RETURNS: Status - */ -{ - MEMORY_AREA* MemoryArea; - NTSTATUS Status; - PEPROCESS Process; - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_OPERATION, - PsProcessType, - UserMode, - (PVOID*)(&Process), - NULL); - if (Status != STATUS_SUCCESS) - { - DbgPrint("ZwFreeVirtualMemory() = %x\n",Status); - return(Status); - } - - MemoryArea = MmOpenMemoryAreaByAddress(Process,*BaseAddress); - if (MemoryArea == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - if (FreeType == MEM_RELEASE) - { - if (MemoryArea->BaseAddress != (*BaseAddress)) - { - return(STATUS_UNSUCCESSFUL); - } - MmFreeMemoryArea(PsGetCurrentProcess(), - BaseAddress, - 0, - TRUE); - return(STATUS_SUCCESS); - } - - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtLockVirtualMemory(HANDLE ProcessHandle, - PVOID BaseAddress, - ULONG NumberOfBytesToLock, - PULONG NumberOfBytesLocked) -{ - return(ZwLockVirtualMemory(ProcessHandle, - BaseAddress, - NumberOfBytesToLock, - NumberOfBytesLocked)); -} - -NTSTATUS STDCALL ZwLockVirtualMemory(HANDLE ProcessHandle, - PVOID BaseAddress, - ULONG NumberOfBytesToLock, - PULONG NumberOfBytesLocked) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtProtectVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN ULONG NumberOfBytesToProtect, - IN ULONG NewAccessProtection, - OUT PULONG OldAccessProtection) -{ - return(ZwProtectVirtualMemory(ProcessHandle, - BaseAddress, - NumberOfBytesToProtect, - NewAccessProtection, - OldAccessProtection)); -} - -VOID MmChangeAreaProtection(PEPROCESS Process, - PVOID BaseAddress, - ULONG Length, - ULONG Protect) -{ - ULONG i; - - for (i=0; i<(Length/PAGESIZE); i++) - { - if (MmIsPagePresent(Process, BaseAddress + (i*PAGESIZE))) - { - MmSetPageProtect(Process, BaseAddress + (i*PAGESIZE), Protect); - } - } -} - -NTSTATUS STDCALL ZwProtectVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN ULONG NumberOfBytesToProtect, - IN ULONG NewAccessProtection, - OUT PULONG OldAccessProtection) -{ - PMEMORY_AREA MemoryArea; - PEPROCESS Process; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_OPERATION, - PsProcessType, - UserMode, - (PVOID*)(&Process), - NULL); - if (Status != STATUS_SUCCESS) - { - DbgPrint("ZwProtectVirtualMemory() = %x\n",Status); - return(Status); - } - - MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); - if (MemoryArea == NULL) - { - DbgPrint("ZwProtectVirtualMemory() = %x\n",STATUS_UNSUCCESSFUL); - return(STATUS_UNSUCCESSFUL); - } - - *OldAccessProtection = MemoryArea->Attributes; - - if (MemoryArea->BaseAddress == BaseAddress && - MemoryArea->Length == NumberOfBytesToProtect) - { - MemoryArea->Attributes = NewAccessProtection; - } - else - { - MemoryArea = MmSplitMemoryArea(Process, - MemoryArea, - BaseAddress, - NumberOfBytesToProtect, - MemoryArea->Type, - NewAccessProtection); - } - MmChangeAreaProtection(Process,BaseAddress,NumberOfBytesToProtect, - NewAccessProtection); - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL NtQueryVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID Address, - IN IN CINT VirtualMemoryInformationClass, - OUT PVOID VirtualMemoryInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - return(ZwQueryVirtualMemory(ProcessHandle, - Address, - VirtualMemoryInformationClass, - VirtualMemoryInformation, - Length, - ResultLength)); -} - -NTSTATUS STDCALL ZwQueryVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID Address, - IN CINT VirtualMemoryInformationClass, - OUT PVOID VirtualMemoryInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtReadVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - OUT PVOID Buffer, - IN ULONG NumberOfBytesToRead, - OUT PULONG NumberOfBytesRead) -{ - return(ZwReadVirtualMemory(ProcessHandle, - BaseAddress, - Buffer, - NumberOfBytesToRead, - NumberOfBytesRead)); -} - -NTSTATUS STDCALL ZwReadVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - OUT PVOID Buffer, - IN ULONG NumberOfBytesToRead, - OUT PULONG NumberOfBytesRead) -{ - PEPROCESS Process; - MEMORY_AREA* MemoryArea; - ULONG i; - NTSTATUS Status; - PULONG CurrentEntry; - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_READ, - NULL, - UserMode, - (PVOID*)(&Process), - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); - - if (MemoryArea == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - if (MemoryArea->Length > NumberOfBytesToRead) - { - NumberOfBytesToRead = MemoryArea->Length; - } - - *NumberOfBytesRead = NumberOfBytesToRead; - - for (i=0; i<(NumberOfBytesToRead/PAGESIZE); i++) - { - CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE)); - RtlCopyMemory(Buffer + (i*PAGESIZE), - (PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)), - PAGESIZE); - - } - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtUnlockVirtualMemory(HANDLE ProcessHandle, - PVOID BaseAddress, - ULONG NumberOfBytesToUnlock, - PULONG NumberOfBytesUnlocked OPTIONAL) -{ - return(ZwUnlockVirtualMemory(ProcessHandle, - BaseAddress, - NumberOfBytesToUnlock, - NumberOfBytesUnlocked)); -} - -NTSTATUS STDCALL ZwUnlockVirtualMemory(HANDLE ProcessHandle, - PVOID BaseAddress, - ULONG NumberOfBytesToUnlock, - PULONG NumberOfBytesUnlocked OPTIONAL) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtWriteVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN PVOID Buffer, - IN ULONG NumberOfBytesToWrite, - OUT PULONG NumberOfBytesWritten) -{ - return(ZwWriteVirtualMemory(ProcessHandle, - BaseAddress, - Buffer, - NumberOfBytesToWrite, - NumberOfBytesWritten)); -} - -NTSTATUS STDCALL ZwWriteVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN PVOID Buffer, - IN ULONG NumberOfBytesToWrite, - OUT PULONG NumberOfBytesWritten) -{ - PEPROCESS Process; - MEMORY_AREA* MemoryArea; - ULONG i; - NTSTATUS Status; - PULONG CurrentEntry; - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_WRITE, - NULL, - UserMode, - (PVOID*)(&Process), - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); - - if (MemoryArea == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - if (MemoryArea->Length > NumberOfBytesToWrite) - { - NumberOfBytesToWrite = MemoryArea->Length; - } - - *NumberOfBytesWritten = NumberOfBytesToWrite; - - for (i=0; i<(NumberOfBytesToWrite/PAGESIZE); i++) - { - CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE)); - RtlCopyMemory((PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)), - Buffer + (i*PAGESIZE), - PAGESIZE); - - } - return(STATUS_SUCCESS); -} - +/* + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/virtual.c + * PURPOSE: implementing the Virtualxxx section of the win32 api + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 09/4/98: Created + * 10/6/98: Corrections from Fatahi (i_fatahi@hotmail.com) + * 30/9/98: Implemented ZwxxxVirtualMemory functions + */ + +/* INCLUDE *****************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +extern unsigned int etext; +extern unsigned int end; + +static MEMORY_AREA* kernel_text_desc = NULL; +static MEMORY_AREA* kernel_data_desc = NULL; +static MEMORY_AREA* kernel_param_desc = NULL; +static MEMORY_AREA* kernel_pool_desc = NULL; + +/* FUNCTIONS ****************************************************************/ + +void VirtualInit(boot_param* bp) +/* + * FUNCTION: Intialize the memory areas list + * ARGUMENTS: + * bp = Pointer to the boot parameters + * kernel_len = Length of the kernel + */ +{ + unsigned int kernel_len = bp->end_mem - bp->start_mem; + PVOID BaseAddress; + ULONG Length; + ULONG ParamLength = kernel_len; + + DPRINT("VirtualInit() %x\n",bp); + + MmInitMemoryAreas(); + ExInitNonPagedPool(KERNEL_BASE+ PAGE_ROUND_UP(kernel_len) + PAGESIZE); + + + /* + * Setup the system area descriptor list + */ + BaseAddress = (PVOID)KERNEL_BASE; + Length = PAGE_ROUND_UP(((ULONG)&etext)) - KERNEL_BASE; + ParamLength = ParamLength - Length; + MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, + Length,0,&kernel_text_desc); + + Length = PAGE_ROUND_UP(((ULONG)&end)) - PAGE_ROUND_UP(((ULONG)&etext)); + ParamLength = ParamLength - Length; + DPRINT("Length %x\n",Length); + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&etext)); + MmCreateMemoryArea(KernelMode, + NULL, + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_data_desc); + + + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&end)); + Length = ParamLength; + MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, + Length,0,&kernel_param_desc); + + BaseAddress = (PVOID)(KERNEL_BASE + PAGE_ROUND_UP(kernel_len) + PAGESIZE); + Length = NONPAGED_POOL_SIZE; + MmCreateMemoryArea(KernelMode,NULL,MEMORY_AREA_SYSTEM,&BaseAddress, + Length,0,&kernel_pool_desc); + +// MmDumpMemoryAreas(); + CHECKPOINT; + + MmInitSectionImplementation(); +} + +ULONG MmCommitedSectionHandleFault(MEMORY_AREA* MemoryArea, ULONG Address) +{ + set_page(Address,0x7,get_free_page()); + return(TRUE); +} + +NTSTATUS MmSectionHandleFault(MEMORY_AREA* MemoryArea, PVOID Address) +{ + LARGE_INTEGER Offset; + IO_STATUS_BLOCK IoStatus; + + DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n", + MemoryArea,Address); + + set_page((DWORD)Address,0x7,get_free_page()); + + LARGE_INTEGER_QUAD_PART(Offset) = (Address - MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + + DPRINT("MemoryArea->Data.SectionData.Section->FileObject %x\n", + MemoryArea->Data.SectionData.Section->FileObject); + + if (MemoryArea->Data.SectionData.Section->FileObject == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + IoPageRead(MemoryArea->Data.SectionData.Section->FileObject, + (PVOID)Address, + &Offset, + &IoStatus); + + DPRINT("Returning from MmSectionHandleFault()\n"); + + return(STATUS_SUCCESS); +} + +asmlinkage int page_fault_handler(unsigned int cs, + unsigned int eip) +/* + * FUNCTION: Handle a page fault + */ +{ + KPROCESSOR_MODE FaultMode; + MEMORY_AREA* MemoryArea; + KIRQL oldlvl; + ULONG stat; + + /* + * Get the address for the page fault + */ + unsigned int cr2; + __asm__("movl %%cr2,%0\n\t" : "=d" (cr2)); + DPRINT("Page fault at address %x with eip %x\n",cr2,eip); + + cr2 = PAGE_ROUND_DOWN(cr2); + + if (KeGetCurrentIrql()!=PASSIVE_LEVEL) + { + DbgPrint("Recursive page fault detected\n"); + return(0); +// KeBugCheck(0); + } + + KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); + + /* + * Find the memory area for the faulting address + */ + if (cr2>=KERNEL_BASE) + { + /* + * Check permissions + */ + if (cs!=KERNEL_CS) + { + printk("%s:%d\n",__FILE__,__LINE__); + return(0); + } + FaultMode = UserMode; + } + else + { + FaultMode = KernelMode; + } + + MemoryArea = MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),(PVOID)cr2); + if (MemoryArea==NULL) + { + printk("%s:%d\n",__FILE__,__LINE__); + return(0); + } + + switch (MemoryArea->Type) + { + case MEMORY_AREA_SYSTEM: + stat = 0; + break; + + case MEMORY_AREA_SECTION_VIEW_COMMIT: + if (MmSectionHandleFault(MemoryArea, (PVOID)cr2)==STATUS_SUCCESS) + { + stat=1; + } + else + { + stat = 0; + } + break; + + case MEMORY_AREA_COMMIT: + stat = MmCommitedSectionHandleFault(MemoryArea,cr2); + break; + + default: + stat = 0; + break; + } + if (stat) + { + KeLowerIrql(oldlvl); + } + return(stat); +} + +BOOLEAN MmIsNonPagedSystemAddressValid(PVOID VirtualAddress) +{ + UNIMPLEMENTED; +} + +BOOLEAN MmIsAddressValid(PVOID VirtualAddress) +/* + * FUNCTION: Checks whether the given address is valid for a read or write + * ARGUMENTS: + * VirtualAddress = address to check + * RETURNS: True if the access would be valid + * False if the access would cause a page fault + * NOTES: This function checks whether a byte access to the page would + * succeed. Is this realistic for RISC processors which don't + * allow byte granular access? + */ +{ + MEMORY_AREA* MemoryArea; + + MemoryArea = MmOpenMemoryAreaByAddress(PsGetCurrentProcess(), + VirtualAddress); + + if (MemoryArea == NULL) + { + return(FALSE); + } + return(TRUE); +} + +NTSTATUS +STDCALL +NtAllocateVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN OUT PULONG RegionSize, + IN ULONG AllocationType, + IN ULONG Protect + ) +{ + return(ZwAllocateVirtualMemory(ProcessHandle, + BaseAddress, + ZeroBits, + RegionSize, + AllocationType, + Protect)); +} + +NTSTATUS +STDCALL +ZwAllocateVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN OUT PULONG RegionSize, + IN ULONG AllocationType, + IN ULONG Protect + ) +/* + * FUNCTION: Allocates a block of virtual memory in the process address space + * ARGUMENTS: + * ProcessHandle = The handle of the process which owns the virtual memory + * BaseAddress = A pointer to the virtual memory allocated. If you + * supply a non zero value the system will try to + * allocate the memory at the address supplied. It round + * it down to a multiple of the page size. + * ZeroBits = (OPTIONAL) You can specify the number of high order bits + * that must be zero, ensuring that the memory will be + * allocated at a address below a certain value. + * RegionSize = The number of bytes to allocate + * AllocationType = Indicates the type of virtual memory you like to + * allocated, can be one of the values : MEM_COMMIT, + * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN + * Protect = Indicates the protection type of the pages allocated, can be + * a combination of PAGE_READONLY, PAGE_READWRITE, + * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD, + * PAGE_NOACCESS + * REMARKS: + * This function maps to the win32 VirtualAllocEx. Virtual memory is + * process based so the protocol starts with a ProcessHandle. I + * splitted the functionality of obtaining the actual address and + * specifying the start address in two parameters ( BaseAddress and + * StartAddress ) The NumberOfBytesAllocated specify the range and the + * AllocationType and ProctectionType map to the other two parameters. + * RETURNS: Status + */ +{ + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG Type; + NTSTATUS Status; + + DPRINT("ZwAllocateVirtualMemory(ProcessHandle %x, *BaseAddress %x, " + "ZeroBits %d, RegionSize %d, AllocationType %x, Protect %x)\n", + ProcessHandle,*BaseAddress,ZeroBits,*RegionSize,AllocationType, + Protect); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT("ZwAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + + if (AllocationType & MEM_RESERVE) + { + Type = MEMORY_AREA_RESERVE; + } + else + { + Type = MEMORY_AREA_COMMIT; + } + + if ((*BaseAddress) != 0) + { + MemoryArea = MmOpenMemoryAreaByAddress(Process, *BaseAddress); + + if (MemoryArea != NULL) + { + if (MemoryArea->BaseAddress == (*BaseAddress) && + MemoryArea->Length == *RegionSize) + { + MemoryArea->Type = Type; + MemoryArea->Attributes =Protect; + DPRINT("*BaseAddress %x\n",*BaseAddress); + return(STATUS_SUCCESS); + } + + MemoryArea = MmSplitMemoryArea(Process, + MemoryArea, + *BaseAddress, + *RegionSize, + Type, + Protect); + DPRINT("*BaseAddress %x\n",*BaseAddress); + return(STATUS_SUCCESS); + } + } + + //FIXME RegionSize should be passed as pointer + + + Status = MmCreateMemoryArea(UserMode, + Process, + Type, + BaseAddress, + *RegionSize, + Protect, + &MemoryArea); + + if (Status != STATUS_SUCCESS) + { + DPRINT("ZwAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + + DPRINT("*BaseAddress %x\n",*BaseAddress); + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL NtFlushVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToFlush, + OUT PULONG NumberOfBytesFlushed OPTIONAL) +{ + return(ZwFlushVirtualMemory(ProcessHandle, + BaseAddress, + NumberOfBytesToFlush, + NumberOfBytesFlushed)); +} + +NTSTATUS STDCALL ZwFlushVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToFlush, + OUT PULONG NumberOfBytesFlushed OPTIONAL) + +/* + * FUNCTION: Flushes virtual memory to file + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual + * memory + * BaseAddress = Points to the memory address + * NumberOfBytesToFlush = Limits the range to flush, + * NumberOfBytesFlushed = Actual number of bytes flushed + * RETURNS: Status + */ +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN PULONG RegionSize, + IN ULONG FreeType) +{ + return(ZwFreeVirtualMemory(ProcessHandle, + BaseAddress, + RegionSize, + FreeType)); +} + +NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN PULONG RegionSize, + IN ULONG FreeType) + +/* + * FUNCTION: Frees a range of virtual memory + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual + * memory + * BaseAddress = Points to the memory address, rounded down to a + * multiple of the pagesize + * RegionSize = Limits the range to free, rounded up to a multiple of + * the paging size + * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE + * RETURNS: Status + */ +{ + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + PEPROCESS Process; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + DbgPrint("ZwFreeVirtualMemory() = %x\n",Status); + return(Status); + } + + MemoryArea = MmOpenMemoryAreaByAddress(Process,*BaseAddress); + if (MemoryArea == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + if (FreeType == MEM_RELEASE) + { + if (MemoryArea->BaseAddress != (*BaseAddress)) + { + return(STATUS_UNSUCCESSFUL); + } + MmFreeMemoryArea(PsGetCurrentProcess(), + BaseAddress, + 0, + TRUE); + return(STATUS_SUCCESS); + } + + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtLockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToLock, + PULONG NumberOfBytesLocked) +{ + return(ZwLockVirtualMemory(ProcessHandle, + BaseAddress, + NumberOfBytesToLock, + NumberOfBytesLocked)); +} + +NTSTATUS STDCALL ZwLockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToLock, + PULONG NumberOfBytesLocked) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtProtectVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection) +{ + return(ZwProtectVirtualMemory(ProcessHandle, + BaseAddress, + NumberOfBytesToProtect, + NewAccessProtection, + OldAccessProtection)); +} + +VOID MmChangeAreaProtection(PEPROCESS Process, + PVOID BaseAddress, + ULONG Length, + ULONG Protect) +{ + ULONG i; + + for (i=0; i<(Length/PAGESIZE); i++) + { + if (MmIsPagePresent(Process, BaseAddress + (i*PAGESIZE))) + { + MmSetPageProtect(Process, BaseAddress + (i*PAGESIZE), Protect); + } + } +} + +NTSTATUS STDCALL ZwProtectVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection) +{ + PMEMORY_AREA MemoryArea; + PEPROCESS Process; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + DbgPrint("ZwProtectVirtualMemory() = %x\n",Status); + return(Status); + } + + MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); + if (MemoryArea == NULL) + { + DbgPrint("ZwProtectVirtualMemory() = %x\n",STATUS_UNSUCCESSFUL); + return(STATUS_UNSUCCESSFUL); + } + + *OldAccessProtection = MemoryArea->Attributes; + + if (MemoryArea->BaseAddress == BaseAddress && + MemoryArea->Length == NumberOfBytesToProtect) + { + MemoryArea->Attributes = NewAccessProtection; + } + else + { + MemoryArea = MmSplitMemoryArea(Process, + MemoryArea, + BaseAddress, + NumberOfBytesToProtect, + MemoryArea->Type, + NewAccessProtection); + } + MmChangeAreaProtection(Process,BaseAddress,NumberOfBytesToProtect, + NewAccessProtection); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL NtQueryVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID Address, + IN IN CINT VirtualMemoryInformationClass, + OUT PVOID VirtualMemoryInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + return(ZwQueryVirtualMemory(ProcessHandle, + Address, + VirtualMemoryInformationClass, + VirtualMemoryInformation, + Length, + ResultLength)); +} + +NTSTATUS STDCALL ZwQueryVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID Address, + IN CINT VirtualMemoryInformationClass, + OUT PVOID VirtualMemoryInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtReadVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + OUT PVOID Buffer, + IN ULONG NumberOfBytesToRead, + OUT PULONG NumberOfBytesRead) +{ + return(ZwReadVirtualMemory(ProcessHandle, + BaseAddress, + Buffer, + NumberOfBytesToRead, + NumberOfBytesRead)); +} + +NTSTATUS STDCALL ZwReadVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + OUT PVOID Buffer, + IN ULONG NumberOfBytesToRead, + OUT PULONG NumberOfBytesRead) +{ + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG i; + NTSTATUS Status; + PULONG CurrentEntry; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_READ, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); + + if (MemoryArea == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + if (MemoryArea->Length > NumberOfBytesToRead) + { + NumberOfBytesToRead = MemoryArea->Length; + } + + *NumberOfBytesRead = NumberOfBytesToRead; + + for (i=0; i<(NumberOfBytesToRead/PAGESIZE); i++) + { + CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE)); + RtlCopyMemory(Buffer + (i*PAGESIZE), + (PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)), + PAGESIZE); + + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL NtUnlockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToUnlock, + PULONG NumberOfBytesUnlocked OPTIONAL) +{ + return(ZwUnlockVirtualMemory(ProcessHandle, + BaseAddress, + NumberOfBytesToUnlock, + NumberOfBytesUnlocked)); +} + +NTSTATUS STDCALL ZwUnlockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToUnlock, + PULONG NumberOfBytesUnlocked OPTIONAL) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtWriteVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, + OUT PULONG NumberOfBytesWritten) +{ + return(ZwWriteVirtualMemory(ProcessHandle, + BaseAddress, + Buffer, + NumberOfBytesToWrite, + NumberOfBytesWritten)); +} + +NTSTATUS STDCALL ZwWriteVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, + OUT PULONG NumberOfBytesWritten) +{ + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG i; + NTSTATUS Status; + PULONG CurrentEntry; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_WRITE, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + MemoryArea = MmOpenMemoryAreaByAddress(Process,BaseAddress); + + if (MemoryArea == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + if (MemoryArea->Length > NumberOfBytesToWrite) + { + NumberOfBytesToWrite = MemoryArea->Length; + } + + *NumberOfBytesWritten = NumberOfBytesToWrite; + + for (i=0; i<(NumberOfBytesToWrite/PAGESIZE); i++) + { + CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE)); + RtlCopyMemory((PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)), + Buffer + (i*PAGESIZE), + PAGESIZE); + + } + return(STATUS_SUCCESS); +} + diff --git a/reactos/ntoskrnl/ob/namespc.c b/reactos/ntoskrnl/ob/namespc.c index 61d2eeea1ee..c74c8391820 100644 --- a/reactos/ntoskrnl/ob/namespc.c +++ b/reactos/ntoskrnl/ob/namespc.c @@ -1,553 +1,554 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ob/namespc.c - * PURPOSE: Manages the system namespace - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 22/05/98: Created - */ - -/* INCLUDES ***************************************************************/ - -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -/* GLOBALS ****************************************************************/ - -POBJECT_TYPE ObDirectoryType = NULL; - -static struct -{ - OBJECT_HEADER hdr; -// DIRECTORY_OBJECT directory; - LIST_ENTRY head; - KSPIN_LOCK Lock; -} namespc_root = {{0,},}; - -/* FUNCTIONS **************************************************************/ - -NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - return(ZwOpenDirectoryObject(DirectoryHandle, - DesiredAccess, - ObjectAttributes)); -} - -NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) -/* - * FUNCTION: Opens a namespace directory object - * ARGUMENTS: - * DirectoryHandle (OUT) = Variable which receives the directory handle - * DesiredAccess = Desired access to the directory - * ObjectAttributes = Structure describing the directory - * RETURNS: Status - * NOTES: Undocumented - */ -{ - PVOID Object; - NTSTATUS Status; - PWSTR Ignored; - - *DirectoryHandle = 0; - - Status = ObOpenObjectByName(ObjectAttributes,&Object,&Ignored); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - if (BODY_TO_HEADER(Object)->Type!=OBJTYP_DIRECTORY) - { - return(STATUS_UNSUCCESSFUL); - } - - *DirectoryHandle = ObInsertHandle(KeGetCurrentProcess(),Object, - DesiredAccess,FALSE); - CHECKPOINT; - return(STATUS_SUCCESS); -} - -NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle, - OUT POBJDIR_INFORMATION DirObjInformation, - IN ULONG BufferLength, - IN BOOLEAN GetNextIndex, - IN BOOLEAN IgnoreInputIndex, - IN OUT PULONG ObjectIndex, - OUT PULONG DataWritten OPTIONAL) -{ - return(ZwQueryDirectoryObject(DirObjHandle, - DirObjInformation, - BufferLength, - GetNextIndex, - IgnoreInputIndex, - ObjectIndex, - DataWritten)); -} - -NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle, - OUT POBJDIR_INFORMATION DirObjInformation, - IN ULONG BufferLength, - IN BOOLEAN GetNextIndex, - IN BOOLEAN IgnoreInputIndex, - IN OUT PULONG ObjectIndex, - OUT PULONG DataWritten OPTIONAL) -/* - * FUNCTION: Reads information from a namespace directory - * ARGUMENTS: - * DirObjInformation (OUT) = Buffer to hold the data read - * BufferLength = Size of the buffer in bytes - * GetNextIndex = If TRUE then set ObjectIndex to the index of the - * next object - * If FALSE then set ObjectIndex to the number of - * objects in the directory - * IgnoreInputIndex = If TRUE start reading at index 0 - * If FALSE start reading at the index specified - * by object index - * ObjectIndex = Zero based index into the directory, interpretation - * depends on IgnoreInputIndex and GetNextIndex - * DataWritten (OUT) = Caller supplied storage for the number of bytes - * written (or NULL) - * RETURNS: Status - */ -{ - PDIRECTORY_OBJECT dir = NULL; - ULONG EntriesToRead; - PLIST_ENTRY current_entry; - POBJECT_HEADER current; - ULONG i=0; - ULONG EntriesToSkip; - NTSTATUS Status; - - DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle); - DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr))); - -// assert_irql(PASSIVE_LEVEL); - - Status = ObReferenceObjectByHandle(DirObjHandle, - DIRECTORY_QUERY, - ObDirectoryType, - UserMode, - (PVOID*)&dir, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION); - *DataWritten = 0; - - DPRINT("EntriesToRead %d\n",EntriesToRead); - - current_entry = dir->head.Flink; - - /* - * Optionally, skip over some entries at the start of the directory - */ - if (!IgnoreInputIndex) - { - CHECKPOINT; - - EntriesToSkip = *ObjectIndex; - while ( iFlink; - } - } - - DPRINT("DirObjInformation %x\n",DirObjInformation); - - /* - * Read the maximum entries possible into the buffer - */ - while ( ihead))) - { - current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry); - DPRINT("Scanning %w\n",current->Name.Buffer); - DirObjInformation[i].ObjectName.Buffer = - ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2); - DirObjInformation[i].ObjectName.Length = current->Name.Length; - DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length; - DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n", - DirObjInformation[i].ObjectName.Buffer); - RtlCopyUnicodeString(&DirObjInformation[i].ObjectName, - &(current->Name)); - i++; - current_entry = current_entry->Flink; - (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION); - CHECKPOINT; - } - CHECKPOINT; - - /* - * Optionally, count the number of entries in the directory - */ - if (GetNextIndex) - { - *ObjectIndex=i; - } - else - { - while ( current_entry!=(&(dir->head)) ) - { - current_entry=current_entry->Flink; - i++; - } - *ObjectIndex=i; - } - return(STATUS_SUCCESS); -} - - -NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectPath, - ULONG Attributes, - PACCESS_STATE PassedAccessState, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE ObjectType, - KPROCESSOR_MODE AccessMode, - PVOID ParseContext, - PVOID* ObjectPtr) -{ - UNIMPLEMENTED; -} - -NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes, - PVOID* Object, PWSTR* UnparsedSection) -{ - NTSTATUS Status; - - DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n", - ObjectAttributes,Object); - DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n", - ObjectAttributes->ObjectName,ObjectAttributes->ObjectName->Buffer); - DPRINT("ObjectAttributes->ObjectName->Length %d\n", - ObjectAttributes->ObjectName->Length); - - *Object = NULL; - Status = ObLookupObject(ObjectAttributes->RootDirectory, - ObjectAttributes->ObjectName->Buffer, - Object, - UnparsedSection, - ObjectAttributes->Attributes); - DPRINT("*Object %x\n",*Object); - DPRINT("ObjectAttributes->ObjectName->Length %d\n", - ObjectAttributes->ObjectName->Length); - return(Status); -} - -void ObInit(void) -/* - * FUNCTION: Initialize the object manager namespace - */ -{ - ANSI_STRING AnsiString; - - ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - ObDirectoryType->TotalObjects = 0; - ObDirectoryType->TotalHandles = 0; - ObDirectoryType->MaxObjects = ULONG_MAX; - ObDirectoryType->MaxHandles = ULONG_MAX; - ObDirectoryType->PagedPoolCharge = 0; - ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT); - ObDirectoryType->Dump = NULL; - ObDirectoryType->Open = NULL; - ObDirectoryType->Close = NULL; - ObDirectoryType->Delete = NULL; - ObDirectoryType->Parse = NULL; - ObDirectoryType->Security = NULL; - ObDirectoryType->QueryName = NULL; - ObDirectoryType->OkayToClose = NULL; - - RtlInitAnsiString(&AnsiString,"Directory"); - RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName, - &AnsiString,TRUE); - - ObInitializeObjectHeader(ObDirectoryType,NULL,&namespc_root.hdr); - InitializeListHead(&namespc_root.head); -} - -NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - return(ZwCreateDirectoryObject(DirectoryHandle, - DesiredAccess, - ObjectAttributes)); -} - -NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) -/* - * FUNCTION: Creates or opens a directory object (a container for other - * objects) - * ARGUMENTS: - * DirectoryHandle (OUT) = Caller supplied storage for the handle - * of the directory - * DesiredAccess = Access desired to the directory - * ObjectAttributes = Object attributes initialized with - * InitializeObjectAttributes - * RETURNS: Status - */ -{ - PDIRECTORY_OBJECT dir; - - dir = ObGenericCreateObject(DirectoryHandle,DesiredAccess,ObjectAttributes, - ObDirectoryType); - - /* - * Initialize the object body - */ - InitializeListHead(&dir->head); - KeInitializeSpinLock(&(dir->Lock)); - - return(STATUS_SUCCESS); -} - -VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, - PUNICODE_STRING ObjectName, - ULONG Attributes, - HANDLE RootDirectory, - PSECURITY_DESCRIPTOR SecurityDescriptor) -/* - * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a - * subsequent call to ZwCreateXXX or ZwOpenXXX - * ARGUMENTS: - * InitializedAttributes (OUT) = Caller supplied storage for the - * object attributes - * ObjectName = Full path name for object - * Attributes = Attributes for the object - * RootDirectory = Where the object should be placed or NULL - * SecurityDescriptor = Ignored - * - * NOTE: - * Either ObjectName is a fully qualified pathname or a path relative - * to RootDirectory - */ -{ - DPRINT("InitializeObjectAttributes(InitializedAttributes %x " - "ObjectName %x Attributes %x RootDirectory %x)\n", - InitializedAttributes,ObjectName,Attributes,RootDirectory); - InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES); - InitializedAttributes->RootDirectory=RootDirectory; - InitializedAttributes->ObjectName=ObjectName; - InitializedAttributes->Attributes=Attributes; - InitializedAttributes->SecurityDescriptor=SecurityDescriptor; - InitializedAttributes->SecurityQualityOfService=NULL; -} - -static PVOID ObDirLookup(PDIRECTORY_OBJECT dir, PWSTR name, - ULONG Attributes) -/* - * FUNCTION: Looks up an entry within a namespace directory - * ARGUMENTS: - * dir = Directory to lookup in - * name = Entry name to find - * RETURNS: A pointer to the object body if found - * NULL otherwise - */ -{ - LIST_ENTRY* current = dir->head.Flink; - POBJECT_HEADER current_obj; - - DPRINT("ObDirLookup(dir %x, name %w)\n",dir,name); - - if (name[0]==0) - { - return(dir); - } - if (name[0]=='.'&&name[1]==0) - { - return(dir); - } - if (name[0]=='.'&&name[1]=='.'&&name[2]==0) - { - return(BODY_TO_HEADER(dir)->Parent); - } - while (current!=(&(dir->head))) - { - current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry); - DPRINT("Scanning %w\n",current_obj->Name.Buffer); - if (Attributes & OBJ_CASE_INSENSITIVE) - { - if (wcsicmp(current_obj->Name.Buffer, name)==0) - { - DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); - return(HEADER_TO_BODY(current_obj)); - } - } - else - { - if ( wcscmp(current_obj->Name.Buffer, name)==0) - { - DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); - return(HEADER_TO_BODY(current_obj)); - } - } - current = current->Flink; - } - DPRINT("%s() = NULL\n",__FUNCTION__); - return(NULL); -} - -VOID ObRemoveEntry(POBJECT_HEADER Header) -{ - KIRQL oldlvl; - - DPRINT("ObRemoveEntry(Header %x)\n",Header); - - KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl); - RemoveEntryList(&(Header->Entry)); - KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl); -} - -VOID ObCreateEntry(PDIRECTORY_OBJECT parent,POBJECT_HEADER Object) -/* - * FUNCTION: Add an entry to a namespace directory - * ARGUMENTS: - * parent = directory to add in - * name = Name to give the entry - * Object = Header of the object to add the entry for - */ -{ - DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent,Object,Object->Name.Buffer, - Object->Name.Buffer); - - /* - * Insert ourselves in our parents list - */ - InsertTailList(&parent->head,&Object->Entry); -} - -NTSTATUS ObLookupObject(HANDLE rootdir, PWSTR string, PVOID* Object, - PWSTR* UnparsedSection, ULONG Attributes) -/* - * FUNCTION: Lookup an object within the system namespc - * ARGUMENTS: - * root = Directory to start lookup from - * _string = Pathname to lookup - * RETURNS: On success a pointer to the object body - * On failure NULL - */ -{ - PWSTR current; - PWSTR next; - PDIRECTORY_OBJECT current_dir = NULL; - NTSTATUS Status; - - DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, " - "UnparsedSection %x)\n",rootdir,string,string,Object, - UnparsedSection); - - - *UnparsedSection = NULL; - *Object = NULL; - - if (rootdir==NULL) - { - current_dir = HEADER_TO_BODY(&(namespc_root.hdr)); - } - else - { - ObReferenceObjectByHandle(rootdir,DIRECTORY_TRAVERSE,NULL, - UserMode,(PVOID*)¤t_dir,NULL); - } - - /* - * Bit of a hack this - */ - if (string[0]==0) - { - *Object=current_dir; - return(STATUS_SUCCESS); - } - - if (string[0]!='\\') - { - DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__, - __LINE__,__FUNCTION__); - return(STATUS_UNSUCCESSFUL); - } - - next = &string[0]; - current = next+1; - - while (next!=NULL && - BODY_TO_HEADER(current_dir)->ObjectType==ObDirectoryType) - { - *next = '\\'; - current = next+1; - next = wcschr(next+1,'\\'); - if (next!=NULL) - { - *next=0; - } - - DPRINT("current %w current[5] %x next %x ",current,current[5],next); - if (next!=NULL) - { - DPRINT("(next+1) %w",next+1); - } - DPRINT("\n",0); - - current_dir=(PDIRECTORY_OBJECT)ObDirLookup(current_dir,current, - Attributes); - if (current_dir==NULL) - { - DbgPrint("(%s:%d) Path component %w not found\n",__FILE__, - __LINE__,current); - return(STATUS_UNSUCCESSFUL); - } - - if (BODY_TO_HEADER(current_dir)->ObjectType==IoSymbolicLinkType) - { - current_dir = IoOpenSymlink(current_dir); - } - - } - DPRINT("next %x\n",next); - DPRINT("current %x current %w\n",current,current); - if (next==NULL) - { - if (current_dir==NULL) - { - Status = STATUS_UNSUCCESSFUL; - } - else - { - Status = STATUS_SUCCESS; - } - } - else - { - CHECKPOINT; - *next = '\\'; - *UnparsedSection = next; - if (BODY_TO_HEADER(current_dir)->ObjectType == IoDeviceType) - { - Status = STATUS_FS_QUERY_REQUIRED; - } - else - { - Status = STATUS_UNSUCCESSFUL; - } - } - CHECKPOINT; - *Object = current_dir; - - return(Status); -} - +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/namespc.c + * PURPOSE: Manages the system namespace + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 22/05/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ****************************************************************/ + +POBJECT_TYPE ObDirectoryType = NULL; + +static struct +{ + OBJECT_HEADER hdr; +// DIRECTORY_OBJECT directory; + LIST_ENTRY head; + KSPIN_LOCK Lock; +} namespc_root = {{0,},}; + +/* FUNCTIONS **************************************************************/ + +NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return(ZwOpenDirectoryObject(DirectoryHandle, + DesiredAccess, + ObjectAttributes)); +} + +NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +/* + * FUNCTION: Opens a namespace directory object + * ARGUMENTS: + * DirectoryHandle (OUT) = Variable which receives the directory handle + * DesiredAccess = Desired access to the directory + * ObjectAttributes = Structure describing the directory + * RETURNS: Status + * NOTES: Undocumented + */ +{ + PVOID Object; + NTSTATUS Status; + PWSTR Ignored; + + *DirectoryHandle = 0; + + Status = ObOpenObjectByName(ObjectAttributes,&Object,&Ignored); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (BODY_TO_HEADER(Object)->Type!=OBJTYP_DIRECTORY) + { + return(STATUS_UNSUCCESSFUL); + } + + *DirectoryHandle = ObInsertHandle(KeGetCurrentProcess(),Object, + DesiredAccess,FALSE); + CHECKPOINT; + return(STATUS_SUCCESS); +} + +NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle, + OUT POBJDIR_INFORMATION DirObjInformation, + IN ULONG BufferLength, + IN BOOLEAN GetNextIndex, + IN BOOLEAN IgnoreInputIndex, + IN OUT PULONG ObjectIndex, + OUT PULONG DataWritten OPTIONAL) +{ + return(ZwQueryDirectoryObject(DirObjHandle, + DirObjInformation, + BufferLength, + GetNextIndex, + IgnoreInputIndex, + ObjectIndex, + DataWritten)); +} + +NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle, + OUT POBJDIR_INFORMATION DirObjInformation, + IN ULONG BufferLength, + IN BOOLEAN GetNextIndex, + IN BOOLEAN IgnoreInputIndex, + IN OUT PULONG ObjectIndex, + OUT PULONG DataWritten OPTIONAL) +/* + * FUNCTION: Reads information from a namespace directory + * ARGUMENTS: + * DirObjInformation (OUT) = Buffer to hold the data read + * BufferLength = Size of the buffer in bytes + * GetNextIndex = If TRUE then set ObjectIndex to the index of the + * next object + * If FALSE then set ObjectIndex to the number of + * objects in the directory + * IgnoreInputIndex = If TRUE start reading at index 0 + * If FALSE start reading at the index specified + * by object index + * ObjectIndex = Zero based index into the directory, interpretation + * depends on IgnoreInputIndex and GetNextIndex + * DataWritten (OUT) = Caller supplied storage for the number of bytes + * written (or NULL) + * RETURNS: Status + */ +{ + PDIRECTORY_OBJECT dir = NULL; + ULONG EntriesToRead; + PLIST_ENTRY current_entry; + POBJECT_HEADER current; + ULONG i=0; + ULONG EntriesToSkip; + NTSTATUS Status; + + DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle); + DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr))); + +// assert_irql(PASSIVE_LEVEL); + + Status = ObReferenceObjectByHandle(DirObjHandle, + DIRECTORY_QUERY, + ObDirectoryType, + UserMode, + (PVOID*)&dir, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION); + *DataWritten = 0; + + DPRINT("EntriesToRead %d\n",EntriesToRead); + + current_entry = dir->head.Flink; + + /* + * Optionally, skip over some entries at the start of the directory + */ + if (!IgnoreInputIndex) + { + CHECKPOINT; + + EntriesToSkip = *ObjectIndex; + while ( iFlink; + } + } + + DPRINT("DirObjInformation %x\n",DirObjInformation); + + /* + * Read the maximum entries possible into the buffer + */ + while ( ihead))) + { + current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry); + DPRINT("Scanning %w\n",current->Name.Buffer); + DirObjInformation[i].ObjectName.Buffer = + ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2); + DirObjInformation[i].ObjectName.Length = current->Name.Length; + DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length; + DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n", + DirObjInformation[i].ObjectName.Buffer); + RtlCopyUnicodeString(&DirObjInformation[i].ObjectName, + &(current->Name)); + i++; + current_entry = current_entry->Flink; + (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION); + CHECKPOINT; + } + CHECKPOINT; + + /* + * Optionally, count the number of entries in the directory + */ + if (GetNextIndex) + { + *ObjectIndex=i; + } + else + { + while ( current_entry!=(&(dir->head)) ) + { + current_entry=current_entry->Flink; + i++; + } + *ObjectIndex=i; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectPath, + ULONG Attributes, + PACCESS_STATE PassedAccessState, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID ParseContext, + PVOID* ObjectPtr) +{ + UNIMPLEMENTED; +} + +NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes, + PVOID* Object, PWSTR* UnparsedSection) +{ + NTSTATUS Status; + + DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n", + ObjectAttributes,Object); + DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n", + ObjectAttributes->ObjectName,ObjectAttributes->ObjectName->Buffer); + DPRINT("ObjectAttributes->ObjectName->Length %d\n", + ObjectAttributes->ObjectName->Length); + + *Object = NULL; + Status = ObLookupObject(ObjectAttributes->RootDirectory, + ObjectAttributes->ObjectName->Buffer, + Object, + UnparsedSection, + ObjectAttributes->Attributes); + DPRINT("*Object %x\n",*Object); + DPRINT("ObjectAttributes->ObjectName->Length %d\n", + ObjectAttributes->ObjectName->Length); + return(Status); +} + +void ObInit(void) +/* + * FUNCTION: Initialize the object manager namespace + */ +{ + ANSI_STRING AnsiString; + + ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + ObDirectoryType->TotalObjects = 0; + ObDirectoryType->TotalHandles = 0; + ObDirectoryType->MaxObjects = ULONG_MAX; + ObDirectoryType->MaxHandles = ULONG_MAX; + ObDirectoryType->PagedPoolCharge = 0; + ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT); + ObDirectoryType->Dump = NULL; + ObDirectoryType->Open = NULL; + ObDirectoryType->Close = NULL; + ObDirectoryType->Delete = NULL; + ObDirectoryType->Parse = NULL; + ObDirectoryType->Security = NULL; + ObDirectoryType->QueryName = NULL; + ObDirectoryType->OkayToClose = NULL; + + RtlInitAnsiString(&AnsiString,"Directory"); + RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName, + &AnsiString,TRUE); + + ObInitializeObjectHeader(ObDirectoryType,NULL,&namespc_root.hdr); + InitializeListHead(&namespc_root.head); +} + +NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return(ZwCreateDirectoryObject(DirectoryHandle, + DesiredAccess, + ObjectAttributes)); +} + +NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +/* + * FUNCTION: Creates or opens a directory object (a container for other + * objects) + * ARGUMENTS: + * DirectoryHandle (OUT) = Caller supplied storage for the handle + * of the directory + * DesiredAccess = Access desired to the directory + * ObjectAttributes = Object attributes initialized with + * InitializeObjectAttributes + * RETURNS: Status + */ +{ + PDIRECTORY_OBJECT dir; + + dir = ObGenericCreateObject(DirectoryHandle,DesiredAccess,ObjectAttributes, + ObDirectoryType); + + /* + * Initialize the object body + */ + InitializeListHead(&dir->head); + KeInitializeSpinLock(&(dir->Lock)); + + return(STATUS_SUCCESS); +} + +VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, + PUNICODE_STRING ObjectName, + ULONG Attributes, + HANDLE RootDirectory, + PSECURITY_DESCRIPTOR SecurityDescriptor) +/* + * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a + * subsequent call to ZwCreateXXX or ZwOpenXXX + * ARGUMENTS: + * InitializedAttributes (OUT) = Caller supplied storage for the + * object attributes + * ObjectName = Full path name for object + * Attributes = Attributes for the object + * RootDirectory = Where the object should be placed or NULL + * SecurityDescriptor = Ignored + * + * NOTE: + * Either ObjectName is a fully qualified pathname or a path relative + * to RootDirectory + */ +{ + DPRINT("InitializeObjectAttributes(InitializedAttributes %x " + "ObjectName %x Attributes %x RootDirectory %x)\n", + InitializedAttributes,ObjectName,Attributes,RootDirectory); + InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES); + InitializedAttributes->RootDirectory=RootDirectory; + InitializedAttributes->ObjectName=ObjectName; + InitializedAttributes->Attributes=Attributes; + InitializedAttributes->SecurityDescriptor=SecurityDescriptor; + InitializedAttributes->SecurityQualityOfService=NULL; +} + +static PVOID ObDirLookup(PDIRECTORY_OBJECT dir, PWSTR name, + ULONG Attributes) +/* + * FUNCTION: Looks up an entry within a namespace directory + * ARGUMENTS: + * dir = Directory to lookup in + * name = Entry name to find + * RETURNS: A pointer to the object body if found + * NULL otherwise + */ +{ + LIST_ENTRY* current = dir->head.Flink; + POBJECT_HEADER current_obj; + + DPRINT("ObDirLookup(dir %x, name %w)\n",dir,name); + + if (name[0]==0) + { + return(dir); + } + if (name[0]=='.'&&name[1]==0) + { + return(dir); + } + if (name[0]=='.'&&name[1]=='.'&&name[2]==0) + { + return(BODY_TO_HEADER(dir)->Parent); + } + while (current!=(&(dir->head))) + { + current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry); + DPRINT("Scanning %w\n",current_obj->Name.Buffer); + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if (wcsicmp(current_obj->Name.Buffer, name)==0) + { + DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); + return(HEADER_TO_BODY(current_obj)); + } + } + else + { + if ( wcscmp(current_obj->Name.Buffer, name)==0) + { + DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); + return(HEADER_TO_BODY(current_obj)); + } + } + current = current->Flink; + } + DPRINT("%s() = NULL\n",__FUNCTION__); + return(NULL); +} + +VOID ObRemoveEntry(POBJECT_HEADER Header) +{ + KIRQL oldlvl; + + DPRINT("ObRemoveEntry(Header %x)\n",Header); + + KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl); + RemoveEntryList(&(Header->Entry)); + KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl); +} + +VOID ObCreateEntry(PDIRECTORY_OBJECT parent,POBJECT_HEADER Object) +/* + * FUNCTION: Add an entry to a namespace directory + * ARGUMENTS: + * parent = directory to add in + * name = Name to give the entry + * Object = Header of the object to add the entry for + */ +{ + DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent,Object,Object->Name.Buffer, + Object->Name.Buffer); + + /* + * Insert ourselves in our parents list + */ + InsertTailList(&parent->head,&Object->Entry); +} + +NTSTATUS ObLookupObject(HANDLE rootdir, PWSTR string, PVOID* Object, + PWSTR* UnparsedSection, ULONG Attributes) +/* + * FUNCTION: Lookup an object within the system namespc + * ARGUMENTS: + * root = Directory to start lookup from + * _string = Pathname to lookup + * RETURNS: On success a pointer to the object body + * On failure NULL + */ +{ + PWSTR current; + PWSTR next; + PDIRECTORY_OBJECT current_dir = NULL; + NTSTATUS Status; + + DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, " + "UnparsedSection %x)\n",rootdir,string,string,Object, + UnparsedSection); + + + *UnparsedSection = NULL; + *Object = NULL; + + if (rootdir==NULL) + { + current_dir = HEADER_TO_BODY(&(namespc_root.hdr)); + } + else + { + ObReferenceObjectByHandle(rootdir,DIRECTORY_TRAVERSE,NULL, + UserMode,(PVOID*)¤t_dir,NULL); + } + + /* + * Bit of a hack this + */ + if (string[0]==0) + { + *Object=current_dir; + return(STATUS_SUCCESS); + } + + if (string[0]!='\\') + { + DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__, + __LINE__,__FUNCTION__); + return(STATUS_UNSUCCESSFUL); + } + + next = &string[0]; + current = next+1; + + while (next!=NULL && + BODY_TO_HEADER(current_dir)->ObjectType==ObDirectoryType) + { + *next = '\\'; + current = next+1; + next = wcschr(next+1,'\\'); + if (next!=NULL) + { + *next=0; + } + + DPRINT("current %w current[5] %x next %x ",current,current[5],next); + if (next!=NULL) + { + DPRINT("(next+1) %w",next+1); + } + DPRINT("\n",0); + + current_dir=(PDIRECTORY_OBJECT)ObDirLookup(current_dir,current, + Attributes); + if (current_dir==NULL) + { + DbgPrint("(%s:%d) Path component %w not found\n",__FILE__, + __LINE__,current); + return(STATUS_UNSUCCESSFUL); + } + + if (BODY_TO_HEADER(current_dir)->ObjectType==IoSymbolicLinkType) + { + current_dir = IoOpenSymlink(current_dir); + } + + } + DPRINT("next %x\n",next); + DPRINT("current %x current %w\n",current,current); + if (next==NULL) + { + if (current_dir==NULL) + { + Status = STATUS_UNSUCCESSFUL; + } + else + { + Status = STATUS_SUCCESS; + } + } + else + { + CHECKPOINT; + *next = '\\'; + *UnparsedSection = next; + if (BODY_TO_HEADER(current_dir)->ObjectType == IoDeviceType) + { + Status = STATUS_FS_QUERY_REQUIRED; + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + } + CHECKPOINT; + *Object = current_dir; + DPRINT("(%s:%d) current_dir %x\n",__FILE__,__LINE__,current_dir); + + return(Status); +} + diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index 39831d13fba..02f60cd505e 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -1,367 +1,379 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ob/object.c - * PURPOSE: Implements generic object managment functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 10/06/98: Created - */ - -/* INCLUDES *****************************************************************/ - -#include -#include -#include - -#define NDEBUG -#include - -/* FUNCTIONS ************************************************************/ - -NTSTATUS STDCALL NtSetInformationObject(IN HANDLE ObjectHandle, - IN CINT ObjectInformationClass, - IN PVOID ObjectInformation, - IN ULONG Length) -{ - return(ZwSetInformationObject(ObjectHandle, - ObjectInformationClass, - ObjectInformation, - Length)); -} - -NTSTATUS STDCALL ZwSetInformationObject(IN HANDLE ObjectHandle, - IN CINT ObjectInformationClass, - IN PVOID ObjectInformation, - IN ULONG Length) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtQueryObject(IN HANDLE ObjectHandle, - IN CINT ObjectInformationClass, - OUT PVOID ObjectInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - return(ZwQueryObject(ObjectHandle, - ObjectInformationClass, - ObjectInformation, - Length, - ResultLength)); -} - -NTSTATUS STDCALL ZwQueryObject(IN HANDLE ObjectHandle, - IN CINT ObjectInformationClass, - OUT PVOID ObjectInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - UNIMPLEMENTED -} - -NTSTATUS NtMakeTemporaryObject(HANDLE Handle) -{ - return(ZwMakeTemporaryObject(Handle)); -} - -NTSTATUS ZwMakeTemporaryObject(HANDLE Handle) -{ - PVOID Object; - NTSTATUS Status; - POBJECT_HEADER ObjectHeader; - - Status = ObReferenceObjectByHandle(Handle, - 0, - NULL, - KernelMode, - &Object, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - ObjectHeader = BODY_TO_HEADER(Object); - ObjectHeader->Permanent = FALSE; - - ObDereferenceObject(Object); - - return(STATUS_SUCCESS); -} - -PVOID ObGenericCreateObject(PHANDLE Handle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - POBJECT_TYPE Type) -{ - POBJECT_HEADER hdr = NULL; - UNICODE_STRING ObjectName; - PWSTR path; - PWSTR name; - PWSTR Ignored; - - DPRINT("ObGenericCreateObject(Handle %x, DesiredAccess %x," - "ObjectAttributes %x, Type %x)\n",Handle,DesiredAccess, - ObjectAttributes,Type); - - /* - * Allocate the object body and header - */ - hdr=(POBJECT_HEADER)ExAllocatePool(NonPagedPool,OBJECT_ALLOC_SIZE(Type)); - if (hdr==NULL) - { - return(NULL); - } - - /* - * If unnamed then initalize - */ - if (ObjectAttributes==NULL) - { - ObInitializeObjectHeader(Type,NULL,hdr); - if (Handle != NULL) - { - *Handle = ObInsertHandle(KeGetCurrentProcess(), - HEADER_TO_BODY(hdr), - DesiredAccess, - FALSE); - } - return(HEADER_TO_BODY(hdr)); - } - - /* - * Copy the object name into a buffer - */ - DPRINT("ObjectAttributes->ObjectName %x\n",ObjectAttributes->ObjectName); - DPRINT("ObjectAttributes->ObjectName->Length %d\n", - ObjectAttributes->ObjectName->Length); - ObjectName.MaximumLength = ObjectAttributes->ObjectName->Length; - ObjectName.Buffer = ExAllocatePool(NonPagedPool, - ((ObjectAttributes->ObjectName->Length+1)*2)); - if (ObjectName.Buffer==NULL) - { - return(NULL); - } - RtlCopyUnicodeString(&ObjectName,ObjectAttributes->ObjectName); - - /* - * Seperate the name into a path and name - */ - name = wcsrchr(ObjectName.Buffer,'\\'); - if (name==NULL) - { - name=ObjectName.Buffer; - path=NULL; - } - else - { - path=ObjectName.Buffer; - *name=0; - name=name+1; - } - - ObLookupObject(ObjectAttributes->RootDirectory,path, - &hdr->Parent,&Ignored, 0L); - - /* - * Initialize the object header - */ - ObInitializeObjectHeader(Type,name,hdr); - ObCreateEntry(hdr->Parent,hdr); - - DPRINT("Handle %x\n",Handle); - if (Handle != NULL) - { - *Handle = ObInsertHandle(KeGetCurrentProcess(), - HEADER_TO_BODY(hdr), - DesiredAccess, - FALSE); - } - - return(HEADER_TO_BODY(hdr)); -} - -VOID ObInitializeObjectHeader(POBJECT_TYPE Type, PWSTR name, - POBJECT_HEADER ObjectHeader) -/* - * FUNCTION: Creates a new object - * ARGUMENT: - * id = Identifier for the type of object - * obj = Pointer to the header of the object - */ -{ - PWSTR temp_name; - - DPRINT("ObInitializeObjectHeader(id %x name %w obj %x)\n",Type, - name,ObjectHeader); - - ObjectHeader->HandleCount = 0; - ObjectHeader->RefCount = 0; - ObjectHeader->ObjectType = Type; - ObjectHeader->Permanent = FALSE; - if (name==NULL) - { - ObjectHeader->Name.Length=0; - ObjectHeader->Name.Buffer=NULL; - } - else - { - ObjectHeader->Name.MaximumLength = wstrlen(name); - ObjectHeader->Name.Buffer = ExAllocatePool(NonPagedPool, - (ObjectHeader->Name.MaximumLength+1)*2); - RtlInitUnicodeString(&ObjectHeader->Name,name); - } -} - - -NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE ObjectType, - KPROCESSOR_MODE AccessMode) -/* - * FUNCTION: Increments the pointer reference count for a given object - * ARGUMENTS: - * ObjectBody = Object's body - * DesiredAccess = Desired access to the object - * ObjectType = Points to the object type structure - * AccessMode = Type of access check to perform - * RETURNS: Status - */ -{ - POBJECT_HEADER Object; - - DPRINT("ObReferenceObjectByPointer(%x)\n",ObjectBody); - - Object = BODY_TO_HEADER(ObjectBody); - Object->RefCount++; - return(STATUS_SUCCESS); -} - -NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header) -{ - if (Header->RefCount == 0 && Header->HandleCount == 0 && - !Header->Permanent) - { - ObRemoveEntry(Header); - ExFreePool(Header); - } - return(STATUS_SUCCESS); -} - -VOID ObDereferenceObject(PVOID ObjectBody) -/* - * FUNCTION: Decrements a given object's reference count and performs - * retention checks - * ARGUMENTS: - * ObjectBody = Body of the object - */ -{ - POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody); - Header->RefCount--; - ObPerformRetentionChecks(Header); -} - - -NTSTATUS NtClose(HANDLE Handle) -{ - return(ZwClose(Handle)); -} - -NTSTATUS ZwClose(HANDLE Handle) -/* - * FUNCTION: Closes a handle reference to an object - * ARGUMENTS: - * Handle = handle to close - * RETURNS: Status - */ -{ - PVOID ObjectBody; - POBJECT_HEADER Header; - PHANDLE_REP HandleRep; - - assert_irql(PASSIVE_LEVEL); - - HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle); - if (HandleRep == NULL) - { - return(STATUS_INVALID_HANDLE); - } - ObjectBody = HandleRep->ObjectBody; - - HandleRep->ObjectBody = NULL; - - Header = BODY_TO_HEADER(ObjectBody); - - Header->HandleCount--; - ObPerformRetentionChecks(Header); - - return(STATUS_SUCCESS); -} - -NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE ObjectType, - KPROCESSOR_MODE AccessMode, - PVOID* Object, - POBJECT_HANDLE_INFORMATION - HandleInformationPtr - ) -/* - * FUNCTION: Increments the reference count for an object and returns a - * pointer to its body - * ARGUMENTS: - * Handle = Handle for the object - * DesiredAccess = Desired access to the object - * ObjectType - * AccessMode - * Object (OUT) = Points to the object body on return - * HandleInformation (OUT) = Contains information about the handle - * on return - * RETURNS: Status - */ -{ - PHANDLE_REP HandleRep; - POBJECT_HEADER ObjectHeader; - - ASSERT_IRQL(PASSIVE_LEVEL); - - DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, " - "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess, - ObjectType,AccessMode,Object); - - if (Handle == NtCurrentProcess()) - { - *Object = PsGetCurrentProcess(); - return(STATUS_SUCCESS); - } - if (Handle == NtCurrentThread()) - { - *Object = PsGetCurrentThread(); - return(STATUS_SUCCESS); - } - - HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle); - if (HandleRep == NULL || HandleRep->ObjectBody == NULL) - { - return(STATUS_INVALID_HANDLE); - } - - ObjectHeader = BODY_TO_HEADER(HandleRep->ObjectBody); - - if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType) - { - return(STATUS_UNSUCCESSFUL); - } - - if (!(HandleRep->GrantedAccess & DesiredAccess)) - { - return(STATUS_ACCESS_DENIED); - } - - ObjectHeader->RefCount++; - - *Object = HandleRep->ObjectBody; - - return(STATUS_SUCCESS); -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/object.c + * PURPOSE: Implements generic object managment functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 10/06/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ************************************************************/ + +NTSTATUS STDCALL NtSetInformationObject(IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG Length) +{ + return(ZwSetInformationObject(ObjectHandle, + ObjectInformationClass, + ObjectInformation, + Length)); +} + +NTSTATUS STDCALL ZwSetInformationObject(IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG Length) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtQueryObject(IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + return(ZwQueryObject(ObjectHandle, + ObjectInformationClass, + ObjectInformation, + Length, + ResultLength)); +} + +NTSTATUS STDCALL ZwQueryObject(IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + UNIMPLEMENTED +} + +NTSTATUS NtMakeTemporaryObject(HANDLE Handle) +{ + return(ZwMakeTemporaryObject(Handle)); +} + +NTSTATUS ZwMakeTemporaryObject(HANDLE Handle) +{ + PVOID Object; + NTSTATUS Status; + POBJECT_HEADER ObjectHeader; + + Status = ObReferenceObjectByHandle(Handle, + 0, + NULL, + KernelMode, + &Object, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + ObjectHeader = BODY_TO_HEADER(Object); + ObjectHeader->Permanent = FALSE; + + ObDereferenceObject(Object); + + return(STATUS_SUCCESS); +} + +PVOID ObGenericCreateObject(PHANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + POBJECT_TYPE Type) +{ + POBJECT_HEADER hdr = NULL; + PWSTR path; + PWSTR name; + PWSTR Ignored; + PULONG addr; + PWSTR Buffer; + + DPRINT("ObGenericCreateObject(Handle %x, DesiredAccess %x," + "ObjectAttributes %x, Type %x)\n",Handle,DesiredAccess, + ObjectAttributes,Type); + + /* + * Allocate the object body and header + */ + hdr=(POBJECT_HEADER)ExAllocatePool(NonPagedPool,OBJECT_ALLOC_SIZE(Type)); + DPRINT("OBJECT_ALLOC_SIZE(Type) %d\n",OBJECT_ALLOC_SIZE(Type)); + if (hdr==NULL) + { + return(NULL); + } + DPRINT("hdr %x\n",hdr); + + + /* + * If unnamed then initalize + */ + if (ObjectAttributes==NULL || ObjectAttributes->ObjectName==NULL) + { + ObInitializeObjectHeader(Type,NULL,hdr); + if (Handle != NULL) + { + *Handle = ObInsertHandle(KeGetCurrentProcess(), + HEADER_TO_BODY(hdr), + DesiredAccess, + FALSE); + } + return(HEADER_TO_BODY(hdr)); + } + + + /* + * Copy the object name into a buffer + */ +// DbgPrint("ObjectAttributes->ObjectName %x\n",ObjectAttributes->ObjectName); +// DbgPrint("ObjectAttributes->ObjectName->Length %d\n", +// ObjectAttributes->ObjectName->Length); +// DbgPrint("ObjectAttributes->ObjectName->MaximumLength %d\n", +// ObjectAttributes->ObjectName->MaximumLength); + Buffer = ExAllocatePool(NonPagedPool, + ((ObjectAttributes->ObjectName->Length+1)*2)); + if (Buffer==NULL) + { + return(NULL); + } + memcpy(Buffer, ObjectAttributes->ObjectName->Buffer, + (ObjectAttributes->ObjectName->Length+1)*2); + + /* + * Seperate the name into a path and name + */ + name = wcsrchr(Buffer,'\\'); + if (name==NULL) + { + name=Buffer; + path=NULL; + } + else + { + path=Buffer; + *name=0; + name=name+1; + } + DPRINT("name %w path %w\n",name,path); + + ObLookupObject(ObjectAttributes->RootDirectory, + path, + &hdr->Parent, + &Ignored, + 0L); + + /* + * Initialize the object header + */ + ObInitializeObjectHeader(Type,name,hdr); + + + ObCreateEntry(hdr->Parent,hdr); + + DPRINT("Handle %x\n",Handle); + if (Handle != NULL) + { + *Handle = ObInsertHandle(KeGetCurrentProcess(), + HEADER_TO_BODY(hdr), + DesiredAccess, + FALSE); + } + + return(HEADER_TO_BODY(hdr)); +} + +VOID ObInitializeObjectHeader(POBJECT_TYPE Type, PWSTR name, + POBJECT_HEADER ObjectHeader) +/* + * FUNCTION: Creates a new object + * ARGUMENT: + * id = Identifier for the type of object + * obj = Pointer to the header of the object + */ +{ + PWSTR temp_name; + extern unsigned long long ticks; + + DPRINT("ObInitializeObjectHeader(id %x name %w obj %x)\n",Type, + name,ObjectHeader); + + ObjectHeader->HandleCount = 0; + ObjectHeader->RefCount = 0; + ObjectHeader->ObjectType = Type; + ObjectHeader->Permanent = FALSE; + if (name==NULL) + { + ObjectHeader->Name.Length=0; + ObjectHeader->Name.Buffer=NULL; + } + else + { + RtlInitUnicodeString(&(ObjectHeader->Name),name); + } +} + + +NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode) +/* + * FUNCTION: Increments the pointer reference count for a given object + * ARGUMENTS: + * ObjectBody = Object's body + * DesiredAccess = Desired access to the object + * ObjectType = Points to the object type structure + * AccessMode = Type of access check to perform + * RETURNS: Status + */ +{ + POBJECT_HEADER Object; + + DPRINT("ObReferenceObjectByPointer(%x)\n",ObjectBody); + + Object = BODY_TO_HEADER(ObjectBody); + Object->RefCount++; + return(STATUS_SUCCESS); +} + +NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header) +{ + if (Header->RefCount == 0 && Header->HandleCount == 0 && + !Header->Permanent) + { + ObRemoveEntry(Header); + ExFreePool(Header); + } + return(STATUS_SUCCESS); +} + +VOID ObDereferenceObject(PVOID ObjectBody) +/* + * FUNCTION: Decrements a given object's reference count and performs + * retention checks + * ARGUMENTS: + * ObjectBody = Body of the object + */ +{ + POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody); + Header->RefCount--; + ObPerformRetentionChecks(Header); +} + + +NTSTATUS NtClose(HANDLE Handle) +{ + return(ZwClose(Handle)); +} + +NTSTATUS ZwClose(HANDLE Handle) +/* + * FUNCTION: Closes a handle reference to an object + * ARGUMENTS: + * Handle = handle to close + * RETURNS: Status + */ +{ + PVOID ObjectBody; + POBJECT_HEADER Header; + PHANDLE_REP HandleRep; + + assert_irql(PASSIVE_LEVEL); + + HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle); + if (HandleRep == NULL) + { + return(STATUS_INVALID_HANDLE); + } + ObjectBody = HandleRep->ObjectBody; + + HandleRep->ObjectBody = NULL; + + Header = BODY_TO_HEADER(ObjectBody); + + Header->HandleCount--; + ObPerformRetentionChecks(Header); + + return(STATUS_SUCCESS); +} + +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID* Object, + POBJECT_HANDLE_INFORMATION + HandleInformationPtr + ) +/* + * FUNCTION: Increments the reference count for an object and returns a + * pointer to its body + * ARGUMENTS: + * Handle = Handle for the object + * DesiredAccess = Desired access to the object + * ObjectType + * AccessMode + * Object (OUT) = Points to the object body on return + * HandleInformation (OUT) = Contains information about the handle + * on return + * RETURNS: Status + */ +{ + PHANDLE_REP HandleRep; + POBJECT_HEADER ObjectHeader; + + ASSERT_IRQL(PASSIVE_LEVEL); + + DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, " + "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess, + ObjectType,AccessMode,Object); + + if (Handle == NtCurrentProcess()) + { + *Object = PsGetCurrentProcess(); + return(STATUS_SUCCESS); + } + if (Handle == NtCurrentThread()) + { + *Object = PsGetCurrentThread(); + return(STATUS_SUCCESS); + } + + HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle); + if (HandleRep == NULL || HandleRep->ObjectBody == NULL) + { + return(STATUS_INVALID_HANDLE); + } + + ObjectHeader = BODY_TO_HEADER(HandleRep->ObjectBody); + + if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType) + { + return(STATUS_UNSUCCESSFUL); + } + + if (!(HandleRep->GrantedAccess & DesiredAccess)) + { + return(STATUS_ACCESS_DENIED); + } + + ObjectHeader->RefCount++; + + *Object = HandleRep->ObjectBody; + + return(STATUS_SUCCESS); +} diff --git a/reactos/ntoskrnl/ob/object.s b/reactos/ntoskrnl/ob/object.s deleted file mode 100644 index 7b2b718f942..00000000000 --- a/reactos/ntoskrnl/ob/object.s +++ /dev/null @@ -1,468 +0,0 @@ - .file "object.c" - .version "01.01" -gcc2_compiled.: -.text - .align 16 -.globl NtSetInformationObject - .type NtSetInformationObject,@function -NtSetInformationObject: - pushl %ebp - movl %esp,%ebp - pushl %ebx - movl 8(%ebp),%ebx - movl 12(%ebp),%ecx - movl 16(%ebp),%edx - movl 20(%ebp),%eax - pushl %eax - pushl %edx - pushl %ecx - pushl %ebx - call ZwSetInformationObject - movl -4(%ebp),%ebx - movl %ebp,%esp - popl %ebp - ret $16 -.Lfe1: - .size NtSetInformationObject,.Lfe1-NtSetInformationObject -.section .rodata -.LC0: - .string "object.c" -.LC1: - .string "ZwSetInformationObject" -.LC2: - .string "%s at %s:%d is unimplemented, have a nice day\n" -.text - .align 16 -.globl ZwSetInformationObject - .type ZwSetInformationObject,@function -ZwSetInformationObject: - pushl %ebp - movl %esp,%ebp - pushl $38 - pushl $.LC0 - pushl $.LC1 - pushl $.LC2 - call DbgPrint - .align 4 -.L17: - jmp .L17 - .align 16 -.Lfe2: - .size ZwSetInformationObject,.Lfe2-ZwSetInformationObject - .align 16 -.globl NtQueryObject - .type NtQueryObject,@function -NtQueryObject: - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %ebx - movl 8(%ebp),%esi - movl 12(%ebp),%ebx - movl 16(%ebp),%ecx - movl 20(%ebp),%edx - movl 24(%ebp),%eax - pushl %eax - pushl %edx - pushl %ecx - pushl %ebx - pushl %esi - call ZwQueryObject - leal -8(%ebp),%esp - popl %ebx - popl %esi - movl %ebp,%esp - popl %ebp - ret $20 -.Lfe3: - .size NtQueryObject,.Lfe3-NtQueryObject -.section .rodata -.LC3: - .string "ZwQueryObject" -.text - .align 16 -.globl ZwQueryObject - .type ZwQueryObject,@function -ZwQueryObject: - pushl %ebp - movl %esp,%ebp - pushl $60 - pushl $.LC0 - pushl $.LC3 - pushl $.LC2 - call DbgPrint - .align 4 -.L26: - jmp .L26 - .align 16 -.Lfe4: - .size ZwQueryObject,.Lfe4-ZwQueryObject - .align 16 -.globl NtMakeTemporaryObject - .type NtMakeTemporaryObject,@function -NtMakeTemporaryObject: - pushl %ebp - movl %esp,%ebp - movl 8(%ebp),%eax - pushl %eax - call ZwMakeTemporaryObject - movl %ebp,%esp - popl %ebp - ret $4 -.Lfe5: - .size NtMakeTemporaryObject,.Lfe5-NtMakeTemporaryObject - .align 16 -.globl ZwMakeTemporaryObject - .type ZwMakeTemporaryObject,@function -ZwMakeTemporaryObject: - pushl %ebp - movl %esp,%ebp - subl $4,%esp - movl 8(%ebp),%edx - pushl $0 - leal -4(%ebp),%eax - pushl %eax - pushl $0 - pushl $0 - pushl $0 - pushl %edx - call ObReferenceObjectByHandle - addl $24,%esp - testl %eax,%eax - jne .L30 - movl -4(%ebp),%eax - movb $0,-12(%eax) - movl -4(%ebp),%eax - pushl %eax - call ObDereferenceObject - xorl %eax,%eax - movl %ebp,%esp - popl %ebp - ret $4 - .align 16 -.L30: - movl %ebp,%esp - popl %ebp - ret $4 -.Lfe6: - .size ZwMakeTemporaryObject,.Lfe6-ZwMakeTemporaryObject - .align 16 -.globl ObGenericCreateObject - .type ObGenericCreateObject,@function -ObGenericCreateObject: - pushl %ebp - movl %esp,%ebp - subl $12,%esp - pushl %edi - pushl %esi - pushl %ebx - movl 16(%ebp),%edi - movl 20(%ebp),%ecx - movl 28(%ecx),%eax - addl $36,%eax - pushl %eax - pushl $0 - call ExAllocatePool - movl %eax,%esi - addl $8,%esp - testl %esi,%esi - je .L46 - testl %edi,%edi - jne .L35 - pushl %esi - pushl $0 - movl 20(%ebp),%ecx - pushl %ecx - call ObInitializeObjectHeader - addl $12,%esp - jmp .L47 - .align 16 -.L35: - movl 8(%edi),%ecx - movw (%ecx),%dx - sall $16,%edx - movzwl -8(%ebp),%eax - orl %edx,%eax - movl %eax,-8(%ebp) - movzwl (%ecx),%eax - leal 2(,%eax,2),%eax - pushl %eax - pushl $0 - call ExAllocatePool - movl %eax,-4(%ebp) - addl $8,%esp - testl %eax,%eax - jne .L39 -.L46: - xorl %eax,%eax - jmp .L45 - .align 16 -.L39: - movl 8(%edi),%eax - pushl %eax - leal -8(%ebp),%eax - pushl %eax - call RtlCopyUnicodeString - pushl $92 - movl -4(%ebp),%eax - pushl %eax - call wcsrchr - movl %eax,%ebx - addl $16,%esp - testl %ebx,%ebx - jne .L40 - movl -4(%ebp),%ebx - xorl %edx,%edx - jmp .L41 - .align 16 -.L40: - movl -4(%ebp),%edx - movw $0,(%ebx) - addl $2,%ebx -.L41: - leal -12(%ebp),%eax - pushl %eax - leal 28(%esi),%eax - pushl %eax - pushl %edx - movl 4(%edi),%eax - pushl %eax - call ObLookupObject - pushl %esi - pushl %ebx - movl 20(%ebp),%ecx - pushl %ecx - call ObInitializeObjectHeader - pushl %esi - movl 28(%esi),%eax - pushl %eax - call ObCreateEntry - addl $36,%esp -.L47: - cmpl $0,8(%ebp) - je .L42 - pushl $0 - movl 12(%ebp),%ecx - pushl %ecx - leal 36(%esi),%eax - pushl %eax - call KeGetCurrentProcess - pushl %eax - call ObInsertHandle - movl 8(%ebp),%ecx - movl %eax,(%ecx) -.L42: - leal 36(%esi),%eax -.L45: - leal -24(%ebp),%esp - popl %ebx - popl %esi - popl %edi - movl %ebp,%esp - popl %ebp - ret -.Lfe7: - .size ObGenericCreateObject,.Lfe7-ObGenericCreateObject - .align 16 -.globl ObInitializeObjectHeader - .type ObInitializeObjectHeader,@function -ObInitializeObjectHeader: - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %ebx - movl 8(%ebp),%eax - movl 12(%ebp),%esi - movl 16(%ebp),%ebx - movl $0,20(%ebx) - movl $0,16(%ebx) - movl %eax,32(%ebx) - movb $0,24(%ebx) - testl %esi,%esi - jne .L49 - movw $0,(%ebx) - movl $0,4(%ebx) - jmp .L50 - .align 16 -.L49: - pushl %esi - call wstrlen - movw %ax,2(%ebx) - andl $65535,%eax - leal 2(,%eax,2),%eax - pushl %eax - pushl $0 - call ExAllocatePool - movl %eax,4(%ebx) - pushl %esi - pushl %ebx - call RtlInitUnicodeString -.L50: - leal -8(%ebp),%esp - popl %ebx - popl %esi - movl %ebp,%esp - popl %ebp - ret -.Lfe8: - .size ObInitializeObjectHeader,.Lfe8-ObInitializeObjectHeader - .align 16 -.globl ObReferenceObjectByPointer - .type ObReferenceObjectByPointer,@function -ObReferenceObjectByPointer: - pushl %ebp - movl %esp,%ebp - movl 8(%ebp),%eax - incl -20(%eax) - xorl %eax,%eax - movl %ebp,%esp - popl %ebp - ret -.Lfe9: - .size ObReferenceObjectByPointer,.Lfe9-ObReferenceObjectByPointer - .align 16 -.globl ObPerformRetentionChecks - .type ObPerformRetentionChecks,@function -ObPerformRetentionChecks: - pushl %ebp - movl %esp,%ebp - pushl %ebx - movl 8(%ebp),%ebx - cmpl $0,16(%ebx) - jne .L54 - cmpl $0,20(%ebx) - jne .L54 - cmpb $0,24(%ebx) - jne .L54 - pushl %ebx - call ObRemoveEntry - pushl %ebx - call ExFreePool -.L54: - xorl %eax,%eax - movl -4(%ebp),%ebx - movl %ebp,%esp - popl %ebp - ret -.Lfe10: - .size ObPerformRetentionChecks,.Lfe10-ObPerformRetentionChecks - .align 16 -.globl ObDereferenceObject - .type ObDereferenceObject,@function -ObDereferenceObject: - pushl %ebp - movl %esp,%ebp - movl 8(%ebp),%eax - leal -36(%eax),%edx - decl -20(%eax) - pushl %edx - call ObPerformRetentionChecks - movl %ebp,%esp - popl %ebp - ret -.Lfe11: - .size ObDereferenceObject,.Lfe11-ObDereferenceObject - .align 16 -.globl NtClose - .type NtClose,@function -NtClose: - pushl %ebp - movl %esp,%ebp - movl 8(%ebp),%eax - pushl %eax - call ZwClose - movl %ebp,%esp - popl %ebp - ret $4 -.Lfe12: - .size NtClose,.Lfe12-NtClose - .align 16 -.globl ZwClose - .type ZwClose,@function -ZwClose: - pushl %ebp - movl %esp,%ebp - movl 8(%ebp),%eax - pushl %eax - call KeGetCurrentProcess - pushl %eax - call ObTranslateHandle - movl %eax,%edx - addl $8,%esp - testl %edx,%edx - je .L59 - movl (%edx),%eax - movl $0,(%edx) - leal -36(%eax),%edx - decl -16(%eax) - pushl %edx - call ObPerformRetentionChecks - xorl %eax,%eax - movl %ebp,%esp - popl %ebp - ret $4 - .align 16 -.L59: - movl $-1073741816,%eax - movl %ebp,%esp - popl %ebp - ret $4 -.Lfe13: - .size ZwClose,.Lfe13-ZwClose - .align 16 -.globl ObReferenceObjectByHandle - .type ObReferenceObjectByHandle,@function -ObReferenceObjectByHandle: - pushl %ebp - movl %esp,%ebp - pushl %edi - pushl %esi - pushl %ebx - movl 8(%ebp),%eax - movl 16(%ebp),%ebx - movl 24(%ebp),%esi - pushl %eax - call KeGetCurrentProcess - pushl %eax - call ObTranslateHandle - testl %eax,%eax - je .L64 - movl (%eax),%edx - testl %edx,%edx - jne .L63 -.L64: - movl $-1073741816,%eax - jmp .L68 - .align 16 -.L63: - leal -36(%edx),%ecx - testl %ebx,%ebx - je .L66 - cmpl %ebx,-4(%edx) - je .L66 - movl $-2147483605,%eax - jmp .L68 - .align 16 -.L66: - movl 12(%ebp),%edi - testl %edi,4(%eax) - jne .L67 - incl 16(%ecx) - movl (%eax),%eax - movl %eax,(%esi) - xorl %eax,%eax - jmp .L68 - .align 16 -.L67: - movl $-2147483557,%eax -.L68: - leal -12(%ebp),%esp - popl %ebx - popl %esi - popl %edi - movl %ebp,%esp - popl %ebp - ret -.Lfe14: - .size ObReferenceObjectByHandle,.Lfe14-ObReferenceObjectByHandle - .ident "GCC: (GNU) 2.7.2.3" diff --git a/reactos/ntoskrnl/ps/idle.c b/reactos/ntoskrnl/ps/idle.c index 1db76a21ae6..d156ecf90ef 100644 --- a/reactos/ntoskrnl/ps/idle.c +++ b/reactos/ntoskrnl/ps/idle.c @@ -1,9 +1,9 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/bug.c - * PURPOSE: Graceful system shutdown if a bug is detected - * PROGRAMMER: David Welch (welch@mcmail.com) + * FILE: ntoskrnl/ps/idle.c + * PURPOSE: Using idle time + * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * Created 22/05/98 */ diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 17032f68176..40870f97810 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -13,9 +13,13 @@ #include #include -#define NDEBUG +//#define NDEBUG #include +/* GLBOALS *******************************************************************/ + +extern ULONG PiNrThreads; + /* FUNCTIONS *****************************************************************/ NTSTATUS STDCALL NtTerminateThread(IN HANDLE ThreadHandle, @@ -51,6 +55,14 @@ NTSTATUS STDCALL ZwTerminateThread(IN HANDLE ThreadHandle, } } +VOID PsReleaseThread(PETHREAD Thread) +{ + DPRINT("PsReleaseThread(Thread %x)\n",Thread); + + RemoveEntryList(&Thread->Tcb.Entry); + ExFreePool(Thread); +} + NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) /* @@ -63,6 +75,8 @@ NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) KIRQL oldlvl; PETHREAD CurrentThread; + PiNrThreads--; + CurrentThread = PsGetCurrentThread(); CurrentThread->ExitStatus = ExitStatus; @@ -70,7 +84,6 @@ NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) DPRINT("terminating %x\n",CurrentThread); KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); CurrentThread->Tcb.ThreadState = THREAD_STATE_TERMINATED; - RemoveEntryList(&CurrentThread->Tcb.Entry); ZwYieldExecution(); for(;;); } diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index cd10a134454..0b02183b360 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,316 +1,329 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/process.c - * PURPOSE: Process managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 21/07/98: Created - */ - -/* INCLUDES ******************************************************************/ - -#include -#include -#include -#include - -#define NDEBUG -#include - -/* GLOBALS ******************************************************************/ - -PEPROCESS SystemProcess = NULL; -HANDLE SystemProcessHandle = NULL; - -POBJECT_TYPE PsProcessType = NULL; - -/* FUNCTIONS *****************************************************************/ - -VOID PsInitProcessManagment(VOID) -{ - ANSI_STRING AnsiString; - PKPROCESS KProcess; - - /* - * Register the process object type - */ - - PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - - PsProcessType->TotalObjects = 0; - PsProcessType->TotalHandles = 0; - PsProcessType->MaxObjects = ULONG_MAX; - PsProcessType->MaxHandles = ULONG_MAX; - PsProcessType->PagedPoolCharge = 0; - PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS); - PsProcessType->Dump = NULL; - PsProcessType->Open = NULL; - PsProcessType->Close = NULL; - PsProcessType->Delete = NULL; - PsProcessType->Parse = NULL; - PsProcessType->Security = NULL; - PsProcessType->QueryName = NULL; - PsProcessType->OkayToClose = NULL; - - RtlInitAnsiString(&AnsiString,"Process"); - RtlAnsiStringToUnicodeString(&PsProcessType->TypeName,&AnsiString,TRUE); - - /* - * Initialize the system process - */ - SystemProcess = ObGenericCreateObject(NULL,PROCESS_ALL_ACCESS,NULL, - PsProcessType); - KProcess = &SystemProcess->Pcb; - - InitializeListHead(&(KProcess->MemoryAreaList)); - ObInitializeHandleTable(NULL,FALSE,KProcess); - KProcess->PageTableDirectory = get_page_directory(); - - SystemProcessHandle = ObInsertHandle(KProcess,SystemProcess, - PROCESS_ALL_ACCESS,FALSE); -} - -PKPROCESS KeGetCurrentProcess(VOID) -/* - * FUNCTION: Returns a pointer to the current process - */ -{ - return(&(PsGetCurrentProcess()->Pcb)); -} - -struct _EPROCESS* PsGetCurrentProcess(VOID) -/* - * FUNCTION: Returns a pointer to the current process - */ -{ - if (PsGetCurrentThread()==NULL - || PsGetCurrentThread()->ThreadsProcess==NULL) - { - return(SystemProcess); - } - else - { - return(PsGetCurrentThread()->ThreadsProcess); - } -} - -NTSTATUS STDCALL NtCreateProcess( - OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN HANDLE ParentProcessHandle, - IN BOOLEAN InheritObjectTable, - IN HANDLE SectionHandle OPTIONAL, - IN HANDLE DebugPort OPTIONAL, - IN HANDLE ExceptionPort OPTIONAL) -{ - return(ZwCreateProcess(ProcessHandle, - DesiredAccess, - ObjectAttributes, - ParentProcessHandle, - InheritObjectTable, - SectionHandle, - DebugPort, - ExceptionPort)); -} - -NTSTATUS STDCALL ZwCreateProcess( - OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN HANDLE ParentProcessHandle, - IN BOOLEAN InheritObjectTable, - IN HANDLE SectionHandle OPTIONAL, - IN HANDLE DebugPort OPTIONAL, - IN HANDLE ExceptionPort OPTIONAL) -/* - * FUNCTION: Creates a process. - * ARGUMENTS: - * ProcessHandle (OUT) = Caller supplied storage for the resulting - * handle - * DesiredAccess = Specifies the allowed or desired access to the - * process can be a combination of - * STANDARD_RIGHTS_REQUIRED| .. - * ObjectAttribute = Initialized attributes for the object, contains - * the rootdirectory and the filename - * ParentProcess = Handle to the parent process. - * InheritObjectTable = Specifies to inherit the objects of the parent - * process if true. - * SectionHandle = Handle to a section object to back the image file - * DebugPort = Handle to a DebugPort if NULL the system default debug - * port will be used. - * ExceptionPort = Handle to a exception port. - * REMARKS: - * This function maps to the win32 CreateProcess. - * RETURNS: Status - */ -{ - PEPROCESS Process; - PEPROCESS ParentProcess; - PULONG PageDirectory; - PULONG CurrentPageDirectory; - ULONG i; - PKPROCESS KProcess; - ULONG Base; - ULONG Length; - LARGE_INTEGER Offset; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ParentProcessHandle, - PROCESS_CREATE_PROCESS, - PsProcessType, - UserMode, - &ParentProcessHandle, - NULL); - if (Status != STATUS_SUCCESS) - { - DPRINT("ZwCreateProcess() = %x\n",Status); - return(Status); - } - - Process = ObGenericCreateObject(ProcessHandle,DesiredAccess, - ObjectAttributes,PsProcessType); - KProcess = &(Process->Pcb); - - InitializeListHead(&(KProcess->MemoryAreaList)); - ObInitializeHandleTable(KProcess,InheritObjectTable,KProcess); - - PageDirectory = physical_to_linear((ULONG)get_free_page()); - KProcess->PageTableDirectory = PageDirectory; - - CurrentPageDirectory = get_page_directory(); - - memset(PageDirectory,0,PAGESIZE); - for (i=768;i<1024;i++) - { - PageDirectory[i]=CurrentPageDirectory[i]; - } - - - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL NtTerminateProcess(IN HANDLE ProcessHandle, - IN NTSTATUS ExitStatus) -{ - return(ZwTerminateProcess(ProcessHandle,ExitStatus)); -} - -NTSTATUS STDCALL ZwTerminateProcess(IN HANDLE ProcessHandle, - IN NTSTATUS ExitStatus) -{ - UNIMPLEMENTED; -} - - -NTSTATUS STDCALL NtOpenProcess (OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) -{ - return(ZwOpenProcess(ProcessHandle, - DesiredAccess, - ObjectAttributes, - ClientId)); -} - -NTSTATUS STDCALL ZwOpenProcess (OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtQueryInformationProcess( - IN HANDLE ProcessHandle, - IN CINT ProcessInformationClass, - OUT PVOID ProcessInformation, - IN ULONG ProcessInformationLength, - OUT PULONG ReturnLength) -{ - return(ZwQueryInformationProcess(ProcessHandle, - ProcessInformationClass, - ProcessInformation, - ProcessInformationLength, - ReturnLength)); -} - -NTSTATUS STDCALL ZwQueryInformationProcess( - IN HANDLE ProcessHandle, - IN CINT ProcessInformationClass, - OUT PVOID ProcessInformation, - IN ULONG ProcessInformationLength, - OUT PULONG ReturnLength) -{ - PEPROCESS Process; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_QUERY_INFORMATION, - PsProcessType, - UserMode, - &ProcessHandle, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - switch (ProcessInformationClass) - { - case ProcessBasicInformation: - case ProcessQuotaLimits: - case ProcessIoCounters: - case ProcessVmCounters: - case ProcessTimes: - case ProcessBasePriority: - case ProcessRaisePriority: - case ProcessDebugPort: - case ProcessExceptionPort: - case ProcessAccessToken: - case ProcessLdtInformation: - case ProcessLdtSize: - case ProcessDefaultHardErrorMode: - case ProcessIoPortHandlers: - case ProcessWorkingSetWatch: - case ProcessUserModeIOPL: - case ProcessEnableAlignmentFaultFixup: - case ProcessPriorityClass: - case ProcessWx86Information: - case ProcessHandleCount: - case ProcessAffinityMask: - default: - Status = STATUS_NOT_IMPLEMENTED; - } - return(Status); -} - -NTSTATUS -STDCALL -NtSetInformationProcess( - IN HANDLE ProcessHandle, - IN CINT ProcessInformationClass, - IN PVOID ProcessInformation, - IN ULONG ProcessInformationLength - ) -{ - return(ZwSetInformationProcess(ProcessHandle, - ProcessInformationClass, - ProcessInformation, - ProcessInformationLength)); -} - -NTSTATUS -STDCALL -ZwSetInformationProcess( - IN HANDLE ProcessHandle, - IN CINT ProcessInformationClass, - IN PVOID ProcessInformation, - IN ULONG ProcessInformationLength - ) -{ - UNIMPLEMENTED; -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/process.c + * PURPOSE: Process managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 21/07/98: Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +PEPROCESS SystemProcess = NULL; +HANDLE SystemProcessHandle = NULL; + +POBJECT_TYPE PsProcessType = NULL; + +/* FUNCTIONS *****************************************************************/ + +VOID PsInitProcessManagment(VOID) +{ + ANSI_STRING AnsiString; + PKPROCESS KProcess; + + /* + * Register the process object type + */ + + PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + PsProcessType->TotalObjects = 0; + PsProcessType->TotalHandles = 0; + PsProcessType->MaxObjects = ULONG_MAX; + PsProcessType->MaxHandles = ULONG_MAX; + PsProcessType->PagedPoolCharge = 0; + PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS); + PsProcessType->Dump = NULL; + PsProcessType->Open = NULL; + PsProcessType->Close = NULL; + PsProcessType->Delete = NULL; + PsProcessType->Parse = NULL; + PsProcessType->Security = NULL; + PsProcessType->QueryName = NULL; + PsProcessType->OkayToClose = NULL; + + RtlInitAnsiString(&AnsiString,"Process"); + RtlAnsiStringToUnicodeString(&PsProcessType->TypeName,&AnsiString,TRUE); + + /* + * Initialize the system process + */ + SystemProcess = ObGenericCreateObject(NULL,PROCESS_ALL_ACCESS,NULL, + PsProcessType); + KProcess = &SystemProcess->Pcb; + + InitializeListHead(&(KProcess->MemoryAreaList)); + ObInitializeHandleTable(NULL,FALSE,KProcess); + KProcess->PageTableDirectory = get_page_directory(); + + SystemProcessHandle = ObInsertHandle(KProcess,SystemProcess, + PROCESS_ALL_ACCESS,FALSE); +} + +PKPROCESS KeGetCurrentProcess(VOID) +/* + * FUNCTION: Returns a pointer to the current process + */ +{ + return(&(PsGetCurrentProcess()->Pcb)); +} + +struct _EPROCESS* PsGetCurrentProcess(VOID) +/* + * FUNCTION: Returns a pointer to the current process + */ +{ + if (PsGetCurrentThread()==NULL + || PsGetCurrentThread()->ThreadsProcess==NULL) + { + return(SystemProcess); + } + else + { + return(PsGetCurrentThread()->ThreadsProcess); + } +} + +NTSTATUS STDCALL NtCreateProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcessHandle, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL) +{ + return(ZwCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + ParentProcessHandle, + InheritObjectTable, + SectionHandle, + DebugPort, + ExceptionPort)); +} + +NTSTATUS STDCALL ZwCreateProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcessHandle, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL) +/* + * FUNCTION: Creates a process. + * ARGUMENTS: + * ProcessHandle (OUT) = Caller supplied storage for the resulting + * handle + * DesiredAccess = Specifies the allowed or desired access to the + * process can be a combination of + * STANDARD_RIGHTS_REQUIRED| .. + * ObjectAttribute = Initialized attributes for the object, contains + * the rootdirectory and the filename + * ParentProcess = Handle to the parent process. + * InheritObjectTable = Specifies to inherit the objects of the parent + * process if true. + * SectionHandle = Handle to a section object to back the image file + * DebugPort = Handle to a DebugPort if NULL the system default debug + * port will be used. + * ExceptionPort = Handle to a exception port. + * REMARKS: + * This function maps to the win32 CreateProcess. + * RETURNS: Status + */ +{ + PEPROCESS Process; + PEPROCESS ParentProcess; + PULONG PageDirectory; + PULONG CurrentPageDirectory; + ULONG i; + PKPROCESS KProcess; + ULONG Base; + ULONG Length; + LARGE_INTEGER Offset; + NTSTATUS Status; + + DPRINT("ZwCreateProcess(ObjectAttributes %x)\n",ObjectAttributes); + + Status = ObReferenceObjectByHandle(ParentProcessHandle, + PROCESS_CREATE_PROCESS, + PsProcessType, + UserMode, + &ParentProcessHandle, + NULL); + + if (Status != STATUS_SUCCESS) + { + DPRINT("ZwCreateProcess() = %x\n",Status); + return(Status); + } + + Process = ObGenericCreateObject(ProcessHandle, + DesiredAccess, + ObjectAttributes, + PsProcessType); + KProcess = &(Process->Pcb); + + InitializeListHead(&(KProcess->MemoryAreaList)); + ObInitializeHandleTable(KProcess,InheritObjectTable,KProcess); + + PageDirectory = physical_to_linear((ULONG)get_free_page()); + KProcess->PageTableDirectory = PageDirectory; + + CurrentPageDirectory = get_page_directory(); + + memset(PageDirectory,0,PAGESIZE); + for (i=768;i<1024;i++) + { + PageDirectory[i]=CurrentPageDirectory[i]; + } + + /* + * FIXME: I don't what I'm supposed to know with a section handle + */ + if (SectionHandle != NULL) + { + DbgPrint("ZwCreateProcess() non-NULL SectionHandle\n"); + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL NtTerminateProcess(IN HANDLE ProcessHandle, + IN NTSTATUS ExitStatus) +{ + return(ZwTerminateProcess(ProcessHandle,ExitStatus)); +} + +NTSTATUS STDCALL ZwTerminateProcess(IN HANDLE ProcessHandle, + IN NTSTATUS ExitStatus) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL NtOpenProcess (OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + return(ZwOpenProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + ClientId)); +} + +NTSTATUS STDCALL ZwOpenProcess (OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtQueryInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength) +{ + return(ZwQueryInformationProcess(ProcessHandle, + ProcessInformationClass, + ProcessInformation, + ProcessInformationLength, + ReturnLength)); +} + +NTSTATUS STDCALL ZwQueryInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength) +{ + PEPROCESS Process; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_QUERY_INFORMATION, + PsProcessType, + UserMode, + &ProcessHandle, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + switch (ProcessInformationClass) + { + case ProcessBasicInformation: + case ProcessQuotaLimits: + case ProcessIoCounters: + case ProcessVmCounters: + case ProcessTimes: + case ProcessBasePriority: + case ProcessRaisePriority: + case ProcessDebugPort: + case ProcessExceptionPort: + case ProcessAccessToken: + case ProcessLdtInformation: + case ProcessLdtSize: + case ProcessDefaultHardErrorMode: + case ProcessIoPortHandlers: + case ProcessWorkingSetWatch: + case ProcessUserModeIOPL: + case ProcessEnableAlignmentFaultFixup: + case ProcessPriorityClass: + case ProcessWx86Information: + case ProcessHandleCount: + case ProcessAffinityMask: + default: + Status = STATUS_NOT_IMPLEMENTED; + } + return(Status); +} + +NTSTATUS +STDCALL +NtSetInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ) +{ + return(ZwSetInformationProcess(ProcessHandle, + ProcessInformationClass, + ProcessInformation, + ProcessInformationLength)); +} + +NTSTATUS +STDCALL +ZwSetInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ) +{ + UNIMPLEMENTED; +} diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 741ed4273c0..0975fc2a9af 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,595 +1,619 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/thread.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 23/06/98: Created - */ - -/* - * NOTE: - * - * All of the routines that manipulate the thread queue synchronize on - * a single spinlock - * - */ - -/* INCLUDES ****************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -/* TYPES *******************************************************************/ - -/* GLOBALS ******************************************************************/ - -POBJECT_TYPE PsThreadType = NULL; - -#define NR_THREAD_PRIORITY_LEVELS (31) -#define THREAD_PRIORITY_MAX (15) - -static KSPIN_LOCK ThreadListLock = {0,}; - -/* - * PURPOSE: List of threads associated with each priority level - */ -static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS]={{NULL,NULL},}; -static BOOLEAN DoneInitYet = FALSE; - -static PETHREAD CurrentThread = NULL; - -static ULONG NextThreadUniqueId = 0; - -/* FUNCTIONS ***************************************************************/ - -PKTHREAD KeGetCurrentThread(VOID) -{ - return(&(CurrentThread->Tcb)); -} - -PETHREAD PsGetCurrentThread(VOID) -{ - return((PETHREAD)KeGetCurrentThread()); -} - -static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread) -{ - KIRQL oldlvl; - - DPRINT("PsInsertIntoThreadList(Priority %d, Thread %x)\n",Priority,Thread); - - KeAcquireSpinLock(&ThreadListLock,&oldlvl); - InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority], - &Thread->Tcb.Entry); - KeReleaseSpinLock(&ThreadListLock,oldlvl); -} - -VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext) -{ - NTSTATUS Ret; - - KeReleaseSpinLock(&ThreadListLock,PASSIVE_LEVEL); - Ret = StartRoutine(StartContext); - PsTerminateSystemThread(Ret); - for(;;); -} - -static PETHREAD PsScanThreadList(KPRIORITY Priority) -{ - PLIST_ENTRY current_entry; - PETHREAD current; - PETHREAD oldest = NULL; - ULONG oldest_time = 0; - - DPRINT("PsScanThreadList(Priority %d)\n",Priority); - - current_entry = PriorityListHead[THREAD_PRIORITY_MAX+Priority].Flink; - while (current_entry != &PriorityListHead[THREAD_PRIORITY_MAX+Priority]) - { - current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.Entry); - if (current->Tcb.ThreadState == THREAD_STATE_RUNNABLE) - { - if (oldest == NULL || oldest_time > current->Tcb.LastTick) - { - oldest = current; - oldest_time = current->Tcb.LastTick; - } - } - current_entry = current_entry->Flink; - } - DPRINT("PsScanThreadList() = %x\n",oldest); - return(oldest); -} - -VOID PsDispatchThread(VOID) -{ - KPRIORITY CurrentPriority; - PETHREAD Candidate; - KIRQL irql; - LARGE_INTEGER TickCount; - - KeAcquireSpinLock(&ThreadListLock,&irql); - - if (!DoneInitYet) - { - return; - } - - DPRINT("PsDispatchThread() Current %x\n",CurrentThread); - - if (CurrentThread->Tcb.ThreadState==THREAD_STATE_RUNNING) - { - CurrentThread->Tcb.ThreadState=THREAD_STATE_RUNNABLE; - } - - for (CurrentPriority=THREAD_PRIORITY_TIME_CRITICAL; - CurrentPriority>=THREAD_PRIORITY_IDLE; - CurrentPriority--) - { - Candidate = PsScanThreadList(CurrentPriority); - if (Candidate == CurrentThread) - { - DPRINT("Scheduling current thread\n"); - KeQueryTickCount(&TickCount); - CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount); - CurrentThread->Tcb.ThreadState = THREAD_STATE_RUNNING; - KeReleaseSpinLock(&ThreadListLock,irql); - return; - } - if (Candidate != NULL) - { - DPRINT("Scheduling %x\n",Candidate); - - Candidate->Tcb.ThreadState = THREAD_STATE_RUNNING; - - KeQueryTickCount(&TickCount); - CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount); - - CurrentThread = Candidate; - - HalTaskSwitch(&CurrentThread->Tcb); - KeReleaseSpinLock(&ThreadListLock,irql); - return; - } - } -} - -NTSTATUS PsInitializeThread(HANDLE ProcessHandle, - PETHREAD* ThreadPtr, - PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ThreadAttributes) -{ - ULONG ThreadId; - ULONG ProcessId; - PETHREAD Thread; - NTSTATUS Status; - - Thread = ObGenericCreateObject(ThreadHandle, - DesiredAccess, - ThreadAttributes, - PsThreadType); - DPRINT("Thread = %x\n",Thread); - Thread->Tcb.LastTick = 0; - Thread->Tcb.ThreadState=THREAD_STATE_SUSPENDED; - Thread->Tcb.BasePriority=THREAD_PRIORITY_NORMAL; - Thread->Tcb.CurrentPriority=THREAD_PRIORITY_NORMAL; - Thread->Tcb.ApcList=ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY)); - Thread->Tcb.SuspendCount = 1; - if (ProcessHandle!=NULL) - { - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_CREATE_THREAD, - PsProcessType, - UserMode, - (PVOID*)&Thread->ThreadsProcess, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - } - else - { - Thread->ThreadsProcess=SystemProcess; - } - InitializeListHead(Thread->Tcb.ApcList); - InitializeListHead(&(Thread->IrpList)); - Thread->Cid.UniqueThread=NextThreadUniqueId++; -// thread->Cid.ThreadId=InterlockedIncrement(&NextThreadUniqueId); - PsInsertIntoThreadList(Thread->Tcb.CurrentPriority,Thread); - - *ThreadPtr = Thread; - - return(STATUS_SUCCESS); -} - -VOID PsResumeThread(PETHREAD Thread) -{ - DPRINT("PsResumeThread(Thread %x)\n",Thread); - - Thread->Tcb.SuspendCount--; - DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount); - DPRINT("Thread->Tcb.ThreadState %d THREAD_STATE_RUNNING %d\n", - Thread->Tcb.ThreadState,THREAD_STATE_RUNNING); - if (Thread->Tcb.SuspendCount <= 0 && - Thread->Tcb.ThreadState != THREAD_STATE_RUNNING) - { - DPRINT("Setting thread to runnable\n"); - Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE; - } - DPRINT("Finished PsResumeThread()\n"); -} - -VOID PsSuspendThread(PETHREAD Thread) -{ - DPRINT("PsSuspendThread(Thread %x)\n",Thread); - Thread->Tcb.SuspendCount++; - if (Thread->Tcb.SuspendCount > 0) - { - Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED; - if (Thread == CurrentThread) - { - PsDispatchThread(); - } - } -} - -void PsInitThreadManagment(void) -/* - * FUNCTION: Initialize thread managment - */ -{ - PETHREAD FirstThread; - ULONG i; - ANSI_STRING AnsiString; - HANDLE FirstThreadHandle; - - KeInitializeSpinLock(&ThreadListLock); - for (i=0; iTypeName,&AnsiString,TRUE); - - PsThreadType->TotalObjects = 0; - PsThreadType->TotalHandles = 0; - PsThreadType->MaxObjects = 0; - PsThreadType->MaxHandles = 0; - PsThreadType->PagedPoolCharge = 0; - PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD); - PsThreadType->Dump = NULL; - PsThreadType->Open = NULL; - PsThreadType->Close = NULL; - PsThreadType->Delete = NULL; - PsThreadType->Parse = NULL; - PsThreadType->Security = NULL; - PsThreadType->QueryName = NULL; - PsThreadType->OkayToClose = NULL; - - PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle, - THREAD_ALL_ACCESS,NULL); - HalInitFirstTask(FirstThread); - FirstThread->Tcb.ThreadState = THREAD_STATE_RUNNING; - FirstThread->Tcb.SuspendCount = 0; - - DPRINT("FirstThread %x\n",FirstThread); - - CurrentThread = FirstThread; - - DoneInitYet = TRUE; -} - -NTSTATUS NtCreateThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID Client, - PCONTEXT ThreadContext, - PINITIAL_TEB InitialTeb, - BOOLEAN CreateSuspended) -{ - return(ZwCreateThread(ThreadHandle, - DesiredAccess, - ObjectAttributes, - ProcessHandle, - Client, - ThreadContext, - InitialTeb, - CreateSuspended)); -} - -NTSTATUS ZwCreateThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID Client, - PCONTEXT ThreadContext, - PINITIAL_TEB InitialTeb, - BOOLEAN CreateSuspended) -{ - PETHREAD Thread; - NTSTATUS Status; - - Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, - DesiredAccess,ObjectAttributes); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - HalInitTaskWithContext(Thread,ThreadContext); - Thread->StartAddress=NULL; - - if (Client!=NULL) - { - *Client=Thread->Cid; - } - - if (!CreateSuspended) - { - DPRINT("Not creating suspended\n"); - PsResumeThread(Thread); - } - DPRINT("Finished PsCreateThread()\n"); - return(STATUS_SUCCESS); -} - -NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID ClientId, - PKSTART_ROUTINE StartRoutine, - PVOID StartContext) -/* - * FUNCTION: Creates a thread which executes in kernel mode - * ARGUMENTS: - * ThreadHandle (OUT) = Caller supplied storage for the returned thread - * handle - * DesiredAccess = Requested access to the thread - * ObjectAttributes = Object attributes (optional) - * ProcessHandle = Handle of process thread will run in - * NULL to use system process - * ClientId (OUT) = Caller supplied storage for the returned client id - * of the thread (optional) - * StartRoutine = Entry point for the thread - * StartContext = Argument supplied to the thread when it begins - * execution - * RETURNS: Success or failure status - */ -{ - PETHREAD Thread; - NTSTATUS Status; - - DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", - ThreadHandle,ProcessHandle); - - Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, - DesiredAccess,ObjectAttributes); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - Thread->StartAddress=StartRoutine; - HalInitTask(Thread,StartRoutine,StartContext); - - if (ClientId!=NULL) - { - *ClientId=Thread->Cid; - } - - PsResumeThread(Thread); - - return(STATUS_SUCCESS); -} - -LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment) -{ - UNIMPLEMENTED; -} - -KPRIORITY KeSetPriorityThread(PKTHREAD Thread, KPRIORITY Priority) -{ - KPRIORITY OldPriority; - OldPriority = Thread->CurrentPriority; - Thread->CurrentPriority = Priority; - - RemoveEntryList(&Thread->Entry); - PsInsertIntoThreadList(Thread->CurrentPriority, - CONTAINING_RECORD(Thread,ETHREAD,Tcb)); - - return(OldPriority); -} - -NTSTATUS STDCALL NtAlertResumeThread(IN HANDLE ThreadHandle, - OUT PULONG SuspendCount) -{ - return(ZwAlertResumeThread(ThreadHandle,SuspendCount)); -} - -NTSTATUS STDCALL ZwAlertResumeThread(IN HANDLE ThreadHandle, - OUT PULONG SuspendCount) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtAlertThread(IN HANDLE ThreadHandle) -{ - return(ZwAlertThread(ThreadHandle)); -} - -NTSTATUS STDCALL ZwAlertThread(IN HANDLE ThreadHandle) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtGetContextThread(IN HANDLE ThreadHandle, - OUT PCONTEXT Context) -{ - return(ZwGetContextThread(ThreadHandle,Context)); -} - -NTSTATUS STDCALL ZwGetContextThread(IN HANDLE ThreadHandle, - OUT PCONTEXT Context) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) -{ - return(ZwOpenThread(ThreadHandle, - DesiredAccess, - ObjectAttributes, - ClientId)); -} - -NTSTATUS STDCALL ZwOpenThread(OUT PHANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtResumeThread(IN HANDLE ThreadHandle, - IN PULONG SuspendCount) -{ - return(ZwResumeThread(ThreadHandle,SuspendCount)); -} - -NTSTATUS STDCALL ZwResumeThread(IN HANDLE ThreadHandle, - IN PULONG SuspendCount) -/* - * FUNCTION: Decrements a thread's resume count - * ARGUMENTS: - * ThreadHandle = Handle to the thread that should be resumed - * ResumeCount = The resulting resume count. - * REMARK: - * A thread is resumed if its suspend count is 0. This procedure maps to - * the win32 ResumeThread function. ( documentation about the the suspend count can be found here aswell ) - * RETURNS: Status - */ -{ - PETHREAD Thread; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - (*SuspendCount) = InterlockedDecrement(&Thread->Tcb.SuspendCount); - if (Thread->Tcb.SuspendCount <= 0) - { - Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE; - } - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtSetContextThread(IN HANDLE ThreadHandle, - IN PCONTEXT Context) -{ - return(ZwSetContextThread(ThreadHandle,Context)); -} - -NTSTATUS STDCALL ZwSetContextThread(IN HANDLE ThreadHandle, - IN PCONTEXT Context) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtSuspendThread(IN HANDLE ThreadHandle, - IN PULONG PreviousSuspendCount) -{ - return(ZwSuspendThread(ThreadHandle,PreviousSuspendCount)); -} - -NTSTATUS STDCALL ZwSuspendThread(IN HANDLE ThreadHandle, - IN PULONG PreviousSuspendCount) -/* - * FUNCTION: Increments a thread's suspend count - * ARGUMENTS: - * ThreadHandle = Handle to the thread that should be resumed - * PreviousSuspendCount = The resulting/previous suspend count. - * REMARK: - * A thread will be suspended if its suspend count is greater than 0. - * This procedure maps to the win32 SuspendThread function. ( - * documentation about the the suspend count can be found here aswell ) - * The suspend count is not increased if it is greater than - * MAXIMUM_SUSPEND_COUNT. - * RETURNS: Status - */ -{ - PETHREAD Thread; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - (*PreviousSuspendCount) = InterlockedIncrement(&Thread->Tcb.SuspendCount); - if (Thread->Tcb.SuspendCount > 0) - { - Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED; - if (Thread == PsGetCurrentThread()) - { - PsDispatchThread(); - } - } - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtContinue(IN PCONTEXT Context, IN CINT IrqLevel) -{ - return(ZwContinue(Context,IrqLevel)); -} - -NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtYieldExecution(VOID) -{ - return(ZwYieldExecution()); -} - -NTSTATUS STDCALL ZwYieldExecution(VOID) -{ - PsDispatchThread(); - return(STATUS_SUCCESS); -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE PsThreadType = NULL; + +#define NR_THREAD_PRIORITY_LEVELS (31) +#define THREAD_PRIORITY_MAX (15) + +static KSPIN_LOCK ThreadListLock = {0,}; + +/* + * PURPOSE: List of threads associated with each priority level + */ +static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS]={{NULL,NULL},}; +static BOOLEAN DoneInitYet = FALSE; +ULONG PiNrThreads = 0; + +static PETHREAD CurrentThread = NULL; + +static ULONG NextThreadUniqueId = 0; + +/* FUNCTIONS ***************************************************************/ + +PKTHREAD KeGetCurrentThread(VOID) +{ + return(&(CurrentThread->Tcb)); +} + +PETHREAD PsGetCurrentThread(VOID) +{ + return((PETHREAD)KeGetCurrentThread()); +} + +static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread) +{ + KIRQL oldlvl; + + DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority, + Thread); + + KeAcquireSpinLock(&ThreadListLock,&oldlvl); + InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority], + &Thread->Tcb.Entry); + KeReleaseSpinLock(&ThreadListLock,oldlvl); +} + +VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext) +{ + NTSTATUS Ret; + + KeReleaseSpinLock(&ThreadListLock,PASSIVE_LEVEL); + Ret = StartRoutine(StartContext); + PsTerminateSystemThread(Ret); + for(;;); +} + +static PETHREAD PsScanThreadList(KPRIORITY Priority) +{ + PLIST_ENTRY current_entry; + PETHREAD current; + PETHREAD oldest = NULL; + ULONG oldest_time = 0; + +// DPRINT("PsScanThreadList(Priority %d)\n",Priority); + + current_entry = PriorityListHead[THREAD_PRIORITY_MAX+Priority].Flink; + while (current_entry != &PriorityListHead[THREAD_PRIORITY_MAX+Priority]) + { + current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.Entry); + #if 0 + if (current->Tcb.ThreadState == THREAD_STATE_TERMINATED && + current != CurrentThread) + { + PsReleaseThread(CurrentThread); + } + #endif + if (current->Tcb.ThreadState == THREAD_STATE_RUNNABLE) + { + if (oldest == NULL || oldest_time > current->Tcb.LastTick) + { + oldest = current; + oldest_time = current->Tcb.LastTick; + } + } + current_entry = current_entry->Flink; + } +// DPRINT("PsScanThreadList() = %x\n",oldest); + return(oldest); +} + +VOID PsDispatchThread(VOID) +{ + KPRIORITY CurrentPriority; + PETHREAD Candidate; + KIRQL irql; + LARGE_INTEGER TickCount; + + KeAcquireSpinLock(&ThreadListLock,&irql); + + if (!DoneInitYet) + { + return; + } + + DPRINT("PsDispatchThread() Current %x\n",CurrentThread); + + if (CurrentThread->Tcb.ThreadState==THREAD_STATE_RUNNING) + { + CurrentThread->Tcb.ThreadState=THREAD_STATE_RUNNABLE; + } + + for (CurrentPriority=THREAD_PRIORITY_TIME_CRITICAL; + CurrentPriority>=THREAD_PRIORITY_IDLE; + CurrentPriority--) + { + Candidate = PsScanThreadList(CurrentPriority); + if (Candidate == CurrentThread) + { +// DbgPrint("Scheduling current thread\n"); + KeQueryTickCount(&TickCount); + CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount); + CurrentThread->Tcb.ThreadState = THREAD_STATE_RUNNING; + KeReleaseSpinLock(&ThreadListLock,irql); + return; + } + if (Candidate != NULL) + { +// DbgPrint("Scheduling %x\n",Candidate); + + Candidate->Tcb.ThreadState = THREAD_STATE_RUNNING; + + KeQueryTickCount(&TickCount); + CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount); + + CurrentThread = Candidate; + + HalTaskSwitch(&CurrentThread->Tcb); + KeReleaseSpinLock(&ThreadListLock,irql); + return; + } + } +} + +NTSTATUS PsInitializeThread(HANDLE ProcessHandle, + PETHREAD* ThreadPtr, + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ThreadAttributes) +{ + ULONG ThreadId; + ULONG ProcessId; + PETHREAD Thread; + NTSTATUS Status; + + PiNrThreads++; + + Thread = ObGenericCreateObject(ThreadHandle, + DesiredAccess, + ThreadAttributes, + PsThreadType); + DPRINT("Thread = %x\n",Thread); + Thread->Tcb.LastTick = 0; + Thread->Tcb.ThreadState=THREAD_STATE_SUSPENDED; + Thread->Tcb.BasePriority=THREAD_PRIORITY_NORMAL; + Thread->Tcb.CurrentPriority=THREAD_PRIORITY_NORMAL; + Thread->Tcb.ApcList=ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY)); + Thread->Tcb.SuspendCount = 1; + if (ProcessHandle!=NULL) + { + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode, + (PVOID*)&Thread->ThreadsProcess, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + } + else + { + Thread->ThreadsProcess=SystemProcess; + ObReferenceObjectByPointer(Thread->ThreadsProcess, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode); + } + ObReferenceObjectByPointer(Thread->ThreadsProcess, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode); + InitializeListHead(Thread->Tcb.ApcList); + InitializeListHead(&(Thread->IrpList)); + Thread->Cid.UniqueThread=InterlockedIncrement(&NextThreadUniqueId); + PsInsertIntoThreadList(Thread->Tcb.CurrentPriority,Thread); + + *ThreadPtr = Thread; + + ObDereferenceObject(Thread->ThreadsProcess); + return(STATUS_SUCCESS); +} + +VOID PsResumeThread(PETHREAD Thread) +{ + DPRINT("PsResumeThread(Thread %x)\n",Thread); + + Thread->Tcb.SuspendCount--; + DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount); + DPRINT("Thread->Tcb.ThreadState %d THREAD_STATE_RUNNING %d\n", + Thread->Tcb.ThreadState,THREAD_STATE_RUNNING); + if (Thread->Tcb.SuspendCount <= 0 && + Thread->Tcb.ThreadState != THREAD_STATE_RUNNING) + { + DPRINT("Setting thread to runnable\n"); + Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE; + } + DPRINT("Finished PsResumeThread()\n"); +} + +VOID PsSuspendThread(PETHREAD Thread) +{ + DPRINT("PsSuspendThread(Thread %x)\n",Thread); + Thread->Tcb.SuspendCount++; + if (Thread->Tcb.SuspendCount > 0) + { + Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED; + if (Thread == CurrentThread) + { + PsDispatchThread(); + } + } +} + +void PsInitThreadManagment(void) +/* + * FUNCTION: Initialize thread managment + */ +{ + PETHREAD FirstThread; + ULONG i; + ANSI_STRING AnsiString; + HANDLE FirstThreadHandle; + + KeInitializeSpinLock(&ThreadListLock); + for (i=0; iTypeName,&AnsiString,TRUE); + + PsThreadType->TotalObjects = 0; + PsThreadType->TotalHandles = 0; + PsThreadType->MaxObjects = 0; + PsThreadType->MaxHandles = 0; + PsThreadType->PagedPoolCharge = 0; + PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD); + PsThreadType->Dump = NULL; + PsThreadType->Open = NULL; + PsThreadType->Close = NULL; + PsThreadType->Delete = NULL; + PsThreadType->Parse = NULL; + PsThreadType->Security = NULL; + PsThreadType->QueryName = NULL; + PsThreadType->OkayToClose = NULL; + + PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle, + THREAD_ALL_ACCESS,NULL); + HalInitFirstTask(FirstThread); + FirstThread->Tcb.ThreadState = THREAD_STATE_RUNNING; + FirstThread->Tcb.SuspendCount = 0; + + DPRINT("FirstThread %x\n",FirstThread); + + CurrentThread = FirstThread; + + DoneInitYet = TRUE; +} + +NTSTATUS NtCreateThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID Client, + PCONTEXT ThreadContext, + PINITIAL_TEB InitialTeb, + BOOLEAN CreateSuspended) +{ + return(ZwCreateThread(ThreadHandle, + DesiredAccess, + ObjectAttributes, + ProcessHandle, + Client, + ThreadContext, + InitialTeb, + CreateSuspended)); +} + +NTSTATUS ZwCreateThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID Client, + PCONTEXT ThreadContext, + PINITIAL_TEB InitialTeb, + BOOLEAN CreateSuspended) +{ + PETHREAD Thread; + NTSTATUS Status; + + DbgPrint("ZwCreateThread(ThreadHandle %x, PCONTEXT %x)\n", + ThreadHandle,ThreadContext); + + Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, + DesiredAccess,ObjectAttributes); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + HalInitTaskWithContext(Thread,ThreadContext); + Thread->StartAddress=NULL; + + if (Client!=NULL) + { + *Client=Thread->Cid; + } + + if (!CreateSuspended) + { + DPRINT("Not creating suspended\n"); + PsResumeThread(Thread); + } + DPRINT("Finished PsCreateThread()\n"); + return(STATUS_SUCCESS); +} + +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext) +/* + * FUNCTION: Creates a thread which executes in kernel mode + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * handle + * DesiredAccess = Requested access to the thread + * ObjectAttributes = Object attributes (optional) + * ProcessHandle = Handle of process thread will run in + * NULL to use system process + * ClientId (OUT) = Caller supplied storage for the returned client id + * of the thread (optional) + * StartRoutine = Entry point for the thread + * StartContext = Argument supplied to the thread when it begins + * execution + * RETURNS: Success or failure status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + + DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", + ThreadHandle,ProcessHandle); + + Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, + DesiredAccess,ObjectAttributes); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + Thread->StartAddress=StartRoutine; + HalInitTask(Thread,StartRoutine,StartContext); + + if (ClientId!=NULL) + { + *ClientId=Thread->Cid; + } + + PsResumeThread(Thread); + + return(STATUS_SUCCESS); +} + +LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment) +{ + UNIMPLEMENTED; +} + +KPRIORITY KeSetPriorityThread(PKTHREAD Thread, KPRIORITY Priority) +{ + KPRIORITY OldPriority; + OldPriority = Thread->CurrentPriority; + Thread->CurrentPriority = Priority; + + RemoveEntryList(&Thread->Entry); + PsInsertIntoThreadList(Thread->CurrentPriority, + CONTAINING_RECORD(Thread,ETHREAD,Tcb)); + + return(OldPriority); +} + +NTSTATUS STDCALL NtAlertResumeThread(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount) +{ + return(ZwAlertResumeThread(ThreadHandle,SuspendCount)); +} + +NTSTATUS STDCALL ZwAlertResumeThread(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtAlertThread(IN HANDLE ThreadHandle) +{ + return(ZwAlertThread(ThreadHandle)); +} + +NTSTATUS STDCALL ZwAlertThread(IN HANDLE ThreadHandle) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtGetContextThread(IN HANDLE ThreadHandle, + OUT PCONTEXT Context) +{ + return(ZwGetContextThread(ThreadHandle,Context)); +} + +NTSTATUS STDCALL ZwGetContextThread(IN HANDLE ThreadHandle, + OUT PCONTEXT Context) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + return(ZwOpenThread(ThreadHandle, + DesiredAccess, + ObjectAttributes, + ClientId)); +} + +NTSTATUS STDCALL ZwOpenThread(OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtResumeThread(IN HANDLE ThreadHandle, + IN PULONG SuspendCount) +{ + return(ZwResumeThread(ThreadHandle,SuspendCount)); +} + +NTSTATUS STDCALL ZwResumeThread(IN HANDLE ThreadHandle, + IN PULONG SuspendCount) +/* + * FUNCTION: Decrements a thread's resume count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * ResumeCount = The resulting resume count. + * REMARK: + * A thread is resumed if its suspend count is 0. This procedure maps to + * the win32 ResumeThread function. ( documentation about the the suspend count can be found here aswell ) + * RETURNS: Status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + (*SuspendCount) = InterlockedDecrement(&Thread->Tcb.SuspendCount); + if (Thread->Tcb.SuspendCount <= 0) + { + Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE; + } + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL NtSetContextThread(IN HANDLE ThreadHandle, + IN PCONTEXT Context) +{ + return(ZwSetContextThread(ThreadHandle,Context)); +} + +NTSTATUS STDCALL ZwSetContextThread(IN HANDLE ThreadHandle, + IN PCONTEXT Context) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtSuspendThread(IN HANDLE ThreadHandle, + IN PULONG PreviousSuspendCount) +{ + return(ZwSuspendThread(ThreadHandle,PreviousSuspendCount)); +} + +NTSTATUS STDCALL ZwSuspendThread(IN HANDLE ThreadHandle, + IN PULONG PreviousSuspendCount) +/* + * FUNCTION: Increments a thread's suspend count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * PreviousSuspendCount = The resulting/previous suspend count. + * REMARK: + * A thread will be suspended if its suspend count is greater than 0. + * This procedure maps to the win32 SuspendThread function. ( + * documentation about the the suspend count can be found here aswell ) + * The suspend count is not increased if it is greater than + * MAXIMUM_SUSPEND_COUNT. + * RETURNS: Status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + (*PreviousSuspendCount) = InterlockedIncrement(&Thread->Tcb.SuspendCount); + if (Thread->Tcb.SuspendCount > 0) + { + Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED; + if (Thread == PsGetCurrentThread()) + { + PsDispatchThread(); + } + } + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL NtContinue(IN PCONTEXT Context, IN CINT IrqLevel) +{ + return(ZwContinue(Context,IrqLevel)); +} + +NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtYieldExecution(VOID) +{ + return(ZwYieldExecution()); +} + +NTSTATUS STDCALL ZwYieldExecution(VOID) +{ + PsDispatchThread(); + return(STATUS_SUCCESS); +} diff --git a/reactos/ntoskrnl/rtl/interlck.asm b/reactos/ntoskrnl/rtl/interlck.asm index 9fca25868ca..6cb2c32cf38 100644 --- a/reactos/ntoskrnl/rtl/interlck.asm +++ b/reactos/ntoskrnl/rtl/interlck.asm @@ -1,48 +1,61 @@ -bits 32 -section .text - -DECLARE_GLOBAL_SYMBOL InterlockedIncrement - mov eax,1 - mov ebx,[esp+4] - xadd [ebx],eax - ret - - -DECLARE_GLOBAL_SYMBOL InterlockedDecrement - mov eax,0xffffffff - mov ebx,[esp+4] - xadd [ebx],eax - dec eax - ret - -DECLARE_GLOBAL_SYMBOL InterlockedExchange - push ebp - mov ebp,esp - - push eax - push ebx - - mov eax,[ebp+12] - mov ebx,[ebp+8] - xchg [ebx],eax - - pop ebx - pop eax - - mov esp,ebp - pop ebp - ret - -DECLARE_GLOBAL_SYMBOL InterlockedExchangeAdd - mov eax,[esp+8] - mov ebx,[esp+4] - xadd [ebx],eax - ret - -DECLARE_GLOBAL_SYMBOL InterlockedCompareExchange - mov eax,[esp+12] - mov edx,[esp+8] - mov ebx,[esp+4] - cmpxchg [ebx],edx - mov eax,edx - ret +bits 32 +section .text + +DECLARE_GLOBAL_SYMBOL InterlockedIncrement + push ebp + mov ebp,esp + + push eax + push ebx + + mov eax,1 + mov ebx,[ebp+8] + xadd [ebx],eax + + pop ebx + pop eax + + mov esp,ebp + pop ebp + + ret + + +DECLARE_GLOBAL_SYMBOL InterlockedDecrement + mov eax,0xffffffff + mov ebx,[esp+4] + xadd [ebx],eax + dec eax + ret + +DECLARE_GLOBAL_SYMBOL InterlockedExchange + push ebp + mov ebp,esp + + push eax + push ebx + + mov eax,[ebp+12] + mov ebx,[ebp+8] + xchg [ebx],eax + + pop ebx + pop eax + + mov esp,ebp + pop ebp + ret + +DECLARE_GLOBAL_SYMBOL InterlockedExchangeAdd + mov eax,[esp+8] + mov ebx,[esp+4] + xadd [ebx],eax + ret + +DECLARE_GLOBAL_SYMBOL InterlockedCompareExchange + mov eax,[esp+12] + mov edx,[esp+8] + mov ebx,[esp+4] + cmpxchg [ebx],edx + mov eax,edx + ret diff --git a/reactos/ntoskrnl/rtl/unicode.c b/reactos/ntoskrnl/rtl/unicode.c index 047ce95005f..0b2bcb8a8bd 100644 --- a/reactos/ntoskrnl/rtl/unicode.c +++ b/reactos/ntoskrnl/rtl/unicode.c @@ -1,534 +1,538 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/rtl/unicode.c - * PURPOSE: String functions - * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) - * UPDATE HISTORY: - * Created 10/08/98 - */ - -#include -#include - -#include - -#include -#include -#include - -#define NDEBUG -#include - -#define Aa_Difference ('A'-'a') - -PUNICODE_STRING RtlDuplicateUnicodeString(PUNICODE_STRING Dest, - PUNICODE_STRING Src) -{ - if (Dest==NULL) - { - Dest=ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING)); - } -} - -VOID RtlUpperString(PSTRING DestinationString, PSTRING SourceString) -{ - UNIMPLEMENTED; -} - -WCHAR wtoupper(WCHAR c) -{ - if((c>='a') && (c<='z')) return c+Aa_Difference; - return c; -} - -WCHAR wtolower(WCHAR c) -{ -// DPRINT("c %c (c-Aa_Difference) %c\n",(char)c,(char)(c-Aa_Difference)); - if((c>='A') && (c<='Z')) return c-Aa_Difference; - return c; -} - -ULONG RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString) -{ - return AnsiString->Length*2; -} - -NTSTATUS RtlAnsiStringToUnicodeString(IN OUT PUNICODE_STRING DestinationString, - IN PANSI_STRING SourceString, IN BOOLEAN AllocateDestinationString) -{ - unsigned long i; - - if(AllocateDestinationString==TRUE) { - DestinationString->Buffer=ExAllocatePool(NonPagedPool, (SourceString->Length+1)*2); - DestinationString->MaximumLength=SourceString->Length; - }; - - DestinationString->Length=SourceString->Length; - memset(DestinationString->Buffer, 0, SourceString->Length*2); - - for (i=0; iLength; i++) - { - *DestinationString->Buffer=*SourceString->Buffer; - - SourceString->Buffer++; - DestinationString->Buffer++; - }; - *DestinationString->Buffer=0; - - SourceString->Buffer-=SourceString->Length; - DestinationString->Buffer-=SourceString->Length; - - return STATUS_SUCCESS; -}; - -NTSTATUS RtlAppendUnicodeStringToString(IN OUT PUNICODE_STRING Destination, - IN PUNICODE_STRING Source) -{ - unsigned long i; - - if(Destination->MaximumLength-Destination->Length-Source->Length<0) - return STATUS_BUFFER_TOO_SMALL; - - Destination->Buffer+=Destination->Length; - for(i=0; iLength; i++) { - *Destination->Buffer=*Source->Buffer; - Destination->Buffer++; - Source->Buffer++; - }; - *Destination->Buffer=0; - Destination->Buffer-=(Destination->Length+Source->Length); - Source->Buffer-=Source->Length; - - Destination->Length+=Source->Length; - return STATUS_SUCCESS; -}; - -NTSTATUS RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination, - IN PWSTR Source) -{ - unsigned long i, slen=wstrlen(Source); - - if(Destination->MaximumLength-Destination->Length-slen<0) - return STATUS_BUFFER_TOO_SMALL; - - Destination->Buffer+=Destination->Length; - for(i=0; iBuffer=*Source; - Destination->Buffer++; - Source++; - }; - *Destination->Buffer=0; - Destination->Buffer-=(Destination->Length+slen); - Source-=slen; - - Destination->Length+=slen; - return STATUS_SUCCESS; -}; - -NTSTATUS RtlCharToInteger(IN PCSZ String, IN ULONG Base, IN OUT PULONG Value) -{ - *Value=simple_strtoul((const char *)String, NULL, Base); -}; - -LONG RtlCompareString(PSTRING String1, PSTRING String2, BOOLEAN CaseInsensitive) -{ - unsigned long i; - char c1, c2; - - if(String1->Length!=String2->Length) return String1->Length-String2->Length; - - for(i=0; iLength; i++) { - if(CaseInsensitive==TRUE) { - c1=toupper(*String1->Buffer); - c2=toupper(*String2->Buffer); - } else { - c1=*String1->Buffer; - c2=*String2->Buffer; - }; - if(c1!=c2) { - String1->Buffer-=i; - String2->Buffer-=i; - return c1-c2; - }; - String1->Buffer++; - String2->Buffer++; - }; - String1->Buffer-=i; - String2->Buffer-=i; - - return 0; -}; - -LONG RtlCompareUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, - BOOLEAN CaseInsensitive) -{ - unsigned long i; - WCHAR wc1, wc2; - - if(String1->Length!=String2->Length) return - String1->Length-String2->Length; - - for(i=0; iLength; i++) { - if(CaseInsensitive==TRUE) { - wc1=wtoupper(*String1->Buffer); - wc2=wtoupper(*String2->Buffer); - } else { - wc1=*String1->Buffer; - wc2=*String2->Buffer; - }; - - if(wc1!=wc2) { - String1->Buffer-=i; - String2->Buffer-=i; - return wc1-wc2; - }; - - String1->Buffer++; - String2->Buffer++; - }; - - String1->Buffer-=i; - String2->Buffer-=i; - - return 0; -}; - -VOID RtlCopyString(IN OUT PSTRING DestinationString, IN PSTRING SourceString) -{ - unsigned long copylen, i; - - if(SourceString==NULL) { - DestinationString->Length=0; - } else { - if(SourceString->LengthMaximumLength) { - copylen=SourceString->Length; - } else { - copylen=DestinationString->MaximumLength; - }; - for(i=0; iBuffer=*SourceString->Buffer; - DestinationString->Buffer++; - SourceString->Buffer++; - }; - *DestinationString->Buffer=0; - DestinationString->Buffer-=copylen; - SourceString->Buffer-=copylen; - }; -}; - -VOID RtlCopyUnicodeString(IN OUT PUNICODE_STRING DestinationString, - IN PUNICODE_STRING SourceString) -{ - unsigned long copylen, i; - - if(SourceString==NULL) { - DestinationString->Length=0; - } else { - if(SourceString->LengthMaximumLength) { - copylen=SourceString->Length; - } else { - copylen=DestinationString->MaximumLength; - }; - for(i=0; iBuffer=*SourceString->Buffer; - DestinationString->Buffer++; - SourceString->Buffer++; - }; - *DestinationString->Buffer=0; - DestinationString->Buffer-=copylen; - SourceString->Buffer-=copylen; - }; -}; - -BOOLEAN RtlEqualString(PSTRING String1, PSTRING String2, BOOLEAN CaseInsensitive) -{ - unsigned long s1l=String1->Length; - unsigned long s2l=String2->Length; - unsigned long i; - char c1, c2; - - if(s1l!=s2l) return FALSE; - - for(i=0; iBuffer; - c2=*String2->Buffer; - - if(CaseInsensitive==TRUE) { - c1=toupper(c1); - c2=toupper(c2); - }; - - if(c1!=c2) { - String1->Buffer-=i; - String2->Buffer-=i; - return FALSE; - }; - - String1->Buffer++; - String2->Buffer++; - }; - - String1->Buffer-=i; - String2->Buffer-=i; - - return TRUE; -}; - -BOOLEAN RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, - BOOLEAN CaseInsensitive) -{ - unsigned long s1l=String1->Length; - unsigned long s2l=String2->Length; - unsigned long i; - char wc1, wc2; - - if(s1l!=s2l) return FALSE; - - for(i=0; iBuffer); - wc2=wtoupper(*String2->Buffer); - } else { - wc1=*String1->Buffer; - wc2=*String2->Buffer; - }; - - if(wc1!=wc2) { - String1->Buffer-=i; - String2->Buffer-=i; - return FALSE; - }; - - String1->Buffer++; - String2->Buffer++; - }; - - String1->Buffer-=i; - String2->Buffer-=i; - - return TRUE; -}; - -VOID RtlFreeAnsiString(IN PANSI_STRING AnsiString) -{ - ExFreePool(AnsiString->Buffer); -}; - -VOID RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString) -{ - ExFreePool(UnicodeString->Buffer); -}; - -VOID RtlInitAnsiString(IN OUT PANSI_STRING DestinationString, - IN PCSZ SourceString) -{ - unsigned long DestSize; - - if(SourceString==NULL) { - DestinationString->Length=0; - DestinationString->MaximumLength=0; - } else { - DestSize=strlen((const char *)SourceString); - DestinationString->Length=DestSize; - DestinationString->MaximumLength=DestSize+1; - }; - DestinationString->Buffer=(PCHAR)SourceString; -}; - -VOID RtlInitString(IN OUT PSTRING DestinationString, - IN PCSZ SourceString) -{ - DestinationString->Length=strlen((char *)SourceString); - DestinationString->MaximumLength=strlen((char *)SourceString)+1; - DestinationString->Buffer=SourceString; -}; - -VOID RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString, - IN PCWSTR SourceString) -{ - unsigned long i, DestSize; - UNICODE_STRING Dest=*DestinationString; - - if(SourceString==NULL) { - DestinationString->Length=0; - DestinationString->MaximumLength=0; - DestinationString->Buffer=NULL; - } else { - DestSize=wstrlen((PWSTR)SourceString); - DestinationString->Length=DestSize; - DestinationString->MaximumLength=DestSize+1; - - DestinationString->Buffer=(PWSTR)SourceString; - }; -}; - -NTSTATUS RtlIntegerToUnicodeString(IN ULONG Value, IN ULONG Base, /* optional */ - IN OUT PUNICODE_STRING String) -{ - char *str; - unsigned long len, i; - - str=ExAllocatePool(NonPagedPool, 1024); - if(Base==16) { - sprintf(str, "%x", Value); - } else - if(Base==8) { - sprintf(str, "%o", Value); - } else - if(Base==2) { - sprintf(str, "%b", Value); - } else { - sprintf(str, "%u", Value); - }; - - len=strlen(str); - if(String->MaximumLengthBuffer=*str; - String->Buffer++; - str++; - }; - *String->Buffer=0; - String->Buffer-=len; - String->Length=len; - str-=len; - ExFreePool(str); - - return STATUS_SUCCESS; -}; - -NTSTATUS RtlUnicodeStringToAnsiString(IN OUT PANSI_STRING DestinationString, - IN PUNICODE_STRING SourceString, - IN BOOLEAN AllocateDestinationString) -{ - unsigned long i; - - if(AllocateDestinationString==TRUE) { - - // Causes excetion 14(0) in _Validate_Free_List - DestinationString->Buffer=ExAllocatePool(NonPagedPool, SourceString->Length+1); - DestinationString->MaximumLength=SourceString->Length+1; - }; - - DestinationString->Length=SourceString->Length; - - for(i=0; iLength; i++) { - *DestinationString->Buffer=*SourceString->Buffer; - DestinationString->Buffer++; - SourceString->Buffer++; - }; - *DestinationString->Buffer=0; - - DestinationString->Buffer-=SourceString->Length; - SourceString->Buffer-=SourceString->Length; - - return STATUS_SUCCESS; -}; - -NTSTATUS RtlUnicodeStringToInteger(IN PUNICODE_STRING String, IN ULONG Base, - OUT PULONG Value) -{ - char *str; - unsigned long i, lenmin=0; - BOOLEAN addneg=FALSE; - - str=ExAllocatePool(NonPagedPool, String->Length+1); - - for(i=0; iLength; i++) { - *str=*String->Buffer; - - if(*str=='b') { Base=2; lenmin++; } else - if(*str=='o') { Base=8; lenmin++; } else - if(*str=='d') { Base=10; lenmin++; } else - if(*str=='x') { Base=16; lenmin++; } else - if(*str=='+') { lenmin++; } else - if(*str=='-') { addneg=TRUE; lenmin++; } else - if((*str>'1') && (Base==2)) { - String->Buffer-=i; - *Value=0; - return STATUS_INVALID_PARAMETER; - } else - if(((*str>'7') || (*str<'0')) && (Base==8)) { - String->Buffer-=i; - *Value=0; - return STATUS_INVALID_PARAMETER; - } else - if(((*str>'9') || (*str<'0')) && (Base==10)) { - String->Buffer-=i; - *Value=0; - return STATUS_INVALID_PARAMETER; - } else - if((((*str>'9') || (*str<'0')) || - ((toupper(*str)>'F') || (toupper(*str)<'A'))) && (Base==16)) - { - String->Buffer-=i; - *Value=0; - return STATUS_INVALID_PARAMETER; - } else - str++; - - String->Buffer++; - }; - - *str=0; - String->Buffer-=String->Length; - str-=(String->Length-lenmin); - - if(addneg==TRUE) { - *Value=simple_strtoul(str, NULL, Base)*-1; - } else - *Value=simple_strtoul(str, NULL, Base); - - ExFreePool(str); -}; - -NTSTATUS RtlUpcaseUnicodeString(IN OUT PUNICODE_STRING DestinationString, - IN PUNICODE_STRING SourceString, - IN BOOLEAN AllocateDestinationString) -{ - unsigned long i; - - if(AllocateDestinationString==TRUE) { - DestinationString->Buffer=ExAllocatePool(NonPagedPool, SourceString->Length*2+1); - DestinationString->Length=SourceString->Length; - DestinationString->MaximumLength=SourceString->Length+1; - }; - - for(i=0; iLength; i++) { - *DestinationString->Buffer=wtoupper(*SourceString->Buffer); - DestinationString->Buffer++; - SourceString->Buffer++; - }; - *DestinationString->Buffer=0; - - DestinationString->Buffer-=SourceString->Length; - SourceString->Buffer-=SourceString->Length; - - return STATUS_SUCCESS; -}; - -VOID RtlUpcaseString(IN OUT PSTRING DestinationString, - IN PSTRING SourceString) -{ - unsigned long i, len; - - if(SourceString->Length>DestinationString->MaximumLength) { - len=DestinationString->MaximumLength; - } else { - len=SourceString->Length; - }; - - for(i=0; iBuffer=toupper(*SourceString->Buffer); - DestinationString->Buffer++; - SourceString->Buffer++; - }; - *DestinationString->Buffer=0; - - DestinationString->Buffer-=len; - SourceString->Buffer-=len; -} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/unicode.c + * PURPOSE: String functions + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * UPDATE HISTORY: + * Created 10/08/98 + */ + +#include +#include + +#include + +#include +#include +#include + +#define NDEBUG +#include + +#define Aa_Difference ('A'-'a') + +PUNICODE_STRING RtlDuplicateUnicodeString(PUNICODE_STRING Dest, + PUNICODE_STRING Src) +{ + if (Dest==NULL) + { + Dest=ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING)); + } +} + +VOID RtlUpperString(PSTRING DestinationString, PSTRING SourceString) +{ + UNIMPLEMENTED; +} + +WCHAR wtoupper(WCHAR c) +{ + if((c>='a') && (c<='z')) return c+Aa_Difference; + return c; +} + +WCHAR wtolower(WCHAR c) +{ +// DPRINT("c %c (c-Aa_Difference) %c\n",(char)c,(char)(c-Aa_Difference)); + if((c>='A') && (c<='Z')) return c-Aa_Difference; + return c; +} + +ULONG RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString) +{ + return AnsiString->Length*2; +} + +NTSTATUS RtlAnsiStringToUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PANSI_STRING SourceString, IN BOOLEAN AllocateDestinationString) +{ + unsigned long i; + + if(AllocateDestinationString==TRUE) { + DestinationString->Buffer=ExAllocatePool(NonPagedPool, (SourceString->Length+1)*2); + DestinationString->MaximumLength=SourceString->Length; + }; + + DestinationString->Length=SourceString->Length; + memset(DestinationString->Buffer, 0, SourceString->Length*2); + + for (i=0; iLength; i++) + { + *DestinationString->Buffer=*SourceString->Buffer; + + SourceString->Buffer++; + DestinationString->Buffer++; + }; + *DestinationString->Buffer=0; + + SourceString->Buffer-=SourceString->Length; + DestinationString->Buffer-=SourceString->Length; + + return STATUS_SUCCESS; +}; + +NTSTATUS RtlAppendUnicodeStringToString(IN OUT PUNICODE_STRING Destination, + IN PUNICODE_STRING Source) +{ + unsigned long i; + + if(Destination->MaximumLength-Destination->Length-Source->Length<0) + return STATUS_BUFFER_TOO_SMALL; + + Destination->Buffer+=Destination->Length; + for(i=0; iLength; i++) { + *Destination->Buffer=*Source->Buffer; + Destination->Buffer++; + Source->Buffer++; + }; + *Destination->Buffer=0; + Destination->Buffer-=(Destination->Length+Source->Length); + Source->Buffer-=Source->Length; + + Destination->Length+=Source->Length; + return STATUS_SUCCESS; +}; + +NTSTATUS RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination, + IN PWSTR Source) +{ + unsigned long i, slen=wstrlen(Source); + + if(Destination->MaximumLength-Destination->Length-slen<0) + return STATUS_BUFFER_TOO_SMALL; + + Destination->Buffer+=Destination->Length; + for(i=0; iBuffer=*Source; + Destination->Buffer++; + Source++; + }; + *Destination->Buffer=0; + Destination->Buffer-=(Destination->Length+slen); + Source-=slen; + + Destination->Length+=slen; + return STATUS_SUCCESS; +}; + +NTSTATUS RtlCharToInteger(IN PCSZ String, IN ULONG Base, IN OUT PULONG Value) +{ + *Value=simple_strtoul((const char *)String, NULL, Base); +}; + +LONG RtlCompareString(PSTRING String1, PSTRING String2, BOOLEAN CaseInsensitive) +{ + unsigned long i; + char c1, c2; + + if(String1->Length!=String2->Length) return String1->Length-String2->Length; + + for(i=0; iLength; i++) { + if(CaseInsensitive==TRUE) { + c1=toupper(*String1->Buffer); + c2=toupper(*String2->Buffer); + } else { + c1=*String1->Buffer; + c2=*String2->Buffer; + }; + if(c1!=c2) { + String1->Buffer-=i; + String2->Buffer-=i; + return c1-c2; + }; + String1->Buffer++; + String2->Buffer++; + }; + String1->Buffer-=i; + String2->Buffer-=i; + + return 0; +}; + +LONG RtlCompareUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, + BOOLEAN CaseInsensitive) +{ + unsigned long i; + WCHAR wc1, wc2; + + if(String1->Length!=String2->Length) return + String1->Length-String2->Length; + + for(i=0; iLength; i++) { + if(CaseInsensitive==TRUE) { + wc1=wtoupper(*String1->Buffer); + wc2=wtoupper(*String2->Buffer); + } else { + wc1=*String1->Buffer; + wc2=*String2->Buffer; + }; + + if(wc1!=wc2) { + String1->Buffer-=i; + String2->Buffer-=i; + return wc1-wc2; + }; + + String1->Buffer++; + String2->Buffer++; + }; + + String1->Buffer-=i; + String2->Buffer-=i; + + return 0; +}; + +VOID RtlCopyString(IN OUT PSTRING DestinationString, IN PSTRING SourceString) +{ + unsigned long copylen, i; + + if(SourceString==NULL) { + DestinationString->Length=0; + } else { + if(SourceString->LengthMaximumLength) { + copylen=SourceString->Length; + } else { + copylen=DestinationString->MaximumLength; + }; + for(i=0; iBuffer=*SourceString->Buffer; + DestinationString->Buffer++; + SourceString->Buffer++; + }; + *DestinationString->Buffer=0; + DestinationString->Buffer-=copylen; + SourceString->Buffer-=copylen; + }; +}; + +VOID RtlCopyUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString) +{ + unsigned long copylen, i; + + if(SourceString==NULL) + { + DestinationString->Length=0; + } + else + { + copylen = min(DestinationString->MaximumLength, + SourceString->Length); + for(i=0; iBuffer=*SourceString->Buffer; + DestinationString->Buffer++; + SourceString->Buffer++; + } + *DestinationString->Buffer=0; + DestinationString->Buffer-=copylen; + SourceString->Buffer-=copylen; + } +} + +BOOLEAN RtlEqualString(PSTRING String1, PSTRING String2, BOOLEAN CaseInsensitive) +{ + unsigned long s1l=String1->Length; + unsigned long s2l=String2->Length; + unsigned long i; + char c1, c2; + + if(s1l!=s2l) return FALSE; + + for(i=0; iBuffer; + c2=*String2->Buffer; + + if(CaseInsensitive==TRUE) { + c1=toupper(c1); + c2=toupper(c2); + }; + + if(c1!=c2) { + String1->Buffer-=i; + String2->Buffer-=i; + return FALSE; + }; + + String1->Buffer++; + String2->Buffer++; + }; + + String1->Buffer-=i; + String2->Buffer-=i; + + return TRUE; +}; + +BOOLEAN RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, + BOOLEAN CaseInsensitive) +{ + unsigned long s1l=String1->Length; + unsigned long s2l=String2->Length; + unsigned long i; + char wc1, wc2; + + if(s1l!=s2l) return FALSE; + + for(i=0; iBuffer); + wc2=wtoupper(*String2->Buffer); + } else { + wc1=*String1->Buffer; + wc2=*String2->Buffer; + }; + + if(wc1!=wc2) { + String1->Buffer-=i; + String2->Buffer-=i; + return FALSE; + }; + + String1->Buffer++; + String2->Buffer++; + }; + + String1->Buffer-=i; + String2->Buffer-=i; + + return TRUE; +}; + +VOID RtlFreeAnsiString(IN PANSI_STRING AnsiString) +{ + ExFreePool(AnsiString->Buffer); +}; + +VOID RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString) +{ + ExFreePool(UnicodeString->Buffer); +}; + +VOID RtlInitAnsiString(IN OUT PANSI_STRING DestinationString, + IN PCSZ SourceString) +{ + unsigned long DestSize; + + if(SourceString==NULL) { + DestinationString->Length=0; + DestinationString->MaximumLength=0; + } else { + DestSize=strlen((const char *)SourceString); + DestinationString->Length=DestSize; + DestinationString->MaximumLength=DestSize+1; + }; + DestinationString->Buffer=(PCHAR)SourceString; +}; + +VOID RtlInitString(IN OUT PSTRING DestinationString, + IN PCSZ SourceString) +{ + DestinationString->Length=strlen((char *)SourceString); + DestinationString->MaximumLength=strlen((char *)SourceString)+1; + DestinationString->Buffer=SourceString; +}; + +VOID RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PCWSTR SourceString) +{ + unsigned long i, DestSize; + + DPRINT("RtlInitUnicodeString(DestinationString %x, " + "SourceString %x)\n",DestinationString,SourceString); + + if (SourceString==NULL) + { + DestinationString->Length=0; + DestinationString->MaximumLength=0; + DestinationString->Buffer=NULL; + } + else + { + DestSize=wstrlen((PWSTR)SourceString); + DestinationString->Length=DestSize; + DestinationString->MaximumLength=DestSize+1; + DestinationString->Buffer=(PWSTR)SourceString; + } +} + +NTSTATUS RtlIntegerToUnicodeString(IN ULONG Value, IN ULONG Base, /* optional */ + IN OUT PUNICODE_STRING String) +{ + char *str; + unsigned long len, i; + + str=ExAllocatePool(NonPagedPool, 1024); + if(Base==16) { + sprintf(str, "%x", Value); + } else + if(Base==8) { + sprintf(str, "%o", Value); + } else + if(Base==2) { + sprintf(str, "%b", Value); + } else { + sprintf(str, "%u", Value); + }; + + len=strlen(str); + if(String->MaximumLengthBuffer=*str; + String->Buffer++; + str++; + }; + *String->Buffer=0; + String->Buffer-=len; + String->Length=len; + str-=len; + ExFreePool(str); + + return STATUS_SUCCESS; +}; + +NTSTATUS RtlUnicodeStringToAnsiString(IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + unsigned long i; + + if(AllocateDestinationString==TRUE) { + + // Causes excetion 14(0) in _Validate_Free_List + DestinationString->Buffer=ExAllocatePool(NonPagedPool, SourceString->Length+1); + DestinationString->MaximumLength=SourceString->Length+1; + }; + + DestinationString->Length=SourceString->Length; + + for(i=0; iLength; i++) { + *DestinationString->Buffer=*SourceString->Buffer; + DestinationString->Buffer++; + SourceString->Buffer++; + }; + *DestinationString->Buffer=0; + + DestinationString->Buffer-=SourceString->Length; + SourceString->Buffer-=SourceString->Length; + + return STATUS_SUCCESS; +}; + +NTSTATUS RtlUnicodeStringToInteger(IN PUNICODE_STRING String, IN ULONG Base, + OUT PULONG Value) +{ + char *str; + unsigned long i, lenmin=0; + BOOLEAN addneg=FALSE; + + str=ExAllocatePool(NonPagedPool, String->Length+1); + + for(i=0; iLength; i++) { + *str=*String->Buffer; + + if(*str=='b') { Base=2; lenmin++; } else + if(*str=='o') { Base=8; lenmin++; } else + if(*str=='d') { Base=10; lenmin++; } else + if(*str=='x') { Base=16; lenmin++; } else + if(*str=='+') { lenmin++; } else + if(*str=='-') { addneg=TRUE; lenmin++; } else + if((*str>'1') && (Base==2)) { + String->Buffer-=i; + *Value=0; + return STATUS_INVALID_PARAMETER; + } else + if(((*str>'7') || (*str<'0')) && (Base==8)) { + String->Buffer-=i; + *Value=0; + return STATUS_INVALID_PARAMETER; + } else + if(((*str>'9') || (*str<'0')) && (Base==10)) { + String->Buffer-=i; + *Value=0; + return STATUS_INVALID_PARAMETER; + } else + if((((*str>'9') || (*str<'0')) || + ((toupper(*str)>'F') || (toupper(*str)<'A'))) && (Base==16)) + { + String->Buffer-=i; + *Value=0; + return STATUS_INVALID_PARAMETER; + } else + str++; + + String->Buffer++; + }; + + *str=0; + String->Buffer-=String->Length; + str-=(String->Length-lenmin); + + if(addneg==TRUE) { + *Value=simple_strtoul(str, NULL, Base)*-1; + } else + *Value=simple_strtoul(str, NULL, Base); + + ExFreePool(str); +}; + +NTSTATUS RtlUpcaseUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + unsigned long i; + + if(AllocateDestinationString==TRUE) { + DestinationString->Buffer=ExAllocatePool(NonPagedPool, SourceString->Length*2+1); + DestinationString->Length=SourceString->Length; + DestinationString->MaximumLength=SourceString->Length+1; + }; + + for(i=0; iLength; i++) { + *DestinationString->Buffer=wtoupper(*SourceString->Buffer); + DestinationString->Buffer++; + SourceString->Buffer++; + }; + *DestinationString->Buffer=0; + + DestinationString->Buffer-=SourceString->Length; + SourceString->Buffer-=SourceString->Length; + + return STATUS_SUCCESS; +}; + +VOID RtlUpcaseString(IN OUT PSTRING DestinationString, + IN PSTRING SourceString) +{ + unsigned long i, len; + + if(SourceString->Length>DestinationString->MaximumLength) { + len=DestinationString->MaximumLength; + } else { + len=SourceString->Length; + }; + + for(i=0; iBuffer=toupper(*SourceString->Buffer); + DestinationString->Buffer++; + SourceString->Buffer++; + }; + *DestinationString->Buffer=0; + + DestinationString->Buffer-=len; + SourceString->Buffer-=len; +} diff --git a/reactos/ntoskrnl/tst/test.c b/reactos/ntoskrnl/tst/test.c index 0721b84ea72..481daac4e9d 100644 --- a/reactos/ntoskrnl/tst/test.c +++ b/reactos/ntoskrnl/tst/test.c @@ -129,7 +129,7 @@ VOID ExExecuteShell(VOID) BaseAddress = (PVOID)0x10000; LARGE_INTEGER_QUAD_PART(SectionOffset) = 0; - Size = 0x10000; + Size = 0x20000; ZwMapViewOfSection(SectionHandle, ShellHandle, &BaseAddress,