imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / mountmgr.sys / diskarb.c
blob4817cfc61d6c492d166834418533f02b21608fa2
1 /*
2 * Devices support using the MacOS Disk Arbitration library.
4 * Copyright 2006 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <assert.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <sys/ioctl.h>
34 #ifdef __APPLE__
35 #include <DiskArbitration/DiskArbitration.h>
36 #include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
37 #include <SystemConfiguration/SCNetworkConfiguration.h>
38 #endif
40 #include "mountmgr.h"
41 #define USE_WS_PREFIX
42 #include "winsock2.h"
43 #include "ws2ipdef.h"
44 #include "dhcpcsdk.h"
45 #include "unixlib.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
51 #ifdef __APPLE__
53 typedef struct
55 uint64_t bus;
56 uint64_t port;
57 uint64_t target;
58 uint64_t lun;
59 } dk_scsi_identify_t;
61 #define DKIOCSCSIIDENTIFY _IOR('d', 254, dk_scsi_identify_t)
63 static void appeared_callback( DADiskRef disk, void *context )
65 CFDictionaryRef dict = DADiskCopyDescription( disk );
66 const void *ref;
67 char device[64];
68 char mount_point[PATH_MAX];
69 size_t model_len = 0;
70 GUID guid, *guid_ptr = NULL;
71 enum device_type type = DEVICE_UNKNOWN;
72 struct scsi_info scsi_info = { 0 };
73 BOOL removable = FALSE;
74 int fd;
76 if (!dict) return;
78 if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumeUUID") )))
80 CFUUIDBytes bytes = CFUUIDGetUUIDBytes( ref );
81 memcpy( &guid, &bytes, sizeof(guid) );
82 guid_ptr = &guid;
85 /* get device name */
86 if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done;
87 strcpy( device, "/dev/r" );
88 CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII );
90 if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumePath") )))
91 CFURLGetFileSystemRepresentation( ref, true, (UInt8 *)mount_point, sizeof(mount_point) );
92 else
93 mount_point[0] = 0;
95 if ((ref = CFDictionaryGetValue( dict, CFSTR("DAMediaKind") )))
97 if (!CFStringCompare( ref, CFSTR("IOCDMedia"), 0 ))
99 type = DEVICE_CDROM;
100 scsi_info.type = 5;
102 if (!CFStringCompare( ref, CFSTR("IODVDMedia"), 0 ) ||
103 !CFStringCompare( ref, CFSTR("IOBDMedia"), 0 ))
105 type = DEVICE_DVD;
106 scsi_info.type = 5;
108 if (!CFStringCompare( ref, CFSTR("IOMedia"), 0 ))
109 type = DEVICE_HARDDISK;
112 if ((ref = CFDictionaryGetValue( dict, CFSTR("DADeviceVendor") )))
114 CFIndex i;
116 CFStringGetCString( ref, scsi_info.model, sizeof(scsi_info.model), kCFStringEncodingASCII );
117 model_len += CFStringGetLength( ref );
118 /* Pad to 8 characters */
119 for (i = 0; i < (CFIndex)8 - CFStringGetLength( ref ); ++i)
120 scsi_info.model[model_len++] = ' ';
122 if ((ref = CFDictionaryGetValue( dict, CFSTR("DADeviceModel") )))
124 CFIndex i;
126 CFStringGetCString( ref, scsi_info.model+model_len, sizeof(scsi_info.model)-model_len, kCFStringEncodingASCII );
127 model_len += CFStringGetLength( ref );
128 /* Pad to 16 characters */
129 for (i = 0; i < (CFIndex)16 - CFStringGetLength( ref ); ++i)
130 scsi_info.model[model_len++] = ' ';
132 if ((ref = CFDictionaryGetValue( dict, CFSTR("DADeviceRevision") )))
134 CFIndex i;
136 CFStringGetCString( ref, scsi_info.model+model_len, sizeof(scsi_info.model)-model_len, kCFStringEncodingASCII );
137 model_len += CFStringGetLength( ref );
138 /* Pad to 4 characters */
139 for (i = 0; i < (CFIndex)4 - CFStringGetLength( ref ); ++i)
140 scsi_info.model[model_len++] = ' ';
143 TRACE( "got mount notification for '%s' on '%s' uuid %s\n",
144 device, mount_point, wine_dbgstr_guid(guid_ptr) );
146 if ((ref = CFDictionaryGetValue( dict, CFSTR("DAMediaRemovable") )))
147 removable = CFBooleanGetValue( ref );
149 if (!access( device, R_OK ) &&
150 (fd = open( device, O_RDONLY )) >= 0)
152 dk_scsi_identify_t dsi;
154 if (ioctl( fd, DKIOCSCSIIDENTIFY, &dsi ) >= 0)
156 scsi_info.addr.PortNumber = dsi.bus;
157 scsi_info.addr.PathId = dsi.port;
158 scsi_info.addr.TargetId = dsi.target;
159 scsi_info.addr.Lun = dsi.lun;
160 scsi_info.init_id = 255; /* FIXME */
161 strcpy( scsi_info.driver, "WINE SCSI" ); /* FIXME */
163 close( fd );
166 if (removable)
167 queue_device_op( ADD_DOS_DEVICE, device, device, mount_point, type, guid_ptr, NULL, &scsi_info );
168 else
169 if (guid_ptr) queue_device_op( ADD_VOLUME, device, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, NULL, &scsi_info );
171 done:
172 CFRelease( dict );
175 static void changed_callback( DADiskRef disk, CFArrayRef keys, void *context )
177 appeared_callback( disk, context );
180 static void disappeared_callback( DADiskRef disk, void *context )
182 CFDictionaryRef dict = DADiskCopyDescription( disk );
183 const void *ref;
184 char device[100];
186 if (!dict) return;
188 /* get device name */
189 if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done;
190 strcpy( device, "/dev/r" );
191 CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII );
193 TRACE( "got unmount notification for '%s'\n", device );
195 queue_device_op( REMOVE_DEVICE, device, NULL, NULL, 0, NULL, NULL, NULL );
197 done:
198 CFRelease( dict );
201 void run_diskarbitration_loop(void)
203 DASessionRef session = DASessionCreate( NULL );
205 if (!session) return;
207 DASessionScheduleWithRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
208 DARegisterDiskAppearedCallback( session, kDADiskDescriptionMatchVolumeMountable,
209 appeared_callback, NULL );
210 DARegisterDiskDisappearedCallback( session, kDADiskDescriptionMatchVolumeMountable,
211 disappeared_callback, NULL );
212 DARegisterDiskDescriptionChangedCallback( session, kDADiskDescriptionMatchVolumeMountable,
213 kDADiskDescriptionWatchVolumePath, changed_callback, NULL );
214 CFRunLoopRun();
215 DASessionUnscheduleFromRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
216 CFRelease( session );
219 #else /* __APPLE__ */
221 void run_diskarbitration_loop(void)
223 TRACE( "Skipping, Disk Arbitration support not compiled in\n" );
226 #endif /* __APPLE__ */
228 #if defined(__APPLE__)
230 static UInt8 map_option( unsigned int option )
232 switch (option)
234 case OPTION_SUBNET_MASK: return 1;
235 case OPTION_ROUTER_ADDRESS: return 3;
236 case OPTION_HOST_NAME: return 12;
237 case OPTION_DOMAIN_NAME: return 15;
238 case OPTION_BROADCAST_ADDRESS: return 28;
239 case OPTION_MSFT_IE_PROXY: return 252;
240 default:
241 FIXME( "unhandled option %u\n", option );
242 return 0;
246 static CFStringRef find_service_id( const char *unix_name )
248 SCPreferencesRef prefs;
249 SCNetworkSetRef set = NULL;
250 CFArrayRef services = NULL;
251 CFStringRef id, ret = NULL;
252 CFIndex i;
254 if (!(prefs = SCPreferencesCreate( NULL, CFSTR("mountmgr.sys"), NULL ))) return NULL;
255 if (!(set = SCNetworkSetCopyCurrent( prefs ))) goto done;
256 if (!(services = SCNetworkSetCopyServices( set ))) goto done;
258 for (i = 0; i < CFArrayGetCount( services ); i++)
260 SCNetworkServiceRef service;
261 char buf[16];
262 CFStringRef name;
264 service = CFArrayGetValueAtIndex( services, i );
265 name = SCNetworkInterfaceGetBSDName( SCNetworkServiceGetInterface(service) );
266 if (name && CFStringGetCString( name, buf, sizeof(buf), kCFStringEncodingUTF8 ))
268 if (!strcmp( buf, unix_name ) && (id = SCNetworkServiceGetServiceID( service )))
270 ret = CFStringCreateCopy( NULL, id );
271 break;
276 done:
277 if (services) CFRelease( services );
278 if (set) CFRelease( set );
279 CFRelease( prefs );
280 return ret;
283 NTSTATUS dhcp_request( void *args )
285 const struct dhcp_request_params *params = args;
286 CFStringRef service_id = find_service_id( params->unix_name );
287 CFDictionaryRef dict;
288 CFDataRef value;
289 DWORD ret = 0;
290 CFIndex len;
292 params->req->offset = 0;
293 params->req->size = 0;
294 *params->ret_size = 0;
296 if (!service_id) return 0;
297 if (!(dict = SCDynamicStoreCopyDHCPInfo( NULL, service_id )))
299 CFRelease( service_id );
300 return STATUS_SUCCESS;
302 CFRelease( service_id );
303 if (!(value = DHCPInfoGetOptionData( dict, map_option(params->req->id) )))
305 CFRelease( dict );
306 return STATUS_SUCCESS;
308 len = CFDataGetLength( value );
310 switch (params->req->id)
312 case OPTION_SUBNET_MASK:
313 case OPTION_ROUTER_ADDRESS:
314 case OPTION_BROADCAST_ADDRESS:
316 unsigned int *ptr = (unsigned int *)(params->buffer + params->offset);
317 if (len == sizeof(*ptr) && params->size >= sizeof(*ptr))
319 CFDataGetBytes( value, CFRangeMake(0, len), (UInt8 *)ptr );
320 params->req->offset = params->offset;
321 params->req->size = sizeof(*ptr);
322 TRACE( "returning %08x\n", *ptr );
324 ret = sizeof(*ptr);
325 break;
327 case OPTION_HOST_NAME:
328 case OPTION_DOMAIN_NAME:
329 case OPTION_MSFT_IE_PROXY:
331 char *ptr = params->buffer + params->offset;
332 if (params->size >= len)
334 CFDataGetBytes( value, CFRangeMake(0, len), (UInt8 *)ptr );
335 params->req->offset = params->offset;
336 params->req->size = len;
337 TRACE( "returning %s\n", debugstr_an(ptr, len) );
339 ret = len;
340 break;
342 default:
343 FIXME( "option %u not supported\n", (unsigned int)params->req->id );
344 break;
347 CFRelease( dict );
348 *params->ret_size = ret;
349 return STATUS_SUCCESS;
352 #elif !defined(SONAME_LIBDBUS_1)
354 NTSTATUS dhcp_request( void *args )
356 return STATUS_NOT_SUPPORTED;
359 #endif