title: How do I move Windows desktop icons using python 2.7?
body: <p>I am trying to write a python routine to save and restore desktop icon positions. I am using 32-bit python 2.7 on Windows 7 x64. Using information from here (stack exchange), I am able to read the icon names and positions from the foreign process list view that Windows uses to store this info, but I fail when using LVM_SETITEMPOSITION to set new positions (or restore the positions). All of the icons end up in the same exact spot on the desktop. 'Auto arrange' and 'align to grid' are off. The relevant code is towards the bottom. WARNING: if you run this code all of your icons will be in a pile :(</p>
  
  <pre><code>import ctypes
  
  class LVITEMW(ctypes.Structure):
      _fields_ = [
          ('mask', ctypes.c_uint32),
          ('iItem', ctypes.c_int32),
          ('iSubItem', ctypes.c_int32),
          ('state', ctypes.c_uint32),
          ('stateMask', ctypes.c_uint32),
          ('pszText', ctypes.c_uint64),
          ('cchTextMax', ctypes.c_int32),
          ('iImage', ctypes.c_int32),
          ('lParam', ctypes.c_uint64), # On 32 bit should be c_long
          ('iIndent',ctypes.c_int32),
          ('iGroupId', ctypes.c_int32),
          ('cColumns', ctypes.c_uint32),
          ('puColumns', ctypes.c_uint64),
          ('piColFmt', ctypes.c_int64),
          ('iGroup', ctypes.c_int32),
      ]
  
  class POINT(ctypes.Structure):
      _fields_ = [('x', ctypes.c_int), ('y', ctypes.c_int)]
  
  def icon_save_restore(savedicons=None, restore=False):
      import struct, commctrl, win32gui, win32con, win32api
      dthwnd = win32gui.FindWindow(None, 'Program Manager')
      ukhwnd = win32gui.GetWindow(dthwnd, win32con.GW_CHILD)
      slvhwnd = win32gui.GetWindow(ukhwnd, win32con.GW_CHILD)
      pid = ctypes.create_string_buffer(4)
      p_pid = ctypes.addressof(pid)
      ctypes.windll.user32.GetWindowThreadProcessId(slvhwnd, p_pid)
      hProcHnd = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, struct.unpack("i",pid)[0])
      pBuffertxt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd, 0, 4096, win32con.MEM_RESERVE|win32con.MEM_COMMIT, win32con.PAGE_READWRITE)
      copied = ctypes.create_string_buffer(4)
      p_copied = ctypes.addressof(copied)
      lvitem = LVITEMW()
      lvitem.mask = ctypes.c_uint32(commctrl.LVIF_TEXT)
      lvitem.pszText = ctypes.c_uint64(pBuffertxt)
      lvitem.cchTextMax = ctypes.c_int32(4096)
      lvitem.iSubItem = ctypes.c_int32(0)
      pLVI = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd, 0, 4096, win32con.MEM_RESERVE| win32con.MEM_COMMIT,  win32con.PAGE_READWRITE)
      win32api.SetLastError(0)
      ctypes.windll.kernel32.WriteProcessMemory(hProcHnd, pLVI, ctypes.addressof(lvitem), ctypes.sizeof(lvitem), p_copied)
      num_items = win32gui.SendMessage(slvhwnd, commctrl.LVM_GETITEMCOUNT)
      if restore is False:
          p = POINT()
          pBufferpnt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd, 0, ctypes.sizeof(p), win32con.MEM_RESERVE|win32con.MEM_COMMIT, win32con.PAGE_READWRITE)
          icons = {}
          for i in xrange(num_items):
              # Get icon text
              win32gui.SendMessage(slvhwnd, commctrl.LVM_GETITEMTEXT, i, pLVI)
              target_bufftxt = ctypes.create_string_buffer(4096)
              ctypes.windll.kernel32.ReadProcessMemory(hProcHnd, pBuffertxt, ctypes.addressof(target_bufftxt), 4096, p_copied)
              key = target_bufftxt.value
              # Get icon position
              win32api.SendMessage(slvhwnd, commctrl.LVM_GETITEMPOSITION, i, pBufferpnt)
              p = POINT()
              ctypes.windll.kernel32.ReadProcessMemory(hProcHnd, pBufferpnt, ctypes.addressof(p), ctypes.sizeof(p), p_copied)
              icons[key] = (i,p)
          ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pLVI, 0, win32con.MEM_RELEASE)
          ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pBuffertxt, 0, win32con.MEM_RELEASE)
          ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pBufferpnt, 0, win32con.MEM_RELEASE)
          win32api.CloseHandle(hProcHnd)
          return icons
      else:  # RESTORE ICON POSITIONS PROBLEM IS HERE SOMEWHERE!!!
          win32gui.SendMessage(slvhwnd, win32con.WM_SETREDRAW, 0, 0)
          for i in xrange(num_items):
              # Get icon text
              win32gui.SendMessage(slvhwnd, commctrl.LVM_GETITEMTEXT, i, pLVI)
              target_bufftxt = ctypes.create_string_buffer(4096)
              ctypes.windll.kernel32.ReadProcessMemory(hProcHnd, pBuffertxt, ctypes.addressof(target_bufftxt), 4096, p_copied)
              key = target_bufftxt.value
              if key in savedicons.keys():
                  # Set icon position
                  p = savedicons[key][1]  # p is ctypes POINT
                  p_lng = point_to_long(p)  # explicitly convert to HIWORD/LOWORD and c_long
                  # Reserve space for input variable in foreign process and get pointer to it the that memory space
                  pBufferpnt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd, 0, ctypes.sizeof(p_lng), win32con.MEM_RESERVE|win32con.MEM_COMMIT, win32con.PAGE_READWRITE)
                  # Write the desired coordinates in to the space just created
                  ret = ctypes.windll.kernel32.WriteProcessMemory(hProcHnd, pBufferpnt, ctypes.addressof(p_lng), ctypes.sizeof(p_lng), p_copied)
                  if ret == 0:
                      raise WindowsError
                  # Send the message to change the position for that item's index and the pointer to the new position
                  ret = win32gui.SendMessage(slvhwnd, commctrl.LVM_SETITEMPOSITION, i, pBufferpnt)
                  if ret == 0:
                      raise WindowsError
                  # Release the reserved memory for the variable (I recognize that I probably don't need to aLloc/free this within the loop)
                  ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pBufferpnt, 0, win32con.MEM_RELEASE)
          win32gui.SendMessage(slvhwnd, win32con.WM_SETREDRAW, 1, 0)
          ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pLVI, 0, win32con.MEM_RELEASE)
          ctypes.windll.kernel32.VirtualFreeEx(hProcHnd, pBuffertxt, 0, win32con.MEM_RELEASE)
          win32api.CloseHandle(hProcHnd)
          return None
  
  
  def point_to_long(p):
      ret = (p.y * 0x10000) + (p.x &amp; 0xFFFF)
      return ctypes.c_long(ret)
  
  if __name__ == '__main__':
      mysavedicons = icon_save_restore(restore=False)
      icon_save_restore(mysavedicons, restore=True)
  </code></pre>
  
  <p>I think there may be a problem with either 1) something to do with 32 bit and 64 bit memory address space, but the other components where I write the LVITEM structure or read the icon text work ok or 2) there is some issue in the way I am converting the coordinate information or calling SendMessage for GETITEMPOSITION. Any insight or help would be greatly appreciated.</p>