|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
4256e2 |
/* Copyright (C) 2013--2016 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/**
|
|
|
dd89bb |
* a simple facility for minimal programs or system libraries
|
|
|
dd89bb |
* with no libc available at the time of invocation, as well
|
|
|
dd89bb |
* as applications using the midipix free-standing development
|
|
|
dd89bb |
* environment.
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* the approach taken by this module to the support of short
|
|
|
dd89bb |
* and long options reflects the above constraint, namely
|
|
|
dd89bb |
* the absence of a callable libc at the time of invocation;
|
|
|
dd89bb |
* there is no intent for interfaces in this module to
|
|
|
dd89bb |
* be POSIXLY correct or otherwise portable. the sole
|
|
|
dd89bb |
* purpose of all functions in this module is to serve
|
|
|
dd89bb |
* internal or otherwise free-standing midipix applications,
|
|
|
dd89bb |
* and their relevance otherwise is accordingly non-existent.
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* all options are encoded in utf-16; note, however, that
|
|
|
dd89bb |
* short options may only use code points that are located
|
|
|
dd89bb |
* in the basic multilingual plane.
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* option values are either required or not allowed altogether,
|
|
|
dd89bb |
* and the first character of an option value may not be a hyphen.
|
|
|
dd89bb |
* if you need the first character of an option value to be a
|
|
|
dd89bb |
* hyphen, then make sure you escape it somehow (for instance by
|
|
|
dd89bb |
* enclosing it in quotation marks).
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* a short option and its value must reside in two separate
|
|
|
dd89bb |
* argv[] elements (in other words: -ooutput is illegal).
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* a long option and its value must reside in the same argv[]
|
|
|
dd89bb |
* element and be separated by a single equal sign.
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* Examples of valid options and option values:
|
|
|
dd89bb |
* --------------------------------------------
|
|
|
dd89bb |
* -o
|
|
|
dd89bb |
* -o value
|
|
|
dd89bb |
* --long-option-with-no-value
|
|
|
dd89bb |
* --long-option=value
|
|
|
dd89bb |
**/
|
|
|
dd89bb |
|
|
|
dd89bb |
#define HYPHEN 0x2D
|
|
|
dd89bb |
#define EQUAL_SIGN 0x3D
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __inline__ __fastcall __is_bmp_code_point(wchar16_t code_point)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return (((code_point >= 0x0000) && (code_point < 0xD800)) \
|
|
|
188aac |
|| (code_point >= 0xE000));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __inline__ __fastcall __is_last_program_option(
|
|
|
dd89bb |
__in nt_program_option * option)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return (!(option->short_name_code))
|
|
|
dd89bb |
&& (!(option->long_name))
|
|
|
dd89bb |
&& (!(option->long_name_hash));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __fastcall __is_short_option(wchar16_t * wch)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return ((wch) && (*wch == HYPHEN)
|
|
|
dd89bb |
&& __is_bmp_code_point(*++wch)
|
|
|
dd89bb |
&& (*++wch == 0));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __fastcall __is_long_option(wchar16_t * wch)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return ((wch) && (*wch == HYPHEN)
|
|
|
dd89bb |
&& (++wch) && (*wch == HYPHEN)
|
|
|
dd89bb |
&& (*++wch));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __fastcall __is_last_option_argument(wchar16_t * wch)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return ((wch) && (*wch == HYPHEN)
|
|
|
dd89bb |
&& (*++wch == HYPHEN)
|
|
|
dd89bb |
&& (*++wch == 0));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static uint32_t __fastcall __compute_crc32_utf16_str(
|
|
|
dd89bb |
__in const uint32_t * crc32_table,
|
|
|
dd89bb |
__in wchar16_t * wch)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
uint32_t crc32;
|
|
|
dd89bb |
unsigned char * byte_buffer;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* crc32 hash... */
|
|
|
dd89bb |
crc32 = 0 ^ 0xFFFFFFFF;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* initialize byte_buffer */
|
|
|
dd89bb |
byte_buffer = (unsigned char *)wch;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* iterate */
|
|
|
dd89bb |
while (*byte_buffer) {
|
|
|
dd89bb |
/* two bytes at a time */
|
|
|
dd89bb |
crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF];
|
|
|
dd89bb |
byte_buffer++;
|
|
|
dd89bb |
crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF];
|
|
|
dd89bb |
byte_buffer++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return crc32;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static uint32_t __fastcall __compute_crc32_long_option_name(
|
|
|
dd89bb |
__in const uint32_t * crc32_table,
|
|
|
dd89bb |
__in wchar16_t * wch_arg,
|
|
|
dd89bb |
__in wchar16_t * wch_termination)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
uint32_t crc32;
|
|
|
dd89bb |
unsigned char * byte_buffer;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* crc32 hash... */
|
|
|
dd89bb |
crc32 = 0 ^ 0xFFFFFFFF;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* initialize byte_buffer */
|
|
|
dd89bb |
byte_buffer = (unsigned char *)wch_arg;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* iterate */
|
|
|
dd89bb |
while ((uintptr_t)byte_buffer < (uintptr_t)wch_termination) {
|
|
|
dd89bb |
/* two bytes at a time */
|
|
|
dd89bb |
crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF];
|
|
|
dd89bb |
byte_buffer++;
|
|
|
dd89bb |
crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF];
|
|
|
dd89bb |
byte_buffer++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return crc32;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static void __fastcall __init_cmd_option_meta_utf16(
|
|
|
dd89bb |
__in nt_cmd_option_meta_utf16 * cmd_opt_meta)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
cmd_opt_meta->short_name = (wchar16_t *)0;
|
|
|
dd89bb |
cmd_opt_meta->short_name_code = 0;
|
|
|
dd89bb |
cmd_opt_meta->long_name = (wchar16_t *)0;
|
|
|
dd89bb |
cmd_opt_meta->long_name_hash = 0;
|
|
|
dd89bb |
cmd_opt_meta->value = (wchar16_t *)0;
|
|
|
dd89bb |
cmd_opt_meta->value_hash = 0;
|
|
|
dd89bb |
cmd_opt_meta->argv_index = 0;
|
|
|
dd89bb |
cmd_opt_meta->flags = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
return;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_short_option_meta_utf16(
|
|
|
dd89bb |
__in const uint32_t * crc32_table,
|
|
|
dd89bb |
__in wchar16_t option_name,
|
|
|
dd89bb |
__in wchar16_t * argv[],
|
|
|
dd89bb |
__out nt_cmd_option_meta_utf16 * cmd_opt_meta)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int idx;
|
|
|
dd89bb |
wchar16_t * wch;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!crc32_table)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_1;
|
|
|
dd89bb |
else if (!option_name)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_2;
|
|
|
dd89bb |
else if (!argv)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_3;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* initialize cmd_opt_meta */
|
|
|
dd89bb |
__init_cmd_option_meta_utf16(cmd_opt_meta);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 1: attempt to find the short option in argv[] */
|
|
|
dd89bb |
idx = 0;
|
|
|
dd89bb |
while (argv[idx] && (!cmd_opt_meta->short_name_code)) {
|
|
|
dd89bb |
wch = argv[idx];
|
|
|
dd89bb |
|
|
|
dd89bb |
/* is this our option? */
|
|
|
dd89bb |
if ((*wch == HYPHEN)
|
|
|
dd89bb |
&& (*++wch == option_name)
|
|
|
dd89bb |
&& (*++wch == 0)) {
|
|
|
dd89bb |
|
|
|
dd89bb |
/* found it, get ready to hash the value */
|
|
|
dd89bb |
cmd_opt_meta->short_name_code = option_name;
|
|
|
dd89bb |
cmd_opt_meta->short_name = argv[idx];
|
|
|
dd89bb |
cmd_opt_meta->argv_index = idx;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* if the next argument is also an option (or is null), just exit */
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
if ((!argv[idx]) || (*argv[idx] == HYPHEN))
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 2: hash the value */
|
|
|
dd89bb |
cmd_opt_meta->value = argv[idx];
|
|
|
dd89bb |
cmd_opt_meta->value_hash =
|
|
|
dd89bb |
__compute_crc32_utf16_str(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
argv[idx]);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_long_option_meta_utf16(
|
|
|
dd89bb |
__in const uint32_t * crc32_table,
|
|
|
dd89bb |
__in wchar16_t * option_name,
|
|
|
dd89bb |
__in uint32_t option_name_hash __optional,
|
|
|
dd89bb |
__in wchar16_t * argv[],
|
|
|
dd89bb |
__out nt_cmd_option_meta_utf16 * cmd_opt_meta)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
/**
|
|
|
dd89bb |
* option_name must always include the two-hyphen prefix;
|
|
|
dd89bb |
* and the option value must be preceded by an equal sign.
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* the only valid long option forms in argv[] are therefore:
|
|
|
dd89bb |
* --long-option
|
|
|
dd89bb |
* --long-option=value
|
|
|
dd89bb |
**/
|
|
|
dd89bb |
|
|
|
dd89bb |
int idx;
|
|
|
dd89bb |
uint32_t crc32;
|
|
|
dd89bb |
wchar16_t * wch;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (!crc32_table)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_1;
|
|
|
dd89bb |
else if ((!option_name) && (!option_name_hash))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
else if ((option_name) && (option_name_hash))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
else if (!argv)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_4;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* initialize cmd_opt_meta */
|
|
|
dd89bb |
__init_cmd_option_meta_utf16(cmd_opt_meta);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 1: crc32 of the target option_name */
|
|
|
dd89bb |
if (option_name_hash)
|
|
|
dd89bb |
crc32 = option_name_hash;
|
|
|
dd89bb |
else
|
|
|
dd89bb |
option_name_hash =
|
|
|
dd89bb |
__compute_crc32_utf16_str(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
option_name);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 2: attempt to find the long option in argv[] */
|
|
|
dd89bb |
idx = 0;
|
|
|
dd89bb |
while (argv[idx] && (!cmd_opt_meta->value)) {
|
|
|
dd89bb |
wch = argv[idx];
|
|
|
dd89bb |
|
|
|
dd89bb |
if (__is_long_option(wch)) {
|
|
|
dd89bb |
/* find the equal sign or null termination */
|
|
|
dd89bb |
while ((*wch) && (*wch != EQUAL_SIGN))
|
|
|
dd89bb |
wch++;
|
|
|
dd89bb |
|
|
|
dd89bb |
crc32 = __compute_crc32_long_option_name(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
argv[idx],
|
|
|
dd89bb |
wch);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (crc32 == option_name_hash) {
|
|
|
dd89bb |
/* found it, get ready to hash the value */
|
|
|
dd89bb |
cmd_opt_meta->long_name_hash = option_name_hash;
|
|
|
dd89bb |
cmd_opt_meta->long_name = argv[idx];
|
|
|
dd89bb |
cmd_opt_meta->argv_index = idx;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (*wch)
|
|
|
dd89bb |
/* skip the equal sign */
|
|
|
dd89bb |
wch++;
|
|
|
dd89bb |
|
|
|
dd89bb |
cmd_opt_meta->value = wch;
|
|
|
dd89bb |
} else
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (cmd_opt_meta->value)
|
|
|
dd89bb |
cmd_opt_meta->value_hash =
|
|
|
dd89bb |
__compute_crc32_utf16_str(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
cmd_opt_meta->value);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_validate_program_options(
|
|
|
dd89bb |
__in const uint32_t * crc32_table,
|
|
|
dd89bb |
__in wchar16_t * argv[],
|
|
|
dd89bb |
__in nt_program_option * options[],
|
|
|
dd89bb |
__in nt_program_options_meta * options_meta)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int idx;
|
|
|
dd89bb |
int idx_arg;
|
|
|
dd89bb |
int idx_option;
|
|
|
dd89bb |
int idx_max;
|
|
|
dd89bb |
uint32_t crc32;
|
|
|
dd89bb |
nt_program_option * option;
|
|
|
dd89bb |
wchar16_t * parg;
|
|
|
dd89bb |
wchar16_t * pvalue;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (!crc32_table)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_1;
|
|
|
dd89bb |
else if (!argv)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_2;
|
|
|
dd89bb |
else if (!options)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_3;
|
|
|
dd89bb |
else if (!options_meta)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_4;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 1: validate options[] hash the long option names */
|
|
|
dd89bb |
idx = 0;
|
|
|
dd89bb |
idx_option = 0;
|
|
|
dd89bb |
option = options[0];
|
|
|
dd89bb |
pvalue = (wchar16_t *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
while (!__is_last_program_option(option)) {
|
|
|
dd89bb |
if (option->short_name_code) {
|
|
|
dd89bb |
if (!(__is_bmp_code_point(option->short_name_code))) {
|
|
|
dd89bb |
options_meta->idx_invalid_short_name = idx;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (option->long_name) {
|
|
|
dd89bb |
if (!(__is_long_option(option->long_name))) {
|
|
|
dd89bb |
options_meta->idx_invalid_long_name = idx;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* update the long name hash (unconditionally) */
|
|
|
dd89bb |
option->long_name_hash =
|
|
|
dd89bb |
__compute_crc32_utf16_str(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
option->long_name);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
option++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* book keeping */
|
|
|
dd89bb |
idx_max = idx;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* step 2: validate argv[] */
|
|
|
dd89bb |
parg = argv[0];
|
|
|
dd89bb |
idx_arg = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
while ((parg) && (!(__is_last_option_argument(parg)))) {
|
|
|
dd89bb |
if (__is_short_option(parg)) {
|
|
|
dd89bb |
idx = 0;
|
|
|
dd89bb |
idx_option = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
while ((idx < idx_max) && (!idx_option)) {
|
|
|
dd89bb |
option = options[idx];
|
|
|
dd89bb |
|
|
|
dd89bb |
if (*(parg+1) == option->short_name_code)
|
|
|
dd89bb |
idx_option = idx;
|
|
|
dd89bb |
else
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (idx == idx_max) {
|
|
|
dd89bb |
options_meta->idx_invalid_argument = idx_arg;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
/* get ready for the next element (or value) */
|
|
|
dd89bb |
parg++;
|
|
|
dd89bb |
idx_arg++;
|
|
|
dd89bb |
pvalue = parg;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
} else if (__is_long_option(parg)) {
|
|
|
dd89bb |
idx = 0;
|
|
|
dd89bb |
idx_option = 0;
|
|
|
dd89bb |
/* find the equal sign or null termination */
|
|
|
dd89bb |
pvalue = parg;
|
|
|
dd89bb |
while ((*pvalue) && (*pvalue != EQUAL_SIGN))
|
|
|
dd89bb |
pvalue++;
|
|
|
dd89bb |
|
|
|
dd89bb |
while ((idx < idx_max) && (!idx_option)) {
|
|
|
dd89bb |
option = options[idx];
|
|
|
dd89bb |
crc32 = __compute_crc32_long_option_name(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
parg,
|
|
|
dd89bb |
pvalue);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (crc32 == option->long_name_hash)
|
|
|
dd89bb |
idx_option = idx;
|
|
|
dd89bb |
else
|
|
|
dd89bb |
idx++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (idx == idx_max) {
|
|
|
dd89bb |
options_meta->idx_invalid_argument = idx_arg;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
if (*pvalue != EQUAL_SIGN)
|
|
|
dd89bb |
/* skip the equal sign */
|
|
|
dd89bb |
pvalue++;
|
|
|
dd89bb |
pvalue = (wchar16_t *)0;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validate the occurrence */
|
|
|
dd89bb |
if (idx_option) {
|
|
|
188aac |
if (option->flags & NT_OPTION_ALLOWED_ONCE) {
|
|
|
dd89bb |
if (option->option_count) {
|
|
|
dd89bb |
options_meta->idx_invalid_argument
|
|
|
dd89bb |
= idx_arg;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
option->option_count++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
188aac |
if (option->flags & NT_OPTION_VALUE_REQUIRED) {
|
|
|
dd89bb |
if ((!(*pvalue)) || (*pvalue == HYPHEN)) {
|
|
|
dd89bb |
options_meta->idx_missing_option_value
|
|
|
dd89bb |
= idx_arg;
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
option->value = pvalue;
|
|
|
dd89bb |
option->value_hash =
|
|
|
dd89bb |
__compute_crc32_utf16_str(
|
|
|
dd89bb |
crc32_table,
|
|
|
dd89bb |
option->value);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
parg++;
|
|
|
dd89bb |
idx_arg++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|