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 }
static CMenu *make_menu(const CXmlTree::CElt ¤t_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; }
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"); }
// Static functions used by make_var_menu_tree (below) static void add_menu_items(CMenu *pmenu, int &item_no, const CXmlTree::CElt ¤t_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); }
// 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; }
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; }