Merge branch 'GP-2821_ryanmkurtz_PR-3808_goatshriek_fix-dialog-resource'

This commit is contained in:
Ryan Kurtz 2022-11-14 11:20:20 -05:00
commit 707ec9288d
2 changed files with 232 additions and 6 deletions

View File

@ -92,10 +92,10 @@ public class DialogResourceDataType extends DynamicDataType {
tempOffset = addDialogTitleArray(memBuffer, comps, tempOffset);
//Check to see if extra font size and array info after three dialog items
//will only be there if DS_SETFONT mask is set at offset 0 of DLGTEMPLATE
byte getStyle = memBuffer.getByte(0);
//will only be there if DS_SETFONT mask is set in the style field
byte getStyle = memBuffer.getByte(ex ? 12 : 0);
if ((getStyle & DS_SETFONT) > 0) {
tempOffset = addDialogFontSizeAndArray(memBuffer, comps, tempOffset);
tempOffset = addDialogFontComponents(memBuffer, comps, tempOffset, ex);
}
//get cdit value at offset 8 of DLGTEMPLATE or offset 16 of DLGTEMPLATEEX
@ -199,14 +199,31 @@ public class DialogResourceDataType extends DynamicDataType {
return tempOffset;
}
//adds Dialog font size and font array - the OPTIONAL 4th and 5th components after the DLGTEMPLATE structure
private int addDialogFontSizeAndArray(MemBuffer memBuffer, List<DataTypeComponent> comps,
int tempOffset) {
//adds Dialog font components
//for DLGITEMTEMPLATE structures this is the font size and typeface array
//for DLGITEMTEMPLATEEX structures three additional fields (weight, italic, and
//charset) are added in between the font size and typeface
private int addDialogFontComponents(MemBuffer memBuffer, List<DataTypeComponent> comps,
int tempOffset, boolean ex) {
//add Dialog Font size
tempOffset =
addComp(new ShortDataType(), 2, "Dialog Font Size",
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
if (ex) {
//add Dialog Font weight
tempOffset = addComp(new WordDataType(), 2, "Dialog Font Weight", memBuffer.getAddress().add(tempOffset),
comps, tempOffset);
//add Dialog Font Italic
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Italic", memBuffer.getAddress().add(tempOffset),
comps, tempOffset);
//add Dialog Font Charset
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Charset", memBuffer.getAddress().add(tempOffset),
comps, tempOffset);
}
//add Dialog Font Style array
tempOffset = addUnicodeString(memBuffer, comps, tempOffset, "Dialog Font Typeface");
return tempOffset;

View File

@ -0,0 +1,209 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.data;
import static org.junit.Assert.assertEquals;
import java.nio.charset.Charset;
import org.junit.Before;
import org.junit.Test;
import generic.test.AbstractGTest;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.GenericAddressSpace;
import ghidra.program.model.mem.ByteMemBufferImpl;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.LittleEndianDataConverter;
public class DialogResourceDataTypeTest extends AbstractGTest {
private GenericAddressSpace addressSpace;
@Before
public void setUp() {
addressSpace = new GenericAddressSpace("Test Address Space", 32, AddressSpace.TYPE_RAM, 1);
}
@Test
public void testDlgTemplate() throws MemoryAccessException {
byte[] dialogTemplate = getDlgTemplateResource();
MemBuffer mb = new ByteMemBufferImpl(addressSpace.getAddress(0), dialogTemplate, false);
DialogResourceDataType dr = new DialogResourceDataType();
DataTypeComponent[] components = dr.getAllComponents(mb);
assertEquals(6, components.length);
DataTypeComponent titleComponent = components[3];
assertEquals("Dialog Title", titleComponent.getFieldName());
byte[] titleBytes = new byte[titleComponent.getLength() - 2]; // cut off the null terminator
mb.getBytes(titleBytes, titleComponent.getOffset());
String title = new String(titleBytes, Charset.forName("UTF-16LE"));
assertEquals("Test Dialog", title);
DataTypeComponent sizeComponent = components[4];
assertEquals("Dialog Font Size", sizeComponent.getFieldName());
assertEquals(8, mb.getShort(sizeComponent.getOffset()));
DataTypeComponent typefaceComponent = components[5];
assertEquals("Dialog Font Typeface", typefaceComponent.getFieldName());
byte[] typefaceBytes = new byte[typefaceComponent.getLength() - 2]; // cut off the null terminator
mb.getBytes(typefaceBytes, typefaceComponent.getOffset());
String typeface = new String(typefaceBytes, Charset.forName("UTF-16LE"));
assertEquals("Test Typeface", typeface);
}
@Test
public void testDlgTemplateEx() throws MemoryAccessException {
byte[] dialogTemplateEx = getDlgTemplateExResource();
MemBuffer mb = new ByteMemBufferImpl(addressSpace.getAddress(0), dialogTemplateEx, false);
DialogResourceDataType dr = new DialogResourceDataType();
DataTypeComponent[] components = dr.getAllComponents(mb);
assertEquals(9, components.length);
DataTypeComponent titleComponent = components[3];
assertEquals("Dialog Title", titleComponent.getFieldName());
byte[] titleBytes = new byte[titleComponent.getLength() - 2]; // cut off the null terminator
mb.getBytes(titleBytes, titleComponent.getOffset());
String title = new String(titleBytes, Charset.forName("UTF-16LE"));
assertEquals("Test Dialog", title);
DataTypeComponent sizeComponent = components[4];
assertEquals("Dialog Font Size", sizeComponent.getFieldName());
assertEquals(8, mb.getShort(sizeComponent.getOffset()));
DataTypeComponent weightComponent = components[5];
assertEquals("Dialog Font Weight", weightComponent.getFieldName());
assertEquals(400, mb.getShort(weightComponent.getOffset()));
DataTypeComponent italicComponent = components[6];
assertEquals("Dialog Font Italic", italicComponent.getFieldName());
assertEquals(0, mb.getByte(italicComponent.getOffset()));
DataTypeComponent charsetComponent = components[7];
assertEquals("Dialog Font Charset", charsetComponent.getFieldName());
assertEquals(1, mb.getByte(charsetComponent.getOffset()));
DataTypeComponent typefaceComponent = components[8];
assertEquals("Dialog Font Typeface", typefaceComponent.getFieldName());
byte[] typefaceBytes = new byte[typefaceComponent.getLength() - 2]; // cut off the null terminator
mb.getBytes(typefaceBytes, typefaceComponent.getOffset());
String typeface = new String(typefaceBytes, Charset.forName("UTF-16LE"));
assertEquals("Test Typeface", typeface);
}
private byte[] getDlgTemplateExResource() {
byte[] resourceBytes = new byte[88];
LittleEndianDataConverter leConverter = LittleEndianDataConverter.INSTANCE;
// @formatter:off
leConverter.putShort(resourceBytes, 0, (short) 1); // dlgVer, must be 1
leConverter.putShort(resourceBytes, 2, (short) -1); // signature, must be 0xffff
leConverter.putInt( resourceBytes, 4, 0); // helpID
leConverter.putInt( resourceBytes, 8, 0); // exStyle
leConverter.putInt( resourceBytes, 12, 0x40); // style: DS_SETFONT
leConverter.putShort(resourceBytes, 16, (short) 0); // cDlgItems (none)
leConverter.putShort(resourceBytes, 18, (short) 0); // x
leConverter.putShort(resourceBytes, 20, (short) 0); // y
leConverter.putShort(resourceBytes, 22, (short) 0xd0); // cx
leConverter.putShort(resourceBytes, 24, (short) 0xd0); // cy
leConverter.putShort(resourceBytes, 26, (short) 0); // menu: (none)
leConverter.putShort(resourceBytes, 28, (short) 0); // windowClass: (predefined dialog box class)
leConverter.putShort(resourceBytes, 30, (short) 0x54); // title: "Test Dialog"
leConverter.putShort(resourceBytes, 32, (short) 0x65);
leConverter.putShort(resourceBytes, 34, (short) 0x73);
leConverter.putShort(resourceBytes, 36, (short) 0x74);
leConverter.putShort(resourceBytes, 38, (short) 0x20);
leConverter.putShort(resourceBytes, 40, (short) 0x44);
leConverter.putShort(resourceBytes, 42, (short) 0x69);
leConverter.putShort(resourceBytes, 44, (short) 0x61);
leConverter.putShort(resourceBytes, 46, (short) 0x6c);
leConverter.putShort(resourceBytes, 48, (short) 0x6f);
leConverter.putShort(resourceBytes, 50, (short) 0x67);
leConverter.putShort(resourceBytes, 52, (short) 0x0);
// optional font fields, present here because DS_SETFONT was used
leConverter.putShort(resourceBytes, 54, (short) 8); // pointsize
leConverter.putShort(resourceBytes, 56, (short) 400); // weight: FW_NORMAL
resourceBytes[58] = 0; // italic: FALSE
resourceBytes[59] = (byte) 1; // charset: DEFAULT_CHARSET
leConverter.putShort(resourceBytes, 60, (short) 0x54); // typeface: "Test Typeface"
leConverter.putShort(resourceBytes, 62, (short) 0x65);
leConverter.putShort(resourceBytes, 64, (short) 0x73);
leConverter.putShort(resourceBytes, 66, (short) 0x74);
leConverter.putShort(resourceBytes, 68, (short) 0x20);
leConverter.putShort(resourceBytes, 70, (short) 0x54);
leConverter.putShort(resourceBytes, 72, (short) 0x79);
leConverter.putShort(resourceBytes, 74, (short) 0x70);
leConverter.putShort(resourceBytes, 76, (short) 0x65);
leConverter.putShort(resourceBytes, 78, (short) 0x66);
leConverter.putShort(resourceBytes, 80, (short) 0x61);
leConverter.putShort(resourceBytes, 82, (short) 0x63);
leConverter.putShort(resourceBytes, 84, (short) 0x65);
leConverter.putShort(resourceBytes, 86, (short) 0x0);
// @formatter:on
return resourceBytes;
}
private byte[] getDlgTemplateResource() {
byte[] resourceBytes = new byte[76];
LittleEndianDataConverter leConverter = LittleEndianDataConverter.INSTANCE;
// @formatter:off
leConverter.putInt( resourceBytes, 0, 0x40); // style: DS_SETFONT
leConverter.putInt( resourceBytes, 4, 0); // exStyle
leConverter.putShort(resourceBytes, 8, (short) 0); // cdit (none)
leConverter.putShort(resourceBytes, 10, (short) 0); // x
leConverter.putShort(resourceBytes, 12, (short) 0); // y
leConverter.putShort(resourceBytes, 14, (short) 0xd0); // cx
leConverter.putShort(resourceBytes, 16, (short) 0xd0); // cy
leConverter.putShort(resourceBytes, 18, (short) 0); // menu: (none)
leConverter.putShort(resourceBytes, 20, (short) 0); // windowClass: (predefined dialog box class)
leConverter.putShort(resourceBytes, 22, (short) 0x54); // title: "Test Dialog"
leConverter.putShort(resourceBytes, 24, (short) 0x65);
leConverter.putShort(resourceBytes, 26, (short) 0x73);
leConverter.putShort(resourceBytes, 28, (short) 0x74);
leConverter.putShort(resourceBytes, 30, (short) 0x20);
leConverter.putShort(resourceBytes, 32, (short) 0x44);
leConverter.putShort(resourceBytes, 34, (short) 0x69);
leConverter.putShort(resourceBytes, 36, (short) 0x61);
leConverter.putShort(resourceBytes, 38, (short) 0x6c);
leConverter.putShort(resourceBytes, 40, (short) 0x6f);
leConverter.putShort(resourceBytes, 42, (short) 0x67);
leConverter.putShort(resourceBytes, 44, (short) 0x0);
// optional font fields, present here because DS_SETFONT was used
leConverter.putShort(resourceBytes, 46, (short) 8); // pointsize
leConverter.putShort(resourceBytes, 48, (short) 0x54); // typeface: "Test Typeface"
leConverter.putShort(resourceBytes, 50, (short) 0x65);
leConverter.putShort(resourceBytes, 52, (short) 0x73);
leConverter.putShort(resourceBytes, 54, (short) 0x74);
leConverter.putShort(resourceBytes, 56, (short) 0x20);
leConverter.putShort(resourceBytes, 58, (short) 0x54);
leConverter.putShort(resourceBytes, 60, (short) 0x79);
leConverter.putShort(resourceBytes, 62, (short) 0x70);
leConverter.putShort(resourceBytes, 64, (short) 0x65);
leConverter.putShort(resourceBytes, 66, (short) 0x66);
leConverter.putShort(resourceBytes, 68, (short) 0x61);
leConverter.putShort(resourceBytes, 70, (short) 0x63);
leConverter.putShort(resourceBytes, 72, (short) 0x65);
leConverter.putShort(resourceBytes, 74, (short) 0x0);
// @formatter:on
return resourceBytes;
}
}