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