class Net::SSH::Authentication::Pageant::Socket

simply by replacing the socket factory used by the Agent class.
the pageant daemon. This allows pageant support to be implemented
a socket, translating each request into a Windows messaging call to
This is the pseudo-socket implementation that mimics the interface of

def self.open(location=nil)

the general Socket interface.
parameter is ignored, and is only needed for compatibility with
The factory method for creating a new Socket instance. The location
def self.open(location=nil)
  new
end

def close

significant, but merely complies with the Socket interface.
Conceptually close the socket. This doesn't really do anthing
def close
  @res = nil
  @pos = 0
end

def closed?

complies with the Socket interface.
this doesn't really do anything significant, but merely
Conceptually asks if the socket is closed. As with #close,
def closed?
  @res.nil? && @pos.zero?
end

def initialize

instance. If no such instance is running, this will cause an error.
Create a new instance that communicates with the running pageant
def initialize
  @win = Win.FindWindow("Pageant", "Pageant")
  if @win == 0
    raise Net::SSH::Exception,
      "pageant process not running"
  end
  @res = nil
  @pos = 0
end

def read(n = nil)

is +nil+, returns all remaining data from the last query.
Reads +n+ bytes from the cached result of the last query. If +n+
def read(n = nil)
  return nil unless @res
  if n.nil?
    start, @pos = @pos, @res.size
    return @res[start..-1]
  else
    start, @pos = @pos, @pos + n
    return @res[start, n]
  end
end

def send(data, *args)

the first. Returns 0.
Forwards the data to #send_query, ignoring any arguments after
def send(data, *args)
  @res = send_query(data)
  @pos = 0
end

def send_query(query)

cached, to be returned piece-wise when #read is called.
process via the Windows messaging subsystem. The result is
Packages the given query string and sends it to the pageant
def send_query(query)
  res = nil
  filemap = 0
  ptr = nil
  id = DL::PtrData.malloc(DL.sizeof("L"))
  mapname = "PageantRequest%08x\000" % Win.getCurrentThreadId()
  filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE, 
                                  Win::NULL,
                                  Win::PAGE_READWRITE, 0, 
                                  AGENT_MAX_MSGLEN, mapname)
  if filemap == 0
    raise Net::SSH::Exception,
      "Creation of file mapping failed"
  end
  ptr = Win.mapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, 
                          AGENT_MAX_MSGLEN)
  if ptr.nil? || ptr.null?
    raise Net::SSH::Exception, "Mapping of file failed"
  end
  ptr[0] = query
  cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname].
    pack("LLp").to_ptr
  succ = Win.sendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
                                cds, Win::SMTO_NORMAL, 5000, id)
  if succ > 0
    retlen = 4 + ptr.to_s(4).unpack("N")[0]
    res = ptr.to_s(retlen)
  end        
  return res
ensure
  Win.unmapViewOfFile(ptr) unless ptr.nil? || ptr.null?
  Win.closeHandle(filemap) if filemap != 0
end