title: How to get a handle on Windows STDOUT handles (in python)?
body: <p>I am trying to get a handle on Windows <em>stdout</em> handles. </p>
  
  <p>I need to understand why there are different handles for STDOUT (<code>CONOUT$</code>?)
  and how to interpret these differences. I know there are different 
  output buffers used by the Windows API, but failt to understand (from the many MSDN docs) when and how to, use them.</p>
  
  <p>Using <code>ctypes</code> and python3, I can get 2 of these by the script below. However, running the script in (Cygwin) <strong><code>mintty/bash</code></strong>, <strong><code>PowerShell</code></strong> (6.1.1), <code>CMD</code> or even <code>ConEmu</code>, all yield slightly different results.</p>
  
  <p>In mintty all the stdout handles are the same, while in PowerShell they are 
  different. What is going on?</p>
  
  <p>Question:<br>
  <strong>Why are the stdout handles obtained by: <code>_get_osfhandle</code> and <code>GetStdHandle</code> different?</strong></p>
  
  <p>Here is my code:</p>
  
  
  
  <pre><code>#!/usr/bin/env python3
  #-*- coding: utf-8 -*-
  #----------------------------------------------------------------------------
  import sys
  import ctypes
  from ctypes import cdll, c_ulong
  
  def color(text, color_code):
      return '\x1b[%sm%s\x1b[0m' % (color_code, text)
  def byellow(text): return color(text, '1;49;33')
  def printHex(mode):
      return byellow("0x%04x  (%s)" % (mode, mode))   # DWORD
  
  kFile = 'C:\\Windows\\System32\\kernel32.dll'
  mFile = 'C:\\Windows\\System32\\msvcrt.dll'
  
  print("\n Getting Console STDOUT handles using 2 different methods:")
  
  try: 
      k32    = cdll.LoadLibrary(kFile)
      msvcrt = cdll.LoadLibrary(mFile)
  except OSError as e:
      print("ERROR: %s" % e)
      sys.exit(1)
  
  try: 
      hmsvcrt_osf = msvcrt._get_osfhandle(sys.stdout.fileno())    # Get the parent (?) process Console Output buffer Handle
      hk32_11     = k32.GetStdHandle(-11)                         # Get the current process Console Output buffer Handle
  except Exception as e:
      print("ERROR: %s" % e)
      sys.exit(1)
  
  print(" Got stdout handles using:\n")
  print("   msvcrt._get_osfhandle : %s" % printHex(hmsvcrt_osf))
  print("   k32.GetStdHandle(-11) : %s" % printHex(hk32_11))
  </code></pre>
  
  <p>Here is the output:</p>
  
  
  
  <pre><code># In PowerShell
  # python3.6m.exe .\testHandles.py
  
   Getting STDOUT handles using 2 different methods:
   Got stdout handles using:
  
     msvcrt._get_osfhandle : 0x001c  (28)
     k32.GetStdHandle(-11) : 0x014c  (332)
  
  # In Cygwin
  # ./testHandles.py
  
   Getting STDOUT handles using 2 different methods:
   Got stdout handles using:
  
     msvcrt._get_osfhandle : 0x0338  (824)
     k32.GetStdHandle(-11) : 0x0338  (824)
  
  # pwsh.exe -NoProfile -c "python3.6m.exe C:\test\testHandles.py"
  
   Getting STDOUT handles using 2 different methods:
   Got stdout handles using:
  
     msvcrt._get_osfhandle : 0x0338  (824)
     k32.GetStdHandle(-11) : 0x0144  (324)
  </code></pre>
  
  <p>According to MSDN: </p>
  
  <ul>
  <li><p><a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=vs-2017" rel="nofollow noreferrer"><code>_get_osfhandle</code></a>:  </p>
  
  <blockquote>
    <p>Retrieves the operating-system file handle that is associated with the specified file descriptor.</p>
  </blockquote></li>
  <li><p><a href="https://docs.microsoft.com/en-us/windows/console/getstdhandle" rel="nofollow noreferrer"><code>GetStdHandle</code></a>:  </p>
  
  <blockquote>
    <p>Retrieves a handle to the specified standard device (standard input, standard output, or standard error).</p>
  </blockquote></li>
  </ul>
  
  <p>Related Questions:  </p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/4232381/handle-to-window-handle-c">Handle to window handle</a></li>
  <li><a href="https://stackoverflow.com/questions/31926470/run-command-and-get-its-stdout-stderr-separately-in-near-real-time-like-in-a-te">Run command and get its stdout, stderr separately in near real time like in a terminal</a></li>
  </ul>
  
  <hr>
  
  <p><strong>ADDENDUM</strong>: 2018-12-14  </p>
  
  <p>In: <code>/usr/lib/python3.6/ctypes/__init__.py</code>:</p>
  
  <ul>
  <li><code>class CDLL(object)</code>:</li>
  </ul>
  
  <blockquote>
    <p>An instance of this class represents a loaded dll/shared
       library, exporting functions using the standard C calling
       convention (named 'cdecl' on Windows).</p>
    
    <p>The exported functions can be accessed as attributes, or by
       indexing with the function name.  Examples:</p>
    
    <p><code>&lt;obj&gt;.qsort</code> -> callable object</p>
    
    <p><code>&lt;obj&gt;['qsort']</code> -> callable object</p>
    
    <p>Calling the functions releases the Python GIL during the call and
       reacquires it afterwards.</p>
  </blockquote>
  
  <ul>
  <li><code>class PyDLL(CDLL)</code>:</li>
  </ul>
  
  <blockquote>
    <p>This class represents the Python library itself.  It allows
    accessing Python API functions.  The GIL is not released, and
    Python exceptions are handled correctly.</p>
  </blockquote>
  
  <p>Then <code>if _os.name == "nt"</code>:</p>
  
  <ul>
  <li><code>class WinDLL(CDLL)</code>:  </li>
  </ul>
  
  <blockquote>
    <p>This class represents a dll exporting functions using the
    Windows stdcall calling convention.</p>
  </blockquote>
  
  <hr>
  
  <h3>From the discussion comments:</h3>
  
  <p><strong><code>stdcall</code></strong>:  </p>
  
  <blockquote>
    <p>The stdcall[4] calling convention is a variation on the Pascal calling
    convention in which the callee is responsible for cleaning up the
    stack, but the parameters are pushed onto the stack in right-to-left
    order, as in the <code>_cdecl</code> calling convention. Registers EAX, ECX, and
    EDX are designated for use within the function. Return values are
    stored in the EAX register.</p>
    
    <p><code>stdcall</code> is the standard calling convention for the Microsoft Win32
    API and for Open Watcom C++.</p>
  </blockquote>