File: pyrapi2.pyx

package info (click to toggle)
librapi2 0.15-2.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,864 kB
  • sloc: ansic: 14,036; sh: 10,572; cpp: 851; python: 338; makefile: 229
file content (1449 lines) | stat: -rw-r--r-- 46,745 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
"""Python bindings to librapi2

RAPI is the protocol used to communicate with Windows CE and
Windows Mobile devices, and librapi2 is the open source
implementation from the SynCE project.

For more information, go to www.synce.org"""

include "types.pxi"
include "constants.pxi"
import sys

cdef extern from "Python.h":
    object PyString_FromStringAndSize ( char *, int )
    object PyCObject_FromVoidPtr(void* cobj, void (*destr)(void *))
    
cdef extern from "stdlib.h":
    void *malloc(size_t size) nogil
    void *realloc(void *ptr, size_t size) nogil
    void free(void *ptr) nogil

cdef extern from "string.h":
    void *memcpy(void *s1, void *s2, size_t n) nogil

cdef extern from "synce.h":
    char *wstr_to_utf8(LPCWSTR unicode) nogil
    LPWSTR wstr_from_utf8(char *utf8) nogil
    void wstr_free_string(void *str) nogil
    char* synce_strerror(DWORD error) nogil

cdef extern from "synce_log.h":
    void synce_log_set_level(int level) nogil

cdef extern from "rapi.h":
    ctypedef void RapiConnection

    # connection functions
    RapiConnection *rapi_connection_from_name(char *device_name) nogil
    void rapi_connection_select(RapiConnection *connection) nogil
    void rapi_connection_destroy(RapiConnection *connection) nogil
    HRESULT CeRapiInit() nogil
    STDAPI CeRapiUninit() nogil

    # registry functions
    LONG CeRegCreateKeyEx(HKEY hKey, LPCWSTR lpszSubKey, DWORD Reserved, LPWSTR lpszClass, DWORD ulOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) nogil
    LONG CeRegOpenKeyEx(HKEY hKey, LPCWSTR lpszSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) nogil
    LONG CeRegCloseKey(HKEY hKey) nogil
    LONG CeRegDeleteKey(HKEY hKey, LPCWSTR lpszSubKey) nogil
    LONG CeRegDeleteValue(HKEY hKey, LPCWSTR lpszValueName) nogil
    LONG CeRegQueryValueEx(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) nogil
    LONG CeRegSetValueEx(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, BYTE *lpData, DWORD cbData) nogil
    LONG CeRegQueryInfoKey ( HKEY hKey, LPWSTR lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime ) nogil

    LONG CeRegEnumKeyEx( HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime) nogil
    LONG CeRegEnumValue( HKEY hKey, DWORD dwIndex, LPWSTR lpszValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) nogil



    # sync functions
    BOOL CeStartReplication() nogil
    HRESULT CeSyncStart(LPCWSTR params) nogil
    HRESULT CeSyncResume() nogil
    HRESULT CeSyncPause() nogil
    HRESULT CeSyncTimeToPc() nogil

    # miscellaneous functions
    HRESULT CeProcessConfig(LPCWSTR config, DWORD flags, LPWSTR* reply) nogil
    BOOL CeGetSystemPowerStatusEx(PSYSTEM_POWER_STATUS_EX pSystemPowerStatus, BOOL refresh) nogil
    DWORD CeGetDiskFreeSpaceEx( LPCTSTR _lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailable, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes) nogil
    BOOL CeFindAllFiles( LPCWSTR szPath, DWORD dwFlags, LPDWORD lpdwFoundCount, LPLPCE_FIND_DATA ppFindDataArray) nogil
    BOOL CeCreateProcess( LPCWSTR lpApplicationName, LPCWSTR lpCommandLine, void* lpProcessAttributes, void* lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPWSTR lpCurrentDirectory, void* lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) nogil
    
    VOID CeGetSystemInfo( LPSYSTEM_INFO lpSystemInfo) nogil
    BOOL CeGetVersionEx( LPCEOSVERSIONINFO lpVersionInformation) nogil

    # file access
    BOOL CeCloseHandle(HANDLE hObject) nogil
    HANDLE CeCreateFile( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) nogil
    BOOL CeWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) nogil
    BOOL CeReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) nogil
    DWORD CeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) nogil

    # error handling
    HRESULT CeRapiGetError() nogil
    DWORD CeGetLastError() nogil

    # connection parameters
    char *rapi_connection_get_name(RapiConnection* connection) nogil
    int rapi_connection_get_os_version(RapiConnection* connection, int *os_major, int *os_minor) nogil
    int rapi_connection_get_build_number(RapiConnection* connection) nogil
    int rapi_connection_get_processor_type(RapiConnection* connection) nogil
    char *rapi_connection_get_os_name(RapiConnection* connection) nogil
    char *rapi_connection_get_model(RapiConnection* connection) nogil
    char *rapi_connection_get_device_ip(RapiConnection* connection) nogil
    char *rapi_connection_get_local_ip(RapiConnection* connection) nogil
    int rapi_connection_get_fd(RapiConnection* connection) nogil

#
# Public constants
#

# from synce_log.h
SYNCE_LOG_LEVEL_LOWEST  = 0

SYNCE_LOG_LEVEL_ERROR   = 1
SYNCE_LOG_LEVEL_WARNING = 2
SYNCE_LOG_LEVEL_INFO    = 3
SYNCE_LOG_LEVEL_DEBUG   = 4
SYNCE_LOG_LEVEL_TRACE   = SYNCE_LOG_LEVEL_DEBUG

