~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to libfreerdp/core/freerdp.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * FreeRDP: A Remote Desktop Protocol Implementation
 
3
 * FreeRDP Core
 
4
 *
 
5
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License");
 
8
 * you may not use this file except in compliance with the License.
 
9
 * You may obtain a copy of the License at
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS,
 
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
16
 * See the License for the specific language governing permissions and
 
17
 * limitations under the License.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include "rdp.h"
 
25
#include "input.h"
 
26
#include "update.h"
 
27
#include "surface.h"
 
28
#include "transport.h"
 
29
#include "connection.h"
 
30
#include "extension.h"
 
31
#include "message.h"
 
32
 
 
33
#include <winpr/crt.h>
 
34
#include <winpr/stream.h>
 
35
 
 
36
#include <freerdp/freerdp.h>
 
37
#include <freerdp/error.h>
 
38
#include <freerdp/event.h>
 
39
#include <freerdp/locale/keyboard.h>
 
40
#include <freerdp/version.h>
 
41
 
 
42
/* connectErrorCode is 'extern' in error.h. See comment there.*/
 
43
 
 
44
/** Creates a new connection based on the settings found in the "instance" parameter
 
45
 *  It will use the callbacks registered on the structure to process the pre/post connect operations
 
46
 *  that the caller requires.
 
47
 *  @see struct rdp_freerdp in freerdp.h
 
48
 *
 
49
 *  @param instance - pointer to a rdp_freerdp structure that contains base information to establish the connection.
 
50
 *                                On return, this function will be initialized with the new connection's settings.
 
51
 *
 
52
 *  @return TRUE if successful. FALSE otherwise.
 
53
 *
 
54
 */
 
55
BOOL freerdp_connect(freerdp* instance)
 
56
{
 
57
        rdpRdp* rdp;
 
58
        rdpSettings* settings;
 
59
        BOOL status = FALSE;
 
60
        ConnectionResultEventArgs e;
 
61
 
 
62
        /* We always set the return code to 0 before we start the connect sequence*/
 
63
        connectErrorCode = 0;
 
64
 
 
65
        rdp = instance->context->rdp;
 
66
        settings = instance->settings;
 
67
 
 
68
        IFCALLRET(instance->PreConnect, status, instance);
 
69
 
 
70
        if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002)
 
71
        {
 
72
                settings->KeyboardType = 7;
 
73
                settings->KeyboardSubType = 2;
 
74
                settings->KeyboardFunctionKey = 12;
 
75
        }
 
76
 
 
77
        extension_load_and_init_plugins(rdp->extension);
 
78
        extension_pre_connect(rdp->extension);
 
79
 
 
80
        if (!status)
 
81
        {
 
82
                if (!connectErrorCode)
 
83
                {
 
84
                        connectErrorCode = PREECONNECTERROR;
 
85
                }
 
86
                fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__);
 
87
                return FALSE;
 
88
        }
 
89
 
 
90
        status = rdp_client_connect(rdp);
 
91
 
 
92
        /* --authonly tests the connection without a UI */
 
93
        if (instance->settings->AuthenticationOnly)
 
94
        {
 
95
                fprintf(stderr, "%s:%d: Authentication only, exit status %d\n", __FILE__, __LINE__, !status);
 
96
                return status;
 
97
        }
 
98
 
 
99
        if (status)
 
