1 // 2 // CoreFoundation.cs 3 // 4 // Author: 5 // Michael Hutchinson <mhutchinson@novell.com> 6 // Miguel de Icaza 7 // 8 // Copyright (c) 2009 Novell, Inc. (http://www.novell.com) 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a copy 11 // of this software and associated documentation files (the "Software"), to deal 12 // in the Software without restriction, including without limitation the rights 13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 // copies of the Software, and to permit persons to whom the Software is 15 // furnished to do so, subject to the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be included in 18 // all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 // THE SOFTWARE. 27 28 using System; 29 using System.Runtime.InteropServices; 30 31 namespace MonoDevelop.MacInterop 32 { 33 internal static class CoreFoundation 34 { 35 const string CFLib = "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"; 36 const string LSLib = "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices"; 37 38 [DllImport (CFLib)] CFStringCreateWithCString(IntPtr alloc, string str, int encoding)39 static extern IntPtr CFStringCreateWithCString (IntPtr alloc, string str, int encoding); 40 CreateString(string s)41 public static IntPtr CreateString (string s) 42 { 43 // The magic value is "kCFStringENcodingUTF8" 44 return CFStringCreateWithCString (IntPtr.Zero, s, 0x08000100); 45 } 46 47 [DllImport (CFLib, EntryPoint="CFRelease")] Release(IntPtr cfRef)48 public static extern void Release (IntPtr cfRef); 49 50 struct CFRange { 51 public int Location, Length; CFRangeMonoDevelop.MacInterop.CoreFoundation.CFRange52 public CFRange (int l, int len) 53 { 54 Location = l; 55 Length = len; 56 } 57 } 58 59 [DllImport (CFLib, CharSet=CharSet.Unicode)] CFStringGetLength(IntPtr handle)60 extern static int CFStringGetLength (IntPtr handle); 61 62 [DllImport (CFLib, CharSet=CharSet.Unicode)] CFStringGetCharactersPtr(IntPtr handle)63 extern static IntPtr CFStringGetCharactersPtr (IntPtr handle); 64 65 [DllImport (CFLib, CharSet=CharSet.Unicode)] CFStringGetCharacters(IntPtr handle, CFRange range, IntPtr buffer)66 extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer); 67 FetchString(IntPtr handle)68 public static string FetchString (IntPtr handle) 69 { 70 if (handle == IntPtr.Zero) 71 return null; 72 73 string str; 74 75 int l = CFStringGetLength (handle); 76 IntPtr u = CFStringGetCharactersPtr (handle); 77 IntPtr buffer = IntPtr.Zero; 78 if (u == IntPtr.Zero){ 79 CFRange r = new CFRange (0, l); 80 buffer = Marshal.AllocCoTaskMem (l * 2); 81 CFStringGetCharacters (handle, r, buffer); 82 u = buffer; 83 } 84 85 /* 86 unsafe { 87 str = new string ((char *) u, 0, l); 88 } 89 */ 90 str = Marshal.PtrToStringUni(u, l); 91 92 if (buffer != IntPtr.Zero) 93 Marshal.FreeCoTaskMem (buffer); 94 95 return str; 96 } 97 FSRefToString(ref FSRef fsref)98 public static string FSRefToString (ref FSRef fsref) 99 { 100 IntPtr url = IntPtr.Zero; 101 IntPtr str = IntPtr.Zero; 102 try { 103 url = CFURLCreateFromFSRef (IntPtr.Zero, ref fsref); 104 if (url == IntPtr.Zero) 105 return null; 106 str = CFURLCopyFileSystemPath (url, CFUrlPathStyle.Posix); 107 if (str == IntPtr.Zero) 108 return null; 109 return FetchString (str); 110 } finally { 111 if (url != IntPtr.Zero) 112 Release (url); 113 if (str != IntPtr.Zero) 114 Release (str); 115 } 116 } 117 118 [DllImport (CFLib)] CFURLCreateFromFSRef(IntPtr allocator, ref FSRef fsref)119 extern static IntPtr CFURLCreateFromFSRef (IntPtr allocator, ref FSRef fsref); 120 121 [DllImport (CFLib)] CFURLCopyFileSystemPath(IntPtr urlRef, CFUrlPathStyle pathStyle)122 extern static IntPtr CFURLCopyFileSystemPath (IntPtr urlRef, CFUrlPathStyle pathStyle); 123 124 enum CFUrlPathStyle 125 { 126 Posix = 0, 127 Hfs = 1, 128 Windows = 2 129 }; 130 131 [DllImport (CFLib)] CFURLCreateWithFileSystemPath(IntPtr allocator, IntPtr filePathString, CFUrlPathStyle pathStyle, bool isDirectory)132 extern static IntPtr CFURLCreateWithFileSystemPath (IntPtr allocator, IntPtr filePathString, 133 CFUrlPathStyle pathStyle, bool isDirectory); 134 135 [DllImport (LSLib)] LSCopyApplicationURLsForURL(IntPtr urlRef, LSRolesMask roleMask)136 extern static IntPtr LSCopyApplicationURLsForURL (IntPtr urlRef, LSRolesMask roleMask); //CFArrayRef 137 138 [DllImport (LSLib)] LSGetApplicationForURL(IntPtr url, LSRolesMask roleMask, IntPtr fsRefZero, ref IntPtr appUrl)139 extern static int LSGetApplicationForURL (IntPtr url, LSRolesMask roleMask, IntPtr fsRefZero, 140 ref IntPtr appUrl); 141 142 [DllImport (CFLib)] CFArrayGetCount(IntPtr theArray)143 extern static int CFArrayGetCount (IntPtr theArray); 144 145 [DllImport (CFLib)] CFArrayGetValueAtIndex(IntPtr theArray, int idx)146 extern static IntPtr CFArrayGetValueAtIndex (IntPtr theArray, int idx); 147 148 [Flags] 149 public enum LSRolesMask : uint 150 { 151 None = 0x00000001, 152 Viewer = 0x00000002, 153 Editor = 0x00000004, 154 Shell = 0x00000008, 155 All = 0xFFFFFFFF 156 } 157 CreatePathUrl(string path)158 static IntPtr CreatePathUrl (string path) 159 { 160 IntPtr str = IntPtr.Zero; 161 IntPtr url = IntPtr.Zero; 162 try { 163 str = CreateString (path); 164 if (str == IntPtr.Zero) 165 throw new Exception ("CreateString failed"); 166 url = CFURLCreateWithFileSystemPath (IntPtr.Zero, str, CFUrlPathStyle.Posix, false); 167 if (url == IntPtr.Zero) 168 throw new Exception ("CFURLCreateWithFileSystemPath failed"); 169 return url; 170 } finally { 171 if (str != IntPtr.Zero) 172 Release (str); 173 } 174 } 175 UrlToPath(IntPtr url)176 public static string UrlToPath (IntPtr url) 177 { 178 IntPtr str = IntPtr.Zero; 179 try { 180 str = CFURLCopyFileSystemPath (url, CFUrlPathStyle.Posix); 181 return str == IntPtr.Zero? null : FetchString (str); 182 } finally { 183 if (str != IntPtr.Zero) 184 Release (str); 185 } 186 } 187 GetApplicationUrl(string filePath, LSRolesMask roles)188 public static string GetApplicationUrl (string filePath, LSRolesMask roles) 189 { 190 IntPtr url = IntPtr.Zero; 191 try { 192 url = CreatePathUrl (filePath); 193 IntPtr appUrl = IntPtr.Zero; 194 if (LSGetApplicationForURL (url, roles, IntPtr.Zero, ref appUrl) == 0 && appUrl != IntPtr.Zero) 195 return UrlToPath (appUrl); 196 return null; 197 } finally { 198 if (url != IntPtr.Zero) 199 Release (url); 200 } 201 } 202 GetApplicationUrls(string filePath, LSRolesMask roles)203 public static string[] GetApplicationUrls (string filePath, LSRolesMask roles) 204 { 205 IntPtr url = IntPtr.Zero; 206 IntPtr arr = IntPtr.Zero; 207 try { 208 url = CreatePathUrl (filePath); 209 arr = LSCopyApplicationURLsForURL (url, roles); 210 if (arr == IntPtr.Zero) 211 return new string[0]; 212 int count = CFArrayGetCount (arr); 213 string[] values = new string [count]; 214 for (int i = 0; i < values.Length; i++ ) { 215 var u = CFArrayGetValueAtIndex (arr, i); 216 if (u != IntPtr.Zero) 217 values[i] = UrlToPath (u); 218 } 219 return values; 220 } finally { 221 if (url != IntPtr.Zero) 222 Release (url); 223 if (arr != IntPtr.Zero) 224 Release (arr); 225 } 226 } 227 } 228 }