SYNCE_LOG_LEVEL_HIGHEST = 5
SYNCE_LOG_LEVEL_DEFAULT = 2

# from synce_sys_error.h
ERROR_SUCCESS           = 0

# from synce_types.h
FALSE                   = 0
TRUE                    = 1

# some HRESULTs
E_ABORT                 = 0x80004004
E_ACCESSDENIED          = 0x80070005
E_FAIL                  = 0x80004005
E_HANDLE                = 0x80070006
E_OUTOFMEMORY           = 0x8007000E
E_INVALIDARG            = 0x80070057
E_NOINTERFACE           = 0x80004002
E_NOTIMPL               = 0x80004001
E_OUTOFMEMORY           = 0x8007000E
E_PENDING               = 0x8000000A
E_POINTER               = 0x80004003
E_UNEXPECTED            = 0x8000FFFF
S_FALSE                 = 0x00000001
S_OK                    = 0x00000000


# from rapi.h
# registry value types
REG_NONE                = 0
REG_SZ                  = 1
REG_EXPAND_SZ           = 2
REG_BINARY              = 3
REG_DWORD               = 4
REG_DWORD_LITTLE_ENDIAN = 4
REG_DWORD_BIG_ENDIAN    = 5
REG_LINK                = 6
REG_MULTI_SZ            = 7

# registry key dispositions
REG_CREATED_NEW_KEY     = 1
REG_OPENED_EXISTING_KEY = 2

# battery status
BATTERY_FLAG_HIGH          =    0x01
BATTERY_FLAG_LOW           =    0x02
BATTERY_FLAG_CRITICAL      =    0x04
BATTERY_FLAG_CHARGING      =    0x08
BATTERY_FLAG_NO_BATTERY    =    0x80
BATTERY_FLAG_UNKNOWN       =    0xFF

# flags for finding file info
FAF_ATTRIBUTES               = 0x00001
FAF_CREATION_TIME            = 0x00002
FAF_LASTACCESS_TIME          = 0x00004
FAF_LASTWRITE_TIME           = 0x00008

FAF_SIZE_HIGH                = 0x00010
FAF_SIZE_LOW                 = 0x00020
FAF_OID                      = 0x00040
FAF_NAME                     = 0x00080

FAF_ATTRIB_CHILDREN          = 0x01000
FAF_ATTRIB_NO_HIDDEN         = 0x02000
FAF_FOLDERS_ONLY             = 0x04000
FAF_NO_HIDDEN_SYS_ROMMODULES = 0x08000

CSIDL_PROGRAMS               = 0x0002
CSIDL_PERSONAL               = 0x0005
CSIDL_FAVORITES_GRYPHON      = 0x0006
CSIDL_STARTUP                = 0x0007
CSIDL_RECENT                 = 0x0008
CSIDL_STARTMENU              = 0x000b
CSIDL_DESKTOPDIRECTORY       = 0x0010
CSIDL_FONTS                  = 0x0014
CSIDL_FAVORITES              = 0x0016

#dwShareMode 
FILE_SHARE_READ              = 0x00000001

# dwMoveMethod
FILE_BEGIN                   = 0
FILE_CURRENT                 = 1
FILE_END                     = 2

#dwFlagsAndAttributes 
FILE_ATTRIBUTE_READONLY      = 0x00000001
FILE_ATTRIBUTE_HIDDEN        = 0x00000002
FILE_ATTRIBUTE_SYSTEM        = 0x00000004
FILE_ATTRIBUTE_1             = 0x00000008

FILE_ATTRIBUTE_DIRECTORY     = 0x00000010
FILE_ATTRIBUTE_ARCHIVE       = 0x00000020
FILE_ATTRIBUTE_INROM         = 0x00000040
FILE_ATTRIBUTE_NORMAL        = 0x00000080

FILE_ATTRIBUTE_TEMPORARY     = 0x00000100
FILE_ATTRIBUTE_2             = 0x00000200
FILE_ATTRIBUTE_3             = 0x00000400
FILE_ATTRIBUTE_COMPRESSED    = 0x00000800

FILE_ATTRIBUTE_ROMSTATICREF  = 0x00001000
FILE_ATTRIBUTE_ROMMODULE     = 0x00002000
FILE_ATTRIBUTE_4             = 0x00004000
FILE_ATTRIBUTE_5             = 0x00008000

FILE_ATTRIBUTE_HAS_CHILDREN  = 0x00010000
FILE_ATTRIBUTE_SHORTCUT      = 0x00020000
FILE_ATTRIBUTE_6             = 0x00040000
FILE_ATTRIBUTE_7             = 0x00080000


#
# RAPIError is a subclass of Exception

class RAPIError(Exception):
    "An error resulting from a RAPI call"
    def __init__(self, err_code=None):
        cdef HRESULT hr
        cdef DWORD last_error

        if err_code != None:
            self.err_code = err_code
        else:
            hr = CeRapiGetError()
            if hr < 0:
                self.err_code = hr
            else:
                last_error = CeGetLastError()
                self.err_code = last_error

    def __str__(self):
        return str(self.err_code)+": "+str(synce_strerror(self.err_code))


