Example #1
0
bool PortParameters::ParseParametersStr(const char *pParameters)
{
  PortParameters tmp = *this;

  if (!lstrcmpi(pParameters, "-") || !lstrcmpi(pParameters, "*")) {
    int i;

    for (i = 0 ; i < sizeof(bits)/sizeof(bits[0]) ; i++) {
      if (!tmp.SetBit(pParameters, bits[i]))
        return FALSE;
    }
  } else {
    char pars[200];

    if (SNPRINTF(pars, sizeof(pars)/sizeof(pars[0]), "%s", pParameters) < 0) {
      Trace("The parameters string '%s' is too long\n", pParameters);
      return FALSE;
    }

    char *pSave1;

    for (char *pPar = STRTOK_R(pars, ",", &pSave1) ; pPar ; pPar = STRTOK_R(NULL, ",", &pSave1)) {
      char *pSave2;
      const char *pKey = STRTOK_R(pPar, "=", &pSave2);
      const char *pVal = STRTOK_R(NULL, "=", &pSave2);

      //Trace("'%s'='%s'\n", pKey, pVal);

      if (!pVal) {
        Trace("Missing value for '%s'\n", pKey);
        return FALSE;
      }

      int i;

      for (i = 0 ; i < sizeof(bits)/sizeof(bits[0]) ; i++) {
        DWORD bit = bits[i].bit;
        const char *pName = GetBitName(bit);

        if (pName == NULL)
          continue;

        if (!lstrcmpi(pKey, pName)) {
          if (!tmp.SetBit(pVal, bits[i]))
            return FALSE;
          break;
        }
      }

      if (i >= sizeof(bits)/sizeof(bits[0])) {
        Trace("Invalid parameter '%s'\n", pKey);
        return FALSE;
      }
    }
  }

  *this = tmp;

  return TRUE;
}
Example #2
0
STATICFNDEF boolean_t process_options(char *option_str, uint4 option_len, boolean_t *isolation, boolean_t *noisolation,
			       boolean_t *consistency, boolean_t *noconsistency)
{
	char		local_options[MAX_OPTIONS_LEN];
	char		*ptr, *strtokptr;

	if (MAX_OPTIONS_LEN < option_len)
	{
		util_out_print_gtmio("Too many options", FLUSH);
		return FALSE;
	}
	memcpy(local_options, option_str, option_len);
	*isolation = *noisolation = *consistency = *noconsistency = FALSE;
	ptr = local_options;
	for ( ; 0 < option_len; ptr++, option_len--)
		*ptr = TOUPPER(*ptr);
	ptr = STRTOK_R(local_options, ",", &strtokptr);
	do
	{
		switch (*ptr)
		{
			case 'C':
				if (1 == STRLEN(ptr))
					*consistency = TRUE;
				else
				{
					assert(0 == MEMCMP_LIT(ptr, HASHT_OPT_CONSISTENCY));
					*consistency = TRUE;
				}
				break;
			case 'I':
				if (1 == STRLEN(ptr))
					*isolation = TRUE;
				else
				{
					assert(0 == MEMCMP_LIT(ptr, HASHT_OPT_ISOLATION));
					*isolation = TRUE;
				}
				break;
			case 'N':
				assert('O' == *(ptr + 1));
				if ('C' == *(ptr + 2))
				{
					assert(0 == MEMCMP_LIT(ptr, HASHT_OPT_NOCONSISTENCY));
					*noconsistency = TRUE;
				} else
				{
					assert('I' == *(ptr + 2));
					assert(0 == MEMCMP_LIT(ptr, HASHT_OPT_NOISOLATION));
					*noisolation = TRUE;
				}
				break;
			default:
				assert(FALSE);	/* Parsing should have found invalid command */
				break;
		}
	} while (ptr = STRTOK_R(NULL, ",", &strtokptr));
	return !((*isolation && *noisolation) || (*consistency && *noconsistency));
}
Example #3
0
static isc_result_t
modrdataset(struct dlz_example_data *state, const char *name,
	    const char *rdatastr, struct record *list)
{
	char *full_name, *dclass, *type, *data, *ttlstr, *buf;
	char absolute[1024];
	isc_result_t result;
#if defined(WIN32) || defined(_REENTRANT)
	char *saveptr = NULL;
#endif

	buf = strdup(rdatastr);
	if (buf == NULL)
		return (ISC_R_FAILURE);

	/*
	 * The format is:
	 * FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
	 *
	 * The DATA field is space separated, and is in the data format
	 * for the type used by dig
	 */

	full_name = STRTOK_R(buf, "\t", &saveptr);
	if (full_name == NULL)
		goto error;

	ttlstr = STRTOK_R(NULL, "\t", &saveptr);
	if (ttlstr == NULL)
		goto error;

	dclass = STRTOK_R(NULL, "\t", &saveptr);
	if (dclass == NULL)
		goto error;

	type = STRTOK_R(NULL, "\t", &saveptr);
	if (type == NULL)
		goto error;

	data = STRTOK_R(NULL, "\t", &saveptr);
	if (data == NULL)
		goto error;

	if (name[strlen(name) - 1] != '.') {
		snprintf(absolute, sizeof(absolute), "%s.", name);
		name = absolute;
	}

	result = add_name(state, list, name, type,
			  strtoul(ttlstr, NULL, 10), data);
	free(buf);
	return (result);

 error:
	free(buf);
	return (ISC_R_FAILURE);
}
Example #4
0
static isc_result_t
modrdataset(struct dlz_example_data *state, const char *name,
	    const char *rdatastr, struct record *list)
{
	char *full_name, *dclass, *type, *data, *ttlstr;
	char *buf = strdup(rdatastr);
	isc_result_t result;
#if defined(WIN32) || defined(_REENTRANT)
	char *saveptr = NULL;
#endif

	/*
	 * The format is:
	 * FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
	 *
	 * The DATA field is space separated, and is in the data format
	 * for the type used by dig
	 */

	full_name = STRTOK_R(buf, "\t", &saveptr);
	if (full_name == NULL)
		return (ISC_R_FAILURE);

	ttlstr = STRTOK_R(NULL, "\t", &saveptr);
	if (ttlstr == NULL)
		return (ISC_R_FAILURE);

	dclass = STRTOK_R(NULL, "\t", &saveptr);
	if (dclass == NULL)
		return (ISC_R_FAILURE);

	type = STRTOK_R(NULL, "\t", &saveptr);
	if (type == NULL)
		return (ISC_R_FAILURE);

	data = STRTOK_R(NULL, "\t", &saveptr);
	if (data == NULL)
		return (ISC_R_FAILURE);

	result = add_name(state, list, name, type,
			  strtoul(ttlstr, NULL, 10), data);
	free(buf);
	return (result);
}
Example #5
0
static int get_band_num(char *bands, int band_count, const char *channel)
{
  char *t_channel, *ptr;
  int ii;

  char *t_bands = STRDUP(bands);
  t_channel = STRTOK_R(t_bands, ",", &ptr);
  if (t_channel != NULL && strcmp_case(t_channel, channel) == 0) {
    FREE(t_bands);
    return 0;
  }
  for (ii=1; ii<band_count; ii++) {
    t_channel = STRTOK_R(NULL, ",", &ptr);
    if (t_channel != NULL && strcmp_case(t_channel, channel) == 0) {
      FREE(t_bands);
      return ii;
    }
  }
  FREE(t_bands);
  return -1;
}
Example #6
0
void view_arg_convert(viewtab_entry *vtp, int vtp_parm, mval *parm, viewparm *parmblk, boolean_t is_dollar_view)
{
	static	int4		first_time = TRUE;
	char			*cptr;
	char			*strtokptr;
	gd_binding		*gd_map;
	gd_region		*gd_reg_start, *r_ptr, *r_top;
	gvnh_reg_t		*gvnh_reg;
	gvnh_spanreg_t		*gvspan;
	gv_namehead		*tmp_gvt;
	ht_ent_mname		*tabent;
	int			n, reg_index;
	mident_fixed		lcl_buff;
	mname_entry		gvent, lvent;
	mstr			namestr, tmpstr;
	unsigned char 		*c, *c_top, *dst, *dst_top, global_names[1024], *nextsrc, *src, *src_top, stashed, y;

	switch (vtp_parm)
	{
		case VTP_NULL:
			if (parm != 0)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			break;
		case (VTP_NULL | VTP_VALUE):
			if (NULL == parm)
			{
				parmblk->value = (mval *)&literal_one;
				break;
			}
			/* caution:  fall through */
		case VTP_VALUE:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			parmblk->value = parm;
			break;
		case (VTP_NULL | VTP_DBREGION):
			if (!is_dollar_view && ((NULL == parm) || ((1 == parm->str.len) && ('*' == *parm->str.addr))))
			{
				parmblk->gv_ptr = NULL;
				break;
			}
			/* caution:  fall through */
		case VTP_DBREGION:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			if (!gd_header)		/* IF GD_HEADER ==0 THEN OPEN GBLDIR */
				gvinit();
			r_ptr = gd_header->regions;
			if (!parm->str.len && vtp->keycode == VTK_GVNEXT)	/* "" => 1st region */
				parmblk->gv_ptr = r_ptr;
			else
			{
				for (cptr = parm->str.addr, n = 0; n < parm->str.len; cptr++, n++)
					lcl_buff.c[n] = TOUPPER(*cptr);		/* Region names are upper-case ASCII */
				namestr.len = n;
				namestr.addr = &lcl_buff.c[0];
				for (r_top = r_ptr + gd_header->n_regions; ; r_ptr++)
				{
					if (r_ptr >= r_top)
					{
						format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n);
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION,2, n, global_names);
					}
					tmpstr.len = r_ptr->rname_len;
					tmpstr.addr = (char *)r_ptr->rname;
					MSTR_CMP(tmpstr, namestr, n);
					if (0 == n)
						break;
				}
				parmblk->gv_ptr = r_ptr;
			}
			break;
		case VTP_DBKEY:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			if (!parm->str.len)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, parm->str.len, NULL);
			if (!gd_header)		/* IF GD_HEADER ==0 THEN OPEN GBLDIR */
				gvinit();
			c = (unsigned char *)parm->str.addr;
			if ('^' != *c)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, parm->str.len, c);
			c_top = c + parm->str.len;
			c++;				/* skip initial '^' */
			parmblk->str.addr = (char *)c;
			for ( ; (c < c_top) && ('(' != *c); c++)
				;
			parmblk->str.len = (char *)c - parmblk->str.addr;
			if (MAX_MIDENT_LEN < parmblk->str.len)
				parmblk->str.len = MAX_MIDENT_LEN;
			if (!valid_mname(&parmblk->str))
			{
				format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names);
			}
			break;
		case VTP_RTNAME:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			memset(&parmblk->ident.c[0], 0, SIZEOF(parmblk->ident));
			if (parm->str.len > 0)
				memcpy(&parmblk->ident.c[0], parm->str.addr,
				       (parm->str.len <= MAX_MIDENT_LEN ? parm->str.len : MAX_MIDENT_LEN));
			break;
		case VTP_NULL | VTP_DBKEYLIST:
			if (NULL == parm || 0 == parm->str.len)
			{
				parmblk->ni_list.gvnh_list = NULL;
				parmblk->ni_list.type = NOISOLATION_NULL;
				break;
			}
			/* caution : explicit fall through */
		case VTP_DBKEYLIST:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			if (!gd_header)
				gvinit();
			if (first_time)
			{
				noisolation_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list));
				initialize_list(noisolation_buddy_list, SIZEOF(noisolation_element), NOISOLATION_INIT_ALLOC);
				gvt_pending_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list));
				initialize_list(gvt_pending_buddy_list, SIZEOF(gvt_container), NOISOLATION_INIT_ALLOC);
				first_time = FALSE;
			}
			assertpro(SIZEOF(global_names) > parm->str.len);
			tmpstr.len = parm->str.len;	/* we need to change len and should not change parm->str, so take a copy */
			tmpstr.addr = parm->str.addr;
			if (0 != tmpstr.len)
			{
				switch (*tmpstr.addr)
				{
					case '+' :
						parmblk->ni_list.type = NOISOLATION_PLUS;
						tmpstr.addr++;
						tmpstr.len--;
						break;
					case '-' :
						parmblk->ni_list.type = NOISOLATION_MINUS;
						tmpstr.addr++;
						tmpstr.len--;
						break;
					default :
						parmblk->ni_list.type = NOISOLATION_NULL;
						break;
				}
				if (!tmpstr.len)
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, tmpstr.len, NULL);
				memcpy(global_names, tmpstr.addr, tmpstr.len);
				global_names[tmpstr.len] = '\0';
				src = (unsigned char *)STRTOK_R((char *)global_names, ",", &strtokptr);
				REINITIALIZE_LIST(noisolation_buddy_list);	/* reinitialize the noisolation buddy_list */
				parmblk->ni_list.gvnh_list = NULL;
				for ( ; src < &global_names[tmpstr.len + 1]; src = nextsrc)
				{
					nextsrc = (unsigned char *)STRTOK_R(NULL, ",", &strtokptr);
					if (NULL == nextsrc)
						nextsrc = &global_names[tmpstr.len + 1];
					if (nextsrc - src >= 2 && '^' == *src)
					{
						namestr.addr = (char *)src + 1;		/* skip initial '^' */
						namestr.len = INTCAST(nextsrc - src - 2); /* don't count initial ^ and trailing 0 */
						if (namestr.len > MAX_MIDENT_LEN)
							namestr.len = MAX_MIDENT_LEN;
						if (valid_mname(&namestr))
						{
							memcpy(&lcl_buff.c[0], namestr.addr, namestr.len);
							gvent.var_name.len = namestr.len;
						} else
						{
							memcpy(&lcl_buff.c[0], src, nextsrc - src - 1);
							format2zwr((sm_uc_ptr_t)&lcl_buff.c, nextsrc - src - 1, global_names, &n);
							rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names);
						}
					} else
					{
						memcpy(&lcl_buff.c[0], src, nextsrc - src - 1);
						format2zwr((sm_uc_ptr_t)&lcl_buff.c, nextsrc - src - 1, global_names, &n);
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names);
					}
					tmp_gvt = NULL;
					gvent.var_name.addr = &lcl_buff.c[0];
					COMPUTE_HASH_MNAME(&gvent);
					if (NULL != (tabent = lookup_hashtab_mname(gd_header->tab_ptr, &gvent)))
					{
						gvnh_reg = (gvnh_reg_t *)tabent->value;
						assert(NULL != gvnh_reg);
						tmp_gvt = gvnh_reg->gvt;
					} else
					{
						gd_map = gv_srch_map(gd_header, gvent.var_name.addr, gvent.var_name.len,
													SKIP_BASEDB_OPEN_FALSE);
						r_ptr = gd_map->reg.addr;
						tmp_gvt = (gv_namehead *)targ_alloc(r_ptr->max_key_size, &gvent, r_ptr);
						GVNH_REG_INIT(gd_header, gd_header->tab_ptr, gd_map, tmp_gvt,
											r_ptr, gvnh_reg, tabent);
						/* In case of a global spanning multiple regions, the gvt pointer corresponding to
						 * the region where the unsubscripted global reference maps to is stored in TWO
						 * locations (one in gvnh_reg->gvspan->gvt_array[index] and one in gvnh_reg->gvt.
						 * So pass in both these pointer addresses to be stored in the pending list in
						 * case this gvt gets reallocated (due to different keysizes between gld and db).
						 */
						if (NULL == (gvspan = gvnh_reg->gvspan))
						{
							ADD_TO_GVT_PENDING_LIST_IF_REG_NOT_OPEN(r_ptr, &gvnh_reg->gvt, NULL);
						} else
						{
							gd_reg_start = &gd_header->regions[0];
							GET_REG_INDEX(gd_header, gd_reg_start, r_ptr, reg_index);
								/* the above sets "reg_index" */
							assert(reg_index >= gvspan->min_reg_index);
							assert(reg_index <= gvspan->max_reg_index);
							reg_index -= gvspan->min_reg_index;
							ADD_TO_GVT_PENDING_LIST_IF_REG_NOT_OPEN(r_ptr,
								&gvspan->gvt_array[reg_index], &gvnh_reg->gvt);
						}
					}
					ADD_GVT_TO_VIEW_NOISOLATION_LIST(tmp_gvt, parmblk);
					if (!is_dollar_view && (NULL != gvnh_reg->gvspan))
					{	/* Global spans multiple regions. Make sure gv_targets corresponding to ALL
						 * spanned regions are allocated so NOISOLATION status can be set in all of
						 * them even if the corresponding regions are not open yet. Do this only for
						 * VIEW "NOISOLATION" commands which change the noisolation characteristic.
						 * $VIEW("NOISOLATION") only examines the characteristics and so no need to
						 * allocate all the gv-targets in that case. Just one is enough.
						 */
						gvnh_spanreg_subs_gvt_init(gvnh_reg, gd_header, parmblk);
					}
				}
			} else
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, tmpstr.len, tmpstr.addr);
			break;
		case VTP_LVN:
			if (NULL == parm)
				rts_error_csa(CSA_ARG(NULL)
					VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
			if (0 < parm->str.len)
			{
				lvent.var_name.addr = parm->str.addr;
				lvent.var_name.len = parm->str.len;
				if (lvent.var_name.len > MAX_MIDENT_LEN)
					lvent.var_name.len = MAX_MIDENT_LEN;
				if (!valid_mname(&lvent.var_name))
				{
					format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n);
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, n, global_names);
				}
			} else
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr);
			/* Now look up the name.. */
			COMPUTE_HASH_MNAME(&lvent);
			if ((tabent = lookup_hashtab_mname(&curr_symval->h_symtab, &lvent)) && (NULL != tabent->value))
				parmblk->value = (mval *)tabent->value;	/* Return lv_val ptr */
			else
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr);
			break;
		default:
			assertpro(FALSE && vtp_parm);
	}
}
Example #7
0
static int TryInstallDevice(
    const char *pInfFilePath,
    const char *pDevId,
    const char *pDevInstID,
    PCNC_DEV_CALLBACK pDevCallBack,
    void *pDevCallBackParam,
    bool updateDriver,
    BOOL *pRebootRequired)
{
  GUID classGUID;
  char className[32];

  if (!SetupDiGetINFClass(pInfFilePath, &classGUID, className, sizeof(className)/sizeof(className[0]), 0)) {
    ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiGetINFClass(%s)", pInfFilePath);
    return IDCANCEL;
  }

  //Trace("className=%s\n", className);

  HDEVINFO hDevInfo;

  hDevInfo = SetupDiCreateDeviceInfoList(&classGUID, 0);

  if (hDevInfo == INVALID_HANDLE_VALUE) {
    ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCreateDeviceInfoList()");
    return IDCANCEL;
  }

  int res = IDCONTINUE;
  SP_DEVINFO_DATA devInfoData;

  devInfoData.cbSize = sizeof(devInfoData);

  if (!pDevInstID) {
    if (StrCmpNI(pDevId, "root\\", 5) == 0) {
      /*
       * root\<enumerator-specific-device-ID>
       */

      if (!SetupDiCreateDeviceInfo(hDevInfo, pDevId + 5, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData))
        res = IDCANCEL;
    } else {
      SetLastError(ERROR_INVALID_DEVINST_NAME);
      res = IDCANCEL;
    }
  }
  else
  if (StrChr(pDevInstID, '\\')) {
    /*
     * <enumerator>\<enumerator-specific-device-ID>\<instance-specific-ID>
     */

    if (!SetupDiCreateDeviceInfo(hDevInfo, pDevInstID, &classGUID, NULL, 0, 0, &devInfoData))
      res = IDCANCEL;

    if (res != IDCONTINUE && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS) {
      char *pTmpDevInstID = NULL;

      if (SetStr(&pTmpDevInstID, pDevInstID)) {
        char *pSave;
        char *p;

        p = STRTOK_R(pTmpDevInstID, "\\", &pSave);

        if (p && !lstrcmp(p, REGSTR_KEY_ROOTENUM)) {
          p = STRTOK_R(NULL, "\\", &pSave);

          if (SetupDiCreateDeviceInfo(hDevInfo, p, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData))
            res = IDCONTINUE;
        }

        SetStr(&pTmpDevInstID, NULL);
      } else {
        SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
      }
    }
  } else {
    /*
     * <enumerator-specific-device-ID>
     */

    if (!SetupDiCreateDeviceInfo(hDevInfo, pDevInstID, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData))
      res = IDCANCEL;
  }

  if (res != IDCONTINUE) {
    ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCreateDeviceInfo()");
    goto exit1;
  }

  char hardwareId[MAX_DEVICE_ID_LEN + 1 + 1];

  SNPRINTF(hardwareId, sizeof(hardwareId)/sizeof(hardwareId[0]) - 1, "%s", pDevId);

  int hardwareIdLen;

  hardwareIdLen = lstrlen(hardwareId) + 1 + 1;
  hardwareId[hardwareIdLen - 1] = 0;

  if (!SetupDiSetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID,
                                        (LPBYTE)hardwareId, hardwareIdLen * sizeof(hardwareId[0])))
  {
    res = IDCANCEL;
    ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiSetDeviceRegistryProperty()");
    goto exit1;
  }

  if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDevInfo, &devInfoData)) {
    res = IDCANCEL;
    ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCallClassInstaller()");
    goto exit1;
  }

  if (pDevCallBack) {
    DevProperties devProperties;

    if (!devProperties.DevId(pDevId)) {
      res = IDCANCEL;
      goto exit2;
    }

    if (!pDevCallBack(hDevInfo, &devInfoData, &devProperties, NULL, pDevCallBackParam)) {
      res = IDCANCEL;
      goto exit2;
    }
  }

  if (updateDriver)
    res = UpdateDriver(pInfFilePath, pDevId, 0, TRUE, pRebootRequired);

exit2:

  if (res != IDCONTINUE) {
    if (!SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &devInfoData))
      ShowLastError(MB_OK|MB_ICONWARNING, "SetupDiCallClassInstaller()");
  }

exit1:

  SetupDiDestroyDeviceInfoList(hDevInfo);

  return res;
}