~ubuntu-branches/ubuntu/raring/freerdp/raring-proposed

« back to all changes in this revision

Viewing changes to channels/rdpdr/irp.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2010-06-23 21:39:09 UTC
  • Revision ID: james.westby@ubuntu.com-20100623213909-bb9pvvv03913tdv6
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c-basic-offset: 8 -*-
 
2
   FreeRDP: A Remote Desktop Protocol client.
 
3
   Device Redirection - Interrupt Request Packet (IRP) Processing
 
4
 
 
5
   Copyright (C) Marc-Andre Moreau <marcandre.moreau@gmail.com> 2009
 
6
 
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2 of the License, or
 
10
   (at your option) any later version.
 
11
 
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software
 
19
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
*/
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
 
 
26
#include "rdpdr_types.h"
 
27
#include "rdpdr_constants.h"
 
28
#include "irp.h"
 
29
 
 
30
char *
 
31
irp_output_device_io_completion(IRP* irp, int * data_size)
 
32
{
 
33
        char * data;
 
34
 
 
35
        *data_size = 20 + irp->outputBufferLength;
 
36
        data = malloc(*data_size);
 
37
        memset(data, 0, *data_size);
 
38
 
 
39
        SET_UINT16(data, 0, RDPDR_CTYP_CORE); /* component */
 
40
        SET_UINT16(data, 2, PAKID_CORE_DEVICE_IOCOMPLETION); /* packetID */
 
41
        SET_UINT32(data, 4, irp->dev->id); /* deviceID */
 
42
        SET_UINT32(data, 8, irp->completionID); /* completionID */
 
43
        SET_UINT32(data, 12, irp->ioStatus); /* ioStatus */
 
44
        SET_UINT32(data, 16, irp->outputResult);
 
45
        if (irp->outputBufferLength > 0)
 
46
        {
 
47
                memcpy(data + 20, irp->outputBuffer, irp->outputBufferLength);
 
48
        }
 
49
        return data;
 
50
}
 
51
 
 
52
void
 
53
irp_process_create_request(IRP* irp, char* data, int data_size)
 
54
{
 
55
        uint32 pathLength;
 
56
        char * path;
 
57
        int size;
 
58
 
 
59
        irp->desiredAccess = GET_UINT32(data, 0); /* desiredAccess */
 
60
        //irp->allocationSize = GET_UINT64(data, 4); /* allocationSize */
 
61
        irp->fileAttributes = GET_UINT32(data, 12); /* fileAttributes */
 
62
        irp->sharedAccess = GET_UINT32(data, 16); /* sharedAccess */
 
63
        irp->createDisposition = GET_UINT32(data, 20); /* createDisposition */
 
64
        irp->createOptions = GET_UINT32(data, 24); /* createOptions */
 
65
        pathLength = GET_UINT32(data, 28); /* pathLength */
 
66
 
 
67
        size = pathLength * 3 / 2 + 1;
 
68
        path = (char *) malloc(size);
 
69
        memset(path, 0, size);
 
70
        if (pathLength > 0)
 
71
        {
 
72
                get_wstr(path, size, &data[32], pathLength);
 
73
        }
 
74
 
 
75
        if (!irp->dev->service->create)
 
76
        {
 
77
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
78
        }
 
79
        else
 
80
        {
 
81
                irp->ioStatus = irp->dev->service->create(irp, path);
 
82
        }
 
83
        free(path);
 
84
 
 
85
        /* construct create response */
 
86
        irp->outputResult = irp->fileID;
 
87
        irp->outputBufferLength = 1;
 
88
        irp->outputBuffer = malloc(1);
 
89
 
 
90
        switch (irp->createDisposition)
 
91
        {
 
92
        case FILE_SUPERSEDE:
 
93
        case FILE_OPEN:
 
94
        case FILE_CREATE:
 
95
        case FILE_OVERWRITE:
 
96
                irp->outputBuffer[0] = FILE_SUPERSEDED;
 
97
                break;
 
98
        case FILE_OPEN_IF:
 
99
                irp->outputBuffer[0] = FILE_OPENED;
 
100
                break;
 
101
        case FILE_OVERWRITE_IF:
 
102
                irp->outputBuffer[0] = FILE_OVERWRITTEN;
 
103
                break;
 
104
        default:
 
105
                irp->outputBuffer[0] = 0;
 
106
                break;
 
107
        }
 
108
}
 
109
 
 
110
void
 
111
irp_process_close_request(IRP* irp, char* data, int data_size)
 
112
{
 
113
        /* 32-byte pad */
 
114
        if (!irp->dev->service->close)
 
115
        {
 
116
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
117
        }
 
118
        else
 
119
        {
 
120
                irp->ioStatus = irp->dev->service->close(irp);
 
121
        }
 
122
 
 
123
        /* construct close response */
 
124
        irp->outputBufferLength = 1;
 
125
        irp->outputBuffer = malloc(1);
 
126
        irp->outputBuffer[0] = 0;
 
127
}
 
