Added rename file and fixed some minor bugs.
authorMike McDonald <Mike.McDonald@software.dell.com>
Tue, 30 Dec 2014 23:41:21 +0000 (18:41 -0500)
committerMike McDonald <Mike.McDonald@software.dell.com>
Tue, 30 Dec 2014 23:41:21 +0000 (18:41 -0500)
channels/rdpdr/server/rdpdr_main.c
channels/rdpdr/server/rdpdr_main.h

index 4f247c0..9d5be7d 100644 (file)
@@ -872,7 +872,7 @@ static BOOL rdpdr_server_send_device_create_request(
        WLog_DBG(TAG, "%s: deviceId=%d, path=%s, desiredAccess=0x%x createOptions=0x%x createDisposition=0x%x",
                __FUNCTION__, deviceId, path, desiredAccess, createOptions, createDisposition);
 
-       /* Computer the required Unicode size. */
+       /* Compute the required Unicode size. */
        pathLength = (strlen(path) + 1) * sizeof(WCHAR);
 
        s = Stream_New(NULL, 256 + pathLength);
@@ -997,7 +997,7 @@ static BOOL rdpdr_server_send_device_write_request(
     return status;
 }
 
-static BOOL rdpdr_server_send_device_query_directory(
+static BOOL rdpdr_server_send_device_query_directory_request(
        RdpdrServerContext* context,
        UINT32 deviceId,
        UINT32 fileId,
@@ -1012,7 +1012,7 @@ static BOOL rdpdr_server_send_device_query_directory(
 
        WLog_DBG(TAG, "%s: deviceId=%d, fileId=%d, path=%s", __FUNCTION__, deviceId, fileId, path);
 
-       /* Computer the required Unicode size. */
+       /* Compute the required Unicode size. */
        pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
 
        s = Stream_New(NULL, 64 + pathLength);
@@ -1040,6 +1040,53 @@ static BOOL rdpdr_server_send_device_query_directory(
     return status;
 }
 
+static BOOL rdpdr_server_send_device_file_rename_request(
+       RdpdrServerContext* context,
+       UINT32 deviceId,
+       UINT32 fileId,
+       UINT32 completionId,
+       const char* path
+)
+{
+       int pathLength;
+       ULONG written;
+       BOOL status;
+       wStream* s;
+
+       WLog_DBG(TAG, "%s: deviceId=%d, fileId=%d, path=%s", __FUNCTION__, deviceId, fileId, path);
+
+       /* Compute the required Unicode size. */
+       pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
+
+       s = Stream_New(NULL, 64 + pathLength);
+
+       rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION, 0);
+
+       Stream_Write_UINT32(s, FileRenameInformation); /* FsInformationClass (4 bytes) */
+       Stream_Write_UINT32(s, pathLength + 6); /* Length (4 bytes) */
+       Stream_Zero(s, 24); /* Padding (24 bytes) */
+
+       /* RDP_FILE_RENAME_INFORMATION */
+       Stream_Write_UINT8(s, 0); /* ReplaceIfExists (1 byte) */
+       Stream_Write_UINT8(s, 0); /* RootDirectory (1 byte) */
+       Stream_Write_UINT32(s, pathLength); /* FileNameLength (4 bytes) */
+
+       /* Convert the path to Unicode. */
+       if (pathLength > 0)
+       {
+               MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR) Stream_Pointer(s), pathLength);
+               Stream_Seek(s, pathLength);
+       }
+
+    Stream_SealLength(s);
+
+       status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
+
+    Stream_Free(s, TRUE);
+
+    return status;
+}
+
 static void rdpdr_server_convert_slashes(char* path, int size)
 {
        int i;
@@ -1123,8 +1170,8 @@ static BOOL rdpdr_server_drive_create_directory(RdpdrServerContext* context, voi
        rdpdr_server_send_device_create_request(
                context, deviceId, irp->CompletionId, irp->PathName,
                FILE_READ_DATA | SYNCHRONIZE,
-               FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT,
-               FILE_OPEN);
+               FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_CREATE);
 
        return TRUE;
 }
@@ -1200,7 +1247,7 @@ static BOOL rdpdr_server_drive_delete_directory(RdpdrServerContext* context, voi
        /* Send a request to open the file. */
        rdpdr_server_send_device_create_request(
                context, deviceId, irp->CompletionId, irp->PathName,
-               FILE_READ_DATA | SYNCHRONIZE,
+               DELETE | SYNCHRONIZE,
                FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT,
                FILE_OPEN);
 
@@ -1218,32 +1265,39 @@ static void rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
 
        WLog_DBG(TAG, "%s: deviceId=%d, completionId=%d, ioStatus=0x%x", __FUNCTION__, deviceId, completionId, ioStatus);
 
-       if (ioStatus != STATUS_SUCCESS)
-       {
-               /* Invoke the query directory completion routine. */
-               context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
-
-               /* Destroy the IRP. */
-               rdpdr_server_irp_free(irp);
+       Stream_Read_UINT32(s, length); /* Length (4 bytes) */
 
-               return;
+       if (length > 0)
+       {
+               rdpdr_server_read_file_directory_information(s, &fdi);
+       }
+       else
+       {
+               Stream_Seek(s, 1); /* Padding (1 byte) */
        }
 
-       Stream_Read_UINT32(s, length); /* Length (4 bytes) */
-
-       rdpdr_server_read_file_directory_information(s, &fdi);
+       if (ioStatus == STATUS_SUCCESS)
+       {
+               /* Invoke the query directory completion routine. */
+               context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, length > 0 ? &fdi : NULL);
 
-       /* Invoke the query directory completion routine. */
-       context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, &fdi);
+               /* Setup the IRP. */
+               irp->CompletionId = context->priv->NextCompletionId++;
+               irp->Callback = rdpdr_server_drive_query_directory_callback2;
 
-       /* Setup the IRP. */
-       irp->CompletionId = context->priv->NextCompletionId++;
-       irp->Callback = rdpdr_server_drive_query_directory_callback2;
+               rdpdr_server_enqueue_irp(context, irp);
 
-       rdpdr_server_enqueue_irp(context, irp);
+               /* Send a request to query the directory. */
+               rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId, irp->CompletionId, NULL);
+       }
+       else
+       {
+               /* Invoke the query directory completion routine. */
+               context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
 
-       /* Send a request to enumerate the directory. */
-       rdpdr_server_send_device_query_directory(context, irp->DeviceId, irp->FileId, irp->CompletionId, NULL);
+               /* Destroy the IRP. */
+               rdpdr_server_irp_free(irp);
+       }
 }
 
 static void rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
