Merge branch 'awakecoding' of https://github.com/vworkspace/FreeRDP
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 20 May 2015 15:40:48 +0000 (11:40 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 20 May 2015 15:40:48 +0000 (11:40 -0400)
Conflicts:
channels/rdpdr/server/rdpdr_main.c

1  2 
channels/rdpdr/server/rdpdr_main.c
libfreerdp/core/capabilities.c
libfreerdp/core/peer.c
winpr/libwinpr/utils/wlog/FileAppender.c

@@@ -591,37 -825,967 +825,968 @@@ static int rdpdr_server_stop(RdpdrServe
        return 0;
  }
  
- RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
+ static void rdpdr_server_write_device_iorequest(
+       wStream* s,
+       UINT32 deviceId,
+       UINT32 fileId,
+       UINT32 completionId,
+       UINT32 majorFunction,
+       UINT32 minorFunction
+ )
  {
-       RdpdrServerContext* context;
-       context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext));
+       Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */
+       Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST); /* PacketId (2 bytes) */
+       Stream_Write_UINT32(s, deviceId); /* DeviceId (4 bytes) */
+       Stream_Write_UINT32(s, fileId); /* FileId (4 bytes) */
+       Stream_Write_UINT32(s, completionId); /* CompletionId (4 bytes) */
+       Stream_Write_UINT32(s, majorFunction); /* MajorFunction (4 bytes) */
+       Stream_Write_UINT32(s, minorFunction); /* MinorFunction (4 bytes) */
+ }
  
-       if (context)
-       {
-               ZeroMemory(context, sizeof(RdpdrServerContext));
-               context->vcm = vcm;
-               context->Start = rdpdr_server_start;
-               context->Stop = rdpdr_server_stop;
-               context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate));
+ static BOOL rdpdr_server_read_file_directory_information(wStream* s, FILE_DIRECTORY_INFORMATION* fdi)
+ {
+       UINT32 fileNameLength;
  
-               if (context->priv)
-               {
-                       ZeroMemory(context->priv, sizeof(RdpdrServerPrivate));
-                       context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
-                       context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
-                       context->priv->ClientId = g_ClientId++;
-                       context->priv->UserLoggedOnPdu = TRUE;
-               }
-       }
+       ZeroMemory(fdi, sizeof(FILE_DIRECTORY_INFORMATION));
  
-       return context;
+       Stream_Read_UINT32(s, fdi->NextEntryOffset); /* NextEntryOffset (4 bytes) */
+       Stream_Read_UINT32(s, fdi->FileIndex); /* FileIndex (4 bytes) */
+       Stream_Read_UINT64(s, fdi->CreationTime); /* CreationTime (8 bytes) */
+       Stream_Read_UINT64(s, fdi->LastAccessTime); /* LastAccessTime (8 bytes) */
+       Stream_Read_UINT64(s, fdi->LastWriteTime); /* LastWriteTime (8 bytes) */
+       Stream_Read_UINT64(s, fdi->ChangeTime); /* ChangeTime (8 bytes) */
+       Stream_Read_UINT64(s, fdi->EndOfFile); /* EndOfFile (8 bytes) */
+       Stream_Read_UINT64(s, fdi->AllocationSize); /* AllocationSize (8 bytes) */
+       Stream_Read_UINT32(s, fdi->FileAttributes); /* FileAttributes (4 bytes) */
+       Stream_Read_UINT32(s, fileNameLength); /* FileNameLength (4 bytes) */
+       WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) Stream_Pointer(s), fileNameLength / 2, fdi->FileName, sizeof(fdi->FileName), NULL, NULL);
+       Stream_Seek(s, fileNameLength);
+       return TRUE;
  }
  
