private void Enumerate(ref PortableDeviceApiLib.IPortableDeviceContent pContent, string parentID, PortableDeviceContainerObject node)
        {
            PortableDeviceApiLib.IPortableDeviceProperties properties;
            pContent.Properties(out properties);

            PortableDeviceApiLib.IEnumPortableDeviceObjectIDs pEnum;
            pContent.EnumObjects(0, parentID, null, out pEnum);

            uint cFetched = 0;
            PortableDeviceObject current;
            do
            {
                string objectID;
                pEnum.Next(1, out objectID, ref cFetched);

                if (cFetched > 0)
                {
                    current = this.ExtractInformation(properties, objectID);
                    node.AddChild(current);
                    if (current is PortableDeviceContainerObject)
                        Enumerate(ref pContent, objectID, (PortableDeviceContainerObject)current);
                }

            } while (cFetched > 0);
        }
        internal void Enumerate(ref IPortableDeviceContent pContent, string parentID, PortableDeviceContainerObject node, IObjectEnumerateHelper helper, bool detectNewObjects = false)
        {
            IPortableDeviceProperties properties;
            pContent.Properties(out properties);

            foreach (var objectID in ExtractObjectIds(pContent, parentID))
            {
                if (detectNewObjects && ParentContainsChildsId(node, objectID))
                    continue;

                PortableDeviceObject current = ExtractInformation(properties, objectID);
                if(!helper.IsObjectMatching(current))
                    continue;

                node.AddChild(current);

                if (!helper.IsLastNode && current is PortableDeviceContainerObject)
                    Enumerate(ref pContent, objectID, (PortableDeviceContainerObject)current, helper.Next(), detectNewObjects);
            }
        }
 private static bool ParentContainsChildsId(PortableDeviceContainerObject node, string objectID)
 {
     string copyId = objectID; // to remove different behavior in compiled code of nested foreach
     var q = from child in node.Childs
             where child.ID == copyId
             select child;
     return q.Any();
 }
 public void Update(ref IPortableDeviceContent pContent, PortableDeviceContainerObject parent)
 {
     lock (dispatcher)
     {
         Enumerate(ref pContent, parent.ID, parent, enumerateHelper, detectNewObjects: true);
     }
 }
        /// <summary>
        ///     Inspired by http://cgeers.com/2012/04/17/wpd-transfer-content-to-a-device/
        /// </summary>
        /// <param name="parentObject"></param>
        /// <param name="sourceStream"></param>
        /// <param name="name"></param>
        /// <param name="originalFileName"></param>
        /// <param name="size"></param>
        public PortableDeviceObject Push(PortableDeviceContainerObject parentObject, Stream sourceStream, string name, string originalFileName, ulong size)
        {
            IPortableDeviceContent content;
            portableDeviceClass.Content(out content);
            IPortableDeviceValues values = GetRequiredPropertiesForPush(parentObject, name, originalFileName, size);

            IStream tempStream;
            uint optimalTransferSizeBytes = 0;
            content.CreateObjectWithPropertiesAndData(values, out tempStream, ref optimalTransferSizeBytes, null);

            var targetStream = (System.Runtime.InteropServices.ComTypes.IStream) tempStream;

            try
            {
                var buffer = new byte[optimalTransferSizeBytes];
                int bytesRead;
                do
                {
                    bytesRead = sourceStream.Read(buffer, 0, (int) optimalTransferSizeBytes);
                    IntPtr pcbWritten = IntPtr.Zero;

                    if (bytesRead < (int) optimalTransferSizeBytes)
                        targetStream.Write(buffer, bytesRead, pcbWritten);
                    else
                        targetStream.Write(buffer, (int) optimalTransferSizeBytes, pcbWritten);
                } while (bytesRead > 0);

                targetStream.Commit(0);

                device.Update(ref content, parentObject);

                // TODO There is no IPortableDeviceDataStream in C# port to get ID, so we will make a bicycle
                return Find("^" + originalFileName + "$", parentObject).First();
            }
            finally
            {
                Marshal.ReleaseComObject(tempStream);
            }
        }
 public PortableDeviceObject Push(PortableDeviceContainerObject parentObject, Stream sourceStream, string originalFileName, ulong size)
 {
     return Push(parentObject, sourceStream, originalFileName, originalFileName, size);
 }
        public PortableDeviceObject Mkdir(PortableDeviceContainerObject parentObject, string name)
        {
            IPortableDeviceContent content;
            portableDeviceClass.Content(out content);

            var values = (IPortableDeviceValues) new PortableDeviceValues();
            values.SetStringValue(PortableDevicePKeys.WPD_OBJECT_PARENT_ID, parentObject.ID);
            values.SetStringValue(PortableDevicePKeys.WPD_OBJECT_ORIGINAL_FILE_NAME, name);
            values.SetGuidValue(PortableDevicePKeys.WPD_OBJECT_CONTENT_TYPE, PortableDeviceGuids.WPD_CONTENT_TYPE_FOLDER);
            string objId = String.Empty;
            content.CreateObjectWithPropertiesOnly(values, ref objId);

            device.Update(ref content, parentObject);

            var q = from obj in parentObject.Childs
                    where obj.ID == objId
                    select obj;

            return q.First();
        }
 /// <summary>
 ///     Finds collection of specified objects in specific storage service of WPD device
 ///     /android/music/mp3
 ///     /.*/.*/mp3
 ///     /android/sic
 /// </summary>
 /// <param name="path">Represents a '/' delimeted path; each node can be RegEx pattern, not wildcard pattern; </param>
 /// <param name="storage"></param>
 /// <returns></returns>
 public IEnumerable<PortableDeviceObject> Find(string path, PortableDeviceContainerObject parent)
 {
     return FindInternal(parent.Childs, new PathEnumerateHelper(path));
 }