BOOL CDFFDUseStruct::OnInitDialog()
{
	CDialog::OnInitDialog();
	SetIcon(AfxGetApp()->LoadIcon(IDI_STRUCT), TRUE);

	// If window position specified
	if (pos_.y != -30000)
	{
		CRect rr;               // Rectangle where we will put the dialog
		GetWindowRect(&rr);

		// Move to where it was when it was last closed
		rr.OffsetRect(pos_.x - rr.left, pos_.y - rr.top);
		(void)::NeedsFix(rr);  // Make sure its visible

		MoveWindow(&rr);
	}

	if (!show_prev_next_)
	{
		// Hide << and >> (previous/next) buttons
		ctl_prev_.ShowWindow(SW_HIDE);
		ctl_next_.ShowWindow(SW_HIDE);
	}
	else
	{
		CXmlTree::CElt ee;
		if (parent_type_ == CHexEditDoc::DF_SWITCH)
			ee = pelt_->GetParent();
		else
			ee = *pelt_;
		ee--;
		ctl_prev_.EnableWindow(!ee.IsEmpty());

		if (parent_type_ == CHexEditDoc::DF_SWITCH)
			ee = pelt_->GetParent();
		else
			ee = *pelt_;
		++ee;
		ctl_next_.EnableWindow(!ee.IsEmpty());
	}

	load_data();

	return TRUE;
}
CDFFDUseStruct::CDFFDUseStruct(CXmlTree::CElt *pp, signed char parent_type, CWnd* pParent /*=NULL*/)
	: CDialog(CDFFDUseStruct::IDD, pParent), saved_(pp->GetOwner())
{
	modified_ = false;
	first_ = false;                     // Default to first (see SetPosition())

	pelt_ = pp;
	parent_type_ = parent_type;

	saved_.SaveKids(pelt_);
	saved_mod_flag_ = pelt_->GetOwner()->IsModified();
	show_prev_next_ = !pParent->IsKindOf(RUNTIME_CLASS(CDataFormatView)) &&
					  (parent_type == CHexEditDoc::DF_FILE ||
					   parent_type == CHexEditDoc::DF_STRUCT ||
					   parent_type == CHexEditDoc::DF_DEFINE_STRUCT ||
					   parent_type == CHexEditDoc::DF_SWITCH ||
					   parent_type == CHexEditDoc::DF_UNION);

	pos_.x = pos_.y = -30000;

	pstruct_menu_  = new CMenu;
	pstruct_menu_->CreatePopupMenu();

	// Build menu of structure definitions that the user can use
	// Note: define_struct elements are always the first children of the root (file) node
	CXmlTree::CElt ee = pelt_->GetOwner()->GetRoot().GetFirstChild();
	int item_no;
	for (item_no = 1; !ee.IsEmpty() && ee.GetName() == "define_struct"; ++item_no, ++ee)
		pstruct_menu_->AppendMenu(MF_ENABLED, item_no, ee.GetAttr("type_name"));

	// Check if no items were added (no struct definitions found)
	if (item_no == 1)
		pstruct_menu_->AppendMenu(MF_GRAYED, -1, _T("No definitions available"));

	// Hook up the menu to the BCG button
	ctl_struct_var_.m_hMenu = pstruct_menu_->GetSafeHmenu();
	ctl_struct_var_.m_bOSMenu = TRUE;
	ctl_struct_var_.m_bStayPressed = TRUE;
	ctl_struct_var_.m_bRightArrow = TRUE;

	//{{AFX_DATA_INIT(CDFFDUseStruct)
	comments_ = _T("");
	name_ = _T("");
	struct_ = _T("");
	expr_ = _T("");
	//}}AFX_DATA_INIT
}
Beispiel #3
0
static CMenu *make_menu(const CXmlTree::CElt &current_elt, int &item_no)
{
	CMenu * retval = new CMenu;
	retval->CreatePopupMenu();
	ASSERT(prev_defined.size() == 0);   // Make sure the list is cleared

	// There is no point in doing siblings of IF/SWITCH since only one element actually
	// exists - ie, if we are evaluating an element then the siblings will not exist.
	if (current_elt.GetParent().GetName() == "if" || current_elt.GetParent().GetName() == "switch")
		return retval;

	// Check all "older" siblings
	CXmlTree::CElt ee = current_elt;
	for (ee--; !ee.IsEmpty(); ee--)
	{
		add_menu_items(retval, item_no, ee, "");
	}

	prev_defined.clear();
	return retval;
}
bool CDFFDUseStruct::check_data()
{
	// Get values from the controls and validate them
	UpdateData();

	// Make sure name is given unless the container is a FOR (whence sub-elements are accessed via array index)
	if (name_.IsEmpty() && parent_type_ != CHexEditDoc::DF_FORV && parent_type_ != CHexEditDoc::DF_FORF)
	{
		TaskMessageBox("No Name", "Please enter a name for this element");
		ctl_name_.SetFocus();
		return false;
	}

	if (!name_.IsEmpty() && !valid_id(name_))
	{
		TaskMessageBox("Invalid STRUCT Name", "Please use alphanumeric characters (or "
						"underscores) and begin the name with an alphabetic character.");
		ctl_name_.SetFocus();
		return false;
	}
	if (name_.CompareNoCase("true") == 0 ||
		name_.CompareNoCase("false") == 0 ||
		name_.CompareNoCase("end") == 0 ||
		expr_eval::func_token(name_) != expr_eval::TOK_NONE)
	{
		TaskMessageBox("Reserved Name", name_ + " is reserved for internal use. Please choose another name.");
		ctl_name_.SetFocus();
		return false;
	}

	if (struct_.IsEmpty())
	{
		TaskMessageBox("No Defined Struct", "Please select a defined struct for this element");
		ctl_struct_.SetFocus();
		return false;
	}
	else if (!valid_id(struct_))
	{
		TaskMessageBox("Invalid Defined Struct Name", "Please use alphanumeric characters "
					  "(or underscore) and start with a alphabetic character.");
		ctl_name_.SetFocus();
		return false;
	}

	// We can only have an empty name if parent is FOR in which case there are no siblings
	ASSERT(!name_.IsEmpty() || pelt_->GetParent().GetNumChildren() == 1);

	// Check that the name is not the same as any siblings
	CXmlTree::CElt ee;

	// First find the actual element whose siblings we want to check (an IF takes the name of its child)
	for (ee = *pelt_; ee.GetParent().GetName() == "if" || ee.GetParent().GetName() == "jump"; ee = ee.GetParent())
		; // empty loop body

	// Check that older siblings don't have the same name
	for (ee--; !ee.IsEmpty(); ee--)
	{
		CXmlTree::CElt ee2;
		for (ee2 = ee; !ee2.IsEmpty() && (ee2.GetName() == "if" || ee2.GetName() == "jump"); ee2 = ee2.GetFirstChild())
			; // nothing here
		if (!ee2.IsEmpty() && ee2.GetAttr("name") == name_)
		{
			TaskMessageBox("Name in use", name_ + " has a sibling with the same name.\n\n"
				           "It is not be possible to differentiate between two elements "
			               "with the same name at the same level (eg, in expressions).");
			ctl_name_.SetFocus();
			return false;
		}
	}

	for (ee = *pelt_; ee.GetParent().GetName() == "if" || ee.GetParent().GetName() == "jump"; ee = ee.GetParent())
		; // empty loop body

	// Check that younger siblings don't have the same name
	for (++ee; !ee.IsEmpty(); ++ee)
	{
		CXmlTree::CElt ee2;
		for (ee2 = ee; !ee2.IsEmpty() && (ee2.GetName() == "if" || ee2.GetName() == "jump"); ee2 = ee2.GetFirstChild())
			; // nothing here
		if (!ee2.IsEmpty() && ee2.GetAttr("name") == name_)
		{
			TaskMessageBox("Name in use", name_ + " has a sibling with the same name.\n\n"
				           "It is not be possible to differentiate between two elements "
			               "with the same name at the same level (eg, in expressions).");
			ctl_name_.SetFocus();
			return false;
		}
	}

	return true;
}
Beispiel #5
0
CString get_name(const CXmlTree::CElt &ee)
{
	ASSERT(!ee.IsEmpty());
	CString elt_type = ee.GetName();

	if (elt_type == "define_struct")
	{
		return ee.GetAttr("type_name") + CString(" [STRUCT DEFN]");
	}
	else if (elt_type == "struct")
	{
		return ee.GetAttr("name") + CString(" [STRUCT]");
	}
	else if (elt_type == "use_struct")
	{
		return ee.GetAttr("name") + CString(" - using ") + ee.GetAttr("type_name");
	}
	else if (elt_type == "for")
	{
		CString name = ee.GetAttr("name");

		if (name.IsEmpty())
			return CString("[FOR] - ") + get_name(ee.GetFirstChild());
		else
			return name + CString(" [FOR]");
	}
	else if (elt_type == "if")
	{
		CString name1 = get_name(ee.GetFirstChild());
		CString name2;
		if (ee.GetNumChildren() > 1)
		{
			// Get name for else part
			ASSERT(ee.GetNumChildren() == 3 && ee.GetChild(1).GetName() == "else");
			name2 = get_name(ee.GetChild(2));
		}
		if (name1.IsEmpty())
			name1 = name2;              // no name for IF part so use else part
		else if (!name2.IsEmpty() && name1 != name2)
			name1 += "/" + name2;       // Combine both names
		return CString("[IF] - ") + name1;
	}
	else if (elt_type == "switch")
	{
		return CString("[CASE] ") + ee.GetAttr("test");
	}
	else if (elt_type == "jump")
	{
		return CString("[JUMP] - ") + get_name(ee.GetFirstChild());
	}
	else if (elt_type == "eval")
	{
		return CString("[EVAL] ") + ee.GetAttr("expr");
	}
	else if (elt_type == "data")
	{
		CString name = ee.GetAttr("name");
		if (name.IsEmpty())
			return CString("[DATA]");
		else
			return name;
	}
	else
		ASSERT(0);

	return CString("ERROR");
}
Beispiel #6
0
// Static functions used by make_var_menu_tree (below)
static void add_menu_items(CMenu *pmenu, int &item_no, const CXmlTree::CElt &current_elt, CString name)
{
	CString ss = current_elt.GetName();    // type of this node

	// Add element name unless parent is FOR (or we are IF/SWITCH/JUMP which use child name)
	if (ss != "if" && ss != "switch" && ss != "jump" && name.Right(1) != "]")
		name += current_elt.GetAttr("name");

	if (ss == "data")
	{
		pmenu->AppendMenu(MF_ENABLED, item_no++, name);
	}
	else if (ss == "for")
	{
		// Add array access operator [] and add item(s) for sub-element
		ASSERT(current_elt.GetNumChildren() <= 1);                              // May be zero for new elt
		if (current_elt.GetNumChildren() > 0)
			add_menu_items(pmenu, item_no, current_elt.GetFirstChild(), name+"[ ]");
	}
	else if (ss == "struct")
	{
		// Add items for all sub-elements of the struct
		for (CXmlTree::CElt ee = current_elt.GetFirstChild(); !ee.IsEmpty(); ++ee)
		{
			add_menu_items(pmenu, item_no, ee, name+".");
		}
	}
	else if (ss == "use_struct")
	{
		CString ss = current_elt.GetAttr("type_name");            // Find struct name to use
		CXmlTree::CElt ee = current_elt.GetOwner()->GetRoot().GetFirstChild();
		for ( ; !ee.IsEmpty() && ee.GetName() == "define_struct"; ++ee)
			if (ss == ee.GetAttr("type_name"))
			{
				// Check if recursive call to same defined struct
				for (std::vector<CString>::const_iterator ps = prev_defined.begin(); ps != prev_defined.end(); ++ps)
				{
					if (*ps == ss)
						return;    // avoid recursion into same define_struct
				}
				prev_defined.push_back(ss);

				// Add items for all sub-elements of the struct
				for (CXmlTree::CElt ee2 = ee.GetFirstChild(); !ee2.IsEmpty(); ++ee2)
				{
					add_menu_items(pmenu, item_no, ee2, name+".");
				}
				break;    // Found the (hopefully) only one with the correct name
			}
	}
	else if (ss == "if")
	{
		if (current_elt.GetNumChildren() > 0)
			add_menu_items(pmenu, item_no, current_elt.GetFirstChild(), name);
		if (current_elt.GetNumChildren() > 1)
		{
			// Add a separate item for the else part
			ASSERT(current_elt.GetNumChildren() == 3 && current_elt.GetChild(1).GetName() == "else");
			add_menu_items(pmenu, item_no, current_elt.GetChild(2), name);
		}
	}
	else if (ss == "switch")
	{
		// Add names of all case sub-elements
		CStringList found;      // just used to eliminate duplicate data elts
		for (CXmlTree::CElt ee = current_elt.GetFirstChild(); !ee.IsEmpty(); ++ee)
		{
			ASSERT(ee.GetName() == "case");
			if (ee.GetFirstChild().GetName() == "data")
			{
				CString ss = ee.GetFirstChild().GetAttr("name");
				if (!ss.IsEmpty())
				{
					if (found.Find(ss) != NULL)
						continue;           // ignore data elements with the same name
					else
						found.AddTail(ss);  // store this one for later checks
				}
			}
			add_menu_items(pmenu, item_no, ee.GetFirstChild(), name);
		}
	}
	else if (ss == "jump")
	{
		if (current_elt.GetNumChildren() > 0)
			add_menu_items(pmenu, item_no, current_elt.GetFirstChild(), name);
	}
	else if (ss == "define_struct" || ss == "eval")
	{
		// Do nothing here
	}
	else
		ASSERT(0);
}
Beispiel #7
0
// Return the size of an element (if it only contains data and/or struct elements) checking
// the size of struct children if necessary.  If any children are DATA elements with calc'd
// size (or FOR or IF) then -1 is returned.
long get_size(const CXmlTree::CElt &ee, int first /*=0*/, int last /*=999999999*/)
{
	long retval = 0;
	CXmlTree::CElt child;
	int ii;
	int bits_used = 0;   // Bits used by all consec. bitfields so far (0 if previous elt not a bitfield)
	int last_size;       // Storage unit size of previous element if a bitfield (1,2,4, or 8) or 0
	bool last_down;      // Direction for previous bitfield (must be same dirn to be put in same stg unit)

	for (child = ee.GetChild(first), ii = first; !child.IsEmpty() && ii < last; ++child, ++ii)
	{
		CString elt_type = child.GetName();
		if (elt_type != "data" && bits_used > 0)
		{
			// End of bit-field stg unit
			ASSERT(last_size == 1 || last_size == 2 || last_size == 4 || last_size == 8);
			retval += last_size;
			bits_used = 0;
		}

		if (elt_type == "data")
		{
			CString ss = child.GetAttr("type");
			int data_bits = 0;   // bits used in this element (or zero if not a bit-field)
			int data_size;
			bool data_down;

			// Check for bit-field (type is "int")
			if (ss.CompareNoCase("int") == 0)
			{
				data_bits = atoi(child.GetAttr("bits"));
				if (data_bits > 0)
				{
					data_size = atoi(child.GetAttr("len"));
					data_down = child.GetAttr("direction") == "down";
				}
			}

			if (bits_used > 0 &&
				(data_bits == 0 ||                     // not bit-field
				 data_size != last_size ||             // diff size
				 data_down != last_down ||             // diff dirn
				 bits_used + data_bits > data_size*8)  // overflow stg unit
			   )
			{
				// Previous elt was end of the bit-field stg unit
				ASSERT(last_size == 1 || last_size == 2 || last_size == 4 || last_size == 8);
				retval += last_size;
				bits_used = 0;
			}

			if (data_bits > 0)
			{
				// Save info about current bit-field
				bits_used += data_bits;
				last_size = data_size;
				last_down = data_down;
			}
			else if (ss.CompareNoCase("char") == 0)
			{
				// Work out the size of a character (normally 1 unless Unicode)
				ss = child.GetAttr("format");
				if (ss.CompareNoCase("unicode") == 0)
					retval += 2;
				else
					retval += 1;
			}
			else if (ss.CompareNoCase("date") == 0)
			{
				// Work out the size of the date field depending on the format
				ss = child.GetAttr("format");
				if (ss.CompareNoCase("c") == 0)
					retval += 4;
				else if (ss.CompareNoCase("c51") == 0)
					retval += 4;
				else if (ss.CompareNoCase("c7") == 0)
					retval += 4;
				else if (ss.CompareNoCase("cmin") == 0)
					retval += 4;
				else if (ss.CompareNoCase("c64") == 0)
					retval += 8;
				else if (ss.CompareNoCase("ole") == 0)
					retval += 8;
				else if (ss.CompareNoCase("systemtime") == 0)
					retval += 16;
				else if (ss.CompareNoCase("filetime") == 0)
					retval += 8;
				else if (ss.CompareNoCase("msdos") == 0)
					retval += 4;
				else
				{
					ASSERT(0);
					return -1;
				}
			}
			else
			{
				// Get the size of the child by checking
				ss = child.GetAttr("len");
				char *endp;
				//ss.TrimLeft();
				//ss.TrimRight();

				// Note: we could use expression parser to handle constant expression (eg, "10+1") but is it necessary?
				long len = strtoul(ss, &endp, 10);
				// Make sure the string was not empty and there was nothing after the number (eg, not "5+n")
				if (endp > (const char *)ss && endp - (const char *)ss == ss.GetLength())
					retval +=len;
				else
					return -1L;             // Does not appear to be a simple number so assume it is an expression
			}
		}
		else if (elt_type == "struct" || elt_type == "binary_file_format")
		{
			// Get the size of child by looking at its children
			long child_size = get_size(child);
			if (child_size > -1)
				retval += child_size;
			else
				return -1L;             // Child size is indeterminate, therefore so is our size
		}
		else if (elt_type == "use_struct")
		{
			long tmp = -1;
			// Find define_struct and get its size
			CString ss = child.GetAttr("type_name");            // Find struct name to use
			CXmlTree::CElt ee = child.GetOwner()->GetRoot().GetFirstChild();
			for ( ; !ee.IsEmpty() && ee.GetName() == "define_struct"; ++ee)
				if (ss == ee.GetAttr("type_name"))
					tmp = get_size(ee);

			// Not found
			if (tmp == -1)
				return -1L;
			else
				retval += tmp;
		}
		else if (elt_type == "eval" || elt_type == "jump" || elt_type == "define_struct")
			;  // zero size so just do nothing to retval
		else if (elt_type == "for")
		{
			// Get the size of the FOR elt's (only) child and multiply by the number of array elts
			long child_size = get_size(child);
			if (child_size <= -1)
				return -1L;             // Child size is indeterminate, therefore so is our size

			// Handle FOR that contains a constant integer in count
			CString ss = child.GetAttr("count");
			char *endp;
			ss.TrimLeft();
			ss.TrimRight();

			// Note: we could use expression parser to handle constant expression (eg, "10+1") but is it necessary?
			long count = strtoul(ss, &endp, 10);
			// Make sure the string was not empty and there was nothing after the number (eg not "10*n")
			if (endp > (const char *)ss && endp - (const char *)ss == ss.GetLength())
				retval += count * child_size;
			else
				return -1L;             // Does not appear to be a simple number so assume it is an expression
		}
		else
			return -1L;  // xxx handle constant size IF/FOR
	}

	// Add last bit-field stg unit if there was one
	if (bits_used > 0)
	{
		ASSERT(last_size == 1 || last_size == 2 || last_size == 4 || last_size == 8);

		// Don't add stg unit if elt after the range (ie last) is part of the same unit as the previous elt
		bool add_last = true;

		if (last < ee.GetNumChildren())  // make sure we are not off the end
		{
			ASSERT(!child.IsEmpty());
			int data_bits;

			// Check if last (elt one past the end) is part of the previous bit-field stg unit
			if (child.GetName() == "data" &&                              // data field
				child.GetAttr("type").CompareNoCase("int") == 0 &&        // integer type
				(data_bits = atoi(child.GetAttr("bits"))) > 0 &&          // bitfield
				atoi(child.GetAttr("len")) == last_size &&                // same size as previous one
				(child.GetAttr("direction") == "down") == last_down &&    // same dirn as previous one
				bits_used + data_bits <= last_size*8)
			{
				add_last = false;  // part way through a stg unit so don't add it to the size
			}
		}
		if (add_last)
			retval += last_size;
	}

	return retval;
}
Beispiel #8
0
BOOL CDFFDJump::OnInitDialog()
{
	CDialog::OnInitDialog();
	SetIcon(AfxGetApp()->LoadIcon(IDI_JUMP), TRUE);

	// If window position specified
	if (pos_.y != -30000)
	{
		CRect rr;               // Rectangle where we will put the dialog
		GetWindowRect(&rr);

		// Move to where it was when it was last closed
		rr.OffsetRect(pos_.x - rr.left, pos_.y - rr.top);
		(void)::NeedsFix(rr);  // Make sure its visible

		MoveWindow(&rr);
	}

	if (!show_prev_next_)
	{
		// Hide << and >> (previous/next) buttons
		ctl_prev_.ShowWindow(SW_HIDE);
		ctl_next_.ShowWindow(SW_HIDE);
	}
	else
	{
		CXmlTree::CElt ee;
		if (parent_type_ == CHexEditDoc::DF_SWITCH)
			ee = pelt_->GetParent();
		else
			ee = *pelt_;
		ee--;
		ctl_prev_.EnableWindow(!ee.IsEmpty());

		if (parent_type_ == CHexEditDoc::DF_SWITCH)
			ee = pelt_->GetParent();
		else
			ee = *pelt_;
		++ee;
		ctl_next_.EnableWindow(!ee.IsEmpty());
	}

	load_data();

	// Setup menu button that allows replace of struct/for/if/data
	VERIFY(button_menu_.LoadMenu(IDR_DFFD));
	CString strTemp;
	ASSERT((button_menu_.GetMenuString(4, strTemp, MF_BYPOSITION), strTemp == "ButtonReplace"));

	// Disable insertion of jump within a jump
	button_menu_.GetSubMenu(4)->EnableMenuItem(ID_DFFD_INSERT_JUMP, MF_BYCOMMAND | MF_GRAYED);

	ctl_replace_.m_hMenu = button_menu_.GetSubMenu(4)->GetSafeHmenu();
//    ctl_replace_.SizeToContent();
	ctl_replace_.m_bOSMenu = TRUE;
	ctl_replace_.m_bStayPressed = TRUE;
	ctl_replace_.m_bRightArrow = TRUE;

	// Set up menu that allows the user to choose any valid variable name
	poffset_menu_ = make_var_menu_tree(*pelt_);
	ctl_offset_var_.m_hMenu = poffset_menu_->GetSafeHmenu();
	ctl_offset_var_.m_bOSMenu = TRUE;
	ctl_offset_var_.m_bStayPressed = TRUE;
	ctl_offset_var_.m_bRightArrow = TRUE;
	ctl_offset_.SetSel(0, -1);           // Select all so a var selection (see OnGetOffsetVar) replaces current contents
	return TRUE;
}