docs: def enumerate_tokens(sid=None, session_id=None, privs=None):
      '''
      Enumerate tokens from any existing processes that can be accessed.
      Optionally filter by sid.
      '''
      for p in psutil.process_iter():
          if p.pid == 0:
              continue
          try:
              ph = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, p.pid)
          except win32api.error as exc:
              if exc.winerror == 5:
                  log.debug("Unable to OpenProcess pid=%d name=%s", p.pid, p.name())
                  continue
              raise exc
          try:
              access = (
                  win32security.TOKEN_DUPLICATE |
                  win32security.TOKEN_QUERY |
                  win32security.TOKEN_IMPERSONATE |
                  win32security.TOKEN_ASSIGN_PRIMARY
              )
              th = win32security.OpenProcessToken(ph, access)
          except Exception as exc:
              log.debug("OpenProcessToken failed pid=%d name=%s user%s", p.pid, p.name(), p.username())
              continue
          try:
              process_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0]
          except Exception as exc:
              log.exception("GetTokenInformation pid=%d name=%s user%s", p.pid, p.name(), p.username())
              continue
  
          proc_sid = win32security.ConvertSidToStringSid(process_sid)
          if sid and sid != proc_sid:
              log.debug("Token for pid does not match user sid: %s", sid)
              continue
  
          if session_id and win32security.GetTokenInformation(th, win32security.TokenSessionId) != session_id:
              continue
  
          def has_priv(tok, priv):
              luid = win32security.LookupPrivilegeValue(None, priv)
              for priv_luid, flags in win32security.GetTokenInformation(tok, win32security.TokenPrivileges):
                  if priv_luid == luid:
                      return True
              return False
          if privs:
              has_all = True
              for name in privs:
                  if not has_priv(th, name):
                      has_all = False
              if not has_all:
                  continue
          yield dup_token(th)