Пример #1
0
        /// <summary>
        /// Utility to set a string property on an INativeContactProperties.
        /// </summary>
        /// <param name="contact">The INativeContactProperties to set the value on.</param>
        /// <param name="propertyName">The property to set.</param>
        /// <param name="value">The value to set to the property.</param>
        /// <returns>HRESULT.</returns>
        /// <remarks>
        /// This is a thin wrapper over the COM INativeContactProperties::SetString to make it more easily consumable
        /// in .Net.  Behavior and returned error codes should be similar to the native version.
        /// </remarks>
        public static HRESULT SetString(INativeContactProperties contact, string propertyName, string value)
        {
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            return contact.SetString(propertyName, ContactValue.CGD_DEFAULT, value);
        }
Пример #2
0
        /// <summary>
        /// Utility to set a date property on an INativeContactProperties.
        /// </summary>
        /// <param name="contact">The INativeContactProperties to set the value on.</param>
        /// <param name="propertyName">The property to set.</param>
        /// <param name="value">The date value to set to the property.</param>
        /// <returns>HRESULT.</returns>
        /// <remarks>
        /// This is a thin wrapper over the COM INativeContactProperties::SetDate to make it more easily consumable
        /// in .Net.  Behavior and returned error codes should be similar to the native version.
        /// </remarks>
        public static HRESULT SetDate(INativeContactProperties contact, string propertyName, DateTime value)
        {
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            // If the caller hasn't explicitly set the kind then assume it's UTC
            // so it will be written as read to the Contact.  
            if (value.Kind != DateTimeKind.Local)
            {
                value = new DateTime(value.Ticks, DateTimeKind.Utc);
            }

            long longFiletime = value.ToFileTime();

            var ft = new FILETIME
            {
                dwLowDateTime = (Int32)longFiletime,
                dwHighDateTime = (Int32)(longFiletime >> 32)
            };

            return contact.SetDate(propertyName, ContactValue.CGD_DEFAULT, ft);
        }
Пример #3
0
        /// <summary>
        /// Utility to augment the label set on a preexisting array node in an INativeContactProperties.
        /// </summary>
        /// <param name="contact">The INativeContactProperties where the labels are to be set.</param>
        /// <param name="arrayNode">The array node to apply the labels to.</param>
        /// <param name="labels">The labels to add to the array node.</param>
        /// <returns>HRESULT.</returns>
        /// <remarks>
        /// This is a thin wrapper over the COM INativeContactProperties::SetLabels to make it more easily consumable
        /// in .Net.  Behavior and returned error codes should be similar to the native version.
        /// </remarks>
        public static HRESULT SetLabels(INativeContactProperties contact, string arrayNode, ICollection<string> labels)
        {
            Verify.IsNotNull(contact, "contact");

            using (var marshalable = new MarshalableLabelCollection(labels))
            {
                return contact.SetLabels(arrayNode, ContactValue.CGD_DEFAULT, marshalable.Count, marshalable.MarshaledLabels);
            }
        }
Пример #4
0
        public static HRESULT GetString(INativeContactProperties contact, string propertyName, bool ignoreDeletes, out string value)
        {
            value = null;
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            uint cch;
            var sb = new StringBuilder((int)Win32Value.MAX_PATH);
            HRESULT hr = contact.GetString(propertyName, ContactValue.CGD_DEFAULT, sb, (uint)sb.Capacity, out cch);
            // If the caller doesn't care about deleted properties, convert the error code.
            if (ignoreDeletes && HRESULT.S_FALSE == hr)
            {
                hr = Win32Error.ERROR_PATH_NOT_FOUND;
            }
            // If we didn't have enough space for the value the first time through, try the bigger size.
            if (Win32Error.ERROR_INSUFFICIENT_BUFFER == hr)
            {
                sb.EnsureCapacity((int)cch);
                hr = contact.GetString(propertyName, ContactValue.CGD_DEFAULT, sb, (uint)sb.Capacity, out cch);

                // If this failed a second time, it shouldn't be because of an insufficient buffer.
                Assert.Implies(hr.Failed(), Win32Error.ERROR_INSUFFICIENT_BUFFER != hr);
            }

            if (HRESULT.S_OK == hr)
            {
                value = sb.ToString();
            }

            return hr;
        }
