mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-26 07:56:27 +00:00
Merge branch 'GP-2821_ryanmkurtz_PR-3808_goatshriek_fix-dialog-resource'
This commit is contained in:
commit
707ec9288d
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user