|
|
@ -34,7 +34,57 @@
|
|
|
|
* o mark local funcs with static
|
|
|
|
* o mark local funcs with static
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "arch.h"
|
|
|
|
|
|
|
|
#include "parse.h"
|
|
|
|
|
|
|
|
#include "os_calls.h"
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
#include "chansrv_fuse.h"
|
|
|
|
#include "devredir.h"
|
|
|
|
#include "devredir.h"
|
|
|
|
|
|
|
|
#include "smartcard.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* module based logging */
|
|
|
|
|
|
|
|
#define LOG_ERROR 0
|
|
|
|
|
|
|
|
#define LOG_INFO 1
|
|
|
|
|
|
|
|
#define LOG_DEBUG 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef LOG_LEVEL
|
|
|
|
|
|
|
|
#define LOG_LEVEL LOG_DEBUG
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define log_error(_params...) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
g_write("[%10.10u]: DEV_REDIR %s: %d : ERROR: ", \
|
|
|
|
|
|
|
|
g_time3(), __func__, __LINE__); \
|
|
|
|
|
|
|
|
g_writeln (_params); \
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define log_info(_params...) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
if (LOG_INFO <= LOG_LEVEL) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
g_write("[%10.10u]: DEV_REDIR %s: %d : ", \
|
|
|
|
|
|
|
|
g_time3(), __func__, __LINE__); \
|
|
|
|
|
|
|
|
g_writeln (_params); \
|
|
|
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define log_debug(_params...) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
if (LOG_DEBUG <= LOG_LEVEL) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
g_write("[%10.10u]: DEV_REDIR %s: %d : ", \
|
|
|
|
|
|
|
|
g_time3(), __func__, __LINE__); \
|
|
|
|
|
|
|
|
g_writeln (_params); \
|
|
|
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* globals */
|
|
|
|
/* globals */
|
|
|
|
extern int g_rdpdr_chan_id; /* in chansrv.c */
|
|
|
|
extern int g_rdpdr_chan_id; /* in chansrv.c */
|
|
|
@ -43,14 +93,12 @@ int g_is_port_redir_supported = 0;
|
|
|
|
int g_is_drive_redir_supported = 0;
|
|
|
|
int g_is_drive_redir_supported = 0;
|
|
|
|
int g_is_smartcard_redir_supported = 0;
|
|
|
|
int g_is_smartcard_redir_supported = 0;
|
|
|
|
int g_drive_redir_version = 1;
|
|
|
|
int g_drive_redir_version = 1;
|
|
|
|
char g_preferred_dos_name_for_filesystem[9];
|
|
|
|
|
|
|
|
char g_full_name_for_filesystem[1024];
|
|
|
|
char g_full_name_for_filesystem[1024];
|
|
|
|
tui32 g_completion_id = 1;
|
|
|
|
tui32 g_completion_id = 1;
|
|
|
|
|
|
|
|
|
|
|
|
tui32 g_clientID; /* unique client ID - announced by client */
|
|
|
|
tui32 g_clientID; /* unique client ID - announced by client */
|
|
|
|
tui32 g_device_id; /* unique device ID - announced by client */
|
|
|
|
tui32 g_device_id; /* unique device ID - announced by client */
|
|
|
|
tui16 g_client_rdp_version; /* returned by client */
|
|
|
|
tui16 g_client_rdp_version; /* returned by client */
|
|
|
|
IRP *g_irp_head = NULL;
|
|
|
|
|
|
|
|
struct stream *g_input_stream = NULL;
|
|
|
|
struct stream *g_input_stream = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length);
|
|
|
|
void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length);
|
|
|
@ -207,7 +255,7 @@ dev_redir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case PAKID_CORE_DEVICELIST_ANNOUNCE:
|
|
|
|
case PAKID_CORE_DEVICELIST_ANNOUNCE:
|
|
|
|
dev_redir_proc_client_devlist_announce_req(ls);
|
|
|
|
devredir_proc_client_devlist_announce_req(ls);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case PAKID_CORE_DEVICE_IOCOMPLETION:
|
|
|
|
case PAKID_CORE_DEVICE_IOCOMPLETION:
|
|
|
@ -347,7 +395,7 @@ void dev_redir_send_server_user_logged_on()
|
|
|
|
xstream_free(s);
|
|
|
|
xstream_free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dev_redir_send_server_device_announce_resp(tui32 device_id)
|
|
|
|
void devredir_send_server_device_announce_resp(tui32 device_id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct stream *s;
|
|
|
|
int bytes;
|
|
|
|
int bytes;
|
|
|
@ -389,7 +437,7 @@ int dev_redir_send_drive_create_request(tui32 device_id, char *path,
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024 + len);
|
|
|
|
xstream_new(s, 1024 + len);
|
|
|
|
|
|
|
|
|
|
|
|
dev_redir_insert_dev_io_req_header(s,
|
|
|
|
devredir_insert_DeviceIoRequest(s,
|
|
|
|
device_id,
|
|
|
|
device_id,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
completion_id,
|
|
|
|
completion_id,
|
|
|
@ -432,7 +480,7 @@ int dev_redir_send_drive_close_request(tui16 Component, tui16 PacketId,
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
|
|
|
|
|
|
|
|
dev_redir_insert_dev_io_req_header(s, DeviceId, FileId, CompletionId,
|
|
|
|
devredir_insert_DeviceIoRequest(s, DeviceId, FileId, CompletionId,
|
|
|
|
MajorFunction, MinorFunc);
|
|
|
|
MajorFunction, MinorFunc);
|
|
|
|
|
|
|
|
|
|
|
|
if (pad_len)
|
|
|
|
if (pad_len)
|
|
|
@ -476,10 +524,10 @@ void dev_redir_send_drive_dir_request(IRP *irp, tui32 device_id,
|
|
|
|
xstream_new(s, 1024 + path_len);
|
|
|
|
xstream_new(s, 1024 + path_len);
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_DIRECTORY_CONTROL;
|
|
|
|
irp->completion_type = CID_DIRECTORY_CONTROL;
|
|
|
|
dev_redir_insert_dev_io_req_header(s,
|
|
|
|
devredir_insert_DeviceIoRequest(s,
|
|
|
|
device_id,
|
|
|
|
device_id,
|
|
|
|
irp->FileId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_DIRECTORY_CONTROL,
|
|
|
|
IRP_MJ_DIRECTORY_CONTROL,
|
|
|
|
IRP_MN_QUERY_DIRECTORY);
|
|
|
|
IRP_MN_QUERY_DIRECTORY);
|
|
|
|
|
|
|
|
|
|
|
@ -574,13 +622,14 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dev_redir_proc_client_devlist_announce_req(struct stream *s)
|
|
|
|
void devredir_proc_client_devlist_announce_req(struct stream *s)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int j;
|
|
|
|
tui32 device_count;
|
|
|
|
tui32 device_count;
|
|
|
|
tui32 device_type;
|
|
|
|
tui32 device_type;
|
|
|
|
tui32 device_data_len;
|
|
|
|
tui32 device_data_len;
|
|
|
|
|
|
|
|
char preferred_dos_name[9];
|
|
|
|
|
|
|
|
|
|
|
|
/* get number of devices being announced */
|
|
|
|
/* get number of devices being announced */
|
|
|
|
xstream_rd_u32_le(s, device_count);
|
|
|
|
xstream_rd_u32_le(s, device_count);
|
|
|
@ -590,8 +639,7 @@ void dev_redir_proc_client_devlist_announce_req(struct stream *s)
|
|
|
|
for (i = 0; i < device_count; i++)
|
|
|
|
for (i = 0; i < device_count; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
xstream_rd_u32_le(s, device_type);
|
|
|
|
xstream_rd_u32_le(s, device_type);
|
|
|
|
xstream_rd_u32_le(s, g_device_id); /* LK_TODO need to support */
|
|
|
|
xstream_rd_u32_le(s, g_device_id);
|
|
|
|
/* multiple drives */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (device_type)
|
|
|
|
switch (device_type)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -599,14 +647,11 @@ void dev_redir_proc_client_devlist_announce_req(struct stream *s)
|
|
|
|
/* get preferred DOS name */
|
|
|
|
/* get preferred DOS name */
|
|
|
|
for (j = 0; j < 8; j++)
|
|
|
|
for (j = 0; j < 8; j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
g_preferred_dos_name_for_filesystem[j] = *s->p++;
|
|
|
|
preferred_dos_name[j] = *s->p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* DOS names that are 8 chars long are not NULL terminated */
|
|
|
|
/* DOS names that are 8 chars long are not NULL terminated */
|
|
|
|
g_preferred_dos_name_for_filesystem[8] = 0;
|
|
|
|
preferred_dos_name[8] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* LK_TODO need to check for invalid chars in DOS name */
|
|
|
|
|
|
|
|
/* see section 2.2.1.3 of the protocol documentation */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* get device data len */
|
|
|
|
/* get device data len */
|
|
|
|
xstream_rd_u32_le(s, device_data_len);
|
|
|
|
xstream_rd_u32_le(s, device_data_len);
|
|
|
@ -618,22 +663,40 @@ void dev_redir_proc_client_devlist_announce_req(struct stream *s)
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("device_type=FILE_SYSTEM device_id=0x%x dosname=%s "
|
|
|
|
log_debug("device_type=FILE_SYSTEM device_id=0x%x dosname=%s "
|
|
|
|
"device_data_len=%d full_name=%s", g_device_id,
|
|
|
|
"device_data_len=%d full_name=%s", g_device_id,
|
|
|
|
g_preferred_dos_name_for_filesystem,
|
|
|
|
preferred_dos_name,
|
|
|
|
device_data_len, g_full_name_for_filesystem);
|
|
|
|
device_data_len, g_full_name_for_filesystem);
|
|
|
|
|
|
|
|
|
|
|
|
dev_redir_send_server_device_announce_resp(g_device_id);
|
|
|
|
devredir_send_server_device_announce_resp(g_device_id);
|
|
|
|
|
|
|
|
|
|
|
|
/* create share directory in xrdp file system; */
|
|
|
|
/* create share directory in xrdp file system; */
|
|
|
|
/* think of this as the mount point for this share */
|
|
|
|
/* think of this as the mount point for this share */
|
|
|
|
xfuse_create_share(g_device_id,
|
|
|
|
xfuse_create_share(g_device_id, preferred_dos_name);
|
|
|
|
g_preferred_dos_name_for_filesystem);
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case RDPDR_DTYP_SMARTCARD:
|
|
|
|
|
|
|
|
/* get preferred DOS name */
|
|
|
|
|
|
|
|
for (j = 0; j < 8; j++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
preferred_dos_name[j] = *s->p++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* DOS names that are 8 chars long are not NULL terminated */
|
|
|
|
|
|
|
|
preferred_dos_name[8] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* for smart cards, device data len always 0 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("device_type=SMARTCARD device_id=0x%x dosname=%s "
|
|
|
|
|
|
|
|
"device_data_len=%d",
|
|
|
|
|
|
|
|
g_device_id, preferred_dos_name, device_data_len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
devredir_send_server_device_announce_resp(g_device_id);
|
|
|
|
|
|
|
|
scard_device_announce(g_device_id);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
/* we don't yet support these devices */
|
|
|
|
/* we don't yet support these devices */
|
|
|
|
case RDPDR_DTYP_SERIAL:
|
|
|
|
case RDPDR_DTYP_SERIAL:
|
|
|
|
case RDPDR_DTYP_PARALLEL:
|
|
|
|
case RDPDR_DTYP_PARALLEL:
|
|
|
|
case RDPDR_DTYP_PRINT:
|
|
|
|
case RDPDR_DTYP_PRINT:
|
|
|
|
case RDPDR_DTYP_SMARTCARD:
|
|
|
|
|
|
|
|
log_debug("unsupported dev: 0x%x", device_type);
|
|
|
|
log_debug("unsupported dev: 0x%x", device_type);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -658,12 +721,19 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId);
|
|
|
|
log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId);
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_find(CompletionId)) == NULL)
|
|
|
|
if ((irp = devredir_irp_find(CompletionId)) == NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_error("IRP with completion ID %d not found", CompletionId);
|
|
|
|
log_error("IRP with completion ID %d not found", CompletionId);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if callback has been set, call it */
|
|
|
|
|
|
|
|
if (irp->callback)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(*irp->callback)(s, irp, DeviceId, CompletionId, IoStatus);
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (irp->completion_type)
|
|
|
|
switch (irp->completion_type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case CID_CREATE_DIR_REQ:
|
|
|
|
case CID_CREATE_DIR_REQ:
|
|
|
@ -679,7 +749,7 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
|
|
|
|
IoStatus);
|
|
|
|
IoStatus);
|
|
|
|
free(fuse_data);
|
|
|
|
free(fuse_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -698,7 +768,7 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
|
|
|
|
xfuse_devredir_cb_open_file(fuse_data->data_ptr,
|
|
|
|
xfuse_devredir_cb_open_file(fuse_data->data_ptr,
|
|
|
|
DeviceId, irp->FileId);
|
|
|
|
DeviceId, irp->FileId);
|
|
|
|
if (irp->type == S_IFDIR)
|
|
|
|
if (irp->type == S_IFDIR)
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case CID_READ:
|
|
|
|
case CID_READ:
|
|
|
@ -718,15 +788,15 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
|
|
|
|
case CID_CLOSE:
|
|
|
|
case CID_CLOSE:
|
|
|
|
log_debug("got CID_CLOSE");
|
|
|
|
log_debug("got CID_CLOSE");
|
|
|
|
log_debug("deleting irp with completion_id=%d comp_type=%d",
|
|
|
|
log_debug("deleting irp with completion_id=%d comp_type=%d",
|
|
|
|
irp->completion_id, irp->completion_type);
|
|
|
|
irp->CompletionId, irp->completion_type);
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case CID_FILE_CLOSE:
|
|
|
|
case CID_FILE_CLOSE:
|
|
|
|
log_debug("got CID_FILE_CLOSE");
|
|
|
|
log_debug("got CID_FILE_CLOSE");
|
|
|
|
fuse_data = dev_redir_fuse_data_dequeue(irp);
|
|
|
|
fuse_data = dev_redir_fuse_data_dequeue(irp);
|
|
|
|
xfuse_devredir_cb_file_close(fuse_data->data_ptr);
|
|
|
|
xfuse_devredir_cb_file_close(fuse_data->data_ptr);
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case CID_DIRECTORY_CONTROL:
|
|
|
|
case CID_DIRECTORY_CONTROL:
|
|
|
@ -767,6 +837,8 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
|
|
|
|
if (fuse_data)
|
|
|
|
if (fuse_data)
|
|
|
|
free(fuse_data);
|
|
|
|
free(fuse_data);
|
|
|
|
|
|
|
|
|
|
|
@ -815,7 +887,7 @@ void dev_redir_proc_query_dir_response(IRP *irp,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
DeviceId,
|
|
|
|
DeviceId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
free(fuse_data);
|
|
|
|
free(fuse_data);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -908,15 +980,15 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("fusep=%p", fusep);
|
|
|
|
log_debug("fusep=%p", fusep);
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_new()) == NULL)
|
|
|
|
if ((irp = devredir_irp_new()) == NULL)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
/* cvt / to windows compatible \ */
|
|
|
|
/* cvt / to windows compatible \ */
|
|
|
|
devredir_cvt_slash(path);
|
|
|
|
devredir_cvt_slash(path);
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_id = g_completion_id++;
|
|
|
|
irp->CompletionId = g_completion_id++;
|
|
|
|
irp->completion_type = CID_CREATE_DIR_REQ;
|
|
|
|
irp->completion_type = CID_CREATE_DIR_REQ;
|
|
|
|
irp->device_id = device_id;
|
|
|
|
irp->DeviceId = device_id;
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
|
|
|
|
|
|
|
@ -927,7 +999,7 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
CreateDisposition,
|
|
|
|
CreateDisposition,
|
|
|
|
irp->completion_id);
|
|
|
|
irp->CompletionId);
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("looking for device_id=%d path=%s", device_id, path);
|
|
|
|
log_debug("looking for device_id=%d path=%s", device_id, path);
|
|
|
|
|
|
|
|
|
|
|
@ -953,7 +1025,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("device_id=%d path=%s mode=0x%x", device_id, path, mode);
|
|
|
|
log_debug("device_id=%d path=%s mode=0x%x", device_id, path, mode);
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_new()) == NULL)
|
|
|
|
if ((irp = devredir_irp_new()) == NULL)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
if (type & OP_RENAME_FILE)
|
|
|
|
if (type & OP_RENAME_FILE)
|
|
|
@ -966,8 +1038,8 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
|
|
|
|
irp->completion_type = CID_CREATE_OPEN_REQ;
|
|
|
|
irp->completion_type = CID_CREATE_OPEN_REQ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_id = g_completion_id++;
|
|
|
|
irp->CompletionId = g_completion_id++;
|
|
|
|
irp->device_id = device_id;
|
|
|
|
irp->DeviceId = device_id;
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
|
|
|
|
|
|
|
@ -1009,7 +1081,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
CreateDisposition,
|
|
|
|
CreateDisposition,
|
|
|
|
irp->completion_id);
|
|
|
|
irp->CompletionId);
|
|
|
|
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1021,26 +1093,26 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId)
|
|
|
|
log_debug("entered");
|
|
|
|
log_debug("entered");
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#if 0
|
|
|
|
if ((irp = dev_redir_irp_new()) == NULL)
|
|
|
|
if ((irp = devredir_irp_new()) == NULL)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_id = g_completion_id++;
|
|
|
|
irp->CompletionId = g_completion_id++;
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
irp->completion_type = CID_FILE_CLOSE;
|
|
|
|
irp->completion_type = CID_FILE_CLOSE;
|
|
|
|
irp->device_id = device_id;
|
|
|
|
irp->DeviceId = device_id;
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
|
|
|
|
|
|
|
|
return dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
return dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
device_id,
|
|
|
|
device_id,
|
|
|
|
FileId,
|
|
|
|
FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_CLOSE,
|
|
|
|
IRP_MJ_CLOSE,
|
|
|
|
0, 32);
|
|
|
|
0, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1057,12 +1129,12 @@ int devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode)
|
|
|
|
int rval;
|
|
|
|
int rval;
|
|
|
|
IRP *irp;
|
|
|
|
IRP *irp;
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_new()) == NULL)
|
|
|
|
if ((irp = devredir_irp_new()) == NULL)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_id = g_completion_id++;
|
|
|
|
irp->CompletionId = g_completion_id++;
|
|
|
|
irp->completion_type = CID_RMDIR_OR_FILE;
|
|
|
|
irp->completion_type = CID_RMDIR_OR_FILE;
|
|
|
|
irp->device_id = device_id;
|
|
|
|
irp->DeviceId = device_id;
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
strcpy(irp->pathname, path);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
|
|
|
|
|
|
|
@ -1079,7 +1151,7 @@ int devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode)
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
rval = dev_redir_send_drive_create_request(device_id, path,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
DesiredAccess, CreateOptions,
|
|
|
|
CreateDisposition,
|
|
|
|
CreateDisposition,
|
|
|
|
irp->completion_id);
|
|
|
|
irp->CompletionId);
|
|
|
|
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1099,7 +1171,7 @@ int dev_redir_file_read(void *fusep, tui32 DeviceId, tui32 FileId,
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
xfuse_devredir_cb_read_file(fusep, NULL, 0);
|
|
|
|
xfuse_devredir_cb_read_file(fusep, NULL, 0);
|
|
|
@ -1108,10 +1180,10 @@ int dev_redir_file_read(void *fusep, tui32 DeviceId, tui32 FileId,
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_READ;
|
|
|
|
irp->completion_type = CID_READ;
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_insert_dev_io_req_header(s,
|
|
|
|
devredir_insert_DeviceIoRequest(s,
|
|
|
|
DeviceId,
|
|
|
|
DeviceId,
|
|
|
|
FileId,
|
|
|
|
FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_READ,
|
|
|
|
IRP_MJ_READ,
|
|
|
|
0);
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
|
@ -1139,7 +1211,7 @@ int dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024 + Length);
|
|
|
|
xstream_new(s, 1024 + Length);
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
log_error("no IRP found with FileId = %d", FileId);
|
|
|
|
xfuse_devredir_cb_write_file(fusep, NULL, 0);
|
|
|
|
xfuse_devredir_cb_write_file(fusep, NULL, 0);
|
|
|
@ -1148,10 +1220,10 @@ int dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_WRITE;
|
|
|
|
irp->completion_type = CID_WRITE;
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_fuse_data_enqueue(irp, fusep);
|
|
|
|
dev_redir_insert_dev_io_req_header(s,
|
|
|
|
devredir_insert_DeviceIoRequest(s,
|
|
|
|
DeviceId,
|
|
|
|
DeviceId,
|
|
|
|
FileId,
|
|
|
|
FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_WRITE,
|
|
|
|
IRP_MJ_WRITE,
|
|
|
|
0);
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
|
@ -1249,182 +1321,11 @@ int dev_redir_fuse_data_enqueue(IRP *irp, void *vp)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
|
|
** IRP stuff **
|
|
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Create a new IRP and append to linked list
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return new IRP or NULL on error
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IRP * dev_redir_irp_new()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *irp;
|
|
|
|
|
|
|
|
IRP *irp_last;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("=== entered");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* create new IRP */
|
|
|
|
|
|
|
|
if ((irp = calloc(1, sizeof(IRP))) == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
log_error("system out of memory!");
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* insert at end of linked list */
|
|
|
|
|
|
|
|
if ((irp_last = dev_redir_irp_get_last()) == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* list is empty, this is the first entry */
|
|
|
|
|
|
|
|
g_irp_head = irp;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
irp_last->next = irp;
|
|
|
|
|
|
|
|
irp->prev = irp_last;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return irp;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Delete specified IRP from linked list
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return 0 on success, -1 on failure
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int dev_redir_irp_delete(IRP *irp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *lirp = g_irp_head;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("=== entered; completion_id=%d type=%d",
|
|
|
|
|
|
|
|
irp->completion_id, irp->completion_type);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((irp == NULL) || (lirp == NULL))
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dev_redir_irp_dump(); // LK_TODO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (lirp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (lirp == irp)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lirp = lirp->next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lirp == NULL)
|
|
|
|
|
|
|
|
return -1; /* did not find specified irp */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lirp->prev == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* we are at head of linked list */
|
|
|
|
|
|
|
|
if (lirp->next == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* only one element in list */
|
|
|
|
|
|
|
|
free(lirp);
|
|
|
|
|
|
|
|
g_irp_head = NULL;
|
|
|
|
|
|
|
|
dev_redir_irp_dump(); // LK_TODO
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lirp->next->prev = NULL;
|
|
|
|
|
|
|
|
g_irp_head = lirp->next;
|
|
|
|
|
|
|
|
free(lirp);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (lirp->next == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* we are at tail of linked list */
|
|
|
|
|
|
|
|
lirp->prev->next = NULL;
|
|
|
|
|
|
|
|
free(lirp);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* we are in between */
|
|
|
|
|
|
|
|
lirp->prev->next = lirp->next;
|
|
|
|
|
|
|
|
lirp->next->prev = lirp->prev;
|
|
|
|
|
|
|
|
free(lirp);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dev_redir_irp_dump(); // LK_TODO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Return IRP containing specified completion_id
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IRP *dev_redir_irp_find(tui32 completion_id)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *irp = g_irp_head;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (irp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (irp->completion_id == completion_id)
|
|
|
|
|
|
|
|
return irp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
irp = irp->next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IRP * dev_redir_irp_find_by_fileid(tui32 FileId)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *irp = g_irp_head;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (irp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (irp->FileId == FileId)
|
|
|
|
|
|
|
|
return irp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
irp = irp->next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Return last IRP in linked list
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IRP * dev_redir_irp_get_last()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *irp = g_irp_head;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (irp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (irp->next == NULL)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
irp = irp->next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return irp;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void dev_redir_irp_dump()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IRP *irp = g_irp_head;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_debug("------- dumping IRPs --------");
|
|
|
|
|
|
|
|
while (irp)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
log_debug(" completion_id=%d\tcompletion_type=%d\tFileId=%d",
|
|
|
|
|
|
|
|
irp->completion_id, irp->completion_type, irp->FileId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
irp = irp->next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("------- dumping IRPs done ---");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
/******************************************************************************
|
|
|
|
** miscellaneous stuff **
|
|
|
|
** miscellaneous stuff **
|
|
|
|
******************************************************************************/
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
void dev_redir_insert_dev_io_req_header(struct stream *s,
|
|
|
|
void devredir_insert_DeviceIoRequest(struct stream *s,
|
|
|
|
tui32 DeviceId,
|
|
|
|
tui32 DeviceId,
|
|
|
|
tui32 FileId,
|
|
|
|
tui32 FileId,
|
|
|
|
tui32 CompletionId,
|
|
|
|
tui32 CompletionId,
|
|
|
@ -1492,7 +1393,7 @@ int dev_redir_string_ends_with(char *string, char c)
|
|
|
|
return (string[len - 1] == c) ? 1 : 0;
|
|
|
|
return (string[len - 1] == c) ? 1 : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dev_redir_insert_rdpdr_header(struct stream *s, tui16 Component,
|
|
|
|
void devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
|
|
|
|
tui16 PacketId)
|
|
|
|
tui16 PacketId)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
xstream_wr_u16_le(s, Component);
|
|
|
|
xstream_wr_u16_le(s, Component);
|
|
|
@ -1512,15 +1413,15 @@ void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
|
|
|
|
xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus);
|
|
|
|
xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus);
|
|
|
|
free(fuse_data);
|
|
|
|
free(fuse_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_RMDIR_OR_FILE_RESP;
|
|
|
|
irp->completion_type = CID_RMDIR_OR_FILE_RESP;
|
|
|
|
dev_redir_insert_dev_io_req_header(s, irp->device_id, irp->FileId,
|
|
|
|
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_SET_INFORMATION, 0);
|
|
|
|
IRP_MJ_SET_INFORMATION, 0);
|
|
|
|
|
|
|
|
|
|
|
|
xstream_wr_u32_le(s, FileDispositionInformation);
|
|
|
|
xstream_wr_u32_le(s, FileDispositionInformation);
|
|
|
@ -1548,16 +1449,16 @@ void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
|
|
|
|
|
|
|
|
|
|
|
|
if (IoStatus != NT_STATUS_SUCCESS)
|
|
|
|
if (IoStatus != NT_STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_CLOSE;
|
|
|
|
irp->completion_type = CID_CLOSE;
|
|
|
|
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
irp->device_id,
|
|
|
|
irp->DeviceId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1579,15 +1480,15 @@ void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
|
|
|
xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
|
|
|
|
xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
|
|
|
|
free(fuse_data);
|
|
|
|
free(fuse_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
xstream_new(s, 1024);
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_RENAME_FILE_RESP;
|
|
|
|
irp->completion_type = CID_RENAME_FILE_RESP;
|
|
|
|
dev_redir_insert_dev_io_req_header(s, irp->device_id, irp->FileId,
|
|
|
|
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_SET_INFORMATION, 0);
|
|
|
|
IRP_MJ_SET_INFORMATION, 0);
|
|
|
|
|
|
|
|
|
|
|
|
flen = strlen(irp->gen_buf) * 2 + 2;
|
|
|
|
flen = strlen(irp->gen_buf) * 2 + 2;
|
|
|
@ -1627,15 +1528,15 @@ void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
|
|
|
|
|
|
|
|
|
|
|
|
if (IoStatus != NT_STATUS_SUCCESS)
|
|
|
|
if (IoStatus != NT_STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
dev_redir_irp_delete(irp);
|
|
|
|
devredir_irp_delete(irp);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
irp->completion_type = CID_CLOSE;
|
|
|
|
irp->completion_type = CID_CLOSE;
|
|
|
|
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
PAKID_CORE_DEVICE_IOREQUEST,
|
|
|
|
irp->device_id,
|
|
|
|
irp->DeviceId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->FileId,
|
|
|
|
irp->completion_id,
|
|
|
|
irp->CompletionId,
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
IRP_MJ_CLOSE, 0, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|