1 /*
   2  * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 // A Simple Windows Debug Server.
  26 //
  27 // This software provides a socket-based debug server which uses
  28 // mostly ASCII protocols to communicate with its clients. Since the
  29 // Windows security model is largely based around being able to run
  30 // programs on the machine, this server only accepts connections
  31 // coming from localhost.
  32 //
  33 // When run as a service (under Windows NT), this software provides
  34 // clients the ability to attach to and detach from processes without
  35 // killing those processes. Ordinarily this is forbidden by the
  36 // Windows debugging APIs (although more recent debugging environments
  37 // from Microsoft seem to have circumvented this restriction, perhaps
  38 // in a different way). This is achieved by forking a persistent
  39 // subprocess for each debugging session which remains alive as long
  40 // as the target process is.
  41 //
  42 // At this point the client can read information out of the target
  43 // process's address space. Future work includes exposing more
  44 // functionality like writing to the remote address space and
  45 // suspending and resuming threads.
  46 
  47 #include <iostream>
  48 #include <vector>
  49 #include <stdlib.h>
  50 // Must come before everything else
  51 #include <winsock2.h>
  52 #include <assert.h>
  53 #include "Dispatcher.hpp"
  54 #include "Handler.hpp"
  55 #include "initWinsock.hpp"
  56 #include "ioUtils.hpp"
  57 #include "isNT4.hpp"
  58 #include "Message.hpp"
  59 #include "nt4internals.hpp"
  60 #include "ports.h"
  61 #include "procList.hpp"
  62 #include "serverLists.hpp"
  63 #include "Reaper.hpp"
  64 
  65 // Uncomment the #define below to get messages on stderr
  66 // #define DEBUGGING
  67 
  68 using namespace std;
  69 
  70 static ChildList childList;
  71 static ClientList clientList;
  72 static Reaper* reaper = NULL;
  73 
  74 // Needed prototypes
  75 void shutdownChild(ChildInfo* childInfo);
  76 void detachClient(ClientInfo* clientInfo);
  77 void shutdownClient(ClientInfo* clientInfo);
  78 
  79 char *
  80 longToDotFormat(long addr)
  81 {
  82   char *temp_s = new char[20];
  83 
  84   sprintf(temp_s, "%d.%d.%d.%d", ((addr & 0xff000000) >> 24),
  85           ((addr & 0x00ff0000) >> 16), ((addr & 0x0000ff00) >> 8),
  86           (addr & 0x000000ff));
  87 
  88   return temp_s;
  89 }
  90 
  91 // NOTE that we do this query every time. It is a bad idea to cache IP
  92 // addresses. For example, we might be hosted on a machine using DHCP
  93 // and the connection addresses might change over time. (Yes, this
  94 // actually happened.)
  95 bool
  96 isConnectionOkay(ULONG connAddr) {
  97   if (connAddr == INADDR_LOOPBACK) {
  98     return true;
  99   }
 100 
 101   const int MAXNAME = 1024;
 102   char myname[MAXNAME];
 103   gethostname(myname, MAXNAME);
 104   struct hostent* myInfo = gethostbyname(myname);
 105   if (myInfo == NULL) {
 106 #ifdef DEBUGGING
 107     cerr << "My host information was null" << endl;
 108 #endif
 109   } else {
 110     // Run down the list of IP addresses for myself
 111     assert(myInfo->h_length == sizeof(ULONG));
 112 #ifdef DEBUGGING
 113     cerr << "My known IP addresses: " << endl;
 114 #endif
 115     for (char** pp = myInfo->h_addr_list; *pp != NULL; pp++) {
 116       char* p = *pp;
 117       ULONG altAddr = ntohl(*((ULONG*) p));
 118 #ifdef DEBUGGING
 119       char* name = longToDotFormat(altAddr);
 120       cerr << name << endl;
 121       delete[] name;
 122 #endif
 123       if (altAddr == connAddr) {
 124 #ifdef DEBUGGING
 125         cerr << "FOUND" << endl;
 126 #endif
 127         return true;
 128       }
 129     }
 130 #ifdef DEBUGGING
 131     cerr << "Done." << endl;
 132 #endif
 133   }
 134 
 135   return false;
 136 }
 137 
 138 SOCKET
 139 setupListeningSocket(short port) {
 140   SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
 141   if (listening == INVALID_SOCKET) {
 142     cerr << "Error creating listening socket" << endl;
 143     exit(1);
 144   }
 145 
 146   int reuseAddress = 1;
 147   if (setsockopt(listening, SOL_SOCKET, SO_REUSEADDR,
 148                  (char *)&reuseAddress, sizeof(reuseAddress)) == -1) {
 149     cerr << "Error reusing address" << endl;
 150     exit(1);
 151   }
 152 
 153   struct sockaddr_in serverInfo;
 154 
 155   memset((char *)&serverInfo, 0, sizeof(serverInfo));
 156   serverInfo.sin_addr.s_addr = INADDR_ANY;
 157   serverInfo.sin_family = AF_INET;
 158   serverInfo.sin_port = htons(port);
 159 
 160   if (bind(listening, (struct sockaddr *) &serverInfo, sizeof(serverInfo)) < 0) {
 161     cerr << "Error binding socket" << endl;
 162     exit(1);
 163   }
 164 
 165   if (listen(listening, 5) < 0) {
 166     cerr << "Error listening" << endl;
 167     exit(1);
 168   }
 169 
 170   return listening;
 171 }
 172 
 173 /** Accepts a connection from the given listening socket, but only if
 174     the connection came from localhost. Returns INVALID_SOCKET if the
 175     connection came from any other IP address or if an error occurred
 176     during the call to accept(). */
 177 SOCKET
 178 acceptFromLocalhost(SOCKET listening) {
 179   struct sockaddr_in peerAddr;
 180   int peerAddrLen = sizeof(peerAddr);
 181   SOCKET fd = accept(listening, (sockaddr*) &peerAddr, &peerAddrLen);
 182   if (fd == INVALID_SOCKET) {
 183     return fd;
 184   }
 185 
 186   if (!isConnectionOkay(ntohl(peerAddr.sin_addr.s_addr))) {
 187     // Reject connections from other machines for security purposes.
 188     // The Windows security model seems to assume one user per
 189     // machine, and that security is compromised if another user is
 190     // able to run executables on the given host. (If these
 191     // assumptions are not strict enough, we will have to change
 192     // this.)
 193     shutdown(fd, SD_BOTH);
 194     closesocket(fd);
 195     return INVALID_SOCKET;
 196   }
 197 
 198   // Disable TCP buffering on all sockets. We send small amounts of
 199   // data back and forth and don't want buffering.
 200   int buffer_val = 1;
 201   if (setsockopt(fd, IPPROTO_IP, TCP_NODELAY,
 202                  (char *) &buffer_val, sizeof(buffer_val)) < 0) {
 203     shutdown(fd, SD_BOTH);
 204     closesocket(fd);
 205   }
 206 
 207   return fd;
 208 }
 209 
 210 void
 211 reapCB(void* arg) {
 212   ChildInfo* info = (ChildInfo*) arg;
 213   ListsLocker ll;
 214   DWORD pid = info->getPid();
 215   shutdownChild(info);
 216 #ifdef DEBUGGING
 217   cerr << "Reaped child for process " << pid << endl;
 218 #endif
 219 }
 220 
 221 /** Starts a child process with stdin and stdout redirected to pipes,
 222     handles to which are returned. auxHandle1 and auxHandle2 should be
 223     closed as well when the child process exits. Returns false if
 224     process creation failed. */
 225 bool
 226 startChildProcess(DWORD pidToDebug,
 227                   DWORD childStdinBufSize,
 228                   DWORD childStdoutBufSize,
 229                   LPHANDLE childProcessHandle,
 230                   LPHANDLE writeToStdinHandle,
 231                   LPHANDLE readFromStdoutHandle,
 232                   LPHANDLE auxHandle1,
 233                   LPHANDLE auxHandle2) {
 234   // Code adapted from Microsoft example
 235   // "Creating a Child Process with Redirected Input and Output"
 236 
 237   SECURITY_ATTRIBUTES saAttr;
 238   BOOL fSuccess;
 239 
 240   HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
 241     hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
 242     hSaveStdin, hSaveStdout;
 243 
 244   // Set the bInheritHandle flag so pipe handles are inherited.
 245   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 246   saAttr.bInheritHandle = TRUE;
 247   saAttr.lpSecurityDescriptor = NULL;
 248 
 249   // The steps for redirecting child process's STDOUT:
 250   //   1. Save current STDOUT, to be restored later.
 251   //   2. Create anonymous pipe to be STDOUT for child process.
 252   //   3. Set STDOUT of the parent process to be write handle to
 253   //      the pipe, so it is inherited by the child process.
 254   //   4. Create a noninheritable duplicate of the read handle and
 255   //      close the inheritable read handle.
 256 
 257   // Save the handle to the current STDOUT.
 258   hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 259   // Create a pipe for the child process's STDOUT.
 260   if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, childStdoutBufSize)) {
 261     return false;
 262   }
 263   // Set a write handle to the pipe to be STDOUT.
 264   if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) {
 265     return false;
 266   }
 267   // Create noninheritable read handle and close the inheritable read
 268   // handle.
 269   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
 270                              GetCurrentProcess(), &hChildStdoutRdDup,
 271                              0, FALSE,
 272                              DUPLICATE_SAME_ACCESS);
 273   if( !fSuccess ) {
 274     return false;
 275   }
 276   CloseHandle(hChildStdoutRd);
 277 
 278   // The steps for redirecting child process's STDIN:
 279   //   1.  Save current STDIN, to be restored later.
 280   //   2.  Create anonymous pipe to be STDIN for child process.
 281   //   3.  Set STDIN of the parent to be the read handle to the
 282   //       pipe, so it is inherited by the child process.
 283   //   4.  Create a noninheritable duplicate of the write handle,
 284   //       and close the inheritable write handle.
 285   // Save the handle to the current STDIN.
 286   hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 287   // Create a pipe for the child process's STDIN.
 288   if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, childStdinBufSize)) {
 289     return false;
 290   }
 291   // Set a read handle to the pipe to be STDIN.
 292   if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) {
 293     return false;
 294   }
 295   // Duplicate the write handle to the pipe so it is not inherited.
 296   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
 297                              GetCurrentProcess(), &hChildStdinWrDup, 0,
 298                              FALSE,                  // not inherited
 299                              DUPLICATE_SAME_ACCESS);
 300   if (! fSuccess) {
 301     return false;
 302   }
 303   CloseHandle(hChildStdinWr);
 304 
 305   // Create the child process
 306   char cmdLine[256];
 307   sprintf(cmdLine, "SwDbgSub.exe %u", pidToDebug);
 308   PROCESS_INFORMATION procInfo;
 309   STARTUPINFO startInfo;
 310   memset((char*) &startInfo, 0, sizeof(startInfo));
 311   startInfo.cb = sizeof(startInfo);
 312   BOOL res = CreateProcess(NULL,
 313                            cmdLine,
 314                            NULL,
 315                            NULL,
 316                            TRUE, // inherit handles: important
 317                            0,
 318                            NULL,
 319                            NULL,
 320                            &startInfo,
 321                            &procInfo);
 322   if (!res) {
 323     return false;
 324   }
 325   // After process creation, restore the saved STDIN and STDOUT.
 326   if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) {
 327     return false;
 328   }
 329   if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
 330     return false;
 331   }
 332 
 333   // hChildStdinWrDup can be used to write to the child's stdin
 334   // hChildStdoutRdDup can be used to read from the child's stdout
 335 
 336   // NOTE: example code closes hChildStdoutWr before reading from
 337   // hChildStdoutRdDup. "Close the write end of the pipe before
 338   // reading from the read end of the pipe"??? Looks like this is
 339   // example-specific.
 340 
 341   // Set up return arguments
 342   // hChildStdoutRd and hChildStdinWr are already closed at this point
 343   *childProcessHandle = procInfo.hProcess;
 344   *writeToStdinHandle = hChildStdinWrDup;
 345   *readFromStdoutHandle = hChildStdoutRdDup;
 346   *auxHandle1 = hChildStdinRd;
 347   *auxHandle2 = hChildStdoutWr;
 348   return true;
 349 }
 350 
 351 /** Clears the event and writes the message to the child process */
 352 bool
 353 sendMessage(ChildInfo* child, Message* message) {
 354   DWORD numBytesWritten;
 355   if (!WriteFile(child->getWriteToStdinHandle(),
 356                  message, sizeof(Message), &numBytesWritten, NULL)) {
 357     return false;
 358   }
 359   if (numBytesWritten != sizeof(Message)) {
 360     return false;
 361   }
 362   // Follow up "poke" messages with the raw data
 363   if (message->type == Message::POKE) {
 364     if (!WriteFile(child->getWriteToStdinHandle(),
 365                    message->pokeArg.data, message->pokeArg.numBytes, &numBytesWritten, NULL)) {
 366       return false;
 367     }
 368     if (numBytesWritten != message->pokeArg.numBytes) {
 369       return false;
 370     }
 371   }
 372   return true;
 373 }
 374 
 375 /** Copies data from child's stdout to the client's IOBuf and sends it
 376     along */
 377 bool
 378 forwardReplyToClient(ChildInfo* child, ClientInfo* client) {
 379   DWORD total = 0;
 380   IOBuf::FillState ret;
 381 
 382   do {
 383     DWORD temp;
 384     ret = client->getIOBuf()->fillFromFileHandle(child->getReadFromStdoutHandle(),
 385                                                  &temp);
 386     if (ret == IOBuf::DONE || ret == IOBuf::MORE_DATA_PENDING) {
 387       if (!client->getIOBuf()->flush()) {
 388 #ifdef DEBUGGING
 389         cerr << "Forward failed because flush failed" << endl;
 390 #endif
 391         return false;
 392       }
 393       total += temp;
 394     }
 395   } while (ret == IOBuf::MORE_DATA_PENDING);
 396 
 397   return (ret == IOBuf::FAILED) ? false : true;
 398 }
 399 
 400 //----------------------------------------------------------------------
 401 // Server Handler
 402 //
 403 
 404 class ServerHandler : public Handler {
 405 public:
 406   ServerHandler();
 407 
 408   // Starts up in Unicode mode by default
 409   bool getASCII();
 410 
 411   void setIOBuf(IOBuf* ioBuf);
 412 
 413   void procList(char* arg);
 414 
 415   // Must be called before calling one of the routines below
 416   void setClientInfo(ClientInfo* info);
 417 
 418   // Indicates to outer loop that exit was called or that an error
 419   // occurred and that the client exited.
 420   bool exited();
 421   // Clears this state
 422   void clearExited();
 423 
 424   void ascii(char* arg);
 425   void unicode(char* arg);
 426   void attach(char* arg);
 427   void detach(char* arg);
 428   void libInfo(char* arg);
 429   void peek(char* arg);
 430   void poke(char* arg);
 431   void threadList(char* arg);
 432   void dupHandle(char* arg);
 433   void closeHandle(char* arg);
 434   void getContext(char* arg);
 435   void setContext(char* arg);
 436   void selectorEntry(char* arg);
 437   void suspend(char* arg);
 438   void resume(char* arg);
 439   void pollEvent(char* arg);
 440   void continueEvent(char* arg);
 441   void exit(char* arg);
 442 
 443   // This is pretty gross. Needed to make the target process know
 444   // about clients that have disconnected unexpectedly while attached.
 445   friend void shutdownClient(ClientInfo*);
 446 private:
 447   // Writes: charSize <space> numChars <space> <binary string>
 448   // Handles both ASCII and UNICODE modes
 449   void writeString(USHORT len, WCHAR* str);
 450 
 451   // Handles only ASCII mode
 452   void writeString(USHORT len, char* str);
 453 
 454   ClientInfo* clientInfo;
 455   IOBuf* ioBuf;
 456   bool _exited;
 457   bool _ascii;
 458 };
 459 
 460 static ServerHandler* handler;
 461 
 462 ServerHandler::ServerHandler() {
 463   _exited = false;
 464   _ascii = false;
 465   ioBuf = NULL;
 466 }
 467 
 468 bool
 469 ServerHandler::getASCII() {
 470   return _ascii;
 471 }
 472 
 473 void
 474 ServerHandler::setIOBuf(IOBuf* buf) {
 475   ioBuf = buf;
 476 }
 477 
 478 void
 479 ServerHandler::setClientInfo(ClientInfo* info) {
 480   clientInfo = info;
 481 }
 482 
 483 bool
 484 ServerHandler::exited() {
 485   return _exited;
 486 }
 487 
 488 void
 489 ServerHandler::clearExited() {
 490   _exited = false;
 491 }
 492 
 493 void
 494 ServerHandler::ascii(char* arg) {
 495   _ascii = true;
 496 }
 497 
 498 void
 499 ServerHandler::unicode(char* arg) {
 500   _ascii = false;
 501 }
 502 
 503 void
 504 ServerHandler::procList(char* arg) {
 505 #ifdef DEBUGGING
 506   cerr << "proclist" << endl;
 507 #endif
 508 
 509   ProcEntryList processes;
 510   ::procList(processes);
 511 
 512   ioBuf->writeInt(processes.size());
 513 
 514   for (ProcEntryList::iterator iter = processes.begin();
 515        iter != processes.end(); iter++) {
 516     ProcEntry& entry = *iter;
 517     ioBuf->writeSpace();
 518     ioBuf->writeUnsignedInt(entry.getPid());
 519     ioBuf->writeSpace();
 520     writeString(entry.getNameLength(), entry.getName());
 521   }
 522 
 523   ioBuf->writeEOL();
 524   ioBuf->flush();
 525 }
 526 
 527 void
 528 ServerHandler::attach(char* arg) {
 529   // If the client is already attached to a process, fail.
 530   if (clientInfo->getTarget() != NULL) {
 531     ioBuf->writeBoolAsInt(false);
 532     ioBuf->writeEOL();
 533     ioBuf->flush();
 534     return;
 535   }
 536 
 537   // Try to get pid
 538   DWORD pid;
 539   if (!scanUnsignedLong(&arg, &pid)) {
 540     ioBuf->writeBoolAsInt(false);
 541     ioBuf->writeEOL();
 542     ioBuf->flush();
 543     return;
 544   }
 545 
 546   // See whether this pid is already forked
 547   ListsLocker ll;
 548   ChildInfo* childInfo = childList.getChildByPid(pid);
 549   if (childInfo != NULL) {
 550     // If this child already has a client, return false
 551     if (childInfo->getClient() != NULL) {
 552       ioBuf->writeBoolAsInt(false);
 553       ioBuf->writeEOL();
 554       ioBuf->flush();
 555       return;
 556     }
 557 
 558     // Otherwise, can associate this client with this child process
 559     childInfo->setClient(clientInfo);
 560     clientInfo->setTarget(childInfo);
 561 
 562     // Tell the child we are attaching so it can suspend the target
 563     // process
 564     Message msg;
 565     msg.type = Message::ATTACH;
 566     sendMessage(childInfo, &msg);
 567 
 568     ioBuf->writeBoolAsInt(true);
 569     ioBuf->writeEOL();
 570     ioBuf->flush();
 571     return;
 572   } else {
 573     // Have to fork a new child subprocess
 574     HANDLE childProcessHandle;
 575     HANDLE writeToStdinHandle;
 576     HANDLE readFromStdoutHandle;
 577     HANDLE auxHandle1;
 578     HANDLE auxHandle2;
 579     if (!startChildProcess(pid,
 580                            32768,
 581                            131072,
 582                            &childProcessHandle,
 583                            &writeToStdinHandle,
 584                            &readFromStdoutHandle,
 585                            &auxHandle1,
 586                            &auxHandle2)) {
 587       ioBuf->writeBoolAsInt(false);
 588       ioBuf->writeEOL();
 589       ioBuf->flush();
 590       return;
 591     }
 592 
 593     // See whether the child succeeded in attaching to the process
 594     char res;
 595     DWORD numRead;
 596     if (!ReadFile(readFromStdoutHandle,
 597                   &res,
 598                   sizeof(char),
 599                   &numRead,
 600                   NULL)) {
 601       ioBuf->writeBoolAsInt(false);
 602       ioBuf->writeEOL();
 603       ioBuf->flush();
 604       return;
 605     }
 606 
 607     if (!res) {
 608       ioBuf->writeBoolAsInt(false);
 609       ioBuf->writeEOL();
 610       ioBuf->flush();
 611       return;
 612     }
 613 
 614     // OK, success.
 615     childInfo = new ChildInfo(pid, childProcessHandle,
 616                               writeToStdinHandle, readFromStdoutHandle,
 617                               auxHandle1, auxHandle2);
 618     childList.addChild(childInfo);
 619     reaper->registerProcess(childProcessHandle, childInfo);
 620     // Associate this client with this child process
 621     childInfo->setClient(clientInfo);
 622     clientInfo->setTarget(childInfo);
 623 
 624     // Tell the child process to actually suspend the target process
 625     Message msg;
 626     msg.type = Message::ATTACH;
 627     sendMessage(childInfo, &msg);
 628 
 629     // Write result to client
 630     ioBuf->writeBoolAsInt(true);
 631     ioBuf->writeEOL();
 632     ioBuf->flush();
 633     return;
 634   }
 635 }
 636 
 637 void
 638 ServerHandler::detach(char* arg) {
 639   // If the client is not attached, fail.
 640   if (clientInfo->getTarget() == NULL) {
 641     ioBuf->writeBoolAsInt(false);
 642     ioBuf->writeEOL();
 643     ioBuf->flush();
 644     return;
 645   }
 646 
 647   detachClient(clientInfo);
 648 
 649   ioBuf->writeBoolAsInt(true);
 650   ioBuf->writeEOL();
 651   ioBuf->flush();
 652 }
 653 
 654 void
 655 ServerHandler::libInfo(char* arg) {
 656   ListsLocker ll;
 657   ChildInfo* child = clientInfo->getTarget();
 658   if (child == NULL) {
 659     ioBuf->writeInt(0);
 660     ioBuf->writeEOL();
 661     ioBuf->flush();
 662     return;
 663   }
 664 
 665   // Send message to child
 666   Message msg;
 667   msg.type = Message::LIBINFO;
 668   sendMessage(child, &msg);
 669 
 670   // Forward reply to client
 671   forwardReplyToClient(child, clientInfo);
 672 }
 673 
 674 void
 675 ServerHandler::peek(char* arg) {
 676   ListsLocker ll;
 677   ChildInfo* child = clientInfo->getTarget();
 678   if (child == NULL) {
 679     ioBuf->writeString("B");
 680     ioBuf->writeBinChar(0);
 681     ioBuf->flush();
 682     return;
 683   }
 684 
 685   // Try to get address
 686   DWORD address;
 687   if (!scanAddress(&arg, &address)) {
 688     ioBuf->writeString("B");
 689     ioBuf->writeBinChar(0);
 690     ioBuf->flush();
 691     return;
 692   }
 693 
 694   // Try to get number of bytes
 695   DWORD numBytes;
 696   if (!scanUnsignedLong(&arg, &numBytes)) {
 697     ioBuf->writeString("B");
 698     ioBuf->writeBinChar(0);
 699     ioBuf->flush();
 700     return;
 701   }
 702 
 703   // Send message to child
 704   Message msg;
 705   msg.type = Message::PEEK;
 706   msg.peekArg.address = address;
 707   msg.peekArg.numBytes = numBytes;
 708   sendMessage(child, &msg);
 709 
 710   // Forward reply to client
 711   forwardReplyToClient(child, clientInfo);
 712 }
 713 
 714 void
 715 ServerHandler::poke(char* arg) {
 716 #ifdef DEBUGGING
 717   cerr << "ServerHandler::poke" << endl;
 718 #endif
 719   ListsLocker ll;
 720   ChildInfo* child = clientInfo->getTarget();
 721   if (child == NULL) {
 722     ioBuf->writeBoolAsInt(false);
 723     ioBuf->flush();
 724     return;
 725   }
 726 
 727   // Try to get address
 728   DWORD address;
 729   if (!scanAddress(&arg, &address)) {
 730     ioBuf->writeBoolAsInt(false);
 731     ioBuf->flush();
 732     return;
 733   }
 734 
 735   // Try to get number of bytes
 736   if (!scanAndSkipBinEscapeChar(&arg)) {
 737     ioBuf->writeBoolAsInt(false);
 738     ioBuf->flush();
 739     return;
 740   }
 741   DWORD numBytes;
 742   if (!scanBinUnsignedLong(&arg, &numBytes)) {
 743     ioBuf->writeBoolAsInt(false);
 744     ioBuf->flush();
 745     return;
 746   }
 747 
 748   // Raw data is now in "arg"
 749   // Send message to child
 750   Message msg;
 751   msg.type = Message::POKE;
 752   msg.pokeArg.address = address;
 753   msg.pokeArg.numBytes = numBytes;
 754   msg.pokeArg.data = arg;
 755   sendMessage(child, &msg);
 756 
 757   // Forward reply to client
 758   forwardReplyToClient(child, clientInfo);
 759 }
 760 
 761 void
 762 ServerHandler::threadList(char* arg) {
 763   ListsLocker ll;
 764   ChildInfo* child = clientInfo->getTarget();
 765   if (child == NULL) {
 766     ioBuf->writeBoolAsInt(false);
 767     ioBuf->flush();
 768     return;
 769   }
 770 
 771   // Send message to child
 772   Message msg;
 773   msg.type = Message::THREADLIST;
 774   sendMessage(child, &msg);
 775 
 776   // Forward reply to client
 777   forwardReplyToClient(child, clientInfo);
 778 }
 779 
 780 void
 781 ServerHandler::dupHandle(char* arg) {
 782   ListsLocker ll;
 783   ChildInfo* child = clientInfo->getTarget();
 784   if (child == NULL) {
 785     ioBuf->writeBoolAsInt(false);
 786     ioBuf->flush();
 787     return;
 788   }
 789 
 790   // Try to get handle
 791   DWORD address;
 792   if (!scanAddress(&arg, &address)) {
 793     ioBuf->writeBoolAsInt(false);
 794     ioBuf->flush();
 795   }
 796 
 797   // Send message to child
 798   Message msg;
 799   msg.type = Message::DUPHANDLE;
 800   msg.handleArg.handle = (HANDLE) address;
 801   sendMessage(child, &msg);
 802 
 803   // Forward reply to client
 804   forwardReplyToClient(child, clientInfo);
 805 }
 806 
 807 void
 808 ServerHandler::closeHandle(char* arg) {
 809   ListsLocker ll;
 810   ChildInfo* child = clientInfo->getTarget();
 811   if (child == NULL) {
 812     return;
 813   }
 814 
 815   // Try to get handle
 816   DWORD address;
 817   if (!scanAddress(&arg, &address)) {
 818     return;
 819   }
 820 
 821   // Send message to child
 822   Message msg;
 823   msg.type = Message::CLOSEHANDLE;
 824   msg.handleArg.handle = (HANDLE) address;
 825   sendMessage(child, &msg);
 826 
 827   // No reply
 828 }
 829 
 830 void
 831 ServerHandler::getContext(char* arg) {
 832   ListsLocker ll;
 833   ChildInfo* child = clientInfo->getTarget();
 834   if (child == NULL) {
 835     ioBuf->writeBoolAsInt(false);
 836     ioBuf->flush();
 837     return;
 838   }
 839 
 840   // Try to get handle
 841   DWORD address;
 842   if (!scanAddress(&arg, &address)) {
 843     ioBuf->writeBoolAsInt(false);
 844     ioBuf->flush();
 845     return;
 846   }
 847 
 848   // Send message to child
 849   Message msg;
 850   msg.type = Message::GETCONTEXT;
 851   msg.handleArg.handle = (HANDLE) address;
 852   sendMessage(child, &msg);
 853 
 854   // Forward reply to client
 855   forwardReplyToClient(child, clientInfo);
 856 }
 857 
 858 void
 859 ServerHandler::setContext(char* arg) {
 860   ListsLocker ll;
 861   ChildInfo* child = clientInfo->getTarget();
 862   if (child == NULL) {
 863     ioBuf->writeBoolAsInt(false);
 864     ioBuf->flush();
 865     return;
 866   }
 867 
 868   // Try to get handle
 869   DWORD address;
 870   if (!scanAddress(&arg, &address)) {
 871     ioBuf->writeBoolAsInt(false);
 872     ioBuf->flush();
 873     return;
 874   }
 875 
 876   // Try to get context
 877   DWORD regs[NUM_REGS_IN_CONTEXT];
 878   for (int i = 0; i < NUM_REGS_IN_CONTEXT; i++) {
 879     if (!scanAddress(&arg, &regs[i])) {
 880       ioBuf->writeBoolAsInt(false);
 881       ioBuf->flush();
 882       return;
 883     }
 884   }
 885 
 886   // Send message to child
 887   Message msg;
 888   msg.type = Message::SETCONTEXT;
 889   msg.setContextArg.handle = (HANDLE) address;
 890   msg.setContextArg.Eax    = regs[0];
 891   msg.setContextArg.Ebx    = regs[1];
 892   msg.setContextArg.Ecx    = regs[2];
 893   msg.setContextArg.Edx    = regs[3];
 894   msg.setContextArg.Esi    = regs[4];
 895   msg.setContextArg.Edi    = regs[5];
 896   msg.setContextArg.Ebp    = regs[6];
 897   msg.setContextArg.Esp    = regs[7];
 898   msg.setContextArg.Eip    = regs[8];
 899   msg.setContextArg.Ds     = regs[9];
 900   msg.setContextArg.Es     = regs[10];
 901   msg.setContextArg.Fs     = regs[11];
 902   msg.setContextArg.Gs     = regs[12];
 903   msg.setContextArg.Cs     = regs[13];
 904   msg.setContextArg.Ss     = regs[14];
 905   msg.setContextArg.EFlags = regs[15];
 906   msg.setContextArg.Dr0    = regs[16];
 907   msg.setContextArg.Dr1    = regs[17];
 908   msg.setContextArg.Dr2    = regs[18];
 909   msg.setContextArg.Dr3    = regs[19];
 910   msg.setContextArg.Dr6    = regs[20];
 911   msg.setContextArg.Dr7    = regs[21];
 912   sendMessage(child, &msg);
 913 
 914   // Forward reply to client
 915   forwardReplyToClient(child, clientInfo);
 916 }
 917 
 918 void
 919 ServerHandler::selectorEntry(char* arg) {
 920   ListsLocker ll;
 921   ChildInfo* child = clientInfo->getTarget();
 922   if (child == NULL) {
 923     ioBuf->writeBoolAsInt(false);
 924     ioBuf->flush();
 925     return;
 926   }
 927 
 928   // Try to get thread handle
 929   DWORD address;
 930   if (!scanAddress(&arg, &address)) {
 931     ioBuf->writeBoolAsInt(false);
 932     ioBuf->flush();
 933     return;
 934   }
 935 
 936   // Try to get selector
 937   DWORD selector;
 938   if (!scanUnsignedLong(&arg, &selector)) {
 939     ioBuf->writeBoolAsInt(false);
 940     ioBuf->flush();
 941     return;
 942   }
 943 
 944   // Send message to child
 945   Message msg;
 946   msg.type = Message::SELECTORENTRY;
 947   msg.selectorArg.handle   = (HANDLE) address;
 948   msg.selectorArg.selector = selector;
 949   sendMessage(child, &msg);
 950 
 951   // Forward reply to client
 952   forwardReplyToClient(child, clientInfo);
 953 }
 954 
 955 void
 956 ServerHandler::suspend(char* arg) {
 957   ListsLocker ll;
 958   ChildInfo* child = clientInfo->getTarget();
 959   if (child == NULL) {
 960     return;
 961   }
 962 
 963   // Send message to child
 964   Message msg;
 965   msg.type = Message::SUSPEND;
 966   sendMessage(child, &msg);
 967 
 968   // No reply
 969 }
 970 
 971 void
 972 ServerHandler::resume(char* arg) {
 973   ListsLocker ll;
 974   ChildInfo* child = clientInfo->getTarget();
 975   if (child == NULL) {
 976     return;
 977   }
 978 
 979   // Send message to child
 980   Message msg;
 981   msg.type = Message::RESUME;
 982   sendMessage(child, &msg);
 983 
 984   // No reply
 985 }
 986 
 987 void
 988 ServerHandler::pollEvent(char* arg) {
 989   ListsLocker ll;
 990   ChildInfo* child = clientInfo->getTarget();
 991   if (child == NULL) {
 992     ioBuf->writeBoolAsInt(false);
 993     ioBuf->flush();
 994     return;
 995   }
 996 
 997   // Send message to child
 998   Message msg;
 999   msg.type = Message::POLLEVENT;
1000   sendMessage(child, &msg);
1001 
1002   // Forward reply to client
1003   forwardReplyToClient(child, clientInfo);
1004 }
1005 
1006 void
1007 ServerHandler::continueEvent(char* arg) {
1008   ListsLocker ll;
1009   ChildInfo* child = clientInfo->getTarget();
1010   if (child == NULL) {
1011     ioBuf->writeBoolAsInt(false);
1012     ioBuf->flush();
1013     return;
1014   }
1015 
1016   // Try to get bool arg
1017   int passEventToClient;
1018   if (!scanInt(&arg, &passEventToClient)) {
1019     ioBuf->writeBoolAsInt(false);
1020     ioBuf->flush();
1021     return;
1022   }
1023 
1024   // Send message to child
1025   Message msg;
1026   msg.type = Message::CONTINUEEVENT;
1027   msg.boolArg.val = ((passEventToClient != 0) ? true : false);
1028   sendMessage(child, &msg);
1029 
1030   // Forward reply to client
1031   forwardReplyToClient(child, clientInfo);
1032 }
1033 
1034 void
1035 ServerHandler::exit(char* arg) {
1036   shutdownClient(clientInfo);
1037   _exited = true;
1038 }
1039 
1040 void
1041 ServerHandler::writeString(USHORT len, WCHAR* str) {
1042   if (_ascii) {
1043     char* cStr = new char[len + 1];
1044     sprintf(cStr, "%.*ls", len, str);
1045     writeString(len, cStr);
1046     delete[] cStr;
1047   } else {
1048     ioBuf->writeInt(sizeof(unsigned short));
1049     ioBuf->writeSpace();
1050     ioBuf->writeInt(len);
1051     ioBuf->writeSpace();
1052     for (int i = 0; i < len; i++) {
1053       ioBuf->writeBinUnsignedShort(str[i]);
1054     }
1055   }
1056 }
1057 
1058 void
1059 ServerHandler::writeString(USHORT len, char* str) {
1060   ioBuf->writeInt(1);
1061   ioBuf->writeSpace();
1062   ioBuf->writeInt(len);
1063   ioBuf->writeSpace();
1064   ioBuf->writeString(str);
1065 }
1066 
1067 //
1068 //----------------------------------------------------------------------
1069 
1070 //----------------------------------------------------------------------
1071 // Shutdown routines
1072 //
1073 
1074 void
1075 shutdownChild(ChildInfo* childInfo) {
1076   childList.removeChild(childInfo);
1077   childInfo->closeAll();
1078   if (childInfo->getClient() != NULL) {
1079     shutdownClient(childInfo->getClient());
1080   }
1081   delete childInfo;
1082 }
1083 
1084 void
1085 detachClient(ClientInfo* info) {
1086   ListsLocker ll;
1087   // May have been dissociated while not under cover of lock
1088   if (info->getTarget() == NULL) {
1089     return;
1090   }
1091 
1092   // Tell the child that we have detached to let the target process
1093   // continue running
1094   Message msg;
1095   msg.type = Message::DETACH;
1096   sendMessage(info->getTarget(), &msg);
1097 
1098   // Dissociate the client and the target
1099   info->getTarget()->setClient(NULL);
1100   info->setTarget(NULL);
1101 }
1102 
1103 void
1104 shutdownClient(ClientInfo* clientInfo) {
1105 #ifdef DEBUGGING
1106   cerr << "Shutting down client" << endl;
1107 #endif
1108 
1109   // If we're connected, inform the target process that we're
1110   // disconnecting
1111   detachClient(clientInfo);
1112 
1113   // Remove this client from the list and delete it
1114   clientList.removeClient(clientInfo);
1115   if (clientInfo->getTarget() != NULL) {
1116     clientInfo->getTarget()->setClient(NULL);
1117   }
1118   clientInfo->closeAll();
1119   delete clientInfo;
1120 }
1121 
1122 //
1123 //----------------------------------------------------------------------
1124 
1125 
1126 /** Main dispatcher for client commands. NOTE: do not refer to this
1127     clientInfo data structure after calling this routine, as it may be
1128     deleted internally. */
1129 void
1130 readAndDispatch(ClientInfo* clientInfo) {
1131   IOBuf::ReadLineResult res;
1132   IOBuf* ioBuf = clientInfo->getIOBuf();
1133   unsigned long howMany;
1134   ioctlsocket(clientInfo->getDataSocket(), FIONREAD, &howMany);
1135   if (howMany == 0) {
1136     // Client closed down.
1137     shutdownClient(clientInfo);
1138     return;
1139   }
1140   // Read and process as much data as possible
1141   do {
1142     res = ioBuf->tryReadLine();
1143     if (res == IOBuf::RL_ERROR) {
1144 #ifdef DEBUGGING
1145       cerr << "Error while reading line" << endl;
1146 #endif
1147       shutdownClient(clientInfo);
1148       return;
1149     } else if (res == IOBuf::RL_GOT_DATA) {
1150 #ifdef DEBUGGING
1151       cerr << "Got data: \"" << ioBuf->getLine() << "\"" << endl;
1152 #endif
1153       handler->setIOBuf(ioBuf);
1154       handler->setClientInfo(clientInfo);
1155       handler->clearExited();
1156       Dispatcher::dispatch(ioBuf->getLine(), handler);
1157     }
1158   } while (res == IOBuf::RL_GOT_DATA && (!handler->exited()));
1159 #ifdef DEBUGGING
1160   cerr << "Exiting readAndDispatch" << endl;
1161 #endif
1162 }
1163 
1164 int
1165 main(int argc, char **argv)
1166 {
1167   initWinsock();
1168 
1169   if (isNT4()) {
1170     loadPSAPIDLL(); // Will exit if not present
1171   }
1172 
1173   SOCKET clientListeningSock = setupListeningSocket(CLIENT_PORT);
1174 
1175   handler = new ServerHandler();
1176   Lists::init();
1177 
1178   reaper = new Reaper(&reapCB);
1179   if (!reaper->start()) {
1180     exit(1);
1181   }
1182 
1183   while (true) {
1184     // Select on all sockets:
1185     //  - client listening socket
1186     //  - sockets for all client connections
1187 
1188     // When one of the client connections closes, close its socket
1189     // handles.
1190 
1191     fd_set set;
1192     SOCKET maxSock = 0;
1193 
1194     // Set up fd_set
1195     {
1196       int i;
1197       FD_ZERO(&set);
1198       FD_SET(clientListeningSock, &set);
1199       if (clientListeningSock > maxSock) {
1200         maxSock = clientListeningSock;
1201       }
1202       for (i = 0; i < clientList.size(); i++) {
1203         ClientInfo* info = clientList.get(i);
1204         if (info->getDataSocket() > maxSock) {
1205           maxSock = info->getDataSocket();
1206         }
1207         FD_SET(info->getDataSocket(), &set);
1208       }
1209     }
1210     struct timeval timeout;
1211     timeout.tv_sec = 300; // 5 minutes
1212     timeout.tv_usec = 0;
1213     int res = select(maxSock, &set, NULL, NULL, &timeout);
1214     if (res > 0) {
1215 
1216       ////////////////
1217       // New client //
1218       ////////////////
1219       if (FD_ISSET(clientListeningSock, &set)) {
1220         SOCKET fd = acceptFromLocalhost(clientListeningSock);
1221         if (fd != INVALID_SOCKET) {
1222           // Create new client information object
1223           ClientInfo* info = new ClientInfo(fd);
1224           // Add to list of clients
1225           clientList.addClient(info);
1226 #ifdef DEBUGGING
1227           cerr << "New client" << endl;
1228 #endif
1229         }
1230       }
1231 
1232       ///////////////////////////
1233       // Commands from clients //
1234       ///////////////////////////
1235       ClientInfo* clientInfo;
1236       if (clientList.isAnyDataSocketSet(&set, &clientInfo)) {
1237         readAndDispatch(clientInfo);
1238       }
1239     } else if (res < 0) {
1240       // Looks like one of the clients was killed. Try to figure out which one.
1241       bool found = false;
1242       fd_set set;
1243       struct timeval timeout;
1244       timeout.tv_sec = 0;
1245       timeout.tv_usec = 0;
1246       for (int i = 0; i < clientList.size(); i++) {
1247         ClientInfo* info = clientList.get(i);
1248         FD_ZERO(&set);
1249         FD_SET(info->getDataSocket(), &set);
1250         if (select(1 + info->getDataSocket(), &set, NULL, NULL, &timeout) < 0) {
1251           found = true;
1252           clientList.removeClient(info);
1253           info->closeAll();
1254           delete info;
1255           break;
1256         }
1257       }
1258       if (!found) {
1259         // This indicates trouble -- one of our listening sockets died.
1260         exit(1);
1261       }
1262     }
1263   }
1264 
1265   return 0;
1266 }