class RegKey(object):
    """Registry key entry from a Windows Mobile Device"""
    def __init__(self, rapi_session, handle, disposition=REG_OPENED_EXISTING_KEY):
        self.rapi_session = rapi_session
        self.handle = handle
        self.disposition = disposition
        self._host_le = (sys.byteorder == "little")

    def __del__(self):
        self.close()

    def keys(self):
        """Returns an array containing all the subkeys"""
        result = [] 

        cdef DWORD index
        cdef LPWSTR name
        cdef DWORD name_len
       
        try:
            self.rapi_session.__session_select__()
            
            name = <LPWSTR> malloc(255) 

            finished = False 
            
            index = 0 

            while not finished:
                name_len = 254
                
                retval =  CeRegEnumKeyEx( self.handle, index, name, &name_len, NULL, NULL, NULL, NULL) 

                if retval == 259L:
                    finished = True

                
                if not finished:
                    if retval != ERROR_SUCCESS:
                            raise RAPIError(retval)
                    
                    result.append( wstr_to_utf8(name) )
                
                    index = index + 1
            
            return result 

        finally:
            if name != NULL:
                free(name) 

    def keys_and_childcount(self, query_child_count=False ):
        """Returns an array containing all the subkeys"""
        result = [] 

        cdef DWORD index
        cdef LPWSTR name
        cdef DWORD name_len
        cdef DWORD key_count 
       
        try:
            self.rapi_session.__session_select__()
            
            name = <LPWSTR> malloc(255) 

            finished = False 
            
            index = 0 
            
            #-1 means that no child count information is requested. 
            #0 cannot be used, because this would collide with nodes having 0 childs
            key_count = -1 

            while not finished:
                name_len = 254
                
                retval =  CeRegEnumKeyEx( self.handle, index, name, &name_len, NULL, NULL, NULL, NULL) 

                if retval == 259L:
                    finished = True

                
                if not finished:
                    if retval != ERROR_SUCCESS:
                            raise RAPIError(retval)
                    
                    if query_child_count:
                        sub_key = self.open_sub_key( wstr_to_utf8(name) )
                        (key_count ,_) = sub_key.number_of_keys_and_values()
                        sub_key.close()
                        
                    result.append( (wstr_to_utf8(name) , key_count ) )
                
                    index = index + 1
            
            return result 

        finally:
            if name != NULL:
                free(name) 

    


    def values(self):
        """Returns a list of tuples (value_name, value_type, value_data) of 
        values stored in the current key"""
       

        #First determine the maximum size for the buffer that we need
        cdef DWORD data_max_size
        
        
        self.rapi_session.__session_select__()
        retval = CeRegQueryInfoKey( self.handle, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_max_size , NULL, NULL) 
        
        result = [] 

        cdef DWORD index
        cdef LPWSTR name
        cdef DWORD name_len

        cdef DWORD type
        cdef DWORD data_size
        cdef LPBYTE data 
        cdef LPDWORD dw_ptr

        try:
            name = <LPWSTR> malloc(255) 
           
            data = <LPBYTE> malloc(data_max_size)

            
            finished = False 
            
            index = 0 

            while not finished:
                name_len = 254
                data_size = data_max_size

                retval =  CeRegEnumValue( self.handle, index, name, &name_len, NULL, &type, data, &data_size) 

                #If return value is 259L, then we are finished
                if retval == 259L:
                    finished = True

                
                if not finished:
                    if retval != ERROR_SUCCESS:
                            raise RAPIError(retval)
                    

                    if type == REG_NONE:
                        value = PyString_FromStringAndSize(<char *>data, data_size)
                    elif type == REG_SZ or type == REG_EXPAND_SZ:
                        value = wstr_to_utf8(<LPCWSTR> data)
                    elif type == REG_BINARY:
                        value = PyString_FromStringAndSize(<char *>data, data_size)
                    elif type == REG_DWORD:
                        dw_ptr = <LPDWORD> data
                        value = self._dword_le_to_host(dw_ptr[0])
                    elif type == REG_DWORD_BIG_ENDIAN:
                        dw_ptr = <LPDWORD> data
                        value = self._dword_be_to_host(dw_ptr[0])
                    elif type == REG_LINK:
                        value = PyString_FromStringAndSize(<char *>data, data_size)
                    elif type == REG_MULTI_SZ:
                        # FIXME - this is doable
                        value = PyString_FromStringAndSize(<char *>data, data_size)
                    else:
                        value = PyString_FromStringAndSize(<char *>data, data_size)

                    
                    
                    
                    
                    
                    
                    result.append( (wstr_to_utf8(name) , type,value)    )
                
                    index = index + 1
            
            return result 

        finally:
            if name != NULL:
                free(name) 
                free(data)      

    def rename_value(self, old_value_name, new_value_name):
        """Rename a value contained in this key"""
        self.copy_value(old_value_name, self, new_value_name) 
        self.delete_value( old_value_name )


    def copy_key_recursively(self, new_key ):
        """Copy the contents of the key denoted by the RegKey object
        old_key recursively to the key denoted by the new_key RegKey object"""

        self.copy_all_values( new_key )

        for (sub_key_name) in self.keys():
            old_sub_key = self.open_sub_key( sub_key_name )
            new_sub_key = new_key.create_sub_key(sub_key_name)

            old_sub_key.copy_key_recursively( new_sub_key )

            old_sub_key.close()
            new_sub_key.close()





    def rename_key(self, old_key_name, new_key_name):
        """Rename a sub key of the current key

        This is done by creating a new key and recursively copy the
        contents of the original key to this new key"""
       
        old_key = self.open_sub_key( old_key_name )

        new_key = self.create_sub_key( new_key_name )

        old_key.copy_key_recursively( new_key )

        old_key.close()
        new_key.close()

        self.delete_sub_key( old_key_name )
        







    def copy_value(self, value_name, destination_key, destination_value_name=None):
        """Copy the value value_name to the registry key denoted by the 
        RegKey object destination_key. 

        If the destination_value_name is not given, the same name is used"""
        
        cdef LPWSTR value_name_w
        cdef LPWSTR destination_value_name_w
        cdef LPBYTE data
        cdef DWORD data_size
        cdef DWORD data_type

        value_name_w = NULL
        destination_value_name_w = NULL
        data = NULL
        
        try: 
            self.rapi_session.__session_select__()

            if destination_value_name is None:
                destination_value_name = value_name


            value_name_w = wstr_from_utf8(value_name)
            
            data_size = 0  
            
            #First determine the size of the buffer we need to allocate
            retval = CeRegQueryValueEx(self.handle, value_name_w , NULL, NULL, NULL, &data_size) 

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)
            

            #Now create buffer for the data and query the data

            data = <LPBYTE> malloc(data_size)

            retval = CeRegQueryValueEx(self.handle, value_name_w , NULL,
                                       &data_type, data, &data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)


            destination_value_name_w = wstr_from_utf8(destination_value_name)

            
           
            #Create a value in the destination_key
            retval = CeRegSetValueEx(destination_key.handle , destination_value_name_w , 0 , data_type, data, data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            return

        finally:
            if value_name_w != NULL:
                wstr_free_string(value_name_w)
            if destination_value_name_w != NULL:
                wstr_free_string(destination_value_name_w)
            if data != NULL:
                free(data)
        pass

    def copy_all_values(self, destination_key):
        """Copy all values that are within the current key to the key denoted
        by the RegKey object destination_key"""
        for (value_name,_,_) in self.values():
            self.copy_value( value_name, destination_key )


    def number_of_keys_and_values(self):
        """Returns the number of child keys and number of values stored in 
        this key."""

        cdef DWORD number_of_keys
        cdef DWORD number_of_values

        self.rapi_session.__session_select__()
        retval = CeRegQueryInfoKey( self.handle, NULL, NULL, NULL, &number_of_keys, NULL, NULL, &number_of_values, NULL, NULL, NULL, NULL) 
        
        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)

        return (number_of_keys, number_of_values) 




    def open_sub_key(self, sub_key):
        """Open an existing sub key of this key.

        Takes as an argument the name of the subkey relative to this key. The path
        to a key more than one level down should be separated by backslashes. Returns
        a new RegKey object on success."""

        cdef LPWSTR sub_key_w
        cdef HKEY opened_key

        if sub_key != None:
            sub_key_w = wstr_from_utf8(sub_key)
        else:
            sub_key_w = NULL

        self.rapi_session.__session_select__()

        retval = CeRegOpenKeyEx(self.handle, sub_key_w, 0, 0, &opened_key)

        if sub_key_w != NULL:
            wstr_free_string(sub_key_w)

        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)

        return RegKey(self.rapi_session, opened_key)

    def create_sub_key(self, sub_key, key_class=""):
        """Creates a sub key of this key, or opens an existing key.

        Takes as an argument the name of the subkey to create relative to this key.
        The path to a key more than one level down should be separated by backslashes.
        The optional key_class argument can be used to specify the class of the new key.
        Returns a new RegKey object on success."""

        cdef HKEY new_key
        cdef DWORD disposition
        cdef LPWSTR sub_key_w
        cdef LPWSTR key_class_w

        if sub_key != None:
            sub_key_w = wstr_from_utf8(sub_key)
        else:
            sub_key_w = NULL

        key_class_w = wstr_from_utf8(key_class)

        self.rapi_session.__session_select__()

        retval = CeRegCreateKeyEx(self.handle, sub_key_w, 0, key_class_w,
                                  0, 0, NULL, &new_key, &disposition)

        if sub_key_w != NULL:
            wstr_free_string(sub_key_w)

        wstr_free_string(key_class_w)

        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)

        return RegKey(self.rapi_session, new_key, disposition)

    def _dword_swap(self, dw):
        return (dw & 0x000000FF) << 24 | \
               (dw & 0x0000FF00) << 8  | \
               (dw & 0x00FF0000) >> 8  | \
               (dw & 0xFF000000) >> 24

    def _dword_le_to_host(self, dw):
        if self._host_le:
            return dw
        else:
            return self._dword_swap(dw)

    def _dword_le_from_host(self, dw):
        if self._host_le:
            return dw
        else:
            return self._dword_swap(dw)

    def _dword_be_to_host(self, dw):
        if self._host_le:
            return self._dword_swap(dw)
        else:
            return dw

    def _dword_be_from_host(self, dw):
        if self._host_le:
            return self._dword_swap(dw)
        else:
            return dw




    def get_value(self, value_name):
        """Obtain a tuple (value_type, value) from a value contained in this
        key

        Takes as an argument the name of the value required, and returns
        a tuple of the type of the value and the value itself, converted
        to a python type
        """
        cdef LPWSTR name_w
        cdef DWORD type
        cdef LPBYTE data
        cdef DWORD data_size
        cdef LPDWORD dw_ptr

        name_w = NULL
        data = NULL

        try:
            if value_name != None:
                name_w = wstr_from_utf8(value_name)
            else:
                name_w = NULL

            self.rapi_session.__session_select__()

            data_size = 0
            retval = CeRegQueryValueEx(self.handle, name_w, NULL,
                                       &type, NULL, &data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            data = <LPBYTE> malloc(data_size)

            retval = CeRegQueryValueEx(self.handle, name_w, NULL,
                                       &type, data, &data_size)


            REG_MULTI_SZ
            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            if type == REG_NONE:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_SZ or type == REG_EXPAND_SZ:
                value = wstr_to_utf8(<LPCWSTR> data)
            elif type == REG_BINARY:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_DWORD:
                dw_ptr = <LPDWORD> data
                value = self._dword_le_to_host(dw_ptr[0])
            elif type == REG_DWORD_BIG_ENDIAN:
                dw_ptr = <LPDWORD> data
                value = self._dword_be_to_host(dw_ptr[0])
            elif type == REG_LINK:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_MULTI_SZ:
                # FIXME - this is doable
                value = PyString_FromStringAndSize(<char *>data, data_size)
            else:
                value = PyString_FromStringAndSize(<char *>data, data_size)

            

            return (type,value)
        finally:
            if name_w != NULL:
                wstr_free_string(name_w)

            if data != NULL:
                free(data)




    def query_value(self, value_name):
        """Obtain a value contained in this key

        Takes as an argument the name of the value required, and returns
        the value. Currently the registry types DWORD, DWORD_BIG_ENDIAN,
        SZ, EXPAND_SZ are fully supported."""

        cdef LPWSTR name_w
        cdef DWORD type
        cdef LPBYTE data
        cdef DWORD data_size
        cdef LPDWORD dw_ptr

        name_w = NULL
        data = NULL

        try:
            if value_name != None:
                name_w = wstr_from_utf8(value_name)
            else:
                name_w = NULL

            self.rapi_session.__session_select__()

            data_size = 0
            retval = CeRegQueryValueEx(self.handle, name_w, NULL,
                                       &type, NULL, &data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            data = <LPBYTE> malloc(data_size)

            retval = CeRegQueryValueEx(self.handle, name_w, NULL,
                                       &type, data, &data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            if type == REG_NONE:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_SZ or type == REG_EXPAND_SZ:
                value = wstr_to_utf8(<LPCWSTR> data)
            elif type == REG_BINARY:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_DWORD:
                dw_ptr = <LPDWORD> data
                value = self._dword_le_to_host(dw_ptr[0])
            elif type == REG_DWORD_BIG_ENDIAN:
                dw_ptr = <LPDWORD> data
                value = self._dword_be_to_host(dw_ptr[0])
            elif type == REG_LINK:
                value = PyString_FromStringAndSize(<char *>data, data_size)
            elif type == REG_MULTI_SZ:
                # FIXME - this is doable
                value = PyString_FromStringAndSize(<char *>data, data_size)
            else:
                value = PyString_FromStringAndSize(<char *>data, data_size)

            return value
        finally:
            if name_w != NULL:
                wstr_free_string(name_w)

            if data != NULL:
                free(data)



        

    def set_value(self, value_name, value_data, value_type=None):
        """Set a value contained in this key

        Takes as arguments the name of the value, the data itself, and
        optionally the value type. Currently only the registry types
        DWORD and SZ (string) are fully supported."""

        cdef LPWSTR name_w
        cdef LPBYTE data
        cdef DWORD data_size

        name_w = NULL
        data = NULL

        try:
            if value_type == None:
                if isinstance(value_data, basestring):
                    value_type = REG_SZ
                else:
                    value_type = REG_DWORD

            if value_name != None:
                name_w = wstr_from_utf8(value_name)
            else:
                name_w = NULL

            if value_type == REG_SZ:
                data = <LPBYTE> wstr_from_utf8(value_data)
                data_size = (len(value_data) + 1) * 2
            elif value_type == REG_DWORD:
                data = <LPBYTE> malloc(4)
                (<LPDWORD> data)[0] = self._dword_le_from_host(value_data)
                data_size = 4
            else:
                raise RAPIError(E_NOTIMPL)

            self.rapi_session.__session_select__()

            retval = CeRegSetValueEx(self.handle, name_w, 0, value_type, data, data_size)

            if retval != ERROR_SUCCESS:
                raise RAPIError(retval)

            return
        finally:
            if name_w != NULL:
                wstr_free_string(name_w)
            if data != NULL:
                if type == REG_SZ:
                    wstr_free_string(data)
                else:
                    free(data)

    

    def delete_sub_key(self, sub_key):
        """Delete a sub key of this key.

        Takes as an argument the name of the subkey to delete relative to this key.
        The path to a key more than one level down should be separated by backslashes.
        There is no return value."""

        cdef LPWSTR key_w

        key_w = wstr_from_utf8(sub_key)
        self.rapi_session.__session_select__()

        retval = CeRegDeleteKey(self.handle, key_w)
        wstr_free_string(key_w)

        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)

        return

    def delete_value(self, value_name=None):
        """Delete a value contained in this key

        Takes as an argument the name of the value to delete. There is
        no return value."""

        cdef LPWSTR name_w

        if value_name != None:
            name_w = wstr_from_utf8(value_name)
        else:
            name_w = NULL

        self.rapi_session.__session_select__()

        retval = CeRegDeleteValue(self.handle, name_w)

        if name_w != NULL:
            wstr_free_string(name_w)

        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)

        return

    def close(self):
        """Close the handle to this key."""

        # we probably dont want to close root keys
        if self.handle == 0x80000000 or self.handle == 0x80000001 or self.handle == 0x80000002 or self.handle == 0x80000003 or self.handle == 0:
            return

        self.rapi_session.__session_select__()

        retval = CeRegCloseKey(self.handle)
        self.handle = 0
        if retval != ERROR_SUCCESS:
            raise RAPIError(retval)


class RAPIFile(object):
    """File object from a Windows Mobile Device

    This attempts to be as close as possible to a standard Python file-like object"""

    def __init__(self, rapi_session, handle, filename, mode):
        self.rapi_session = rapi_session
        self.handle = handle
        self.name = filename
        self.mode = mode

    def __del__(self):
        self.close()

    def read(self, size=-1):
        """Read from the file.

        Reads at most size bytes from the file, or the complete file if size is not given"""

        cdef DWORD bytes_read
        cdef DWORD bytes_to_read
        cdef LPBYTE readbuf
        cdef LPBYTE buffer
        cdef BOOL retval
        cdef DWORD total_read

        total_read = 0

        if size >= 0:
            bytes_to_read = size
        else:
            bytes_to_read = 1024*1024

        readbuf = <LPBYTE> malloc (bytes_to_read)
        buffer = NULL

        while TRUE:
            retval = CeReadFile(self.handle, readbuf, bytes_to_read, &bytes_read, NULL)

            if retval == FALSE:
                free(readbuf)
                free(buffer)
                raise RAPIError

            if bytes_read == 0:
                break

            buffer = <LPBYTE> realloc(buffer, (total_read + bytes_read))
            memcpy(buffer+(sizeof(BYTE)*total_read), readbuf, bytes_read)
            total_read = total_read + bytes_read

            if bytes_read < bytes_to_read:
                bytes_to_read = bytes_to_read - bytes_read
                continue

            if size >= 0:
                break

            bytes_to_read = 1024*1024

        free(readbuf)

        cdef object returnstring
        returnstring = PyString_FromStringAndSize(<char *>buffer, total_read)
        free(buffer)
        return returnstring


    def write(self, buffer):
        """Write to the file.

        Writes the given buffer to the file."""

        cdef HANDLE hFile
        cdef char * lpBuffer
        cdef DWORD bytes_to_write
        cdef DWORD bytes_written
        cdef BOOL retval

        hFile = self.handle
        lpBuffer = buffer
        bytes_to_write = len(buffer)

        with nogil:
            retval = CeWriteFile(hFile, lpBuffer, bytes_to_write, &bytes_written, NULL)

        if retval == FALSE:
            raise RAPIError

        return bytes_written

    def tell(self):
        """Return the position of the file pointer."""

        cdef DWORD retval

        retval = CeSetFilePointer(self.handle, 0, NULL, FILE_CURRENT);
        if retval == 0xFFFFFFFF:
            raise RAPIError

        return retval

    def seek(self, offset, whence=0):
        """ Set the position of the file pointer."""

        cdef DWORD retval

        retval = CeSetFilePointer(self.handle, offset, NULL, whence);
        if retval == 0xFFFFFFFF:
            raise RAPIError

    def close(self):
        """Close the file handle."""

        if self.handle == 0:
            return

        retval = CeCloseHandle(self.handle) 
        self.handle = 0
        if retval == FALSE:
            raise RAPIError


cdef class RAPISession:
    """A connection to a Windows Mobile device."""

    cdef RapiConnection *rapi_conn

    def __cinit__(self, device=None, log_level=SYNCE_LOG_LEVEL_LOWEST, *args, **keywords):
        synce_log_set_level(log_level)

        if device == None:
            self.rapi_conn = rapi_connection_from_name(NULL)
        else:
            self.rapi_conn = rapi_connection_from_name(device)

        if self.rapi_conn == NULL:
            raise RAPIError(E_FAIL)

        rapi_connection_select(self.rapi_conn)
        
        retval = CeRapiInit()
        
        if retval != 0:
            raise RAPIError(retval)


    def __init__(self, device=None, log_level=SYNCE_LOG_LEVEL_LOWEST):
        return


    def __dealloc__(self):
        if self.rapi_conn != NULL:
            rapi_connection_select(self.rapi_conn)
            CeRapiUninit()
            rapi_connection_destroy(self.rapi_conn)
            self.rapi_conn = NULL


    def __getattr__(self, name):
        cdef int os_major
        cdef int os_minor
        cdef int retval

        if name == "HKEY_CLASSES_ROOT" or name == "HKCR":
            return RegKey(self, 0x80000000)
        elif name == "HKEY_CURRENT_USER" or name == "HKCU":
            return RegKey(self, 0x80000001)
        elif name == "HKEY_LOCAL_MACHINE" or name == "HKLM":
            return RegKey(self, 0x80000002)
        elif name == "HKEY_USERS" or name == "HKU":
            return RegKey(self, 0x80000003)
        elif name == "name":
            return rapi_connection_get_name(self.rapi_conn)
        elif name == "os_version":
            retval = rapi_connection_get_os_version(self.rapi_conn, &os_major, &os_minor)
            if retval == 0:
                return None
            else:
                return (os_major, os_minor)
        elif name == "build_number":
            return rapi_connection_get_build_number(self.rapi_conn)
        elif name == "processor_type":
            return rapi_connection_get_processor_type(self.rapi_conn)
        elif name == "os_name":
            return rapi_connection_get_os_name(self.rapi_conn)
        elif name == "model":
            return rapi_connection_get_model(self.rapi_conn)
        elif name == "device_ip":
            return rapi_connection_get_device_ip(self.rapi_conn)
        elif name == "local_ip":
            return rapi_connection_get_local_ip(self.rapi_conn)

        # this gives access to the RapiConnection C object wrapped in a
        # python CObject, be careful !!!
        elif name == "rapi_connection":
            return PyCObject_FromVoidPtr(<void *>self.rapi_conn, NULL)
        else:
            raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))


    def __session_select__(self):
        rapi_connection_select(self.rapi_conn)


    def process_config(self, config, flags):
        """Process the supplied configuration xml.

        Returns the reply document if there is one, otherwise
        an empty string."""

        cdef LPWSTR config_w
        cdef LPWSTR reply_w
        cdef DWORD flags_c
        cdef HRESULT retval
        cdef char *reply

        reply_w = NULL;

        config_w = wstr_from_utf8(config)
        flags_c = flags

        self.__session_select__()

        with nogil:
            retval = CeProcessConfig(config_w, flags_c, &reply_w)
            wstr_free_string(config_w)

            reply = wstr_to_utf8(reply_w)
            wstr_free_string(reply_w)

        if retval != 0:
            raise RAPIError(retval)

        if reply == NULL:
            return ""
        else:
            return reply

    def start_replication(self):
        self.__session_select__()

        retval = CeStartReplication()
        if retval != TRUE:
            raise RAPIError(retval)

    def sync_start(self, params):
        cdef LPWSTR params_w

        params_w = wstr_from_utf8(params)

        self.__session_select__()

        retval = CeSyncStart(params_w)
        wstr_free_string(params_w)
        if retval != 0:
            raise RAPIError

    def sync_resume(self):
        self.__session_select__()

        retval = CeSyncResume()
        if retval != 0:
            raise RAPIError

    def sync_pause(self):
        self.__session_select__()

        retval = CeSyncPause()
        if retval != 0:
            raise RAPIError

    def SyncTimeToPc(self):
        self.__session_select__()

        return CeSyncTimeToPc()

    def getDiskFreeSpaceEx(self, path):
        """Retrieve the amount of space on a disk volume.

        Takes as an argument a path to a storage location. Returns a tuple
        consisting of free bytes available to the calling user, total number
        of bytes available to the user, and total free bytes."""

        cdef ULARGE_INTEGER freeBytesAvailable  
        cdef ULARGE_INTEGER totalNumberOfBytes  
        cdef ULARGE_INTEGER totalNumberOfFreeBytes 

        self.__session_select__()

        retval = CeGetDiskFreeSpaceEx( path, &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes) 

        #This functions returns 0 if something went wrong....
        if retval == 0:
            raise RAPIError

        #return a tuple at the moment, maybe later make this a list
        return (freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes) 

    def getSystemPowerStatus(self, refresh):
        """Retrieves the system power status.

        Returns a dictionary containing various details of the power status"""

        cdef SYSTEM_POWER_STATUS_EX powerStatus
        cdef BOOL retval

        self.__session_select__()

        with nogil:
            retval = CeGetSystemPowerStatusEx( &powerStatus, 0 )
        #In contrast to other functions, this returns a boolean,
        #denoting whether the call was succesfull
        if retval == FALSE:
            raise RAPIError

        #Now construct the dictionary:
        result = dict()
        result["ACLineStatus"] = powerStatus.ACLineStatus
        result["BatteryFlag"]               = powerStatus.BatteryFlag
        result["BatteryLifePercent"]        = powerStatus.BatteryLifePercent
        result["Reserved1"]                 = powerStatus.Reserved1
        result["BatteryLifeTime"]           = powerStatus.BatteryLifeTime
        result["BatteryFullLifeTime"]       = powerStatus.BatteryFullLifeTime
        result["Reserved2"]                 = powerStatus.Reserved2
        result["BackupBatteryFlag"]         = powerStatus.BackupBatteryFlag
        result["BackupBatteryLifePercent"]  = powerStatus.BackupBatteryLifePercent
        result["Reserved3"]                 = powerStatus.Reserved3
        result["BackupBatteryLifeTime"]     = powerStatus.BackupBatteryLifeTime
        result["BackupBatteryFullLifeTime"] = powerStatus.BackupBatteryFullLifeTime
        return result


    def findAllFiles( self, query, flags ):
        """Retrieves information about files and directories.

        Takes as arguments the path to search in, and a combination of
        filter and search flags. Returns a list containing dictionaries
        of attributes for each entry."""

        cdef LPWSTR query_w
        query_w = wstr_from_utf8(query)

        cdef LPCE_FIND_DATA find_data 
        cdef DWORD numberOfFiles

        cdef CE_FIND_DATA found_file

        self.__session_select__()

        retval = CeFindAllFiles( query_w, flags , &numberOfFiles, &find_data )
        wstr_free_string(query_w)
        if retval == 0:
            raise RAPIError

        #Now create a list of dictionaries
        result = [] 
        i=0
        while i < numberOfFiles:
            found_file = find_data[ i ] 
            
            this_file = dict()

            if flags & FAF_ATTRIBUTES:
                this_file["Attributes"] = found_file.dwFileAttributes

            if flags & FAF_CREATION_TIME:
                this_file["CreationLowDateTime"] = found_file.ftCreationTime.dwLowDateTime
                this_file["CreationHighDateTime"] = found_file.ftCreationTime.dwHighDateTime
            
            if flags & FAF_LASTACCESS_TIME:
                this_file["LastAccessLowDateTime"] = found_file.ftLastAccessTime.dwLowDateTime
                this_file["LastAccessHighDateTime"] = found_file.ftLastAccessTime.dwHighDateTime
            
            if flags & FAF_LASTWRITE_TIME:
                this_file["LastWriteLowDateTime"] = found_file.ftCreationTime.dwLowDateTime
                this_file["LastWriteHighDateTime"] = found_file.ftCreationTime.dwHighDateTime

            if flags & FAF_SIZE_HIGH:
                this_file["SizeHigh"] = found_file.nFileSizeHigh
             
            if flags & FAF_SIZE_LOW:
                this_file["SizeLow"] = found_file.nFileSizeLow
            
            if flags & FAF_OID:
                this_file["OID"] = found_file.dwOID

            if flags & FAF_NAME:
                this_file["Name"] = wstr_to_utf8(found_file.cFileName)


            result.append( this_file )
            i = i + 1


        return result


    def file_open(self, filename, mode="r", shareMode=0, flagsAndAttributes=0):
        """Open a file.

        Takes as an argument the name of the file, and the open mode. Returns
        a RAPIFile object."""

        cdef LPWSTR filename_w
        cdef HANDLE fileHandle
        cdef DWORD desiredAccess
        cdef DWORD createDisposition
        cdef DWORD seek_ret

        if mode[0] not in "rwa":
            raise ValueError("mode string must begin with one of 'r', 'w' or 'a', not '%s'" % mode[0])

        filename_w = wstr_from_utf8(filename)

        if mode[0] == "r":
            desiredAccess = GENERIC_READ
            createDisposition = OPEN_EXISTING
        elif mode[0] == "w":
            desiredAccess = GENERIC_WRITE
            createDisposition = CREATE_ALWAYS
        else:
            desiredAccess = GENERIC_WRITE
            createDisposition = OPEN_ALWAYS

        if "+" in mode:
            desiredAccess = desiredAccess|GENERIC_WRITE

        fileHandle = CeCreateFile( filename_w, desiredAccess, shareMode, NULL, createDisposition, flagsAndAttributes, 0) 

        wstr_free_string(filename_w)
        if fileHandle == <HANDLE> -1:
            raise RAPIError

        if mode[0] == "a":
            seek_ret = CeSetFilePointer(fileHandle, 0, NULL, FILE_END)
            if seek_ret == 0xFFFFFFFF:
                raise RAPIError

        return RAPIFile(self, fileHandle, filename, mode)

    
    #TODO: Provide the user with the processInformation
    def createProcess(self, applicationName, applicationParams):
        """Start a remote process.

        Arguments are the name of the application to run, and a
        string of the arguments to the application."""

        cdef PROCESS_INFORMATION processInformation
        cdef LPWSTR applicationName_w
        cdef LPWSTR applicationParams_w

        applicationName_w = wstr_from_utf8(applicationName)
        applicationParams_w = wstr_from_utf8(applicationParams)

        self.__session_select__()

        retval = CeCreateProcess( applicationName_w, applicationParams_w, NULL, NULL, False, 0, NULL, NULL, NULL, &processInformation)

        wstr_free_string(applicationName_w)
        wstr_free_string(applicationParams_w)

        if retval == 0:
            raise RAPIError

        return retval


    def getVersion(self):
        """Obtain operating system version information.

        Returns a dictionary of version information."""

        cdef CEOSVERSIONINFO osVersionInfo
        
        self.__session_select__()

        retval = CeGetVersionEx( &osVersionInfo)
     
        if retval == 0:
            raise RAPIError

		#Now construct the dictionary:
        result = dict()
        result["OSVersionInfoSize"] = osVersionInfo.dwOSVersionInfoSize
        result["MajorVersion"]      = osVersionInfo.dwMajorVersion
        result["MinorVersion"]      = osVersionInfo.dwMinorVersion
        result["BuildNumber"]       = osVersionInfo.dwBuildNumber
        result["PlatformId"]        = osVersionInfo.dwPlatformId
        
        return result
    
    def getSystemInfo(self):
        """Obtain information about the system.

        Returns a dictionary containing the system information."""

        cdef SYSTEM_INFO systemInfo
        
        self.__session_select__()

        CeGetSystemInfo( &systemInfo )
        
        result = dict()
        result["ProcessorArchitecture"]                 = systemInfo.wProcessorArchitecture
        result["Reserved"]                              = systemInfo.wReserved
        result["PageSize"]                              = systemInfo.dwPageSize
        result["MinimumApplicationAddress"]             = systemInfo.lpMinimumApplicationAddress
        result["MaximumApplicationAddress"]             = systemInfo.lpMaximumApplicationAddress
        result["ActiveProcessorMask"]                   = systemInfo.dwActiveProcessorMask
        result["NumberOfProcessors"]                    = systemInfo.dwNumberOfProcessors
        result["ProcessorType"]                         = systemInfo.dwProcessorType
        result["AllocationGranularity"]                 = systemInfo.dwAllocationGranularity
        result["ProcessorLevel"]                        = systemInfo.wProcessorLevel
        result["ProcessorRevision"]                     = systemInfo.wProcessorRevision
        
        return result