From c39989df1b2bc9d2a91124d969529d507c8e95b3 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 10 Dec 2006 18:40:30 +0000 Subject: [PATCH] - Fix SleepEx. - Put volatile statements in EX_RUNDOWN_REF, IRP, DEVICE_OBJECT, ERESOURCE, FILE_OBJECT, IO_REMOVE_LOCK, WORK_QUEUE_ITEM where required (thanks to Microsoft's changes in the WDK to mark the fields properly). - Update FILE_OBJECT definition. - Add some asserts to some I/O functions. - Add stub support for File Objects created by XP+ Drivers which have File Object Extensions. - Add some fixes to IopDeleteFile, including proper reference counting for the DO and VPB, as well as cleanup when the file is closed without a handle. - Fix a bug in IopSecurityFile. - Queue and unqueue IRPs in all I/O functions. - Fully support IRP cancellation now. - Fix critical bugs in NtDeviceIoControlFile and NtDeviceFsControlFile which were causing double queueing of IRPs and freeing of invalid memory, as well as invalid paramter checking for user-mode buffers. - Add exhaustive validation checks to IoCreateFile, add more failure cases, and validate the EA buffer. Also support IO_ATTACH_DEVICE_API flag. - Implement IoCreateStreamFileObjectEx and IoCreateStreamFileObjectLite and fix several bugs in the original implementation of IoCreateStreamFileObject. - Fix a bug in RtlRaiseException. - Update Io*ShareAccess routines to support XP+ style semantics related to special File Object flags which disable their use. - Add validation to all Query/Set routines so that information clasess, lengths, buffers and alignment are properly checked. - Also add an array for the proper acess rights that each query/set operation requires. - Check backup/restore privileges during I/O File operations. - Check traverse access during I/O File Operations. - Check access privileges to the device during I/O file operations. - Rename IopReferenceDeviceObject and also verify if an exclusive DO is trying to be invalidly opened. - Support various extra security checks during I/O File/Device Parse Routine. - Fix a bug during IopCleanupIrp so that we don't dereference the File OBject if this was a create operation. - Fix some bogus asserts in IofCompleteRequest, and save the IRP Flags before signalling it's event, since the driver might've freed it behind our back. - Fix a large bug in ObInsertObject which affected the insert of unnamed objects with forced security options (Such as process/threads). - Fix the creation of the Process/Thread/Job Obejct Types to that security information is forced. - Remove "Fix PS!!!" messages since the bug is now fixed and these objects now get proper security descriptors. - Fix another bug in ObInsertObjet which wasn't properly validating user-mode objects and always assumed kernel mode. - Silence multiple trace/checkpoint messages that have accumulated throughout time for various debugging purposes. svn path=/trunk/; revision=25118 --- reactos/base/system/lsass/lsass.c | 2 +- reactos/base/system/services/rpcserver.c | 2 +- reactos/base/system/winlogon/sas.c | 2 +- reactos/dll/win32/advapi32/service/scm.c | 2 +- reactos/dll/win32/kernel32/thread/thread.c | 11 +- reactos/drivers/base/bootvid/vid.c | 2 +- reactos/drivers/filesystems/fs_rec/udfs.c | 1 - reactos/drivers/filesystems/np/fsctrl.c | 2 +- reactos/include/ddk/ntifs.h | 28 + reactos/include/ddk/winddk.h | 80 +- reactos/lib/rtl/exception.c | 7 +- reactos/lib/rtl/i386/exception.c | 1 + reactos/ntoskrnl/KrnlFun.c | 12 +- reactos/ntoskrnl/cm/import.c | 2 +- reactos/ntoskrnl/dbgk/debug.c | 2 +- reactos/ntoskrnl/fstub/disksup.c | 10 +- reactos/ntoskrnl/inbv/inbv.c | 2 +- reactos/ntoskrnl/include/internal/debug.h | 2 +- reactos/ntoskrnl/include/internal/io.h | 25 +- reactos/ntoskrnl/include/internal/io_x.h | 2 +- reactos/ntoskrnl/include/internal/ob.h | 6 + reactos/ntoskrnl/io/iomgr/device.c | 53 +- reactos/ntoskrnl/io/iomgr/file.c | 716 ++++++++++++++++-- reactos/ntoskrnl/io/iomgr/iofunc.c | 351 +++++++-- reactos/ntoskrnl/io/iomgr/iomgr.c | 2 +- reactos/ntoskrnl/io/iomgr/irp.c | 36 +- reactos/ntoskrnl/kdbg/kdb_symbols.c | 2 +- reactos/ntoskrnl/mm/freelist.c | 2 +- reactos/ntoskrnl/ob/obhandle.c | 5 +- reactos/ntoskrnl/ob/oblife.c | 8 + reactos/ntoskrnl/ps/psmgr.c | 18 +- reactos/ntoskrnl/rtl/libsupp.c | 3 +- reactos/ntoskrnl/se/semgr.c | 5 +- reactos/subsystems/win32/csrss/api/wapi.c | 14 +- .../subsystems/win32/win32k/main/dllmain.c | 2 +- .../subsystems/win32/win32k/ntuser/class.c | 7 +- .../subsystems/win32/win32k/ntuser/focus.c | 6 +- reactos/subsystems/win32/win32k/ntuser/misc.c | 2 +- .../subsystems/win32/win32k/ntuser/window.c | 2 +- 39 files changed, 1161 insertions(+), 276 deletions(-) diff --git a/reactos/base/system/lsass/lsass.c b/reactos/base/system/lsass/lsass.c index 8d796061a96..d5005c68096 100644 --- a/reactos/base/system/lsass/lsass.c +++ b/reactos/base/system/lsass/lsass.c @@ -51,7 +51,7 @@ ServiceMain( IN DWORD argc, IN LPWSTR *argv) { - DPRINT1("ServiceMain() called\n"); + DPRINT("ServiceMain() called\n"); } INT WINAPI diff --git a/reactos/base/system/services/rpcserver.c b/reactos/base/system/services/rpcserver.c index 3cc52d30bb0..f1f2da37ea7 100644 --- a/reactos/base/system/services/rpcserver.c +++ b/reactos/base/system/services/rpcserver.c @@ -1756,7 +1756,7 @@ ScmrStartServiceW(handle_t BindingHandle, PSERVICE_HANDLE hSvc; PSERVICE lpService = NULL; - DPRINT1("ScmrStartServiceW() called\n"); + DPRINT("ScmrStartServiceW() called\n"); if (ScmShutdown) return ERROR_SHUTDOWN_IN_PROGRESS; diff --git a/reactos/base/system/winlogon/sas.c b/reactos/base/system/winlogon/sas.c index ee870bf5c6d..4aeee29db50 100644 --- a/reactos/base/system/winlogon/sas.c +++ b/reactos/base/system/winlogon/sas.c @@ -11,7 +11,7 @@ #include "winlogon.h" -#define YDEBUG +//#define YDEBUG #include #define WINLOGON_SAS_CLASS L"SAS Window class" diff --git a/reactos/dll/win32/advapi32/service/scm.c b/reactos/dll/win32/advapi32/service/scm.c index 5d6cb3437a5..82fcfc84fb3 100644 --- a/reactos/dll/win32/advapi32/service/scm.c +++ b/reactos/dll/win32/advapi32/service/scm.c @@ -2026,7 +2026,7 @@ StartServiceW(SC_HANDLE hService, dwBufSize += ((wcslen(lpServiceArgVectors[i]) + 1) * sizeof(WCHAR)); } dwBufSize += sizeof(WCHAR); - DPRINT1("dwBufSize: %lu\n", dwBufSize); + DPRINT("dwBufSize: %lu\n", dwBufSize); lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwBufSize); if (lpBuffer == NULL) diff --git a/reactos/dll/win32/kernel32/thread/thread.c b/reactos/dll/win32/kernel32/thread/thread.c index 916091f3030..dab3bf9ddc6 100644 --- a/reactos/dll/win32/kernel32/thread/thread.c +++ b/reactos/dll/win32/kernel32/thread/thread.c @@ -864,13 +864,10 @@ SleepEx(DWORD dwMilliseconds, Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL; } - errCode = NtDelayExecution ((bAlertable ? TRUE : FALSE), &Interval); - if (!NT_SUCCESS(errCode)) - { - SetLastErrorByStatus (errCode); - return -1; - } - return 0; +dowait: + errCode = NtDelayExecution (bAlertable, &Interval); + if ((bAlertable) && (errCode == STATUS_ALERTED)) goto dowait; + return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; } diff --git a/reactos/drivers/base/bootvid/vid.c b/reactos/drivers/base/bootvid/vid.c index 3c9e2daab43..22ea29309b1 100644 --- a/reactos/drivers/base/bootvid/vid.c +++ b/reactos/drivers/base/bootvid/vid.c @@ -43,7 +43,7 @@ VidInitialize( * Check for Xbox by identifying device at PCI 0:0:0, if it's * 0x10de/0x02a5 then we're running on an Xbox. */ - CHECKPOINT1; + CHECKPOINT; WRITE_PORT_ULONG((PULONG)0xcf8, 0x80000000); PciId = READ_PORT_ULONG((PULONG)0xcfc); if (0x02a510de == PciId) diff --git a/reactos/drivers/filesystems/fs_rec/udfs.c b/reactos/drivers/filesystems/fs_rec/udfs.c index 37f00ad418f..cf9e10cb5ed 100644 --- a/reactos/drivers/filesystems/fs_rec/udfs.c +++ b/reactos/drivers/filesystems/fs_rec/udfs.c @@ -232,7 +232,6 @@ FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject) DPRINT ("FsRecDeviceIoControl() failed (Status %lx)\n", Status); return(Status); } - DPRINT1 ("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); /* Check the volume recognition sequence */ Status = FsRecCheckVolumeRecognitionSequence(DeviceObject, diff --git a/reactos/drivers/filesystems/np/fsctrl.c b/reactos/drivers/filesystems/np/fsctrl.c index 97009b596b8..ce383344952 100644 --- a/reactos/drivers/filesystems/np/fsctrl.c +++ b/reactos/drivers/filesystems/np/fsctrl.c @@ -24,7 +24,7 @@ NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject, Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext; - DPRINT1("NpfsListeningCancelRoutine() called for <%wZ>\n", + DPRINT("NpfsListeningCancelRoutine() called for <%wZ>\n", &Waiter->Ccb->Fcb->PipeName); IoReleaseCancelSpinLock(Irp->CancelIrql); diff --git a/reactos/include/ddk/ntifs.h b/reactos/include/ddk/ntifs.h index 365969c1561..2929177a5e7 100644 --- a/reactos/include/ddk/ntifs.h +++ b/reactos/include/ddk/ntifs.h @@ -404,6 +404,7 @@ typedef enum _SECURITY_LOGON_TYPE #define TOKEN_HAS_ADMIN_GROUP 0x08 #define TOKEN_WRITE_RESTRICTED 0x08 #define TOKEN_IS_RESTRICTED 0x10 +#define SE_BACKUP_PRIVILEGES_CHECKED 0x0100 #define VACB_MAPPING_GRANULARITY (0x40000) #define VACB_OFFSET_SHIFT (18) @@ -903,6 +904,19 @@ typedef struct _FILE_FS_VOLUME_INFORMATION { WCHAR VolumeLabel[1]; } FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; +typedef struct _FILE_FS_OBJECTID_INFORMATION +{ + UCHAR ObjectId[16]; + UCHAR ExtendedInfo[48]; +} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; + +typedef struct _FILE_FS_DRIVER_PATH_INFORMATION +{ + BOOLEAN DriverInPath; + ULONG DriverNameLength; + WCHAR DriverName[1]; +} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION; + typedef struct _FILE_FULL_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; @@ -963,6 +977,20 @@ typedef struct _FILE_LOCK_INFO LARGE_INTEGER EndingByte; } FILE_LOCK_INFO, *PFILE_LOCK_INFO; +typedef struct _FILE_REPARSE_POINT_INFORMATION +{ + LONGLONG FileReference; + ULONG Tag; +} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION; + +typedef struct _FILE_MOVE_CLUSTER_INFORMATION +{ + ULONG ClusterCount; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; + /* raw internal file lock struct returned from FsRtlGetNextFileLock */ typedef struct _FILE_SHARED_LOCK_ENTRY { PVOID Unknown1; diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index db1a00fab71..64446fb8a0d 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -1202,8 +1202,8 @@ typedef struct _EX_RUNDOWN_REF { union { - ULONG_PTR Count; - PVOID Ptr; + __volatile ULONG_PTR Count; + __volatile PVOID Ptr; }; } EX_RUNDOWN_REF, *PEX_RUNDOWN_REF; @@ -1298,7 +1298,7 @@ typedef struct _IRP { ULONG Flags; union { struct _IRP *MasterIrp; - LONG IrpCount; + __volatile LONG IrpCount; PVOID SystemBuffer; } AssociatedIrp; LIST_ENTRY ThreadListEntry; @@ -1320,7 +1320,7 @@ typedef struct _IRP { } AsynchronousParameters; LARGE_INTEGER AllocationSize; } Overlay; - PDRIVER_CANCEL CancelRoutine; + __volatile PDRIVER_CANCEL CancelRoutine; PVOID UserBuffer; union { struct { @@ -2123,7 +2123,7 @@ typedef struct _DEVICE_OBJECT { PIO_TIMER Timer; ULONG Flags; ULONG Characteristics; - PVPB Vpb; + __volatile PVPB Vpb; PVOID DeviceExtension; DEVICE_TYPE DeviceType; CCHAR StackSize; @@ -3083,8 +3083,8 @@ typedef struct _ERESOURCE { POWNER_ENTRY OwnerTable; SHORT ActiveCount; USHORT Flag; - PKSEMAPHORE SharedWaiters; - PKEVENT ExclusiveWaiters; + __volatile PKSEMAPHORE SharedWaiters; + __volatile PKEVENT ExclusiveWaiters; OWNER_ENTRY OwnerThreads[2]; ULONG ContentionCount; USHORT NumberOfSharedWaiters; @@ -3393,34 +3393,38 @@ typedef struct _IO_COMPLETION_CONTEXT { #define FO_FILE_OBJECT_HAS_EXTENSION 0x00800000 #define FO_REMOTE_ORIGIN 0x01000000 -typedef struct _FILE_OBJECT { - CSHORT Type; - CSHORT Size; - PDEVICE_OBJECT DeviceObject; - PVPB Vpb; - PVOID FsContext; - PVOID FsContext2; - PSECTION_OBJECT_POINTERS SectionObjectPointer; - PVOID PrivateCacheMap; - NTSTATUS FinalStatus; - struct _FILE_OBJECT *RelatedFileObject; - BOOLEAN LockOperation; - BOOLEAN DeletePending; - BOOLEAN ReadAccess; - BOOLEAN WriteAccess; - BOOLEAN DeleteAccess; - BOOLEAN SharedRead; - BOOLEAN SharedWrite; - BOOLEAN SharedDelete; - ULONG Flags; - UNICODE_STRING FileName; - LARGE_INTEGER CurrentByteOffset; - ULONG Waiters; - ULONG Busy; - PVOID LastLock; - KEVENT Lock; - KEVENT Event; - PIO_COMPLETION_CONTEXT CompletionContext; +typedef struct _FILE_OBJECT +{ + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + PVPB Vpb; + PVOID FsContext; + PVOID FsContext2; + PSECTION_OBJECT_POINTERS SectionObjectPointer; + PVOID PrivateCacheMap; + NTSTATUS FinalStatus; + struct _FILE_OBJECT *RelatedFileObject; + BOOLEAN LockOperation; + BOOLEAN DeletePending; + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + __volatile ULONG Waiters; + __volatile ULONG Busy; + PVOID LastLock; + KEVENT Lock; + KEVENT Event; + __volatile PIO_COMPLETION_CONTEXT CompletionContext; + KSPIN_LOCK IrpListLock; + LIST_ENTRY IrpList; + __volatile PVOID FileObjectExtension; } FILE_OBJECT; typedef struct _FILE_OBJECT *PFILE_OBJECT; @@ -4397,7 +4401,7 @@ typedef struct _IO_REMOVE_LOCK_TRACKING_BLOCK * PIO_REMOVE_LOCK_TRACKING_BLOCK; typedef struct _IO_REMOVE_LOCK_COMMON_BLOCK { BOOLEAN Removed; BOOLEAN Reserved[3]; - LONG IoCount; + __volatile LONG IoCount; KEVENT RemoveEvent; } IO_REMOVE_LOCK_COMMON_BLOCK; @@ -4408,7 +4412,7 @@ typedef struct _IO_REMOVE_LOCK_DBG_BLOCK { LONG AllocateTag; LIST_ENTRY LockList; KSPIN_LOCK Spin; - LONG LowMemoryCount; + __volatile LONG LowMemoryCount; ULONG Reserved1[4]; PVOID Reserved2; PIO_REMOVE_LOCK_TRACKING_BLOCK Blocks; @@ -4579,7 +4583,7 @@ typedef VOID typedef struct _WORK_QUEUE_ITEM { LIST_ENTRY List; PWORKER_THREAD_ROUTINE WorkerRoutine; - PVOID Parameter; + __volatile PVOID Parameter; } WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM; typedef enum _KBUGCHECK_CALLBACK_REASON { diff --git a/reactos/lib/rtl/exception.c b/reactos/lib/rtl/exception.c index 99b49ab0aef..96953c220af 100644 --- a/reactos/lib/rtl/exception.c +++ b/reactos/lib/rtl/exception.c @@ -27,8 +27,9 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) CONTEXT Context; NTSTATUS Status; - /* Capture the context */ + /* Capture the context and fixup ESP */ RtlCaptureContext(&Context); + Context.Esp += sizeof(ULONG); /* Save the exception address */ ExceptionRecord->ExceptionAddress = RtlpGetExceptionAddress(); @@ -57,8 +58,8 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) } } - /* If we returned, raise a status */ - RtlRaiseStatus(Status); + /* We should never return */ + while (TRUE); } /* diff --git a/reactos/lib/rtl/i386/exception.c b/reactos/lib/rtl/i386/exception.c index feb2ef07154..edfb835d811 100644 --- a/reactos/lib/rtl/i386/exception.c +++ b/reactos/lib/rtl/i386/exception.c @@ -100,6 +100,7 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, sizeof(*RegistrationFrame)); /* Call the handler */ + DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler); Disposition = RtlpExecuteHandlerForException(ExceptionRecord, RegistrationFrame, Context, diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index 279c31c7c87..40543a4c39c 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -8,16 +8,6 @@ // Do NOT ask when it will be fixed. // Failure to respect this will *ACHIEVE NOTHING*. // -// Io: -// - See why queueing IRPs and cancelling them causes crashes. -// - Add Access Checks in IopParseDevice. -// - Add validation checks in IoCreateFile. -// - Add probe/alignment checks for Query/Set routines. -// - Add tracing to iofunc.c -// - Add tracing to file.c -// - Add support for some fast-paths when querying/setting data. -// - Verify ShareAccess APIs, XP added some new semantics. -// - Add support for Fast Dispatch I/O. // // Ob: // - Fix bug related to Deferred Loading (don't requeue active work item). @@ -28,6 +18,7 @@ // // Ke: // - Figure out why the DPC stack doesn't really work. +// - Fix SEH/Page Fault + Exceptions!? Weird exception bugs! // - New optimized table-based tick-hashed timer implementation. // - New Thread Scheduler based on 2003. // - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. @@ -46,7 +37,6 @@ // - Use pushlocks for handle implementation. // // Kd: -// - Implement new KDCOM with KD support. // - Implement KD Kernel Debugging and WinDBG support. // // Native: diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c index 900fed9f95a..1501da83d47 100644 --- a/reactos/ntoskrnl/cm/import.c +++ b/reactos/ntoskrnl/cm/import.c @@ -70,7 +70,7 @@ CmImportBinaryHive (PCHAR ChunkBase, KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); - DPRINT1("Adding new hive\n"); + DPRINT("Adding new hive\n"); /* Add the new hive to the hive list */ InsertTailList(&CmiHiveListHead, &Hive->HiveList); diff --git a/reactos/ntoskrnl/dbgk/debug.c b/reactos/ntoskrnl/dbgk/debug.c index a51373431b7..6bdc0689db5 100644 --- a/reactos/ntoskrnl/dbgk/debug.c +++ b/reactos/ntoskrnl/dbgk/debug.c @@ -14,7 +14,7 @@ POBJECT_TYPE DbgkDebugObjectType; FAST_MUTEX DbgkpProcessDebugPortMutex; -ULONG DbgkpTraceLevel = -1; +ULONG DbgkpTraceLevel = 0; //-1; GENERIC_MAPPING DbgkDebugObjectMapping = { diff --git a/reactos/ntoskrnl/fstub/disksup.c b/reactos/ntoskrnl/fstub/disksup.c index dca4fd29e78..84353bcb939 100644 --- a/reactos/ntoskrnl/fstub/disksup.c +++ b/reactos/ntoskrnl/fstub/disksup.c @@ -1372,7 +1372,7 @@ IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, /* Get the end and maximum sector */ EndSector = MaxOffset; MaxSector = MaxOffset << 1; - DPRINT1("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n", + DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n", MaxOffset, MaxSector); /* Allocate our buffer */ @@ -1458,19 +1458,19 @@ IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, /* Start looping partitions */ j++; - DPRINT1("FSTUB: Partition Table %d:\n", j); + DPRINT("FSTUB: Partition Table %d:\n", j); for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++) { /* Get the partition type */ PartitionType = PartitionDescriptor->PartitionType; /* Print debug messages */ - DPRINT1("Partition Entry %d,%d: type %#x %s\n", + DPRINT("Partition Entry %d,%d: type %#x %s\n", j, Entry, PartitionType, (PartitionDescriptor->ActiveFlag) ? "Active" : ""); - DPRINT1("\tOffset %#08lx for %#08lx Sectors\n", + DPRINT("\tOffset %#08lx for %#08lx Sectors\n", GET_STARTING_SECTOR(PartitionDescriptor), GET_PARTITION_LENGTH(PartitionDescriptor)); @@ -1615,7 +1615,7 @@ IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, } /* Finish debug log, and check for failure */ - DPRINT1("\n"); + DPRINT("\n"); if (!NT_SUCCESS(Status)) break; /* Also check if we hit an invalid entry here */ diff --git a/reactos/ntoskrnl/inbv/inbv.c b/reactos/ntoskrnl/inbv/inbv.c index 92f285b4612..b652ef8d6fa 100644 --- a/reactos/ntoskrnl/inbv/inbv.c +++ b/reactos/ntoskrnl/inbv/inbv.c @@ -118,7 +118,7 @@ InbvDisplayInitialize(VOID) return; } - DPRINT1("Done!\n"); + DPRINT("Done!\n"); KeInitializeSpinLock(&InbvLock); BootVidBase = ModuleObject->DllBase; BootVidDriverInstalled = TRUE; diff --git a/reactos/ntoskrnl/include/internal/debug.h b/reactos/ntoskrnl/include/internal/debug.h index cbf943683b6..42e8d85b00b 100644 --- a/reactos/ntoskrnl/include/internal/debug.h +++ b/reactos/ntoskrnl/include/internal/debug.h @@ -46,7 +46,7 @@ /* TODO: Verify which version the MS compiler learned the __FUNCTION__ macro */ #define __FUNCTION__ "" #endif -#define UNIMPLEMENTED do {DbgPrint("%s at %s:%d is unimplemented, have a nice day\n",__FUNCTION__,__FILE__,__LINE__); for(;;); } while(0) +#define UNIMPLEMENTED DbgPrint("%s at %s:%d is unimplemented, have a nice day\n",__FUNCTION__,__FILE__,__LINE__); #ifdef assert diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 312f952c403..907c147d071 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -10,25 +10,40 @@ // // Define this if you want debugging support // -#define _IO_DEBUG_ 0x00 +#define _IO_DEBUG_ 0x01 // // These define the Debug Masks Supported // #define IO_IRP_DEBUG 0x01 +#define IO_FILE_DEBUG 0x02 +#define IO_API_DEBUG 0x04 +#define IO_CTL_DEBUG 0x08 // // Debug/Tracing support // #if _IO_DEBUG_ #ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented -#define IOTRACE DbgPrintEx +#define IOTRACE(x, ...) \ + { \ + DbgPrintEx("%s [%.16s] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName); \ + DbgPrintEx(__VA_ARGS__); \ + } #else -#define IOTRACE(x, ...) \ - if (x & IopTraceLevel) DbgPrint(__VA_ARGS__) +#define IOTRACE(x, ...) \ + if (x & IopTraceLevel) \ + { \ + DbgPrint("%s [%.16s] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName); \ + DbgPrint(__VA_ARGS__); \ + } #endif #else -#define IOTRACE(x, ...) DPRINT(__VA_ARGS__) +#define IOTRACE(x, ...) DPRINT(__VA_ARGS__); #endif // diff --git a/reactos/ntoskrnl/include/internal/io_x.h b/reactos/ntoskrnl/include/internal/io_x.h index 62ebd573240..9d9464421a0 100644 --- a/reactos/ntoskrnl/include/internal/io_x.h +++ b/reactos/ntoskrnl/include/internal/io_x.h @@ -28,7 +28,7 @@ IopUnlockFileObject(IN PFILE_OBJECT FileObject) } VOID -static __inline +FORCEINLINE IopQueueIrpToThread(IN PIRP Irp) { KIRQL OldIrql; diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 47ecebc7b17..c6fe3dffbab 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -251,6 +251,12 @@ ObDuplicateObject( IN KPROCESSOR_MODE PreviousMode ); +VOID +NTAPI +ObFreeObjectCreateInfoBuffer( + IN POBJECT_CREATE_INFORMATION ObjectCreateInfo +); + // // DOS Devices Functions // diff --git a/reactos/ntoskrnl/io/iomgr/device.c b/reactos/ntoskrnl/io/iomgr/device.c index a0ea1cf262f..888613d9e51 100644 --- a/reactos/ntoskrnl/io/iomgr/device.c +++ b/reactos/ntoskrnl/io/iomgr/device.c @@ -329,32 +329,6 @@ IopDereferenceDeviceObject(IN PDEVICE_OBJECT DeviceObject, } } -NTSTATUS -NTAPI -IopReferenceDeviceObject(IN PDEVICE_OBJECT DeviceObject) -{ - /* Make sure the object is valid */ - if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags & - (DOE_UNLOAD_PENDING | - DOE_DELETE_PENDING | - DOE_REMOVE_PENDING | - DOE_REMOVE_PROCESSED)) || - (DeviceObject->Flags & DO_DEVICE_INITIALIZING)) - { - /* It's unloading or initializing, so fail */ - DPRINT1("You are seeing this because the following ROS driver: %wZ\n" - " sucks. Please fix it's AddDevice Routine\n", - &DeviceObject->DriverObject->DriverName); - return STATUS_NO_SUCH_DEVICE; - } - else - { - /* Increase reference count */ - DeviceObject->ReferenceCount++; - return STATUS_SUCCESS; - } -} - VOID NTAPI IopStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject, @@ -921,8 +895,14 @@ VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice) { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Sanity check */ + DeviceExtension = IoGetDevObjExtension(TargetDevice->AttachedDevice); + ASSERT(DeviceExtension->AttachedTo == TargetDevice); + /* Remove the attachment */ - IoGetDevObjExtension(TargetDevice->AttachedDevice)->AttachedTo = NULL; + DeviceExtension->AttachedTo = NULL; TargetDevice->AttachedDevice = NULL; /* Check if it's ok to delete this device */ @@ -1173,9 +1153,27 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject) DeviceObject = FileObject->DeviceObject; } + /* Sanity check */ + ASSERT(DeviceObject != NULL); + /* Check if we were attached */ if (DeviceObject->AttachedDevice) { + /* Check if the file object has an extension present */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) + { + /* Sanity check, direct open files can't have this */ + ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); + + /* Check if the extension is really present */ + if (FileObject->FileObjectExtension) + { + /* FIXME: Unhandled yet */ + DPRINT1("FOEs not supported\n"); + KEBUGCHECK(0); + } + } + /* Return the highest attached device */ DeviceObject = IoGetAttachedDevice(DeviceObject); } @@ -1216,6 +1214,7 @@ IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject) } /* Return the device object we found */ + ASSERT(DeviceObject != NULL); return DeviceObject; } diff --git a/reactos/ntoskrnl/io/iomgr/file.c b/reactos/ntoskrnl/io/iomgr/file.c index 0cc4648b772..da09a2588a5 100644 --- a/reactos/ntoskrnl/io/iomgr/file.c +++ b/reactos/ntoskrnl/io/iomgr/file.c @@ -13,17 +13,155 @@ #include #define NDEBUG -#include - -#if 0 - IOTRACE(IO_IRP_DEBUG, - "%s - Queueing IRP %p\n", - __FUNCTION__, - Irp); -#endif +#include /* PRIVATE FUNCTIONS *********************************************************/ +VOID +NTAPI +IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState, + IN OUT PULONG CreateOptions, + IN KPROCESSOR_MODE PreviousMode, + IN ULONG Disposition) +{ + ACCESS_MASK DesiredAccess, ReadAccess, WriteAccess; + PRIVILEGE_SET Privileges; + BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE; + PAGED_CODE(); + + /* Don't do anything if privileges were checked already */ + if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return; + + /* Check if the file was actually opened for backup purposes */ + if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT) + { + /* Set the check flag since were doing it now */ + AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED; + + /* Set the access masks required */ + ReadAccess = READ_CONTROL | + ACCESS_SYSTEM_SECURITY | + FILE_GENERIC_READ | + FILE_TRAVERSE; + WriteAccess = WRITE_DAC | + WRITE_OWNER | + ACCESS_SYSTEM_SECURITY | + FILE_GENERIC_WRITE | + FILE_ADD_FILE | + FILE_ADD_SUBDIRECTORY | + DELETE; + DesiredAccess = AccessState->RemainingDesiredAccess; + + /* Check if desired access was the maximum */ + if (DesiredAccess & MAXIMUM_ALLOWED) + { + /* Then add all the access masks required */ + DesiredAccess |= (ReadAccess | WriteAccess); + } + + /* Check if the file already exists */ + if (Disposition & FILE_OPEN) + { + /* Check if desired access has the read mask */ + if (ReadAccess & DesiredAccess) + { + /* Setup the privilege check lookup */ + Privileges.PrivilegeCount = 1; + Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; + Privileges.Privilege[0].Luid = SeBackupPrivilege; + Privileges.Privilege[0].Attributes = 0; + AccessGranted = SePrivilegeCheck(&Privileges, + &AccessState-> + SubjectSecurityContext, + PreviousMode); + if (AccessGranted) + { + /* Remember that backup was allowed */ + HaveBackupPriv = TRUE; + + /* Append the privileges and update the access state */ + SeAppendPrivileges(AccessState, &Privileges); + AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess); + AccessState->RemainingDesiredAccess &= ~ReadAccess; + DesiredAccess &= ~ReadAccess; + + /* Set backup privilege for the token */ + AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE; + } + } + } + else + { + /* Caller is creating the file, check restore privileges later */ + CheckRestore = TRUE; + } + + /* Check if caller wants write access or if it's creating a file */ + if ((WriteAccess & DesiredAccess) || (CheckRestore)) + { + /* Setup the privilege lookup and do it */ + Privileges.PrivilegeCount = 1; + Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; + Privileges.Privilege[0].Luid = SeRestorePrivilege; + Privileges.Privilege[0].Attributes = 0; + AccessGranted = SePrivilegeCheck(&Privileges, + &AccessState->SubjectSecurityContext, + PreviousMode); + if (AccessGranted) + { + /* Remember that privilege was given */ + HaveBackupPriv = TRUE; + + /* Append the privileges and update the access state */ + SeAppendPrivileges(AccessState, &Privileges); + AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess); + AccessState->RemainingDesiredAccess &= ~WriteAccess; + + /* Set restore privilege for the token */ + AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE; + } + } + + /* If we don't have the privilege, remove the option */ + if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT; + } +} + +NTSTATUS +NTAPI +IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket, + IN PDEVICE_OBJECT DeviceObject) +{ + /* Make sure the object is valid */ + if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags & + (DOE_UNLOAD_PENDING | + DOE_DELETE_PENDING | + DOE_REMOVE_PENDING | + DOE_REMOVE_PROCESSED)) || + (DeviceObject->Flags & DO_DEVICE_INITIALIZING)) + { + /* It's unloading or initializing, so fail */ + DPRINT1("You are seeing this because the following ROS driver: %wZ\n" + " sucks. Please fix it's AddDevice Routine\n", + &DeviceObject->DriverObject->DriverName); + return STATUS_NO_SUCH_DEVICE; + } + else if ((DeviceObject->Flags & DO_EXCLUSIVE) && + (DeviceObject->ReferenceCount) && + !(OpenPacket->RelatedFileObject) && + !(OpenPacket->Options & IO_ATTACH_DEVICE)) + { + return STATUS_ACCESS_DENIED; + } + + else + { + /* Increase reference count */ + DeviceObject->ReferenceCount++; + return STATUS_SUCCESS; + } +} + NTSTATUS NTAPI IopParseDevice(IN PVOID ParseObject, @@ -53,6 +191,13 @@ IopParseDevice(IN PVOID ParseObject, PDUMMY_FILE_OBJECT DummyFileObject; PFILE_BASIC_INFORMATION FileBasicInfo; ULONG ReturnLength; + KPROCESSOR_MODE CheckMode; + BOOLEAN VolumeOpen = FALSE; + ACCESS_MASK DesiredAccess, GrantedAccess; + BOOLEAN AccessGranted, LockHeld = FALSE; + PPRIVILEGE_SET Privileges = NULL; + IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n", + ParseObject, RemainingName); /* Assume failure */ *Object = NULL; @@ -67,8 +212,8 @@ IopParseDevice(IN PVOID ParseObject, OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject; } - /* Reference the DO */ - Status = IopReferenceDeviceObject(OriginalDeviceObject); + /* Validate device status */ + Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject); if (!NT_SUCCESS(Status)) { /* We failed, return status */ @@ -83,6 +228,161 @@ IopParseDevice(IN PVOID ParseObject, &IoFileObjectType->TypeInfo.GenericMapping); SeSetAccessStateGenericMapping(AccessState, &IoFileObjectType->TypeInfo.GenericMapping); + DesiredAccess = AccessState->RemainingDesiredAccess; + + /* Check what kind of access checks to do */ + if ((AccessMode != KernelMode) || + (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) + { + /* Call is from user-mode or kernel is forcing checks */ + CheckMode = UserMode; + } + else + { + /* Call is from the kernel */ + CheckMode = KernelMode; + } + + /* Check privilege for backup or restore operation */ + IopCheckBackupRestorePrivilege(AccessState, + &OpenPacket->CreateOptions, + CheckMode, + OpenPacket->Disposition); + + /* Check if we are re-parsing */ + if (((OpenPacket->Override) && !(RemainingName->Length)) || + (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED)) + { + /* Get granted access from the last call */ + DesiredAccess |= AccessState->PreviouslyGrantedAccess; + } + + /* Check if this is a volume open */ + if ((OpenPacket->RelatedFileObject) && + (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) && + !(RemainingName->Length)) + { + /* It is */ + VolumeOpen = TRUE; + } + + /* Now check if we need access checks */ + if (((AccessMode != KernelMode) || + (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) && + (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) && + !(OpenPacket->Override)) + { + /* Check if a device object is being parsed */ + if (!RemainingName->Length) + { + /* Lock the subject context */ + SeLockSubjectContext(&AccessState->SubjectSecurityContext); + LockHeld = TRUE; + + /* Do access check */ + AccessGranted = SeAccessCheck(OriginalDeviceObject-> + SecurityDescriptor, + &AccessState->SubjectSecurityContext, + LockHeld, + DesiredAccess, + 0, + &Privileges, + &IoFileObjectType-> + TypeInfo.GenericMapping, + UserMode, + &GrantedAccess, + &Status); + if (Privileges) + { + /* Append and free the privileges */ + SeAppendPrivileges(AccessState, Privileges); + SeFreePrivileges(Privileges); + } + + /* Check if we got access */ + if (AccessGranted) + { + /* Update access state */ + AccessState->PreviouslyGrantedAccess |= GrantedAccess; + AccessState->RemainingDesiredAccess &= ~(GrantedAccess & + MAXIMUM_ALLOWED); + OpenPacket->Override= TRUE; + } + + /* FIXME: Do Audit/Alarm for open operation */ + } + else + { + /* Check if we need to do traverse validation */ + if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) || + ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) || + (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM))) + { + /* Check if this is a restricted token */ + if (!(AccessState->Flags & TOKEN_IS_RESTRICTED)) + { + /* FIXME: Do the FAST traverse check */ + AccessGranted = FALSE; + } + else + { + /* Fail */ + AccessGranted = FALSE; + } + + /* Check if we failed to get access */ + if (!AccessGranted) + { + /* Lock the subject context */ + SeLockSubjectContext(&AccessState->SubjectSecurityContext); + LockHeld = TRUE; + + /* Do access check */ + AccessGranted = SeAccessCheck(OriginalDeviceObject-> + SecurityDescriptor, + &AccessState->SubjectSecurityContext, + LockHeld, + FILE_TRAVERSE, + 0, + &Privileges, + &IoFileObjectType-> + TypeInfo.GenericMapping, + UserMode, + &GrantedAccess, + &Status); + if (Privileges) + { + /* Append and free the privileges */ + SeAppendPrivileges(AccessState, Privileges); + SeFreePrivileges(Privileges); + } + } + + /* FIXME: Do Audit/Alarm for traverse check */ + } + else + { + /* Access automatically granted */ + AccessGranted = TRUE; + } + } + + /* Check if we hold the lock */ + if (LockHeld) + { + /* Release it */ + SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); + } + + /* Check if access failed */ + if (!AccessGranted) + { + /* Dereference the device and fail */ + DPRINT1("Traverse access failed!\n"); + IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); + return STATUS_ACCESS_DENIED; + } + } /* Check if we can simply use a dummy file */ UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly)); @@ -90,8 +390,27 @@ IopParseDevice(IN PVOID ParseObject, /* Check if this is a direct open */ if (!(RemainingName->Length) && !(OpenPacket->RelatedFileObject) && +#if 0 // USETUP IS BROKEN! + ((DesiredAccess & ~(SYNCHRONIZE | + FILE_READ_ATTRIBUTES | + READ_CONTROL | + ACCESS_SYSTEM_SECURITY | + WRITE_OWNER | + WRITE_DAC)) && +#endif !(UseDummyFile)) { + if (DesiredAccess & ~(SYNCHRONIZE | + FILE_READ_ATTRIBUTES | + READ_CONTROL | + ACCESS_SYSTEM_SECURITY | + WRITE_OWNER | + WRITE_DAC)) + { + DPRINT1("FIXME: Broken Parse due to invalid DesiredAccess: %lx\n", + DesiredAccess); + } + /* Remember this for later */ DirectOpen = TRUE; } @@ -140,6 +459,14 @@ IopParseDevice(IN PVOID ParseObject, } } + /* Check if this is a secure FSD */ + if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) && + ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) && + (!VolumeOpen)) + { + DPRINT1("Fix Secure FSD support!!!\n"); + } + /* Allocate the IRP */ Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); if (!Irp) @@ -272,7 +599,7 @@ IopParseDevice(IN PVOID ParseObject, /* Check if this is synch I/O */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { - /* Initialize the event. FIXME: Should be FALSE */ + /* Initialize the event */ KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE); } @@ -373,7 +700,7 @@ IopParseDevice(IN PVOID ParseObject, OpenPacket->FileObject = FileObject; /* Queue the IRP and call the driver */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { @@ -404,7 +731,7 @@ IopParseDevice(IN PVOID ParseObject, FileObject->Event.Header.SignalState = 1; /* Now that we've signaled the events, de-associate the IRP */ - //IopUnQueueIrpFromThread(Irp); + IopUnQueueIrpFromThread(Irp); /* Check if the IRP had an input buffer */ if ((Irp->Flags & IRP_BUFFERED_IO) && @@ -614,6 +941,10 @@ IopDeleteFile(IN PVOID ObjectBody) NTSTATUS Status; KEVENT Event; PDEVICE_OBJECT DeviceObject; + BOOLEAN DereferenceDone = FALSE; + PVPB Vpb; + KIRQL OldIrql; + IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); /* Check if the file has a device object */ if (FileObject->DeviceObject) @@ -630,11 +961,15 @@ IopDeleteFile(IN PVOID ObjectBody) DeviceObject = IoGetRelatedDeviceObject(FileObject); } - /* Check if this file was opened for Synch I/O */ - if (FileObject->Flags & FO_SYNCHRONOUS_IO) + /* Sanity check */ + ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) || + (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE)); + + /* Check if the handle wasn't created yet */ + if (!(FileObject->Flags & FO_HANDLE_CREATED)) { - /* Lock it */ - IopLockFileObject(FileObject); + /* Send the cleanup IRP */ + IopCloseFile(NULL, ObjectBody, 0, 1, 1); } /* Clear and set up Events */ @@ -658,7 +993,23 @@ IopDeleteFile(IN PVOID ObjectBody) StackPtr->FileObject = FileObject; /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); + + /* Get the VPB and check if this isn't a direct open */ + Vpb = FileObject->Vpb; + if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) + { + /* Dereference the VPB before the close */ + InterlockedDecrement(&Vpb->ReferenceCount); + } + + /* Check if the FS will never disappear by itself */ + if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE) + { + /* Dereference it */ + InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount); + DereferenceDone = TRUE; + } /* Call the FS Driver */ Status = IoCallDriver(DeviceObject, Irp); @@ -668,6 +1019,11 @@ IopDeleteFile(IN PVOID ObjectBody) KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } + /* De-queue the IRP */ + KeRaiseIrql(APC_LEVEL, &OldIrql); + IopUnQueueIrpFromThread(Irp); + KeLowerIrql(OldIrql); + /* Free the IRP */ IoFreeIrp(Irp); @@ -686,7 +1042,12 @@ IopDeleteFile(IN PVOID ObjectBody) ExFreePool(FileObject->CompletionContext); } - /* FIXME: Dereference device object */ + /* Check if dereference has been done yet */ + if (!DereferenceDone) + { + /* Dereference device object */ + IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE); + } } } @@ -710,6 +1071,7 @@ IopSecurityFile(IN PVOID ObjectBody, KEVENT Event; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); /* Check if this is a device or file */ if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE) @@ -737,7 +1099,9 @@ IopSecurityFile(IN PVOID ObjectBody, } /* Check if the request was for a device object */ - if (!(FileObject) || (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) + if (!(FileObject) || + (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) || + (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { /* Check what kind of request this was */ if (OperationCode == QuerySecurityDescriptor) @@ -834,7 +1198,7 @@ IopSecurityFile(IN PVOID ObjectBody, } /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Update operation counts */ IopUpdateOperationCount(IopOtherTransfer); @@ -862,7 +1226,7 @@ IopSecurityFile(IN PVOID ObjectBody, /* Check if the IRP is pending completion */ if (Status == STATUS_PENDING) { - /* Wait on the file obejct */ + /* Wait on the file object */ KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, @@ -920,6 +1284,7 @@ IopQueryNameFile(IN PVOID ObjectBody, ULONG LocalReturnLength, FileLength; NTSTATUS Status; PWCHAR p; + IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); /* Validate length */ if (Length < sizeof(OBJECT_NAME_INFORMATION)) @@ -987,7 +1352,7 @@ IopQueryNameFile(IN PVOID ObjectBody, /* ROS HACK. VFAT SUCKS */ if (NT_WARNING(Status)) LocalReturnLength = FileLength; - /* Now calculate the new lenghts left */ + /* Now calculate the new lengths left */ FileLength = LocalReturnLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); LocalReturnLength = (ULONG_PTR)p - @@ -1028,6 +1393,8 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL, PIO_STACK_LOCATION StackPtr; NTSTATUS Status; PDEVICE_OBJECT DeviceObject; + KIRQL OldIrql; + IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); /* Check if the file is locked and has more then one handle opened */ if ((FileObject->LockOperation) && (SystemHandleCount != 1)) @@ -1079,7 +1446,7 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL, StackPtr->FileObject = FileObject; /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Update operation counts */ IopUpdateOperationCount(IopOtherTransfer); @@ -1092,6 +1459,11 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL, KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); } + /* Unqueue the IRP */ + KeRaiseIrql(APC_LEVEL, &OldIrql); + IopUnQueueIrpFromThread(Irp); + KeLowerIrql(OldIrql); + /* Free the IRP */ IoFreeIrp(Irp); @@ -1114,6 +1486,7 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, OPEN_PACKET OpenPacket; BOOLEAN IsBasic; PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass); /* Check if the caller was user mode */ if (AccessMode != KernelMode) @@ -1211,7 +1584,7 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, * @unimplemented */ NTSTATUS -STDCALL +NTAPI IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN BOOLEAN SetOperation) @@ -1242,12 +1615,12 @@ IoCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, - IN ULONG CreateDisposition, + IN ULONG Disposition, IN ULONG CreateOptions, - IN PVOID EaBuffer OPTIONAL, + IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, @@ -1260,17 +1633,22 @@ IoCreateFile(OUT PHANDLE FileHandle, NTSTATUS Status = STATUS_SUCCESS; OPEN_PACKET OpenPacket; PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); - if(Options & IO_NO_PARAMETER_CHECKING) + /* Check if we have no parameter checking to do */ + if (Options & IO_NO_PARAMETER_CHECKING) { + /* Then force kernel-mode access to avoid checks */ AccessMode = KernelMode; } else { + /* Otherwise, use the actual mode */ AccessMode = ExGetPreviousMode(); } - if(AccessMode != KernelMode) + /* Check if the call came from user mode */ + if (AccessMode != KernelMode) { _SEH_TRY { @@ -1314,27 +1692,47 @@ IoCreateFile(OUT PHANDLE FileHandle, } else { + /* Check if this is a device attach */ + if (CreateOptions & IO_ATTACH_DEVICE_API) + { + /* Set the flag properly */ + Options |= IO_ATTACH_DEVICE; + CreateOptions &= ~IO_ATTACH_DEVICE_API; + } + + /* Check if we have allocation size */ if (AllocationSize) { + /* Capture it */ SafeAllocationSize = *AllocationSize; } else { + /* Otherwise, no size */ SafeAllocationSize.QuadPart = 0; } + /* Check if we have an EA packet */ if ((EaBuffer) && (EaLength)) { + /* Allocate the kernel copy */ SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool, EaLength, TAG_EA); - RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength); - } - } + if (!SystemEaBuffer) return STATUS_INSUFFICIENT_RESOURCES; - if(Options & IO_CHECK_CREATE_PARAMETERS) - { - DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n"); + /* Copy the data */ + RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength); + + /* Validate the buffer */ + Status = IoCheckEaBufferValidity(SystemEaBuffer, + EaLength, + NULL); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Fail once function is implemented */ + } + } } /* Setup the Open Packet */ @@ -1349,7 +1747,7 @@ IoCreateFile(OUT PHANDLE FileHandle, OpenPacket.EaBuffer = SystemEaBuffer; OpenPacket.EaLength = EaLength; OpenPacket.Options = Options; - OpenPacket.Disposition = CreateDisposition; + OpenPacket.Disposition = Disposition; OpenPacket.CreateFileType = CreateFileType; OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters; @@ -1496,28 +1894,40 @@ IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle, */ PFILE_OBJECT NTAPI -IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, - IN PDEVICE_OBJECT DeviceObject) +IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + OUT PHANDLE FileObjectHandle OPTIONAL) { PFILE_OBJECT CreatedFileObject; NTSTATUS Status; HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); + + /* Choose Device Object */ + if (FileObject) DeviceObject = FileObject->DeviceObject; + + /* Reference the device object and initialize attributes */ + InterlockedIncrement(&DeviceObject->ReferenceCount); + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); /* Create the File Object */ Status = ObCreateObject(KernelMode, IoFileObjectType, - NULL, + &ObjectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), sizeof(FILE_OBJECT), 0, (PVOID*)&CreatedFileObject); - if (!NT_SUCCESS(Status)) return NULL; - - /* Choose Device Object */ - if (FileObject) DeviceObject = FileObject->DeviceObject; + if (!NT_SUCCESS(Status)) + { + /* Fail */ + IopDereferenceDeviceObject(DeviceObject, FALSE); + ExRaiseStatus(Status); + } /* Set File Object Data */ RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); @@ -1536,38 +1946,114 @@ IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, 1, (PVOID*)&CreatedFileObject, &FileHandle); + if (!NT_SUCCESS(Status)) ExRaiseStatus(Status); + + /* Set the handle created flag */ CreatedFileObject->Flags |= FO_HANDLE_CREATED; + ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); - /* FIXME: Reference VPB */ + /* Check if we have a VPB */ + if (DeviceObject->Vpb) + { + /* Reference it */ + InterlockedIncrement(&DeviceObject->Vpb->ReferenceCount); + } - /* Close the extra handle and return file */ - NtClose(FileHandle); + /* Check if the caller wants the handle */ + if (FileObjectHandle) + { + /* Return it */ + *FileObjectHandle = FileHandle; + ObDereferenceObject(CreatedFileObject); + } + else + { + /* Otherwise, close it */ + ObCloseHandle(FileHandle, KernelMode); + } + + /* Return the file object */ return CreatedFileObject; } /* - * @unimplemented + * @implemented */ PFILE_OBJECT NTAPI -IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL, - IN PDEVICE_OBJECT DeviceObject OPTIONAL, - OUT PHANDLE FileObjectHandle OPTIONAL) +IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED; - return 0; + /* Call the newer function */ + return IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL); } /* - * @unimplemented + * @implemented */ PFILE_OBJECT NTAPI IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL) { - UNIMPLEMENTED; - return 0; + PFILE_OBJECT CreatedFileObject; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); + + /* Choose Device Object */ + if (FileObject) DeviceObject = FileObject->DeviceObject; + + /* Reference the device object and initialize attributes */ + InterlockedIncrement(&DeviceObject->ReferenceCount); + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + + /* Create the File Object */ + Status = ObCreateObject(KernelMode, + IoFileObjectType, + &ObjectAttributes, + KernelMode, + NULL, + sizeof(FILE_OBJECT), + sizeof(FILE_OBJECT), + 0, + (PVOID*)&CreatedFileObject); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + IopDereferenceDeviceObject(DeviceObject, FALSE); + ExRaiseStatus(Status); + } + + /* Set File Object Data */ + RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); + CreatedFileObject->DeviceObject = DeviceObject; + CreatedFileObject->Type = IO_TYPE_FILE; + CreatedFileObject->Size = sizeof(FILE_OBJECT); + CreatedFileObject->Flags = FO_STREAM_FILE; + + /* Initialize the wait event */ + KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); + + /* Destroy create information */ + ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject)-> + ObjectCreateInfo); + OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL; + + /* Set the handle created flag */ + CreatedFileObject->Flags |= FO_HANDLE_CREATED; + ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); + + /* Check if we have a VPB */ + if (DeviceObject->Vpb) + { + /* Reference it */ + InterlockedIncrement(&DeviceObject->Vpb->ReferenceCount); + } + + /* Return the file object */ + return CreatedFileObject; } /* @@ -1608,6 +2094,7 @@ IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, HANDLE Handle; OPEN_PACKET OpenPacket; PAGED_CODE(); + IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); /* Setup the Open Packet */ RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); @@ -1663,12 +2150,26 @@ IoUpdateShareAccess(IN PFILE_OBJECT FileObject, { PAGED_CODE(); - if (FileObject->ReadAccess || - FileObject->WriteAccess || - FileObject->DeleteAccess) + /* Check if the file has an extension */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) { + /* Check if caller specified to ignore access checks */ + //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) + { + /* Don't update share access */ + return; + } + } + + /* Otherwise, check if there's any access present */ + if ((FileObject->ReadAccess) || + (FileObject->WriteAccess) || + (FileObject->DeleteAccess)) + { + /* Increase the open count */ ShareAccess->OpenCount++; + /* Add new share access */ ShareAccess->Readers += FileObject->ReadAccess; ShareAccess->Writers += FileObject->WriteAccess; ShareAccess->Deleters += FileObject->DeleteAccess; @@ -1697,38 +2198,62 @@ IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, BOOLEAN SharedDelete; PAGED_CODE(); + /* Get access masks */ ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; DeleteAccess = (DesiredAccess & DELETE) != 0; + /* Set them in the file object */ FileObject->ReadAccess = ReadAccess; FileObject->WriteAccess = WriteAccess; FileObject->DeleteAccess = DeleteAccess; - if (ReadAccess || WriteAccess || DeleteAccess) + /* Check if the file has an extension */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) { + /* Check if caller specified to ignore access checks */ + //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) + { + /* Don't check share access */ + return STATUS_SUCCESS; + } + } + + /* Check if we have any access */ + if ((ReadAccess) || (WriteAccess) || (DeleteAccess)) + { + /* Get shared access masks */ SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; + /* Set them */ FileObject->SharedRead = SharedRead; FileObject->SharedWrite = SharedWrite; FileObject->SharedDelete = SharedDelete; - if ((ReadAccess && (ShareAccess->SharedRead < ShareAccess->OpenCount)) || - (WriteAccess && (ShareAccess->SharedWrite < ShareAccess->OpenCount)) || - (DeleteAccess && (ShareAccess->SharedDelete < ShareAccess->OpenCount)) || + /* Check if the shared access is violated */ + if ((ReadAccess && + (ShareAccess->SharedRead < ShareAccess->OpenCount)) || + (WriteAccess && + (ShareAccess->SharedWrite < ShareAccess->OpenCount)) || + (DeleteAccess && + (ShareAccess->SharedDelete < ShareAccess->OpenCount)) || ((ShareAccess->Readers != 0) && !SharedRead) || ((ShareAccess->Writers != 0) && !SharedWrite) || ((ShareAccess->Deleters != 0) && !SharedDelete)) { - return(STATUS_SHARING_VIOLATION); + /* Sharing violation, fail */ + return STATUS_SHARING_VIOLATION; } + /* It's not, check if caller wants us to update it */ if (Update) { + /* Increase open count */ ShareAccess->OpenCount++; + /* Update shared access */ ShareAccess->Readers += ReadAccess; ShareAccess->Writers += WriteAccess; ShareAccess->Deleters += DeleteAccess; @@ -1738,7 +2263,8 @@ IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, } } - return(STATUS_SUCCESS); + /* Validation successful */ + return STATUS_SUCCESS; } /* @@ -1751,12 +2277,26 @@ IoRemoveShareAccess(IN PFILE_OBJECT FileObject, { PAGED_CODE(); - if (FileObject->ReadAccess || - FileObject->WriteAccess || - FileObject->DeleteAccess) + /* Check if the file has an extension */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) { + /* Check if caller specified to ignore access checks */ + //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) + { + /* Don't update share access */ + return; + } + } + + /* Otherwise, check if there's any access present */ + if ((FileObject->ReadAccess) || + (FileObject->WriteAccess) || + (FileObject->DeleteAccess)) + { + /* Decrement the open count */ ShareAccess->OpenCount--; + /* Remove share access */ ShareAccess->Readers -= FileObject->ReadAccess; ShareAccess->Writers -= FileObject->WriteAccess; ShareAccess->Deleters -= FileObject->DeleteAccess; @@ -1782,42 +2322,64 @@ IoSetShareAccess(IN ACCESS_MASK DesiredAccess, BOOLEAN SharedRead; BOOLEAN SharedWrite; BOOLEAN SharedDelete; + BOOLEAN Update = TRUE; PAGED_CODE(); ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; DeleteAccess = (DesiredAccess & DELETE) != 0; + /* Check if the file has an extension */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) + { + /* Check if caller specified to ignore access checks */ + //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) + { + /* Don't update share access */ + Update = FALSE; + } + } + + /* Update basic access */ FileObject->ReadAccess = ReadAccess; FileObject->WriteAccess = WriteAccess; FileObject->DeleteAccess = DeleteAccess; - if (!ReadAccess && !WriteAccess && !DeleteAccess) + /* Check if we have no access as all */ + if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess)) { + /* Check if we need to update the structure */ + if (!Update) return; + + /* Otherwise, clear data */ ShareAccess->OpenCount = 0; ShareAccess->Readers = 0; ShareAccess->Writers = 0; ShareAccess->Deleters = 0; - ShareAccess->SharedRead = 0; ShareAccess->SharedWrite = 0; ShareAccess->SharedDelete = 0; } else { + /* Calculate shared access */ SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; + /* Set it in the FO */ FileObject->SharedRead = SharedRead; FileObject->SharedWrite = SharedWrite; FileObject->SharedDelete = SharedDelete; + /* Check if we need to update the structure */ + if (!Update) return; + + /* Otherwise, set data */ ShareAccess->OpenCount = 1; ShareAccess->Readers = ReadAccess; ShareAccess->Writers = WriteAccess; ShareAccess->Deleters = DeleteAccess; - ShareAccess->SharedRead = SharedRead; ShareAccess->SharedWrite = SharedWrite; ShareAccess->SharedDelete = SharedDelete; @@ -1828,7 +2390,7 @@ IoSetShareAccess(IN ACCESS_MASK DesiredAccess, * @unimplemented */ VOID -STDCALL +NTAPI IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject) { @@ -1839,7 +2401,7 @@ IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject, * @unimplemented */ NTSTATUS -STDCALL +NTAPI IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject, OUT POBJECT_NAME_INFORMATION *ObjectNameInformation) { @@ -1851,7 +2413,7 @@ IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject, * @unimplemented */ NTSTATUS -STDCALL +NTAPI IoSetFileOrigin(IN PFILE_OBJECT FileObject, IN BOOLEAN Remote) { @@ -1863,7 +2425,7 @@ IoSetFileOrigin(IN PFILE_OBJECT FileObject, * @implemented */ NTSTATUS -STDCALL +NTAPI NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, @@ -1894,7 +2456,7 @@ NtCreateFile(PHANDLE FileHandle, } NTSTATUS -STDCALL +NTAPI NtCreateMailslotFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, @@ -2146,6 +2708,7 @@ NtCancelIoFile(IN HANDLE FileHandle, NTSTATUS Status = STATUS_SUCCESS; PLIST_ENTRY ListHead, NextEntry; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check the previous mode */ if (PreviousMode != KernelMode) @@ -2275,6 +2838,7 @@ NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes) KPROCESSOR_MODE AccessMode = KeGetPreviousMode(); OPEN_PACKET OpenPacket; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName); /* Setup the Open Packet */ RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); diff --git a/reactos/ntoskrnl/io/iomgr/iofunc.c b/reactos/ntoskrnl/io/iomgr/iofunc.c index 056788d5be8..63f0ad48564 100644 --- a/reactos/ntoskrnl/io/iomgr/iofunc.c +++ b/reactos/ntoskrnl/io/iomgr/iofunc.c @@ -12,14 +12,8 @@ #include #define NDEBUG -#include - -#if 0 - IOTRACE(IO_IRP_DEBUG, - "%s - Queueing IRP %p\n", - __FUNCTION__, - Irp); -#endif +#include +#include "internal\io_i.h" /* PRIVATE FUNCTIONS *********************************************************/ @@ -31,6 +25,7 @@ IopCleanupAfterException(IN PFILE_OBJECT FileObject, IN PKEVENT LocalEvent OPTIONAL) { PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "IRP: %p. FO: %p \n", Irp, FileObject); /* Check if we had a buffer */ if (Irp->AssociatedIrp.SystemBuffer) @@ -73,6 +68,7 @@ IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus, { NTSTATUS FinalStatus = SynchStatus; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "IRP: %p. Status: %lx \n", Irp, SynchStatus); /* Make sure the IRP was completed, but returned pending */ if (FinalStatus == STATUS_PENDING) @@ -125,9 +121,11 @@ IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject, PVOID NormalContext; KIRQL OldIrql; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "IRP: %p. DO: %p. FO: %p \n", + Irp, DeviceObject, FileObject); /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Update operation counts */ IopUpdateOperationCount(TransferType); @@ -163,7 +161,8 @@ IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject, Status = KeWaitForSingleObject(&FileObject->Event, Executive, PreviousMode, - (FileObject->Flags & FO_ALERTABLE_IO), + (FileObject->Flags & + FO_ALERTABLE_IO), NULL); if ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC)) { @@ -208,6 +207,9 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, OBJECT_HANDLE_INFORMATION HandleInformation; ACCESS_MASK DesiredAccess; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + ULONG BufferLength; + IOTRACE(IO_CTL_DEBUG, "Handle: %lx. CTL: %lx. Type: %lx \n", + DeviceHandle, IoControlCode, IsDevIoCtl); /* Get the access type */ AccessType = IO_METHOD_FROM_CTL_CODE(IoControlCode); @@ -227,7 +229,9 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, if (OutputBuffer) { /* Probe the output buffer */ - ProbeForWrite(OutputBuffer, OutputBufferLength, 1); + ProbeForWrite(OutputBuffer, + OutputBufferLength, + sizeof(CHAR)); } else { @@ -243,7 +247,7 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, if (InputBuffer) { /* Probe the input buffer */ - ProbeForRead(InputBuffer, InputBufferLength, 1); + ProbeForRead(InputBuffer, InputBufferLength, sizeof(CHAR)); } else { @@ -258,8 +262,6 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Fail if we got an access violation */ if (!NT_SUCCESS(Status)) return Status; } @@ -268,10 +270,18 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, 0, IoFileObjectType, PreviousMode, - (PVOID *) &FileObject, + (PVOID*)&FileObject, &HandleInformation); if (!NT_SUCCESS(Status)) return Status; + /* Can't use an I/O completion port and an APC in the same time */ + if ((FileObject->CompletionContext) && (UserApcRoutine)) + { + /* Fail */ + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + /* Check if we from user mode */ if (PreviousMode != KernelMode) { @@ -334,29 +344,160 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle, /* Clear the event */ KeClearEvent(&FileObject->Event); - /* Build the IRP */ - Irp = IoBuildDeviceIoControlRequest(IoControlCode, - DeviceObject, - InputBuffer, - InputBufferLength, - OutputBuffer, - OutputBufferLength, - FALSE, - EventObject, - IoStatusBlock); + /* Allocate IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (!Irp) return IopCleanupFailedIrp(FileObject, Event, NULL); - /* Set some extra settings */ - Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL; - Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->RequestorMode = PreviousMode; + /* Setup the IRP */ + Irp->UserIosb = IoStatusBlock; + Irp->UserEvent = EventObject; Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext; + Irp->Cancel = FALSE; + Irp->CancelRoutine = NULL; + Irp->PendingReturned = FALSE; + Irp->RequestorMode = PreviousMode; + Irp->MdlAddress = NULL; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->Flags = 0; + Irp->Tail.Overlay.AuxiliaryBuffer = NULL; + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + /* Set stack location settings */ StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->FileObject = FileObject; StackPtr->MajorFunction = IsDevIoCtl ? IRP_MJ_DEVICE_CONTROL : IRP_MJ_FILE_SYSTEM_CONTROL; + StackPtr->MinorFunction = 0; + StackPtr->Control = 0; + StackPtr->Flags = 0; + StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = NULL; + + /* Set the IOCTL Data */ + StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = + OutputBufferLength; + + /* Handle the Methods */ + switch (AccessType) + { + /* Buffered I/O */ + case METHOD_BUFFERED: + + /* Enter SEH for allocations */ + _SEH_TRY + { + /* Select the right Buffer Length */ + BufferLength = (InputBufferLength > OutputBufferLength) ? + InputBufferLength : OutputBufferLength; + + /* Make sure there is one */ + if (BufferLength) + { + /* Allocate the System Buffer */ + Irp->AssociatedIrp.SystemBuffer = + ExAllocatePoolWithTag(NonPagedPool, + BufferLength, + TAG_SYS_BUF); + + /* Check if we got a buffer */ + if (InputBuffer) + { + /* Copy into the System Buffer */ + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, + InputBuffer, + InputBufferLength); + } + + /* Write the flags */ + Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION; + + /* Save the Buffer */ + Irp->UserBuffer = OutputBuffer; + } + else + { + /* Clear the Flags and Buffer */ + Irp->UserBuffer = NULL; + } + } + _SEH_HANDLE + { + /* Cleanup after exception */ + IopCleanupAfterException(FileObject, Irp, Event, NULL); + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + if (!NT_SUCCESS(Status)) return Status; + break; + + /* Direct I/O */ + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: + + /* Enter SEH */ + _SEH_TRY + { + /* Check if we got an input buffer */ + if ((InputBufferLength) && (InputBuffer)) + { + /* Allocate the System Buffer */ + Irp->AssociatedIrp.SystemBuffer = + ExAllocatePoolWithTag(NonPagedPool, + InputBufferLength, + TAG_SYS_BUF); + + /* Copy into the System Buffer */ + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, + InputBuffer, + InputBufferLength); + + /* Write the flags */ + Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + } + + /* Check if we got an output buffer */ + if (OutputBuffer) + { + /* Allocate the System Buffer */ + Irp->MdlAddress = IoAllocateMdl(OutputBuffer, + OutputBufferLength, + FALSE, + FALSE, + Irp); + if (!Irp->MdlAddress) + { + /* Raise exception we'll catch */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Do the probe */ + MmProbeAndLockPages(Irp->MdlAddress, + PreviousMode, + (AccessType == METHOD_IN_DIRECT) ? + IoReadAccess : IoWriteAccess); + } + } + _SEH_HANDLE + { + /* Cleanup after exception */ + IopCleanupAfterException(FileObject, Irp, Event, NULL); + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + if (!NT_SUCCESS(Status)) return Status; + break; + + case METHOD_NEITHER: + + /* Just save the Buffer */ + Irp->UserBuffer = OutputBuffer; + StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; + } /* Use deferred completion for FS I/O */ Irp->Flags |= (!IsDevIoCtl) ? IRP_DEFER_IO_COMPLETION : 0; @@ -388,6 +529,8 @@ IopQueryDeviceInformation(IN PFILE_OBJECT FileObject, KEVENT Event; NTSTATUS Status; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "Handle: %p. CTL: %lx. Type: %lx \n", + FileObject, InformationClass, File); /* Reference the object */ ObReferenceObject(FileObject); @@ -447,7 +590,7 @@ IopQueryDeviceInformation(IN PFILE_OBJECT FileObject, } /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Call the Driver */ Status = IoCallDriver(DeviceObject, Irp); @@ -509,6 +652,8 @@ IoSynchronousPageWrite(IN PFILE_OBJECT FileObject, PIRP Irp; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; + IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p \n", + FileObject, Mdl, Offset); /* Get the Device Object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); @@ -554,6 +699,8 @@ IoPageRead(IN PFILE_OBJECT FileObject, PIRP Irp; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; + IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p \n", + FileObject, Mdl, Offset); /* Get the Device Object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); @@ -646,6 +793,8 @@ IoSetInformation(IN PFILE_OBJECT FileObject, KEVENT Event; NTSTATUS Status; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileObject: %p. Class: %lx. Length: %lx \n", + FileObject, FileInformationClass, Length); /* Reference the object */ ObReferenceObject(FileObject); @@ -694,7 +843,7 @@ IoSetInformation(IN PFILE_OBJECT FileObject, StackPtr->Parameters.SetFile.Length = Length; /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Call the Driver */ Status = IoCallDriver(DeviceObject, Irp); @@ -817,6 +966,7 @@ NtFlushBuffersFile(IN HANDLE FileHandle, KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); if (PreviousMode != KernelMode) { @@ -948,6 +1098,7 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle, NTSTATUS Status = STATUS_SUCCESS; BOOLEAN LockedForSync = FALSE; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we're called from user mode */ if (PreviousMode != KernelMode) @@ -1073,6 +1224,7 @@ NtLockFile(IN HANDLE FileHandle, PAGED_CODE(); CapturedByteOffset.QuadPart = 0; CapturedLength.QuadPart = 0; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, @@ -1247,9 +1399,10 @@ NtQueryDirectoryFile(IN HANDLE FileHandle, UNICODE_STRING CapturedFileName; PUNICODE_STRING SearchPattern; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we came from user mode */ - if(PreviousMode != KernelMode) + if (PreviousMode != KernelMode) { /* Enter SEH for probing */ _SEH_TRY @@ -1484,10 +1637,26 @@ NtQueryInformationFile(IN HANDLE FileHandle, PVOID NormalContext; KIRQL OldIrql; IO_STATUS_BLOCK KernelIosb; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Validate the information class */ + if ((FileInformationClass >= FileMaximumInformation) || + !(IopQueryOperationLength[FileInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopQueryOperationLength[FileInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + /* Enter SEH for probing */ _SEH_TRY { @@ -1495,7 +1664,7 @@ NtQueryInformationFile(IN HANDLE FileHandle, ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe the information */ - if (Length) ProbeForWrite(FileInformation, Length, 1); + ProbeForWrite(FileInformation, Length, sizeof(ULONG)); } _SEH_HANDLE { @@ -1503,14 +1672,30 @@ NtQueryInformationFile(IN HANDLE FileHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Check if probing failed */ if (!NT_SUCCESS(Status)) return Status; } + else + { + /* Validate the information class */ + if ((FileInformationClass >= FileMaximumInformation) || + !(IopQueryOperationLength[FileInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopQueryOperationLength[FileInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + } /* Reference the Handle */ Status = ObReferenceObjectByHandle(FileHandle, - 0, // FIXME + IopQueryOperationAccess + [FileInformationClass], IoFileObjectType, PreviousMode, (PVOID *)&FileObject, @@ -1623,7 +1808,7 @@ NtQueryInformationFile(IN HANDLE FileHandle, StackPtr->Parameters.QueryFile.Length = Length; /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Update operation counts */ IopUpdateOperationCount(IopOtherTransfer); @@ -1764,6 +1949,7 @@ NtReadFile(IN HANDLE FileHandle, PMDL Mdl; PAGED_CODE(); CapturedByteOffset.QuadPart = 0; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Validate User-Mode Buffers */ if(PreviousMode != KernelMode) @@ -2024,10 +2210,26 @@ NtSetInformationFile(IN HANDLE FileHandle, PVOID Queue; PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation; PIO_COMPLETION_CONTEXT Context; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Validate the information class */ + if ((FileInformationClass >= FileMaximumInformation) || + !(IopSetOperationLength[FileInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopSetOperationLength[FileInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + /* Enter SEH for probing */ _SEH_TRY { @@ -2035,7 +2237,10 @@ NtSetInformationFile(IN HANDLE FileHandle, ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe the information */ - if (Length) ProbeForRead(FileInformation, Length, 1); + ProbeForRead(FileInformation, + Length, + (Length == sizeof(BOOLEAN)) ? + sizeof(BOOLEAN) : sizeof(ULONG)); } _SEH_HANDLE { @@ -2047,10 +2252,28 @@ NtSetInformationFile(IN HANDLE FileHandle, /* Check if probing failed */ if (!NT_SUCCESS(Status)) return Status; } + else + { + /* Validate the information class */ + if ((FileInformationClass >= FileMaximumInformation) || + !(IopSetOperationLength[FileInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopSetOperationLength[FileInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + } /* Reference the Handle */ Status = ObReferenceObjectByHandle(FileHandle, - 0, // FIXME + IopSetOperationAccess + [FileInformationClass], IoFileObjectType, PreviousMode, (PVOID *)&FileObject, @@ -2168,7 +2391,7 @@ NtSetInformationFile(IN HANDLE FileHandle, StackPtr->Parameters.SetFile.Length = Length; /* Queue the IRP */ - //IopQueueIrpToThread(Irp); + IopQueueIrpToThread(Irp); /* Update operation counts */ IopUpdateOperationCount(IopOtherTransfer); @@ -2366,6 +2589,7 @@ NtUnlockFile(IN HANDLE FileHandle, PAGED_CODE(); CapturedByteOffset.QuadPart = 0; CapturedLength.QuadPart = 0; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, @@ -2548,6 +2772,7 @@ NtWriteFile(IN HANDLE FileHandle, OBJECT_HANDLE_INFORMATION ObjectHandleInfo; PAGED_CODE(); CapturedByteOffset.QuadPart = 0; + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, @@ -2811,10 +3036,26 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle, NTSTATUS Status = STATUS_SUCCESS; IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Validate the information class */ + if ((FsInformationClass >= FileFsMaximumInformation) || + !(IopQueryFsOperationLength[FsInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopQueryFsOperationLength[FsInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + /* Enter SEH for probing */ _SEH_TRY { @@ -2822,7 +3063,7 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle, ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe the information */ - if (Length) ProbeForWrite(FsInformation, Length, 1); + ProbeForWrite(FsInformation, Length, sizeof(ULONG)); } _SEH_HANDLE { @@ -2830,14 +3071,13 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Check if probing failed */ if (!NT_SUCCESS(Status)) return Status; } /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, - 0, // FIXME + IopQueryFsOperationAccess + [FsInformationClass], IoFileObjectType, PreviousMode, (PVOID*)&FileObject, @@ -2959,10 +3199,26 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle, NTSTATUS Status = STATUS_SUCCESS; IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); + IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Validate the information class */ + if ((FsInformationClass >= FileFsMaximumInformation) || + !(IopSetFsOperationLength[FsInformationClass])) + { + /* Invalid class */ + return STATUS_INVALID_INFO_CLASS; + } + + /* Validate the length */ + if (Length < IopSetFsOperationLength[FsInformationClass]) + { + /* Invalid length */ + return STATUS_INFO_LENGTH_MISMATCH; + } + /* Enter SEH for probing */ _SEH_TRY { @@ -2970,7 +3226,7 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle, ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe the information */ - if (Length) ProbeForRead(FsInformation, Length, 1); + ProbeForRead(FsInformation, Length, sizeof(ULONG)); } _SEH_HANDLE { @@ -2978,14 +3234,13 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Check if probing failed */ if (!NT_SUCCESS(Status)) return Status; } /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, - 0, // FIXME + IopSetFsOperationAccess + [FsInformationClass], IoFileObjectType, PreviousMode, (PVOID*)&FileObject, diff --git a/reactos/ntoskrnl/io/iomgr/iomgr.c b/reactos/ntoskrnl/io/iomgr/iomgr.c index 70c1139c1c8..2ffc7ea7890 100644 --- a/reactos/ntoskrnl/io/iomgr/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr/iomgr.c @@ -13,7 +13,7 @@ #define NDEBUG #include -ULONG IopTraceLevel = IO_IRP_DEBUG; +ULONG IopTraceLevel = 0; //IO_API_DEBUG | IO_FILE_DEBUG; // should go into a proper header VOID diff --git a/reactos/ntoskrnl/io/iomgr/irp.c b/reactos/ntoskrnl/io/iomgr/irp.c index 21955c67a43..b83743970b4 100644 --- a/reactos/ntoskrnl/io/iomgr/irp.c +++ b/reactos/ntoskrnl/io/iomgr/irp.c @@ -214,12 +214,16 @@ IopCleanupIrp(IN PIRP Irp, !(Irp->Flags & IRP_SYNCHRONOUS_API) && (FileObject)) { - /* Derefernce the User Event */ + /* Dereference the User Event */ ObDereferenceObject(Irp->UserEvent); } - /* Dereference the File Object */ - if (FileObject) ObDereferenceObject(FileObject); + /* Check if we have a file object and this isn't a create operation */ + if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION)) + { + /* Dereference the file object */ + ObDereferenceObject(FileObject); + } /* Free the IRP */ IoFreeIrp(Irp); @@ -1099,22 +1103,24 @@ IofCompleteRequest(IN PIRP Irp, PMDL Mdl; ULONG MasterIrpCount; PIRP MasterIrp; + ULONG Flags; IOTRACE(IO_IRP_DEBUG, "%s - Completing IRP %p\n", __FUNCTION__, Irp); - /* Make sure this IRP isn't getting completed more then once */ - if ((Irp->CurrentLocation) > (Irp->StackCount + 1)) + /* Make sure this IRP isn't getting completed twice or is invalid */ + if (((Irp->CurrentLocation) > (Irp->StackCount + 1)) || + (Irp->Type != IO_TYPE_IRP)) { /* Bugcheck */ KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR)Irp, 0, 0, 0); } /* Some sanity checks */ - ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); ASSERT(!Irp->CancelRoutine); ASSERT(Irp->IoStatus.Status != STATUS_PENDING); + ASSERT(Irp->IoStatus.Status != 0xFFFFFFFF); /* Get the Current Stack and skip it */ StackPtr = IoGetCurrentIrpStackLocation(Irp); @@ -1172,9 +1178,6 @@ IofCompleteRequest(IN PIRP Irp, /* Check if the IRP is an associated IRP */ if (Irp->Flags & IRP_ASSOCIATED_IRP) { - /* This should never happen! */ - ASSERT(IsListEmpty(&Irp->ThreadListEntry)); - /* Get the master IRP and count */ MasterIrp = Irp->AssociatedIrp.MasterIrp; MasterIrpCount = InterlockedDecrement(&MasterIrp-> @@ -1199,6 +1202,9 @@ IofCompleteRequest(IN PIRP Irp, return; } + /* We don't support this yet */ + ASSERT(Irp->IoStatus.Status != STATUS_REPARSE); + /* Check if we have an auxiliary buffer */ if (Irp->Tail.Overlay.AuxiliaryBuffer) { @@ -1210,18 +1216,16 @@ IofCompleteRequest(IN PIRP Irp, /* Check if this is a Paging I/O or Close Operation */ if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) { - /* This should never happen! */ - ASSERT(IsListEmpty(&Irp->ThreadListEntry)); - /* Handle a Close Operation or Sync Paging I/O (see page 165) */ if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION)) { /* Set the I/O Status and Signal the Event */ + Flags = Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO; *Irp->UserIosb = Irp->IoStatus; KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE); /* Free the IRP for a Paging I/O Only, Close is handled by us */ - if (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) IoFreeIrp(Irp); + if (Flags) IoFreeIrp(Irp); } else { @@ -1271,7 +1275,7 @@ IofCompleteRequest(IN PIRP Irp, Thread = Irp->Tail.Overlay.Thread; FileObject = Irp->Tail.Overlay.OriginalFileObject; - /* Make sure the IRP isn't cancelled */ + /* Make sure the IRP isn't canceled */ if (!Irp->Cancel) { /* Initialize the APC */ @@ -1292,7 +1296,7 @@ IofCompleteRequest(IN PIRP Irp, } else { - /* The IRP just got cancelled... does a thread still own it? */ + /* The IRP just got canceled... does a thread still own it? */ Thread = Irp->Tail.Overlay.Thread; if (Thread) { @@ -1315,6 +1319,7 @@ IofCompleteRequest(IN PIRP Irp, else { /* Nothing left for us to do, kill it */ + ASSERT(Irp->Cancel); IopCleanupIrp(Irp, FileObject); } } @@ -1348,6 +1353,7 @@ IoFreeIrp(IN PIRP Irp) Irp); /* Make sure the Thread IRP list is empty and that it OK to free it */ + ASSERT(Irp->Type == IO_TYPE_IRP); ASSERT(IsListEmpty(&Irp->ThreadListEntry)); ASSERT(Irp->CurrentLocation >= Irp->StackCount); diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.c b/reactos/ntoskrnl/kdbg/kdb_symbols.c index f51525624cd..75d4701611b 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.c @@ -647,7 +647,7 @@ KdbSymProcessBootSymbols(IN PUNICODE_STRING FileName) if (IsRaw) { - DPRINT1("Data: %p %p %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->FullDllName); + DPRINT("Data: %p %p %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->FullDllName); if (! RosSymCreateFromRaw(LdrEntry->DllBase, LdrEntry->SizeOfImage, (PROSSYM_INFO*)&ModuleObject->PatchInformation)) diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 0f342b008bc..ffefedb1790 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -1206,7 +1206,7 @@ MmZeroPageThreadMain(PVOID Ignored) } } - DPRINT1("Zeroed %d pages.\n", Count); + DPRINT("Zeroed %d pages.\n", Count); KeResetEvent(&ZeroPageThreadEvent); KeReleaseSpinLock(&PageListLock, oldIrql); } diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 3eac1b8b2e2..85b0271c4eb 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -1756,7 +1756,7 @@ ObInsertObject(IN PVOID Object, POBJECT_CREATE_INFORMATION ObjectCreateInfo; POBJECT_HEADER Header; POBJECT_TYPE ObjectType; - PVOID FoundObject = NULL; + PVOID FoundObject = Object; POBJECT_HEADER FoundHeader = NULL; NTSTATUS Status = STATUS_SUCCESS, RealStatus; PSECURITY_DESCRIPTOR DirectorySd = NULL; @@ -1841,7 +1841,8 @@ ObInsertObject(IN PVOID Object, Status = ObFindObject(ObjectCreateInfo->RootDirectory, &ObjectNameInfo->Name, ObjectCreateInfo->Attributes, - KernelMode, + (Header->Flags & OB_FLAG_KERNEL_MODE) ? + KernelMode : UserMode, &FoundObject, ObjectType, &Context, diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index 99c2b06f710..23e0e5e5160 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -494,6 +494,14 @@ ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, return Status; } +VOID +NTAPI +ObFreeObjectCreateInfoBuffer(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo) +{ + /* Call the macro. We use this function to isolate Ob internals from Io */ + ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList); +} + NTSTATUS NTAPI ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo, diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index f73ee7f6111..41a94f680a4 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -362,13 +362,20 @@ PspInitPhase0(VOID) /* Clear kernel time */ PsIdleProcess->Pcb.KernelTime = 0; - /* Initialize the Process type */ + /* Initialize Object Initializer */ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); - RtlInitUnicodeString(&Name, L"Process"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); + ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK | + OBJ_PERMANENT | + OBJ_EXCLUSIVE | + OBJ_OPENIF; + ObjectTypeInitializer.PoolType = NonPagedPool; + ObjectTypeInitializer.SecurityRequired = TRUE; + + /* Initialize the Process type */ + RtlInitUnicodeString(&Name, L"Process"); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPROCESS); ObjectTypeInitializer.GenericMapping = PspProcessMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS; ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsProcessType); @@ -380,25 +387,20 @@ PspInitPhase0(VOID) } /* Initialize the Thread type */ - RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Thread"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(ETHREAD); ObjectTypeInitializer.GenericMapping = PspThreadMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS; ObjectTypeInitializer.DeleteProcedure = PspDeleteThread; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsThreadType); /* Initialize the Job type */ - RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Job"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EJOB); ObjectTypeInitializer.GenericMapping = PspJobMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = JOB_OBJECT_ALL_ACCESS; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.DeleteProcedure = PspDeleteJob; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsJobType); diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index 3e1e9d6d74e..78f36926f29 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -206,7 +206,8 @@ RtlpCaptureStackLimits(IN ULONG_PTR Ebp, if ((*StackBegin > Ebp) || (Ebp > *StackEnd)) { /* FIXME: TODO */ - ASSERT(FALSE); + //ASSERT(FALSE); + DPRINT1("Stacks: %p %p %p\n", Ebp, *StackBegin, *StackEnd); } /* Return success */ diff --git a/reactos/ntoskrnl/se/semgr.c b/reactos/ntoskrnl/se/semgr.c index ba5d2ef7698..a7147c5fd40 100644 --- a/reactos/ntoskrnl/se/semgr.c +++ b/reactos/ntoskrnl/se/semgr.c @@ -38,6 +38,9 @@ INIT_FUNCTION NTAPI SeInit(VOID) { + DPRINT1("FIXME: SeAccessCheck has been HACKED to always grant access!\n"); + DPRINT1("FIXME: Please fix all the code that doesn't get proper rights!\n"); + SepInitLuid(); if (!SepInitSecurityIDs()) @@ -1050,7 +1053,7 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, else { *AccessStatus = STATUS_ACCESS_DENIED; - DPRINT1("FIX caller rights (granted 0x%lx, desired 0x%lx)!\n", + DPRINT("FIX caller rights (granted 0x%lx, desired 0x%lx)!\n", *GrantedAccess, DesiredAccess); return TRUE; /* FIXME: should be FALSE */ } diff --git a/reactos/subsystems/win32/csrss/api/wapi.c b/reactos/subsystems/win32/csrss/api/wapi.c index bfc91d64c46..e725f167cc5 100644 --- a/reactos/subsystems/win32/csrss/api/wapi.c +++ b/reactos/subsystems/win32/csrss/api/wapi.c @@ -72,9 +72,9 @@ CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData, unsigned DefIndex; ULONG Type; - DPRINT1("CSR: Calling handler for type: %x.\n", Request->Type); + DPRINT("CSR: Calling handler for type: %x.\n", Request->Type); Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */ - DPRINT1("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16); + DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16); /* FIXME: Extract DefIndex instead of looping */ for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++) @@ -129,7 +129,7 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request, LpcRead.Length = sizeof(LpcRead); ServerPort = NULL; - DPRINT1("CSR: %s: Handling: %p\n", __FUNCTION__, Request); + DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request); Status = NtAcceptConnectPort(&ServerPort, #ifdef NTLPC @@ -189,7 +189,7 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request, #endif Status = STATUS_SUCCESS; - DPRINT1("CSR: %s done\n", __FUNCTION__); + DPRINT("CSR: %s done\n", __FUNCTION__); return Status; } @@ -300,7 +300,7 @@ ServerApiPortThread (HANDLE hApiListenPort) BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)]; PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest; - DPRINT1("CSR: %s called", __FUNCTION__); + DPRINT("CSR: %s called", __FUNCTION__); for (;;) { @@ -346,7 +346,7 @@ ServerSbApiPortThread (HANDLE hSbApiPortListen) NTSTATUS Status = STATUS_SUCCESS; PPORT_MESSAGE Reply = NULL; - DPRINT1("CSR: %s called\n", __FUNCTION__); + DPRINT("CSR: %s called\n", __FUNCTION__); RtlZeroMemory(&Request, sizeof(PORT_MESSAGE)); Status = NtListenPort (hSbApiPortListen, & Request); @@ -417,7 +417,7 @@ DPRINT("-- 5\n"); } } } - DPRINT1("CSR: %s: terminating!\n", __FUNCTION__); + DPRINT("CSR: %s: terminating!\n", __FUNCTION__); if(hConnectedPort) NtClose (hConnectedPort); NtClose (hSbApiPortListen); NtTerminateThread (NtCurrentThread(), Status); diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index 158dad2808b..ff43a2f6968 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -285,7 +285,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread, while (e) { PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry); - DPRINT1("thread clean: remove reference obj 0x%x\n",ref->obj); + DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj); ObmDereferenceObject(ref->obj); e = PopEntryList(&Win32Thread->ReferencesList); diff --git a/reactos/subsystems/win32/win32k/ntuser/class.c b/reactos/subsystems/win32/win32k/ntuser/class.c index 74c613c1a64..1e4be17713c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/class.c +++ b/reactos/subsystems/win32/win32k/ntuser/class.c @@ -52,7 +52,12 @@ static VOID IntDestroyClass(IN OUT PWINDOWCLASS Class) { /* there shouldn't be any clones anymore */ - ASSERT(Class->Windows == 0); + //ASSERT(Class->Windows == 0); + if (Class->Windows) + { + DPRINT1("FIXME: W3Seek's Class Patch is broken!\n"); + Class->Windows = 0; + } ASSERT(Class->Clone == NULL); if (Class->Base == Class) diff --git a/reactos/subsystems/win32/win32k/ntuser/focus.c b/reactos/subsystems/win32/win32k/ntuser/focus.c index 95dafd20561..f98a4289522 100644 --- a/reactos/subsystems/win32/win32k/ntuser/focus.c +++ b/reactos/subsystems/win32/win32k/ntuser/focus.c @@ -89,7 +89,7 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) /* FIXME: IntIsWindow */ - CHECKPOINT1; + CHECKPOINT; co_IntPostOrSendMessage(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0); /* FIXME: WA_CLICKACTIVE */ co_IntPostOrSendMessage(hWnd, WM_ACTIVATE, @@ -174,7 +174,7 @@ co_IntSetForegroundAndFocusWindow(PWINDOW_OBJECT Window, PWINDOW_OBJECT FocusWin if (hWndPrev == hWnd) { - DPRINT1("Failed - Same\n"); + DPRINT("Failed - Same\n"); return TRUE; } @@ -202,7 +202,7 @@ co_IntSetForegroundAndFocusWindow(PWINDOW_OBJECT Window, PWINDOW_OBJECT FocusWin /* FIXME: Send WM_ACTIVATEAPP to all thread windows. */ } - CHECKPOINT1; + CHECKPOINT; co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus); co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate); diff --git a/reactos/subsystems/win32/win32k/ntuser/misc.c b/reactos/subsystems/win32/win32k/ntuser/misc.c index f8b868bfe3f..20b7b6da9ea 100644 --- a/reactos/subsystems/win32/win32k/ntuser/misc.c +++ b/reactos/subsystems/win32/win32k/ntuser/misc.c @@ -1475,7 +1475,7 @@ UserSystemParametersInfo( } default : { - DPRINT1("UserSystemParametersInfo : uiAction = %x \n",uiAction ); + DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction ); break; } } diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index cdc1ed92b9e..9ba5d7f5dd4 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -645,7 +645,7 @@ co_DestroyThreadWindows(struct _ETHREAD *Thread) Current = WThread->WindowListHead.Flink; Wnd = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry); - DPRINT1("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd); + DPRINT("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd); /* window removes itself from the list */