8#ifndef PSTSDK_NDB_DATABASE_H
9#define PSTSDK_NDB_DATABASE_H
202 template<
typename K,
typename V>
231#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
234 if(crc != m_header.dwCRCPartial)
235 throw crc_fail(
"header dwCRCPartial failure", 0, 0, crc, m_header.dwCRCPartial);
244 throw invalid_format();
246#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
247 ulong crc_partial =
disk::compute_crc(((
byte*)&m_header) + disk::header_crc_locations<ulonglong>::partial_start, disk::header_crc_locations<ulonglong>::partial_length);
248 ulong crc_full =
disk::compute_crc(((
byte*)&m_header) + disk::header_crc_locations<ulonglong>::full_start, disk::header_crc_locations<ulonglong>::full_length);
250 if(crc_partial != m_header.dwCRCPartial)
251 throw crc_fail(
"header dwCRCPartial failure", 0, 0, crc_partial, m_header.dwCRCPartial);
253 if(crc_full != m_header.dwCRCFull)
254 throw crc_fail(
"header dwCRCFull failure", 0, 0, crc_full, m_header.dwCRCFull);
308 if (
wver >= disk::database_format_unicode_min) {
335#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
348#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
352 if(
bt->cb !=
bi.size)
359#ifdef PSTSDK_VALIDATION_LEVEL_FULL
362 throw crc_fail(
"block crc failure",
bi.address,
bi.id, crc,
bt->crc);
371#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
376 throw unexpected_page(
"nonsensical page location; not sector aligned");
384#ifdef PSTSDK_VALIDATION_LEVEL_FULL
386 if(crc !=
ppage->trailer.crc)
390#ifdef PSTSDK_VALIDATION_LEVEL_WEAK
391 if(
ppage->trailer.bid !=
pi.id)
394 if(
ppage->trailer.page_type !=
ppage->trailer.page_type_repeat)
410 page_info pi = { m_header.root_info.brefBBT.bid, m_header.root_info.brefBBT.ib };
411 m_bbt_root = read_bbt_page(
pi);
422 page_info pi = { m_header.root_info.brefNBT.bid, m_header.root_info.brefNBT.ib };
423 m_nbt_root = read_nbt_page(
pi);
462 std::vector<byte>
buffer = read_page_data(
pi);
480 std::vector<std::pair<node_id, node_info> >
nodes;
489 nodes.push_back(std::make_pair(
ni.id,
ni));
492#ifndef BOOST_NO_RVALUE_REFERENCES
502 std::vector<byte>
buffer = read_page_data(
pi);
520 std::vector<std::pair<block_id, block_info> >
blocks;
532#ifndef BOOST_NO_RVALUE_REFERENCES
542 std::vector<byte>
buffer = read_page_data(
pi);
557template<
typename K,
typename V>
560 std::vector<std::pair<K, page_info> >
nodes;
568#ifndef BOOST_NO_RVALUE_REFERENCES
578 std::vector<byte>
buffer = read_page_data(
pi);
595 std::vector<byte>
buffer = read_page_data(
pi);
604 return read_bbt_leaf_page(
pi, *
leaf);
621 std::vector<byte>
buffer = read_page_data(
pi);
630 return read_nbt_leaf_page(
pi, *
leaf);
647 return read_nbt_root()->lookup(nid);
656 bi.id =
bi.address =
bi.size =
bi.ref_count = 0;
668 std::shared_ptr<block>
pblock;
686 return read_external_block(
parent,
bi);
696 return read_extended_block(
parent,
bi);
705 std::vector<byte>
buffer = read_block_data(
bi);
719 sub_size = disk::extended_block<T>::max_size;
725#ifndef BOOST_NO_RVALUE_REFERENCES
742 std::vector<std::shared_ptr<data_block> > child_blocks;
743 child_blocks.push_back(pchild_block);
745#ifndef BOOST_NO_RVALUE_REFERENCES
746 return std::shared_ptr<extended_block>(
new extended_block(parent, 1, pchild_block->get_total_size(),
disk::external_block<T>::max_size, disk::extended_block<T>::max_count, 1, std::move(child_blocks)));
748 return std::shared_ptr<extended_block>(
new extended_block(parent, 1, pchild_block->get_total_size(),
disk::external_block<T>::max_size, disk::extended_block<T>::max_count, 1, child_blocks));
755 std::vector<std::shared_ptr<data_block> > child_blocks;
756 child_blocks.push_back(pchild_block);
758 assert(pchild_block->get_level() == 1);
760#ifndef BOOST_NO_RVALUE_REFERENCES
761 return std::shared_ptr<extended_block>(
new extended_block(parent, 2, pchild_block->get_total_size(), disk::extended_block<T>::max_size, disk::extended_block<T>::max_count, disk::extended_block<T>::max_count, std::move(child_blocks)));
763 return std::shared_ptr<extended_block>(
new extended_block(parent, 2, pchild_block->get_total_size(), disk::extended_block<T>::max_size, disk::extended_block<T>::max_count, disk::extended_block<T>::max_count, child_blocks));
770 ushort level = size > disk::extended_block<T>::max_size ? 2 : 1;
773 size_t child_max_size;
777 child_max_size = disk::extended_block<T>::max_size;
781 ulong child_max_blocks = level == 1 ? 1 : disk::extended_block<T>::max_count;
783 return std::shared_ptr<extended_block>(
new extended_block(parent, level, size, child_max_size, disk::extended_block<T>::max_count, child_max_blocks));
798 std::vector<byte>
buffer = read_block_data(
bi);
809#ifndef BOOST_NO_RVALUE_REFERENCES
824 std::vector<byte>
buffer = read_block_data(
bi);
826 std::shared_ptr<subnode_block> sub_block;
843 std::vector<byte>
buffer = read_block_data(
bi);
845 std::shared_ptr<subnode_leaf_block> sub_block;
862 std::vector<byte>
buffer = read_block_data(
bi);
864 std::shared_ptr<subnode_nonleaf_block> sub_block;
868 sub_block = read_subnode_nonleaf_block(
parent,
bi, *
psub);
882 std::vector<std::pair<node_id, subnode_info> >
subnodes;
884 for(
int i = 0;
i < sub_block.count; ++
i)
886 ni.id = sub_block.entry[
i].nid;
887 ni.data_bid = sub_block.entry[
i].data;
888 ni.sub_bid = sub_block.entry[
i].sub;
890 subnodes.push_back(std::make_pair(sub_block.entry[
i].nid,
ni));
893#ifndef BOOST_NO_RVALUE_REFERENCES
903 std::vector<std::pair<node_id, block_id> >
subnodes;
905 for(
int i = 0;
i < sub_block.count; ++
i)
907 subnodes.push_back(std::make_pair(sub_block.entry[
i].nid_key, sub_block.entry[
i].sub_block_bid));
910#ifndef BOOST_NO_RVALUE_REFERENCES
Generic BTree implementation.
Contains references to other bth_node allocations.
const V & lookup(const K &key) const
Looks up the associated value for a given key.
std::shared_ptr< bt_nonleaf_page< K, V > > read_bt_nonleaf_page(const page_info &pi, disk::bt_page< T, disk::bt_entry< T > > &the_page)
std::shared_ptr< nbt_page > read_nbt_page(const page_info &pi)
Open a NBT page.
std::shared_ptr< subnode_nonleaf_block > read_subnode_nonleaf_block(const shared_db_ptr &parent, block_id bid)
Open a subnode_nonleaf_block in the specified context.
std::shared_ptr< bbt_page > read_bbt_page(const page_info &pi)
Open a BBT page.
node_info lookup_node_info(node_id nid)
Lookup information about a node.
std::vector< byte > read_block_data(const block_info &bi)
Read block data, perform validation checks.
std::vector< byte > read_page_data(const page_info &pi)
Read page data, perform validation checks.
disk::header< T > m_header
std::shared_ptr< subnode_leaf_block > read_subnode_leaf_block(const shared_db_ptr &parent, block_id bid)
Open a subnode_leaf_block in the specified context.
friend shared_db_ptr open_database(const std::wstring &filename)
Open a db_context for the given file.
std::shared_ptr< nbt_leaf_page > read_nbt_leaf_page(const page_info &pi)
Open a NBT leaf page.
friend std::shared_ptr< large_pst > open_large_pst(std::shared_ptr< file > file)
Try to open the given file as a Unicode store with custom file instance.
std::shared_ptr< file > m_file
node lookup_node(node_id nid)
Open a node.
std::shared_ptr< extended_block > read_extended_block(const shared_db_ptr &parent, block_id bid)
Open an extended_block in the specified context.
friend shared_db_ptr open_database(std::shared_ptr< file > file)
Open a db_context for the given file instance.
std::shared_ptr< nbt_page > m_nbt_root
std::shared_ptr< block > read_block(const shared_db_ptr &parent, block_id bid)
Open a block in the specified context.
std::shared_ptr< nbt_nonleaf_page > read_nbt_nonleaf_page(const page_info &pi)
Open a NBT nonleaf page.
std::shared_ptr< bbt_nonleaf_page > read_bbt_nonleaf_page(const page_info &pi)
Open a BBT nonleaf page.
std::shared_ptr< bbt_page > read_bbt_root()
Get the root of the BBT of this context.
std::shared_ptr< nbt_page > read_nbt_root()
Get the root of the NBT of this context.
friend std::shared_ptr< large_pst > open_large_pst(const std::wstring &filename)
Try to open the given file as a Unicode store.
friend shared_db_ptr open_database(const shared_db_ptr &other_database)
Open a db_context by copying the in-memory header and file handle from another db_context.
block_info lookup_block_info(block_id bid)
Lookup information about a block.
std::shared_ptr< subnode_block > read_subnode_block(const shared_db_ptr &parent, block_id bid)
Open a subnode_block in the specified context.
std::shared_ptr< data_block > read_data_block(const shared_db_ptr &parent, block_id bid)
Open a data_block in the specified context.
friend std::shared_ptr< small_pst > open_small_pst(const std::wstring &filename)
Try to open the given file as an ANSI store.
std::shared_ptr< bbt_page > m_bbt_root
friend std::shared_ptr< small_pst > open_small_pst(std::shared_ptr< file > file)
Try to open the given file as an ANSI store with custom file instance.
std::shared_ptr< bbt_leaf_page > read_bbt_leaf_page(const page_info &pi)
Open a BBT leaf page.
std::shared_ptr< external_block > read_external_block(const shared_db_ptr &parent, block_id bid)
Open a external_block in the specified context.
void validate_header()
Validate the header of this file.
Database external interface.
A data block which refers to other data blocks, in order to extend the physical size limit (8k) to a ...
A generic class to read and write to a file.
An in memory representation of the "node" concept in a PST data file.
An unexpected signature was encountered.
Contains the actual subnode information.
Contains references to subnode_leaf_blocks.
An unexpected block or block type was encountered.
An unexpected page or page type was encountered.
Disk data structure definitions.
The exceptions used by pstsdk.
void permute(void *pdata, ulong cb, bool encrypt)
Modifies the data block in place, according to the permute method.
void cyclic(void *pdata, ulong cb, ulong key)
Modifies the data block in place, according to the cyclic method.
const uint block_id_attached_bit
The attached bit indicates a block is referenced in memory This is an implementation detail,...
Contains the definition of all in memory representations of disk structures.
database_impl< ulong > small_pst
bt_leaf_page< block_id, block_info > bbt_leaf_page
std::shared_ptr< db_context > shared_db_ptr
database_impl< ulonglong > large_pst
bt_leaf_page< node_id, node_info > nbt_leaf_page
Node and Block definitions.
Primitive structures defined by MS-PST and MAPI.
An in memory, database format agnostic version of disk::bbt_leaf_entry.
The fundamental page structure which forms the basis of the two BTrees.
External block definition.
static const size_t max_size
An in memory, database format agnostic version of disk::nbt_leaf_entry.
An in memory, database format agnostic version of disk::block_reference used specifically for the pag...
An in memory, database format agnostic version of disk::sub_leaf_entry.
General utility functions and classes.