/// <returns>short PropertyID used to store the property</returns>
        public PropertyID AddToMap(PropertyLongID propertyLongID, Guid propertySetGuid)
        {
            PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);

            int wGuid = GetPropertySetGuidIndexHint(propertySetGuid);

            if (wGuid == -1)
            {
                wGuid = 3 + AddPropertySetGuid(node, propertySetGuid);
            }

            byte[] oldBuffer     = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamEntry);
            int    propertyIndex = oldBuffer.Length / 8;

            NameID nameID = new NameID(propertyLongID, (ushort)wGuid, (ushort)propertyIndex);

            byte[] newBuffer = new byte[oldBuffer.Length + 8];
            Array.Copy(oldBuffer, newBuffer, oldBuffer.Length);
            nameID.WriteBytes(newBuffer, oldBuffer.Length);
            node.PC.SetBytesProperty(PropertyID.PidTagNameidStreamEntry, newBuffer);

            AddPropertyToHashBucket(node, nameID);
            node.SaveChanges();

            PropertyID propertyID = (PropertyID)(nameID.PropertyShortID);

            m_map.Add(new PropertyName(propertyLongID, propertySetGuid), (ushort)propertyID);
            return(propertyID);
        }
        public void FillMap()
        {
            m_map = new Dictionary <PropertyName, ushort>();
            PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);

            byte[] buffer = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamEntry);
            if (buffer.Length % 8 > 0)
            {
                throw new InvalidPropertyException("Invalid NameidStreamEntry");
            }

            for (int index = 0; index < buffer.Length; index += 8)
            {
                NameID nameID = new NameID(buffer, index);
                if (!nameID.IsStringIdentifier)
                {
                    ushort         propertyShortID = nameID.PropertyShortID;
                    PropertyLongID propertyLongID  = (PropertyLongID)nameID.dwPropertyID;
                    Guid           propertySetGuid = GetPropertySetGuid(nameID.wGuid);

                    m_map.Add(new PropertyName(propertyLongID, propertySetGuid), propertyShortID);
                }
            }
        }
        // Note: Changes must be saved by the caller method
        private void AddPropertyToHashBucket(Node node, NameID nameID)
        {
            int    bucketCount           = node.PC.GetInt32Property(PropertyID.PidTagNameidBucketCount).Value;
            uint   firstBucketPropertyID = (uint)PropertyID.PidTagNameidBucketBase;
            uint   arg0        = nameID.dwPropertyID;
            uint   arg1        = Convert.ToUInt32(nameID.IdentifierType) + nameID.wGuid << 1;
            ushort bucketIndex = (ushort)((arg0 ^ arg1) % bucketCount);

            if (nameID.IsStringIdentifier)
            {
                throw new NotImplementedException("Named property with string identifier is not supported");
            }
            PropertyID bucketPropertyID = (PropertyID)(firstBucketPropertyID + bucketIndex);

            byte[] oldBuffer = node.PC.GetBytesProperty(bucketPropertyID);
            if (oldBuffer == null)
            {
                oldBuffer = new byte[0];
            }
            byte[] newBuffer = new byte[oldBuffer.Length + NameID.Length];
            Array.Copy(oldBuffer, newBuffer, oldBuffer.Length);
            nameID.WriteBytes(newBuffer, oldBuffer.Length);
            node.PC.SetBytesProperty(bucketPropertyID, newBuffer);
        }