void SecurityPipeServer::generateSecConnection(Channel *tempPublChan)
{
  NamedPipe *otherSideChannel = 0;

  try {
    DataInputStream svcInput(tempPublChan);
    DataOutputStream svcOutput(tempPublChan);

    UINT32 procId = svcInput.readUInt32();
    // Check the id. If it is "right" process then generate
    // transport handles specially for it.
    if (!Environment::isItTheSamePathAsCurrent(procId)) {
      throw Exception(_T("The process that has requested connection")
                      _T(" to the log server has not access right"));
    }
    // Give to process exclusive pipe handles

    StringStorage randomName;
    srand((unsigned)time(0));
    for (int i = 0; i < 20; i++) {
      randomName.appendChar('a' + rand() % ('z' - 'a'));
    }
    PipeServer pipeServer(randomName.getString(), 0, 1000);
    otherSideChannel = PipeClient::connect(randomName.getString());
    m_secChannel = pipeServer.accept();

    HANDLE otherSideHandle = otherSideChannel->getHandle();
    svcOutput.writeUInt64((UINT64)assignHandleFor(procId, otherSideHandle));
  } catch (...) {
    if (otherSideChannel != 0) delete otherSideChannel;
    throw;
  }
  if (otherSideChannel != 0) delete otherSideChannel;
}
DesktopServerApplication::DesktopServerApplication(HINSTANCE appInstance, const TCHAR *commandLine)
: LocalWindowsApplication(appInstance),
  m_clToSrvChan(0),
  m_srvToClChan(0),
  m_clToSrvGate(0),
  m_srvToClGate(0),
  m_dispatcher(0),
  m_updHandlerSrv(0),
  m_uiSrv(0),
  m_cfgServer(0),
  m_gateKickHandler(0),
  m_sessionChangesWatcher(0)
{
  DesktopServerCommandLine cmdLineParser;

  cmdLineParser.parse(commandLine);

  DWORD baseSessionId = WTS::getActiveConsoleSessionId();

  StringStorage pathToLog;

  cmdLineParser.getLogDir(&pathToLog);

  if (!pathToLog.endsWith(_T('\\'))) {
    pathToLog.appendChar(_T('\\'));
  }
  pathToLog.appendString(_T("dtserver.log"));
  m_log = new FileLog(pathToLog.getString(), true);
  Configurator::getInstance()->addListener(this);

  m_log->changeLevel(cmdLineParser.getLogLevel());
  Log::message(_T("Log level has been changed to %d"),
               cmdLineParser.getLogLevel());

  try {
    StringStorage shMemName;
    cmdLineParser.getSharedMemName(&shMemName);
    SharedMemory shMem(shMemName.getString(), 72);
    UINT64 *mem = (UINT64 *)shMem.getMemPointer();
    HANDLE hWrite, hRead;

    DateTime startTime = DateTime::now();

    while (mem[0] == 0) {
      unsigned int timeForWait = max((int)10000 - 
                                     (int)(DateTime::now() -
                                           startTime).getTime(),
                                     0);
      if (timeForWait == 0) {
        throw Exception(_T("The desktop server time out expired"));
      }
    }

    hWrite = (HANDLE)mem[1];
    hRead  = (HANDLE)mem[2];
    m_clToSrvChan = new AnonymousPipe(hWrite, hRead);
    Log::info(_T("Client->server hWrite = %u; hRead = %u"), hWrite, hRead);

    hWrite = (HANDLE)mem[3];
    hRead  = (HANDLE)mem[4];
    m_srvToClChan = new AnonymousPipe(hWrite, hRead);
    Log::info(_T("Server->client hWrite = %u; hRead = %u"), hWrite, hRead);

    m_clToSrvGate = new BlockingGate(m_clToSrvChan);
    m_srvToClGate = new BlockingGate(m_srvToClChan);

    m_dispatcher = new DesktopSrvDispatcher(m_clToSrvGate, this);

    m_updHandlerSrv = new UpdateHandlerServer(m_srvToClGate, m_dispatcher, this);
    m_uiSrv = new UserInputServer(m_srvToClGate, m_dispatcher, this);
    m_cfgServer = new ConfigServer(m_dispatcher);
    m_gateKickHandler = new GateKickHandler(m_dispatcher);

    m_dispatcher->resume();

    m_sessionChangesWatcher = new SessionChangesWatcher(this);
  } catch (Exception &e) {
    Log::error(e.getMessage());
    freeResources();
    throw;
  }
}