title: Why does this code call CloseHandle on a NULL handle?
body: <p>I'm trying to recreate some functionality found on the psutil project (https://code.google.com/p/psutil/) using ctypes. Using psutil would be an overkill for what I want, which is simply check if a given pid is currently running or not.</p>
  
  <p>The code snippet I'm trying to recreate is the <a href="http://code.google.com/searchframe#Dnjw9wRLlM4/trunk/psutil/arch/mswindows/process_info.c&amp;q=pid_is_running%20package%3apsutil%5C.googlecode%5C.com&amp;l=150" rel="nofollow">pid_is_running function</a>.</p>
  
  <pre><code>int
  pid_is_running(DWORD pid)
  {
      HANDLE hProcess;
      DWORD exitCode;
  
      // Special case for PID 0 System Idle Process
      if (pid == 0) {
          return 1;
      }
  
      if (pid &lt; 0) {
          return 0;
      }
  
      hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                             FALSE, pid);
      if (NULL == hProcess) {
          // invalid parameter is no such process
          if (GetLastError() == ERROR_INVALID_PARAMETER) {
              CloseHandle(hProcess);
              return 0;
          }
  
          // access denied obviously means there's a process to deny access to...
          if (GetLastError() == ERROR_ACCESS_DENIED) {
              CloseHandle(hProcess);
              return 1;
          }
  
          CloseHandle(hProcess);
          PyErr_SetFromWindowsErr(0);
          return -1;
      }
  
      if (GetExitCodeProcess(hProcess, &amp;exitCode)) {
          CloseHandle(hProcess);
          return (exitCode == STILL_ACTIVE);
      }
  
      // access denied means there's a process there so we'll assume it's running
      if (GetLastError() == ERROR_ACCESS_DENIED) {
          CloseHandle(hProcess);
          return 1;
      }
  
      PyErr_SetFromWindowsErr(0);
      CloseHandle(hProcess);
      return -1;
  }
  </code></pre>
  
  <p>I don't understand why the code is closing a NULL handle. Is that truly necessary? Is it wrong or could potentially cause an error?</p>
  
  <p>I would also appreciate any input on what I could come up with so far</p>
  
  <pre><code>import os
  import shlex
  import subprocess
  import ctypes as c
  import ctypes.wintypes as w
  
  PROCESS_QUERY_INFORMATION   = 0x0400L
  PROCESS_VM_READ             = 0x0010L             
  ERROR_INVALID_PARAMETER     = 0x57L
  ERROR_ACCESS_DENIED         = 0x5L
  STILL_ACTIVE                = 0x103L
  FALSE                       = 0L
  
  def start(cmd):
      l = shlex.split(cmd)
      return subprocess.Popen(l).pid
  
  def get_pid(hProcess):
      pid = w.DWORD()
      return c.windll.kernel32.GetProcessId(hProcess);
  
  def pid_is_running(pid):
      # adapted from psutil library 
      # http://code.google.com/searchframe#Dnjw9wRLlM4/trunk/psutil/arch/mswindows/process_info.c&amp;q=pid_is_running%20package:psutil\.googlecode\.com&amp;l=150
  
      pid         = w.DWORD(pid)
      hProcess    = w.HANDLE()
  
      if pid.value == 0L:
          return True
  
      if pid.value &lt; 0L:
          return False
  
      flags = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
      hProcess = c.windll.kernel32.OpenProcess(flags, FALSE, pid)
      try:
          if 0 == hProcess:
              # invalid parameter is no such process
              last_error = c.windll.kernel32.GetLastError()
              if last_error == ERROR_INVALID_PARAMETER:
                  return False
  
              # access denied obviously means there's a process to deny access to...
              if last_error == ERROR_ACCESS_DENIED:
                  return True
              #return -1 #  Error? Should I throw an exception
              raise Exception('Could not find process and an error occurred')
          else:
              exitCode = w.DWORD()    
              if c.windll.kernel32.GetExitCodeProcess(hProcess, c.byref(exitCode)):
                  return exitCode.value == STILL_ACTIVE
  
              # access denied means there's a process there so we'll assume it's running
              if c.windll.kernel32.GetLastError() == ERROR_ACCESS_DENIED:
                  return True
              #return -1 #  Error? Should I throw an exception
              raise Exception('Process found and an error occurred')
      finally:
          if hProcess != 0:
              c.windll.kernel32.CloseHandle(hProcess)
  </code></pre>