Dispose() public method

Release the native objects.
public Dispose ( ) : void
return void
		/*

		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and constant value. 
		/// </summary>
		/// <param name="propertyName">The name of a property to be compared, or null for an unspecified property. 
		/// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
		/// <param name="value">The constant value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(string propertyName, string value, SearchConditionOperation operation) {
			using (PropVariant propVar = new PropVariant(value)) {
				return CreateLeafCondition(propertyName, propVar, null, operation);
			}
		}

		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and constant value. 
		/// Overload method takes a DateTime parameter for the comparison value.
		/// </summary>
		/// <param name="propertyName">The name of a property to be compared, or null for an unspecified property. 
		/// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
		/// <param name="value">The DateTime value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(string propertyName, DateTime value, SearchConditionOperation operation) {
			using (PropVariant propVar = new PropVariant(value)) {
				return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.DateTime", operation);
			}
		}
		*/

		/*
		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Integer value. 
		/// </summary>
		/// <param name="propertyName">The name of a property to be compared, or null for an unspecified property. 
		/// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
		/// <param name="value">The Integer value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(string propertyName, int value, SearchConditionOperation operation) {
			using (PropVariant propVar = new PropVariant(value)) {
				return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.Integer", operation);
			}
		}
		*/

		/*
		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Boolean value. 
		/// </summary>
		/// <param name="propertyName">The name of a property to be compared, or null for an unspecified property. 
		/// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
		/// <param name="value">The Boolean value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(string propertyName, bool value, SearchConditionOperation operation) {
			using (PropVariant propVar = new PropVariant(value)) {
				return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.Boolean", operation);
			}
		}
		*/

		/*
		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Floating Point value. 
		/// </summary>
		/// <param name="propertyName">The name of a property to be compared, or null for an unspecified property. 
		/// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
		/// <param name="value">The Floating Point value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(string propertyName, double value, SearchConditionOperation operation) {
			using (PropVariant propVar = new PropVariant(value)) {
				return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.FloatingPoint", operation);
			}
		}
		*/

		/*
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
		private static SearchCondition CreateLeafCondition(string propertyName, PropVariant propVar, string valueType, SearchConditionOperation operation) {
			IConditionFactory nativeConditionFactory = null;
			SearchCondition condition = null;

			try {
				// Same as the native "IConditionFactory:MakeLeaf" method
				nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();

				ICondition nativeCondition = null;

				if (string.IsNullOrEmpty(propertyName) || propertyName.ToUpperInvariant() == "SYSTEM.NULL") {
					propertyName = null;
				}

				HResult hr = HResult.S_FALSE;

				hr = nativeConditionFactory.MakeLeaf(propertyName, operation, valueType,
						propVar, null, null, null, false, out nativeCondition);

				if (hr != HResult.S_OK) {
					throw Marshal.GetExceptionForHR((int)hr);
				}

				// Create our search condition and set the various properties.
				condition = new SearchCondition(nativeCondition);
			}
			finally {
				if (nativeConditionFactory != null) {
					Marshal.ReleaseComObject(nativeConditionFactory);
				}
			}

			return condition;
		}
		*/

		/*
		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and constant value. 
		/// </summary>
		/// <param name="propertyKey">The property to be compared.</param>
		/// <param name="value">The constant value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, string value, SearchConditionOperation operation) {
			string canonicalName;
			PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);

			if (string.IsNullOrEmpty(canonicalName)) {
				throw new ArgumentException("Invalid PK", "propertyKey");
			}

			return CreateLeafCondition(canonicalName, value, operation);
		}
		*/

		/*
		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and constant value. 
		/// Overload method takes a DateTime parameter for the comparison value.
		/// </summary>
		/// <param name="propertyKey">The property to be compared.</param>
		/// <param name="value">The DateTime value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, DateTime value, SearchConditionOperation operation) {
			string canonicalName;
			PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);

			if (string.IsNullOrEmpty(canonicalName)) {
				throw new ArgumentException("Invalid PK", "propertyKey");
			}
			return CreateLeafCondition(canonicalName, value, operation);
		}
		*/

		/*

		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Boolean value. 
		/// Overload method takes a DateTime parameter for the comparison value.
		/// </summary>
		/// <param name="propertyKey">The property to be compared.</param>
		/// <param name="value">The boolean value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, bool value, SearchConditionOperation operation) {
			string canonicalName;
			PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);

			if (string.IsNullOrEmpty(canonicalName)) {
				throw new ArgumentException("Invalid PK", "propertyKey");
			}
			return CreateLeafCondition(canonicalName, value, operation);
		}

		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Floating Point value. 
		/// Overload method takes a DateTime parameter for the comparison value.
		/// </summary>
		/// <param name="propertyKey">The property to be compared.</param>
		/// <param name="value">The Floating Point value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, double value, SearchConditionOperation operation) {
			string canonicalName;
			PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);

			if (string.IsNullOrEmpty(canonicalName)) {
				throw new ArgumentException("Invalid PK", "propertyKey");
			}
			return CreateLeafCondition(canonicalName, value, operation);
		}

		/// <summary>
		/// Creates a leaf condition node that represents a comparison of property value and Integer value. 
		/// Overload method takes a DateTime parameter for the comparison value.
		/// </summary>
		/// <param name="propertyKey">The property to be compared.</param>
		/// <param name="value">The Integer value against which the property value should be compared.</param>
		/// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
		/// <returns>SearchCondition based on the given parameters</returns>
		/// <remarks>
		/// The search will only work for files that are indexed, as well as the specific properties are indexed. To find 
		/// the properties that are indexed, look for the specific property's property description and 
		/// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
		/// </remarks>
		public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, int value, SearchConditionOperation operation) {
			string canonicalName;
			PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);

			if (string.IsNullOrEmpty(canonicalName)) {
				throw new ArgumentException("Invalid PK", "propertyKey");
			}
			return CreateLeafCondition(canonicalName, value, operation);
		}

		/// <summary>
		/// Creates a condition node that is a logical conjunction ("AND") or disjunction ("OR") 
		/// of a collection of subconditions.
		/// </summary>
		/// <param name="conditionType">The SearchConditionType of the condition node. 
		/// Must be either AndCondition or OrCondition.</param>
		/// <param name="simplify">TRUE to logically simplify the result, if possible; 
		/// then the result will not necessarily to be of the specified kind. FALSE if the result should 
		/// have exactly the prescribed structure. An application that plans to execute a query based on the 
		/// condition tree would typically benefit from setting this parameter to TRUE. </param>
		/// <param name="conditionNodes">Array of subconditions</param>
		/// <returns>New SearchCondition based on the operation</returns>
		public static SearchCondition CreateAndOrCondition(SearchConditionType conditionType, bool simplify, params SearchCondition[] conditionNodes) {
			// Same as the native "IConditionFactory:MakeAndOr" method
			IConditionFactory nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();
			ICondition result = null;

			try {
				// 
				List<ICondition> conditionList = new List<ICondition>();
				if (conditionNodes != null) {
					foreach (SearchCondition c in conditionNodes) {
						conditionList.Add(c.NativeSearchCondition);
					}
				}

				IEnumUnknown subConditions = new EnumUnknownClass(conditionList.ToArray());

				HResult hr = nativeConditionFactory.MakeAndOr(conditionType, subConditions, simplify, out result);

				if (hr != HResult.S_OK) {
					throw Marshal.GetExceptionForHR((int)hr);
				}
			}
			finally {
				if (nativeConditionFactory != null) {
					Marshal.ReleaseComObject(nativeConditionFactory);
				}
			}

			return new SearchCondition(result);
		}

		/// <summary>
		/// Creates a condition node that is a logical negation (NOT) of another condition 
		/// (a subnode of this node). 
		/// </summary>
		/// <param name="conditionToBeNegated">SearchCondition node to be negated.</param>
		/// <param name="simplify">True to logically simplify the result if possible; False otherwise. 
		/// In a query builder scenario, simplyfy should typically be set to false.</param>
		/// <returns>New SearchCondition</returns>
		public static SearchCondition CreateNotCondition(SearchCondition conditionToBeNegated, bool simplify) {
			if (conditionToBeNegated == null) {
				throw new ArgumentNullException("conditionToBeNegated");
			}

			// Same as the native "IConditionFactory:MakeNot" method
			IConditionFactory nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();
			ICondition result;

			try {
				HResult hr = nativeConditionFactory.MakeNot(conditionToBeNegated.NativeSearchCondition, simplify, out result);

				if (hr != HResult.S_OK) {
					throw Marshal.GetExceptionForHR((int)hr);
				}
			}
			finally {
				if (nativeConditionFactory != null) {
					Marshal.ReleaseComObject(nativeConditionFactory);
				}
			}

			return new SearchCondition(result);
		}

		*/

		/*
		/// <summary>
		/// Parses an input string that contains Structured Query keywords (using Advanced Query Syntax 
		/// or Natural Query Syntax) and produces a SearchCondition object.
		/// </summary>
		/// <param name="query">The query to be parsed</param>
		/// <returns>Search condition resulting from the query</returns>
		/// <remarks>For more information on structured query syntax, visit http://msdn.microsoft.com/en-us/library/bb233500.aspx and
		/// http://www.microsoft.com/windows/products/winfamily/desktopsearch/technicalresources/advquery.mspx</remarks>
		public static SearchCondition ParseStructuredQuery(string query) {
			return ParseStructuredQuery(query, null);
		}
		*/

		/// <summary>
		/// Parses an input string that contains Structured Query keywords (using Advanced Query Syntax 
		/// or Natural Query Syntax) and produces a SearchCondition object.
		/// </summary>
		/// <param name="query">The query to be parsed</param>
		/// <param name="cultureInfo">The culture used to select the localized language for keywords.</param>
		/// <returns>Search condition resulting from the query</returns>
		/// <remarks>For more information on structured query syntax, visit http://msdn.microsoft.com/en-us/library/bb233500.aspx and
		/// http://www.microsoft.com/windows/products/winfamily/desktopsearch/technicalresources/advquery.mspx</remarks>
		public static SearchCondition ParseStructuredQuery(string query, CultureInfo cultureInfo = null) {
			if (string.IsNullOrEmpty(query)) {
				throw new ArgumentNullException("query");
			}

			IQueryParserManager nativeQueryParserManager = (IQueryParserManager)new QueryParserManagerCoClass();
			IQueryParser queryParser = null;
			IQuerySolution querySolution = null;
			ICondition result = null;

			IEntity mainType = null;
			SearchCondition searchCondition = null;
			try {
				// First, try to create a new IQueryParser using IQueryParserManager
				Guid guid = new Guid(InterfaceGuids.IQueryParser);
				HResult hr = nativeQueryParserManager.CreateLoadedParser(
						"SystemIndex",
						cultureInfo == null ? (ushort)0 : (ushort)cultureInfo.LCID,
						ref guid,
						out queryParser);

				if (hr != HResult.S_OK) {
					throw Marshal.GetExceptionForHR((int)hr);
				}

				if (queryParser != null) {
					// If user specified natural query, set the option on the query parser
					using (PropVariant optionValue = new PropVariant(true)) {
						hr = queryParser.SetOption(StructuredQuerySingleOption.NaturalSyntax, optionValue);
					}

					if (hr != HResult.S_OK) {
						throw Marshal.GetExceptionForHR((int)hr);
					}

					// Next, try to parse the query.
					// Result would be IQuerySolution that we can use for getting the ICondition and other
					// details about the parsed query.
					hr = queryParser.Parse(query, null, out querySolution);

					if (hr != HResult.S_OK) {
						throw Marshal.GetExceptionForHR((int)hr);
					}

					if (querySolution != null) {
						// Lastly, try to get the ICondition from this parsed query
						hr = querySolution.GetQuery(out result, out mainType);

						if (hr != HResult.S_OK) {
							throw Marshal.GetExceptionForHR((int)hr);
						}
					}
				}

				searchCondition = new SearchCondition(result);
				return searchCondition;
			}
			catch {
				if (searchCondition != null) searchCondition.Dispose();
				throw;
			}
			finally {
				if (nativeQueryParserManager != null) {
					Marshal.ReleaseComObject(nativeQueryParserManager);
				}

				if (queryParser != null) {
					Marshal.ReleaseComObject(queryParser);
				}

				if (querySolution != null) {
					Marshal.ReleaseComObject(querySolution);
				}

				if (mainType != null) {
					Marshal.ReleaseComObject(mainType);
				}
			}
		}
