From d378c68f5a9bb25c9e671dacd482d2e25d211df3 Mon Sep 17 00:00:00 2001 From: short <> Date: Thu, 7 Nov 2002 12:04:04 +0000 Subject: [PATCH] update for HEAD-2002110701 --- include/ddk/fsfuncs.h | 15 ++ include/ddk/fstypes.h | 17 ++ include/ddk/iodef.h | 8 + include/ddk/iotypes.h | 8 + include/ntos/heap.h | 2 +- lib/kernel32/file/curdir.c | 7 - lib/kernel32/file/file.c | 76 +++++++- lib/kernel32/file/lfile.c | 6 +- lib/kernel32/process/create.c | 106 +++++------ lib/msvcrt/process/process.c | 106 +++++++++-- lib/user32/windows/bitmap.c | 2 +- lib/user32/windows/defwnd.c | 2 +- lib/user32/windows/prop.c | 2 +- loaders/boot/boot.asm | 4 +- loaders/boot/boot.mak | 4 +- loaders/boot/bootbk.asm | 4 +- ntoskrnl/io/create.c | 3 + ntoskrnl/io/iomgr.c | 47 +++-- ntoskrnl/ldr/loader.c | 2 +- ntoskrnl/lpc/connect.c | 16 +- ntoskrnl/mm/anonmem.c | 13 +- ntoskrnl/mm/cont.c | 4 + ntoskrnl/mm/i386/page.c | 402 ++++++++++++++++++++++++++---------------- ntoskrnl/mm/iospace.c | 14 +- ntoskrnl/mm/kmap.c | 123 +++++-------- ntoskrnl/mm/marea.c | 15 +- ntoskrnl/mm/mdl.c | 61 ++++--- ntoskrnl/mm/ncache.c | 4 +- ntoskrnl/mm/npool.c | 309 +++++++++++++++++++------------- ntoskrnl/mm/rmap.c | 4 +- ntoskrnl/mm/section.c | 128 ++++++++++---- ntoskrnl/ob/object.c | 7 +- ntoskrnl/rtl/bitmap.c | 2 +- 33 files changed, 968 insertions(+), 555 deletions(-) diff --git a/include/ddk/fsfuncs.h b/include/ddk/fsfuncs.h index 6f03dd3..06ce05f 100644 --- a/include/ddk/fsfuncs.h +++ b/include/ddk/fsfuncs.h @@ -3,6 +3,21 @@ /* $Id$ */ #define FlagOn(x,f) ((x) & (f)) +VOID +STDCALL +FsRtlFreeFileLock( + IN PFILE_LOCK FileLock + ); + +PFILE_LOCK +STDCALL +FsRtlAllocateFileLock ( + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL + ); + +#define FsRtlAreThereCurrentFileLocks(FL) (((FL)->FastIoIsQuestionable)) + BOOLEAN STDCALL FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, diff --git a/include/ddk/fstypes.h b/include/ddk/fstypes.h index 03a6401..8b77390 100644 --- a/include/ddk/fstypes.h +++ b/include/ddk/fstypes.h @@ -14,6 +14,23 @@ typedef struct _FILE_LOCK_INFO { LARGE_INTEGER EndingByte; } FILE_LOCK_INFO, *PFILE_LOCK_INFO; +typedef struct _FILE_LOCK_TOC { + KSPIN_LOCK SpinLock; + LIST_ENTRY GrantedListHead; + LIST_ENTRY PendingListHead; +} FILE_LOCK_TOC, *PFILE_LOCK_TOC; + +typedef struct _FILE_LOCK_GRANTED { + LIST_ENTRY ListEntry; + FILE_LOCK_INFO Lock; +} FILE_LOCK_GRANTED, *PFILE_LOCK_GRANTED; + +typedef struct _FILE_LOCK_PENDING { + LIST_ENTRY ListEntry; + PIRP Irp; + PVOID Context; +} FILE_LOCK_PENDING, *PFILE_LOCK_PENDING; + // raw internal file lock struct returned from FsRtlGetNextFileLock typedef struct _FILE_SHARED_LOCK_ENTRY { PVOID Unknown1; diff --git a/include/ddk/iodef.h b/include/ddk/iodef.h index 4d199cd..4d0b4e9 100644 --- a/include/ddk/iodef.h +++ b/include/ddk/iodef.h @@ -249,6 +249,14 @@ enum #define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL /* + * Minor function numbers for IRP_MJ_LOCK_CONTROL + */ +#define IRP_MN_LOCK 0x01 +#define IRP_MN_UNLOCK_SINGLE 0x02 +#define IRP_MN_UNLOCK_ALL 0x03 +#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 + +/* * Minor function numbers for IRP_MJ_FILE_SYSTEM_CONTROL */ #define IRP_MN_USER_FS_REQUEST 0x00 diff --git a/include/ddk/iotypes.h b/include/ddk/iotypes.h index d04fd7f..3d6b27a 100644 --- a/include/ddk/iotypes.h +++ b/include/ddk/iotypes.h @@ -432,6 +432,14 @@ typedef struct __attribute__((packed)) _IO_STACK_LOCATION struct _SCSI_REQUEST_BLOCK *Srb; } Scsi; + //byte range file locking + struct + { + PLARGE_INTEGER Length; + ULONG Key; + LARGE_INTEGER ByteOffset; + } LockControl; + /* Paramters for other calls */ struct { diff --git a/include/ntos/heap.h b/include/ntos/heap.h index 5efac19..391d638 100644 --- a/include/ntos/heap.h +++ b/include/ntos/heap.h @@ -18,7 +18,7 @@ #define HEAP_NO_SERIALIZE (1) #define HEAP_ZERO_MEMORY (8) #define HEAP_REALLOC_IN_PLACE_ONLY (16) -#define HEAP_GROWABLE (32) +#define HEAP_GROWABLE (2) #define HEAP_NO_VALLOC (64) #endif /* __INCLUDE_HEAP_H */ diff --git a/lib/kernel32/file/curdir.c b/lib/kernel32/file/curdir.c index 85caf3f..31b64a2 100644 --- a/lib/kernel32/file/curdir.c +++ b/lib/kernel32/file/curdir.c @@ -324,12 +324,8 @@ GetWindowsDirectoryA ( Length = RtlUnicodeStringToAnsiSize (&WindowsDirectory); //len of ansi str incl. nullchar - printf("windirlen incl term %i\n", Length); - if (uSize >= Length){ - printf("ok: enoug space\n"); - String.Length = 0; String.MaximumLength = uSize; String.Buffer = lpBuffer; @@ -347,12 +343,9 @@ GetWindowsDirectoryA ( if (!NT_SUCCESS(Status)) return 0; - printf("good: ret chars %i\n",Length-1); - printf("dir: %s\n",lpBuffer); return Length-1; //good: ret chars excl. nullchar } - printf("bad: ret chars needed %i\n",Length); return Length; //bad: ret space needed incl. nullchar } diff --git a/lib/kernel32/file/file.c b/lib/kernel32/file/file.c index e4c7163..7d0e41d 100644 --- a/lib/kernel32/file/file.c +++ b/lib/kernel32/file/file.c @@ -259,15 +259,18 @@ GetFileType(HANDLE hFile) switch ((ULONG)hFile) { case STD_INPUT_HANDLE: - hFile = NtCurrentPeb()->ProcessParameters->hStdInput; + hFile = NtCurrentPeb()->ProcessParameters->hStdInput; + break; case STD_OUTPUT_HANDLE: - hFile = NtCurrentPeb()->ProcessParameters->hStdOutput; + hFile = NtCurrentPeb()->ProcessParameters->hStdOutput; + break; case STD_ERROR_HANDLE: - hFile = NtCurrentPeb()->ProcessParameters->hStdError; + hFile = NtCurrentPeb()->ProcessParameters->hStdError; + break; } @@ -800,12 +803,73 @@ SetFileTime(HANDLE hFile, } +/* +The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set. +*/ WINBOOL STDCALL SetEndOfFile(HANDLE hFile) { - int x = -1; - DWORD Num; - return WriteFile(hFile,&x,1,&Num,NULL); + IO_STATUS_BLOCK IoStatusBlock; + FILE_END_OF_FILE_INFORMATION EndOfFileInfo; + FILE_ALLOCATION_INFORMATION FileAllocationInfo; + FILE_POSITION_INFORMATION FilePosInfo; + NTSTATUS Status; + + //get current position + Status = NtQueryInformationFile( + hFile, + &IoStatusBlock, + &FilePosInfo, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation + ); + + if (!NT_SUCCESS(Status)){ + SetLastErrorByStatus(Status); + return FALSE; + } + + EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart; + + /* + NOTE: + This call is not supposed to free up any space after the eof marker + if the file gets truncated. We have to deallocate the space explicitly afterwards. + But...most file systems dispatch both FileEndOfFileInformation + and FileAllocationInformation as they were the same command. + + */ + Status = NtSetInformationFile( + hFile, + &IoStatusBlock, //out + &EndOfFileInfo, + sizeof(FILE_END_OF_FILE_INFORMATION), + FileEndOfFileInformation + ); + + if (!NT_SUCCESS(Status)){ + SetLastErrorByStatus(Status); + return FALSE; + } + + FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart; + + + Status = NtSetInformationFile( + hFile, + &IoStatusBlock, //out + &FileAllocationInfo, + sizeof(FILE_ALLOCATION_INFORMATION), + FileAllocationInformation + ); + + if (!NT_SUCCESS(Status)){ + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; + } /* EOF */ diff --git a/lib/kernel32/file/lfile.c b/lib/kernel32/file/lfile.c index 6bbec15..4dd4acd 100644 --- a/lib/kernel32/file/lfile.c +++ b/lib/kernel32/file/lfile.c @@ -156,11 +156,11 @@ _lcreat ( DWORD FileAttributes = 0; - if ( iAttribute == 1 ) + if ( iAttribute == 0 ) FileAttributes |= FILE_ATTRIBUTE_NORMAL; - else if ( iAttribute == 2 ) + else if ( iAttribute == 1 ) FileAttributes |= FILE_ATTRIBUTE_READONLY; - else if ( iAttribute == 3 ) + else if ( iAttribute == 2 ) FileAttributes |= FILE_ATTRIBUTE_HIDDEN; else if ( iAttribute == 4 ) FileAttributes |= FILE_ATTRIBUTE_SYSTEM; diff --git a/lib/kernel32/process/create.c b/lib/kernel32/process/create.c index 9abb98f..34748ee 100644 --- a/lib/kernel32/process/create.c +++ b/lib/kernel32/process/create.c @@ -167,20 +167,22 @@ CreateProcessA (LPCSTR lpApplicationName, return Result; } +struct _CONTEXT; +struct __EXCEPTION_RECORD; + +static +EXCEPTION_DISPOSITION +__cdecl +_except_handler( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext ) +{ + DPRINT("Process terminated abnormally...\n"); -static -EXCEPTION_DISPOSITION -__cdecl -_except_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void * EstablisherFrame, - struct _CONTEXT *ContextRecord, - void * DispatcherContext ) -{ - DPRINT("Process terminated abnormally...\n"); - - if (/* FIXME: */ TRUE) /* Not a service */ - { + if (/* FIXME: */ TRUE) /* Not a service */ + { ExitProcess(0); } else @@ -190,17 +192,17 @@ _except_handler( /* We should not get to here */ return ExceptionContinueSearch; -} +} VOID STDCALL BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress, - DWORD lpParameter) + DWORD lpParameter) { UINT uExitCode = 0; __try1(_except_handler) { - uExitCode = (lpStartAddress)(lpParameter); + uExitCode = (lpStartAddress)((PVOID)lpParameter); } __except1 { } @@ -520,7 +522,7 @@ KlInitPeb (HANDLE ProcessHandle, /* create the PPB */ PpbBase = NULL; - PpbSize = Ppb->AllocationSize; + PpbSize = Ppb->AllocationSize; Status = NtAllocateVirtualMemory(ProcessHandle, &PpbBase, 0, @@ -536,7 +538,7 @@ KlInitPeb (HANDLE ProcessHandle, NtWriteVirtualMemory(ProcessHandle, PpbBase, Ppb, - Ppb->AllocationSize, + Ppb->AllocationSize, &BytesWritten); /* write pointer to environment */ @@ -658,7 +660,7 @@ CreateProcessW(LPCWSTR lpApplicationName, { s = TempApplicationNameW; } - s = wcsrchr(TempApplicationNameW, L'.'); + s = wcsrchr(s, L'.'); if (s == NULL) wcscat(TempApplicationNameW, L".exe"); } @@ -798,23 +800,23 @@ CreateProcessW(LPCWSTR lpApplicationName, /* * Translate some handles for the new process */ - if (Ppb->CurrentDirectoryHandle) + if (Ppb->CurrentDirectoryHandle) { Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->CurrentDirectoryHandle, + Ppb->CurrentDirectoryHandle, hProcess, - &Ppb->CurrentDirectoryHandle, + &Ppb->CurrentDirectoryHandle, 0, TRUE, DUPLICATE_SAME_ACCESS); } - if (Ppb->hConsole) + if (Ppb->hConsole) { Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hConsole, + Ppb->hConsole, hProcess, - &Ppb->hConsole, + &Ppb->hConsole, 0, TRUE, DUPLICATE_SAME_ACCESS); @@ -862,31 +864,31 @@ CreateProcessW(LPCWSTR lpApplicationName, } // Set the child console handles - Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; - Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; - Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError; + Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; + Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; + Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError; if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES)) { if (lpStartupInfo->hStdInput) - Ppb->hStdInput = lpStartupInfo->hStdInput; + Ppb->hStdInput = lpStartupInfo->hStdInput; if (lpStartupInfo->hStdOutput) - Ppb->hStdOutput = lpStartupInfo->hStdOutput; + Ppb->hStdOutput = lpStartupInfo->hStdOutput; if (lpStartupInfo->hStdError) - Ppb->hStdError = lpStartupInfo->hStdError; + Ppb->hStdError = lpStartupInfo->hStdError; } - if (IsConsoleHandle(Ppb->hStdInput)) + if (IsConsoleHandle(Ppb->hStdInput)) { - Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; + Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; } else { DPRINT("Duplicate input handle\n"); Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdInput, + Ppb->hStdInput, hProcess, - &Ppb->hStdInput, + &Ppb->hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); @@ -896,17 +898,17 @@ CreateProcessW(LPCWSTR lpApplicationName, } } - if (IsConsoleHandle(Ppb->hStdOutput)) + if (IsConsoleHandle(Ppb->hStdOutput)) { - Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; + Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; } else { DPRINT("Duplicate output handle\n"); Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdOutput, + Ppb->hStdOutput, hProcess, - &Ppb->hStdOutput, + &Ppb->hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); @@ -915,17 +917,17 @@ CreateProcessW(LPCWSTR lpApplicationName, DPRINT("NtDuplicateObject failed, status %x\n", Status); } } - if (IsConsoleHandle(Ppb->hStdError)) + if (IsConsoleHandle(Ppb->hStdError)) { - Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle; + Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle; } else { DPRINT("Duplicate error handle\n"); Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdError, + Ppb->hStdError, hProcess, - &Ppb->hStdError, + &Ppb->hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); @@ -940,20 +942,20 @@ CreateProcessW(LPCWSTR lpApplicationName, */ if (lpStartupInfo) { - Ppb->dwFlags = lpStartupInfo->dwFlags; - if (Ppb->dwFlags & STARTF_USESHOWWINDOW) + Ppb->dwFlags = lpStartupInfo->dwFlags; + if (Ppb->dwFlags & STARTF_USESHOWWINDOW) { - Ppb->wShowWindow = lpStartupInfo->wShowWindow; + Ppb->wShowWindow = lpStartupInfo->wShowWindow; } else { - Ppb->wShowWindow = SW_SHOWDEFAULT; + Ppb->wShowWindow = SW_SHOWDEFAULT; } - Ppb->dwX = lpStartupInfo->dwX; - Ppb->dwY = lpStartupInfo->dwY; - Ppb->dwXSize = lpStartupInfo->dwXSize; - Ppb->dwYSize = lpStartupInfo->dwYSize; - Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute; + Ppb->dwX = lpStartupInfo->dwX; + Ppb->dwY = lpStartupInfo->dwY; + Ppb->dwXSize = lpStartupInfo->dwXSize; + Ppb->dwYSize = lpStartupInfo->dwYSize; + Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute; } else { diff --git a/lib/msvcrt/process/process.c b/lib/msvcrt/process/process.c index d9cdc52..7e4f85f 100644 --- a/lib/msvcrt/process/process.c +++ b/lib/msvcrt/process/process.c @@ -1,15 +1,97 @@ /* $Id$ */ -#include #include #include -#include +#include #include +#include #define NDEBUG #include extern int maxfno; +char const* ext[] = +{ + "", + ".bat", + ".cmd", + ".com", + ".exe" +}; + +const char* find_exec(const char* path, char* rpath) +{ + char *rp; + const char *rd; + int i, found = 0; + + DPRINT("find_exec('%s', %x)\n", path, rpath); + + if (path == NULL) + { + return NULL; + } + if (strlen(path) > FILENAME_MAX - 1) + { + return path; + } + /* copy path in rpath */ + for (rd = path, rp = rpath; *rd; *rp++ = *rd++); + *rp = 0; + /* try first with the name as is */ + for (i = 0; i < sizeof(ext) / sizeof(*ext); i++) + { + strcpy(rp, ext[i]); + + DPRINT("trying '%s'\n", rpath); + + if (_access(rpath, F_OK) == 0 && _access(rpath, D_OK) != 0) + { + found = 1; + break; + } + } + if (!found) + { + char* env = getenv("PATH"); + if (env) + { + char* ep = env; + while (*ep && !found) + { + if (*ep == ';') ep++; + rp=rpath; + for (; *ep && (*ep != ';'); *rp++ = *ep++); + if (rp > rpath) + { + rp--; + if (*rp != '/' && *rp != '\\') + { + *++rp = '\\'; + } + rp++; + } + for (rd=path; *rd; *rp++ = *rd++); + for (i = 0; i < sizeof(ext) / sizeof(*ext); i++) + { + strcpy(rp, ext[i]); + + DPRINT("trying '%s'\n", rpath); + + if (_access(rpath, F_OK) == 0 && _access(rpath, D_OK) != 0) + { + found = 1; + break; + } + } + } + free(env); + } + } + + return found ? rpath : path; +} + static char* argvtos(char* const* argv, char delim) { @@ -300,9 +382,7 @@ int _spawnvp(int mode, const char* cmdname, char* const* argv) DPRINT("_spawnvp('%s')\n", cmdname); - _searchenv(cmdname, "PATH", pathname); - - return _spawnv(mode, pathname[0] ? pathname : cmdname, argv); + return _spawnv(mode, find_exec(cmdname, pathname), argv); } int _spawnlpe(int mode, const char* cmdname, const char* arg0, .../*, NULL, const char* const* envp*/) @@ -316,8 +396,6 @@ int _spawnlpe(int mode, const char* cmdname, const char* arg0, .../*, NULL, cons DPRINT("_spawnlpe('%s')\n", cmdname); - _searchenv(cmdname, "PATH", pathname); - va_start(argp, arg0); args = valisttos(arg0, argp, ' '); do @@ -328,7 +406,7 @@ int _spawnlpe(int mode, const char* cmdname, const char* arg0, .../*, NULL, cons envs = argvtos(ptr, 0); if (args) { - ret = do_spawn(mode, pathname[0] ? pathname : cmdname, args, envs); + ret = do_spawn(mode, find_exec(cmdname, pathname), args, envs); free(args); } if (envs) @@ -344,9 +422,7 @@ int _spawnvpe(int mode, const char* cmdname, char* const* argv, char* const* env DPRINT("_spawnvpe('%s')\n", cmdname); - _searchenv(cmdname, "PATH", pathname); - - return _spawnve(mode, pathname[0] ? pathname : cmdname, argv, envp); + return _spawnve(mode, find_exec(cmdname, pathname), argv, envp); } int _execl(const char* cmdname, const char* arg0, ...) @@ -419,14 +495,12 @@ int _execlp(const char* cmdname, const char* arg0, ...) DPRINT("_execlp('%s')\n", cmdname); - _searchenv(cmdname, "PATH", pathname); - va_start(argp, arg0); args = valisttos(arg0, argp, ' '); if (args) { - ret = do_spawn(P_OVERLAY, pathname[0] ? pathname : cmdname, args, NULL); + ret = do_spawn(P_OVERLAY, find_exec(cmdname, pathname), args, NULL); free(args); } return ret; @@ -449,8 +523,6 @@ int _execlpe(const char* cmdname, const char* arg0, ... /*, NULL, char* const* e DPRINT("_execlpe('%s')\n", cmdname); - _searchenv(cmdname, "PATH", pathname); - va_start(argp, arg0); args = valisttos(arg0, argp, ' '); do @@ -461,7 +533,7 @@ int _execlpe(const char* cmdname, const char* arg0, ... /*, NULL, char* const* e envs = argvtos(ptr, 0); if (args) { - ret = do_spawn(P_OVERLAY, pathname[0] ? pathname : cmdname, args, envs); + ret = do_spawn(P_OVERLAY, find_exec(cmdname, pathname), args, envs); free(args); } if (envs) diff --git a/lib/user32/windows/bitmap.c b/lib/user32/windows/bitmap.c index 9b8147b..72a6977 100644 --- a/lib/user32/windows/bitmap.c +++ b/lib/user32/windows/bitmap.c @@ -57,7 +57,7 @@ LoadImageA(HINSTANCE hinst, } else { - Handle = LoadImageW(hinst, lpszWName, uType, cxDesired, + Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired, cyDesired, fuLoad); } return(Handle); diff --git a/lib/user32/windows/defwnd.c b/lib/user32/windows/defwnd.c index 631d63e..de7d91b 100644 --- a/lib/user32/windows/defwnd.c +++ b/lib/user32/windows/defwnd.c @@ -956,7 +956,7 @@ DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle) LRESULT STDCALL DefWndNCCalcSize(HWND hWnd, RECT* Rect) { - LRESULT Result; + LRESULT Result = 0; LONG Style = GetClassLongW(hWnd, GCL_STYLE); RECT TmpRect = {0, 0, 0, 0}; diff --git a/lib/user32/windows/prop.c b/lib/user32/windows/prop.c index 9de81de..6ca29d1 100644 --- a/lib/user32/windows/prop.c +++ b/lib/user32/windows/prop.c @@ -118,7 +118,7 @@ RemovePropA(HWND hWnd, LPCSTR lpString) } else { - Ret = RemovePropW(hWnd, lpWString); + Ret = RemovePropW(hWnd, (LPCWSTR)lpString); } return(Ret); } diff --git a/loaders/boot/boot.asm b/loaders/boot/boot.asm index 17fe2c7..019ea01 100644 --- a/loaders/boot/boot.asm +++ b/loaders/boot/boot.asm @@ -30,8 +30,8 @@ ; $Header$ ; ; $Log$ -; Revision 1.2 2002/11/04 22:01:07 short -; update for HEAD-2002110401 +; Revision 1.3 2002/11/07 12:04:04 short +; update for HEAD-2002110701 ; ; Revision 1.4 2000/06/25 03:59:14 dwelch ; diff --git a/loaders/boot/boot.mak b/loaders/boot/boot.mak index 43dc66a..99fb0b9 100644 --- a/loaders/boot/boot.mak +++ b/loaders/boot/boot.mak @@ -4,8 +4,8 @@ # $Header$ # # $Log$ -# Revision 1.2 2002/11/04 22:01:07 short -# update for HEAD-2002110401 +# Revision 1.3 2002/11/07 12:04:04 short +# update for HEAD-2002110701 # # Revision 1.4 2000/06/25 03:59:14 dwelch # diff --git a/loaders/boot/bootbk.asm b/loaders/boot/bootbk.asm index 3e8d8f0..aafff8c 100644 --- a/loaders/boot/bootbk.asm +++ b/loaders/boot/bootbk.asm @@ -30,8 +30,8 @@ ; $Header$ ; ; $Log$ -; Revision 1.2 2002/11/04 22:01:07 short -; update for HEAD-2002110401 +; Revision 1.3 2002/11/07 12:04:04 short +; update for HEAD-2002110701 ; ; Revision 1.4 2000/06/25 03:59:14 dwelch ; diff --git a/ntoskrnl/io/create.c b/ntoskrnl/io/create.c index e2a0400..4d02162 100644 --- a/ntoskrnl/io/create.c +++ b/ntoskrnl/io/create.c @@ -432,6 +432,9 @@ IoCreateFile(OUT PHANDLE FileHandle, if (!NT_SUCCESS(Status)) { DPRINT("Failing create request with status %x\n", Status); + FileObject->DeviceObject = NULL; + FileObject->Vpb = NULL; + ZwClose(*FileHandle); } if (IoStatusBlock) diff --git a/ntoskrnl/io/iomgr.c b/ntoskrnl/io/iomgr.c index 4c5a358..46b2631 100644 --- a/ntoskrnl/io/iomgr.c +++ b/ntoskrnl/io/iomgr.c @@ -54,7 +54,7 @@ IopCloseFile(PVOID ObjectBody, DPRINT("IopCloseFile()\n"); - if (HandleCount > 0) + if (HandleCount > 0 || FileObject->DeviceObject == NULL) { return; } @@ -63,7 +63,8 @@ IopCloseFile(PVOID ObjectBody, STANDARD_RIGHTS_REQUIRED, IoFileObjectType, UserMode); - + KeResetEvent( &FileObject->Event ); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLEANUP, FileObject->DeviceObject, NULL, @@ -75,6 +76,10 @@ IopCloseFile(PVOID ObjectBody, StackPtr->FileObject = FileObject; Status = IoCallDriver(FileObject->DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, NULL); + } } VOID STDCALL @@ -86,23 +91,31 @@ IopDeleteFile(PVOID ObjectBody) NTSTATUS Status; DPRINT("IopDeleteFile()\n"); + + if (FileObject->DeviceObject) + { + ObReferenceObjectByPointer(ObjectBody, + STANDARD_RIGHTS_REQUIRED, + IoFileObjectType, + UserMode); - ObReferenceObjectByPointer(ObjectBody, - STANDARD_RIGHTS_REQUIRED, - IoFileObjectType, - UserMode); - - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLOSE, - FileObject->DeviceObject, - NULL, - 0, - NULL, - NULL, - NULL); - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->FileObject = FileObject; + KeResetEvent( &FileObject->Event ); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLOSE, + FileObject->DeviceObject, + NULL, + 0, + NULL, + NULL, + NULL); + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; - Status = IoCallDriver(FileObject->DeviceObject, Irp); + Status = IoCallDriver(FileObject->DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, NULL); + } + } if (FileObject->FileName.Buffer != NULL) { diff --git a/ntoskrnl/ldr/loader.c b/ntoskrnl/ldr/loader.c index eba5f27..f428552 100644 --- a/ntoskrnl/ldr/loader.c +++ b/ntoskrnl/ldr/loader.c @@ -1115,7 +1115,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase, Characteristics & IMAGE_SECTION_CHAR_DATA || Characteristics & IMAGE_SECTION_CHAR_BSS)) { - for (i = 0; i < PAGE_ROUND_DOWN(Length) / PAGE_SIZE; i++) + for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++) { MmSetPageProtect(NULL, BaseAddress + (i * PAGE_SIZE), PAGE_READONLY); diff --git a/ntoskrnl/lpc/connect.c b/ntoskrnl/lpc/connect.c index 460e36a..78e0f35 100644 --- a/ntoskrnl/lpc/connect.c +++ b/ntoskrnl/lpc/connect.c @@ -517,9 +517,15 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, KIRQL oldIrql; PEPORT_CONNECT_REQUEST_MESSAGE CRequest; PEPORT_CONNECT_REPLY_MESSAGE CReply; + ULONG Size; - CReply = ExAllocatePool(NonPagedPool, - sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize); + Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE); + if (LpcMessage) + { + Size += LpcMessage->DataSize; + } + + CReply = ExAllocatePool(NonPagedPool, Size); if (CReply == NULL) { return(STATUS_NO_MEMORY); @@ -540,7 +546,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, /* * Create a port object for our side of the connection */ - if (AcceptIt == 1) + if (AcceptIt) { Status = ObCreateObject(ServerPortHandle, PORT_ALL_ACCESS, @@ -549,6 +555,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, (PVOID*)&OurPort); if (!NT_SUCCESS(Status)) { + ExFreePool(CReply); ObDereferenceObject(NamedPort); return(Status); } @@ -584,7 +591,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, sizeof(LPC_MESSAGE); CReply->ConnectDataLength = 0; } - if (AcceptIt != 1) + if (!AcceptIt) { EiReplyOrRequestPort(ConnectionRequest->Sender, &CReply->MessageHeader, @@ -707,6 +714,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, LPC_REPLY, OurPort); ExFreePool(ConnectionRequest); + ExFreePool(CReply); ObDereferenceObject(OurPort); ObDereferenceObject(NamedPort); diff --git a/ntoskrnl/mm/anonmem.c b/ntoskrnl/mm/anonmem.c index 0737009..451c5c2 100644 --- a/ntoskrnl/mm/anonmem.c +++ b/ntoskrnl/mm/anonmem.c @@ -154,6 +154,7 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, */ MmDisableVirtualMapping(MemoryArea->Process, Address, &WasDirty, &PhysicalAddress); + if (PhysicalAddress.QuadPart == 0) { KeBugCheck(0); @@ -200,7 +201,7 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, * Write the page to the pagefile */ Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); - MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress); + MmBuildMdlFromPages(Mdl, &PhysicalAddress.u.LowPart); Status = MmWriteToSwapPage(SwapEntry, Mdl); if (!NT_SUCCESS(Status)) { @@ -439,7 +440,7 @@ MmModifyAttributes(PMADDRESS_SPACE AddressSpace, { ULONG i; - for (i=0; i <= (RegionSize/PAGE_SIZE); i++) + for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) { LARGE_INTEGER PhysicalAddr; @@ -485,7 +486,7 @@ MmModifyAttributes(PMADDRESS_SPACE AddressSpace, { ULONG i; - for (i=0; i <= (RegionSize/PAGE_SIZE); i++) + for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) { if (MmIsPagePresent(AddressSpace->Process, BaseAddress + (i*PAGE_SIZE))) @@ -581,7 +582,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, if (PBaseAddress != 0) { - MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); if (MemoryArea != NULL && @@ -589,7 +590,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, MemoryArea->Length >= RegionSize) { Status = - MmAlterRegion(&Process->AddressSpace, + MmAlterRegion(AddressSpace, MemoryArea->BaseAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, PBaseAddress, RegionSize, @@ -690,7 +691,7 @@ MmFreeVirtualMemory(PEPROCESS Process, */ if (MemoryArea->PageOpCount > 0) { - for (i = 0; i < (PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE); i++) + for (i = 0; i < PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE; i++) { PMM_PAGEOP PageOp; diff --git a/ntoskrnl/mm/cont.c b/ntoskrnl/mm/cont.c index 37af4a1..8d3bbc6 100644 --- a/ntoskrnl/mm/cont.c +++ b/ntoskrnl/mm/cont.c @@ -63,11 +63,13 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes, Alignment); if (PBase.QuadPart == 0LL) { + MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryArea(MmGetKernelAddressSpace(), BaseAddress, 0, NULL, NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); return(NULL); } for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / 4096); i++) @@ -142,11 +144,13 @@ MmAllocateContiguousMemory (IN ULONG NumberOfBytes, VOID STDCALL MmFreeContiguousMemory(IN PVOID BaseAddress) { + MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryArea(MmGetKernelAddressSpace(), BaseAddress, 0, MmFreeContinuousPage, NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index 3e19b06..185921c 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -161,7 +161,7 @@ NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest) } DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024)); PageDirectory[PAGETABLE_MAP / (4*1024*1024)] = - (ULONG)PhysPageDirectory.QuadPart | 0x7; + PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE; ExUnmapPage(PageDirectory); @@ -180,7 +180,8 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address) *(ADDR_TO_PDE(Address)) = 0; if (Address >= (PVOID)KERNEL_BASE) { - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; + KeBugCheck(0); +// MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; } FLUSH_TLB; if (Process != NULL && Process != CurrentProcess) @@ -197,31 +198,37 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address) ULONG npage; if (Process != NULL && Process != CurrentProcess) - { - KeAttachProcess(Process); - } + { + KeAttachProcess(Process); + } + PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address)); for (i = 0; i < 1024; i++) - { - if (PageTable[i] != 0) - { - DbgPrint("Page table entry not clear at %x/%x (is %x)\n", - ((ULONG)Address / 4*1024*1024), i, PageTable[i]); - KeBugCheck(0); - } - } + { + if (PageTable[i] != 0) + { + DbgPrint("Page table entry not clear at %x/%x (is %x)\n", + ((ULONG)Address / 4*1024*1024), i, PageTable[i]); + KeBugCheck(0); + } + } npage = *(ADDR_TO_PDE(Address)); *(ADDR_TO_PDE(Address)) = 0; - if (Address >= (PVOID)KERNEL_BASE) - { - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; - } - MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(npage)); FLUSH_TLB; + + if (Address >= (PVOID)KERNEL_BASE) + { +// MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; + KeBugCheck(0); + } + else + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(npage)); + } if (Process != NULL && Process != CurrentProcess) - { - KeDetachProcess(); - } + { + KeDetachProcess(); + } } NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte, BOOLEAN MayWait) @@ -229,41 +236,66 @@ NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte, BOOLEAN MayWait) * FUNCTION: Get a pointer to the page table entry for a virtual address */ { - PULONG Pde; - ULONG Address = (ULONG)PAddress; + PULONG Pde, kePde; PHYSICAL_ADDRESS npage; + BOOLEAN Free = FALSE; + NTSTATUS Status; + KIRQL oldIrql; - DPRINT("MmGetPageEntry(Address %x)\n", Address); + DPRINT("MmGetPageEntry(Address %x)\n", PAddress); - Pde = ADDR_TO_PDE(Address); - if ((*Pde) == 0) - { - if (Address >= KERNEL_BASE && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + Pde = ADDR_TO_PDE(PAddress); + if (*Pde == 0) + { + if (PAddress >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + oldIrql = KeRaiseIrqlToSynchLevel(); + if (*kePde != 0) { - (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; + *Pde = *kePde; + FLUSH_TLB; } - else + else { - NTSTATUS Status; - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - (*Pde) = npage.QuadPart | 0x7; - if (Address >= KERNEL_BASE) - { - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = - *Pde; - } - memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); - FLUSH_TLB; + KeLowerIrql(oldIrql); + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + oldIrql = KeRaiseIrqlToSynchLevel(); + /* An other thread can set this pde entry, we must check again */ + if (*kePde == 0) + { + *kePde = npage.u.LowPart | PA_PRESENT | PA_READWRITE; + } + else + { + Free = TRUE; + } + *Pde = *kePde; + FLUSH_TLB; } - } - *Pte = ADDR_TO_PTE(Address); - return(STATUS_SUCCESS); + KeLowerIrql(oldIrql); + } + else + { + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER; + FLUSH_TLB; + } + } + *Pte = (PULONG)ADDR_TO_PTE(PAddress); + if (Free) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, npage); + } + return STATUS_SUCCESS; } ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) @@ -288,27 +320,30 @@ ULONG MmGetPageEntry1(PVOID PAddress) * FUNCTION: Get a pointer to the page table entry for a virtual address */ { - PULONG page_tlb; - PULONG page_dir; - ULONG Address = (ULONG)PAddress; + PULONG Pde, kePde; + ULONG Entry = 0; - DPRINT("MmGetPageEntry(Address %x)\n", Address); + DPRINT("MmGetPageEntry(Address %x)\n", PAddress); - page_dir = ADDR_TO_PDE(Address); - if ((*page_dir) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); - if ((*page_dir) == 0) - { - return(0); - } - page_tlb = ADDR_TO_PTE(Address); - DPRINT("page_tlb %x\n",page_tlb); - return(*page_tlb); + Pde = ADDR_TO_PDE(PAddress); + if (*Pde == 0) + { + if (PAddress >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + Entry = *(PULONG)ADDR_TO_PTE(PAddress); + } + } + } + else + { + Entry = *(PULONG)ADDR_TO_PTE(PAddress); + } + return Entry; } ULONG MmGetPageEntryForProcess1(PEPROCESS Process, PVOID Address) @@ -422,7 +457,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, */ { ULONG Pte; - PULONG Pde; + PULONG Pde, kePde; PEPROCESS CurrentProcess = PsGetCurrentProcess(); BOOLEAN WasValid; @@ -440,13 +475,17 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, * the global page directory. */ Pde = ADDR_TO_PDE(Address); - if ((*Pde) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - if ((*Pde) == 0) + if (*Pde == 0 && Address >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + } + } + + if (*Pde == 0) { if (Process != NULL && Process != CurrentProcess) { @@ -475,7 +514,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, } if (FreePage && WasValid) { - MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(Pte)); + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(Pte)); } /* @@ -483,7 +522,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, */ if (Process != NULL && WasValid && Process->AddressSpace.PageTableRefCountTable != NULL && - ADDR_TO_PAGE_TABLE(Address) < 768) + Address < (PVOID)KERNEL_BASE) { PUSHORT Ptrc; @@ -532,7 +571,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, */ { ULONG Pte; - PULONG Pde; + PULONG Pde, kePde; PEPROCESS CurrentProcess = PsGetCurrentProcess(); BOOLEAN WasValid = FALSE; @@ -550,13 +589,19 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, * the global page directory. */ Pde = ADDR_TO_PDE(Address); - if ((*Pde) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - if ((*Pde) == 0) + if (*Pde == 0) + { + if (Address >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + } + } + } + if (*Pde == 0) { if (Process != NULL && Process != CurrentProcess) { @@ -572,12 +617,14 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0); FLUSH_TLB; + WasValid = PAGE_MASK(Pte) == 0 ? FALSE : TRUE; + /* * Decrement the reference count for this page table. */ if (Process != NULL && WasValid && Process->AddressSpace.PageTableRefCountTable != NULL && - ADDR_TO_PAGE_TABLE(Address) < 768) + Address < (PVOID)KERNEL_BASE) { PUSHORT Ptrc; @@ -607,63 +654,75 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID PAddress) { - PULONG page_dir; - ULONG Address = (ULONG)PAddress; + PULONG kePde, Pde; - page_dir = ADDR_TO_PDE(Address); - if ((*page_dir) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - return(TRUE); - } + Pde = ADDR_TO_PDE(PAddress); + if (*Pde == 0) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + return(TRUE); + } + } return(FALSE); } BOOLEAN MmIsPageTablePresent(PVOID PAddress) { - PULONG page_dir; - ULONG Address = (ULONG)PAddress; + PULONG Pde, kePde; - page_dir = ADDR_TO_PDE(Address); - if ((*page_dir) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - return((*page_dir) == 0); + Pde = ADDR_TO_PDE(PAddress); + if (*Pde == 0) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + return TRUE; + } + } + return FALSE; } NTSTATUS MmCreatePageTable(PVOID PAddress) { - PULONG page_dir; - ULONG Address = (ULONG)PAddress; + PULONG Pde, kePde; PHYSICAL_ADDRESS npage; + NTSTATUS Status; - DPRINT("MmGetPageEntry(Address %x)\n", Address); + DPRINT("MmGetPageEntry(Address %x)\n", PAddress); - page_dir = ADDR_TO_PDE(Address); - DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); - if ((*page_dir) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - if ((*page_dir) == 0) - { - NTSTATUS Status; - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - (*page_dir) = npage.QuadPart | 0x7; - memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); - FLUSH_TLB; - } + Pde = ADDR_TO_PDE(PAddress); + DPRINT("page_dir %x *page_dir %x\n", Pde, *Pde); + if (*Pde == 0 && PAddress >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + return STATUS_SUCCESS; + } + /* Should we create a kernel page table? */ + DPRINT1("!!!!!!!!!!!!!!!!!!\n"); + return STATUS_UNSUCCESSFUL; + } + + if (*Pde == 0) + { + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + MiZeroPage(npage); + *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER; + FLUSH_TLB; + } return(STATUS_SUCCESS); } @@ -672,36 +731,69 @@ PULONG MmGetPageEntry(PVOID PAddress) * FUNCTION: Get a pointer to the page table entry for a virtual address */ { - PULONG page_tlb; - PULONG page_dir; - ULONG Address = (ULONG)PAddress; + PULONG Pde, kePde; PHYSICAL_ADDRESS npage; + KIRQL oldIrql; + BOOLEAN Free = FALSE; + NTSTATUS Status; - DPRINT("MmGetPageEntry(Address %x)\n", Address); + DPRINT("MmGetPageEntry(Address %x)\n", PAddress); - page_dir = ADDR_TO_PDE(Address); - DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); - if ((*page_dir) == 0 && - MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) - { - (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; - FLUSH_TLB; - } - if ((*page_dir) == 0) - { - NTSTATUS Status; - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); - if (!NT_SUCCESS(Status)) + Pde = ADDR_TO_PDE(PAddress); + DPRINT("page_dir %x *page_dir %x\n",Pde,*Pde); + if (*Pde == 0) + { + if (PAddress >= (PVOID)KERNEL_BASE) + { + oldIrql = KeRaiseIrqlToSynchLevel(); + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress); + if (*kePde != 0) { - KeBugCheck(0); + *Pde = *kePde; + FLUSH_TLB; } - (*page_dir) = npage.QuadPart | 0x7; - memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); - FLUSH_TLB; - } - page_tlb = ADDR_TO_PTE(Address); - DPRINT("page_tlb %x\n",page_tlb); - return(page_tlb); + else + { + KeLowerIrql(oldIrql); + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + MiZeroPage(npage); + oldIrql = KeRaiseIrqlToSynchLevel(); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + Free = TRUE; + } + else + { + *Pde = *kePde = npage.u.LowPart | PA_PRESENT | PA_READWRITE; + FLUSH_TLB; + } + } + KeLowerIrql(oldIrql); + } + else + { + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + MiZeroPage(npage); + *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER; + FLUSH_TLB; + } + if (Free) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, npage); + } + } + + return ADDR_TO_PTE(PAddress); } BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address) diff --git a/ntoskrnl/mm/iospace.c b/ntoskrnl/mm/iospace.c index a1b55a9..645a778 100644 --- a/ntoskrnl/mm/iospace.c +++ b/ntoskrnl/mm/iospace.c @@ -96,7 +96,7 @@ MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress, { Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH); } - for (i = 0; (i < ((NumberOfBytes + PAGE_SIZE - 1) / PAGE_SIZE)); i++) + for (i = 0; (i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE)); i++) { Status = MmCreateVirtualMappingForKernel(Result + (i * PAGE_SIZE), @@ -141,11 +141,13 @@ VOID STDCALL MmUnmapIoSpace (IN PVOID BaseAddress, IN ULONG NumberOfBytes) { - (VOID)MmFreeMemoryArea(&PsGetCurrentProcess()->AddressSpace, - (PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE), - NumberOfBytes, - NULL, - NULL); + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmFreeMemoryArea(MmGetKernelAddressSpace(), + (PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE), + NumberOfBytes, + NULL, + NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/ntoskrnl/mm/kmap.c b/ntoskrnl/mm/kmap.c index 6980931..ab48792 100644 --- a/ntoskrnl/mm/kmap.c +++ b/ntoskrnl/mm/kmap.c @@ -26,9 +26,10 @@ * One bit for each page in the kmalloc region * If set then the page is used by a kmalloc block */ -static ULONG AllocMap[ALLOC_MAP_SIZE/32]={0,}; +static UCHAR AllocMapBuffer[ROUND_UP(ALLOC_MAP_SIZE, 8) / 8]; +static RTL_BITMAP AllocMap; static KSPIN_LOCK AllocMapLock; -static ULONG AllocMapHint = 1; +static ULONG AllocMapHint = 0; static PVOID NonPagedPoolBase; @@ -38,15 +39,14 @@ VOID ExUnmapPage(PVOID Addr) { KIRQL oldIrql; - ULONG i = (Addr - NonPagedPoolBase) / PAGE_SIZE; + ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE; DPRINT("ExUnmapPage(Addr %x)\n",Addr); - DPRINT("i %x\n",i); MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL); KeAcquireSpinLock(&AllocMapLock, &oldIrql); - AllocMap[i / 32] &= (~(1 << (i % 32))); - AllocMapHint = min(AllocMapHint, i); + RtlClearBits(&AllocMap, Base, 1); + AllocMapHint = min(AllocMapHint, Base); KeReleaseSpinLock(&AllocMapLock, oldIrql); } @@ -99,35 +99,31 @@ PVOID ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage) { KIRQL oldlvl; - ULONG addr; - ULONG i; + PVOID Addr; + ULONG Base; NTSTATUS Status; KeAcquireSpinLock(&AllocMapLock, &oldlvl); - for (i = AllocMapHint; i < ALLOC_MAP_SIZE; i++) - { - if (!(AllocMap[i / 32] & (1 << (i % 32)))) - { - DPRINT("i %x\n",i); - AllocMap[i / 32] |= (1 << (i % 32)); - AllocMapHint = i + 1; - addr = (ULONG)(NonPagedPoolBase + (i*PAGE_SIZE)); - Status = MmCreateVirtualMapping(NULL, - (PVOID)addr, - PAGE_READWRITE | PAGE_SYSTEM, - PhysPage, - FALSE); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KeBugCheck(0); - } - KeReleaseSpinLock(&AllocMapLock, oldlvl); - return((PVOID)addr); - } - } + Base = RtlFindClearBitsAndSet(&AllocMap, 1, AllocMapHint); + if (Base != 0xFFFFFFFF) + { + AllocMapHint = Base + 1; + KeReleaseSpinLock(&AllocMapLock, oldlvl); + Addr = NonPagedPoolBase + Base * PAGE_SIZE; + Status = MmCreateVirtualMapping(NULL, + Addr, + PAGE_READWRITE | PAGE_SYSTEM, + PhysPage, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + return Addr; + } KeReleaseSpinLock(&AllocMapLock, oldlvl); - return(NULL); + return NULL; } VOID @@ -135,6 +131,8 @@ MmInitKernelMap(PVOID BaseAddress) { NonPagedPoolBase = BaseAddress; KeInitializeSpinLock(&AllocMapLock); + RtlInitializeBitMap(&AllocMap, (PVOID)&AllocMapBuffer, ALLOC_MAP_SIZE); + RtlClearAllBits(&AllocMap); } VOID @@ -142,21 +140,19 @@ MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free) { ULONG i; ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE; - ULONG Offset; KIRQL oldlvl; - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - AllocMapHint = min(AllocMapHint, Base); for (i = 0; i < Count; i++) - { - Offset = Base + i; - AllocMap[Offset / 32] &= (~(1 << (Offset % 32))); + { MmDeleteVirtualMapping(NULL, Addr + (i * PAGE_SIZE), Free, NULL, NULL); - } + } + KeAcquireSpinLock(&AllocMapLock, &oldlvl); + RtlClearBits(&AllocMap, Base, Count); + AllocMapHint = min(AllocMapHint, Base); KeReleaseSpinLock(&AllocMapLock, oldlvl); } @@ -166,44 +162,21 @@ MiAllocNonPagedPoolRegion(ULONG 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; + ULONG Base; KIRQL oldlvl; KeAcquireSpinLock(&AllocMapLock, &oldlvl); - for (i=AllocMapHint; iFlink,MEMORY_AREA,Entry); - Gap = (next->BaseAddress ) -(current->BaseAddress + current->Length); + Gap = next->BaseAddress - (current->BaseAddress + PAGE_ROUND_UP(current->Length)); if (Gap >= Length) { return(current->BaseAddress + PAGE_ROUND_UP(current->Length)); @@ -274,7 +274,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++) { PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL; - BOOL Dirty; + BOOL Dirty = FALSE; SWAPENTRY SwapEntry = 0; if (MmIsPageSwapEntry(AddressSpace->Process, @@ -376,12 +376,14 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, * NOTES: Lock the address space before calling this function */ { + ULONG tmpLength; DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x," "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n", Type,BaseAddress,*BaseAddress,Length,Attributes,Result); if ((*BaseAddress)==0 && !FixedAddress) { + tmpLength = PAGE_ROUND_UP(Length); *BaseAddress = MmFindGap(AddressSpace, PAGE_ROUND_UP(Length) +(PAGE_SIZE*2)); if ((*BaseAddress)==0) @@ -392,11 +394,12 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, (*BaseAddress)=(*BaseAddress)+PAGE_SIZE; } else - { - (*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress)); + { + tmpLength = (ULONG)*BaseAddress + Length - PAGE_ROUND_DOWN((*BaseAddress)); + (*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress)); if (MmOpenMemoryAreaByRegion(AddressSpace, *BaseAddress, - Length)!=NULL) + tmpLength)!=NULL) { DPRINT("Memory area already occupied\n"); return(STATUS_CONFLICTING_ADDRESSES); @@ -408,7 +411,7 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, RtlZeroMemory(*Result,sizeof(MEMORY_AREA)); (*Result)->Type = Type; (*Result)->BaseAddress = *BaseAddress; - (*Result)->Length = Length; + (*Result)->Length = tmpLength; (*Result)->Attributes = Attributes; (*Result)->LockCount = 0; (*Result)->Process = Process; diff --git a/ntoskrnl/mm/mdl.c b/ntoskrnl/mm/mdl.c index 9ce47a3..4a2f83d 100644 --- a/ntoskrnl/mm/mdl.c +++ b/ntoskrnl/mm/mdl.c @@ -15,6 +15,7 @@ #include #include #include +#include #define NDEBUG #include @@ -26,8 +27,8 @@ #define MI_MDL_MAPPING_REGION_SIZE (256*1024*1024) static PVOID MiMdlMappingRegionBase = NULL; -static PULONG MiMdlMappingRegionAllocMap = NULL; -static ULONG MiMdlMappingRegionHighWaterMark = 0; +static RTL_BITMAP MiMdlMappingRegionAllocMap; +static ULONG MiMdlMappingRegionHint; static KSPIN_LOCK MiMdlMappingRegionLock; /* FUNCTIONS *****************************************************************/ @@ -37,7 +38,9 @@ MmInitializeMdlImplementation(VOID) { MEMORY_AREA* Result; NTSTATUS Status; + PVOID Buffer; + MiMdlMappingRegionHint = 0; MiMdlMappingRegionBase = NULL; MmLockAddressSpace(MmGetKernelAddressSpace()); @@ -56,10 +59,11 @@ MmInitializeMdlImplementation(VOID) } MmUnlockAddressSpace(MmGetKernelAddressSpace()); - MiMdlMappingRegionAllocMap = - ExAllocatePool(NonPagedPool, - MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 32)); - MiMdlMappingRegionHighWaterMark = 0; + Buffer = ExAllocatePool(NonPagedPool, MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 8)); + + RtlInitializeBitMap(&MiMdlMappingRegionAllocMap, Buffer, MI_MDL_MAPPING_REGION_SIZE / PAGE_SIZE); + RtlClearAllBits(&MiMdlMappingRegionAllocMap); + KeInitializeSpinLock(&MiMdlMappingRegionLock); } @@ -130,6 +134,7 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) PULONG MdlPages; KIRQL oldIrql; ULONG RegionSize; + ULONG StartingOffset; DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode); @@ -149,13 +154,22 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) /* Allocate that number of pages from the mdl mapping region. */ KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); - Base = MiMdlMappingRegionBase + MiMdlMappingRegionHighWaterMark * PAGE_SIZE; - for (i = 0; i < RegionSize; i++) - { - ULONG Offset = MiMdlMappingRegionHighWaterMark + i; - MiMdlMappingRegionAllocMap[Offset / 32] |= (1 << (Offset % 32)); - } - MiMdlMappingRegionHighWaterMark += RegionSize; + + StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint); + + if (StartingOffset == 0xffffffff) + { + DPRINT1("Out of MDL mapping space\n"); + KeBugCheck(0); + } + + Base = MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE; + + if (MiMdlMappingRegionHint == StartingOffset) + { + MiMdlMappingRegionHint +=RegionSize; + } + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); /* Set the virtual mappings for the MDL pages. */ @@ -195,7 +209,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) ULONG RegionSize; ULONG Base; - DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", Mdl, BaseAddress); + DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl); /* * In this case, the MDL has the same system address as the base address @@ -208,6 +222,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) /* Calculate the number of pages we mapped. */ RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + BaseAddress -= Mdl->ByteOffset; /* Unmap all the pages. */ for (i = 0; i < RegionSize; i++) @@ -221,18 +236,12 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); /* Deallocate all the pages used. */ - Base = (ULONG)(BaseAddress - MiMdlMappingRegionBase - Mdl->ByteOffset); - Base = Base / PAGE_SIZE; - for (i = 0; i < RegionSize; i++) - { - ULONG Offset = Base + i; - MiMdlMappingRegionAllocMap[Offset / 32] &= ~(1 << (Offset % 32)); - } - /* If all the pages below the high-water mark are free then move it down. */ - if ((Base + RegionSize) == MiMdlMappingRegionHighWaterMark) - { - MiMdlMappingRegionHighWaterMark = Base; - } + Base = (ULONG)(BaseAddress - MiMdlMappingRegionBase) / PAGE_SIZE; + + RtlClearBits(&MiMdlMappingRegionAllocMap, Base, RegionSize); + + MiMdlMappingRegionHint = min (MiMdlMappingRegionHint, Base); + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); /* Reset the MDL state. */ diff --git a/ntoskrnl/mm/ncache.c b/ntoskrnl/mm/ncache.c index 2ff2129..d013d53 100644 --- a/ntoskrnl/mm/ncache.c +++ b/ntoskrnl/mm/ncache.c @@ -71,7 +71,7 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes) } Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE | PAGE_WRITETHROUGH; - for (i = 0; i <= (NumberOfBytes / PAGE_SIZE); i++) + for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE); i++) { PHYSICAL_ADDRESS NPage; @@ -125,11 +125,13 @@ MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, VOID STDCALL MmFreeNonCachedMemory (IN PVOID BaseAddress, IN ULONG NumberOfBytes) { + MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryArea (MmGetKernelAddressSpace(), BaseAddress, NumberOfBytes, MmFreeNonCachedPage, NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/ntoskrnl/mm/npool.c b/ntoskrnl/mm/npool.c index 391c1ae..daef537 100644 --- a/ntoskrnl/mm/npool.c +++ b/ntoskrnl/mm/npool.c @@ -203,7 +203,7 @@ MiAddToTagHashTable(BLOCK_HDR* block) return; } previous = current; - if ((PVOID)current->tag_next >= (PVOID)0xc1123160) + if (current->tag_next &&((PVOID)current->tag_next >= (PVOID)kernel_pool_base + NONPAGED_POOL_SIZE || (PVOID)current->tag_next < (PVOID)kernel_pool_base)) { DbgPrint("previous %x\n", previous); } @@ -596,7 +596,9 @@ merge_free_block(BLOCK_HDR* blk) (unsigned int)next) { RemoveEntryList(&next->ListEntry); - blk->Size = blk->Size + sizeof(BLOCK_HDR) + next->Size; + blk->Size = blk->Size + next->Size; + memset(next, 0xcc, sizeof(BLOCK_HDR)); + EiFreeNonPagedPool += sizeof(BLOCK_HDR); EiNrFreeBlocks--; } } @@ -610,6 +612,8 @@ merge_free_block(BLOCK_HDR* blk) { RemoveEntryList(&blk->ListEntry); previous->Size = previous->Size + sizeof(BLOCK_HDR) + blk->Size; + memset(blk, 0xcc, sizeof(BLOCK_HDR)); + EiFreeNonPagedPool += sizeof(BLOCK_HDR); EiNrFreeBlocks--; } } @@ -635,6 +639,7 @@ add_to_free_list(BLOCK_HDR* blk) blk->ListEntry.Blink = current_entry->Blink; current_entry->Blink->Flink = &blk->ListEntry; current_entry->Blink = &blk->ListEntry; + EiFreeNonPagedPool += blk->Size; EiNrFreeBlocks++; return; } @@ -642,6 +647,7 @@ add_to_free_list(BLOCK_HDR* blk) current_entry = current_entry->Flink; } InsertTailList(&FreeBlockListHead, &blk->ListEntry); + EiFreeNonPagedPool += blk->Size; EiNrFreeBlocks++; } @@ -651,6 +657,7 @@ static void add_to_used_list(BLOCK_HDR* blk) */ { InsertHeadList(&UsedBlockListHead, &blk->ListEntry); + EiUsedNonPagedPool += blk->Size; EiNrUsedBlocks++; } @@ -658,6 +665,7 @@ static void add_to_used_list(BLOCK_HDR* blk) static void remove_from_free_list(BLOCK_HDR* current) { RemoveEntryList(¤t->ListEntry); + EiFreeNonPagedPool -= current->Size; EiNrFreeBlocks--; } @@ -665,6 +673,7 @@ static void remove_from_free_list(BLOCK_HDR* current) static void remove_from_used_list(BLOCK_HDR* current) { RemoveEntryList(¤t->ListEntry); + EiUsedNonPagedPool -= current->Size; EiNrUsedBlocks--; } @@ -684,86 +693,54 @@ inline static BLOCK_HDR* address_to_block(void* addr) ( ((int)addr) - sizeof(BLOCK_HDR) ); } -static BLOCK_HDR* grow_kernel_pool(unsigned int size, ULONG Tag, PVOID Caller) -/* - * FUNCTION: Grow the executive heap to accomodate a block of at least 'size' - * bytes - */ +static BLOCK_HDR* lookup_block(unsigned int size) { - unsigned int total_size = size + sizeof(BLOCK_HDR); - unsigned int nr_pages = PAGE_ROUND_UP(total_size) / PAGE_SIZE; - unsigned int start; - BLOCK_HDR* used_blk=NULL; - BLOCK_HDR* free_blk=NULL; - int i; - NTSTATUS Status; - KIRQL oldIrql; - - start = (ULONG)MiAllocNonPagedPoolRegion(nr_pages); - - DPRINT("growing heap for block size %d, ",size); - DPRINT("start %x\n",start); - - for (i=0;iSize, current->tag_next); + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + if (current->Size >= size && + (best == NULL || current->Size < best->Size)) { - KeBugCheck(0); - return(NULL); + best = current; } - Status = MmCreateVirtualMapping(NULL, - (PVOID)(start + (i*PAGE_SIZE)), - PAGE_READWRITE, - Page, - FALSE); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KeBugCheck(0); - } - } - - KeAcquireSpinLock(&MmNpoolLock, &oldIrql); - if ((PAGE_SIZE-(total_size%PAGE_SIZE))>(2*sizeof(BLOCK_HDR))) - { - used_blk = (struct _BLOCK_HDR *)start; - DPRINT("Creating block at %x\n",start); - used_blk->Magic = BLOCK_HDR_USED_MAGIC; - used_blk->Size = size; - add_to_used_list(used_blk); - - free_blk = (BLOCK_HDR *)(start + sizeof(BLOCK_HDR) + size); - DPRINT("Creating block at %x\n",free_blk); - free_blk->Magic = BLOCK_HDR_FREE_MAGIC; - free_blk->Size = (nr_pages * PAGE_SIZE) -((sizeof(BLOCK_HDR)*2) + size); - add_to_free_list(free_blk); - - EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->Size; - EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->Size; - } + current_entry = current_entry->Flink; + } + } else - { - used_blk = (struct _BLOCK_HDR *)start; - used_blk->Magic = BLOCK_HDR_USED_MAGIC; - used_blk->Size = (nr_pages * PAGE_SIZE) - sizeof(BLOCK_HDR); - add_to_used_list(used_blk); - - EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->Size; - } - - used_blk->Tag = Tag; - used_blk->Caller = Caller; - used_blk->Dumped = FALSE; -#ifdef TAG_STATISTICS_TRACKING - MiAddToTagHashTable(used_blk); -#endif /* TAG_STATISTICS_TRACKING */ - - VALIDATE_POOL; - KeReleaseSpinLock(&MmNpoolLock, oldIrql); - return(used_blk); + { + while (current_entry != &FreeBlockListHead) + { + DPRINT("current %x size %x tag_next %x\n", + current, current->Size, current->tag_next); + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + + block = block_to_address(current); + block_boundary = (PVOID)PAGE_ROUND_UP((ULONG)block); + new_size = (ULONG)block_boundary - (ULONG)block + size; + if (new_size != size && (ULONG)block_boundary - (ULONG)block < sizeof(BLOCK_HDR)) + { + new_size += PAGE_SIZE; + } + if (current->Size >= new_size && + (best == NULL || current->Size < best->Size)) + { + best = current; + } + current_entry = current_entry->Flink; + } + } + return best; } static void* take_block(BLOCK_HDR* current, unsigned int size, @@ -774,17 +751,40 @@ static void* take_block(BLOCK_HDR* current, unsigned int size, * RETURNS: The address of the created memory block */ { + + BLOCK_HDR* blk; + if (size >= PAGE_SIZE) + { + blk = address_to_block((PVOID)PAGE_ROUND_UP(block_to_address (current))); + if (blk != current) + { + if ((ULONG)blk - (ULONG)current < sizeof(BLOCK_HDR)) + { + (ULONG)blk += PAGE_SIZE; + } + assert((ULONG)blk - (ULONG)current + size <= current->Size && (ULONG)blk - (ULONG)current >= sizeof(BLOCK_HDR)); + + memset(blk, 0, sizeof(BLOCK_HDR)); + blk->Magic = BLOCK_HDR_FREE_MAGIC; + blk->Size = current->Size - ((ULONG)blk - (ULONG)current); + current->Size -= (blk->Size + sizeof(BLOCK_HDR)); + InsertHeadList(¤t->ListEntry, &blk->ListEntry); + EiFreeNonPagedPool -= sizeof(BLOCK_HDR); + EiNrFreeBlocks++; + current = blk; + } + } /* * 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))) + if (current->Size > size + sizeof(BLOCK_HDR)) { BLOCK_HDR* free_blk; - EiFreeNonPagedPool = EiFreeNonPagedPool - current->Size; + EiFreeNonPagedPool -= current->Size; /* * Replace the bigger block with a smaller block in the @@ -798,8 +798,7 @@ static void* take_block(BLOCK_HDR* current, unsigned int size, current->Size=size; RemoveEntryList(¤t->ListEntry); - InsertHeadList(&UsedBlockListHead, ¤t->ListEntry); - EiNrUsedBlocks++; + add_to_used_list(current); current->Magic = BLOCK_HDR_USED_MAGIC; current->Tag = Tag; current->Caller = Caller; @@ -808,8 +807,7 @@ static void* take_block(BLOCK_HDR* current, unsigned int size, MiAddToTagHashTable(current); #endif /* TAG_STATISTICS_TRACKING */ - EiUsedNonPagedPool = EiUsedNonPagedPool + current->Size; - EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->Size; + EiFreeNonPagedPool += free_blk->Size; VALIDATE_POOL; return(block_to_address(current)); @@ -821,9 +819,6 @@ static void* take_block(BLOCK_HDR* current, unsigned int size, remove_from_free_list(current); add_to_used_list(current); - EiFreeNonPagedPool = EiFreeNonPagedPool - current->Size; - EiUsedNonPagedPool = EiUsedNonPagedPool + current->Size; - current->Magic = BLOCK_HDR_USED_MAGIC; current->Tag = Tag; current->Caller = Caller; @@ -836,6 +831,76 @@ static void* take_block(BLOCK_HDR* current, unsigned int size, return(block_to_address(current)); } +static void* grow_kernel_pool(unsigned int size, ULONG Tag, PVOID Caller) +/* + * FUNCTION: Grow the executive heap to accomodate a block of at least 'size' + * bytes + */ +{ + ULONG nr_pages = PAGE_ROUND_UP(size + sizeof(BLOCK_HDR)) / PAGE_SIZE; + ULONG start; + BLOCK_HDR* blk=NULL; + int i; + KIRQL oldIrql; + NTSTATUS Status; + PVOID block = NULL; + + if (size >= PAGE_SIZE) + { + nr_pages++; + } + + start = (ULONG)MiAllocNonPagedPoolRegion(nr_pages); + + DPRINT("growing heap for block size %d, ",size); + DPRINT("start %x\n",start); + + for (i=0;iSize = (nr_pages * PAGE_SIZE) - sizeof(BLOCK_HDR); + blk->Magic = BLOCK_HDR_FREE_MAGIC; + memset(block_to_address(blk), 0xcc, blk->Size); + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + add_to_free_list(blk); + merge_free_block(blk); + + blk = lookup_block(size); + if (blk) + { + block = take_block(blk, size, Tag, Caller); + VALIDATE_POOL; + } + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + if (block == NULL) + { + CHECKPOINT1; + } + return block; +} + #endif /* not WHOLE_PAGE_ALLOCATIONS */ VOID STDCALL ExFreeNonPagedPool (PVOID block) @@ -904,11 +969,12 @@ VOID STDCALL ExFreeNonPagedPool (PVOID block) #endif /* TAG_STATISTICS_TRACKING */ remove_from_used_list(blk); blk->Magic = BLOCK_HDR_FREE_MAGIC; + blk->Tag = 0; + blk->Caller = NULL; + blk->tag_next = NULL; add_to_free_list(blk); merge_free_block(blk); - EiUsedNonPagedPool = EiUsedNonPagedPool - blk->Size; - EiFreeNonPagedPool = EiFreeNonPagedPool + blk->Size; VALIDATE_POOL; KeReleaseSpinLock(&MmNpoolLock, oldIrql); @@ -942,8 +1008,6 @@ ExAllocateNonPagedPoolWithTag(ULONG Type, ULONG Size, ULONG Tag, PVOID Caller) return(block); #else /* not WHOLE_PAGE_ALLOCATIONS */ - BLOCK_HDR* current = NULL; - PLIST_ENTRY current_entry; PVOID block; BLOCK_HDR* best = NULL; KIRQL oldIrql; @@ -952,9 +1016,21 @@ ExAllocateNonPagedPoolWithTag(ULONG Type, ULONG Size, ULONG Tag, PVOID Caller) Size,Caller); KeAcquireSpinLock(&MmNpoolLock, &oldIrql); - + VALIDATE_POOL; - + +#if 0 + /* after some allocations print the npaged pool stats */ +#ifdef TAG_STATISTICS_TRACKING + { + static ULONG counter = 0; + if (counter++ % 100000 == 0) + { + MiDebugDumpNonPagedPoolStats(FALSE); + } + } +#endif +#endif /* * accomodate this useful idiom */ @@ -964,39 +1040,26 @@ ExAllocateNonPagedPoolWithTag(ULONG Type, ULONG Size, ULONG Tag, PVOID Caller) KeReleaseSpinLock(&MmNpoolLock, oldIrql); return(NULL); } - + /* Make the size dword alligned, this makes the block dword alligned */ + Size = ROUND_UP(Size, 4); /* * Look for an already created block of sufficent size */ - current_entry = FreeBlockListHead.Flink; - while (current_entry != &FreeBlockListHead) - { - DPRINT("current %x size %x tag_next %x\n",current,current->Size, - current->tag_next); - current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); - if (current->Size >= Size && - (best == NULL || current->Size < best->Size)) - { - best = current; - } - current_entry = current_entry->Flink; - } - if (best != NULL) - { - block=take_block(best, Size, Tag, Caller); - VALIDATE_POOL; - memset(block,0,Size); - KeReleaseSpinLock(&MmNpoolLock, oldIrql); - return(block); - } - - - /* - * Otherwise create a new block - */ - KeReleaseSpinLock(&MmNpoolLock, oldIrql); - block=block_to_address(grow_kernel_pool(Size, Tag, Caller)); - memset(block, 0, Size); + best = lookup_block(Size); + if (best == NULL) + { + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + block = grow_kernel_pool(Size, Tag, Caller); + assert(block != NULL); + memset(block,0,Size); + } + else + { + block=take_block(best, Size, Tag, Caller); + VALIDATE_POOL; + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + memset(block,0,Size); + } return(block); #endif /* WHOLE_PAGE_ALLOCATIONS */ } diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index 81df3e4..056b906 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -45,6 +45,8 @@ typedef struct _MM_RMAP_ENTRY PVOID Address; } MM_RMAP_ENTRY, *PMM_RMAP_ENTRY; +#define TAG_RMAP TAG('R', 'M', 'A', 'P') + /* GLOBALS ******************************************************************/ static FAST_MUTEX RmapListLock; @@ -353,7 +355,7 @@ MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process, Address = (PVOID)PAGE_ROUND_DOWN(Address); - new_entry = ExAllocatePool(NonPagedPool, sizeof(MM_RMAP_ENTRY)); + new_entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_RMAP_ENTRY), TAG_RMAP); if (new_entry == NULL) { KeBugCheck(0); diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index d4b5f53..5c3af8c 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -318,12 +318,13 @@ MiReadPage(PMEMORY_AREA MemoryArea, * Page - Variable that receives a page contains the read data. */ { - IO_STATUS_BLOCK IoStatus; + ULONG BaseOffset; + PVOID BaseAddress; + BOOLEAN UptoDate; + PCACHE_SEGMENT CacheSeg; PFILE_OBJECT FileObject; - PMDL Mdl; NTSTATUS Status; PREACTOS_COMMON_FCB_HEADER Fcb; - KEVENT Event; FileObject = MemoryArea->Data.SectionData.Section->FileObject; Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; @@ -336,10 +337,6 @@ MiReadPage(PMEMORY_AREA MemoryArea, if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ && (Offset->QuadPart % PAGE_SIZE) == 0) { - ULONG BaseOffset; - PVOID BaseAddress; - BOOLEAN UptoDate; - PCACHE_SEGMENT CacheSeg; PHYSICAL_ADDRESS Addr; /* @@ -348,7 +345,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, * alignment less than the file system block size. */ Status = CcRosGetCacheSegment(Fcb->Bcb, - (ULONG)Offset->QuadPart, + Offset->u.LowPart, &BaseOffset, &BaseAddress, &UptoDate, @@ -366,6 +363,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, Status = ReadCacheSegment(CacheSeg); if (!NT_SUCCESS(Status)) { + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE); return Status; } } @@ -373,15 +371,16 @@ MiReadPage(PMEMORY_AREA MemoryArea, * Retrieve the page from the cache segment that we actually want. */ Addr = MmGetPhysicalAddress(BaseAddress + - Offset->QuadPart - BaseOffset); + Offset->u.LowPart - BaseOffset); (*Page) = Addr; MmReferencePage((*Page)); CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, TRUE); - return(STATUS_SUCCESS); } else { + PVOID PageAddr; + ULONG OffsetInPage; /* * Allocate a page, this is rather complicated by the possibility * we might have to move other things out of memory @@ -392,28 +391,70 @@ MiReadPage(PMEMORY_AREA MemoryArea, return(Status); } - /* - * Create an mdl to hold the page we are going to read data into. - */ - Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); - MmBuildMdlFromPages(Mdl, &Page->u.LowPart); - /* - * Call the FSD to read the page - */ - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - Status = IoPageRead(FileObject, - Mdl, - Offset, - &Event, - &IoStatus); - if (Status == STATUS_PENDING) + Status = CcRosGetCacheSegment(Fcb->Bcb, + Offset->u.LowPart, + &BaseOffset, + &BaseAddress, + &UptoDate, + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (!UptoDate) + { + /* + * If the cache segment isn't up to date then call the file + * system to read in the data. + */ + Status = ReadCacheSegment(CacheSeg); + if (!NT_SUCCESS(Status)) + { + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE); + return Status; + } + } + PageAddr = ExAllocatePageWithPhysPage(*Page); + OffsetInPage = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - Offset->u.LowPart; + if (OffsetInPage >= PAGE_SIZE) { - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - return(IoStatus.Status); + memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, PAGE_SIZE); } - return(Status); + else + { + memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, OffsetInPage); + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE); + Status = CcRosGetCacheSegment(Fcb->Bcb, + Offset->u.LowPart + OffsetInPage, + &BaseOffset, + &BaseAddress, + &UptoDate, + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + ExUnmapPage(PageAddr); + return(Status); + } + if (!UptoDate) + { + /* + * If the cache segment isn't up to date then call the file + * system to read in the data. + */ + Status = ReadCacheSegment(CacheSeg); + if (!NT_SUCCESS(Status)) + { + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE); + ExUnmapPage(PageAddr); + return Status; + } + } + memcpy(PageAddr + OffsetInPage, BaseAddress, PAGE_SIZE - OffsetInPage); + } + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE); + ExUnmapPage(PageAddr); } + return(STATUS_SUCCESS); } NTSTATUS @@ -558,7 +599,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, Status = MmCreateVirtualMapping(PsGetCurrentProcess(), Address, - Attributes, + MemoryArea->Attributes, Page, FALSE); if (!NT_SUCCESS(Status)) @@ -1253,7 +1294,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, /* * Take an additional reference to the page. */ - MmReferencePage(PhysicalAddress); +// MmReferencePage(PhysicalAddress); /* * Paging out data mapped read-only is easy. @@ -1680,7 +1721,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace, if (OldProtect != NewProtect) { - for (i = 0; i < (RegionSize / PAGE_SIZE); i++) + for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++) { PVOID Address = BaseAddress + (i * PAGE_SIZE); ULONG Protect = NewProtect; @@ -2873,6 +2914,19 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment, Offset); + + if (PageOp) + { + KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + MmReleasePageOp(PageOp); + PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment, + Offset); + } + assert(PageOp == NULL); /* @@ -3189,7 +3243,7 @@ MmAllocateSection (IN ULONG Length) } MmUnlockAddressSpace(AddressSpace); DPRINT("Result %p\n",Result); - for (i = 0; (i <= (Length / PAGE_SIZE)); i++) + for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++) { PHYSICAL_ADDRESS Page; @@ -3310,22 +3364,22 @@ MmMapViewOfSection(IN PVOID SectionObject, /* Check there is enough space to map the section at that point. */ if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase, - ImageSize) != NULL) + PAGE_ROUND_UP(ImageSize)) != NULL) { /* Fail if the user requested a fixed base address. */ if ((*BaseAddress) != NULL) { MmUnlockSection(Section); MmUnlockAddressSpace(AddressSpace); - return(Status); + return(STATUS_UNSUCCESSFUL); } /* Otherwise find a gap to map the image. */ - ImageBase = MmFindGap(AddressSpace, ImageSize); + ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize)); if (ImageBase == NULL) { MmUnlockSection(Section); MmUnlockAddressSpace(AddressSpace); - return(Status); + return(STATUS_UNSUCCESSFUL); } } diff --git a/ntoskrnl/ob/object.c b/ntoskrnl/ob/object.c index 7ac9996..383a25f 100644 --- a/ntoskrnl/ob/object.c +++ b/ntoskrnl/ob/object.c @@ -17,6 +17,7 @@ #include #include #include +#include #define NDEBUG #include @@ -111,6 +112,7 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, PWSTR Path; PWSTR current; UNICODE_STRING PathString; + ULONG Attributes; DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, " "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath); @@ -167,6 +169,9 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, } RootObject = CurrentObject; + Attributes = ObjectAttributes->Attributes; + if (ObjectType == IoSymbolicLinkType) + Attributes |= OBJ_OPENLINK; while (TRUE) { @@ -185,7 +190,7 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, &NextObject, &PathString, ¤t, - ObjectAttributes->Attributes); + Attributes); if (Status == STATUS_REPARSE) { /* reparse the object path */ diff --git a/ntoskrnl/rtl/bitmap.c b/ntoskrnl/rtl/bitmap.c index 6823b48..3760fa6 100644 --- a/ntoskrnl/rtl/bitmap.c +++ b/ntoskrnl/rtl/bitmap.c @@ -136,7 +136,7 @@ RtlClearBits ( if (StartingIndex + NumberToClear > Size) NumberToClear = Size - StartingIndex; - Ptr = (PCHAR)(BitMapHeader->Buffer + (StartingIndex / 8)); + Ptr = (PCHAR)BitMapHeader->Buffer + (StartingIndex / 8); while (NumberToClear) { /* bit shift in current byte */ -- 1.8.3.1