- void rdpdr_server_context_free(RdpdrServerContext* context)
+ static BOOL rdpdr_server_send_device_create_request(
+       RdpdrServerContext* context,
+       UINT32 deviceId,
+       UINT32 completionId,
+       const char* path,
+       UINT32 desiredAccess,
+       UINT32 createOptions,
+       UINT32 createDisposition
+ )
  {
-       if (context)
-       {
-               free(context->priv);
-               free(context);
-       }
+       int pathLength;
+       ULONG written;
+       BOOL status;
+       wStream* s;
+       WLog_DBG(TAG, "%s: deviceId=%d, path=%s, desiredAccess=0x%x createOptions=0x%x createDisposition=0x%x",
+               __FUNCTION__, deviceId, path, desiredAccess, createOptions, createDisposition);
+       /* Compute the required Unicode size. */
+       pathLength = (strlen(path) + 1) * sizeof(WCHAR);
+       s = Stream_New(NULL, 256 + pathLength);
+       rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
+       Stream_Write_UINT32(s, desiredAccess); /* DesiredAccess (4 bytes) */
+     Stream_Write_UINT32(s, 0); /* AllocationSize (8 bytes) */
+     Stream_Write_UINT32(s, 0);
+     Stream_Write_UINT32(s, 0); /* FileAttributes (4 bytes) */
+     Stream_Write_UINT32(s, 3); /* SharedAccess (4 bytes) */
+     Stream_Write_UINT32(s, createDisposition); /* CreateDisposition (4 bytes) */
+     Stream_Write_UINT32(s, createOptions); /* CreateOptions (4 bytes) */
+     Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */
+       /* Convert the path to Unicode. */
+       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 BOOL rdpdr_server_send_device_close_request(
+       RdpdrServerContext* context,
+       UINT32 deviceId,
+       UINT32 fileId,
+       UINT32 completionId
+ )
+ {
+       ULONG written;
+       BOOL status;
+       wStream* s;
+       WLog_DBG(TAG, "%s: deviceId=%d, fileId=%d", __FUNCTION__, deviceId, fileId);
+       s = Stream_New(NULL, 128);
+       rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0);
+       Stream_Zero(s, 32); /* Padding (32 bytes) */
+     Stream_SealLength(s);
+       status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
+     Stream_Free(s, TRUE);
+     return status;
+ }
+ static BOOL rdpdr_server_send_device_read_request(
+       RdpdrServerContext* context,
+       UINT32 deviceId,
+       UINT32 fileId,
+       UINT32 completionId,
+       UINT32 length,
+       UINT32 offset
+ )
+ {
+       ULONG written;
+       BOOL status;
+       wStream* s;
+       WLog_DBG(TAG, "%s: deviceId=%d, fileId=%d, length=%d, offset=%d", __FUNCTION__, deviceId, fileId, length, offset);
+       s = Stream_New(NULL, 128);
+       rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0);
+       Stream_Write_UINT32(s, length); /* Length (4 bytes) */
+       Stream_Write_UINT32(s, offset); /* Offset (8 bytes) */
+       Stream_Write_UINT32(s, 0);
+       Stream_Zero(s, 20); /* Padding (20 bytes) */
+     Stream_SealLength(s);
+       status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
+     Stream_Free(s, TRUE);
+     return status;
  }
