ntoskrnl: Implement creation and destruction of file objects.
This commit is contained in:
parent
350ee62ab4
commit
13499a3d11
|
@ -151,6 +151,94 @@ static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* process a create request for a given file */
|
||||
static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
ULONG out_size, HANDLE irp_handle )
|
||||
{
|
||||
IRP *irp;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
FILE_OBJECT *file;
|
||||
DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
|
||||
|
||||
if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) return STATUS_NO_MEMORY;
|
||||
|
||||
TRACE( "device %p -> file %p\n", device, file );
|
||||
|
||||
file->Type = 5; /* MSDN */
|
||||
file->Size = sizeof(*file);
|
||||
file->DeviceObject = device;
|
||||
|
||||
if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, file );
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
irpsp = IoGetNextIrpStackLocation( irp );
|
||||
irpsp->MajorFunction = IRP_MJ_CREATE;
|
||||
irpsp->DeviceObject = device;
|
||||
irpsp->CompletionRoutine = NULL;
|
||||
irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
|
||||
irpsp->Parameters.Create.Options = params->create.options;
|
||||
irpsp->Parameters.Create.ShareAccess = params->create.sharing;
|
||||
irpsp->Parameters.Create.FileAttributes = 0;
|
||||
irpsp->Parameters.Create.EaLength = 0;
|
||||
|
||||
irp->Tail.Overlay.OriginalFileObject = file;
|
||||
irp->AssociatedIrp.SystemBuffer = NULL;
|
||||
irp->UserBuffer = NULL;
|
||||
irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
|
||||
irp->UserEvent = NULL;
|
||||
|
||||
irp->IoStatus.u.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* process a close request for a given file */
|
||||
static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
ULONG out_size, HANDLE irp_handle )
|
||||
{
|
||||
IRP *irp;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
DEVICE_OBJECT *device;
|
||||
FILE_OBJECT *file = wine_server_get_ptr( params->close.file );
|
||||
|
||||
if (!file) return STATUS_INVALID_HANDLE;
|
||||
|
||||
device = file->DeviceObject;
|
||||
|
||||
TRACE( "device %p file %p\n", device, file );
|
||||
|
||||
if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, file );
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
irpsp = IoGetNextIrpStackLocation( irp );
|
||||
irpsp->MajorFunction = IRP_MJ_CLOSE;
|
||||
irpsp->DeviceObject = device;
|
||||
irpsp->CompletionRoutine = NULL;
|
||||
irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
|
||||
irpsp->Parameters.Create.Options = params->create.options;
|
||||
irpsp->Parameters.Create.ShareAccess = params->create.sharing;
|
||||
irpsp->Parameters.Create.FileAttributes = 0;
|
||||
irpsp->Parameters.Create.EaLength = 0;
|
||||
|
||||
irp->Tail.Overlay.OriginalFileObject = file;
|
||||
irp->AssociatedIrp.SystemBuffer = NULL;
|
||||
irp->UserBuffer = NULL;
|
||||
irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
|
||||
irp->UserEvent = NULL;
|
||||
|
||||
irp->IoStatus.u.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, file ); /* FIXME: async close processing not supported */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* process a read request for a given device */
|
||||
static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
ULONG out_size, HANDLE irp_handle )
|
||||
|
@ -268,9 +356,9 @@ typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, UL
|
|||
|
||||
static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
|
||||
{
|
||||
NULL, /* IRP_MJ_CREATE */
|
||||
dispatch_create, /* IRP_MJ_CREATE */
|
||||
NULL, /* IRP_MJ_CREATE_NAMED_PIPE */
|
||||
NULL, /* IRP_MJ_CLOSE */
|
||||
dispatch_close, /* IRP_MJ_CLOSE */
|
||||
dispatch_read, /* IRP_MJ_READ */
|
||||
dispatch_write, /* IRP_MJ_WRITE */
|
||||
NULL, /* IRP_MJ_QUERY_INFORMATION */
|
||||
|
@ -1149,12 +1237,14 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
|
|||
{
|
||||
HANDLE manager = get_device_manager();
|
||||
void *out_buff = irp->UserBuffer;
|
||||
FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
|
||||
|
||||
SERVER_START_REQ( set_irp_result )
|
||||
{
|
||||
req->manager = wine_server_obj_handle( manager );
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->status = irp->IoStatus.u.Status;
|
||||
req->file_ptr = wine_server_client_ptr( file );
|
||||
if (irp->IoStatus.u.Status >= 0)
|
||||
{
|
||||
req->size = irp->IoStatus.Information;
|
||||
|
|
|
@ -646,7 +646,7 @@ typedef union
|
|||
{
|
||||
unsigned int major;
|
||||
int __pad;
|
||||
client_ptr_t device;
|
||||
client_ptr_t file;
|
||||
} close;
|
||||
struct
|
||||
{
|
||||
|
@ -3216,9 +3216,10 @@ struct set_irp_result_request
|
|||
obj_handle_t manager;
|
||||
obj_handle_t handle;
|
||||
unsigned int status;
|
||||
client_ptr_t file_ptr;
|
||||
data_size_t size;
|
||||
/* VARARG(data,bytes); */
|
||||
char __pad_28[4];
|
||||
char __pad_36[4];
|
||||
};
|
||||
struct set_irp_result_reply
|
||||
{
|
||||
|
@ -6095,6 +6096,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 479
|
||||
#define SERVER_PROTOCOL_VERSION 480
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -164,6 +164,7 @@ struct device_file
|
|||
struct object obj; /* object header */
|
||||
struct device *device; /* device for this file */
|
||||
struct fd *fd; /* file descriptor for irp */
|
||||
client_ptr_t user_ptr; /* opaque ptr for client side */
|
||||
struct list entry; /* entry in device list */
|
||||
struct list requests; /* list of pending irp requests */
|
||||
};
|
||||
|
@ -358,6 +359,7 @@ static struct object *device_open_file( struct object *obj, unsigned int access,
|
|||
if (!(file = alloc_object( &device_file_ops ))) return NULL;
|
||||
|
||||
file->device = (struct device *)grab_object( device );
|
||||
file->user_ptr = 0;
|
||||
list_init( &file->requests );
|
||||
list_add_tail( &device->files, &file->entry );
|
||||
if (device->unix_path)
|
||||
|
@ -420,7 +422,7 @@ static int device_file_close_handle( struct object *obj, struct process *process
|
|||
irp_params_t params;
|
||||
|
||||
params.close.major = IRP_MJ_CLOSE;
|
||||
params.close.device = file->device->user_ptr;
|
||||
params.close.file = file->user_ptr;
|
||||
|
||||
if ((irp = create_irp( file, ¶ms, NULL, 0, 0 )))
|
||||
{
|
||||
|
@ -458,6 +460,25 @@ static struct irp_call *find_irp_call( struct device_file *file, struct thread *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void set_file_user_ptr( struct device_file *file, client_ptr_t ptr )
|
||||
{
|
||||
struct irp_call *irp;
|
||||
|
||||
if (file->user_ptr == ptr) return; /* nothing to do */
|
||||
|
||||
file->user_ptr = ptr;
|
||||
|
||||
/* update already queued irps */
|
||||
|
||||
LIST_FOR_EACH_ENTRY( irp, &file->requests, struct irp_call, dev_entry )
|
||||
{
|
||||
switch (irp->params.major)
|
||||
{
|
||||
case IRP_MJ_CLOSE: irp->params.close.file = ptr; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* queue an irp to the device */
|
||||
static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp,
|
||||
const async_data_t *async_data, int blocking )
|
||||
|
@ -780,6 +801,7 @@ DECL_HANDLER(set_irp_result)
|
|||
|
||||
if ((irp = (struct irp_call *)get_handle_obj( current->process, req->handle, 0, &irp_call_ops )))
|
||||
{
|
||||
if (irp->file) set_file_user_ptr( irp->file, req->file_ptr );
|
||||
set_irp_result( irp, req->status, get_req_data(), get_req_data_size(), req->size );
|
||||
close_handle( current->process, req->handle ); /* avoid an extra round-trip for close */
|
||||
release_object( irp );
|
||||
|
|
|
@ -662,7 +662,7 @@ typedef union
|
|||
{
|
||||
unsigned int major; /* IRP_MJ_CLOSE */
|
||||
int __pad;
|
||||
client_ptr_t device; /* opaque ptr for the device */
|
||||
client_ptr_t file; /* opaque ptr for the file object */
|
||||
} close;
|
||||
struct
|
||||
{
|
||||
|
@ -2338,6 +2338,7 @@ enum message_type
|
|||
obj_handle_t manager; /* handle to the device manager */
|
||||
obj_handle_t handle; /* handle to the irp */
|
||||
unsigned int status; /* status of the irp */
|
||||
client_ptr_t file_ptr; /* opaque pointer to the file object */
|
||||
data_size_t size; /* result size (input or output depending on the operation) */
|
||||
VARARG(data,bytes); /* output data of the irp */
|
||||
@END
|
||||
|
|
|
@ -1555,8 +1555,9 @@ C_ASSERT( sizeof(struct ioctl_reply) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, manager) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, handle) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, status) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, size) == 24 );
|
||||
C_ASSERT( sizeof(struct set_irp_result_request) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, file_ptr) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, size) == 32 );
|
||||
C_ASSERT( sizeof(struct set_irp_result_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_irp_result_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_irp_result_request, user_arg) == 16 );
|
||||
C_ASSERT( sizeof(struct get_irp_result_request) == 24 );
|
||||
|
|
|
@ -324,7 +324,7 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data )
|
|||
break;
|
||||
case IRP_MJ_CLOSE:
|
||||
fprintf( stderr, "%s{major=CLOSE", prefix );
|
||||
dump_uint64( ",device=", &data->close.device );
|
||||
dump_uint64( ",file=", &data->close.file );
|
||||
fputc( '}', stderr );
|
||||
break;
|
||||
case IRP_MJ_READ:
|
||||
|
@ -2826,6 +2826,7 @@ static void dump_set_irp_result_request( const struct set_irp_result_request *re
|
|||
fprintf( stderr, " manager=%04x", req->manager );
|
||||
fprintf( stderr, ", handle=%04x", req->handle );
|
||||
fprintf( stderr, ", status=%08x", req->status );
|
||||
dump_uint64( ", file_ptr=", &req->file_ptr );
|
||||
fprintf( stderr, ", size=%u", req->size );
|
||||
dump_varargs_bytes( ", data=", cur_size );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue