1  /* $Id: USBFilter.cpp 100772 20230801 17:34:48Z vboxsync $ */


2  /** @file


3  * VirtualBox USB filter abstraction.


4  */


5 


6  /*


7  * Copyright (C) 20072023 Oracle and/or its affiliates.


8  *


9  * This file is part of VirtualBox base platform packages, as


10  * available from https://www.virtualbox.org.


11  *


12  * This program is free software; you can redistribute it and/or


13  * modify it under the terms of the GNU General Public License


14  * as published by the Free Software Foundation, in version 3 of the


15  * License.


16  *


17  * This program is distributed in the hope that it will be useful, but


18  * WITHOUT ANY WARRANTY; without even the implied warranty of


19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU


20  * General Public License for more details.


21  *


22  * You should have received a copy of the GNU General Public License


23  * along with this program; if not, see <https://www.gnu.org/licenses>.


24  *


25  * The contents of this file may alternatively be used under the terms


26  * of the Common Development and Distribution License Version 1.0


27  * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included


28  * in the VirtualBox distribution, in which case the provisions of the


29  * CDDL are applicable instead of those of the GPL.


30  *


31  * You may elect to license modified versions of this file under the


32  * terms and conditions of either the GPL or the CDDL or both.


33  *


34  * SPDXLicenseIdentifier: GPL3.0only OR CDDL1.0


35  */


36 


37 


38  /*********************************************************************************************************************************


39  * Header Files *


40  *********************************************************************************************************************************/


41  #include <VBox/usbfilter.h>


42  #include <VBox/usblib.h>


43  #include <VBox/err.h>


44  #include <VBox/log.h>


45  #include <iprt/string.h>


46  #include <iprt/assert.h>


47  #include <iprt/ctype.h>


48 


49 


50  /** @todo split this up for the sake of device drivers and such. */


51 


52 


53  /**


54  * Initializes an USBFILTER structure.


55  *


56  * @param pFilter The filter to initialize.


57  * @param enmType The filter type. If not valid, the filter will not


58  * be properly initialized and all other calls will fail.


59  */


60  USBLIB_DECL(void) USBFilterInit(PUSBFILTER pFilter, USBFILTERTYPE enmType)


61  {


62  memset(pFilter, 0, sizeof(*pFilter));


63  AssertReturnVoid(enmType > USBFILTERTYPE_INVALID && enmType < USBFILTERTYPE_END);


64  pFilter>u32Magic = USBFILTER_MAGIC;


65  pFilter>enmType = enmType;


66  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


67  pFilter>aFields[i].enmMatch = USBFILTERMATCH_IGNORE;


68  }


69 


70 


71  /**


72  * Make a clone of the specified filter.


73  *


74  * @param pFilter The target filter.


75  * @param pToClone The source filter.


76  */


77  USBLIB_DECL(void) USBFilterClone(PUSBFILTER pFilter, PCUSBFILTER pToClone)


78  {


79  memcpy(pFilter, pToClone, sizeof(*pToClone));


80  }


81 


82 


83  /**


84  * Deletes (invalidates) an USBFILTER structure.


85  *


86  * @param pFilter The filter to delete.


87  */


88  USBLIB_DECL(void) USBFilterDelete(PUSBFILTER pFilter)


89  {


90  pFilter>u32Magic = ~USBFILTER_MAGIC;


91  pFilter>enmType = USBFILTERTYPE_INVALID;


92  pFilter>offCurEnd = 0xfffff;


93  }


94 


95 


96  /**


97  * Skips blanks.


98  *


99  * @returns Next nonblank char in the string.


100  * @param psz The string.


101  */


102  DECLINLINE(const char *) usbfilterSkipBlanks(const char *psz)


103  {


104  while (RT_C_IS_BLANK(*psz))


105  psz++;


106  return psz;


107  }


108 


109 


110  /**


111  * Worker for usbfilterReadNumber that parses a hexadecimal number.


112  *


113  * @returns Same as usbfilterReadNumber, except for VERR_NO_DIGITS.


114  * @param pszExpr Where to start converting, first char is a valid digit.


115  * @param ppszExpr See usbfilterReadNumber.


116  * @param pu16Val See usbfilterReadNumber.


117  */


118  static int usbfilterReadNumberHex(const char *pszExpr, const char **ppszExpr, uint16_t *pu16Val)


119  {


120  int rc = VINF_SUCCESS;


121  uint32_t u32 = 0;


122  do


123  {


124  unsigned uDigit = *pszExpr >= 'a' && *pszExpr <= 'f'


125  ? *pszExpr  'a' + 10


126  : *pszExpr >= 'A' && *pszExpr <= 'F'


127  ? *pszExpr  'A' + 10


128  : *pszExpr  '0';


129  if (uDigit >= 16)


130  break;


131  u32 *= 16;


132  u32 += uDigit;


133  if (u32 > UINT16_MAX)


134  rc = VWRN_NUMBER_TOO_BIG;


135  } while (*++pszExpr);


136 


137  *ppszExpr = usbfilterSkipBlanks(pszExpr);


138  *pu16Val = rc == VINF_SUCCESS ? u32 : UINT16_MAX;


139  return VINF_SUCCESS;


140  }


141 


142 


143  /**


144  * Worker for usbfilterReadNumber that parses a decimal number.


145  *


146  * @returns Same as usbfilterReadNumber, except for VERR_NO_DIGITS.


147  * @param pszExpr Where to start converting, first char is a valid digit.


148  * @param uBase The base  8 or 16.


149  * @param ppszExpr See usbfilterReadNumber.


150  * @param pu16Val See usbfilterReadNumber.


151  */


152  static int usbfilterReadNumberDecimal(const char *pszExpr, unsigned uBase, const char **ppszExpr, uint16_t *pu16Val)


153  {


154  int rc = VINF_SUCCESS;


155  uint32_t u32 = 0;


156  do


157  {


158  unsigned uDigit = *pszExpr  '0';


159  if (uDigit >= uBase)


160  break;


161  u32 *= uBase;


162  u32 += uDigit;


163  if (u32 > UINT16_MAX)


164  rc = VWRN_NUMBER_TOO_BIG;


165  } while (*++pszExpr);


166 


167  *ppszExpr = usbfilterSkipBlanks(pszExpr);


168  *pu16Val = rc == VINF_SUCCESS ? u32 : UINT16_MAX;


169  return rc;


170  }


171 


172 


173  /**


174  * Reads a number from a numeric expression.


175  *


176  * @returns IPRT status code.


177  * @retval VINF_SUCCESS if all is fine. *ppszExpr and *pu16Val are updated.


178  * @retval VWRN_NUMBER_TOO_BIG if the number exceeds unsigned 16bit, both *ppszExpr and *pu16Val are updated.


179  * @retval VERR_NO_DIGITS if there aren't any digits.


180  *


181  * @param ppszExpr Pointer to the current expression pointer.


182  * This is advanced past the expression and trailing blanks on success.


183  * @param pu16Val Where to store the value on success.


184  */


185  static int usbfilterReadNumber(const char **ppszExpr, uint16_t *pu16Val)


186  {


187  const char *pszExpr = usbfilterSkipBlanks(*ppszExpr);


188  if (!RT_C_IS_DIGIT(*pszExpr))


189  return VERR_NO_DIGITS;


190 


191  if (*pszExpr == '0')


192  {


193  if (pszExpr[1] == 'x'  pszExpr[1] == 'X')


194  {


195  if (!RT_C_IS_XDIGIT(pszExpr[2]))


196  return VERR_NO_DIGITS;


197  return usbfilterReadNumberHex(pszExpr + 2, ppszExpr, pu16Val);


198  }


199  if (RT_C_IS_ODIGIT(pszExpr[1]))


200  return usbfilterReadNumberDecimal(pszExpr + 1, 8, ppszExpr, pu16Val);


201  /* Solitary 0! */


202  if (RT_C_IS_DIGIT(pszExpr[1]))


203  return VERR_NO_DIGITS;


204  }


205  return usbfilterReadNumberDecimal(pszExpr, 10, ppszExpr, pu16Val);


206  }


207 


208 


209  /**


210  * Validates a numeric expression.


211  *


212  * @returns VBox status code.


213  * @retval VINF_SUCCESS if valid.


214  * @retval VERR_INVALID_PARAMETER if invalid.


215  * @retval VERR_NO_DIGITS if some expression is short of digits.


216  *


217  * @param pszExpr The numeric expression.


218  */


219  static int usbfilterValidateNumExpression(const char *pszExpr)


220  {


221  /*


222  * An empty expression is fine.


223  */


224  if (!*pszExpr)


225  return VINF_SUCCESS;


226 


227  /*


228  * The string format is: "int:((<m>)([<m>][<n>]))(,(<m>)([<m>][<n>]))*"


229  * where <m> and <n> are numbers in decimal, hex (0xNNN) or octal (0NNN).


230  * Spaces are allowed around <m> and <n>.


231  */


232  unsigned cSubExpressions = 0;


233  while (*pszExpr)


234  {


235  if (!strncmp(pszExpr, RT_STR_TUPLE("int:")))


236  pszExpr += strlen("int:");


237 


238  /*


239  * Skip remnants of the previous expression and any empty expressions.


240  * ('' is the expression separator.)


241  */


242  while (*pszExpr == ''  RT_C_IS_BLANK(*pszExpr)  *pszExpr == '('  *pszExpr == ')')


243  pszExpr++;


244  if (!*pszExpr)


245  break;


246 


247  /*


248  * Parse the expression.


249  */


250  int rc;


251  uint16_t u16First = 0;


252  uint16_t u16Last = 0;


253  if (*pszExpr == '')


254  {


255  /* N */


256  pszExpr++;


257  rc = usbfilterReadNumber(&pszExpr, &u16Last);


258  }


259  else


260  {


261  /* M or M,N or MN or M */


262  rc = usbfilterReadNumber(&pszExpr, &u16First);


263  if (RT_SUCCESS(rc))


264  {


265  pszExpr = usbfilterSkipBlanks(pszExpr);


266  if (*pszExpr == '')


267  {


268  pszExpr++;


269  if (*pszExpr) /* MN */


270  rc = usbfilterReadNumber(&pszExpr, &u16Last);


271  else /* M */


272  u16Last = UINT16_MAX;


273  }


274  else if (*pszExpr == ',')


275  {


276  /* M,N */


277  pszExpr++;


278  rc = usbfilterReadNumber(&pszExpr, &u16Last);


279  }


280  else


281  {


282  /* M */


283  u16Last = u16First;


284  }


285  }


286  }


287  if (RT_FAILURE(rc))


288  return rc;


289 


290  /*


291  * We should either be at the end of the string, at an expression separator (),


292  * or at the end of an interval filter (')').


293  */


294  if (*pszExpr && *pszExpr != '' && *pszExpr != ')')


295  return VERR_INVALID_PARAMETER;


296 


297  cSubExpressions++;


298  }


299 


300  return cSubExpressions ? VINF_SUCCESS : VERR_INVALID_PARAMETER;


301  }


302 


303 


304  /**


305  * Validates a string pattern.


306  *


307  * @returns VBox status code.


308  * @retval VINF_SUCCESS if valid.


309  * @retval VERR_INVALID_PARAMETER if invalid.


310  *


311  * @param psz The string pattern.


312  */


313  static int usbfilterValidateStringPattern(const char *psz)


314  {


315  /*


316  * This is only becomes important if we start doing


317  * sets ([09]) and such like.


318  */


319  RT_NOREF1(psz);


320  return VINF_SUCCESS;


321  }


322 


323 


324  /**


325  * Thoroughly validates the USB Filter.


326  *


327  * @returns Appropriate VBox status code.


328  * @param pFilter The filter to validate.


329  */


330  USBLIB_DECL(int) USBFilterValidate(PCUSBFILTER pFilter)


331  {


332  if (!RT_VALID_PTR(pFilter))


333  return VERR_INVALID_POINTER;


334 


335  if (pFilter>u32Magic != USBFILTER_MAGIC)


336  return VERR_INVALID_MAGIC;


337 


338  if ( pFilter>enmType <= USBFILTERTYPE_INVALID


339   pFilter>enmType >= USBFILTERTYPE_END)


340  {


341  Log(("USBFilter: %p  enmType=%d!\n", pFilter, pFilter>enmType));


342  return VERR_INVALID_PARAMETER;


343  }


344 


345  if (pFilter>offCurEnd >= sizeof(pFilter>achStrTab))


346  {


347  Log(("USBFilter: %p  offCurEnd=%#x!\n", pFilter, pFilter>offCurEnd));


348  return VERR_INVALID_PARAMETER;


349  }


350 


351  /* Validate that string value offsets are inside the string table. */


352  for (uint32_t i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


353  {


354  if ( USBFilterIsMethodUsingStringValue((USBFILTERMATCH)pFilter>aFields[i].enmMatch)


355  && pFilter>aFields[i].u16Value > pFilter>offCurEnd)


356  {


357  Log(("USBFilter: %p  bad offset=%#x\n", pFilter, pFilter>aFields[i].u16Value));


358  return VERR_INVALID_PARAMETER;


359  }


360  }


361 


362  /*


363  * Validate the string table.


364  */


365  if (pFilter>achStrTab[0])


366  {


367  Log(("USBFilter: %p  bad null string\n", pFilter));


368  return VERR_INVALID_PARAMETER;


369  }


370 


371  const char *psz = &pFilter>achStrTab[1];


372  while (psz < &pFilter>achStrTab[pFilter>offCurEnd])


373  {


374  const char *pszEnd = RTStrEnd(psz, &pFilter>achStrTab[sizeof(pFilter>achStrTab)]  psz);


375  if (!pszEnd)


376  {


377  Log(("USBFilter: %p  string at %#x isn't terminated!\n",


378  pFilter, psz  &pFilter>achStrTab[0]));


379  return VERR_INVALID_PARAMETER;


380  }


381 


382  uint16_t off = (uint16_t)(uintptr_t)(psz  &pFilter>achStrTab[0]);


383  unsigned i;


384  for (i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


385  if ( USBFilterIsMethodUsingStringValue((USBFILTERMATCH)pFilter>aFields[i].enmMatch)


386  && pFilter>aFields[i].u16Value == off)


387  break;


388  if (i >= RT_ELEMENTS(pFilter>aFields))


389  {


390  Log(("USBFilter: %p  string at %#x isn't used by anyone! (%s)\n",


391  pFilter, psz  &pFilter>achStrTab[0], psz));


392  return VERR_INVALID_PARAMETER;


393  }


394 


395  psz = pszEnd + 1;


396  }


397 


398  if ((uintptr_t)(psz  &pFilter>achStrTab[0]  1) != pFilter>offCurEnd)


399  {


400  Log(("USBFilter: %p  offCurEnd=%#x currently at %#x\n",


401  pFilter, pFilter>offCurEnd, psz  &pFilter>achStrTab[0]  1));


402  return VERR_INVALID_PARAMETER;


403  }


404 


405  while (psz < &pFilter>achStrTab[sizeof(pFilter>achStrTab)])


406  {


407  if (*psz)


408  {


409  Log(("USBFilter: %p  str tab isn't zero padded! %#x: %c\n",


410  pFilter, psz  &pFilter>achStrTab[0], *psz));


411  return VERR_INVALID_PARAMETER;


412  }


413  psz++;


414  }


415 


416 


417  /*


418  * Validate the fields.


419  */


420  int rc;


421  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


422  {


423  switch (pFilter>aFields[i].enmMatch)


424  {


425  case USBFILTERMATCH_IGNORE:


426  case USBFILTERMATCH_PRESENT:


427  if (pFilter>aFields[i].u16Value)


428  {


429  Log(("USBFilter: %p  #%d/%d u16Value=%d expected 0!\n",


430  pFilter, i, pFilter>aFields[i].enmMatch, pFilter>aFields[i].u16Value));


431  return VERR_INVALID_PARAMETER;


432  }


433  break;


434 


435  case USBFILTERMATCH_NUM_EXACT:


436  case USBFILTERMATCH_NUM_EXACT_NP:


437  if (!USBFilterIsNumericField((USBFILTERIDX)i))


438  {


439  Log(("USBFilter: %p  #%d / %d  not numeric field\n",


440  pFilter, i, pFilter>aFields[i].enmMatch));


441  return VERR_INVALID_PARAMETER;


442  }


443  break;


444 


445  case USBFILTERMATCH_NUM_EXPRESSION:


446  case USBFILTERMATCH_NUM_EXPRESSION_NP:


447  if (!USBFilterIsNumericField((USBFILTERIDX)i))


448  {


449  Log(("USBFilter: %p  #%d / %d  not numeric field\n",


450  pFilter, i, pFilter>aFields[i].enmMatch));


451  return VERR_INVALID_PARAMETER;


452  }


453  if ( pFilter>aFields[i].u16Value >= pFilter>offCurEnd


454  && pFilter>offCurEnd)


455  {


456  Log(("USBFilter: %p  #%d / %d  off=%#x max=%#x\n",


457  pFilter, i, pFilter>aFields[i].enmMatch, pFilter>aFields[i].u16Value, pFilter>offCurEnd));


458  return VERR_INVALID_PARAMETER;


459  }


460  psz = &pFilter>achStrTab[pFilter>aFields[i].u16Value];


461  rc = usbfilterValidateNumExpression(psz);


462  if (RT_FAILURE(rc))


463  {


464  Log(("USBFilter: %p  #%d / %d  bad num expr: %s (rc=%Rrc)\n",


465  pFilter, i, pFilter>aFields[i].enmMatch, psz, rc));


466  return rc;


467  }


468  break;


469 


470  case USBFILTERMATCH_STR_EXACT:


471  case USBFILTERMATCH_STR_EXACT_NP:


472  if (!USBFilterIsStringField((USBFILTERIDX)i))


473  {


474  Log(("USBFilter: %p  #%d / %d  not string field\n",


475  pFilter, i, pFilter>aFields[i].enmMatch));


476  return VERR_INVALID_PARAMETER;


477  }


478  if ( pFilter>aFields[i].u16Value >= pFilter>offCurEnd


479  && pFilter>offCurEnd)


480  {


481  Log(("USBFilter: %p  #%d / %d  off=%#x max=%#x\n",


482  pFilter, i, pFilter>aFields[i].enmMatch, pFilter>aFields[i].u16Value, pFilter>offCurEnd));


483  return VERR_INVALID_PARAMETER;


484  }


485  break;


486 


487  case USBFILTERMATCH_STR_PATTERN:


488  case USBFILTERMATCH_STR_PATTERN_NP:


489  if (!USBFilterIsStringField((USBFILTERIDX)i))


490  {


491  Log(("USBFilter: %p  #%d / %d  not string field\n",


492  pFilter, i, pFilter>aFields[i].enmMatch));


493  return VERR_INVALID_PARAMETER;


494  }


495  if ( pFilter>aFields[i].u16Value >= pFilter>offCurEnd


496  && pFilter>offCurEnd)


497  {


498  Log(("USBFilter: %p  #%d / %d  off=%#x max=%#x\n",


499  pFilter, i, pFilter>aFields[i].enmMatch, pFilter>aFields[i].u16Value, pFilter>offCurEnd));


500  return VERR_INVALID_PARAMETER;


501  }


502  psz = &pFilter>achStrTab[pFilter>aFields[i].u16Value];


503  rc = usbfilterValidateStringPattern(psz);


504  if (RT_FAILURE(rc))


505  {


506  Log(("USBFilter: %p  #%d / %d  bad string pattern: %s (rc=%Rrc)\n",


507  pFilter, i, pFilter>aFields[i].enmMatch, psz, rc));


508  return rc;


509  }


510  break;


511 


512  default:


513  Log(("USBFilter: %p  #%d enmMatch=%d!\n", pFilter, i, pFilter>aFields[i].enmMatch));


514  return VERR_INVALID_PARAMETER;


515  }


516  }


517 


518  return VINF_SUCCESS;


519  }


520 


521 


522  /**


523  * Find the specified field in the string table.


524  *


525  * @returns Pointer to the string in the string table on success.


526  * NULL if the field is invalid or it doesn't have a string value.


527  * @param pFilter The filter.


528  * @param enmFieldIdx The field index.


529  */


530  DECLINLINE(const char *) usbfilterGetString(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


531  {


532  if ((unsigned)enmFieldIdx < (unsigned)USBFILTERIDX_END)


533  {


534  switch (pFilter>aFields[enmFieldIdx].enmMatch)


535  {


536  case USBFILTERMATCH_NUM_EXPRESSION:


537  case USBFILTERMATCH_NUM_EXPRESSION_NP:


538  case USBFILTERMATCH_STR_EXACT:


539  case USBFILTERMATCH_STR_EXACT_NP:


540  case USBFILTERMATCH_STR_PATTERN:


541  case USBFILTERMATCH_STR_PATTERN_NP:


542  Assert(pFilter>aFields[enmFieldIdx].u16Value < sizeof(pFilter>achStrTab));


543  return &pFilter>achStrTab[pFilter>aFields[enmFieldIdx].u16Value];


544 


545  default:


546  AssertMsgFailed(("%d\n", pFilter>aFields[enmFieldIdx].enmMatch));


547  case USBFILTERMATCH_IGNORE:


548  case USBFILTERMATCH_PRESENT:


549  case USBFILTERMATCH_NUM_EXACT:


550  case USBFILTERMATCH_NUM_EXACT_NP:


551  break;


552  }


553  }


554  return NULL;


555  }


556 


557 


558  /**


559  * Gets a number value of a field.


560  *


561  * The field must contain a numeric value.


562  *


563  * @returns The field value on success, 1 on failure (invalid input / not numeric).


564  * @param pFilter The filter.


565  * @param enmFieldIdx The field index.


566  */


567  DECLINLINE(int) usbfilterGetNum(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


568  {


569  if ((unsigned)enmFieldIdx < (unsigned)USBFILTERIDX_END)


570  {


571  switch (pFilter>aFields[enmFieldIdx].enmMatch)


572  {


573  case USBFILTERMATCH_NUM_EXACT:


574  case USBFILTERMATCH_NUM_EXACT_NP:


575  return pFilter>aFields[enmFieldIdx].u16Value;


576 


577  default:


578  AssertMsgFailed(("%d\n", pFilter>aFields[enmFieldIdx].enmMatch));


579  case USBFILTERMATCH_IGNORE:


580  case USBFILTERMATCH_PRESENT:


581  case USBFILTERMATCH_NUM_EXPRESSION:


582  case USBFILTERMATCH_NUM_EXPRESSION_NP:


583  case USBFILTERMATCH_STR_EXACT:


584  case USBFILTERMATCH_STR_EXACT_NP:


585  case USBFILTERMATCH_STR_PATTERN:


586  case USBFILTERMATCH_STR_PATTERN_NP:


587  break;


588  }


589  }


590  return 1;


591  }


592 


593 


594  /**


595  * Performs simple pattern matching.


596  *


597  * @returns true on match and false on mismatch.


598  * @param pszExpr The numeric expression.


599  * @param u16Value The value to match.


600  */


601  static bool usbfilterMatchNumExpression(const char *pszExpr, uint16_t u16Value)


602  {


603  /*


604  * The string format is: "int:((<m>)([<m>][<n>]))(,(<m>)([<m>][<n>]))*"


605  * where <m> and <n> are numbers in decimal, hex (0xNNN) or octal (0NNN).


606  * Spaces are allowed around <m> and <n>.


607  */


608  while (*pszExpr)


609  {


610  if (!strncmp(pszExpr, RT_STR_TUPLE("int:")))


611  pszExpr += strlen("int:");


612 


613  /*


614  * Skip remnants of the previous expression and any empty expressions.


615  * ('' is the expression separator.)


616  */


617  while (*pszExpr == ''  RT_C_IS_BLANK(*pszExpr)  *pszExpr == '('  *pszExpr == ')')


618  pszExpr++;


619  if (!*pszExpr)


620  break;


621 


622  /*


623  * Parse the expression.


624  */


625  int rc;


626  uint16_t u16First = 0;


627  uint16_t u16Last = 0;


628  if (*pszExpr == '')


629  {


630  /* N */


631  pszExpr++;


632  rc = usbfilterReadNumber(&pszExpr, &u16Last);


633  }


634  else


635  {


636  /* M or M,N or MN or M */


637  rc = usbfilterReadNumber(&pszExpr, &u16First);


638  if (RT_SUCCESS(rc))


639  {


640  pszExpr = usbfilterSkipBlanks(pszExpr);


641  if (*pszExpr == '')


642  {


643  pszExpr++;


644  if (*pszExpr) /* MN */


645  rc = usbfilterReadNumber(&pszExpr, &u16Last);


646  else /* M */


647  u16Last = UINT16_MAX;


648  }


649  else if (*pszExpr == ',')


650  {


651  /* M,N */


652  pszExpr++;


653  rc = usbfilterReadNumber(&pszExpr, &u16Last);


654  }


655  else


656  {


657  /* M */


658  u16Last = u16First;


659  }


660  }


661  }


662 


663  /* On success, we should either be at the end of the string, at an expression


664  * separator (), or at the end of an interval filter (')').


665  */


666  if (RT_SUCCESS(rc) && *pszExpr && *pszExpr != '' && *pszExpr != ')')


667  rc = VERR_INVALID_PARAMETER;


668  if (RT_SUCCESS(rc))


669  {


670  /*


671  * Swap the values if the order is mixed up.


672  */


673  if (u16First > u16Last)


674  {


675  uint16_t u16Tmp = u16First;


676  u16First = u16Last;


677  u16Last = u16Tmp;


678  }


679 


680  /*


681  * Perform the compare.


682  */


683  if ( u16Value >= u16First


684  && u16Value <= u16Last)


685  return true;


686  }


687  else


688  {


689  /*


690  * Skip the bad expression.


691  * ('' is the expression separator.)


692  */


693  while (*pszExpr && *pszExpr != '')


694  pszExpr++;


695  }


696  }


697 


698  return false;


699  }


700 


701 


702  /**


703  * Performs simple pattern matching.


704  *


705  * @returns true on match and false on mismatch.


706  * @param pszPattern The pattern to match against.


707  * @param psz The string to match.


708  */


709  static bool usbfilterMatchStringPattern(const char *pszPattern, const char *psz)


710  {


711  char ch;


712  while ((ch = *pszPattern++))


713  {


714  if (ch == '?')


715  {


716  /*


717  * Matches one char or end of string.


718  */


719  if (*psz)


720  psz++;


721  }


722  else if (ch == '*')


723  {


724  /*


725  * Matches zero or more characters.


726  */


727  /* skip subsequent wildcards */


728  while ( (ch = *pszPattern) == '*'


729   ch == '?')


730  pszPattern++;


731  if (!ch)


732  /* Pattern ends with a '*' and thus matches the rest of psz. */


733  return true;


734 


735  /* Find the length of the following exact pattern sequence. */


736  ssize_t cchMatch = 1;


737  while ( (ch = pszPattern[cchMatch]) != '\0'


738  && ch != '*'


739  && ch != '?')


740  cchMatch++;


741 


742  /* Check if the exact pattern sequence is too long. */


743  ssize_t cch = strlen(psz);


744  cch = cchMatch;


745  if (cch < 0)


746  return false;


747 


748  /* Is the rest an exact match? */


749  if (!ch)


750  return memcmp(psz + cch, pszPattern, cchMatch) == 0;


751 


752  /*


753  * This is where things normally starts to get recursive or ugly.


754  *


755  * Just to make life simple, we'll skip the nasty stuff and say


756  * that we will do a maximal wildcard match and forget about any


757  * alternative matches.


758  *


759  * If somebody is bored out of their mind one day, feel free to


760  * implement correct matching without using recursion.


761  */


762  ch = *pszPattern;


763  const char *pszMatch = NULL;


764  while ( cch >= 0


765  && *psz)


766  {


767  if ( *psz == ch


768  && !strncmp(psz, pszPattern, cchMatch))


769  pszMatch = psz;


770  psz++;


771  }


772  if (!pszMatch)


773  return false;


774 


775  /* advance */


776  psz = pszMatch + cchMatch;


777  pszPattern += cchMatch;


778  }


779  else


780  {


781  /* exact match */


782  if (ch != *psz)


783  return false;


784  psz++;


785  }


786  }


787 


788  return *psz == '\0';


789  }


790 


791 


792  /**


793  * Match a filter against a device.


794  *


795  * @returns true if they match, false if not.


796  *


797  * @param pFilter The filter to match with.


798  * @param pDevice The device data. This is a filter (type ignored) that


799  * contains 'exact' values for all present fields and 'ignore'


800  * values for the nonpresent fields.


801  *


802  * @remark Both the filter and the device are ASSUMED to be valid because


803  * we don't wish to waste any time in this function.


804  */


805  USBLIB_DECL(bool) USBFilterMatch(PCUSBFILTER pFilter, PCUSBFILTER pDevice)


806  {


807  return USBFilterMatchRated(pFilter, pDevice) > 0;


808  }


809 


810 


811  #if 0 /*def IN_RING0*/ /** @todo convert to proper logging. */


812  extern "C" int printf(const char *format, ...);


813  # define dprintf(a) printf a


814  #else


815  # define dprintf(a) do {} while (0)


816  #endif


817 


818  /**


819  * Match a filter against a device and rate the result.


820  *


821  * @returns 1 if no match, matching rate between 1 and 100 (inclusive) if matched.


822  *


823  * @param pFilter The filter to match with.


824  * @param pDevice The device data. This is a filter (type ignored) that


825  * contains 'exact' values for all present fields and 'ignore'


826  * values for the nonpresent fields.


827  *


828  * @remark Both the filter and the device are ASSUMED to be valid because


829  * we don't wish to waste any time in this function.


830  */


831  USBLIB_DECL(int) USBFilterMatchRated(PCUSBFILTER pFilter, PCUSBFILTER pDevice)


832  {


833  unsigned iRate = 0;


834  dprintf(("USBFilterMatchRated: %p %p\n", pFilter, pDevice));


835 


836  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


837  {


838  switch (pFilter>aFields[i].enmMatch)


839  {


840  case USBFILTERMATCH_IGNORE:


841  iRate += 2;


842  break;


843 


844  case USBFILTERMATCH_PRESENT:


845  if (pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE)


846  {


847  dprintf(("filter match[%d]: !present\n", i));


848  return 1;


849  }


850  iRate += 2;


851  break;


852 


853  case USBFILTERMATCH_NUM_EXACT:


854  if ( pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE


855   pFilter>aFields[i].u16Value != pDevice>aFields[i].u16Value)


856  {


857  if (pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE)


858  dprintf(("filter match[%d]: !num_exact device=ignore\n", i));


859  else


860  dprintf(("filter match[%d]: !num_exact %#x (filter) != %#x (device)\n", i, pFilter>aFields[i].u16Value, pDevice>aFields[i].u16Value));


861  return 1;


862  }


863  iRate += 2;


864  break;


865 


866  case USBFILTERMATCH_NUM_EXACT_NP:


867  if ( pDevice>aFields[i].enmMatch != USBFILTERMATCH_IGNORE


868  && pFilter>aFields[i].u16Value != pDevice>aFields[i].u16Value)


869  {


870  dprintf(("filter match[%d]: !num_exact_np %#x (filter) != %#x (device)\n", i, pFilter>aFields[i].u16Value, pDevice>aFields[i].u16Value));


871  return 1;


872  }


873  iRate += 2;


874  break;


875 


876  case USBFILTERMATCH_NUM_EXPRESSION:


877  if ( pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE


878   !usbfilterMatchNumExpression(usbfilterGetString(pFilter, (USBFILTERIDX)i),


879  pDevice>aFields[i].u16Value))


880  {


881  dprintf(("filter match[%d]: !num_expression\n", i));


882  return 1;


883  }


884  iRate += 1;


885  break;


886 


887  case USBFILTERMATCH_NUM_EXPRESSION_NP:


888  if ( pDevice>aFields[i].enmMatch != USBFILTERMATCH_IGNORE


889  && !usbfilterMatchNumExpression(usbfilterGetString(pFilter, (USBFILTERIDX)i),


890  pDevice>aFields[i].u16Value))


891  {


892  dprintf(("filter match[%d]: !num_expression_no\n", i));


893  return 1;


894  }


895  iRate += 1;


896  break;


897 


898  case USBFILTERMATCH_STR_EXACT:


899  if ( pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE


900   strcmp(usbfilterGetString(pFilter, (USBFILTERIDX)i),


901  usbfilterGetString(pDevice, (USBFILTERIDX)i)))


902  {


903  dprintf(("filter match[%d]: !str_exact\n", i));


904  return 1;


905  }


906  iRate += 2;


907  break;


908 


909  case USBFILTERMATCH_STR_EXACT_NP:


910  if ( pDevice>aFields[i].enmMatch != USBFILTERMATCH_IGNORE


911  && strcmp(usbfilterGetString(pFilter, (USBFILTERIDX)i),


912  usbfilterGetString(pDevice, (USBFILTERIDX)i)))


913  {


914  dprintf(("filter match[%d]: !str_exact_np\n", i));


915  return 1;


916  }


917  iRate += 2;


918  break;


919 


920  case USBFILTERMATCH_STR_PATTERN:


921  if ( pDevice>aFields[i].enmMatch == USBFILTERMATCH_IGNORE


922   !usbfilterMatchStringPattern(usbfilterGetString(pFilter, (USBFILTERIDX)i),


923  usbfilterGetString(pDevice, (USBFILTERIDX)i)))


924  {


925  dprintf(("filter match[%d]: !str_pattern\n", i));


926  return 1;


927  }


928  iRate += 1;


929  break;


930 


931  case USBFILTERMATCH_STR_PATTERN_NP:


932  if ( pDevice>aFields[i].enmMatch != USBFILTERMATCH_IGNORE


933  && !usbfilterMatchStringPattern(usbfilterGetString(pFilter, (USBFILTERIDX)i),


934  usbfilterGetString(pDevice, (USBFILTERIDX)i)))


935  {


936  dprintf(("filter match[%d]: !str_pattern_np\n", i));


937  return 1;


938  }


939  iRate += 1;


940  break;


941 


942  default:


943  AssertMsgFailed(("#%d: %d\n", i, pFilter>aFields[i].enmMatch));


944  return 1;


945  }


946  }


947 


948  /* iRate is the range 0..2*cFields  recalc to percent. */


949  dprintf(("filter match: iRate=%d", iRate));


950  return iRate == 2 * RT_ELEMENTS(pFilter>aFields)


951  ? 100


952  : (iRate * 100) / (2 * RT_ELEMENTS(pFilter>aFields));


953  }


954 


955 


956  /**


957  * Match a filter against a USBDEVICE.


958  *


959  * @returns true if they match, false if not.


960  *


961  * @param pFilter The filter to match with.


962  * @param pDevice The device to match.


963  *


964  * @remark Both the filter and the device are ASSUMED to be valid because


965  * we don't wish to waste any time in this function.


966  */


967  USBLIB_DECL(bool) USBFilterMatchDevice(PCUSBFILTER pFilter, PUSBDEVICE pDevice)


968  {


969  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


970  {


971  switch (pFilter>aFields[i].enmMatch)


972  {


973  case USBFILTERMATCH_IGNORE:


974  break;


975 


976  case USBFILTERMATCH_PRESENT:


977  {


978  const char *psz;


979  switch (i)


980  {


981  case USBFILTERIDX_MANUFACTURER_STR: psz = pDevice>pszManufacturer; break;


982  case USBFILTERIDX_PRODUCT_STR: psz = pDevice>pszProduct; break;


983  case USBFILTERIDX_SERIAL_NUMBER_STR: psz = pDevice>pszSerialNumber; break;


984  default: psz = ""; break;


985  }


986  if (!psz)


987  return false;


988  break;


989  }


990 


991  case USBFILTERMATCH_NUM_EXACT:


992  case USBFILTERMATCH_NUM_EXACT_NP:


993  case USBFILTERMATCH_NUM_EXPRESSION:


994  case USBFILTERMATCH_NUM_EXPRESSION_NP:


995  {


996  uint16_t u16Value;


997  switch (i)


998  {


999  case USBFILTERIDX_VENDOR_ID: u16Value = pDevice>idVendor; break;


1000  case USBFILTERIDX_PRODUCT_ID: u16Value = pDevice>idProduct; break;


1001  case USBFILTERIDX_DEVICE: u16Value = pDevice>bcdDevice; break;


1002  case USBFILTERIDX_DEVICE_CLASS: u16Value = pDevice>bDeviceClass; break;


1003  case USBFILTERIDX_DEVICE_SUB_CLASS: u16Value = pDevice>bDeviceSubClass; break;


1004  case USBFILTERIDX_DEVICE_PROTOCOL: u16Value = pDevice>bDeviceProtocol; break;


1005  case USBFILTERIDX_BUS: u16Value = pDevice>bBus; break;


1006  case USBFILTERIDX_PORT: u16Value = pDevice>bPort; break;


1007  default: u16Value = UINT16_MAX; break;


1008 


1009  }


1010  switch (pFilter>aFields[i].enmMatch)


1011  {


1012  case USBFILTERMATCH_NUM_EXACT:


1013  case USBFILTERMATCH_NUM_EXACT_NP:


1014  if (pFilter>aFields[i].u16Value != u16Value)


1015  return false;


1016  break;


1017  case USBFILTERMATCH_NUM_EXPRESSION:


1018  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1019  if (!usbfilterMatchNumExpression(usbfilterGetString(pFilter, (USBFILTERIDX)i), u16Value))


1020  return false;


1021  break;


1022  }


1023  break;


1024  }


1025 


1026  case USBFILTERMATCH_STR_EXACT:


1027  case USBFILTERMATCH_STR_EXACT_NP:


1028  case USBFILTERMATCH_STR_PATTERN:


1029  case USBFILTERMATCH_STR_PATTERN_NP:


1030  {


1031  const char *psz;


1032  switch (i)


1033  {


1034  case USBFILTERIDX_MANUFACTURER_STR: psz = pDevice>pszManufacturer; break;


1035  case USBFILTERIDX_PRODUCT_STR: psz = pDevice>pszProduct; break;


1036  case USBFILTERIDX_SERIAL_NUMBER_STR: psz = pDevice>pszSerialNumber; break;


1037  default: psz = NULL; break;


1038  }


1039  switch (pFilter>aFields[i].enmMatch)


1040  {


1041  case USBFILTERMATCH_STR_EXACT:


1042  if ( !psz


1043   strcmp(usbfilterGetString(pFilter, (USBFILTERIDX)i), psz))


1044  return false;


1045  break;


1046 


1047  case USBFILTERMATCH_STR_EXACT_NP:


1048  if ( psz


1049  && strcmp(usbfilterGetString(pFilter, (USBFILTERIDX)i), psz))


1050  return false;


1051  break;


1052 


1053  case USBFILTERMATCH_STR_PATTERN:


1054  if ( !psz


1055   !usbfilterMatchStringPattern(usbfilterGetString(pFilter, (USBFILTERIDX)i), psz))


1056  return false;


1057  break;


1058 


1059  case USBFILTERMATCH_STR_PATTERN_NP:


1060  if ( psz


1061  && !usbfilterMatchStringPattern(usbfilterGetString(pFilter, (USBFILTERIDX)i), psz))


1062  return false;


1063  break;


1064  }


1065  break;


1066  }


1067 


1068  default:


1069  AssertMsgFailed(("#%d: %d\n", i, pFilter>aFields[i].enmMatch));


1070  return false;


1071  }


1072  }


1073 


1074  return true;


1075  }


1076 


1077 


1078  /**


1079  * Checks if the two filters are identical.


1080  *


1081  * @returns true if the are identical, false if they aren't.


1082  * @param pFilter The first filter.


1083  * @param pFilter2 The second filter.


1084  */


1085  USBLIB_DECL(bool) USBFilterIsIdentical(PCUSBFILTER pFilter, PCUSBFILTER pFilter2)


1086  {


1087  /* Lazy works here because we're darn strict with zero padding and such elsewhere. */


1088  return memcmp(pFilter, pFilter2, sizeof(*pFilter)) == 0;


1089  }


1090 


1091 


1092 


1093  /**


1094  * Sets the filter type.


1095  *


1096  * @returns VBox status code.


1097  * @retval VERR_INVALID_PARAMETER if the filter type is invalid.


1098  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1099  *


1100  * @param pFilter The filter.


1101  * @param enmType The new filter type.


1102  */


1103  USBLIB_DECL(int) USBFilterSetFilterType(PUSBFILTER pFilter, USBFILTERTYPE enmType)


1104  {


1105  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, VERR_INVALID_MAGIC);


1106  AssertReturn(enmType > USBFILTERTYPE_INVALID && enmType < USBFILTERTYPE_END, VERR_INVALID_PARAMETER);


1107 


1108  pFilter>enmType = enmType;


1109  return VINF_SUCCESS;


1110  }


1111 


1112 


1113  /**


1114  * Replaces the string value of a field.


1115  *


1116  * This will remove any existing string value current held by the field from the


1117  * string table and then attempt to add the new value. This function can be used


1118  * to delete any assigned string before changing the type to numeric by passing


1119  * in an empty string. This works because the first byte in the string table is


1120  * reserved for the empty (NULL) string.


1121  *


1122  * @returns VBox status code.


1123  * @retval VINF_SUCCESS on success.


1124  * @retval VERR_BUFFER_OVERFLOW if the string table is full.


1125  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid.


1126  * @retval VERR_INVALID_POINTER if pszString isn't valid.


1127  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1128  *


1129  * @param pFilter The filter.


1130  * @param enmFieldIdx The field index.


1131  * @param pszString The string to add.


1132  * @param fPurge Purge invalid UTF8 encoding and control characters


1133  * before setting it.


1134  */


1135  static int usbfilterSetString(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszString, bool fPurge)


1136  {


1137  /*


1138  * Validate input.


1139  */


1140  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, VERR_INVALID_MAGIC);


1141  AssertReturn((unsigned)enmFieldIdx < (unsigned)USBFILTERIDX_END, VERR_INVALID_PARAMETER);


1142  AssertPtrReturn(pszString, VERR_INVALID_POINTER);


1143 


1144  Assert(pFilter>offCurEnd < sizeof(pFilter>achStrTab));


1145  Assert(pFilter>achStrTab[pFilter>offCurEnd] == '\0');


1146 


1147  /*


1148  * Remove old string value if any.


1149  */


1150  if ( USBFilterIsMethodUsingStringValue((USBFILTERMATCH)pFilter>aFields[enmFieldIdx].enmMatch)


1151  && pFilter>aFields[enmFieldIdx].u16Value != 0)


1152  {


1153  uint32_t off = pFilter>aFields[enmFieldIdx].u16Value;


1154  pFilter>aFields[enmFieldIdx].u16Value = 0; /* Assign it to the NULL string. */


1155 


1156  unsigned cchShift = (unsigned)strlen(&pFilter>achStrTab[off]) + 1;


1157  ssize_t cchToMove = (pFilter>offCurEnd + 1)  (off + cchShift);


1158  Assert(cchToMove >= 0);


1159  if (cchToMove > 0)


1160  {


1161  /* We're not last  must shift the strings. */


1162  memmove(&pFilter>achStrTab[off], &pFilter>achStrTab[off + cchShift], cchToMove);


1163  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


1164  if ( pFilter>aFields[i].u16Value >= off


1165  && USBFilterIsMethodUsingStringValue((USBFILTERMATCH)pFilter>aFields[i].enmMatch))


1166  pFilter>aFields[i].u16Value = cchShift;


1167  }


1168  pFilter>offCurEnd = cchShift;


1169  Assert(pFilter>offCurEnd < sizeof(pFilter>achStrTab));


1170  Assert(pFilter>offCurEnd + cchShift <= sizeof(pFilter>achStrTab));


1171 


1172  /* zero the unused string table (to allow lazyness/strictness elsewhere). */


1173  memset(&pFilter>achStrTab[pFilter>offCurEnd], '\0', cchShift);


1174  }


1175 


1176  /*


1177  * Make a special case for the empty string.


1178  * (This also makes the delete logical above work correctly for the last string.)


1179  */


1180  if (!*pszString)


1181  pFilter>aFields[enmFieldIdx].u16Value = 0;


1182  else


1183  {


1184  size_t cch = strlen(pszString);


1185  if (pFilter>offCurEnd + cch + 2 > sizeof(pFilter>achStrTab))


1186  return VERR_BUFFER_OVERFLOW;


1187 


1188  pFilter>aFields[enmFieldIdx].u16Value = pFilter>offCurEnd + 1;


1189  memcpy(&pFilter>achStrTab[pFilter>offCurEnd + 1], pszString, cch + 1);


1190  if (fPurge)


1191  cch = USBLibPurgeEncoding(&pFilter>achStrTab[pFilter>offCurEnd + 1]);


1192  pFilter>offCurEnd += (uint32_t)cch + 1;


1193  }


1194 


1195  return VINF_SUCCESS;


1196  }


1197 


1198  /**


1199  * Wrapper around usbfilterSetString() that deletes any string value


1200  * currently assigned to a field.


1201  *


1202  * Upon successful return the field contains a null string, nothing or a number.


1203  *


1204  * This function will validate the field index if there isn't any string


1205  * value to delete, thus preventing any extra validating of the index.


1206  *


1207  * @returns VBox status code. See usbfilterSetString.


1208  * @param pFilter The filter.


1209  * @param enmFieldIdx The index of the field which string value should be deleted.


1210  */


1211  static int usbfilterDeleteAnyStringValue(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1212  {


1213  int rc = VINF_SUCCESS;


1214  if ( USBFilterIsMethodUsingStringValue((USBFILTERMATCH)pFilter>aFields[enmFieldIdx].enmMatch)


1215  && pFilter>aFields[enmFieldIdx].u16Value != 0)


1216  rc = usbfilterSetString(pFilter, enmFieldIdx, "", false /*fPurge*/);


1217  else if ((unsigned)enmFieldIdx >= (unsigned)USBFILTERIDX_END)


1218  rc = VERR_INVALID_PARAMETER;


1219  return rc;


1220  }


1221 


1222 


1223  /**


1224  * Sets a field to always match (ignore whatever is thrown at it).


1225  *


1226  * @returns VBox status code.


1227  * @retval VINF_SUCCESS on success.


1228  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid.


1229  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1230  *


1231  * @param pFilter The filter.


1232  * @param enmFieldIdx The field index. This must be a string field.


1233  */


1234  USBLIB_DECL(int) USBFilterSetIgnore(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1235  {


1236  int rc = usbfilterDeleteAnyStringValue(pFilter, enmFieldIdx);


1237  if (RT_SUCCESS(rc))


1238  {


1239  pFilter>aFields[enmFieldIdx].enmMatch = USBFILTERMATCH_IGNORE;


1240  pFilter>aFields[enmFieldIdx].u16Value = 0;


1241  }


1242  return rc;


1243  }


1244 


1245 


1246  /**


1247  * Sets a field to match on device field present only.


1248  *


1249  * @returns VBox status code.


1250  * @retval VINF_SUCCESS on success.


1251  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid.


1252  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1253  *


1254  * @param pFilter The filter.


1255  * @param enmFieldIdx The field index. This must be a string field.


1256  */


1257  USBLIB_DECL(int) USBFilterSetPresentOnly(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1258  {


1259  int rc = usbfilterDeleteAnyStringValue(pFilter, enmFieldIdx);


1260  if (RT_SUCCESS(rc))


1261  {


1262  pFilter>aFields[enmFieldIdx].enmMatch = USBFILTERMATCH_PRESENT;


1263  pFilter>aFields[enmFieldIdx].u16Value = 0;


1264  }


1265  return rc;


1266  }


1267 


1268 


1269  /**


1270  * Sets a field to exactly match a number.


1271  *


1272  * @returns VBox status code.


1273  * @retval VINF_SUCCESS on success.


1274  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid.


1275  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1276  *


1277  * @param pFilter The filter.


1278  * @param enmFieldIdx The field index. This must be a string field.


1279  * @param u16Value The string pattern.


1280  * @param fMustBePresent If set, a nonpresent field on the device will result in a mismatch.


1281  * If clear, a nonpresent field on the device will match.


1282  */


1283  USBLIB_DECL(int) USBFilterSetNumExact(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, uint16_t u16Value, bool fMustBePresent)


1284  {


1285  int rc = USBFilterIsNumericField(enmFieldIdx) ? VINF_SUCCESS : VERR_INVALID_PARAMETER;


1286  if (RT_SUCCESS(rc))


1287  {


1288  rc = usbfilterDeleteAnyStringValue(pFilter, enmFieldIdx);


1289  if (RT_SUCCESS(rc))


1290  {


1291  pFilter>aFields[enmFieldIdx].u16Value = u16Value;


1292  pFilter>aFields[enmFieldIdx].enmMatch = fMustBePresent ? USBFILTERMATCH_NUM_EXACT : USBFILTERMATCH_NUM_EXACT_NP;


1293  }


1294  }


1295 


1296  return rc;


1297  }


1298 


1299 


1300  /**


1301  * Sets a field to match a numeric expression.


1302  *


1303  * @returns VBox status code.


1304  * @retval VINF_SUCCESS on success.


1305  * @retval VERR_BUFFER_OVERFLOW if the string table is full.


1306  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx or the numeric expression aren't valid.


1307  * @retval VERR_INVALID_POINTER if pszExpression isn't a valid pointer.


1308  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1309  *


1310  * @param pFilter The filter.


1311  * @param enmFieldIdx The field index. This must be a string field.


1312  * @param pszExpression The numeric expression.


1313  * @param fMustBePresent If set, a nonpresent field on the device will result in a mismatch.


1314  * If clear, a nonpresent field on the device will match.


1315  */


1316  USBLIB_DECL(int) USBFilterSetNumExpression(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszExpression, bool fMustBePresent)


1317  {


1318  int rc = USBFilterIsNumericField(enmFieldIdx) ? VINF_SUCCESS : VERR_INVALID_PARAMETER;


1319  if (RT_SUCCESS(rc))


1320  {


1321  /* Strip leading spaces and empty sub expressions (). */


1322  while (*pszExpression && (RT_C_IS_BLANK(*pszExpression)  *pszExpression == ''))


1323  pszExpression++;


1324 


1325  rc = usbfilterValidateNumExpression(pszExpression);


1326  if (RT_SUCCESS(rc))


1327  {


1328  /* We could optimize the expression further (stripping spaces, convert numbers),


1329  but it's more work than what it's worth and it could upset some users. */


1330  rc = usbfilterSetString(pFilter, enmFieldIdx, pszExpression, false /*fPurge*/);


1331  if (RT_SUCCESS(rc))


1332  pFilter>aFields[enmFieldIdx].enmMatch = fMustBePresent ? USBFILTERMATCH_NUM_EXPRESSION : USBFILTERMATCH_NUM_EXPRESSION_NP;


1333  else if (rc == VERR_NO_DIGITS)


1334  rc = VERR_INVALID_PARAMETER;


1335  }


1336  }


1337  return rc;


1338  }


1339 


1340 


1341  /**


1342  * Sets a field to exactly match a string.


1343  *


1344  * @returns VBox status code.


1345  * @retval VINF_SUCCESS on success.


1346  * @retval VERR_BUFFER_OVERFLOW if the string table is full.


1347  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid.


1348  * @retval VERR_INVALID_POINTER if pszPattern isn't a valid pointer.


1349  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1350  *


1351  * @param pFilter The filter.


1352  * @param enmFieldIdx The field index. This must be a string field.


1353  * @param pszValue The string value.


1354  * @param fMustBePresent If set, a nonpresent field on the device will result in a mismatch.


1355  * If clear, a nonpresent field on the device will match.


1356  * @param fPurge Purge invalid UTF8 encoding and control


1357  * characters before setting it.


1358  */


1359  USBLIB_DECL(int) USBFilterSetStringExact(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszValue,


1360  bool fMustBePresent, bool fPurge)


1361  {


1362  int rc = USBFilterIsStringField(enmFieldIdx) ? VINF_SUCCESS : VERR_INVALID_PARAMETER;


1363  if (RT_SUCCESS(rc))


1364  {


1365  rc = usbfilterSetString(pFilter, enmFieldIdx, pszValue, fPurge);


1366  if (RT_SUCCESS(rc))


1367  pFilter>aFields[enmFieldIdx].enmMatch = fMustBePresent ? USBFILTERMATCH_STR_EXACT : USBFILTERMATCH_STR_EXACT_NP;


1368  }


1369  return rc;


1370  }


1371 


1372 


1373  /**


1374  * Sets a field to match a string pattern.


1375  *


1376  * @returns VBox status code.


1377  * @retval VINF_SUCCESS on success.


1378  * @retval VERR_BUFFER_OVERFLOW if the string table is full.


1379  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx or pattern aren't valid.


1380  * @retval VERR_INVALID_POINTER if pszPattern isn't a valid pointer.


1381  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1382  *


1383  * @param pFilter The filter.


1384  * @param enmFieldIdx The field index. This must be a string field.


1385  * @param pszPattern The string pattern.


1386  * @param fMustBePresent If set, a nonpresent field on the device will result in a mismatch.


1387  * If clear, a nonpresent field on the device will match.


1388  */


1389  USBLIB_DECL(int) USBFilterSetStringPattern(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszPattern, bool fMustBePresent)


1390  {


1391  int rc = USBFilterIsStringField(enmFieldIdx) ? VINF_SUCCESS : VERR_INVALID_PARAMETER;


1392  if (RT_SUCCESS(rc))


1393  {


1394  rc = usbfilterValidateStringPattern(pszPattern);


1395  if (RT_SUCCESS(rc))


1396  {


1397  rc = usbfilterSetString(pFilter, enmFieldIdx, pszPattern, false /*fPurge*/);


1398  if (RT_SUCCESS(rc))


1399  pFilter>aFields[enmFieldIdx].enmMatch = fMustBePresent ? USBFILTERMATCH_STR_PATTERN : USBFILTERMATCH_STR_PATTERN_NP;


1400  }


1401  }


1402  return rc;


1403  }


1404 


1405 


1406  /**


1407  * Sets the mustbepresent part of a field.


1408  *


1409  * This only works on field which already has matching criteria. This means


1410  * that field marked 'ignore' will not be processed and will result in a


1411  * warning status code.


1412  *


1413  * @returns VBox status code.


1414  * @retval VINF_SUCCESS on success.


1415  * @retval VWRN_INVALID_PARAMETER if the field is marked 'ignore'. No assertions.


1416  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx or pattern aren't valid.


1417  * @retval VERR_INVALID_POINTER if pszPattern isn't a valid pointer.


1418  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1419  *


1420  * @param pFilter The filter.


1421  * @param enmFieldIdx The field index.


1422  * @param fMustBePresent If set, a nonpresent field on the device will result in a mismatch.


1423  * If clear, a nonpresent field on the device will match.


1424  */


1425  USBLIB_DECL(int) USBFilterSetMustBePresent(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, bool fMustBePresent)


1426  {


1427  AssertPtrReturn(pFilter, VERR_INVALID_POINTER);


1428  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, VERR_INVALID_MAGIC);


1429  AssertReturn((unsigned)enmFieldIdx < (unsigned)USBFILTERIDX_END, VERR_INVALID_PARAMETER);


1430 


1431  USBFILTERMATCH enmMatch = (USBFILTERMATCH)pFilter>aFields[enmFieldIdx].enmMatch;


1432  if (fMustBePresent)


1433  {


1434  switch (enmMatch)


1435  {


1436  case USBFILTERMATCH_IGNORE:


1437  return VWRN_INVALID_PARAMETER;


1438 


1439  case USBFILTERMATCH_PRESENT:


1440  case USBFILTERMATCH_NUM_EXACT:


1441  case USBFILTERMATCH_NUM_EXPRESSION:


1442  case USBFILTERMATCH_STR_EXACT:


1443  case USBFILTERMATCH_STR_PATTERN:


1444  break;


1445 


1446  case USBFILTERMATCH_NUM_EXACT_NP:


1447  enmMatch = USBFILTERMATCH_NUM_EXACT;


1448  break;


1449  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1450  enmMatch = USBFILTERMATCH_NUM_EXPRESSION;


1451  break;


1452  case USBFILTERMATCH_STR_EXACT_NP:


1453  enmMatch = USBFILTERMATCH_STR_EXACT;


1454  break;


1455  case USBFILTERMATCH_STR_PATTERN_NP:


1456  enmMatch = USBFILTERMATCH_STR_PATTERN;


1457  break;


1458  default:


1459  AssertMsgFailedReturn(("%p: enmFieldIdx=%d enmMatch=%d\n", pFilter, enmFieldIdx, enmMatch), VERR_INVALID_MAGIC);


1460  }


1461  }


1462  else


1463  {


1464  switch (enmMatch)


1465  {


1466  case USBFILTERMATCH_IGNORE:


1467  return VWRN_INVALID_PARAMETER;


1468 


1469  case USBFILTERMATCH_NUM_EXACT_NP:


1470  case USBFILTERMATCH_STR_PATTERN_NP:


1471  case USBFILTERMATCH_STR_EXACT_NP:


1472  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1473  break;


1474 


1475  case USBFILTERMATCH_PRESENT:


1476  enmMatch = USBFILTERMATCH_IGNORE;


1477  break;


1478  case USBFILTERMATCH_NUM_EXACT:


1479  enmMatch = USBFILTERMATCH_NUM_EXACT_NP;


1480  break;


1481  case USBFILTERMATCH_NUM_EXPRESSION:


1482  enmMatch = USBFILTERMATCH_NUM_EXPRESSION_NP;


1483  break;


1484  case USBFILTERMATCH_STR_EXACT:


1485  enmMatch = USBFILTERMATCH_STR_EXACT_NP;


1486  break;


1487  case USBFILTERMATCH_STR_PATTERN:


1488  enmMatch = USBFILTERMATCH_STR_PATTERN_NP;


1489  break;


1490 


1491  default:


1492  AssertMsgFailedReturn(("%p: enmFieldIdx=%d enmMatch=%d\n", pFilter, enmFieldIdx, enmMatch), VERR_INVALID_MAGIC);


1493  }


1494  }


1495 


1496  pFilter>aFields[enmFieldIdx].enmMatch = enmMatch;


1497  return VINF_SUCCESS;


1498  }


1499 


1500 


1501  /**


1502  * Gets the filter type.


1503  *


1504  * @returns The filter type.


1505  * USBFILTERTYPE_INVALID if the filter is invalid.


1506  * @param pFilter The filter.


1507  */


1508  USBLIB_DECL(USBFILTERTYPE) USBFilterGetFilterType(PCUSBFILTER pFilter)


1509  {


1510  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, USBFILTERTYPE_INVALID);


1511  return pFilter>enmType;


1512  }


1513 


1514 


1515  /**


1516  * Gets the matching method for a field.


1517  *


1518  * @returns The matching method on success, UBFILTERMATCH_INVALID on invalid field index.


1519  * @param pFilter The filter.


1520  * @param enmFieldIdx The field index.


1521  */


1522  USBLIB_DECL(USBFILTERMATCH) USBFilterGetMatchingMethod(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1523  {


1524  if ( pFilter>u32Magic == USBFILTER_MAGIC


1525  && (unsigned)enmFieldIdx < (unsigned)USBFILTERIDX_END)


1526  return (USBFILTERMATCH)pFilter>aFields[enmFieldIdx].enmMatch;


1527  return USBFILTERMATCH_INVALID;


1528  }


1529 


1530 


1531  /**


1532  * Gets the numeric value of a field.


1533  *


1534  * The field must contain a number, we're not doing any conversions for you.


1535  *


1536  * @returns VBox status code.


1537  * @retval VINF_SUCCESS on success.


1538  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid or if the field doesn't contain a number.


1539  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1540  *


1541  * @param pFilter The filter.


1542  * @param enmFieldIdx The field index.


1543  * @param pu16Value Where to store the value.


1544  */


1545  USBLIB_DECL(int) USBFilterQueryNum(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, uint16_t *pu16Value)


1546  {


1547  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, VERR_INVALID_MAGIC);


1548  int iValue = usbfilterGetNum(pFilter, enmFieldIdx);


1549  if (iValue == 1)


1550  return VERR_INVALID_PARAMETER;


1551  *pu16Value = (uint16_t)iValue;


1552  return VINF_SUCCESS;


1553  }


1554 


1555 


1556  /**


1557  * Gets the numeric value of a field.


1558  *


1559  * The field must contain a number, we're not doing any conversions for you.


1560  *


1561  * @returns The field value on success, 1 on failure (invalid input / not numeric).


1562  *


1563  * @param pFilter The filter.


1564  * @param enmFieldIdx The field index.


1565  */


1566  USBLIB_DECL(int) USBFilterGetNum(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1567  {


1568  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, 1);


1569  return usbfilterGetNum(pFilter, enmFieldIdx);


1570  }


1571 


1572 


1573  /**


1574  * Gets the string value of a field.


1575  *


1576  * The field must contain a string, we're not doing any conversions for you.


1577  *


1578  * @returns VBox status code.


1579  * @retval VINF_SUCCESS on success.


1580  * @retval VERR_BUFFER_OVERFLOW if the buffer isn't sufficient to hold the string. The buffer


1581  * will be filled with as much of the string that'll fit.


1582  * @retval VERR_INVALID_PARAMETER if the enmFieldIdx isn't valid or if the field doesn't contain a string.


1583  * @retval VERR_INVALID_MAGIC if pFilter is invalid.


1584  *


1585  * @param pFilter The filter.


1586  * @param enmFieldIdx The field index.


1587  * @param pszBuf Where to store the string.


1588  * @param cchBuf The size of the buffer.


1589  */


1590  USBLIB_DECL(int) USBFilterQueryString(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, char *pszBuf, size_t cchBuf)


1591  {


1592  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, VERR_INVALID_MAGIC);


1593 


1594  const char *psz = usbfilterGetString(pFilter, enmFieldIdx);


1595  if (RT_UNLIKELY(!psz))


1596  return VERR_INVALID_PARAMETER;


1597 


1598  int rc = VINF_SUCCESS;


1599  size_t cch = strlen(psz);


1600  if (cch < cchBuf)


1601  memcpy(pszBuf, psz, cch + 1);


1602  else


1603  {


1604  rc = VERR_BUFFER_OVERFLOW;


1605  if (cchBuf)


1606  {


1607  memcpy(pszBuf, psz, cchBuf  1);


1608  pszBuf[cchBuf  1] = '\0';


1609  }


1610  }


1611 


1612  return rc;


1613  }


1614 


1615 


1616  /**


1617  * Gets the string table entry for a field.


1618  *


1619  * @returns Pointer to the string. (readonly!)


1620  *


1621  * @param pFilter The filter.


1622  * @param enmFieldIdx The field index.


1623  */


1624  USBLIB_DECL(const char *) USBFilterGetString(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1625  {


1626  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, NULL);


1627 


1628  const char *psz = usbfilterGetString(pFilter, enmFieldIdx);


1629  if (RT_UNLIKELY(!psz))


1630  return NULL;


1631  return psz;


1632  }


1633 


1634 


1635  /**


1636  * Gets the string length of a field containing a string.


1637  *


1638  * @returns String length on success, 1 on failure (not a string, bad filter).


1639  * @param pFilter The filter.


1640  * @param enmFieldIdx The field index.


1641  */


1642  USBLIB_DECL(ssize_t) USBFilterGetStringLen(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx)


1643  {


1644  if (RT_LIKELY(pFilter>u32Magic == USBFILTER_MAGIC))


1645  {


1646  const char *psz = usbfilterGetString(pFilter, enmFieldIdx);


1647  if (RT_LIKELY(psz))


1648  return strlen(psz);


1649  }


1650  return 1;


1651  }


1652 


1653 


1654  /**


1655  * Check if any of the fields are set to something substatial.


1656  *


1657  * Consider the fileter a wildcard if this returns false.


1658  *


1659  * @returns true / false.


1660  * @param pFilter The filter.


1661  */


1662  USBLIB_DECL(bool) USBFilterHasAnySubstatialCriteria(PCUSBFILTER pFilter)


1663  {


1664  AssertReturn(pFilter>u32Magic == USBFILTER_MAGIC, false);


1665 


1666  for (unsigned i = 0; i < RT_ELEMENTS(pFilter>aFields); i++)


1667  {


1668  switch (pFilter>aFields[i].enmMatch)


1669  {


1670  case USBFILTERMATCH_IGNORE:


1671  case USBFILTERMATCH_PRESENT:


1672  break;


1673 


1674  case USBFILTERMATCH_NUM_EXACT:


1675  case USBFILTERMATCH_NUM_EXACT_NP:


1676  case USBFILTERMATCH_STR_EXACT:


1677  case USBFILTERMATCH_STR_EXACT_NP:


1678  return true;


1679 


1680  case USBFILTERMATCH_NUM_EXPRESSION:


1681  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1682  {


1683  const char *psz = usbfilterGetString(pFilter, (USBFILTERIDX)i);


1684  if (psz)


1685  {


1686  while (*psz && (*psz == ''  RT_C_IS_BLANK(*psz)))


1687  psz++;


1688  if (*psz)


1689  return true;


1690  }


1691  break;


1692  }


1693 


1694  case USBFILTERMATCH_STR_PATTERN:


1695  case USBFILTERMATCH_STR_PATTERN_NP:


1696  {


1697  const char *psz = usbfilterGetString(pFilter, (USBFILTERIDX)i);


1698  if (psz)


1699  {


1700  while (*psz && (*psz == '*'  *psz == '?'))


1701  psz++;


1702  if (*psz)


1703  return true;


1704  }


1705  break;


1706  }


1707  }


1708  }


1709 


1710  return false;


1711  }


1712 


1713 


1714 


1715  /**


1716  * Checks whether the specified field is a numeric field or not.


1717  *


1718  * @returns true / false.


1719  * @param enmFieldIdx The field index.


1720  */


1721  USBLIB_DECL(bool) USBFilterIsNumericField(USBFILTERIDX enmFieldIdx)


1722  {


1723  switch (enmFieldIdx)


1724  {


1725  case USBFILTERIDX_VENDOR_ID:


1726  case USBFILTERIDX_PRODUCT_ID:


1727  case USBFILTERIDX_DEVICE:


1728  case USBFILTERIDX_DEVICE_CLASS:


1729  case USBFILTERIDX_DEVICE_SUB_CLASS:


1730  case USBFILTERIDX_DEVICE_PROTOCOL:


1731  case USBFILTERIDX_BUS:


1732  case USBFILTERIDX_PORT:


1733  return true;


1734 


1735  default:


1736  AssertMsgFailed(("%d\n", enmFieldIdx));


1737  RT_FALL_THRU();


1738  case USBFILTERIDX_MANUFACTURER_STR:


1739  case USBFILTERIDX_PRODUCT_STR:


1740  case USBFILTERIDX_SERIAL_NUMBER_STR:


1741  return false;


1742  }


1743  }


1744 


1745 


1746  /**


1747  * Checks whether the specified field is a string field or not.


1748  *


1749  * @returns true / false.


1750  * @param enmFieldIdx The field index.


1751  */


1752  USBLIB_DECL(bool) USBFilterIsStringField(USBFILTERIDX enmFieldIdx)


1753  {


1754  switch (enmFieldIdx)


1755  {


1756  default:


1757  AssertMsgFailed(("%d\n", enmFieldIdx));


1758  RT_FALL_THRU();


1759  case USBFILTERIDX_VENDOR_ID:


1760  case USBFILTERIDX_PRODUCT_ID:


1761  case USBFILTERIDX_DEVICE:


1762  case USBFILTERIDX_DEVICE_CLASS:


1763  case USBFILTERIDX_DEVICE_SUB_CLASS:


1764  case USBFILTERIDX_DEVICE_PROTOCOL:


1765  case USBFILTERIDX_BUS:


1766  case USBFILTERIDX_PORT:


1767  return false;


1768 


1769  case USBFILTERIDX_MANUFACTURER_STR:


1770  case USBFILTERIDX_PRODUCT_STR:


1771  case USBFILTERIDX_SERIAL_NUMBER_STR:


1772  return true;


1773  }


1774  }


1775 


1776 


1777  /**


1778  * Checks whether the specified matching method uses a numeric value or not.


1779  *


1780  * @returns true / false.


1781  * @param enmMatchingMethod The matching method.


1782  */


1783  USBLIB_DECL(bool) USBFilterIsMethodUsingNumericValue(USBFILTERMATCH enmMatchingMethod)


1784  {


1785  switch (enmMatchingMethod)


1786  {


1787  default:


1788  AssertMsgFailed(("%d\n", enmMatchingMethod));


1789  RT_FALL_THRU();


1790  case USBFILTERMATCH_IGNORE:


1791  case USBFILTERMATCH_PRESENT:


1792  case USBFILTERMATCH_NUM_EXPRESSION:


1793  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1794  case USBFILTERMATCH_STR_EXACT:


1795  case USBFILTERMATCH_STR_EXACT_NP:


1796  case USBFILTERMATCH_STR_PATTERN:


1797  case USBFILTERMATCH_STR_PATTERN_NP:


1798  return false;


1799 


1800  case USBFILTERMATCH_NUM_EXACT:


1801  case USBFILTERMATCH_NUM_EXACT_NP:


1802  return true;


1803  }


1804  }


1805 


1806 


1807  /**


1808  * Checks whether the specified matching method uses a string value or not.


1809  *


1810  * @returns true / false.


1811  * @param enmMatchingMethod The matching method.


1812  */


1813  USBLIB_DECL(bool) USBFilterIsMethodUsingStringValue(USBFILTERMATCH enmMatchingMethod)


1814  {


1815  switch (enmMatchingMethod)


1816  {


1817  default:


1818  AssertMsgFailed(("%d\n", enmMatchingMethod));


1819  RT_FALL_THRU();


1820  case USBFILTERMATCH_IGNORE:


1821  case USBFILTERMATCH_PRESENT:


1822  case USBFILTERMATCH_NUM_EXACT:


1823  case USBFILTERMATCH_NUM_EXACT_NP:


1824  return false;


1825 


1826  case USBFILTERMATCH_NUM_EXPRESSION:


1827  case USBFILTERMATCH_NUM_EXPRESSION_NP:


1828  case USBFILTERMATCH_STR_EXACT:


1829  case USBFILTERMATCH_STR_EXACT_NP:


1830  case USBFILTERMATCH_STR_PATTERN:


1831  case USBFILTERMATCH_STR_PATTERN_NP:


1832  return true;


1833  }


1834  }


1835 


1836 


1837  /**


1838  * Checks if a matching method is for numeric fields or not.


1839  *


1840  * @returns true / false.


1841  * @param enmMatchingMethod The matching method.


1842  */


1843  USBLIB_DECL(bool) USBFilterIsMethodNumeric(USBFILTERMATCH enmMatchingMethod)


1844  {


1845  return enmMatchingMethod >= USBFILTERMATCH_NUM_FIRST


1846  && enmMatchingMethod <= USBFILTERMATCH_NUM_LAST;


1847  }


1848 


1849  /**


1850  * Checks if a matching method is for string fields or not.


1851  *


1852  * @returns true / false.


1853  * @param enmMatchingMethod The matching method.


1854  */


1855  USBLIB_DECL(bool) USBFilterIsMethodString(USBFILTERMATCH enmMatchingMethod)


1856  {


1857  return enmMatchingMethod >= USBFILTERMATCH_STR_FIRST


1858  && enmMatchingMethod <= USBFILTERMATCH_STR_LAST;


1859  }


1860 