Пример #5
0
        /// <summary>
        /// Utility to set a binary property on an INativeContactProperties.
        /// </summary>
        /// <param name="contact">The INativeContactProperties to set the value on.</param>
        /// <param name="propertyName">The property to set.</param>
        /// <param name="binary">The value to set to the property.</param>
        /// <param name="binaryType">The mime-type of the value being applied.</param>
        /// <returns>HRESULT.</returns>
        /// <remarks>
        /// This is a thin wrapper over the COM INativeContactProperties::SetBinary to make it more easily consumable
        /// in .Net.  Behavior and returned error codes should be similar to the native version.
        /// </remarks>
        public static HRESULT SetBinary(INativeContactProperties contact, string propertyName, string binaryType, Stream binary)
        {
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            using (var mstream = new ManagedIStream(binary))
            {
                mstream.Seek(0, (int)SeekOrigin.Begin, IntPtr.Zero);
                return contact.SetBinary(propertyName, ContactValue.CGD_DEFAULT, binaryType, mstream);
            }
        }
Пример #6
0
        public static HRESULT GetLabels(INativeContactProperties contact, string arrayNode, out List<string> labels)
        {
            HRESULT hr;
            labels = null;

            Verify.IsNotNull(contact, "contact");

            using (var marshalable = new MarshalableDoubleNullString(Win32Value.MAX_PATH))
            {
                uint cch;
                hr = contact.GetLabels(arrayNode, ContactValue.CGD_DEFAULT, marshalable.MarshaledString, marshalable.Capacity, out cch);
                // If we didn't have enough space for the node the first time through, try the bigger size.
                if (Win32Error.ERROR_INSUFFICIENT_BUFFER == hr)
                {
                    // Reallocate to the size returned by the last GetLabels call.
                    marshalable.Realloc(cch);

                    hr = contact.GetLabels(arrayNode, ContactValue.CGD_DEFAULT, marshalable.MarshaledString, marshalable.Capacity, out cch);
                    // If this failed a second time, it shouldn't be because of an insufficient buffer.
                    Assert.Implies(hr.Failed(), Win32Error.ERROR_INSUFFICIENT_BUFFER != hr);
                }

                if (hr.Succeeded())
                {
                    labels = marshalable.ParsedStrings;
                }
            }

            return hr;
        }
Пример #7
0
        public static HRESULT GetPropertyCollection(INativeContactProperties contact, string collection, string[] labels, bool anyLabelMatches, out IContactPropertyCollection propertyCollection)
        {
            Verify.IsNotNull(contact, "contact");

            uint fAnyLabelMatches = anyLabelMatches ? Win32Value.TRUE : Win32Value.FALSE;

            using (var mlc = new MarshalableLabelCollection(labels))
            {
                return contact.GetPropertyCollection(out propertyCollection, ContactValue.CGD_DEFAULT, collection, mlc.Count, mlc.MarshaledLabels, fAnyLabelMatches);
            }
        }
Пример #8
0
        public static HRESULT GetDate(INativeContactProperties contact, string propertyName, bool ignoreDeletes, out DateTime value)
        {
            value = default(DateTime);
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            FILETIME ft;
            HRESULT hr = contact.GetDate(propertyName, ContactValue.CGD_DEFAULT, out ft);
            // If the caller doesn't care about deleted properties, convert the error code.
            if (ignoreDeletes && HRESULT.S_FALSE == hr)
            {
                hr = Win32Error.ERROR_PATH_NOT_FOUND;
            }

            if (HRESULT.S_OK == hr)
            {
                value = DateTimeFromFILETIME(ft);
            }

            return hr;
        }
