title: python map drive programmatically in Windows 10
body: <p>I'm trying to map a remote path on Windows 10 for serveral hours but i don't get it to work. At first i tried it with <code>WNetAddConnection2</code> but no matter what credentials or flags i use, when I type <code>net use</code> the mapped drive has always the status <code>not available</code>.</p>
  
  <p>Manually i can map drives without problems, I only have problems when i map the drive programmatically.</p>
  
  <pre><code>import win32wnet
  import win32netcon
  
  nr = win32wnet.NETRESOURCE()
  nr.dwScope = win32netcon.RESOURCE_GLOBALNET
  nr.dwType = win32netcon.RESOURCETYPE_DISK
  nr.dwUsage = win32netcon.RESOURCEUSAGE_CONNECTABLE
  nr.lpLocalName = 'Z:'
  nr.lpRemoteName = '\\\\192.168.178.46\\Test'
  
  win32wnet.WNetAddConnection2(nr, None, None, 25)
  </code></pre>
  
  <p>The 25 is a flag set of <code>interactive</code> and <code>prompt</code>. I don't get any errors and the drive is listed when i type <code>net use</code>, but the status is always <code>not available</code> and the drive is not visible under workstation.</p>
  
  <p>After that I tried <code>NetUseAdd</code>:</p>
  
  <pre><code>import win32net
  win32net.NetUseAdd(None, 3, {'remote': r'\\192.168.178.46\Test',
      'local': 'Z:', 'username': 'Admin', 'password': '123',
      'status': 0, 'flags': 1, 'asg_type': 0})
  </code></pre>
  
  <p>It runs successfully but <code>net use</code> doesn't list anything and no mapped drives are visible under workstation.</p>
  
  <p>A solution without subprocess would be nice. Can someone help please?</p>
  
  <p><strong>EDIT</strong>: Now i understand why it doesn't work. The app is running in admin context and I'm current logged in as non-admin. This behaviour is expalined here: <a href="https://superuser.com/questions/495370/why-isnt-a-mapped-drive-available-under-an-elevated-cmd-prompt-but-is-under-a-r">https://superuser.com/questions/495370/why-isnt-a-mapped-drive-available-under-an-elevated-cmd-prompt-but-is-under-a-r</a></p>
  
  <p>Is it possible to run the app as admin but the <code>WNetAddConnection2</code> method as current user??</p>
  
  <p><strong>EDIT 2</strong>: Following the instructions from eryksun i came up with this:</p>
  
  <pre><code>import ctypes
  from win32security import TOKEN_IMPERSONATE, TOKEN_ALL_ACCESS
  from win32process import GetWindowThreadProcessId
  from win32api import OpenProcess
  from win32security import OpenProcessToken
  from win32security import ImpersonateLoggedOnUser
  from win32security import RevertToSelf
  
  user32 = ctypes.WinDLL('user32', use_last_error=True);
  
  user32.GetShellWindow.restype = ctypes.c_void_p
  handle = user32.GetShellWindow()
  
  threadId, processId = GetWindowThreadProcessId(handle)
  
  handle_op = OpenProcess(TOKEN_ALL_ACCESS, True, processId)
  
  handle_opt = OpenProcessToken(handle_op, TOKEN_IMPERSONATE)
  ImpersonateLoggedOnUser(handle_opt) # throws access denied error
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/QLKmv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QLKmv.png" alt="enter image description here"></a></p>
  
  <p><strong>SOLUTION</strong>:</p>
  
  <pre><code>    import ctypes
      from win32process import GetWindowThreadProcessId
      from win32api import OpenProcess
      from win32security import OpenProcessToken, ImpersonateLoggedOnUser, RevertToSelf, TOKEN_QUERY, TOKEN_DUPLICATE
  
      from win32con import PROCESS_QUERY_INFORMATION
  
      user32 = ctypes.WinDLL('user32', use_last_error=True);
  
      user32.GetShellWindow.restype = ctypes.c_void_p
      handle = user32.GetShellWindow()
  
      threadId, processId = GetWindowThreadProcessId(handle)
  
      handle_op = OpenProcess(PROCESS_QUERY_INFORMATION, False, processId)
  
      handle_opt = OpenProcessToken(handle_op, TOKEN_QUERY | TOKEN_DUPLICATE)
      ImpersonateLoggedOnUser(handle_opt)
  
  
      try:
          nr = win32wnet.NETRESOURCE()
          nr.dwScope = win32netcon.RESOURCE_GLOBALNET
          nr.dwType = DISK
          nr.dwUsage = win32netcon.RESOURCEUSAGE_CONNECTABLE
          nr.lpLocalName = 'Z:'
          nr.lpRemoteName = '\\\\192.168.178.46\\Test'
  
          win32wnet.WNetAddConnection3(None, nr, None, None, 25)
      except:
          print("Unexpected error...")
  
      RevertToSelf()
  </code></pre>