Author: hbelusca Date: Sun Aug 20 21:30:13 2017 New Revision: 75632
URL: http://svn.reactos.org/svn/reactos?rev=75632&view=rev Log: [SETUPLIB]: Factor out and introduce a ParseArcName() helper function that does its job. Used in exiting code and in later code in this file.
Modified: branches/setup_improvements/base/setup/lib/arcname.c
Modified: branches/setup_improvements/base/setup/lib/arcname.c URL: http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/li... ============================================================================== --- branches/setup_improvements/base/setup/lib/arcname.c [iso-8859-1] (original) +++ branches/setup_improvements/base/setup/lib/arcname.c [iso-8859-1] Sun Aug 20 21:30:13 2017 @@ -345,6 +345,218 @@
/* + * ArcNamePath: + * In input, pointer to an ARC path (NULL-terminated) starting by an + * ARC name to be parsed into its different components. + * In output, ArcNamePath points to the beginning of the path after + * the ARC name part. + */ +static NTSTATUS +ParseArcName( + IN OUT PCWSTR* ArcNamePath, + OUT PULONG pAdapterKey, + OUT PULONG pControllerKey, + OUT PULONG pPeripheralKey, + OUT PULONG pPartitionNumber, + OUT PADAPTER_TYPE pAdapterType, + OUT PCONTROLLER_TYPE pControllerType, + OUT PPERIPHERAL_TYPE pPeripheralType, + OUT PBOOLEAN pUseSignature) +{ + WCHAR TokenBuffer[50]; + UNICODE_STRING Token; + PCWSTR p, q; + ULONG AdapterKey; + ULONG ControllerKey; + ULONG PeripheralKey; + ULONG PartitionNumber; + ADAPTER_TYPE AdapterType; + CONTROLLER_TYPE ControllerType; + PERIPHERAL_TYPE PeripheralType; + BOOLEAN UseSignature = FALSE; + + /* + * The format of ArcName is: + * adapter(www)[controller(xxx)peripheral(yyy)[partition(zzz)][filepath]] , + * where the [filepath] part is not being parsed. + */ + + RtlInitEmptyUnicodeString(&Token, TokenBuffer, sizeof(TokenBuffer)); + + p = *ArcNamePath; + + /* Retrieve the adapter */ + p = ArcGetNextTokenU(p, &Token, &AdapterKey); + if (!p) + { + DPRINT1("No adapter specified!\n"); + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + /* Check for the 'signature()' pseudo-adapter, introduced in Windows 2000 */ + if (_wcsicmp(Token.Buffer, L"signature") == 0) + { + /* + * We've got a signature! Remember this for later, and set the adapter type to SCSI. + * We however check that the rest of the ARC path is valid by parsing the other tokens. + * AdapterKey stores the disk signature value (that holds in a ULONG). + */ + UseSignature = TRUE; + AdapterType = ScsiAdapter; + } + else + { + /* Check for regular adapters */ + AdapterType = (ADAPTER_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, AdapterTypes_U); + if (AdapterType >= AdapterTypeMax) + { + DPRINT1("Invalid adapter type %wZ\n", &Token); + return STATUS_OBJECT_NAME_INVALID; + } + + /* Check for adapters that don't take any extra controller or peripheral nodes */ + if (AdapterType == NetAdapter || AdapterType == RamdiskAdapter) + { + // if (*p) + // return STATUS_OBJECT_PATH_SYNTAX_BAD; + + if (AdapterType == NetAdapter) + { + DPRINT1("%S(%lu) path is not supported!\n", AdapterTypes_U[AdapterType], AdapterKey); + return STATUS_NOT_SUPPORTED; + } + + goto Quit; + } + } + + /* Here, we have either an 'eisa', a 'scsi/signature', or a 'multi' adapter */ + + /* Check for a valid controller */ + p = ArcGetNextTokenU(p, &Token, &ControllerKey); + if (!p) + { + DPRINT1("%S(%lu) adapter doesn't have a controller!\n", AdapterTypes_U[AdapterType], AdapterKey); + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + ControllerType = (CONTROLLER_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, ControllerTypes_U); + if (ControllerType >= ControllerTypeMax) + { + DPRINT1("Invalid controller type %wZ\n", &Token); + return STATUS_OBJECT_NAME_INVALID; + } + + /* Here the controller can only be either a disk or a CDROM */ + + /* + * Ignore the controller in case we have a 'multi' adapter. + * I guess a similar condition holds for the 'eisa' adapter too... + * + * For SignatureAdapter, as similar for ScsiAdapter, the controller key corresponds + * to the disk target ID. Note that actually, the implementation just ignores the + * target ID, as well as the LUN, and just loops over all the available disks and + * searches for the one having the correct signature. + */ + if ((AdapterType == MultiAdapter /* || AdapterType == EisaAdapter */) && ControllerKey != 0) + { + DPRINT1("%S(%lu) adapter with %S(%lu non-zero), ignored!\n", + AdapterTypes_U[AdapterType], AdapterKey, + ControllerTypes_U[ControllerType], ControllerKey); + ControllerKey = 0; + } + + /* + * Only the 'scsi' adapter supports a direct 'cdrom' controller. + * For the others, we need a 'disk' controller to which a 'cdrom' peripheral can talk to. + */ + if ((AdapterType != ScsiAdapter) && (ControllerType == CdRomController)) + { + DPRINT1("%S(%lu) adapter cannot have a CDROM controller!\n", AdapterTypes_U[AdapterType], AdapterKey); + return STATUS_OBJECT_PATH_INVALID; + } + + /* Check for a valid peripheral */ + p = ArcGetNextTokenU(p, &Token, &PeripheralKey); + if (!p) + { + DPRINT1("%S(%lu)%S(%lu) adapter-controller doesn't have a peripheral!\n", + AdapterTypes_U[AdapterType], AdapterKey, + ControllerTypes_U[ControllerType], ControllerKey); + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + PeripheralType = (PERIPHERAL_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, PeripheralTypes_U); + if (PeripheralType >= PeripheralTypeMax) + { + DPRINT1("Invalid peripheral type %wZ\n", &Token); + return STATUS_OBJECT_NAME_INVALID; + } + + /* + * If we had a 'cdrom' controller already, the corresponding peripheral can only be 'fdisk' + * (see for example the ARC syntax for SCSI CD-ROMs: scsi(x)cdrom(y)fdisk(z) where z == 0). + */ + if ((ControllerType == CdRomController) && (PeripheralType != FDiskPeripheral)) + { + DPRINT1("%S(%lu) controller cannot have a %S(%lu) peripheral! (note that we haven't check whether the adapter was SCSI or not)\n", + ControllerTypes_U[ControllerType], ControllerKey, + PeripheralTypes_U[PeripheralType], PeripheralKey); + return STATUS_OBJECT_PATH_INVALID; + } + + /* For a 'scsi' adapter, the possible peripherals are only 'rdisk' or 'fdisk' */ + if (AdapterType == ScsiAdapter && !(PeripheralType == RDiskPeripheral || PeripheralType == FDiskPeripheral)) + { + DPRINT1("%S(%lu)%S(%lu) SCSI adapter-controller has an invalid peripheral %S(%lu) !\n", + AdapterTypes_U[AdapterType], AdapterKey, + ControllerTypes_U[ControllerType], ControllerKey, + PeripheralTypes_U[PeripheralType], PeripheralKey); + return STATUS_OBJECT_PATH_INVALID; + } + +#if 0 + if (AdapterType == SignatureAdapter && PeripheralKey != 0) + { + DPRINT1("%S(%lu) adapter with %S(%lu non-zero), ignored!\n", + AdapterTypes_U[AdapterType], AdapterKey, + PeripheralTypes_U[PeripheralType], PeripheralKey); + PeripheralKey = 0; + } +#endif + + /* Check for the optional 'partition' specifier */ + q = ArcGetNextTokenU(p, &Token, &PartitionNumber); + if (q && _wcsicmp(Token.Buffer, L"partition") == 0) + { + /* We've got a partition! */ + p = q; + } + else + { + /* + * Either no other ARC token was found, or we've got something else + * (possibly invalid or not)... + */ + PartitionNumber = 0; + } + + // TODO: Check the partition number in case of fdisks and cdroms?? + +Quit: + /* Return the results */ + *ArcNamePath = p; + *pAdapterKey = AdapterKey; + *pControllerKey = ControllerKey; + *pPeripheralKey = PeripheralKey; + *pPartitionNumber = PartitionNumber; + *pAdapterType = AdapterType; + *pControllerType = ControllerType; + *pPeripheralType = PeripheralType; + *pUseSignature = UseSignature; + + return STATUS_SUCCESS; +} + +/* * ArcName: * ARC name (counted string) to be resolved into a NT device name. * The caller should have already delimited it from within an ARC path @@ -434,12 +646,12 @@
/* * ArcNamePath: - * In input, pointer to an ARC path (NULL-terminated) starting by an ARC name - * to be resolved into a NT device name. - * In opposition to ResolveArcNameNtSymLink(), the caller does not have to - * delimit the ARC name from within an ARC path. The real ARC name is deduced - * after parsing the ARC path, and, in output, ArcNamePath points to the - * beginning of the path after the ARC name part. + * In input, pointer to an ARC path (NULL-terminated) starting by an + * ARC name to be resolved into a NT device name. + * In opposition to ResolveArcNameNtSymLink(), the caller does not have + * to delimit the ARC name from within an ARC path. The real ARC name is + * deduced after parsing the ARC path, and, in output, ArcNamePath points + * to the beginning of the path after the ARC name part. * * NtName: * Receives the resolved NT name. The buffer is NULL-terminated. @@ -452,12 +664,10 @@ ResolveArcNameManually( OUT PUNICODE_STRING NtName, IN OUT PCWSTR* ArcNamePath, - IN PPARTLIST PartList OPTIONAL) -{ + IN PPARTLIST PartList) +{ + NTSTATUS Status; HRESULT hr; - WCHAR TokenBuffer[50]; - UNICODE_STRING Token; - PCWSTR p, q; ULONG AdapterKey; ULONG ControllerKey; ULONG PeripheralKey; @@ -465,7 +675,7 @@ ADAPTER_TYPE AdapterType; CONTROLLER_TYPE ControllerType; PERIPHERAL_TYPE PeripheralType; - BOOLEAN UseSignature = FALSE; + BOOLEAN UseSignature;
PDISKENTRY DiskEntry; PPARTENTRY PartEntry = NULL; @@ -478,176 +688,34 @@ NtName->Length = 0; #endif
- /* - * The format of ArcName is: - * adapter(www)[controller(xxx)peripheral(yyy)[partition(zzz)][filepath]] , - * where the [filepath] part is not being parsed. - */ - - RtlInitEmptyUnicodeString(&Token, TokenBuffer, sizeof(TokenBuffer)); - - p = *ArcNamePath; - - /* Retrieve the adapter */ - p = ArcGetNextTokenU(p, &Token, &AdapterKey); - if (!p) - { - DPRINT1("No adapter specified!\n"); - return STATUS_OBJECT_PATH_SYNTAX_BAD; - } - - /* Check for the 'signature()' pseudo-adapter, introduced in Windows 2000 */ - if (_wcsicmp(Token.Buffer, L"signature") == 0) - { - /* - * We've got a signature! Remember this for later, and set the adapter type to SCSI. - * We however check that the rest of the ARC path is valid by parsing the other tokens. - * AdapterKey stores the disk signature value (that holds in a ULONG). - */ - UseSignature = TRUE; - AdapterType = ScsiAdapter; + /* Parse the ARC path */ + Status = ParseArcName(ArcNamePath, + &AdapterKey, + &ControllerKey, + &PeripheralKey, + &PartitionNumber, + &AdapterType, + &ControllerType, + &PeripheralType, + &UseSignature); + if (!NT_SUCCESS(Status)) + return Status; + + // TODO: Check the partition number in case of fdisks and cdroms?? + + /* Check for adapters that don't take any extra controller or peripheral nodes */ + if (AdapterType == NetAdapter || AdapterType == RamdiskAdapter) + { + if (AdapterType == NetAdapter) + { + DPRINT1("%S(%lu) path is not supported!\n", AdapterTypes_U[AdapterType], AdapterKey); + return STATUS_NOT_SUPPORTED; + } + + hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\Device\Ramdisk%lu", AdapterKey); } else - { - /* Check for regular adapters */ - AdapterType = (ADAPTER_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, AdapterTypes_U); - if (AdapterType >= AdapterTypeMax) - { - DPRINT1("Invalid adapter type %wZ\n", &Token); - return STATUS_OBJECT_NAME_INVALID; - } - - /* Check for adapters that don't take any extra controller or peripheral nodes */ - if (AdapterType == NetAdapter || AdapterType == RamdiskAdapter) - { - // if (*p) - // return STATUS_OBJECT_PATH_SYNTAX_BAD; - - if (AdapterType == NetAdapter) - { - DPRINT1("%S(%lu) path is not supported!\n", AdapterTypes_U[AdapterType], AdapterKey); - return STATUS_NOT_SUPPORTED; - } - - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, - L"\Device\Ramdisk%lu", AdapterKey); - goto Quit; - } - } - - /* Here, we have either an 'eisa', a 'scsi/signature', or a 'multi' adapter */ - - /* Check for a valid controller */ - p = ArcGetNextTokenU(p, &Token, &ControllerKey); - if (!p) - { - DPRINT1("%S(%lu) adapter doesn't have a controller!\n", AdapterTypes_U[AdapterType], AdapterKey); - return STATUS_OBJECT_PATH_SYNTAX_BAD; - } - ControllerType = (CONTROLLER_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, ControllerTypes_U); - if (ControllerType >= ControllerTypeMax) - { - DPRINT1("Invalid controller type %wZ\n", &Token); - return STATUS_OBJECT_NAME_INVALID; - } - - /* Here the controller can only be either a disk or a CDROM */ - - /* - * Ignore the controller in case we have a 'multi' adapter. - * I guess a similar condition holds for the 'eisa' adapter too... - * - * For SignatureAdapter, as similar for ScsiAdapter, the controller key corresponds - * to the disk target ID. Note that actually, the implementation just ignores the - * target ID, as well as the LUN, and just loops over all the available disks and - * searches for the one having the correct signature. - */ - if ((AdapterType == MultiAdapter /* || AdapterType == EisaAdapter */) && ControllerKey != 0) - { - DPRINT1("%S(%lu) adapter with %S(%lu non-zero), ignored!\n", - AdapterTypes_U[AdapterType], AdapterKey, - ControllerTypes_U[ControllerType], ControllerKey); - ControllerKey = 0; - } - - /* - * Only the 'scsi' adapter supports a direct 'cdrom' controller. - * For the others, we need a 'disk' controller to which a 'cdrom' peripheral can talk to. - */ - if ((AdapterType != ScsiAdapter) && (ControllerType == CdRomController)) - { - DPRINT1("%S(%lu) adapter cannot have a CDROM controller!\n", AdapterTypes_U[AdapterType], AdapterKey); - return STATUS_OBJECT_PATH_INVALID; - } - - /* Check for a valid peripheral */ - p = ArcGetNextTokenU(p, &Token, &PeripheralKey); - if (!p) - { - DPRINT1("%S(%lu)%S(%lu) adapter-controller doesn't have a peripheral!\n", - AdapterTypes_U[AdapterType], AdapterKey, - ControllerTypes_U[ControllerType], ControllerKey); - return STATUS_OBJECT_PATH_SYNTAX_BAD; - } - PeripheralType = (PERIPHERAL_TYPE)/*ArcMatchTokenU*/ArcMatchToken_UStr(/*Token.Buffer*/&Token, PeripheralTypes_U); - if (PeripheralType >= PeripheralTypeMax) - { - DPRINT1("Invalid peripheral type %wZ\n", &Token); - return STATUS_OBJECT_NAME_INVALID; - } - - /* - * If we had a 'cdrom' controller already, the corresponding peripheral can only be 'fdisk' - * (see for example the ARC syntax for SCSI CD-ROMs: scsi(x)cdrom(y)fdisk(z) where z == 0). - */ - if ((ControllerType == CdRomController) && (PeripheralType != FDiskPeripheral)) - { - DPRINT1("%S(%lu) controller cannot have a %S(%lu) peripheral! (note that we haven't check whether the adapter was SCSI or not)\n", - ControllerTypes_U[ControllerType], ControllerKey, - PeripheralTypes_U[PeripheralType], PeripheralKey); - return STATUS_OBJECT_PATH_INVALID; - } - - /* For a 'scsi' adapter, the possible peripherals are only 'rdisk' or 'fdisk' */ - if (AdapterType == ScsiAdapter && !(PeripheralType == RDiskPeripheral || PeripheralType == FDiskPeripheral)) - { - DPRINT1("%S(%lu)%S(%lu) SCSI adapter-controller has an invalid peripheral %S(%lu) !\n", - AdapterTypes_U[AdapterType], AdapterKey, - ControllerTypes_U[ControllerType], ControllerKey, - PeripheralTypes_U[PeripheralType], PeripheralKey); - return STATUS_OBJECT_PATH_INVALID; - } - -#if 0 - if (AdapterType == SignatureAdapter && PeripheralKey != 0) - { - DPRINT1("%S(%lu) adapter with %S(%lu non-zero), ignored!\n", - AdapterTypes_U[AdapterType], AdapterKey, - PeripheralTypes_U[PeripheralType], PeripheralKey); - PeripheralKey = 0; - } -#endif - - /* Check for the optional 'partition' specifier */ - q = ArcGetNextTokenU(p, &Token, &PartitionNumber); - if (q && _wcsicmp(Token.Buffer, L"partition") == 0) - { - /* We've got a partition! */ - p = q; - } - else - { - /* - * Either no other ARC token was found, or we've got something else - * (possibly invalid or not)... - */ - PartitionNumber = 0; - } - - - // TODO: Check the partition number in case of fdisks and cdroms?? - - if (ControllerType == CdRomController) // and so, AdapterType == ScsiAdapter and PeripheralType == FDiskPeripheral { hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, @@ -718,7 +786,6 @@ return (NTSTATUS)hr; }
- *ArcNamePath = p; return STATUS_SUCCESS; }