100
        {
 
101
                if (instance->settings->DumpRemoteFx)
 
102
                {
 
103
                        instance->update->pcap_rfx = pcap_open(instance->settings->DumpRemoteFxFile, TRUE);
 
104
                        if (instance->update->pcap_rfx)
 
105
                                instance->update->dump_rfx = TRUE;
 
106
                }
 
107
 
 
108
                extension_post_connect(rdp->extension);
 
109
 
 
110
                IFCALLRET(instance->PostConnect, status, instance);
 
111
                update_post_connect(instance->update);
 
112
 
 
113
                if (!status)
 
114
                {
 
115
                        fprintf(stderr, "freerdp_post_connect failed\n");
 
116
 
 
117
                        if (!connectErrorCode)
 
118
                        {
 
119
                                connectErrorCode = POSTCONNECTERROR;
 
120
                        }
 
121
 
 
122
                        return FALSE;
 
123
                }
 
124
 
 
125
                if (instance->settings->PlayRemoteFx)
 
126
                {
 
127
                        wStream* s;
 
128
                        rdpUpdate* update;
 
129
                        pcap_record record;
 
130
 
 
131
                        update = instance->update;
 
132
 
 
133
                        update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
 
134
 
 
135
                        if (!update->pcap_rfx)
 
136
                                return FALSE;
 
137
                        else
 
138
                                update->play_rfx = TRUE;
 
139
 
 
140
                        while (pcap_has_next_record(update->pcap_rfx))
 
141
                        {
 
142
 
 
143
                                pcap_get_next_record_header(update->pcap_rfx, &record);
 
144
 
 
145
                                s = StreamPool_Take(rdp->transport->ReceivePool, record.length);
 
146
                                record.data = Stream_Buffer(s);
 
147
 
 
148
                                pcap_get_next_record_content(update->pcap_rfx, &record);
 
149
                                Stream_SetLength(s,record.length);
 
150
                                Stream_SetPosition(s, 0);
 
151
 
 
152
                                update->BeginPaint(update->context);
 
153
                                update_recv_surfcmds(update, Stream_Length(s) , s);
 
154
                                update->EndPaint(update->context);
 
155
                                Stream_Release(s);
 
156
                        }
 
157
 
 
158
                        return TRUE;
 
159
                }
 
160
        }
 
161
 
 
162
        if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
 
163
        {
 
164
                connectErrorCode = INSUFFICIENTPRIVILEGESERROR;
 
165
        }
 
166
 
 
167
        if (!connectErrorCode)
 
168
        {
 
169
                connectErrorCode = UNDEFINEDCONNECTERROR;
 
170
        }
 
171
 
 
172
        SetEvent(rdp->transport->connectedEvent);
 
173
 
 
174
        EventArgsInit(&e, "freerdp");
 
175
        e.result = status ? 0 : -1;
 
176
        PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e);
 
177
 
 
178
        return status;
 
179
}
 
180
 
 
181
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
 
182
{
 
183
        rdpRdp* rdp;
 
184
 
 
185
        rdp = instance->context->rdp;
 
186
        transport_get_fds(rdp->transport, rfds, rcount);
 
187
 
 
188
        return TRUE;
 
189
}
 
190
 
 
191
BOOL freerdp_check_fds(freerdp* instance)
 
192
{
 
193
        int status;
 
194
        rdpRdp* rdp;
 
195
 
 
196
        rdp = instance->context->rdp;
 
197
 
 
198
        status = rdp_check_fds(rdp);
 
199
 
 
200
        if (status < 0)
 
201
        {
 
202
                TerminateEventArgs e;
 
203
                rdpContext* context = instance->context;
 
204
 
 
205
                EventArgsInit(&e, "freerdp");
 
206
                e.code = 0;
 
207
                PubSub_OnTerminate(context->pubSub, context, &e);
 
208
 
 
209
                return FALSE;
 
210
        }
 
211
 
 
212
        return TRUE;
 
213
}
 
214
 
 
215
wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id)
 
216
{
 
217
        wMessageQueue* queue = NULL;
 
218
 
 
219
        switch (id)
 
220
        {
 
221
                case FREERDP_UPDATE_MESSAGE_QUEUE:
 
222
                        queue = instance->update->queue;
 
223
                        break;
 
224
 
 
225
                case FREERDP_INPUT_MESSAGE_QUEUE:
 
226
                        queue = instance->input->queue;
 
227
                        break;
 
228
        }
 
229
 
 
230
        return queue;
 
231
}
 
232
 
 
233
HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id)
 
234
{
 
235
        HANDLE event = NULL;
 
236
        wMessageQueue* queue = NULL;
 
237
 
 
238
        queue = freerdp_get_message_queue(instance, id);
 
239
 
 
240
        if (queue)
 
241
                event = MessageQueue_Event(queue);
 
242
 
 
243
        return event;
 
244
}
 
245
 
 
246
int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message)
 