Пример #9
0
        public static HRESULT GetLabeledNode(INativeContactProperties contact, string collection, string[] labels, out string labeledNode)
        {
            labeledNode = null;
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(collection, "collection");

            if (null == labels)
            {
                labels = new string[0];
            }

            // Make a copy of the label set.
            // We're going to take two passes while trying to find the labeled value.
            // One has the Preferred label, the second doesn't.
            var preferredLabels = new string[labels.Length + 1];
            labels.CopyTo(preferredLabels, 0);
            preferredLabels[labels.Length] = PropertyLabels.Preferred;

            HRESULT hr;
            IContactPropertyCollection propertyCollection = null;

            try
            {
                hr = GetPropertyCollection(contact, collection, preferredLabels, false, out propertyCollection);
                if (hr.Succeeded())
                {
                    // If a node satisfies this constraint, use it.
                    hr = propertyCollection.Next();
                    if (HRESULT.S_FALSE == hr)
                    {
                        // Otherwise, try it again without the extra "Preferred" label.
                        Utility.SafeRelease(ref propertyCollection);
                        hr = GetPropertyCollection(contact, collection, labels, false, out propertyCollection);
                        if (hr.Succeeded())
                        {
                            // Does an array node exist with these labels?
                            hr = propertyCollection.Next();
                            // There's nothing left to fall back on.  S_FALSE implies this property doesn't exist.
                            if (HRESULT.S_FALSE == hr)
                            {
                                hr = Win32Error.ERROR_PATH_NOT_FOUND;
                            }
                        }
                    }
                }

                if (hr.Succeeded())
                {
                    hr = GetPropertyName(propertyCollection, out labeledNode);
                }
            }
            finally
            {
                Utility.SafeRelease(ref propertyCollection);
            }

            return hr;
        }
Пример #10
0
        // There's a bug in Windows Contacts that simple extension array nodes return S_OK
        // instead of S_FALSE.  This function happens to behave correctly anyways.
        public static bool DoesPropertyExist(INativeContactProperties contact, string propertyName)
        {
            Verify.IsNotNull(contact, "contact");

            if (string.IsNullOrEmpty(propertyName))
            {
                return false;
            }

            string dummy;
            HRESULT hr = GetString(contact, propertyName, false, out dummy);
            if (HRESULT.S_FALSE == hr)
            {
                // S_FALSE usually implies a deleted property,
                // but if it's an array node then it's present.
                return propertyName.EndsWith("]", StringComparison.Ordinal);
            }
            if (Win32Error.ERROR_PATH_NOT_FOUND == hr)
            {
                return false;
            }
            // Other errors are unexpected.
            hr.ThrowIfFailed("Error querying the property");
            return true;
        }
Пример #11
0
        public static HRESULT GetBinary(INativeContactProperties contact, string propertyName, bool ignoreDeletes, out string binaryType, out Stream binary)
        {
            binaryType = null;
            binary = null;
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            HRESULT hr;
            var sb = new StringBuilder((int)Win32Value.MAX_PATH);
            IStream stm = null;

            try
            {
                uint cch;
                hr = contact.GetBinary(propertyName, ContactValue.CGD_DEFAULT, sb, (uint)sb.Capacity, out cch, out stm);
                if (ignoreDeletes && HRESULT.S_FALSE == hr)
                {
                    hr = Win32Error.ERROR_PATH_NOT_FOUND;
                }
                // If we didn't have enough space for the binaryType the first time through, try the bigger size.
                if (Win32Error.ERROR_INSUFFICIENT_BUFFER == hr)
                {
                    Assert.IsNull(stm);
                    sb.EnsureCapacity((int)cch);
                    hr = contact.GetBinary(propertyName, ContactValue.CGD_DEFAULT, sb, (uint)sb.Capacity, out cch, out stm);
                    // GetBinary shouldn't return ERROR_INSUFFICIENT_BUFFER if it's going to subsequently return S_FALSE.
                    Assert.AreNotEqual(HRESULT.S_FALSE, hr);
                    // If this failed a second time, it shouldn't be because of an insufficient buffer.
                    Assert.Implies(hr.Failed(), Win32Error.ERROR_INSUFFICIENT_BUFFER != hr);
                }

                if (HRESULT.S_OK == hr)
                {
                    binary = new ComStream(ref stm);
                    binaryType = sb.ToString();
                }
            }
            finally
            {
                Utility.SafeRelease(ref stm);
            }

            return hr;
        }
