From ce8653e31ac6e6edc5e2202f8eb7786ebb53819a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 11 Mar 2008 10:58:10 -0700 Subject: [PATCH] mountmgr.sys: Add registry keys for usb mass storage devices --- dlls/mountmgr.sys/mountmgr.c | 157 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 152 insertions(+), 5 deletions(-) diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 049cab5..6210e32 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -79,7 +79,7 @@ extern NTSTATUS MOUNTMGR_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT extern NTSTATUS MOUNTMGR_ScsiPassThrough(int, PSCSI_PASS_THROUGH pPacket); static struct mount_point mount_points[MAX_MOUNT_POINTS]; -static HKEY mount_key, drive_key; +static HKEY mount_key, drive_key, usbenum_key, devclass_key; static ULONG globaldevicenumber; static unsigned initializing; static DEVICE_OBJECT *harddisk0; @@ -581,6 +581,12 @@ static NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STR 'M','o','u','n','t','e','d','D','e','v','i','c','e','s',0}; static const WCHAR wine_drivesW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', 'D','r','i','v','e','s',0}; + static const WCHAR devclassW[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\', + '{','5','3','f','5','6','3','0','7','-','b','6','b','f','-','1','1','d','0','-', + '9','4','f','2','-','0','0','a','0','c','9','1','e','f','b','8','b','}',0 }; + static const WCHAR enumusbW[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'E','n','u','m','\\','U','S','B','S','T','O','R',0}; NTSTATUS status; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = harddisk_ioctl; @@ -588,7 +594,10 @@ static NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STR RegCreateKeyExW( HKEY_LOCAL_MACHINE, mounted_devicesW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &mount_key, NULL ); RegCreateKeyExW( HKEY_LOCAL_MACHINE, wine_drivesW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &drive_key, NULL ); - + RegCreateKeyExW( HKEY_LOCAL_MACHINE, devclassW, 0, NULL, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &devclass_key, NULL ); + RegCreateKeyExW( HKEY_LOCAL_MACHINE, enumusbW, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &usbenum_key, NULL ); status = create_harddisk( driver, &harddisk0, "/dev/null" ); if (status) { @@ -780,14 +789,152 @@ static DEVICE_OBJECT *find_parent_device(const char *parent_device) return devobj; } +/* Convert all non-alphanumeric characters except hash to underscore */ +static void make_valid(char *string) +{ + for (;*string;string++) + { + if (*string >= '0' && *string <= '9') continue; + if (*string >= 'a' && *string <= 'z') continue; + if (*string >= 'A' && *string <= 'Z') continue; + if (*string == '#' || *string == '-') continue; + if (*string == '{' || *string == '}') continue; + if (*string == '&') continue; + *string = '_'; + } +} + +const char enumstor1printf[] = "Disk&Ven_%s&Prod_%s&Rev_%s"; +const char enumstor2printf[] = "%s&0"; +const char devinstlinkprintf[] = "USBSTOR\\%s\\%s"; +const char devclassprintf[] = "##?#USBSTOR#%s#%s#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"; +const char hardwareidprintf[] = + "USBSTOR\\Disk%s%s%s\n" /* ven, prod, rev */ + "USBSTOR\\Disk%s%s\n" /* ven, prod */ + "USBSTOR\\Disk%s\n" /* ven */ + "USBSTOR\\%s%s%s\n" /* ven, prod, rev */ + "%s%s%s\n" /* ven, prod, rev */ + "USBSTOR\\GenDisk\n" + "GenDisk\n\n"; + BOOL add_extended_dos_device( const char *udi, const char *device, const char *parent_device, const char *mount_point, const char *type, const char *vendor, const char *product, const char *fw_version, const char *serial ) { + char msvendor[] = "________", msproduct[] = "________________"; + char *enumstor1, *enumstor2, *devinstlink, *devclass, *hardwareid, *versiondot, *newline; + int enumstor1len, enumstor2len, devinstlinklen, devclasslen, hardwareidlen; + HKEY dev1 = 0, dev2 = 0, enum1 = 0, enum2 = 0; BOOL ret; - ret = add_dos_device( udi, parent_device, device, mount_point, type ); - FIXME("stub!\n"); - return ret; + + if (!add_dos_device( udi, parent_device, device, mount_point, type )) + { + WARN("Could not add device %s, or device already added, skipping creationism\n", udi); + return FALSE; + } + if (!type || strcmp(type, "hd")) + { + TRACE("Only adding extra information for hard disk devices\n"); + return TRUE; + } + + /* This allocation is optimistic: the length is bigger then the actual usage */ + enumstor1len = sizeof(enumstor1printf) + strlen(vendor) + strlen(product) + strlen(fw_version); + enumstor2len = sizeof(enumstor2printf) + strlen(serial); + devinstlinklen = sizeof(devinstlinkprintf) + enumstor1len + enumstor2len; + devclasslen = sizeof(devclassprintf) + enumstor1len + enumstor2len; + hardwareidlen = sizeof(hardwareidprintf) + 5 * sizeof(msvendor) + 4 * sizeof(msproduct) - 9 + 3 * strlen(fw_version); + + enumstor1 = RtlAllocateHeap(GetProcessHeap(), 0, enumstor1len); + enumstor2 = RtlAllocateHeap(GetProcessHeap(), 0, enumstor2len); + devinstlink = RtlAllocateHeap(GetProcessHeap(), 0, devinstlinklen); + devclass = RtlAllocateHeap(GetProcessHeap(), 0, devclasslen); + hardwareid = RtlAllocateHeap(GetProcessHeap(), 0, hardwareidlen); + + if (!enumstor1 || !enumstor2 || !devinstlink || !devclass || !hardwareid) + goto out_heap; + + sprintf(enumstor1, enumstor1printf, vendor, product, fw_version); + sprintf(enumstor2, enumstor2printf, serial); + sprintf(devinstlink, devinstlinkprintf, enumstor1, enumstor2); + sprintf(devclass, devclassprintf, enumstor1, enumstor2); + + versiondot = strchr(fw_version, '.'); + if (versiondot) + *versiondot = 0; + + lstrcpynA(msvendor, vendor, sizeof(msvendor)-1); + make_valid(msvendor); + if (strlen(msvendor) < sizeof(msvendor)-1) + memset(msvendor + strlen(msvendor), '_', sizeof(msvendor)-1-strlen(msvendor)); + + lstrcpynA(msproduct, product, sizeof(msproduct)-1); + make_valid(msproduct); + if (strlen(msproduct) < sizeof(msproduct)-1) + memset(msproduct + strlen(msproduct), '_', sizeof(msproduct)-1-strlen(msproduct)); + + sprintf(hardwareid, hardwareidprintf, msvendor, msproduct, fw_version, msvendor, msproduct, + msvendor, msvendor, msproduct, fw_version, msvendor, msproduct, fw_version); + hardwareidlen = strlen(hardwareid)+1; + + if (versiondot) + *versiondot = '.'; + + /* These keys can not be created by setupapi, because that would require an installation using a .inf (as far as I can see) */ + ret = !RegCreateKeyExA(usbenum_key, enumstor1, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &enum1, NULL); + if (ret) + ret = !RegCreateKeyExA(enum1, enumstor2, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &enum2, NULL); + if (ret) + ret = !RegCreateKeyExA(devclass_key, devclass, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &dev1, NULL); + if (ret) + ret = !RegCreateKeyExA(dev1, "#", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &dev2, NULL); + if (ret) + { + static const WCHAR caps[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0}; + static const WCHAR class[] = {'C','l','a','s','s',0}; + static const WCHAR disk[] = {'D','i','s','k','D','r','i','v','e',0}; + static const WCHAR cguid[] = {'C','l','a','s','s','G','u','i','d',0}; + static const WCHAR diskguid[] = {'{','4','D','3','6','E','9','6','7','-','E','3','2','5','-','1','1','C','E','-', + 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0}; + DEVICE_OBJECT *parent; + UNICODE_STRING symlink; + NTSTATUS res; + DWORD capsvalue = 0x10; + + RegSetValueExW(enum2, caps, 0, REG_DWORD, (BYTE*)&capsvalue, sizeof(capsvalue)); + RegSetValueExW(enum2, class, 0, REG_SZ, (BYTE*)&disk, sizeof(disk)); + RegSetValueExW(enum2, cguid, 0, REG_SZ, (BYTE*)&diskguid, sizeof(diskguid)); + /* Convert all newlines to \0's, for the REG_SZ_MULTI type */ + while ((newline = strrchr(hardwareid, '\n'))) + *newline = 0; + RegSetValueExA(enum2, "HardwareId", 0, REG_MULTI_SZ, (BYTE*)hardwareid, hardwareidlen); + RegSetValueExA(dev1, "DeviceInstance", 0, REG_SZ, (BYTE*)devinstlink, strlen(devinstlink)+1); + devclass[0] = devclass[1] = devclass[3] = '\\'; + RegSetValueExA(dev2, "SymbolicLink", 0, REG_SZ, (BYTE*)devclass, strlen(devclass)+1); + devclass[1] = '?'; + symlink.Length = symlink.MaximumLength = (strlen(devclass)+1)*sizeof(WCHAR); + symlink.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, symlink.Length); + MultiByteToWideChar(CP_ACP, 0, devclass, -1, symlink.Buffer, symlink.Length); + symlink.Length -= sizeof(WCHAR); + parent = find_parent_device( parent_device ); + res = IoCreateSymbolicLink(&symlink, get_device_name(parent)); + TRACE("RES: %08x (%s->%s)\n", res, debugstr_wn(symlink.Buffer, symlink.Length/sizeof(WCHAR)), debugstr_w(get_device_name(parent)->Buffer)); + RtlFreeHeap(GetProcessHeap(), 0, symlink.Buffer); + } + + RegCloseKey(dev2); + RegCloseKey(dev1); + RegCloseKey(enum2); + RegCloseKey(enum1); + +out_heap: + RtlFreeHeap(GetProcessHeap(), 0, enumstor1); + RtlFreeHeap(GetProcessHeap(), 0, enumstor2); + RtlFreeHeap(GetProcessHeap(), 0, devinstlink); + RtlFreeHeap(GetProcessHeap(), 0, devclass); + RtlFreeHeap(GetProcessHeap(), 0, hardwareid); + + return TRUE; } BOOL add_dos_device( const char *udi, const char *parent_device, const char *device, -- 1.5.4.1