3.2 File Structure
This section provides an example of how to construct the persist object directory for the file. Correctly constructing the persist object directory is the first step in finding the rest of the presentation content in the file—main master slides, notes master slide, handout master slide, presentation slides, notes slides, embedded or linked OLE object storages, and the VBA project storage. Because new user edits can simply be appended to the existing stream contents, the process for constructing the persist object directory needs to be carefully followed to ensure that the most recent version of a persist object is used and older versions are ignored.
Construction of the persist object directory begins with parsing the CurrentUserAtom record (section 2.3.2). The child-record hierarchy of the CurrentUserAtom record is shown expanded in the following table.
Offset |
Size |
Structure |
Value |
---|---|---|---|
00000000 |
005F |
CurrentUserAtom - currentUserAtom |
|
00000000 |
0008 |
RecordHeader - rh |
|
00000008 |
0004 |
unsigned integer - size |
0x00000014 |
0000000C |
0004 |
unsigned integer - headerToken |
0xE391C05F |
00000010 |
0004 |
unsigned integer - offsetToCurrentEdit |
0x00008290 |
00000014 |
0002 |
unsigned integer - lenUserName |
0x0015 |
00000016 |
0002 |
unsigned integer - docFileVersion |
0x03F4 |
00000018 |
0001 |
unsigned integer - majorVersion |
0x03 |
00000019 |
0001 |
unsigned integer - minorVersion |
0x00 |
0000001A |
0002 |
unsigned integer - unused |
0x0000 |
0000001C |
0015 |
array of bytes - ansiUserName |
Microsoft Corporation |
00000031 |
0004 |
unsigned integer - relVersion |
0x00000008 |
00000035 |
002A |
array of bytes - unicodeUserName |
Microsoft Corporation |
Figure 20: CurrentUserAtom child-record hierarchy
offsetToCurrentEdit: 0x00008290 specifies the offset, in bytes, from the beginning of the PowerPoint Document Stream (section 2.1.2) to the UserEditAtom record (section 2.3.3) for the most recent user edit.
The UserEditAtom record specified by the offsetToCurrentEdit field in the previous table is shown expanded in the following table.
Offset |
Size |
Structure |
Value |
---|---|---|---|
00008290 |
0024 |
UserEditAtom |
|
00008290 |
0008 |
RecordHeader - rh |
|
00008298 |
0004 |
unsigned integer - lastSlideIdRef |
0x00000100 |
0000829C |
16 bits |
unsigned integer - version |
0x1FE9 |
0000829C |
8 bits |
unsigned integer - minorVersion |
0x00 |
0000829C |
8 bits |
unsigned integer - majorVersion |
0x03 |
000082A0 |
0004 |
unsigned integer - offsetLastEdit |
0x00005C45 |
000082A4 |
0004 |
unsigned integer - offsetPersistDirectory |
0x0000826C |
000082A8 |
0004 |
unsigned integer - docPersistIdRef |
0x00000001 |
000082AC |
0004 |
unsigned integer - persistIdSeed |
0x00000014 |
000082B0 |
0002 |
ViewTypeEnum - lastView |
0x0001 |
000082B2 |
0002 |
unsigned integer - unused |
0x31C5 |
Figure 21: UserEditAtom child-record hierarchy for the most recent user edit
offsetLastEdit: 0x00005C45 specifies the offset, in bytes, from the beginning of the PowerPoint Document Stream to the UserEditAtom record for the previous user edit.
offsetPersistDirectory: 0x0000826C specifies the offset, in bytes, from the beginning of the PowerPoint Document Stream to the PersistDirectoryAtom record (section 2.3.4) for the most recent user edit.
The PersistDirectoryAtom record specified by the offsetPersistDirectory field in the previous table titled "UserEditAtom child-record hierarchy for the most recent user edit" is shown expanded in the following table.
Offset |
Size |
Structure |
Value |
---|---|---|---|
0000826C |
0024 |
PersistDirectoryAtom |
|
0000826C |
0008 |
RecordHeader - rh |
|
00008274 |
0008 |
PersistDirectoryEntry - persistDirEntry[0] |
|
00008274 |
20 bits |
unsigned integer - persistId |
0x00001 |
00008274 |
12 bits |
unsigned integer - cPersist |
0x001 |
00008278 |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x00005C69 |
0000827C |
0008 |
PersistDirectoryEntry - persistDirEntry[1] |
|
0000827C |
20 bits |
unsigned integer - persistId |
0x00006 |
0000827C |
12 bits |
unsigned integer - cPersist |
0x001 |
00008280 |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x00006964 |
00008284 |
000C |
PersistDirectoryEntry - persistDirEntry[2] |
|
00008284 |
20 bits |
unsigned integer - persistId |
0x00013 |
00008284 |
12 bits |
unsigned integer - cPersist |
0x002 |
00008288 |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x00007AF6 |
0000828C |
0004 |
PersistOffsetEntry - persistOffset[1] |
0x00007FE3 |
Figure 22: PersistDirectoryAtom child-record hierarchy for the most recent user edit
persistDirEntry[0].persistId: 0x00001 specifies the starting persist object identifier for the PersistOffsetEntry entries (section 2.3.6) that follow.
persistDirEntry[0].cPersist: 0x001 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[0].persistOffset[0]: 0x00005C69 specifies the stream offset for the persist object with persist object identifier 0x00001.
persistDirEntry[1].persistId: 0x00006 specifies the starting persist object identifier for the PersistOffsetEntry entries that follow.
persistDirEntry[1].cPersist: 0x001 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[1].persistOffset[0]: 0x00006964 specifies the stream offset for the persist object with persist object identifier 0x00006.
persistDirEntry[2].persistId: 0x00013 specifies the starting persist object identifier for the PersistOffsetEntry entries that follow.
persistDirEntry[2].cPersist: 0x002 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[2].persistOffset[0]: 0x00007AF6 specifies the stream offset for the persist object with persist object identifier 0x00013.
persistDirEntry[2].persistOffset[1]: 0x00007FE3 specifies the stream offset for the persist object with persist object identifier 0x00014.
The partial persist object directory constructed after parsing the first PersistDirectoryAtom record is summarized in the following table.
Persist object identifier |
Persist object stream offset |
---|---|
0x00001 |
0x00005C69 |
0x00006 |
0x00006964 |
0x00013 |
0x00007AF6 |
0x00014 |
0x00007FE3 |
The UserEditAtom record specified by the offsetLastEdit field in the previous table titled "UserEditAtom child-record hierarchy for the most recent user edit" is shown expanded in the following table.
Offset |
Size |
Structure |
Value |
---|---|---|---|
00005C45 |
0024 |
UserEditAtom |
|
00005C45 |
0008 |
RecordHeader - rh |
|
00005C4D |
0004 |
unsigned integer - lastSlideIdRef |
0x00000104 |
00005C51 |
16 bits |
unsigned integer - version |
0x1FE9 |
00005C51 |
8 bits |
unsigned integer - minorVersion |
0x00 |
00005C51 |
8 bits |
unsigned integer - majorVersion |
0x03 |
00005C55 |
0004 |
unsigned integer - offsetLastEdit |
0x00000000 |
00005C59 |
0004 |
unsigned integer - offsetPersistDirectory |
0x00005BF1 |
00005C5D |
0004 |
unsigned integer - docPersistIdRef |
0x00000001 |
00005C61 |
0004 |
unsigned integer - persistIdSeed |
0x00000012 |
00005C65 |
0002 |
ViewTypeEnum - lastView |
0x000F |
00005C67 |
0002 |
unsigned integer - unused |
0x31C5 |
Figure 23: UserEditAtom child-record hierarchy for the previous user edit
offsetLastEdit: 0x00000000 specifies that no further user edits exist.
offsetPersistDirectory: 0x00005BF1 specifies the offset, in bytes, from the beginning of the PowerPoint Document Stream to the PersistDirectoryAtom record for this previous user edit.
The PersistDirectoryAtom record specified by the offsetPersistDirectory field in the previous table is shown expanded in the following table.
Offset |
Size |
Structure |
Value |
---|---|---|---|
00005BF1 |
0054 |
PersistDirectoryAtom |
|
00005BF1 |
0008 |
RecordHeader - rh |
|
00005BF9 |
0028 |
PersistDirectoryEntry - persistDirEntry[0] |
|
00005BF9 |
20 bits |
unsigned integer - persistId |
0x00001 |
00005BF9 |
12 bits |
unsigned integer - cPersist |
0x009 |
00005BFD |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x00000000 |
00005C01 |
0004 |
PersistOffsetEntry - persistOffset[1] |
0x00000CC5 |
00005C05 |
0004 |
PersistOffsetEntry - persistOffset[2] |
0x00001671 |
00005C09 |
0004 |
PersistOffsetEntry - persistOffset[3] |
0x000021C8 |
00005C0D |
0004 |
PersistOffsetEntry - persistOffset[4] |
0x000023F4 |
00005C11 |
0004 |
PersistOffsetEntry - persistOffset[5] |
0x000030CD |
00005C15 |
0004 |
PersistOffsetEntry - persistOffset[6] |
0x00004D69 |
00005C19 |
0004 |
PersistOffsetEntry - persistOffset[7] |
0x000037B5 |
00005C1D |
0004 |
PersistOffsetEntry - persistOffset[8] |
0x00003E83 |
00005C21 |
0008 |
PersistDirectoryEntry - persistDirEntry[1] |
|
00005C21 |
20 bits |
unsigned integer - persistId |
0x0000B |
00005C21 |
12 bits |
unsigned integer - cPersist |
0x001 |
00005C25 |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x00001B98 |
00005C29 |
001C |
PersistDirectoryEntry - persistDirEntry[2] |
|
00005C29 |
20 bits |
unsigned integer - persistId |
0x0000D |
00005C29 |
12 bits |
unsigned integer - cPersist |
0x006 |
00005C2D |
0004 |
PersistOffsetEntry - persistOffset[0] |
0x000040CB |
00005C31 |
0004 |
PersistOffsetEntry - persistOffset[1] |
0x00004319 |
00005C35 |
0004 |
PersistOffsetEntry - persistOffset[2] |
0x000045D4 |
00005C39 |
0004 |
PersistOffsetEntry - persistOffset[3] |
0x00004873 |
00005C3D |
0004 |
PersistOffsetEntry - persistOffset[4] |
0x00004B22 |
00005C41 |
0004 |
PersistOffsetEntry - persistOffset[5] |
0x00002E81 |
Figure 24: PersistDirectoryAtom child-record hierarchy for the previous user edit
persistDirEntry[0].persistId: 0x00001 specifies the starting persist object identifier for the PersistOffsetEntry entries that follow.
persistDirEntry[0].cPersist: 0x009 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[0].persistOffset[0]: 0x00000000 specifies the stream offset for the persist object with persist object identifier 0x00001. However, because the persist object identifier 0x00001 already appears in the first table in this section, this stream offset is ignored.
persistDirEntry[0].persistOffset[1]: 0x00000CC5 specifies the stream offset for the persist object with persist object identifier 0x00002.
persistDirEntry[0].persistOffset[2]: 0x00001671 specifies the stream offset for the persist object with persist object identifier 0x00003.
persistDirEntry[0].persistOffset[3]: 0x000021C8 specifies the stream offset for the persist object with persist object identifier 0x00004.
persistDirEntry[0].persistOffset[4]: 0x000023F4 specifies the stream offset for the persist object with persist object identifier 0x00005.
persistDirEntry[0].persistOffset[5]: 0x000030CD specifies the stream offset for the persist object with persist object identifier 0x00006. However, because the persist object identifier 0x00006 already appears in the first table in this section, this stream offset is ignored.
persistDirEntry[0].persistOffset[6]: 0x00004D69 specifies the stream offset for the persist object with persist object identifier 0x00007.
persistDirEntry[0].persistOffset[7]: 0x000037B5 specifies the stream offset for the persist object with persist object identifier 0x00008.
persistDirEntry[0].persistOffset[8]: 0x00003E83 specifies the stream offset for the persist object with persist object identifier 0x00009.
persistDirEntry[1].persistId: 0x0000B specifies the starting persist object identifier for the PersistOffsetEntry entries that follow.
persistDirEntry[1].cPersist: 0x001 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[1].persistOffset[0]: 0x00001B98 specifies the stream offset for the persist object with persist object identifier 0x0000B.
persistDirEntry[2].persistId: 0x0000D specifies the starting persist object identifier for the PersistOffsetEntry entries that follow.
persistDirEntry[2].cPersist: 0x006 specifies the count of PersistOffsetEntry entries that follow.
persistDirEntry[2].persistOffset[0]: 0x000040CB specifies the stream offset for the persist object with persist object identifier 0x0000D.
persistDirEntry[2].persistOffset[1]: 0x00004319 specifies the stream offset for the persist object with persist object identifier 0x0000E.
persistDirEntry[2].persistOffset[2]: 0x000045D4 specifies the stream offset for the persist object with persist object identifier 0x0000F.
persistDirEntry[2].persistOffset[3]: 0x00004873 specifies the stream offset for the persist object with persist object identifier 0x00010.
persistDirEntry[2].persistOffset[4]: 0x00004B22 specifies the stream offset for the persist object with persist object identifier 0x00011.
persistDirEntry[2].persistOffset[5]: 0x00002E81 specifies the stream offset for the persist object with persist object identifier 0x00012.
The complete persist object directory constructed after parsing all PersistDirectoryAtom records is summarized in the following table.
Persist object identifier |
Persist object stream offset |
---|---|
0x00001 |
0x00005C69 |
0x00002 |
0x00000CC5 |
0x00003 |
0x00001671 |
0x00004 |
0x000021C8 |
0x00005 |
0x000023F4 |
0x00006 |
0x00006964 |
0x00007 |
0x00004D69 |
0x00008 |
0x000037B5 |
0x00009 |
0x00003E83 |
0x0000B |
0x00001B98 |
0x0000D |
0x000040CB |
0x0000E |
0x00004319 |
0x0000F |
0x000045D4 |
0x00010 |
0x00004873 |
0x00011 |
0x00004B22 |
0x00012 |
0x00002E81 |
0x00013 |
0x00007AF6 |
0x00014 |
0x00007FE3 |