diff --git a/dlls/kernel32/oldconfig.c b/dlls/kernel32/oldconfig.c index 20b6eaa..d538d7d 100644 --- a/dlls/kernel32/oldconfig.c +++ b/dlls/kernel32/oldconfig.c @@ -331,8 +331,8 @@ static int SCSI_getprocentry( FILE * procfile, struct LinuxProcScsiDevice * dev } -/* create the hardware registry branch */ -static void create_hardware_branch(void) +/* create the scsi registry branch */ +static void create_scsi_branch(void) { /* The following mostly will work on Linux, but should not cause * problems on other systems. */ @@ -454,6 +454,149 @@ static void create_hardware_branch(void) } +/* create SERIALCOMM branch containing keys for /dev/ttyS* */ +void create_serialcomm_branch(void) +{ + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameU; + WCHAR dataW[50]; + DWORD length; + DWORD disp; + HANDLE targetKey; + struct dirent * dent; + DIR * dir; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + char deviceprefix[5] = "cuad"; +#else + char deviceprefix[5] = "ttyS"; +#endif + int portmap[256]; + int isdevice[256]; + char readlinkbuf[261]; + char keyname[] = "\\Device\\Serial999"; + char keydata[] = "COM999"; + const char * wineprefixdir; + char * dosdevicepath = 0; + static const char dosdevdirsuffix[] = "/dosdevices"; + int suffixlength = 11; + int pathlength = 0; + int index = 0; + int numbytes = 0; + int devnumber = 0; + int portnumber = 0; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.ObjectName = &nameU; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + /* Ensure there is HARDWARE\\DEVICEMAP\\SERIALCOMM key */ + if(!RtlCreateUnicodeStringFromAsciiz( &nameU, "Machine\\HARDWARE\\DEVICEMAP\\SERIALCOMM" ) || + NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0, + NULL, REG_OPTION_VOLATILE, &disp )) + { + ERR("Cannot create DEVICEMAP\\SERIALCOMM registry key\n" ); + return; + } + RtlFreeUnicodeString( &nameU ); + + /*initialise portmap and devices arrays to -1*/ + for(index = 0; index < 256; index++) + { + portmap[index] = -1; + isdevice[index] = 0; + } + + /* we're doing a subset of mountmgr.sys/device.c's get_dosdevices_path() */ + wineprefixdir = wine_get_config_dir(); + pathlength = strlen(wineprefixdir) + suffixlength + 1; + /*alloc 256 more bytes than pathlength so we can put filename on the end */ + dosdevicepath = HeapAlloc(GetProcessHeap(), 0, pathlength + 256); + strcpy(dosdevicepath, wineprefixdir); + strcat(dosdevicepath, dosdevdirsuffix); + + /* Enumerate all ttyS* devices first */ + dir = opendir("/dev"); + if(dir) + { + while((dent = readdir(dir))) + { + if(strncmp(dent->d_name, deviceprefix, 4) == 0) + { + /*d_name is null terminated already*/ + devnumber = strtol(dent->d_name + 4, NULL, 10); + /*which COM port will this device map onto*/ + portmap[devnumber] = devnumber + 1; + isdevice[devnumber] = 1; + } + } + } + closedir(dir); + + /* Enumerate all dosdevices/com* symlinks */ + dir = opendir(dosdevicepath); + if(dir) + { + dosdevicepath[pathlength -1] = '/'; + while((dent = readdir(dir))) + { + if(strncmp(dent->d_name, "com", 3) == 0) + { + portnumber = strtol(dent->d_name + 3, NULL, 10); + if(portnumber < 1 || portnumber > 256) + { + continue; + } + else + { + /* get the symlink target + * strtol the last chars + * check and set portmap entry */ + memcpy(dosdevicepath + pathlength, dent->d_name, strlen(dent->d_name) + 1); + numbytes = readlink(dosdevicepath, readlinkbuf, 261); + if(numbytes > 0 && numbytes < 261) + { + readlinkbuf[numbytes] = '\0'; + devnumber = strtol(readlinkbuf + 9, NULL, 10); + if((strncmp(readlinkbuf, "/dev/", 5) == 0) + && strncmp(readlinkbuf + 5, deviceprefix, 4) == 0 + && isdevice[devnumber]) + { + /*avoid duplicates*/ + for(index = 0; index < 256; index++) + if(portmap[index] == portnumber) + portmap[index] = -1; + portmap[devnumber] = portnumber; + } + } + } + } + } + } + closedir(dir); + + for(index = 0; index < 256; index++ ) + { + if(portmap[index] != -1) + { + /* write the keys we've made */ + sprintf(keyname + 14, "%u", index); + sprintf(keydata + 3, "%u", portmap[index]); + + RtlCreateUnicodeStringFromAsciiz( &nameU, keyname ); + RtlMultiByteToUnicodeN( dataW, sizeof(dataW), &length, keydata, 5 ); + NtSetValueKey( targetKey, &nameU, 0, REG_SZ, (BYTE*)dataW, length ); + RtlFreeUnicodeString( &nameU ); + } + } + + HeapFree(GetProcessHeap(), 0, dosdevicepath); + NtClose(targetKey); +} + + /*********************************************************************** * convert_old_config */ @@ -463,5 +606,6 @@ void convert_old_config(void) return; /* someone else already loaded the registry */ /* create some hardware keys (FIXME: should not be done here) */ - create_hardware_branch(); + create_scsi_branch(); + create_serialcomm_branch(); }