128
 
 
129
void
 
130
irp_process_read_request(IRP* irp, char* data, int data_size)
 
131
{
 
132
        irp->length = GET_UINT32(data, 0); /* length */
 
133
        irp->offset = GET_UINT64(data, 4); /* offset */
 
134
        /* 20-byte pad */
 
135
 
 
136
        if (!irp->dev->service->read)
 
137
        {
 
138
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
139
        }
 
140
        else
 
141
        {
 
142
                irp->ioStatus = irp->dev->service->read(irp);
 
143
                irp->outputResult = irp->outputBufferLength;
 
144
        }
 
145
}
 
146
 
 
147
void
 
148
irp_process_write_request(IRP* irp, char* data, int data_size)
 
149
{
 
150
        irp->length = GET_UINT32(data, 0); /* length */
 
151
        irp->offset = GET_UINT64(data, 4); /* offset */
 
152
        /* 20-byte pad */
 
153
        irp->inputBuffer = data + 32;
 
154
        irp->inputBufferLength = irp->length;
 
155
 
 
156
        if (!irp->dev->service->write)
 
157
        {
 
158
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
159
        }
 
160
        else
 
161
        {
 
162
                irp->ioStatus = irp->dev->service->write(irp);
 
163
        }
 
164
        if (irp->ioStatus == RD_STATUS_SUCCESS)
 
165
        {
 
166
                irp->outputResult = irp->length;
 
167
                /* [MS-RDPEFS] says this is an optional padding, but unfortunately it's required! */
 
168
                irp->outputBufferLength = 1;
 
169
                irp->outputBuffer = malloc(1);
 
170
                irp->outputBuffer[0] = '\0';
 
171
        }
 
172
}
 
173
 
 
174
void
 
175
irp_process_query_volume_information_request(IRP* irp, char* data, int data_size)
 
176
{
 
177
        irp->infoClass = GET_UINT32(data, 0); /* fsInformationClass */
 
178
        irp->inputBufferLength = GET_UINT32(data, 4); /* length */
 
179
        /* 24-byte pad */
 
180
        
 
181
        /* queryVolumeBuffer */
 
182
        irp->inputBuffer = data + 32;
 
183
 
 
184
        if (!irp->dev->service->query_volume_info)
 
185
        {
 
186
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
187
        }
 
188
        else
 
189
        {
 
190
                irp->ioStatus = irp->dev->service->query_volume_info(irp);
 
191
                irp->outputResult = irp->outputBufferLength;
 
192
        }
 
193
}
 
194
 
 
195
void
 
196
irp_process_set_volume_information_request(IRP* irp, char* data, int data_size)
 
197
{
 
198
#if 0
 
199
        uint32 fsInformationClass;
 
200
        uint32 length;
 
201
 
 
202
        fsInformationClass = GET_UINT32(data, 0); /* fsInformationClass */
 
203
        length = GET_UINT32(data, 4); /* length */
 
204
        /* 24-byte pad */
 
205
        
 
206
        /* setVolumeBuffer */
 
207
#endif
 
208
}
 
209
 
 
210
void
 
211
irp_process_query_information_request(IRP* irp, char* data, int data_size)
 
212
{
 
213
        irp->infoClass = GET_UINT32(data, 0); /* fsInformationClass */
 
214
        irp->inputBufferLength = GET_UINT32(data, 4); /* length */
 
215
        /* 24-byte pad */
 
216
 
 
217
        /* QueryBuffer */
 
218
        irp->inputBuffer = data + 32;
 
219
 
 
220
        if (!irp->dev->service->query_info)
 
221
        {
 
222
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
223
        }
 
224
        else
 
225
        {
 
226
                irp->ioStatus = irp->dev->service->query_info(irp);
 
227
                irp->outputResult = irp->outputBufferLength;
 
228
        }
 
229
}
 
230
 
 
231
void
 
232
irp_process_set_information_request(IRP* irp, char* data, int data_size)
 
233
{
 
234
        irp->infoClass = GET_UINT32(data, 0); /* fsInformationClass */
 
235
        irp->inputBufferLength = GET_UINT32(data, 4); /* length */
 
236
        /* 24-byte pad */
 
237
        
 
238
        /* setBuffer */
 
239
        irp->inputBuffer = data + 32;
 
240
 
 
241
        if (!irp->dev->service->set_info)
 
242
        {
 
243
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
244
        }
 
245
        else
 
246
        {
 
247
                irp->ioStatus = irp->dev->service->set_info(irp);
 
248
                irp->outputResult = irp->inputBufferLength;
 
249
        }
 
250
}
 
251
 
 
252
void
 
253
irp_process_directory_control_request(IRP* irp, char* data, int data_size)
 