Example #2
0
        /*
         *
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and constant value.
         * /// </summary>
         * /// <param name="propertyName">The name of a property to be compared, or null for an unspecified property.
         * /// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
         * /// <param name="value">The constant value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(string propertyName, string value, SearchConditionOperation operation) {
         *      using (PropVariant propVar = new PropVariant(value)) {
         *              return CreateLeafCondition(propertyName, propVar, null, operation);
         *      }
         * }
         *
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and constant value.
         * /// Overload method takes a DateTime parameter for the comparison value.
         * /// </summary>
         * /// <param name="propertyName">The name of a property to be compared, or null for an unspecified property.
         * /// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
         * /// <param name="value">The DateTime value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(string propertyName, DateTime value, SearchConditionOperation operation) {
         *      using (PropVariant propVar = new PropVariant(value)) {
         *              return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.DateTime", operation);
         *      }
         * }
         */

        /*
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Integer value.
         * /// </summary>
         * /// <param name="propertyName">The name of a property to be compared, or null for an unspecified property.
         * /// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
         * /// <param name="value">The Integer value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(string propertyName, int value, SearchConditionOperation operation) {
         *      using (PropVariant propVar = new PropVariant(value)) {
         *              return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.Integer", operation);
         *      }
         * }
         */

        /*
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Boolean value.
         * /// </summary>
         * /// <param name="propertyName">The name of a property to be compared, or null for an unspecified property.
         * /// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
         * /// <param name="value">The Boolean value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(string propertyName, bool value, SearchConditionOperation operation) {
         *      using (PropVariant propVar = new PropVariant(value)) {
         *              return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.Boolean", operation);
         *      }
         * }
         */

        /*
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Floating Point value.
         * /// </summary>
         * /// <param name="propertyName">The name of a property to be compared, or null for an unspecified property.
         * /// The locale name of the leaf node is LOCALE_NAME_USER_DEFAULT.</param>
         * /// <param name="value">The Floating Point value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(string propertyName, double value, SearchConditionOperation operation) {
         *      using (PropVariant propVar = new PropVariant(value)) {
         *              return CreateLeafCondition(propertyName, propVar, "System.StructuredQuery.CustomProperty.FloatingPoint", operation);
         *      }
         * }
         */

        /*
         * [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
         * private static SearchCondition CreateLeafCondition(string propertyName, PropVariant propVar, string valueType, SearchConditionOperation operation) {
         *      IConditionFactory nativeConditionFactory = null;
         *      SearchCondition condition = null;
         *
         *      try {
         *              // Same as the native "IConditionFactory:MakeLeaf" method
         *              nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();
         *
         *              ICondition nativeCondition = null;
         *
         *              if (string.IsNullOrEmpty(propertyName) || propertyName.ToUpperInvariant() == "SYSTEM.NULL") {
         *                      propertyName = null;
         *              }
         *
         *              HResult hr = HResult.S_FALSE;
         *
         *              hr = nativeConditionFactory.MakeLeaf(propertyName, operation, valueType,
         *                              propVar, null, null, null, false, out nativeCondition);
         *
         *              if (hr != HResult.S_OK) {
         *                      throw Marshal.GetExceptionForHR((int)hr);
         *              }
         *
         *              // Create our search condition and set the various properties.
         *              condition = new SearchCondition(nativeCondition);
         *      }
         *      finally {
         *              if (nativeConditionFactory != null) {
         *                      Marshal.ReleaseComObject(nativeConditionFactory);
         *              }
         *      }
         *
         *      return condition;
         * }
         */

        /*
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and constant value.
         * /// </summary>
         * /// <param name="propertyKey">The property to be compared.</param>
         * /// <param name="value">The constant value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, string value, SearchConditionOperation operation) {
         *      string canonicalName;
         *      PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);
         *
         *      if (string.IsNullOrEmpty(canonicalName)) {
         *              throw new ArgumentException("Invalid PK", "propertyKey");
         *      }
         *
         *      return CreateLeafCondition(canonicalName, value, operation);
         * }
         */

        /*
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and constant value.
         * /// Overload method takes a DateTime parameter for the comparison value.
         * /// </summary>
         * /// <param name="propertyKey">The property to be compared.</param>
         * /// <param name="value">The DateTime value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, DateTime value, SearchConditionOperation operation) {
         *      string canonicalName;
         *      PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);
         *
         *      if (string.IsNullOrEmpty(canonicalName)) {
         *              throw new ArgumentException("Invalid PK", "propertyKey");
         *      }
         *      return CreateLeafCondition(canonicalName, value, operation);
         * }
         */

        /*
         *
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Boolean value.
         * /// Overload method takes a DateTime parameter for the comparison value.
         * /// </summary>
         * /// <param name="propertyKey">The property to be compared.</param>
         * /// <param name="value">The boolean value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, bool value, SearchConditionOperation operation) {
         *      string canonicalName;
         *      PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);
         *
         *      if (string.IsNullOrEmpty(canonicalName)) {
         *              throw new ArgumentException("Invalid PK", "propertyKey");
         *      }
         *      return CreateLeafCondition(canonicalName, value, operation);
         * }
         *
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Floating Point value.
         * /// Overload method takes a DateTime parameter for the comparison value.
         * /// </summary>
         * /// <param name="propertyKey">The property to be compared.</param>
         * /// <param name="value">The Floating Point value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, double value, SearchConditionOperation operation) {
         *      string canonicalName;
         *      PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);
         *
         *      if (string.IsNullOrEmpty(canonicalName)) {
         *              throw new ArgumentException("Invalid PK", "propertyKey");
         *      }
         *      return CreateLeafCondition(canonicalName, value, operation);
         * }
         *
         * /// <summary>
         * /// Creates a leaf condition node that represents a comparison of property value and Integer value.
         * /// Overload method takes a DateTime parameter for the comparison value.
         * /// </summary>
         * /// <param name="propertyKey">The property to be compared.</param>
         * /// <param name="value">The Integer value against which the property value should be compared.</param>
         * /// <param name="operation">Specific condition to be used when comparing the actual value and the expected value of the given property</param>
         * /// <returns>SearchCondition based on the given parameters</returns>
         * /// <remarks>
         * /// The search will only work for files that are indexed, as well as the specific properties are indexed. To find
         * /// the properties that are indexed, look for the specific property's property description and
         * /// <see cref="P:Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyDescription.TypeFlags"/> property for IsQueryable flag.
         * /// </remarks>
         * public static SearchCondition CreateLeafCondition(PROPERTYKEY propertyKey, int value, SearchConditionOperation operation) {
         *      string canonicalName;
         *      PropertySystemNativeMethods.PSGetNameFromPropertyKey(ref propertyKey, out canonicalName);
         *
         *      if (string.IsNullOrEmpty(canonicalName)) {
         *              throw new ArgumentException("Invalid PK", "propertyKey");
         *      }
         *      return CreateLeafCondition(canonicalName, value, operation);
         * }
         *
         * /// <summary>
         * /// Creates a condition node that is a logical conjunction ("AND") or disjunction ("OR")
         * /// of a collection of subconditions.
         * /// </summary>
         * /// <param name="conditionType">The SearchConditionType of the condition node.
         * /// Must be either AndCondition or OrCondition.</param>
         * /// <param name="simplify">TRUE to logically simplify the result, if possible;
         * /// then the result will not necessarily to be of the specified kind. FALSE if the result should
         * /// have exactly the prescribed structure. An application that plans to execute a query based on the
         * /// condition tree would typically benefit from setting this parameter to TRUE. </param>
         * /// <param name="conditionNodes">Array of subconditions</param>
         * /// <returns>New SearchCondition based on the operation</returns>
         * public static SearchCondition CreateAndOrCondition(SearchConditionType conditionType, bool simplify, params SearchCondition[] conditionNodes) {
         *      // Same as the native "IConditionFactory:MakeAndOr" method
         *      IConditionFactory nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();
         *      ICondition result = null;
         *
         *      try {
         *              //
         *              List<ICondition> conditionList = new List<ICondition>();
         *              if (conditionNodes != null) {
         *                      foreach (SearchCondition c in conditionNodes) {
         *                              conditionList.Add(c.NativeSearchCondition);
         *                      }
         *              }
         *
         *              IEnumUnknown subConditions = new EnumUnknownClass(conditionList.ToArray());
         *
         *              HResult hr = nativeConditionFactory.MakeAndOr(conditionType, subConditions, simplify, out result);
         *
         *              if (hr != HResult.S_OK) {
         *                      throw Marshal.GetExceptionForHR((int)hr);
         *              }
         *      }
         *      finally {
         *              if (nativeConditionFactory != null) {
         *                      Marshal.ReleaseComObject(nativeConditionFactory);
         *              }
         *      }
         *
         *      return new SearchCondition(result);
         * }
         *
         * /// <summary>
         * /// Creates a condition node that is a logical negation (NOT) of another condition
         * /// (a subnode of this node).
         * /// </summary>
         * /// <param name="conditionToBeNegated">SearchCondition node to be negated.</param>
         * /// <param name="simplify">True to logically simplify the result if possible; False otherwise.
         * /// In a query builder scenario, simplyfy should typically be set to false.</param>
         * /// <returns>New SearchCondition</returns>
         * public static SearchCondition CreateNotCondition(SearchCondition conditionToBeNegated, bool simplify) {
         *      if (conditionToBeNegated == null) {
         *              throw new ArgumentNullException("conditionToBeNegated");
         *      }
         *
         *      // Same as the native "IConditionFactory:MakeNot" method
         *      IConditionFactory nativeConditionFactory = (IConditionFactory)new ConditionFactoryCoClass();
         *      ICondition result;
         *
         *      try {
         *              HResult hr = nativeConditionFactory.MakeNot(conditionToBeNegated.NativeSearchCondition, simplify, out result);
         *
         *              if (hr != HResult.S_OK) {
         *                      throw Marshal.GetExceptionForHR((int)hr);
         *              }
         *      }
         *      finally {
         *              if (nativeConditionFactory != null) {
         *                      Marshal.ReleaseComObject(nativeConditionFactory);
         *              }
         *      }
         *
         *      return new SearchCondition(result);
         * }
         *
         */

        /*
         * /// <summary>
         * /// Parses an input string that contains Structured Query keywords (using Advanced Query Syntax
         * /// or Natural Query Syntax) and produces a SearchCondition object.
         * /// </summary>
         * /// <param name="query">The query to be parsed</param>
         * /// <returns>Search condition resulting from the query</returns>
         * /// <remarks>For more information on structured query syntax, visit http://msdn.microsoft.com/en-us/library/bb233500.aspx and
         * /// http://www.microsoft.com/windows/products/winfamily/desktopsearch/technicalresources/advquery.mspx</remarks>
         * public static SearchCondition ParseStructuredQuery(string query) {
         *      return ParseStructuredQuery(query, null);
         * }
         */

        /// <summary>
        /// Parses an input string that contains Structured Query keywords (using Advanced Query Syntax
        /// or Natural Query Syntax) and produces a SearchCondition object.
        /// </summary>
        /// <param name="query">The query to be parsed</param>
        /// <param name="cultureInfo">The culture used to select the localized language for keywords.</param>
        /// <returns>Search condition resulting from the query</returns>
        /// <remarks>For more information on structured query syntax, visit http://msdn.microsoft.com/en-us/library/bb233500.aspx and
        /// http://www.microsoft.com/windows/products/winfamily/desktopsearch/technicalresources/advquery.mspx</remarks>
        public static SearchCondition ParseStructuredQuery(string query, CultureInfo cultureInfo = null)
        {
            if (string.IsNullOrEmpty(query))
            {
                throw new ArgumentNullException("query");
            }

            IQueryParserManager nativeQueryParserManager = (IQueryParserManager) new QueryParserManagerCoClass();
            IQueryParser        queryParser   = null;
            IQuerySolution      querySolution = null;
            ICondition          result        = null;

            IEntity         mainType        = null;
            SearchCondition searchCondition = null;

            try {
                // First, try to create a new IQueryParser using IQueryParserManager
                Guid    guid = new Guid(InterfaceGuids.IQueryParser);
                HResult hr   = nativeQueryParserManager.CreateLoadedParser(
                    "SystemIndex",
                    cultureInfo == null ? (ushort)0 : (ushort)cultureInfo.LCID,
                    ref guid,
                    out queryParser);

                if (hr != HResult.S_OK)
                {
                    throw Marshal.GetExceptionForHR((int)hr);
                }

                if (queryParser != null)
                {
                    // If user specified natural query, set the option on the query parser
                    using (PropVariant optionValue = new PropVariant(true)) {
                        hr = queryParser.SetOption(StructuredQuerySingleOption.NaturalSyntax, optionValue);
                    }

                    if (hr != HResult.S_OK)
                    {
                        throw Marshal.GetExceptionForHR((int)hr);
                    }

                    // Next, try to parse the query.
                    // Result would be IQuerySolution that we can use for getting the ICondition and other
                    // details about the parsed query.
                    hr = queryParser.Parse(query, null, out querySolution);

                    if (hr != HResult.S_OK)
                    {
                        throw Marshal.GetExceptionForHR((int)hr);
                    }

                    if (querySolution != null)
                    {
                        // Lastly, try to get the ICondition from this parsed query
                        hr = querySolution.GetQuery(out result, out mainType);

                        if (hr != HResult.S_OK)
                        {
                            throw Marshal.GetExceptionForHR((int)hr);
                        }
                    }
                }

                searchCondition = new SearchCondition(result);
                return(searchCondition);
            }
            catch {
                if (searchCondition != null)
                {
                    searchCondition.Dispose();
                }
                throw;
            }
            finally {
                if (nativeQueryParserManager != null)
                {
                    Marshal.ReleaseComObject(nativeQueryParserManager);
                }

                if (queryParser != null)
                {
                    Marshal.ReleaseComObject(queryParser);
                }

                if (querySolution != null)
                {
                    Marshal.ReleaseComObject(querySolution);
                }

                if (mainType != null)
                {
                    Marshal.ReleaseComObject(mainType);
                }
            }
        }