During this Article, I’ll show how to read some very basic information from Delphi’s DCP-Files. This includes name of BPL to link with, required DCPs and contained Units.During the last past weeks, i wrote a Project-Analyzationtool, which is able to completely unwire all Unit-Dependencies and fix searchpathes. However, to do so, i had to work with DCPs, too. Some searching didn’t reveal much (besides the same questions as i had). I know that things might have changed from XE to XE8, but i hope this article is still helpfull to get anybody outside of XE started.
So let’s get started with our dirty work. For analyzing a DCP, i created a new Package, called TestPackage.bpl. It requires only the RTL and has 2 empty units: MyUnit and Foo.OtherUnit. This should do the job for experimenting. Grab a Hex-Editor of your choice and look into it. You’ll see something like this:
Something you’ll notice is, that the Stream starts with the 4 AnsiChars “PKX0″. All DCP seem to start with it, so i declared it as our DCP-Signature. YOu may validate this when loading a file to make sure you have a DCP. On line 3 you’ll see “TestPackage.bpl”. This is the name fo the BPL the linker will link to. This is required when dealing with BPLs which have Postfixes. For example, for VCL150.bpl only a VCL.dcp exists. And this is the place where you’ll find the final BPL-Name. By comparing different DCPs, you’ll notice, that the BPL-Name always starts at the same position (Byte 33). So our first 32 Bytes are for sure some kind of Header. Let’s take a close look:
I have outline the fields i already analyzed and describe them here. The Red-Field is our Signature as discussed before. Green and Blue contain numbers, which change depending on the Number of contained Units and required DCPs. By fiddling around, you’ll notice that Green is the number of required DCPs and Blue the number of Contained Units. Wait, we have to units, why does it tell me that there are 3? Quite simple, the DPK-File of your Package (In this case TestPackage.dpk) is included in this list, too. The Orange box simply contains the lengths in Bytes of the BPL-Name which follows the header (Excluding the terminating NULL-Character). So to sum it up, our header looks like this in Delphi:
But wait, there is more!
Right after our BPL-Name, we’ll notice “RTL”. This is because it is directly followed by a list of zero-terminated strings which include the names of required DCPs. In our case it is just “RTL”. So to get a list of required DCPs, you simply read zero-terminated string after zero-terminated string based on the number of required DCPs as noted in our header. After that, a list of contained units with their own header follows. To sum it up here, each element of this list contains of a 60 Byte-Blob i haven’t investigated, yet. And 2 zero-terminated strings after each block. The first string is our Unit-Name, the second one seems to be some kind of NameSpace. When your unit is not dotted, the second string is always empty and consists only of the NULL-Character. But when your unit is dotted like “Foo.OtherUnit”, it’ll contain “Foo”. This pattern goes on with units like “Foo.Bar.MyUnit”, where the NameSpace is “Foo.Bar”. I highlighted theses fields in Green/Brown and Blue/Orange. So to get a list of contained units here, you simply skipp 60 Bytes and read 2 strings per element based on the number of contained units in our header. The last element is always the Package-DPK unit. So if you’ve done everything right, you can get an output like this:
Something to note here: The last entry, which is the DPK-Entry seems to have a Header with a length of 61. I just looped with a pattern of 60 Bytes here, that’s why i have an extra character here in front of the last name. You might want to skip that one.
I hope this article gets you started on Delphi’s DCP-File.