Merge pull request #2720 from mono/fix-39325
[mono.git] / mcs / class / corlib / CoreFoundation / CFHelpers.cs
1 using System;
2 using System.Runtime.InteropServices;
3
4 namespace XamMac.CoreFoundation
5 {
6         internal static class CFHelpers
7         {
8                 internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
9                 internal const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
10
11                 [DllImport (CoreFoundationLibrary)]
12                 internal extern static void CFRelease (IntPtr obj);
13
14                 [DllImport (CoreFoundationLibrary)]
15                 internal extern static IntPtr CFRetain (IntPtr obj);
16
17                 [StructLayout (LayoutKind.Sequential)]
18                 struct CFRange {
19                         public IntPtr loc;
20                         public IntPtr len;
21
22                         public CFRange (int loc, int len)
23                                 : this ((long) loc, (long) len)
24                         {
25                         }
26
27                         public CFRange (long l, long len)
28                         {
29                                 this.loc = (IntPtr) l;
30                                 this.len = (IntPtr) len;
31                         }
32                 }
33
34                 [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
35                 extern static IntPtr CFStringCreateWithCharacters (IntPtr allocator, string str, IntPtr count);
36
37                 [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
38                 extern static IntPtr CFStringGetLength (IntPtr handle);
39
40                 [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
41                 extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
42
43                 [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
44                 extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
45
46                 internal static string FetchString (IntPtr handle)
47                 {
48                         if (handle == IntPtr.Zero)
49                                 return null;
50
51                         string str;
52
53                         int l = (int)CFStringGetLength (handle);
54                         IntPtr u = CFStringGetCharactersPtr (handle);
55                         IntPtr buffer = IntPtr.Zero;
56                         if (u == IntPtr.Zero){
57                                 CFRange r = new CFRange (0, l);
58                                 buffer = Marshal.AllocCoTaskMem (l * 2);
59                                 CFStringGetCharacters (handle, r, buffer);
60                                 u = buffer;
61                         }
62                         unsafe {
63                                 str = new string ((char *) u, 0, l);
64                         }
65
66                         if (buffer != IntPtr.Zero)
67                                 Marshal.FreeCoTaskMem (buffer);
68
69                         return str;
70                 }
71
72                 [DllImport (CoreFoundationLibrary)]
73                 extern static IntPtr CFDataGetLength (IntPtr handle);
74
75                 [DllImport (CoreFoundationLibrary)]
76                 extern static IntPtr CFDataGetBytePtr (IntPtr handle);
77
78                 internal static byte[] FetchDataBuffer (IntPtr handle)
79                 {
80                         var length = (int)CFDataGetLength (handle);
81                         var buffer = new byte [length];
82                         var ptr = CFDataGetBytePtr (handle);
83                         Marshal.Copy (ptr, buffer, 0, buffer.Length);
84                         return buffer;
85                 }
86
87                 [DllImport (CoreFoundationLibrary)]
88                 extern static IntPtr CFDataCreateWithBytesNoCopy (IntPtr allocator, IntPtr bytes, IntPtr length, IntPtr bytesDeallocator);
89
90                 [DllImport (CoreFoundationLibrary)]
91                 extern static IntPtr CFDataCreate (IntPtr allocator, IntPtr bytes, IntPtr length);
92
93                 [DllImport (SecurityLibrary)]
94                 extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
95
96                 unsafe internal static IntPtr CreateCertificateFromData (byte[] data)
97                 {
98                         fixed (void *ptr = data) {
99                                 var cfdata = CFDataCreate (IntPtr.Zero, (IntPtr)ptr, new IntPtr (data.Length));
100                                 if (cfdata == IntPtr.Zero)
101                                         return IntPtr.Zero;
102
103                                 var certificate = SecCertificateCreateWithData (IntPtr.Zero, cfdata);
104                                 if (cfdata != IntPtr.Zero)
105                                         CFRelease (cfdata);
106                                 return certificate;
107                         }
108                 }
109         }
110 }