mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-22 08:24:11 +00:00
mountmgr: Add requests to query and set shell folder symbolic links.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fa6e791ca5
commit
0a8776d455
|
@ -18,6 +18,9 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CFString.h>
|
||||
#define LoadResource mac_LoadResource
|
||||
|
@ -29,6 +32,9 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#define NONAMELESSUNION
|
||||
|
||||
|
@ -286,6 +292,125 @@ static NTSTATUS define_unix_drive( const void *in_buff, SIZE_T insize )
|
|||
}
|
||||
}
|
||||
|
||||
/* implementation of IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER */
|
||||
static NTSTATUS define_shell_folder( const void *in_buff, SIZE_T insize )
|
||||
{
|
||||
const struct mountmgr_shell_folder *input = in_buff;
|
||||
const char *link = NULL;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING name;
|
||||
NTSTATUS status;
|
||||
ULONG size = 256;
|
||||
char *buffer, *backup = NULL;
|
||||
struct stat st;
|
||||
unsigned int i;
|
||||
|
||||
if (input->folder_offset >= insize || input->folder_size > insize - input->folder_offset ||
|
||||
input->symlink_offset >= insize)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* make sure string is null-terminated */
|
||||
if (input->symlink_offset)
|
||||
{
|
||||
link = (const char *)in_buff + input->symlink_offset;
|
||||
for (i = input->symlink_offset; i < insize; i++)
|
||||
if (!*((const char *)in_buff + i)) break;
|
||||
if (i >= insize) return STATUS_INVALID_PARAMETER;
|
||||
if (!link[0]) link = NULL;
|
||||
}
|
||||
|
||||
/* ignore nonexistent link targets */
|
||||
if (link && stat( link, &st )) return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
|
||||
name.Buffer = (WCHAR *)((char *)in_buff + input->folder_offset);
|
||||
name.Length = input->folder_size;
|
||||
InitializeObjectAttributes( &attr, &name, 0, 0, NULL );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
|
||||
status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN );
|
||||
if (!status) break;
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) return status;
|
||||
}
|
||||
|
||||
if (!(backup = HeapAlloc( GetProcessHeap(), 0, strlen(buffer) + sizeof(".backup" ) )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
strcpy( backup, buffer );
|
||||
strcat( backup, ".backup" );
|
||||
|
||||
if (!lstat( buffer, &st )) /* move old folder/link out of the way */
|
||||
{
|
||||
if (S_ISLNK( st.st_mode ))
|
||||
{
|
||||
unlink( buffer );
|
||||
}
|
||||
else if (link && S_ISDIR( st.st_mode ))
|
||||
{
|
||||
if (rmdir( buffer )) /* non-empty dir, try to make a backup */
|
||||
{
|
||||
if (!backup || rename( buffer, backup ))
|
||||
{
|
||||
status = STATUS_OBJECT_NAME_COLLISION;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
else goto done; /* nothing to do, folder already exists */
|
||||
}
|
||||
|
||||
if (link) symlink( link, buffer );
|
||||
else
|
||||
{
|
||||
if (backup && !lstat( backup, &st ) && S_ISDIR( st.st_mode )) rename( backup, buffer );
|
||||
else mkdir( buffer, 0777 );
|
||||
}
|
||||
|
||||
done:
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
HeapFree( GetProcessHeap(), 0, backup );
|
||||
return status;
|
||||
}
|
||||
|
||||
/* implementation of IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER */
|
||||
static NTSTATUS query_shell_folder( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb )
|
||||
{
|
||||
char *output = buff;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING name;
|
||||
NTSTATUS status;
|
||||
ULONG size = 256;
|
||||
char *buffer;
|
||||
int ret;
|
||||
|
||||
name.Buffer = buff;
|
||||
name.Length = insize;
|
||||
InitializeObjectAttributes( &attr, &name, 0, 0, NULL );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
|
||||
status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN );
|
||||
if (!status) break;
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) return status;
|
||||
}
|
||||
ret = readlink( buffer, output, outsize - 1 );
|
||||
if (ret >= 0)
|
||||
{
|
||||
output[ret] = 0;
|
||||
iosb->Information = ret + 1;
|
||||
}
|
||||
else status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
/* implementation of IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS */
|
||||
static void WINAPI query_dhcp_request_params( TP_CALLBACK_INSTANCE *instance, void *context )
|
||||
{
|
||||
|
@ -934,6 +1059,27 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp )
|
|||
irpsp->Parameters.DeviceIoControl.OutputBufferLength,
|
||||
&irp->IoStatus );
|
||||
break;
|
||||
case IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER:
|
||||
if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_shell_folder))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
irp->IoStatus.Information = 0;
|
||||
status = define_shell_folder( irp->AssociatedIrp.SystemBuffer,
|
||||
irpsp->Parameters.DeviceIoControl.InputBufferLength );
|
||||
break;
|
||||
case IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER:
|
||||
if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_shell_folder))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
status = query_shell_folder( irp->AssociatedIrp.SystemBuffer,
|
||||
irpsp->Parameters.DeviceIoControl.InputBufferLength,
|
||||
irpsp->Parameters.DeviceIoControl.OutputBufferLength,
|
||||
&irp->IoStatus );
|
||||
break;
|
||||
case IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS:
|
||||
if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_dhcp_request_params))
|
||||
{
|
||||
|
|
|
@ -51,8 +51,10 @@ static const WCHAR MOUNTMGR_DOS_DEVICE_NAME[] = {'\\','\\','.','\\','M','o','u',
|
|||
/* Wine extensions */
|
||||
#ifdef WINE_MOUNTMGR_EXTENSIONS
|
||||
|
||||
#define IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE CTL_CODE(MOUNTMGRCONTROLTYPE, 32, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE CTL_CODE(MOUNTMGRCONTROLTYPE, 33, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE CTL_CODE(MOUNTMGRCONTROLTYPE, 32, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE CTL_CODE(MOUNTMGRCONTROLTYPE, 33, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER CTL_CODE(MOUNTMGRCONTROLTYPE, 34, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER CTL_CODE(MOUNTMGRCONTROLTYPE, 35, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
enum mountmgr_fs_type
|
||||
{
|
||||
|
@ -76,6 +78,13 @@ struct mountmgr_unix_drive
|
|||
USHORT label_offset;
|
||||
};
|
||||
|
||||
struct mountmgr_shell_folder
|
||||
{
|
||||
ULONG folder_offset;
|
||||
ULONG folder_size;
|
||||
ULONG symlink_offset;
|
||||
};
|
||||
|
||||
#define IOCTL_MOUNTMGR_READ_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 48, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_WRITE_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 49, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DELETE_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 50, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
|
|
Loading…
Reference in a new issue