Пример #12
0
        public static HRESULT DeleteProperty(INativeContactProperties contact, string propertyName)
        {
            Verify.IsNotNull(contact, "contact");
            Verify.IsNotNull(propertyName, "propertyName");

            // COM APIs don't check for this.  DeleteArrayNode should be used in this case.
            if (propertyName.EndsWith("]", StringComparison.Ordinal))
            {
                return Win32Error.ERROR_INVALID_DATATYPE;
            }

            return contact.DeleteProperty(propertyName, ContactValue.CGD_DEFAULT);
        }
Пример #13
0
        public static HRESULT DeleteLabels(INativeContactProperties contact, string nodeName)
        {
            Verify.IsNotNull(contact, "contact");

            return contact.DeleteLabels(nodeName, ContactValue.CGD_DEFAULT);
        }
Пример #14
0
        public static HRESULT CreateArrayNode(INativeContactProperties contact, string arrayName, bool appendNode, out string node)
        {
            node = null;
            Verify.IsNotNull(contact, "contact");

            HRESULT hr;
            var sb = new StringBuilder((int)Win32Value.MAX_PATH);
            uint convertedAppend = appendNode ? Win32Value.TRUE : Win32Value.FALSE;
            uint cch;

            hr = contact.CreateArrayNode(arrayName, ContactValue.CGD_DEFAULT, convertedAppend, sb, (uint)sb.Capacity, out cch);
            
            // If we didn't have enough space for the node the first time through, try the bigger size.
            if (Win32Error.ERROR_INSUFFICIENT_BUFFER == hr)
            {
                sb.EnsureCapacity((int)cch);
                hr = contact.CreateArrayNode(arrayName, ContactValue.CGD_DEFAULT, convertedAppend, sb, (uint)sb.Capacity, out cch);

                // If this failed a second time, it shouldn't be because of an insufficient buffer.
                Assert.Implies(hr.Failed(), Win32Error.ERROR_INSUFFICIENT_BUFFER != hr);
            }

            if (hr.Succeeded())
            {
                node = sb.ToString();
            }

            return hr;
        }
Пример #15
0
		public static HRESULT DeleteArrayNode(INativeContactProperties contact, string nodeName)
        {
            Verify.IsNotNull(contact, "contact");
			Verify.IsNotNull(nodeName, "nodeName");

            // COM APIs don't check for this.  DeleteProperty should be used in this case.
            if (!nodeName.EndsWith("]"))
            {
                return (HRESULT)Win32Error.ERROR_INVALID_DATATYPE;
            }

            return contact.DeleteArrayNode(nodeName, ContactValue.CGD_DEFAULT);
        }
Пример #16
0
        private VistaContactProperties(Stream stream, bool ownsStream)
        {
            Verify.IsNotNull(stream, "stream");

            _nativeContact = new ContactRcw();

            var persistStream = (IPersistStream)_nativeContact;
            stream.Seek(0, SeekOrigin.Begin);

            // COM APIs may keep the stream and rely on using it later.
            // Managed callers are likely to call dispose on it, which destroys it.
            // Need to create a copy of the stream and keep it alive and unchanged
            // for the lifetime of this object.
            if (ownsStream)
            {
                // This is our own copy.  Don't need to dupe it.
                _streamCopy = stream;
            }
            else
            {
                _streamCopy = new MemoryStream();
                Utility.CopyStream(_streamCopy, stream);
            }
            _istreamCopy = new ManagedIStream(_streamCopy);

            HRESULT hr = persistStream.Load(_istreamCopy);
            if (HRESULT.WC_E_SYNTAX == hr || HRESULT.WC_E_GREATERTHAN == hr || Win32Error.ERROR_INVALID_DATATYPE == hr)
            {
                throw new InvalidDataException("The data stream is of an invalid format");
            }
            hr.ThrowIfFailed("An error occurred loading the contact");

            //_modified = false;
        }