- 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
IN DWORD argc,
IN LPWSTR *argv)
{
- DPRINT1("ServiceMain() called\n");
+ DPRINT("ServiceMain() called\n");
}
INT WINAPI
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
- DPRINT1("ScmrStartServiceW() called\n");
+ DPRINT("ScmrStartServiceW() called\n");
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
#include "winlogon.h"
-#define YDEBUG
+//#define YDEBUG
#include <wine/debug.h>
#define WINLOGON_SAS_CLASS L"SAS Window class"
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)
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;
}
* 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)
DPRINT ("FsRecDeviceIoControl() failed (Status %lx)\n", Status);
return(Status);
}
- DPRINT1 ("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
/* Check the volume recognition sequence */
Status = FsRecCheckVolumeRecognitionSequence(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);
#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)
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;
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;
{
union
{
- ULONG_PTR Count;
- PVOID Ptr;
+ __volatile ULONG_PTR Count;
+ __volatile PVOID Ptr;
};
} EX_RUNDOWN_REF, *PEX_RUNDOWN_REF;
ULONG Flags;
union {
struct _IRP *MasterIrp;
- LONG IrpCount;
+ __volatile LONG IrpCount;
PVOID SystemBuffer;
} AssociatedIrp;
LIST_ENTRY ThreadListEntry;
} AsynchronousParameters;
LARGE_INTEGER AllocationSize;
} Overlay;
- PDRIVER_CANCEL CancelRoutine;
+ __volatile PDRIVER_CANCEL CancelRoutine;
PVOID UserBuffer;
union {
struct {
PIO_TIMER Timer;
ULONG Flags;
ULONG Characteristics;
- PVPB Vpb;
+ __volatile PVPB Vpb;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType;
CCHAR StackSize;
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;
#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;
typedef struct _IO_REMOVE_LOCK_COMMON_BLOCK {
BOOLEAN Removed;
BOOLEAN Reserved[3];
- LONG IoCount;
+ __volatile LONG IoCount;
KEVENT RemoveEvent;
} IO_REMOVE_LOCK_COMMON_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;
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 {
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();
}
}
- /* If we returned, raise a status */
- RtlRaiseStatus(Status);
+ /* We should never return */
+ while (TRUE);
}
/*
sizeof(*RegistrationFrame));
/* Call the handler */
+ DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler);
Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
// 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).
//
// 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.
// - Use pushlocks for handle implementation.
//
// Kd:
-// - Implement new KDCOM with KD support.
// - Implement KD Kernel Debugging and WinDBG support.
//
// Native:
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);
POBJECT_TYPE DbgkDebugObjectType;
FAST_MUTEX DbgkpProcessDebugPortMutex;
-ULONG DbgkpTraceLevel = -1;
+ULONG DbgkpTraceLevel = 0; //-1;
GENERIC_MAPPING DbgkDebugObjectMapping =
{
/* Get the end and maximum sector */\r
EndSector = MaxOffset;\r
MaxSector = MaxOffset << 1;\r
- DPRINT1("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",\r
+ DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",\r
MaxOffset, MaxSector);\r
\r
/* Allocate our buffer */\r
\r
/* Start looping partitions */\r
j++;\r
- DPRINT1("FSTUB: Partition Table %d:\n", j);\r
+ DPRINT("FSTUB: Partition Table %d:\n", j);\r
for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++)\r
{\r
/* Get the partition type */\r
PartitionType = PartitionDescriptor->PartitionType;\r
\r
/* Print debug messages */\r
- DPRINT1("Partition Entry %d,%d: type %#x %s\n", \r
+ DPRINT("Partition Entry %d,%d: type %#x %s\n", \r
j,\r
Entry,\r
PartitionType,\r
(PartitionDescriptor->ActiveFlag) ? "Active" : "");\r
- DPRINT1("\tOffset %#08lx for %#08lx Sectors\n", \r
+ DPRINT("\tOffset %#08lx for %#08lx Sectors\n", \r
GET_STARTING_SECTOR(PartitionDescriptor),\r
GET_PARTITION_LENGTH(PartitionDescriptor));\r
\r
}\r
\r
/* Finish debug log, and check for failure */\r
- DPRINT1("\n");\r
+ DPRINT("\n");\r
if (!NT_SUCCESS(Status)) break;\r
\r
/* Also check if we hit an invalid entry here */\r
return;
}
- DPRINT1("Done!\n");
+ DPRINT("Done!\n");
KeInitializeSpinLock(&InbvLock);
BootVidBase = ModuleObject->DllBase;
BootVidDriverInstalled = TRUE;
/* TODO: Verify which version the MS compiler learned the __FUNCTION__ macro */
#define __FUNCTION__ "<unknown>"
#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
//
// 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
//
}
VOID
-static __inline
+FORCEINLINE
IopQueueIrpToThread(IN PIRP Irp)
{
KIRQL OldIrql;
IN KPROCESSOR_MODE PreviousMode
);
+VOID
+NTAPI
+ObFreeObjectCreateInfoBuffer(
+ IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
+);
+
//
// DOS Devices Functions
//
}
}
-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,
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 */
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);
}
}
/* Return the device object we found */
+ ASSERT(DeviceObject != NULL);
return DeviceObject;
}
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-#if 0
- IOTRACE(IO_IRP_DEBUG,
- "%s - Queueing IRP %p\n",
- __FUNCTION__,
- Irp);
-#endif
+#include <debug.h>
/* 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,
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;
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 */
&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));
/* 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;
}
}
}
+ /* 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)
/* 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);
}
OpenPacket->FileObject = FileObject;
/* Queue the IRP and call the driver */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
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) &&
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)
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 */
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);
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
+ /* De-queue the IRP */
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+ IopUnQueueIrpFromThread(Irp);
+ KeLowerIrql(OldIrql);
+
/* Free the IRP */
IoFreeIrp(Irp);
ExFreePool(FileObject->CompletionContext);
}
- /* FIXME: Dereference device object */
+ /* Check if dereference has been done yet */
+ if (!DereferenceDone)
+ {
+ /* Dereference device object */
+ IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE);
+ }
}
}
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)
}
/* 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)
}
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Update operation counts */
IopUpdateOperationCount(IopOtherTransfer);
/* 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,
ULONG LocalReturnLength, FileLength;
NTSTATUS Status;
PWCHAR p;
+ IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
/* Validate length */
if (Length < sizeof(OBJECT_NAME_INFORMATION))
/* 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 -
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))
StackPtr->FileObject = FileObject;
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Update operation counts */
IopUpdateOperationCount(IopOtherTransfer);
KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
}
+ /* Unqueue the IRP */
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+ IopUnQueueIrpFromThread(Irp);
+ KeLowerIrql(OldIrql);
+
/* Free the IRP */
IoFreeIrp(Irp);
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)
* @unimplemented
*/
NTSTATUS
-STDCALL
+NTAPI
IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
IN ULONG Length,
IN BOOLEAN SetOperation)
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,
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
{
}
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);
+ if (!SystemEaBuffer) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Copy the data */
RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);
- }
- }
- if(Options & IO_CHECK_CREATE_PARAMETERS)
- {
- DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
+ /* Validate the buffer */
+ Status = IoCheckEaBufferValidity(SystemEaBuffer,
+ EaLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Fail once function is implemented */
+ }
+ }
}
/* Setup the Open Packet */
OpenPacket.EaBuffer = SystemEaBuffer;
OpenPacket.EaLength = EaLength;
OpenPacket.Options = Options;
- OpenPacket.Disposition = CreateDisposition;
+ OpenPacket.Disposition = Disposition;
OpenPacket.CreateFileType = CreateFileType;
OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters;
*/
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));
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;
}
/*
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));
{
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;
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;
}
}
- return(STATUS_SUCCESS);
+ /* Validation successful */
+ return STATUS_SUCCESS;
}
/*
{
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;
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;
* @unimplemented
*/
VOID
-STDCALL
+NTAPI
IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject)
{
* @unimplemented
*/
NTSTATUS
-STDCALL
+NTAPI
IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
OUT POBJECT_NAME_INFORMATION *ObjectNameInformation)
{
* @unimplemented
*/
NTSTATUS
-STDCALL
+NTAPI
IoSetFileOrigin(IN PFILE_OBJECT FileObject,
IN BOOLEAN Remote)
{
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
NtCreateFile(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
}
NTSTATUS
-STDCALL
+NTAPI
NtCreateMailslotFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
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)
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));
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-#if 0
- IOTRACE(IO_IRP_DEBUG,
- "%s - Queueing IRP %p\n",
- __FUNCTION__,
- Irp);
-#endif
+#include <debug.h>
+#include "internal\io_i.h"
/* PRIVATE FUNCTIONS *********************************************************/
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)
{
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)
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);
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))
{
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);
if (OutputBuffer)
{
/* Probe the output buffer */
- ProbeForWrite(OutputBuffer, OutputBufferLength, 1);
+ ProbeForWrite(OutputBuffer,
+ OutputBufferLength,
+ sizeof(CHAR));
}
else
{
if (InputBuffer)
{
/* Probe the input buffer */
- ProbeForRead(InputBuffer, InputBufferLength, 1);
+ ProbeForRead(InputBuffer, InputBufferLength, sizeof(CHAR));
}
else
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
- /* Fail if we got an access violation */
if (!NT_SUCCESS(Status)) return Status;
}
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)
{
/* 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;
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);
}
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Call the Driver */
Status = IoCallDriver(DeviceObject, Irp);
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);
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);
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);
StackPtr->Parameters.SetFile.Length = Length;
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Call the Driver */
Status = IoCallDriver(DeviceObject, Irp);
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
IO_STATUS_BLOCK KernelIosb;
PAGED_CODE();
+ IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
if (PreviousMode != KernelMode)
{
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)
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
CapturedLength.QuadPart = 0;
+ IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
/* Get File Object */
Status = ObReferenceObjectByHandle(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
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
{
ProbeForWriteIoStatusBlock(IoStatusBlock);
/* Probe the information */
- if (Length) ProbeForWrite(FileInformation, Length, 1);
+ ProbeForWrite(FileInformation, Length, sizeof(ULONG));
}
_SEH_HANDLE
{
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,
StackPtr->Parameters.QueryFile.Length = Length;
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Update operation counts */
IopUpdateOperationCount(IopOtherTransfer);
PMDL Mdl;
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
+ IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
/* Validate User-Mode Buffers */
if(PreviousMode != KernelMode)
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
{
ProbeForWriteIoStatusBlock(IoStatusBlock);
/* Probe the information */
- if (Length) ProbeForRead(FileInformation, Length, 1);
+ ProbeForRead(FileInformation,
+ Length,
+ (Length == sizeof(BOOLEAN)) ?
+ sizeof(BOOLEAN) : sizeof(ULONG));
}
_SEH_HANDLE
{
/* 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,
StackPtr->Parameters.SetFile.Length = Length;
/* Queue the IRP */
- //IopQueueIrpToThread(Irp);
+ IopQueueIrpToThread(Irp);
/* Update operation counts */
IopUpdateOperationCount(IopOtherTransfer);
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
CapturedLength.QuadPart = 0;
+ IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
/* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle,
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
+ IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
/* Get File Object */
Status = ObReferenceObjectByHandle(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
{
ProbeForWriteIoStatusBlock(IoStatusBlock);
/* Probe the information */
- if (Length) ProbeForWrite(FsInformation, Length, 1);
+ ProbeForWrite(FsInformation, Length, sizeof(ULONG));
}
_SEH_HANDLE
{
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,
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
{
ProbeForWriteIoStatusBlock(IoStatusBlock);
/* Probe the information */
- if (Length) ProbeForRead(FsInformation, Length, 1);
+ ProbeForRead(FsInformation, Length, sizeof(ULONG));
}
_SEH_HANDLE
{
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,
#define NDEBUG
#include <internal/debug.h>
-ULONG IopTraceLevel = IO_IRP_DEBUG;
+ULONG IopTraceLevel = 0; //IO_API_DEBUG | IO_FILE_DEBUG;
// should go into a proper header
VOID
!(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);
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);
/* 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->
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)
{
/* 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
{
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 */
}
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)
{
else
{
/* Nothing left for us to do, kill it */
+ ASSERT(Irp->Cancel);
IopCleanupIrp(Irp, FileObject);
}
}
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);
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))
}
}
- DPRINT1("Zeroed %d pages.\n", Count);
+ DPRINT("Zeroed %d pages.\n", Count);
KeResetEvent(&ZeroPageThreadEvent);
KeReleaseSpinLock(&PageListLock, oldIrql);
}
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;
Status = ObFindObject(ObjectCreateInfo->RootDirectory,
&ObjectNameInfo->Name,
ObjectCreateInfo->Attributes,
- KernelMode,
+ (Header->Flags & OB_FLAG_KERNEL_MODE) ?
+ KernelMode : UserMode,
&FoundObject,
ObjectType,
&Context,
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,
/* 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);
}
/* 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);
if ((*StackBegin > Ebp) || (Ebp > *StackEnd))
{
/* FIXME: TODO */
- ASSERT(FALSE);
+ //ASSERT(FALSE);
+ DPRINT1("Stacks: %p %p %p\n", Ebp, *StackBegin, *StackEnd);
}
/* Return success */
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())
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 */
}
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++)
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
#endif
Status = STATUS_SUCCESS;
- DPRINT1("CSR: %s done\n", __FUNCTION__);
+ DPRINT("CSR: %s done\n", __FUNCTION__);
return Status;
}
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 (;;)
{
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);
}
}
}
- DPRINT1("CSR: %s: terminating!\n", __FUNCTION__);
+ DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
if(hConnectedPort) NtClose (hConnectedPort);
NtClose (hSbApiPortListen);
NtTerminateThread (NtCurrentThread(), Status);
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);
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)
/* FIXME: IntIsWindow */
- CHECKPOINT1;
+ CHECKPOINT;
co_IntPostOrSendMessage(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0);
/* FIXME: WA_CLICKACTIVE */
co_IntPostOrSendMessage(hWnd, WM_ACTIVATE,
if (hWndPrev == hWnd)
{
- DPRINT1("Failed - Same\n");
+ DPRINT("Failed - Same\n");
return TRUE;
}
/* FIXME: Send WM_ACTIVATEAPP to all thread windows. */
}
- CHECKPOINT1;
+ CHECKPOINT;
co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus);
co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate);
}
default :
{
- DPRINT1("UserSystemParametersInfo : uiAction = %x \n",uiAction );
+ DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction );
break;
}
}
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 */