The following example is similar to the included file demo.c. It opens, display the tree and closes a Structured Storage file:
#include <stdio.h> #include <cole/cole.h> |
You need to include cole/cole.h header to use the cole functions.
int main (int argc, char **argv) { int result; pps_entry *stream_tree; U32 root_stream; U32 stream; if (argc != 3) { fprintf (stderr, "cole example 1. cole is a free C OLE library.\n"); fprintf (stderr, "Usage: coleexample1 srcFILE destFILE.\n"); fprintf (stderr, "Note: if srcFILE and destFILE are the same file, it will be overwritten.\n"); return 1; } |
Just argument checks.
verbose ("Decoding ************************************"); result = OLEdecode (argv[1], &stream_tree, &root_stream, 0); |
Here we call OLEdecode in order to extract the structure of the Structured Storage file which name is stored in argv[1]. The structure will be stored in stream_tree, and the root of the structure in root_stream (we will need the root later). The last argument indicate the level of the structure that OLEdecode will extract, if it's zero it will extract all the levels.
fprintf (stderr, "OLEdecode output = %d\n", result); if (result != 0) { fprintf (stderr, "Decoding: "); perror (argv[1]); return 1; } else verbose ("Success decoding"); printf ("******* Stream tree:\n"); verbosePPSTree (stream_tree, root_stream, 0); |
verbosePPSTree is a cole function that prints to the standard output the complete tree of a Structured Storage file. With the last parameter equal to zero, we are printing all levels of the structure.
printf ("******* Top level no directory streams:\n"); /* travel through the top level no directory streams, just follows next field and ignore type 1 fileds */ for (stream = stream_tree[root_stream].dir; stream != 0xffffffff; stream = stream_tree[stream].next) { if (stream_tree[stream].type != 1 && stream_tree[stream].level == 1) if (!isprint(stream_tree[stream].name[0])) printf ("'\\x%02x%s'\n", stream_tree[stream].name[0], stream_tree[stream].name+1); else printf ("'%s'\n", stream_tree[stream].name); } |
With this code, we are traveling in the structure, which is a tree in an array, this means it's a tree of structures with indexes for the brothers and the children (if any). As you can see, the actual names of the streams may begin with no printable characters.
verbose ("Coding **************************************"); result = OLEcode (argv[2], 1, stream_tree, root_stream); |
If you want to read the raw streams you only need OLEdecode function. But if you want to generate a Structured Storage file, you need to have the raw streams, the tree in an array structure and the root of such tree to use OLEcode. cole 1.0.0 doesn't provide functions to such tasks, wait for cole 2.0.0.
fprintf (stderr, "OLEcode output = %d\n", result); if (result != 0) { fprintf (stderr, "Coding "); perror (argv[2]); return 1; } else verbose ("Success coding\n"); verbose ("Freeing *************************************"); /* need to free all the allocated memory */ result = freeOLEtree (stream_tree); |
If you used OLEdecode, you must use freeOLEtree after process the raw stream.
fprintf (stderr, "freeOLEtree output = %d\n", result); return result; } |
When you run this example, the following output is produced:
$ ./coleexample1 examples/text.doc text2.doc OLEdecode output = 0 ******* Stream tree: DIR 00 'Root Entry' FILE 01 98 ' CompObj' FILE 03 312 ' SummaryInformation' FILE 04 2381 'WordDocument' FILE 02 20 ' Ole' ******* Top level no directory streams: '\x01CompObj' '\x05SummaryInformation' 'WordDocument' '\x01Ole' OLEcode output = 0 freeOLEtree output = 0 |