2 * Mount manager service implementation
4 * Copyright 2008 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
24 #define NONAMELESSUNION
29 #include "wine/list.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mountmgr
);
38 struct list entry
; /* entry in mount points list */
39 DEVICE_OBJECT
*device
; /* disk device */
40 UNICODE_STRING name
; /* device name */
41 UNICODE_STRING link
; /* DOS device symlink */
42 void *id
; /* device unique id */
46 static struct list mount_points_list
= LIST_INIT(mount_points_list
);
47 static HKEY mount_key
;
49 unixlib_handle_t mountmgr_handle
= 0;
51 void set_mount_point_id( struct mount_point
*mount
, const void *id
, unsigned int id_len
)
53 RtlFreeHeap( GetProcessHeap(), 0, mount
->id
);
54 mount
->id_len
= max( MIN_ID_LEN
, id_len
);
55 if ((mount
->id
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, mount
->id_len
)))
57 memcpy( mount
->id
, id
, id_len
);
58 RegSetValueExW( mount_key
, mount
->link
.Buffer
, 0, REG_BINARY
, mount
->id
, mount
->id_len
);
60 else mount
->id_len
= 0;
63 static struct mount_point
*add_mount_point( DEVICE_OBJECT
*device
, UNICODE_STRING
*device_name
,
66 struct mount_point
*mount
;
68 UINT len
= (lstrlenW(link
) + 1) * sizeof(WCHAR
) + device_name
->Length
+ sizeof(WCHAR
);
70 if (!(mount
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mount
) + len
))) return NULL
;
72 str
= (WCHAR
*)(mount
+ 1);
73 lstrcpyW( str
, link
);
74 RtlInitUnicodeString( &mount
->link
, str
);
75 str
+= lstrlenW(str
) + 1;
76 memcpy( str
, device_name
->Buffer
, device_name
->Length
);
77 str
[device_name
->Length
/ sizeof(WCHAR
)] = 0;
78 mount
->name
.Buffer
= str
;
79 mount
->name
.Length
= device_name
->Length
;
80 mount
->name
.MaximumLength
= device_name
->Length
+ sizeof(WCHAR
);
81 mount
->device
= device
;
83 list_add_tail( &mount_points_list
, &mount
->entry
);
85 IoCreateSymbolicLink( &mount
->link
, device_name
);
87 TRACE( "created %s id %s for %s\n", debugstr_w(mount
->link
.Buffer
),
88 debugstr_a(mount
->id
), debugstr_w(mount
->name
.Buffer
) );
92 /* create the DosDevices mount point symlink for a new device */
93 struct mount_point
*add_dosdev_mount_point( DEVICE_OBJECT
*device
, UNICODE_STRING
*device_name
, int drive
)
95 WCHAR link
[] = L
"\\DosDevices\\A:";
97 link
[12] = 'A' + drive
;
98 return add_mount_point( device
, device_name
, link
);
101 /* create the Volume mount point symlink for a new device */
102 struct mount_point
*add_volume_mount_point( DEVICE_OBJECT
*device
, UNICODE_STRING
*device_name
,
107 swprintf( link
, ARRAY_SIZE(link
), L
"\\??\\Volume{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
108 guid
->Data1
, guid
->Data2
, guid
->Data3
,
109 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
110 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
111 return add_mount_point( device
, device_name
, link
);
114 /* delete the mount point symlinks when a device goes away */
115 void delete_mount_point( struct mount_point
*mount
)
117 TRACE( "deleting %s\n", debugstr_w(mount
->link
.Buffer
) );
118 list_remove( &mount
->entry
);
119 RegDeleteValueW( mount_key
, mount
->link
.Buffer
);
120 IoDeleteSymbolicLink( &mount
->link
);
121 RtlFreeHeap( GetProcessHeap(), 0, mount
->id
);
122 RtlFreeHeap( GetProcessHeap(), 0, mount
);
125 /* check if a given mount point matches the requested specs */
126 static BOOL
matching_mount_point( const struct mount_point
*mount
, const MOUNTMGR_MOUNT_POINT
*spec
)
128 if (spec
->SymbolicLinkNameOffset
)
130 const WCHAR
*name
= (const WCHAR
*)((const char *)spec
+ spec
->SymbolicLinkNameOffset
);
131 if (spec
->SymbolicLinkNameLength
!= mount
->link
.Length
) return FALSE
;
132 if (wcsnicmp( name
, mount
->link
.Buffer
, mount
->link
.Length
/sizeof(WCHAR
)))
135 if (spec
->DeviceNameOffset
)
137 const WCHAR
*name
= (const WCHAR
*)((const char *)spec
+ spec
->DeviceNameOffset
);
138 if (spec
->DeviceNameLength
!= mount
->name
.Length
) return FALSE
;
139 if (wcsnicmp( name
, mount
->name
.Buffer
, mount
->name
.Length
/sizeof(WCHAR
)))
142 if (spec
->UniqueIdOffset
)
144 const void *id
= ((const char *)spec
+ spec
->UniqueIdOffset
);
145 if (spec
->UniqueIdLength
!= mount
->id_len
) return FALSE
;
146 if (memcmp( id
, mount
->id
, mount
->id_len
)) return FALSE
;
151 /* implementation of IOCTL_MOUNTMGR_QUERY_POINTS */
152 static NTSTATUS
query_mount_points( void *buff
, SIZE_T insize
,
153 SIZE_T outsize
, IO_STATUS_BLOCK
*iosb
)
155 UINT count
, pos
, size
;
156 MOUNTMGR_MOUNT_POINT
*input
= buff
;
157 MOUNTMGR_MOUNT_POINTS
*info
;
158 struct mount_point
*mount
;
160 if (insize
< sizeof(*input
) ||
161 outsize
< sizeof(*info
) ||
162 input
->SymbolicLinkNameOffset
+ input
->SymbolicLinkNameLength
> insize
||
163 input
->UniqueIdOffset
+ input
->UniqueIdLength
> insize
||
164 input
->DeviceNameOffset
+ input
->DeviceNameLength
> insize
||
165 input
->SymbolicLinkNameOffset
+ input
->SymbolicLinkNameLength
< input
->SymbolicLinkNameOffset
||
166 input
->UniqueIdOffset
+ input
->UniqueIdLength
< input
->UniqueIdOffset
||
167 input
->DeviceNameOffset
+ input
->DeviceNameLength
< input
->DeviceNameOffset
)
168 return STATUS_INVALID_PARAMETER
;
171 LIST_FOR_EACH_ENTRY( mount
, &mount_points_list
, struct mount_point
, entry
)
173 if (!matching_mount_point( mount
, input
)) continue;
174 size
+= mount
->name
.Length
;
175 size
+= mount
->link
.Length
;
176 size
+= mount
->id_len
;
177 size
= (size
+ sizeof(WCHAR
) - 1) & ~(sizeof(WCHAR
) - 1);
180 pos
= FIELD_OFFSET( MOUNTMGR_MOUNT_POINTS
, MountPoints
[count
] );
187 iosb
->Information
= sizeof(info
->Size
);
188 return STATUS_BUFFER_OVERFLOW
;
191 input
= HeapAlloc( GetProcessHeap(), 0, insize
);
193 return STATUS_NO_MEMORY
;
194 memcpy( input
, buff
, insize
);
197 info
->NumberOfMountPoints
= count
;
199 LIST_FOR_EACH_ENTRY( mount
, &mount_points_list
, struct mount_point
, entry
)
201 if (!matching_mount_point( mount
, input
)) continue;
203 info
->MountPoints
[count
].DeviceNameOffset
= pos
;
204 info
->MountPoints
[count
].DeviceNameLength
= mount
->name
.Length
;
205 memcpy( (char *)buff
+ pos
, mount
->name
.Buffer
, mount
->name
.Length
);
206 pos
+= mount
->name
.Length
;
208 info
->MountPoints
[count
].SymbolicLinkNameOffset
= pos
;
209 info
->MountPoints
[count
].SymbolicLinkNameLength
= mount
->link
.Length
;
210 memcpy( (char *)buff
+ pos
, mount
->link
.Buffer
, mount
->link
.Length
);
211 pos
+= mount
->link
.Length
;
213 info
->MountPoints
[count
].UniqueIdOffset
= pos
;
214 info
->MountPoints
[count
].UniqueIdLength
= mount
->id_len
;
215 memcpy( (char *)buff
+ pos
, mount
->id
, mount
->id_len
);
216 pos
+= mount
->id_len
;
217 pos
= (pos
+ sizeof(WCHAR
) - 1) & ~(sizeof(WCHAR
) - 1);
221 iosb
->Information
= pos
;
222 HeapFree( GetProcessHeap(), 0, input
);
223 return STATUS_SUCCESS
;
226 /* implementation of IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE */
227 static NTSTATUS
define_unix_drive( const void *in_buff
, SIZE_T insize
)
229 const struct mountmgr_unix_drive
*input
= in_buff
;
230 const char *mount_point
= NULL
, *device
= NULL
;
231 WCHAR letter
= towlower( input
->letter
);
233 if (letter
< 'a' || letter
> 'z') return STATUS_INVALID_PARAMETER
;
234 if (input
->type
> DRIVE_RAMDISK
) return STATUS_INVALID_PARAMETER
;
235 if (input
->mount_point_offset
> insize
|| input
->device_offset
> insize
)
236 return STATUS_INVALID_PARAMETER
;
238 /* make sure string are null-terminated */
239 if (input
->mount_point_offset
)
241 mount_point
= (const char *)in_buff
+ input
->mount_point_offset
;
242 if (!memchr( mount_point
, 0, insize
- input
->mount_point_offset
)) return STATUS_INVALID_PARAMETER
;
244 if (input
->device_offset
)
246 device
= (const char *)in_buff
+ input
->device_offset
;
247 if (!memchr( device
, 0, insize
- input
->device_offset
)) return STATUS_INVALID_PARAMETER
;
250 if (input
->type
!= DRIVE_NO_ROOT_DIR
)
252 enum device_type type
= DEVICE_UNKNOWN
;
254 TRACE( "defining %c: dev %s mount %s type %u\n",
255 letter
, debugstr_a(device
), debugstr_a(mount_point
), input
->type
);
258 case DRIVE_REMOVABLE
: type
= (letter
>= 'c') ? DEVICE_HARDDISK
: DEVICE_FLOPPY
; break;
259 case DRIVE_REMOTE
: type
= DEVICE_NETWORK
; break;
260 case DRIVE_CDROM
: type
= DEVICE_CDROM
; break;
261 case DRIVE_RAMDISK
: type
= DEVICE_RAMDISK
; break;
262 case DRIVE_FIXED
: type
= DEVICE_HARDDISK_VOL
; break;
264 return add_dos_device( letter
- 'a', NULL
, device
, mount_point
, type
, NULL
, NULL
);
268 TRACE( "removing %c:\n", letter
);
269 return remove_dos_device( letter
- 'a', NULL
);
273 /* implementation of IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER */
274 static NTSTATUS
define_shell_folder( const void *in_buff
, SIZE_T insize
)
276 const struct mountmgr_shell_folder
*input
= in_buff
;
277 const char *link
= NULL
;
278 OBJECT_ATTRIBUTES attr
;
282 char *buffer
= NULL
, *backup
= NULL
;
283 struct set_shell_folder_params params
;
285 if (input
->folder_offset
>= insize
|| input
->folder_size
> insize
- input
->folder_offset
||
286 input
->symlink_offset
>= insize
)
287 return STATUS_INVALID_PARAMETER
;
289 /* make sure string is null-terminated */
290 if (input
->symlink_offset
)
292 link
= (const char *)in_buff
+ input
->symlink_offset
;
293 if (!memchr( link
, 0, insize
- input
->symlink_offset
)) return STATUS_INVALID_PARAMETER
;
294 if (!link
[0]) link
= NULL
;
297 name
.Buffer
= (WCHAR
*)((char *)in_buff
+ input
->folder_offset
);
298 name
.Length
= input
->folder_size
;
299 InitializeObjectAttributes( &attr
, &name
, 0, 0, NULL
);
303 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
)))
305 status
= STATUS_NO_MEMORY
;
308 status
= wine_nt_to_unix_file_name( &attr
, buffer
, &size
, FILE_OPEN_IF
);
309 if (status
== STATUS_NO_SUCH_FILE
) status
= STATUS_SUCCESS
;
310 if (status
== STATUS_SUCCESS
) break;
311 if (status
!= STATUS_BUFFER_TOO_SMALL
) goto done
;
312 HeapFree( GetProcessHeap(), 0, buffer
);
315 if (input
->create_backup
)
317 if (!(backup
= HeapAlloc( GetProcessHeap(), 0, strlen(buffer
) + sizeof(".backup" ) )))
319 status
= STATUS_NO_MEMORY
;
322 strcpy( backup
, buffer
);
323 strcat( backup
, ".backup" );
326 params
.folder
= buffer
;
327 params
.backup
= backup
;
329 status
= MOUNTMGR_CALL( set_shell_folder
, ¶ms
);
332 HeapFree( GetProcessHeap(), 0, buffer
);
333 HeapFree( GetProcessHeap(), 0, backup
);
337 /* implementation of IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER */
338 static NTSTATUS
query_shell_folder( void *buff
, SIZE_T insize
, SIZE_T outsize
, IO_STATUS_BLOCK
*iosb
)
341 OBJECT_ATTRIBUTES attr
;
348 name
.Length
= insize
;
349 InitializeObjectAttributes( &attr
, &name
, 0, 0, NULL
);
353 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
))) return STATUS_NO_MEMORY
;
354 status
= wine_nt_to_unix_file_name( &attr
, buffer
, &size
, FILE_OPEN
);
357 struct get_shell_folder_params params
= { buffer
, output
, outsize
};
358 status
= MOUNTMGR_CALL( get_shell_folder
, ¶ms
);
359 if (!status
) iosb
->Information
= strlen(output
) + 1;
362 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
363 HeapFree( GetProcessHeap(), 0, buffer
);
366 HeapFree( GetProcessHeap(), 0, buffer
);
370 /* implementation of IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS */
371 static void WINAPI
query_dhcp_request_params( TP_CALLBACK_INSTANCE
*instance
, void *context
)
374 struct mountmgr_dhcp_request_params
*query
= irp
->AssociatedIrp
.SystemBuffer
;
375 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
376 SIZE_T insize
= irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
;
377 SIZE_T outsize
= irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
381 if (FIELD_OFFSET(struct mountmgr_dhcp_request_params
, params
[query
->count
]) > insize
)
383 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
387 for (i
= 0; i
< query
->count
; i
++)
388 if (query
->params
[i
].offset
+ query
->params
[i
].size
> insize
)
390 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
394 if (!memchr( query
->unix_name
, 0, sizeof(query
->unix_name
) ))
396 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
400 offset
= FIELD_OFFSET(struct mountmgr_dhcp_request_params
, params
[query
->count
]);
401 for (i
= 0; i
< query
->count
; i
++)
404 struct dhcp_request_params params
= { query
->unix_name
, &query
->params
[i
],
405 (char *)query
, offset
, outsize
- offset
, &ret_size
};
406 MOUNTMGR_CALL( dhcp_request
, ¶ms
);
408 if (offset
> outsize
)
410 if (offset
>= sizeof(query
->size
)) query
->size
= offset
;
411 offset
= sizeof(query
->size
);
412 irp
->IoStatus
.u
.Status
= STATUS_BUFFER_OVERFLOW
;
416 irp
->IoStatus
.u
.Status
= STATUS_SUCCESS
;
419 irp
->IoStatus
.Information
= offset
;
420 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
423 static void WINAPI
query_symbol_file_callback( TP_CALLBACK_INSTANCE
*instance
, void *context
)
426 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
428 struct ioctl_params params
= { irp
->AssociatedIrp
.SystemBuffer
,
429 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
430 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
432 NTSTATUS status
= MOUNTMGR_CALL( query_symbol_file
, ¶ms
);
434 irp
->IoStatus
.Information
= info
;
435 irp
->IoStatus
.u
.Status
= status
;
436 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
439 /* NT APC called from Unix side to add/remove devices */
440 static void CALLBACK
device_op( ULONG_PTR arg1
, ULONG_PTR arg2
, ULONG_PTR arg3
)
442 struct device_info info
;
443 struct dequeue_device_op_params params
= { arg1
, &info
};
445 if (MOUNTMGR_CALL( dequeue_device_op
, ¶ms
)) return;
450 add_dos_device( -1, info
.udi
, info
.device
, info
.mount_point
,
451 info
.type
, info
.guid
, info
.scsi_info
);
454 add_volume( info
.udi
, info
.device
, info
.mount_point
, DEVICE_HARDDISK_VOL
,
455 info
.guid
, info
.serial
, info
.scsi_info
);
458 if (!remove_dos_device( -1, info
.udi
)) remove_volume( info
.udi
);
463 /* handler for ioctls on the mount manager device */
464 static NTSTATUS WINAPI
mountmgr_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
466 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
470 TRACE( "ioctl %x insize %u outsize %u\n",
471 irpsp
->Parameters
.DeviceIoControl
.IoControlCode
,
472 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
473 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
);
475 switch(irpsp
->Parameters
.DeviceIoControl
.IoControlCode
)
477 case IOCTL_MOUNTMGR_QUERY_POINTS
:
478 status
= query_mount_points( irp
->AssociatedIrp
.SystemBuffer
,
479 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
480 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
483 case IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE
:
484 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(struct mountmgr_unix_drive
))
486 status
= STATUS_INVALID_PARAMETER
;
489 irp
->IoStatus
.Information
= 0;
490 status
= define_unix_drive( irp
->AssociatedIrp
.SystemBuffer
,
491 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
);
493 case IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
:
494 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(struct mountmgr_unix_drive
))
496 status
= STATUS_INVALID_PARAMETER
;
499 status
= query_unix_drive( irp
->AssociatedIrp
.SystemBuffer
,
500 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
501 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
504 case IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER
:
505 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(struct mountmgr_shell_folder
))
507 status
= STATUS_INVALID_PARAMETER
;
510 irp
->IoStatus
.Information
= 0;
511 status
= define_shell_folder( irp
->AssociatedIrp
.SystemBuffer
,
512 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
);
514 case IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER
:
515 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(struct mountmgr_shell_folder
))
517 status
= STATUS_INVALID_PARAMETER
;
520 status
= query_shell_folder( irp
->AssociatedIrp
.SystemBuffer
,
521 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
522 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
525 case IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS
:
526 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(struct mountmgr_dhcp_request_params
))
528 status
= STATUS_INVALID_PARAMETER
;
532 if (TrySubmitThreadpoolCallback( query_dhcp_request_params
, irp
, NULL
))
533 return (irp
->IoStatus
.u
.Status
= STATUS_PENDING
);
534 status
= STATUS_NO_MEMORY
;
536 case IOCTL_MOUNTMGR_QUERY_SYMBOL_FILE
:
537 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
!= sizeof(GUID
))
539 status
= STATUS_INVALID_PARAMETER
;
542 if (TrySubmitThreadpoolCallback( query_symbol_file_callback
, irp
, NULL
))
543 return (irp
->IoStatus
.u
.Status
= STATUS_PENDING
);
544 status
= STATUS_NO_MEMORY
;
546 case IOCTL_MOUNTMGR_READ_CREDENTIAL
:
547 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(struct mountmgr_credential
))
549 struct ioctl_params params
= { irp
->AssociatedIrp
.SystemBuffer
,
550 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
551 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
553 status
= MOUNTMGR_CALL( read_credential
, ¶ms
);
554 irp
->IoStatus
.Information
= info
;
556 else status
= STATUS_INVALID_PARAMETER
;
558 case IOCTL_MOUNTMGR_WRITE_CREDENTIAL
:
559 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(struct mountmgr_credential
))
561 struct ioctl_params params
= { irp
->AssociatedIrp
.SystemBuffer
,
562 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
563 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
565 status
= MOUNTMGR_CALL( write_credential
, ¶ms
);
566 irp
->IoStatus
.Information
= info
;
568 else status
= STATUS_INVALID_PARAMETER
;
570 case IOCTL_MOUNTMGR_DELETE_CREDENTIAL
:
571 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(struct mountmgr_credential
))
573 struct ioctl_params params
= { irp
->AssociatedIrp
.SystemBuffer
,
574 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
575 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
577 status
= MOUNTMGR_CALL( delete_credential
, ¶ms
);
578 irp
->IoStatus
.Information
= info
;
580 else status
= STATUS_INVALID_PARAMETER
;
582 case IOCTL_MOUNTMGR_ENUMERATE_CREDENTIALS
:
583 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(struct mountmgr_credential
))
585 struct ioctl_params params
= { irp
->AssociatedIrp
.SystemBuffer
,
586 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
587 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
589 status
= MOUNTMGR_CALL( enumerate_credentials
, ¶ms
);
590 irp
->IoStatus
.Information
= info
;
592 else status
= STATUS_INVALID_PARAMETER
;
595 FIXME( "ioctl %x not supported\n", irpsp
->Parameters
.DeviceIoControl
.IoControlCode
);
596 status
= STATUS_NOT_SUPPORTED
;
599 irp
->IoStatus
.u
.Status
= status
;
600 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
604 static DWORD WINAPI
device_op_thread( void *arg
)
606 for (;;) SleepEx( INFINITE
, TRUE
); /* wait for APCs */
610 static DWORD WINAPI
run_loop_thread( void *arg
)
612 return MOUNTMGR_CALL( run_loop
, arg
);
616 /* main entry point for the mount point manager driver */
617 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
620 HKEY wow64_ports_key
= NULL
;
623 UNICODE_STRING nameW
, linkW
;
624 DEVICE_OBJECT
*device
;
627 struct run_loop_params params
;
629 TRACE( "%s\n", debugstr_w(path
->Buffer
) );
631 RtlPcToFileHeader( DriverEntry
, &instance
);
632 status
= NtQueryVirtualMemory( GetCurrentProcess(), instance
, MemoryWineUnixFuncs
,
633 &mountmgr_handle
, sizeof(mountmgr_handle
), NULL
);
634 if (status
) return status
;
636 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = mountmgr_ioctl
;
638 RtlInitUnicodeString( &nameW
, L
"\\Device\\MountPointManager" );
639 RtlInitUnicodeString( &linkW
, L
"\\??\\MountPointManager" );
640 if (!(status
= IoCreateDevice( driver
, 0, &nameW
, 0, 0, FALSE
, &device
)))
641 status
= IoCreateSymbolicLink( &linkW
, &nameW
);
644 FIXME( "failed to create device error %x\n", status
);
648 RegCreateKeyExW( HKEY_LOCAL_MACHINE
, L
"System\\MountedDevices", 0, NULL
,
649 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &mount_key
, NULL
);
651 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE
, L
"HARDWARE\\DEVICEMAP\\Scsi", 0, NULL
, REG_OPTION_VOLATILE
,
652 KEY_ALL_ACCESS
, NULL
, &devicemap_key
, NULL
))
653 RegCloseKey( devicemap_key
);
655 RtlInitUnicodeString( &nameW
, L
"\\Driver\\Harddisk" );
656 status
= IoCreateDriver( &nameW
, harddisk_driver_entry
);
658 params
.op_thread
= CreateThread( NULL
, 0, device_op_thread
, NULL
, 0, NULL
);
659 params
.op_apc
= device_op
;
660 CloseHandle( CreateThread( NULL
, 0, run_loop_thread
, ¶ms
, 0, NULL
));
663 /* create a symlink so that the Wine port overrides key can be edited with 32-bit reg or regedit */
664 RegCreateKeyExW( HKEY_LOCAL_MACHINE
, L
"Software\\Wow6432Node\\Wine\\Ports", 0, NULL
,
665 REG_OPTION_CREATE_LINK
, KEY_SET_VALUE
, NULL
, &wow64_ports_key
, NULL
);
666 RegSetValueExW( wow64_ports_key
, L
"SymbolicLinkValue", 0, REG_LINK
,
667 (BYTE
*)L
"\\REGISTRY\\MACHINE\\Software\\Wine\\Ports",
668 sizeof(L
"\\REGISTRY\\MACHINE\\Software\\Wine\\Ports") - sizeof(WCHAR
) );
669 RegCloseKey( wow64_ports_key
);
672 RtlInitUnicodeString( &nameW
, L
"\\Driver\\Serial" );
673 IoCreateDriver( &nameW
, serial_driver_entry
);
675 RtlInitUnicodeString( &nameW
, L
"\\Driver\\Parallel" );
676 IoCreateDriver( &nameW
, parallel_driver_entry
);