See the question and my original answer on StackOverflow

Here is some sample code that supports Windows 10 and Windows 7, however not in the same manner.

The WPDShext.dll component shipped in Windows which is reponsible for handling the portable devices hierarchy is more limited in Windows 7 than in Window 10. It does not support interfaces such as IStream or IStorage from an IShellItem::BindToHandler implementation, which is probably what IFileOperation tries to do.

All it seems it can do is support an IStream when requested through its root folder's IShellFolder::BindToObject method implementation.

import pythoncom
import platform
from import shell, shellcon
from win32com import storagecon

# this points to my IPhone's root, adapt to your code or enumerate from root
folderPath = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\\\\?\\usb#vid_05ac&pid_12a8&mi_00#6&211e6304&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}"

# this relative path points to some image in that IPhone (same path as shown in Explorer)
itemPath = "Internal Storage\\DCIM\\202308__\\IMG_2047.JPG"

# get the root folder (IPhone, etc.)
folderItem = shell.SHCreateItemFromParsingName(folderPath, None, shell.IID_IShellItem)

if (int(platform.release()) < 8): # release is hopefully reliable enough for Windows 7 detection...

    # get WPDShext.dll's namespace extension IShellFolder implementation
    folder = folderItem.BindToHandler(None, shell.BHID_SFObject, shell.IID_IShellFolder)

    # get the relative child item
    ret = folder.ParseDisplayName(None, None, itemPath, 0)

    # get the item's stream using the relative pidl, from IShellFolder
    inputStream = folder.BindToObject(ret[1], None, pythoncom.IID_IStream)

    # get its size, don't ask for name in this code (avoid releasing mem)
    inputStat = inputStream.Stat(1) # STATFLAG_NONAME

    # open a file for writing & copy from input to output
    outputStream = shell.SHCreateStreamOnFileEx("c:\\temp\\IMG_2047.JPG", storagecon.STGM_CREATE | storagecon.STGM_WRITE, 0, True, None)
    inputStream.CopyTo(outputStream, inputStat[2])


    src = shell.SHCreateItemFromRelativeName(folderItem, itemPath, None, shell.IID_IShellItem)
    dst = shell.SHCreateItemFromParsingName("c:\\temp", None, shell.IID_IShellItem)
    fo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation)
    fo.CopyItem(src, dst)

Note you can also use the WPD API if you want but 1) it's not super easy to use and 2) not sure it's easy to do in python.

Here is some extra sample code that allows you to determine what to use for the folderPath variable used above:

import pythoncom
from import shell

desktopItem = shell.SHCreateItemFromParsingName("", None, shell.IID_IShellItem)
for item in desktopItem.BindToHandler(None, shell.BHID_EnumItems, shell.IID_IEnumShellItems):
    print(item.GetDisplayName(0) + " parsing name: " + item.GetDisplayName(0x80018001)) # SIGDN_DESKTOPABSOLUTEPARSING

It will display something like this:

Downloads parsing name: ::{088E3905-0323-4B02-9826-5D99428E115F}
3D Objects parsing name: ::{0DB7E03F-FC29-4DC6-9020-FF41B59E513A}
Pictures parsing name: ::{24AD3AD4-A569-4530-98E1-AB02F9417AA8}
Music parsing name: ::{3DFDF296-DBEC-4FB4-81D1-6A3438BCF4DE}
Desktop parsing name: ::{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}
Documents parsing name: ::{D3162B92-9365-467A-956B-92703ACA08AF}
Videos parsing name: ::{F86FA3AB-70D2-4FC7-9C99-FCBF05467F3A}
Apple iPhone parsing name: \\?\usb#vid_05ac&pid_12a8&mi_00#6&211e6304&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}
Local Disk (C:) parsing name: C:
DATA (D:) parsing name: D:

And {20D04FE0-3AEA-1069-A2D8-08002B30309D} is CLSID_MyComputer (aka "This PC" or "Computer" or whatever in localized Windows version)