bool idaapi type_builder_t::check_memptr(struct_filed &str_fld)
{
	// check if it has at least two parents
	if ( parents.size() > 2 )
	{
		citem_t *parent_1 = parents.back();

		// check if its parent is memptr
		if(parent_1->is_expr() && (parent_1->op == cot_memptr))
		{
			citem_t *parent_2 = parents[parents.size() - 2];
			citem_t *parent_3 = NULL;
			
			int num = 0;
			int off = 0;
			
			// check presence of the helper block
			bool bHelper = check_helper(parent_2, off, num);
			if(bHelper)
				parent_3 = parents[parents.size() - 3];
			else
				parent_3 = parent_2;

			if(parent_2->is_expr() && (parent_2->op == cot_asg))
			{
				cexpr_t *expr = (cexpr_t *)parent_1;

				if(bHelper)
				{
					str_fld.offset = expr->m + off;
					str_fld.size = num;
				}
				else
				{
					str_fld.offset = expr->m;
					str_fld.size = expr->ptrsize;
				}

				return true;
			}
		}
	}

	return false;
}
bool idaapi type_builder_t::check_ptr(struct_filed &str_fld)
{
	// check if it has at least three parents
	if ( parents.size() > 2 )
	{
		citem_t *parent_1 = parents.back();
		int offset = 0;
		int parent_idx = 1;

		// if its parent is addition 
		if(parent_1->is_expr() && (parent_1->op == cot_add))
		{
			parent_idx ++;
			cexpr_t *expr_2 = (cexpr_t *)parent_1;
				
			// get index_value
			char buff[MAXSTR];
			expr_2->y->print1(buff, MAXSTR, NULL);
			tag_remove(buff, buff, 0);
			offset = atoi(buff);
		}

		citem_t *parent_3 = parents[parents.size() - parent_idx];
		if(parent_3->is_expr() && (parent_3->op == cot_cast))
			parent_idx ++;
			
		citem_t *parent_4 = parents[parents.size() - parent_idx];
		if(parent_4->is_expr() && (parent_4->op == cot_ptr))
		{
			parent_idx ++;
			citem_t *parent_5 = parents[parents.size() - parent_idx];

			int num_hlpr = 0;
			int off_hlpr = 0;
			
			bool bHelper = check_helper(parent_5, off_hlpr, num_hlpr);
			if(bHelper)
				parent_idx ++;

			citem_t *parent_6 = parents[parents.size() - parent_idx];
			if(parent_6->is_expr() && (parent_6->op == cot_asg))
			{
				cexpr_t *expr_4 = (cexpr_t *)parent_4;	

				if(bHelper)
				{
					str_fld.offset = offset + off_hlpr;
					str_fld.size = num_hlpr;
				}
				else
				{
					str_fld.offset = offset;
					str_fld.size = expr_4->ptrsize;
				}

				return true;
			}
		}
	}

	return false;
}
bool idaapi type_builder_t::check_ptr(cexpr_t *e, struct_filed &str_fld)
{
	str_fld.offset = 0;
	str_fld.size = 0;
	str_fld.vftbl = BADADDR;

	type_reference referInfo;
	referInfo.init(e);

	qstring dbg_info;

	bool done = false;

	int par_size = parents.size();
	// check if it has at least three parents
	if ( par_size > 2 )
	{
		int offset = 0;
		int parent_idx = 1;

		int num = 0;
		int off = 0;

		for (size_t i = 0 ; i < parents.size() - 1 ; i ++) {
			citem_t *parent_i = parents[parents.size() - i - 1];

			// if its parent is addition 
			if(parent_i->is_expr() && (parent_i->op == cot_add))
			{
				cexpr_t *expr_2 = (cexpr_t *)parent_i;
				
				// get index_value
				char buff[MAXSTR];
				expr_2->y->print1(buff, MAXSTR, NULL);
				tag_remove(buff, buff, 0);
				
				int base = 10;
				if (strncmp(buff, "0x", 2) == 0)
					base = 16;
				
				offset = strtol(buff, NULL, base);

				referInfo.update_offset(offset);
			} else if(parent_i->is_expr() && (parent_i->op == cot_cast)) {
				referInfo.update_type((cexpr_t *)parent_i);
			} else if(parent_i->is_expr() && check_helper((cexpr_t *)parent_i, off, num)) {
				referInfo.update_hlpr(off, num);
			} else if(parent_i->is_expr() && (parent_i->op == cot_ptr)) {
				referInfo.update_size(((cexpr_t *)parent_i)->ptrsize);
				citem_t *parent_ii = parents[parents.size() - i - 2];
				// check the r-value for a pointer to vftable
				if ((parent_ii->is_expr()) && (((cexpr_t *)parent_ii)->op == cot_asg) && (((cexpr_t *)parent_ii)->x == parent_i)) {
					ea_t vftbl = get_vftbl(((cexpr_t *)parent_ii)->y);
					if (vftbl != BADADDR)
						str_fld.vftbl = vftbl;
				}
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_memptr)) {
				referInfo.update_offset(((cexpr_t *)parent_i)->m);
				referInfo.update_size(((cexpr_t *)parent_i)->ptrsize);
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_asg)) {
				if (((cexpr_t *)parent_i)->y == e) { //parents[parents.size() - i]) {
					char expr_name[MAXSTR];
					((cexpr_t *)parent_i)->x->print1(expr_name, MAXSTR, NULL);
					tag_remove(expr_name, expr_name, 0);

					char comment[258];
					memset(comment, 0x00, sizeof(comment));
					sprintf_s(comment, sizeof(comment), "monitoring %s\r\n", expr_name);

					msg(comment);

					expression_to_match.push_back(expr_name);
				} else {
					get_vftbl(((cexpr_t *)parent_i)->y);
				}
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_call)) {
				done = true;
				break;
			}
		}
	}

	if(done) {
		str_fld.offset = referInfo.get_offset();
		str_fld.size = referInfo.get_size();
		if (str_fld.size == 0) {
			str_fld.size = 4;
		}

		if (str_fld.vftbl != BADADDR) {
			char tmp[1024];
			memset(tmp, 0x00, sizeof(tmp));
			sprintf_s(tmp, sizeof(tmp), "possible vftbl reference detected at offset 0x%X, ea=0x%08X\r\n", str_fld.offset, str_fld.vftbl);

			msg(tmp);
		}
	}

	return done;
}
bool idaapi type_builder_t::check_ptr(cexpr_t *e, struct_filed &str_fld)
{
	type_reference referInfo;
	referInfo.init(e);

	qstring dbg_info;

	bool done = false;

	int par_size = parents.size();
	// check if it has at least three parents
	if ( par_size > 2 )
	{
		int offset = 0;
		int parent_idx = 1;

		int num = 0;
		int off = 0;

		for (size_t i = 0 ; i < parents.size() - 1 ; i ++) {
			citem_t *parent_i = parents[parents.size() - i - 1];

			// if its parent is addition 
			if(parent_i->is_expr() && (parent_i->op == cot_add))
			{
				cexpr_t *expr_2 = (cexpr_t *)parent_i;
				
				// get index_value
				char buff[MAXSTR];
				expr_2->y->print1(buff, MAXSTR, NULL);
				tag_remove(buff, buff, 0);
				offset = atoi(buff);

				referInfo.update_offset(offset);
			} else if(parent_i->is_expr() && (parent_i->op == cot_cast)) {
				referInfo.update_type((cexpr_t *)parent_i);
			} else if(parent_i->is_expr() && check_helper((cexpr_t *)parent_i, off, num)) {
				referInfo.update_hlpr(off, num);
			} else if(parent_i->is_expr() && (parent_i->op == cot_ptr)) {
				referInfo.update_size(((cexpr_t *)parent_i)->ptrsize);
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_memptr)) {
				referInfo.update_offset(((cexpr_t *)parent_i)->m);
				referInfo.update_size(((cexpr_t *)parent_i)->ptrsize);
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_asg)) {
				done = true;
				break;
			} else if(parent_i->is_expr() && (parent_i->op == cot_call)) {
				done = true;
				break;
			}
		}
	}

	if(done) {
		str_fld.offset = referInfo.get_offset();
		str_fld.size = referInfo.get_size();
		if (str_fld.size == 0) {
			str_fld.size = 4;
		}
	}

	return done;
}