254
{
 
255
        switch(irp->minorFunction)
 
256
        {
 
257
                case IRP_MN_QUERY_DIRECTORY:
 
258
                        LLOGLN(10, ("IRP_MN_QUERY_DIRECTORY"));
 
259
                        irp_process_query_directory_request(irp, data, data_size);
 
260
                        break;
 
261
                
 
262
                case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
 
263
                        LLOGLN(10, ("IRP_MN_NOTIFY_CHANGE_DIRECTORY"));
 
264
                        irp_process_notify_change_directory_request(irp, data, data_size);
 
265
                        break;
 
266
 
 
267
                default:
 
268
                        LLOGLN(0, ("IRP majorFunction=0x%x minorFunction=0x%x", irp->majorFunction, irp->minorFunction));
 
269
                        irp->ioStatus = RD_STATUS_INVALID_PARAMETER;
 
270
                        return;
 
271
        }
 
272
}
 
273
 
 
274
void
 
275
irp_process_device_control_request(IRP* irp, char* data, int data_size)
 
276
{
 
277
        //irp->outputBufferLength = GET_UINT32(data, 0); /* outputBufferLength */
 
278
        irp->inputBufferLength = GET_UINT32(data, 4); /* inputBufferLength */
 
279
        irp->ioControlCode = GET_UINT32(data, 8); /* ioControlCode */
 
280
        /* 20-byte pad */
 
281
 
 
282
        /* inputBuffer */
 
283
        irp->inputBuffer = data + 32;
 
284
 
 
285
        if (!irp->dev->service->control)
 
286
        {
 
287
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
288
        }
 
289
        else
 
290
        {
 
291
                irp->ioStatus = irp->dev->service->control(irp);
 
292
                irp->outputResult = irp->outputBufferLength;
 
293
        }
 
294
}
 
295
 
 
296
void
 
297
irp_process_file_lock_control_request(IRP* irp, char* data, int data_size)
 
298
{
 
299
        uint32 numLocks;
 
300
 
 
301
        irp->operation = GET_UINT32(data, 0); /* operation */
 
302
        irp->waitOperation = GET_UINT8(data, 4); /* f (first bit) */
 
303
        /* pad (f + pad = 32 bits) */
 
304
        numLocks = GET_UINT32(data, 8); /* numLocks */
 
305
        irp->inputBufferLength = numLocks * 16; /* sizeof(RDP_LOCK_INFO) */
 
306
        /* 20-byte pad */
 
307
        irp->inputBuffer = data + 32;
 
308
 
 
309
        if (!irp->dev->service->lock_control)
 
310
        {
 
311
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
312
        }
 
313
        else
 
314
        {
 
315
                irp->ioStatus = irp->dev->service->lock_control(irp);
 
316
                irp->outputResult = irp->outputBufferLength;
 
317
        }
 
318
}
 
319
 
 
320
void
 
321
irp_process_query_directory_request(IRP* irp, char* data, int data_size)
 
322
{
 
323
        uint8 initialQuery;
 
324
        uint32 pathLength;
 
325
        int size;
 
326
        char * path;
 
327
 
 
328
        irp->infoClass = GET_UINT32(data, 0); /* fsInformationClass */
 
329
        initialQuery = GET_UINT8(data, 4); /* initialQuery */
 
330
        pathLength = GET_UINT32(data, 5); /* pathLength */
 
331
        /* 23-byte pad */
 
332
 
 
333
        size = pathLength * 3 / 2 + 1;
 
334
        path = (char *) malloc(size);
 
335
        memset(path, 0, size);
 
336
        if (pathLength > 0)
 
337
        {
 
338
                get_wstr(path, size, &data[32], pathLength);
 
339
        }
 
340
 
 
341
        if (!irp->dev->service->query_directory)
 
342
        {
 
343
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
344
        }
 
345
        else
 
346
        {
 
347
                irp->ioStatus = irp->dev->service->query_directory(irp, initialQuery, path);
 
348
        }
 
349
        free(path);
 
350
 
 
351
        if (irp->ioStatus == RD_STATUS_NO_MORE_FILES)
 
352
        {
 
353
                /* [MS-RDPEFS] said it's an optional padding, however it's *required* for this last query!!! */
 
354
                irp->outputBufferLength = 1;
 
355
                irp->outputBuffer = malloc(1);
 
356
                irp->outputBuffer[0] = '\0';
 
357
        }
 
358
        else
 
359
        {
 
360
                irp->outputResult = irp->outputBufferLength;
 
361
        }
 
362
}
 
363
 
 
364
void
 
365
irp_process_notify_change_directory_request(IRP* irp, char* data, int data_size)
 
366
{
 
367
        irp->watchTree = GET_UINT8(data, 0); /* watchQuery */
 
368
        irp->completionFilter = GET_UINT32(data, 1); /* completionQuery */
 
369
        /* 27-byte pad */
 
370
 
 
371
        if (!irp->dev->service->notify_change_directory)
 
372
        {
 
373
                irp->ioStatus = RD_STATUS_NOT_SUPPORTED;
 
374
        }
 
375
        else
 
376
        {
 
377
                irp->ioStatus = irp->dev->service->notify_change_directory(irp);
 
378
        }
 
379
}
 
380