247
{
 
248
        int status = -1;
 
249
 
 
250
        switch (id)
 
251
        {
 
252
                case FREERDP_UPDATE_MESSAGE_QUEUE:
 
253
                        status = update_message_queue_process_message(instance->update, message);
 
254
                        break;
 
255
 
 
256
                case FREERDP_INPUT_MESSAGE_QUEUE:
 
257
                        status = input_message_queue_process_message(instance->input, message);
 
258
                        break;
 
259
        }
 
260
 
 
261
        return status;
 
262
}
 
263
 
 
264
int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id)
 
265
{
 
266
        int status = -1;
 
267
 
 
268
        switch (id)
 
269
        {
 
270
                case FREERDP_UPDATE_MESSAGE_QUEUE:
 
271
                        status = update_message_queue_process_pending_messages(instance->update);
 
272
                        break;
 
273
 
 
274
                case FREERDP_INPUT_MESSAGE_QUEUE:
 
275
                        status = input_message_queue_process_pending_messages(instance->input);
 
276
                        break;
 
277
        }
 
278
 
 
279
        return status;
 
280
}
 
281
 
 
282
static int freerdp_send_channel_data(freerdp* instance, int channel_id, BYTE* data, int size)
 
283
{
 
284
        return rdp_send_channel_data(instance->context->rdp, channel_id, data, size);
 
285
}
 
286
 
 
287
BOOL freerdp_disconnect(freerdp* instance)
 
288
{
 
289
        rdpRdp* rdp;
 
290
 
 
291
        rdp = instance->context->rdp;
 
292
        transport_disconnect(rdp->transport);
 
293
 
 
294
        return TRUE;
 
295
}
 
296
 
 
297
BOOL freerdp_shall_disconnect(freerdp* instance)
 
298
{
 
299
        return instance->context->rdp->disconnect;
 
300
}
 
301
 
 
302
FREERDP_API BOOL freerdp_focus_required(freerdp* instance)
 
303
{
 
304
        rdpRdp* rdp;
 
305
        BOOL bRetCode = FALSE;
 
306
 
 
307
        rdp = instance->context->rdp;
 
308
 
 
309
        if (rdp->resendFocus)
 
310
        {
 
311
                bRetCode = TRUE;
 
312
                rdp->resendFocus = FALSE;
 
313
        }
 
314
 
 
315
        return bRetCode;
 
316
}
 
317
 
 
318
void freerdp_get_version(int* major, int* minor, int* revision)
 
319
{
 
320
        if (major != NULL)
 
321
                *major = FREERDP_VERSION_MAJOR;
 
322
 
 
323
        if (minor != NULL)
 
324
                *minor = FREERDP_VERSION_MINOR;
 
325
 
 
326
        if (revision != NULL)
 
327
                *revision = FREERDP_VERSION_REVISION;
 
328
}
 
329
 
 
330
static wEventType FreeRDP_Events[] =
 
331
{
 
332
        DEFINE_EVENT_ENTRY(WindowStateChange)
 
333
        DEFINE_EVENT_ENTRY(ResizeWindow)
 
334
        DEFINE_EVENT_ENTRY(LocalResizeWindow)
 
335
        DEFINE_EVENT_ENTRY(EmbedWindow)
 
336
        DEFINE_EVENT_ENTRY(PanningChange)
 
337
        DEFINE_EVENT_ENTRY(ScalingFactorChange)
 
338
        DEFINE_EVENT_ENTRY(ErrorInfo)
 
339
        DEFINE_EVENT_ENTRY(ParamChange)
 
340
        DEFINE_EVENT_ENTRY(Terminate)
 
341
        DEFINE_EVENT_ENTRY(ConnectionResult)
 
342
        DEFINE_EVENT_ENTRY(ChannelConnected)
 
343
        DEFINE_EVENT_ENTRY(ChannelDisconnected)
 
344
};
 
345
 
 
346
/** Allocator function for a rdp context.
 
347
 *  The function will allocate a rdpRdp structure using rdp_new(), then copy
 
348
 *  its contents to the appropriate fields in the rdp_freerdp structure given in parameters.
 
349
 *  It will also initialize the 'context' field in the rdp_freerdp structure as needed.
 
350
 *  If the caller has set the ContextNew callback in the 'instance' parameter, it will be called at the end of the function.
 
351
 *
 
352
 *  @param instance - Pointer to the rdp_freerdp structure that will be initialized with the new context.
 
353
 */
 