+ static BOOL rdpdr_server_send_device_write_request(
+       RdpdrServerContext* context,
+       UINT32 deviceId,
+       UINT32 fileId,
+       UINT32 completionId,
+       const char* data,
+       UINT32 length,
+       UINT32 offset
+ )
+ {
+       ULONG written;
+       BOOL status;
+       wStream* s;
+       WLog_DBG(TAG, "%s: deviceId=%d, fileId=%d, length=%d, offset=%d", __FUNCTION__, deviceId, fileId, length, offset);
+       s = Stream_New(NULL, 64 + length);
+       rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0);
+       Stream_Write_UINT32(s, length); /* Length (4 bytes) */
+       Stream_Write_UINT32(s, offset); /* Offset (8 bytes) */
+       Stream_Write_UINT32(s, 0);
+       Stream_Zero(s, 20); /* Padding (20 bytes) */
+       Stream_Write(s, data, length); /* WriteData (variable) */
+     Stream_SealLength(s);
+       status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
+     Stream_Free(s, TRUE);
+     return status;
+ }
+ static BOOL rdpdr_server_send_device_query_directory_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_DIRECTORY_CONTROL, IRP_MN_QUERY_DIRECTORY);
+       Stream_Write_UINT32(s, FileDirectoryInformation); /* FsInformationClass (4 bytes) */
+       Stream_Write_UINT8(s, path ? 1 : 0); /* InitialQuery (1 byte) */
+       Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */
+       Stream_Zero(s, 23); /* Padding (23 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 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;
+       for (i = 0; (i < size) && (path[i] != '\0'); i++)
+       {
+               if (path[i] == '/')
+                       path[i] = '\\';
+       }
+ }
+ /*************************************************
+  * Drive Create Directory
+  ************************************************/
+ static void rdpdr_server_drive_create_directory_callback2(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);
+       /* Invoke the create directory completion routine. */
+       context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static void rdpdr_server_drive_create_directory_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 create directory completion routine. */
+               context->OnDriveCreateDirectoryComplete(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) */
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_create_directory_callback2;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to close the file */
+       rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
+ }
+ static BOOL rdpdr_server_drive_create_directory(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* path)
+ {
+       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_create_directory_callback1;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, path, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       printf("PathName=%s\n", irp->PathName); 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_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_CREATE);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Delete Directory
+  ************************************************/
+ static void rdpdr_server_drive_delete_directory_callback2(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);
+       /* Invoke the delete directory completion routine. */
+       context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static void rdpdr_server_drive_delete_directory_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 delete directory completion routine. */
+               context->OnDriveDeleteFileComplete(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) */
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_delete_directory_callback2;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to close the file */
+       rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
+ }
+ static BOOL rdpdr_server_drive_delete_directory(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* path)
+ {
+       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_delete_directory_callback1;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, path, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       printf("PathName=%s\n", irp->PathName); 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,
+               DELETE | SYNCHRONIZE,
+               FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_OPEN);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Query Directory
+  ************************************************/
+ static void rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
+ {
+       FILE_DIRECTORY_INFORMATION fdi;
+       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) */
+       if (length > 0)
+       {
+               rdpdr_server_read_file_directory_information(s, &fdi);
+       }
+       else
+       {
+               Stream_Seek(s, 1); /* Padding (1 byte) */
+       }
+       if (ioStatus == STATUS_SUCCESS)
+       {
+               /* Invoke the query directory completion routine. */
+               context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, length > 0 ? &fdi : NULL);
+               /* Setup the IRP. */
+               irp->CompletionId = context->priv->NextCompletionId++;
+               irp->Callback = rdpdr_server_drive_query_directory_callback2;
+               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);
+               /* 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)
+ {
+       UINT32 fileId;
+       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);
+               return;
+       }
+       Stream_Read_UINT32(s, fileId);
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_query_directory_callback2;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       strcat(irp->PathName, "\\*.*");
+       rdpdr_server_enqueue_irp(context, irp);
+       /* 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)
+ {
+       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_query_directory_callback1;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, path, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       printf("PathName=%s\n", irp->PathName); fflush(stdout);
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to open the directory. */
+       rdpdr_server_send_device_create_request(
+               context, deviceId, irp->CompletionId, irp->PathName,
+               FILE_READ_DATA | SYNCHRONIZE,
+               FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_OPEN);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Open File
+  ************************************************/
+ static void rdpdr_server_drive_open_file_callback(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);
+       Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */
+       Stream_Read_UINT8(s, information); /* Information (1 byte) */
+       /* Invoke the open file completion routine. */
+       context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static BOOL rdpdr_server_drive_open_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* path, UINT32 desiredAccess, UINT32 createDisposition)
+ {
+       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_open_file_callback;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, path, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       printf("PathName=%s\n", irp->PathName); 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,
+               desiredAccess | SYNCHRONIZE,
+               FILE_SYNCHRONOUS_IO_NONALERT,
+               createDisposition);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Read File
+  ************************************************/
+ static void rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus)
+ {
+       UINT32 length;
+       char* buffer = NULL;
+       WLog_DBG(TAG, "%s: deviceId=%d, completionId=%d, ioStatus=0x%x", __FUNCTION__, deviceId, completionId, ioStatus);
+       Stream_Read_UINT32(s, length); /* Length (4 bytes) */
+       if (length > 0)
+       {
+               buffer = (char*) Stream_Pointer(s);
+               Stream_Seek(s, length);
+       }
+       /* Invoke the read file completion routine. */
+       context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static BOOL rdpdr_server_drive_read_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, UINT32 fileId, UINT32 length, UINT32 offset)
+ {
+       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_read_file_callback;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to open the directory. */
+       rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId,     length, offset);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Write File
+  ************************************************/
+ static void rdpdr_server_drive_write_file_callback(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 write file completion routine. */
+       context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static BOOL rdpdr_server_drive_write_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, UINT32 fileId, const char* buffer, UINT32 length, UINT32 offset)
+ {
+       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_write_file_callback;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to open the directory. */
+       rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId, buffer, length, offset);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Close File
+  ************************************************/
+ static void rdpdr_server_drive_close_file_callback(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);
+       /* Invoke the close file completion routine. */
+       context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static BOOL rdpdr_server_drive_close_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, UINT32 fileId)
+ {
+       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_close_file_callback;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to open the directory. */
+       rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
+       return TRUE;
+ }
+ /*************************************************
+  * Drive Delete File
+  ************************************************/
+ static void rdpdr_server_drive_delete_file_callback2(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);
+       /* Invoke the delete file completion routine. */
+       context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
+       /* Destroy the IRP. */
+       rdpdr_server_irp_free(irp);
+ }
+ static void rdpdr_server_drive_delete_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 close file completion routine. */
+               context->OnDriveDeleteFileComplete(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) */
+       /* Setup the IRP. */
+       irp->CompletionId = context->priv->NextCompletionId++;
+       irp->Callback = rdpdr_server_drive_delete_file_callback2;
+       irp->DeviceId = deviceId;
+       irp->FileId = fileId;
+       rdpdr_server_enqueue_irp(context, irp);
+       /* Send a request to close the file */
+       rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
+ }
+ static BOOL rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* callbackData, UINT32 deviceId, const char* path)
+ {
+       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_delete_file_callback1;
+       irp->CallbackData = callbackData;
+       irp->DeviceId = deviceId;
+       strncpy(irp->PathName, path, sizeof(irp->PathName));
+       rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
+       printf("PathName=%s\n", irp->PathName); 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_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT,
+               FILE_OPEN);
+       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)
+ {
+       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;
+ }
+ RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
+ {
+       RdpdrServerContext* context;
+       context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext));
+       if (context)
+       {
+               ZeroMemory(context, sizeof(RdpdrServerContext));
+               context->vcm = vcm;
+               context->Start = rdpdr_server_start;
+               context->Stop = rdpdr_server_stop;
+               context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
+               context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
+               context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
+               context->DriveOpenFile = rdpdr_server_drive_open_file;
+               context->DriveReadFile = rdpdr_server_drive_read_file;
+               context->DriveWriteFile = rdpdr_server_drive_write_file;
+               context->DriveCloseFile = rdpdr_server_drive_close_file;
+               context->DriveDeleteFile = rdpdr_server_drive_delete_file;
+               context->DriveRenameFile = rdpdr_server_drive_rename_file;
+               context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate));
+               if (context->priv)
+               {
+                       ZeroMemory(context->priv, sizeof(RdpdrServerPrivate));
+                       context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
+                       context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
+                       context->priv->ClientId = g_ClientId++;
+                       context->priv->UserLoggedOnPdu = TRUE;
+                       context->priv->IrpList = ListDictionary_New(TRUE);
+                       context->priv->NextCompletionId = 1;
+               }
+       }
+       return context;
+ }
+ void rdpdr_server_context_free(RdpdrServerContext* context)
+ {
+       if (context)
+       {
+               if (context->priv)
+               {
+                       ListDictionary_Free(context->priv->IrpList);
+                       free(context->priv);
+               }
+               free(context);
+       }
+ }
++
Simple merge
Simple merge