@@ -1275,8 +1329,8 @@ static void rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* con
 
        rdpdr_server_enqueue_irp(context, irp);
 
-       /* Send a request to enumerate the directory. */
-       rdpdr_server_send_device_query_directory(context, deviceId, fileId, irp->CompletionId, irp->PathName);
+       /* Send a request to query the directory. */
+       rdpdr_server_send_device_query_directory_request(context, deviceId, fileId, irp->CompletionId, irp->PathName);
 }
 
 static BOOL rdpdr_server_drive_query_directory(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* path)
@@ -1564,9 +1618,105 @@ static BOOL rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* ca
        return TRUE;
 }
 
+/*************************************************
+ * Drive Rename File
+ ************************************************/
+
+static void rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
+{
+       WLog_DBG(TAG, "%s: deviceId=%d, completionId=%d, ioStatus=0x%x", __FUNCTION__, deviceId, completionId, ioStatus);
+
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+}
+
+static void rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
+{
+       UINT32 length;
+
+       WLog_DBG(TAG, "%s: deviceId=%d, completionId=%d, ioStatus=0x%x", __FUNCTION__, deviceId, completionId, ioStatus);
+
+       Stream_Read_UINT32(s, length); /* Length (4 bytes) */
+       Stream_Seek(s, 1); /* Padding (1 byte) */
+
+       /* Invoke the rename file completion routine. */
+       context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
+
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_rename_file_callback3;
+       irp->DeviceId = deviceId;
+
+       rdpdr_server_enqueue_irp(context, irp);
+
+       /* Send a request to close the file */
+       rdpdr_server_send_device_close_request(context, deviceId, irp->FileId, irp->CompletionId);
+}
+
+static void rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
+{
+       UINT32 fileId;
+       UINT8 information;
+
+       WLog_DBG(TAG, "%s: deviceId=%d, completionId=%d, ioStatus=0x%x", __FUNCTION__, deviceId, completionId, ioStatus);
+
+       if (ioStatus != STATUS_SUCCESS)
+       {
+               /* Invoke the rename file completion routine. */
+               context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
+
+               /* Destroy the IRP. */
+               rdpdr_server_irp_free(irp);
+
+               return;
+       }
+
+       Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */
+       Stream_Read_UINT8(s, information); /* Information (1 byte) */
+
+       printf("%s: FileId=%u\n", __FUNCTION__, fileId); fflush(stdout);
+
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_rename_file_callback2;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+
+       rdpdr_server_enqueue_irp(context, irp);
+
+       /* Send a request to rename the file */
+       rdpdr_server_send_device_file_rename_request(context, deviceId, fileId, irp->CompletionId, irp->ExtraBuffer);
+}
+
 static BOOL rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* oldPath, const char* newPath)
 {
-       context->OnDriveRenameFileComplete(context, callbackData, STATUS_ACCESS_DENIED);
+       RDPDR_IRP* irp;
+
+       /* Create an IRP. */
+       irp = rdpdr_server_irp_new();
+       if (irp == NULL) return FALSE;
+
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_rename_file_callback1;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, oldPath, sizeof(irp->PathName));
+       strncpy(irp->ExtraBuffer, newPath, sizeof(irp->ExtraBuffer));
+
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->ExtraBuffer, sizeof(irp->ExtraBuffer));
+
+       printf("PathName=%s\n", irp->PathName); fflush(stdout);
+       printf("ExtraBuffer=%s\n", irp->ExtraBuffer); fflush(stdout);
+
+       rdpdr_server_enqueue_irp(context, irp);
+
+       /* Send a request to open the file. */
+       rdpdr_server_send_device_create_request(
+               context, deviceId, irp->CompletionId, irp->PathName,
+               FILE_READ_DATA | SYNCHRONIZE,
+               FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_OPEN);
 
        return TRUE;
 }
index 2768eb4..4fd4759 100644 (file)
@@ -78,6 +78,7 @@ struct _RDPDR_IRP
        UINT32 DeviceId;
        UINT32 FileId;
        char PathName[256];
+       char ExtraBuffer[256];
        void *CallbackData;
        void (*Callback)(RdpdrServerContext* context, wStream* s, struct _RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus);
 };