354
int freerdp_context_new(freerdp* instance)
 
355
{
 
356
        rdpRdp* rdp;
 
357
        rdpContext* context;
 
358
 
 
359
        instance->context = (rdpContext*) malloc(instance->ContextSize);
 
360
        ZeroMemory(instance->context, instance->ContextSize);
 
361
        context = instance->context;
 
362
 
 
363
        context->pubSub = PubSub_New(TRUE);
 
364
        PubSub_AddEventTypes(context->pubSub, FreeRDP_Events, sizeof(FreeRDP_Events) / sizeof(wEventType));
 
365
 
 
366
        rdp = rdp_new(instance);
 
367
        instance->input = rdp->input;
 
368
        instance->update = rdp->update;
 
369
        instance->settings = rdp->settings;
 
370
 
 
371
        context->graphics = graphics_new(context);
 
372
        context->instance = instance;
 
373
        context->rdp = rdp;
 
374
 
 
375
        context->input = instance->input;
 
376
        context->update = instance->update;
 
377
        context->settings = instance->settings;
 
378
 
 
379
        instance->update->context = instance->context;
 
380
        instance->update->pointer->context = instance->context;
 
381
        instance->update->primary->context = instance->context;
 
382
        instance->update->secondary->context = instance->context;
 
383
        instance->update->altsec->context = instance->context;
 
384
 
 
385
        instance->input->context = context;
 
386
 
 
387
        update_register_client_callbacks(rdp->update);
 
388
 
 
389
        IFCALL(instance->ContextNew, instance, instance->context);
 
390
 
 
391
        return 0;
 
392
}
 
393
 
 
394
/** Deallocator function for a rdp context.
 
395
 *  The function will deallocate the resources from the 'instance' parameter that were allocated from a call
 
396
 *  to freerdp_context_new().
 
397
 *  If the ContextFree callback is set in the 'instance' parameter, it will be called before deallocation occurs.
 
398
 *
 
399
 *  @param instance - Pointer to the rdp_freerdp structure that was initialized by a call to freerdp_context_new().
 
400
 *                                On return, the fields associated to the context are invalid.
 
401
 */
 
402
void freerdp_context_free(freerdp* instance)
 
403
{
 
404
        if (!instance->context)
 
405
                return;
 
406
 
 
407
        IFCALL(instance->ContextFree, instance, instance->context);
 
408
 
 
409
        rdp_free(instance->context->rdp);
 
410
        instance->context->rdp = NULL;
 
411
 
 
412
        graphics_free(instance->context->graphics);
 
413
        instance->context->graphics = NULL;
 
414
 
 
415
        PubSub_Free(instance->context->pubSub);
 
416
 
 
417
        free(instance->context);
 
418
        instance->context = NULL;
 
419
}
 
420
 
 
421
UINT32 freerdp_error_info(freerdp* instance)
 
422
{
 
423
        return instance->context->rdp->errorInfo;
 
424
}
 
425
 
 
426
/** Allocator function for the rdp_freerdp structure.
 
427
 *  @return an allocated structure filled with 0s. Need to be deallocated using freerdp_free()
 
428
 */
 
429
freerdp* freerdp_new()
 
430
{
 
431
        freerdp* instance;
 
432
 
 
433
        instance = (freerdp*) malloc(sizeof(freerdp));
 
434
 
 
435
        if (instance)
 
436
        {
 
437
                ZeroMemory(instance, sizeof(freerdp));
 
438
                instance->ContextSize = sizeof(rdpContext);
 
439
                instance->SendChannelData = freerdp_send_channel_data;
 
440
        }
 
441
 
 
442
        return instance;
 
443
}
 
444
 
 
445
/** Deallocator function for the rdp_freerdp structure.
 
446
 *  @param instance - pointer to the rdp_freerdp structure to deallocate.
 
447
 *                    On return, this pointer is not valid anymore.
 
448
 */
 
449
void freerdp_free(freerdp* instance)
 
450
{
 
451
        if (instance)
 
452
        {
 
453
                free(instance);
 
454
        }
 
455
}