void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus) { FUSE_DATA *fuse_data; log_debug("entered"); fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) { xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus); free(fuse_data); } if (IoStatus != NT_STATUS_SUCCESS) { devredir_irp_delete(irp); return; } irp->completion_type = CID_CLOSE; dev_redir_send_drive_close_request(RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOREQUEST, irp->DeviceId, irp->FileId, irp->CompletionId, IRP_MJ_CLOSE, 0, 32); }
void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus) { struct stream *s; int bytes; if (IoStatus != NT_STATUS_SUCCESS) { FUSE_DATA *fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) { xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus); free(fuse_data); } devredir_irp_delete(irp); return; } xstream_new(s, 1024); irp->completion_type = CID_RMDIR_OR_FILE_RESP; devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId, irp->CompletionId, IRP_MJ_SET_INFORMATION, 0); xstream_wr_u32_le(s, FileDispositionInformation); xstream_wr_u32_le(s, 0); /* length is zero */ xstream_seek(s, 24); /* padding */ /* send to client */ bytes = xstream_len(s); send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); return; }
void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus) { struct stream *s; int bytes; int sblen; /* SetBuffer length */ int flen; /*FileNameLength */ if (IoStatus != NT_STATUS_SUCCESS) { log_debug("rename returned with IoStatus=0x%x", IoStatus); FUSE_DATA *fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) { xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus); free(fuse_data); } devredir_irp_delete(irp); return; } xstream_new(s, 1024); irp->completion_type = CID_RENAME_FILE_RESP; devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId, irp->CompletionId, IRP_MJ_SET_INFORMATION, 0); flen = strlen(irp->gen_buf) * 2 + 2; sblen = 6 + flen; xstream_wr_u32_le(s, FileRenameInformation); xstream_wr_u32_le(s, sblen); /* Length */ xstream_seek(s, 24); /* padding */ xstream_wr_u8(s, 1); /* ReplaceIfExists */ xstream_wr_u8(s, 0); /* RootDirectory */ xstream_wr_u32_le(s, flen); /* FileNameLength */ /* filename in unicode */ devredir_cvt_to_unicode(s->p, irp->gen_buf); xstream_seek(s, flen); /* send to client */ bytes = xstream_len(s); send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); return; }
void dev_redir_proc_query_dir_response(IRP *irp, struct stream *s_in, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { FUSE_DATA *fuse_data = NULL; XRDP_INODE *xinode = NULL; tui32 Length; tui32 NextEntryOffset; tui64 CreationTime; tui64 LastAccessTime; tui64 LastWriteTime; tui64 ChangeTime; tui64 EndOfFile; tui32 FileAttributes; tui32 FileNameLength; tui32 status; #ifdef USE_SHORT_NAMES_IN_DIR_LISTING tui32 EaSize; tui8 ShortNameLength; tui8 Reserved; #endif char filename[256]; int i = 0; stream_rd_u32_le(s_in, Length); if ((IoStatus == NT_STATUS_UNSUCCESSFUL) || (IoStatus == STATUS_NO_MORE_FILES)) { status = (IoStatus == STATUS_NO_MORE_FILES) ? 0 : IoStatus; fuse_data = dev_redir_fuse_data_dequeue(irp); xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr, status); irp->completion_type = CID_CLOSE; dev_redir_send_drive_close_request(RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOREQUEST, DeviceId, irp->FileId, irp->completion_id, IRP_MJ_CLOSE, 0, 32); free(fuse_data); return; } /* TODO check status for errors */ /* process FILE_DIRECTORY_INFORMATION structures */ while (i < Length) { log_debug("processing FILE_DIRECTORY_INFORMATION structs"); stream_rd_u32_le(s_in, NextEntryOffset); stream_seek(s_in, 4); /* FileIndex */ stream_rd_u64_le(s_in, CreationTime); stream_rd_u64_le(s_in, LastAccessTime); stream_rd_u64_le(s_in, LastWriteTime); stream_rd_u64_le(s_in, ChangeTime); stream_rd_u64_le(s_in, EndOfFile); stream_seek(s_in, 8); /* AllocationSize */ stream_rd_u32_le(s_in, FileAttributes); stream_rd_u32_le(s_in, FileNameLength); #ifdef USE_SHORT_NAMES_IN_DIR_LISTING stream_rd_u32_le(s_in, EaSize); stream_rd_u8(s_in, ShortNameLength); stream_rd_u8(s_in, Reserved); stream_seek(s_in, 23); /* ShortName in Unicode */ #endif devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength); #ifdef USE_SHORT_NAMES_IN_DIR_LISTING i += 70 + 23 + FileNameLength; #else i += 64 + FileNameLength; #endif //log_debug("NextEntryOffset: 0x%x", NextEntryOffset); //log_debug("CreationTime: 0x%llx", CreationTime); //log_debug("LastAccessTime: 0x%llx", LastAccessTime); //log_debug("LastWriteTime: 0x%llx", LastWriteTime); //log_debug("ChangeTime: 0x%llx", ChangeTime); //log_debug("EndOfFile: %lld", EndOfFile); //log_debug("FileAttributes: 0x%x", FileAttributes); #ifdef USE_SHORT_NAMES_IN_DIR_LISTING //log_debug("ShortNameLength: %d", ShortNameLength); #endif //log_debug("FileNameLength: %d", FileNameLength); log_debug("FileName: %s", filename); if ((xinode = calloc(1, sizeof(struct xrdp_inode))) == NULL) { log_error("system out of memory"); fuse_data = dev_redir_fuse_data_peek(irp); xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL); return; } strcpy(xinode->name, filename); xinode->size = (size_t) EndOfFile; xinode->mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes); xinode->atime = WINDOWS_TO_LINUX_TIME(LastAccessTime); xinode->mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime); xinode->ctime = WINDOWS_TO_LINUX_TIME(CreationTime); /* add this entry to xrdp file system */ fuse_data = dev_redir_fuse_data_peek(irp); xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, xinode); } dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL); }
void dev_redir_proc_device_iocompletion(struct stream *s) { FUSE_DATA *fuse_data = NULL; IRP *irp = NULL; tui32 DeviceId; tui32 CompletionId; tui32 IoStatus; tui32 Length; stream_rd_u32_le(s, DeviceId); stream_rd_u32_le(s, CompletionId); stream_rd_u32_le(s, IoStatus); /* LK_TODO need to check for IoStatus */ log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId); if ((irp = dev_redir_irp_find(CompletionId)) == NULL) { log_error("IRP with completion ID %d not found", CompletionId); return; } switch (irp->completion_type) { case CID_CREATE_DIR_REQ: log_debug("got CID_CREATE_DIR_REQ"); if (IoStatus != NT_STATUS_SUCCESS) { /* we were trying to create a request to enumerate a dir */ /* that does not exist; let FUSE know */ fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) { xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr, IoStatus); free(fuse_data); } dev_redir_irp_delete(irp); return; } stream_rd_u32_le(s, irp->FileId); log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d", IoStatus, irp->FileId); dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname); break; case CID_CREATE_OPEN_REQ: stream_rd_u32_le(s, irp->FileId); log_debug("got CID_CREATE_OPEN_REQ IoStatus=0x%x FileId=%d", IoStatus, irp->FileId); fuse_data = dev_redir_fuse_data_dequeue(irp); xfuse_devredir_cb_open_file(fuse_data->data_ptr, DeviceId, irp->FileId); if (irp->type == S_IFDIR) dev_redir_irp_delete(irp); break; case CID_READ: log_debug("got CID_READ"); stream_rd_u32_le(s, Length); fuse_data = dev_redir_fuse_data_dequeue(irp); xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length); break; case CID_WRITE: log_debug("got CID_WRITE"); stream_rd_u32_le(s, Length); fuse_data = dev_redir_fuse_data_dequeue(irp); xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length); break; case CID_CLOSE: log_debug("got CID_CLOSE"); log_debug("deleting irp with completion_id=%d comp_type=%d", irp->completion_id, irp->completion_type); dev_redir_irp_delete(irp); break; case CID_FILE_CLOSE: log_debug("got CID_FILE_CLOSE"); fuse_data = dev_redir_fuse_data_dequeue(irp); xfuse_devredir_cb_file_close(fuse_data->data_ptr); dev_redir_irp_delete(irp); break; case CID_DIRECTORY_CONTROL: log_debug("got CID_DIRECTORY_CONTROL"); dev_redir_proc_query_dir_response(irp, s, DeviceId, CompletionId, IoStatus); break; case CID_RMDIR_OR_FILE: log_debug("got CID_RMDIR_OR_FILE"); stream_rd_u32_le(s, irp->FileId); devredir_proc_cid_rmdir_or_file(irp, IoStatus); return; break; case CID_RMDIR_OR_FILE_RESP: log_debug("got CID_RMDIR_OR_FILE_RESP"); devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus); break; case CID_RENAME_FILE: log_debug("got CID_RENAME_FILE"); stream_rd_u32_le(s, irp->FileId); devredir_proc_cid_rename_file(irp, IoStatus); return; break; case CID_RENAME_FILE_RESP: log_debug("got CID_RENAME_FILE_RESP"); devredir_proc_cid_rename_file_resp(irp, IoStatus); break; default: log_error("got unknown CompletionID: DeviceId=0x%x " "CompletionId=0x%x IoStatus=0x%x", DeviceId, CompletionId, IoStatus); break; } if (fuse_data) free(fuse_data); log_debug("exiting"); }