int ControlApplication::checkServicePasswords(bool isRunAsRequested) { // FIXME: code duplication. if (IsUserAnAdmin() == FALSE) { // If admin rights already requested and application still don't have them, // then show error message and exit. if (isRunAsRequested) { MessageBox(0, StringTable::getString(IDS_ADMIN_RIGHTS_NEEDED), StringTable::getString(IDS_MBC_TVNCONTROL), MB_OK | MB_ICONERROR); return 1; } // Path to tvnserver binary. StringStorage pathToBinary; // Command line for child process. StringStorage childCommandLine; // Get path to tvnserver binary. Environment::getCurrentModulePath(&pathToBinary); // Set -dontelevate flag to tvncontrol know that admin rights already requested. childCommandLine.format(_T("%s -dontelevate"), m_commandLine.getString()); // Start child. try { Shell::runAsAdmin(pathToBinary.getString(), childCommandLine.getString()); return 0; } catch (SystemException &sysEx) { if (sysEx.getErrorCode() != ERROR_CANCELLED) { MessageBox(0, sysEx.getMessage(), StringTable::getString(IDS_MBC_TVNCONTROL), MB_OK | MB_ICONERROR); } return 1; } // try / catch. return 0; } checkServicePasswords(); return 0; }
void ControlTrayIcon::onShutdownServerMenuItemClick() { // Promt user if any client is connected to rfb server. // FIXME: Bad way to determinate connected clients. bool someoneConnected = (getIcon() == m_iconWorking); if (someoneConnected) { TvnServerInfo serverInfo = {0}; { AutoLock l(&m_serverInfoMutex); serverInfo = m_lastKnownServerInfo; } StringStorage userMessage; UINT stringId = serverInfo.m_serviceFlag ? IDS_TVNSERVER_SERVICE : IDS_TVNSERVER_APP; userMessage.format( StringTable::getString(IDS_SHUTDOWN_NOTIFICATION_FORMAT), StringTable::getString(stringId)); if (MessageBox( getWindow(), userMessage.getString(), StringTable::getString(IDS_MBC_TVNCONTROL), MB_YESNO | MB_ICONQUESTION) == IDNO) { return; } } // Shutdown TightVNC server. ShutdownCommand unsafeCommand(m_serverControl); ControlCommand safeCommand(&unsafeCommand, m_notificator); safeCommand.execute(); }
void UploadOperation::processFolder() { StringStorage message; // Try list files from folder FolderListener listener(m_pathToSourceFile.getString()); if (listener.list()) { m_toCopy->setChild(listener.getFilesInfo(), listener.getFilesCount()); } else { // Logging StringStorage message; message.format(_T("Error: failed to get file list in local folder '%s'"), m_pathToSourceFile.getString()); notifyError(message.getString()); } // Send request to create folder m_sender->sendMkDirRequest(m_pathToTargetFile.getString()); }
void DownloadOperation::processFolder() { File local(m_pathToTargetFile.getString()); if (local.exists() && local.isDirectory()) { } else { if (!local.mkdir()) { StringStorage message; message.format(_T("Error: failed to create local '%s' folder"), m_pathToTargetFile.getString()); notifyError(message.getString()); gotoNext(); return ; } } m_sender->sendFileListRequest(m_pathToSourceFile.getString(), m_replyBuffer->isCompressionSupported()); }
void PortMappingDialog::onAddButtonClick() { EditPortMappingDialog addDialog(EditPortMappingDialog::Add); PortMapping newPM; addDialog.setMapping(&newPM); addDialog.setParent(&m_ctrlThis); if (addDialog.showModal() == IDOK) { { StringStorage mappingString; newPM.toString(&mappingString); m_exPortsListBox.addString(mappingString.getString()); } m_extraPorts->pushBack(newPM); ((ConfigDialog *)m_parent)->updateApplyButtonState(); } }
WinDxgiAdapter::WinDxgiAdapter(WinDxgiDevice *winDxgiDevice, int iAdapter) : m_dxgiAdapter(0) { winDxgiDevice->getAdapter(&m_dxgiAdapter); IDXGIFactory *m_dxgiFactory; HRESULT hr = m_dxgiAdapter->GetParent( __uuidof( IDXGIFactory ), (void**) (&m_dxgiFactory) ); if (FAILED(hr)) { throw WinDxCriticalException(_T("Can't get IDXGIAdapter parent factory (%ld)"), (long)hr); } hr = m_dxgiFactory->EnumAdapters(iAdapter, &m_dxgiAdapter); m_dxgiFactory->Release(); if (hr == DXGI_ERROR_NOT_FOUND) { StringStorage errMess; errMess.format(_T("IDXGIAdapter not found for iAdapter = %u"), iAdapter); throw WinDxRecoverableException(errMess.getString(), hr); } if (FAILED(hr)) { throw WinDxCriticalException(_T("Can't IDXGIFactory::EnumAdapters()"), hr); } }
void DownloadOperation::onLastRequestFailedReply(DataInputStream *input) { // // This LRF message received from get folder size request // we do need to download next file // if (m_foldersToCalcSizeLeft > 0) { decFoldersToCalcSizeCount(); } else { // Logging StringStorage message; m_replyBuffer->getLastErrorMessage(&message); notifyFailedToDownload(message.getString()); // Download next file gotoNext(); } }
void IpAccessControl::deserialize(DataInputStream *input) { clear(); size_t count = input->readUInt32(); StringStorage string; for (size_t i = 0; i < count; i++) { input->readUTF8(&string); IpAccessRule *rule = new IpAccessRule(); if (!IpAccessRule::parse(string.getString(), rule)) { delete rule; continue; } push_back(rule); } }
DesktopServerWatcher::DesktopServerWatcher(ReconnectionListener *recListener, LogWriter *log) : m_recListener(recListener), m_process(0), m_log(log) { // Desktop server folder. StringStorage currentModulePath; Environment::getCurrentModulePath(¤tModulePath); // Path to desktop server application. StringStorage path; // FIXME: To think: is quotes needed? path.format(_T("\"%s\""), currentModulePath.getString()); try { m_process = new CurrentConsoleProcess(m_log, path.getString()); } catch (...) { if (m_process) delete m_process; throw; } }
void CommentHistory::truncate() { StringStorage valueName; StringStorage value; size_t i = (size_t)m_limit; while (true) { valueName.format(_T("%u"), i); if (i >= getCommCount()) { return ; } removeCom(getCom(i)); if (!m_key->getValueAsString(valueName.getString(), &value)) { break; } m_key->deleteSubKey(value.getString()); m_key->deleteValue(valueName.getString()); i++; } load(); }
Logger *ViewerConfig::initLog(const TCHAR logDir[], const TCHAR logName[]) { m_logName = logName; StringStorage logFileFolderPath; StringStorage appDataPath; // After that logFilePath variable will contain path to folder // where tvnviewer.log must be located if (Environment::getSpecialFolderPath(Environment::APPLICATION_DATA_SPECIAL_FOLDER, &appDataPath)) { logFileFolderPath.format(_T("%s\\%s"), appDataPath.getString(), logDir); } else { logFileFolderPath.format(_T("%s"), logDir); } // Create TightVNC folder { File folder(logFileFolderPath.getString()); folder.mkdir(); } // Path to log file AutoLock l(&m_cs); m_pathToLogFile = logFileFolderPath; if (m_logger != 0) { delete m_logger; } m_logger = new FileLogger(m_pathToLogFile.getString(), logName, m_logLevel, false); return m_logger; }
void ReconnectingChannel::waitForReconnect(const TCHAR *funName, Channel *channel) { DateTime startTime = DateTime::now(); bool success = false; while (!success) { unsigned int timeForWait = max((int)m_timeOut - (int)(DateTime::now() - startTime).getTime(), 0); if (timeForWait == 0 || m_isClosed) { StringStorage errMess; errMess.format(_T("The ReconnectingChannel::%s() function") _T(" failed."), funName); throw IOException(errMess.getString()); } m_timer.waitForEvent(timeForWait); AutoLock al(&m_chanMut); if (m_channel != channel) { m_chanWasChanged = false; success = true; } } Log::info(_T("ReconnectingChannel was successfully reconnected.")); if (channel != 0) { StringStorage errMess; errMess.format(_T("Transport was reconnected in the") _T(" %s() function. The %s()") _T(" function() at this time will be aborted"), funName, funName); throw ReconnectException(errMess.getString()); } }
void WsConfigRunner::execute() { Process *process = 0; try { // Prepare path to executable. StringStorage pathToBin; Environment::getCurrentModulePath(&pathToBin); pathToBin.quoteSelf(); // Prepare arguments. StringStorage args; args.format(_T("%s %s"), m_serviceMode ? ControlCommandLine::CONTROL_SERVICE : ControlCommandLine::CONTROL_APPLICATION, ControlCommandLine::SLAVE_MODE); // Start process. process = new Process(pathToBin.getString(), args.getString()); process->start(); } catch (Exception &e) { m_log.error(_T("Cannot start the WsControl process (%s)"), e.getMessage()); } if (process != 0) { delete process; } }
void Screen::getBMI(BMI *bmi, HDC dc) { HDC bitmapDC = dc; if (bitmapDC == 0) { bitmapDC = GetDC(0); if (bitmapDC == NULL) { throw Exception(_T("Can't get a bitmap dc")); } } memset(bmi, 0, sizeof(BMI)); bmi->bmiHeader.biBitCount = 0; bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); HBITMAP hbm; hbm = (HBITMAP)GetCurrentObject(bitmapDC, OBJ_BITMAP); if (GetDIBits(bitmapDC, hbm, 0, 0, NULL, (LPBITMAPINFO)bmi, DIB_RGB_COLORS) == 0) { StringStorage errMess; Environment::getErrStr(_T("Can't get a DIBits"), &errMess); DeleteObject(hbm); DeleteDC(bitmapDC); throw Exception(errMess.getString()); } // The color table is filled only if it is used BI_BITFIELDS if (bmi->bmiHeader.biCompression == BI_BITFIELDS) { if (GetDIBits(bitmapDC, hbm, 0, 0, NULL, (LPBITMAPINFO)bmi, DIB_RGB_COLORS) == 0) { StringStorage errMess; Environment::getErrStr(_T("Can't get a DIBits"), &errMess); DeleteObject(hbm); DeleteDC(bitmapDC); throw Exception(errMess.getString()); } } DeleteObject(hbm); if (dc == 0) { DeleteDC(bitmapDC); } }
void ControlClient::addClientMsgRcvd() { m_gate->writeUInt32(ControlProto::REPLY_OK); // // Read parameters. // StringStorage connectString; m_gate->readUTF8(&connectString); bool viewOnly = m_gate->readUInt8() == 1; // // Parse host and port from connection string. // AnsiStringStorage connectStringAnsi(&connectString); HostPath hp(connectStringAnsi.getString(), 5500); if (!hp.isValid()) { return; } StringStorage host; AnsiStringStorage ansiHost(hp.getVncHost()); ansiHost.toStringStorage(&host); // // Make outgoing connection in separate thread. // OutgoingRfbConnectionThread *newConnectionThread = new OutgoingRfbConnectionThread(host.getString(), hp.getVncPort(), viewOnly, m_rfbClientManager, m_log); newConnectionThread->resume(); ZombieKiller::getInstance()->addZombie(newConnectionThread); }
Channel *ReconnectingChannel::getChannel(const TCHAR *funName) { if (m_isClosed) { StringStorage errMess; errMess.format(_T("The %s() function has failed:") _T(" connection has already been closed."), funName); throw IOException(errMess.getString()); } Channel *channel; { AutoLock al(&m_chanMut); if (m_oldChannel != 0) { delete m_oldChannel; m_oldChannel = 0; } if (m_chanWasChanged) { m_chanWasChanged = false; StringStorage errMess; errMess.format(_T("Transport was reconnected outside from") _T(" the %s() function. The %s()") _T(" function at this time will be aborted."), funName, funName); throw ReconnectException(errMess.getString()); } channel = m_channel; } return channel; }
void DesktopServerProto::readConfigSettings(BlockingGate *gate) { ServerConfig *srvConf = Configurator::getInstance()->getServerConfig(); // Log srvConf->setLogLevel(gate->readUInt32()); // Polling srvConf->setPollingInterval(gate->readUInt32()); srvConf->setGrabTransparentWindowsFlag(gate->readUInt8() != 0); srvConf->blockLocalInput(gate->readUInt8() != 0); srvConf->setLocalInputPriority(gate->readUInt8() != 0); srvConf->setLocalInputPriorityTimeout(gate->readUInt32()); srvConf->enableRemovingDesktopWallpaper(gate->readUInt8() != 0); // Receive video class names AutoLock al(srvConf); size_t stringCount = gate->readUInt32(); StringStorage tmpString; for (size_t i = 0; i < stringCount; i++) { gate->readUTF8(&tmpString); srvConf->getVideoClassNames()->push_back(tmpString); } // Receive video rects stringCount = gate->readUInt32(); tmpString.setString(_T("")); for (size_t i = 0; i < stringCount; i++) { gate->readUTF8(&tmpString); srvConf->getVideoRects()->push_back(RectSerializer::toRect(&tmpString)); } // Receive video recognition interval srvConf->setVideoRecognitionInterval(gate->readUInt32()); // Receive socket timeout srvConf->setIdleTimeout(gate->readUInt32()); }
void EditPortMappingDialog::onOkButtonClick() { if (!isUserDataValid()) return ; PortMappingRect rect; int port; StringStorage portStringStorage; StringStorage rectStringStorage; m_geometryTextBox.getText(&rectStringStorage); m_portTextBox.getText(&portStringStorage); PortMappingRect::parse(rectStringStorage.getString(), &rect); StringParser::parseInt(portStringStorage.getString(), &port); m_mapping->setPort(port); m_mapping->setRect(rect); kill(IDOK); }
void TvnServer::getServerInfo(TvnServerInfo *info) { bool rfbServerListening = true; { AutoLock l(&m_mutex); rfbServerListening = m_rfbServer != 0; } StringStorage statusString; bool vncAuthEnabled = m_config->isUsingAuthentication(); bool noVncPasswords = !m_config->hasPrimaryPassword() && !m_config->hasReadOnlyPassword(); bool vncPasswordsError = vncAuthEnabled && noVncPasswords; if (rfbServerListening) { if (vncPasswordsError) { statusString = StringTable::getString(IDS_NO_PASSWORDS_SET); } else { char localAddressString[1024]; getLocalIPAddrString(localAddressString, 1024); statusString.fromAnsiString(localAddressString); if (!vncAuthEnabled) { statusString.appendString(StringTable::getString(IDS_NO_AUTH_STATUS)); } } } else { statusString = StringTable::getString(IDS_SERVER_NOT_LISTENING); } UINT stringId = m_runAsService ? IDS_TVNSERVER_SERVICE : IDS_TVNSERVER_APP; info->m_statusText.format(_T("%s - %s"), StringTable::getString(stringId), statusString.getString()); info->m_acceptFlag = rfbServerListening && !vncPasswordsError; info->m_serviceFlag = m_runAsService; }
bool EditIpAccessRuleDialog::validateInput() { StringStorage firstIp; StringStorage lastIp; m_firstIp.getText(&firstIp); m_lastIp.getText(&lastIp); if (!IpAccessRule::isIpAddressStringValid(firstIp.getString())) { m_firstIp.setFocus(); m_firstIp.showBalloonTip(&m_warningBalloonTip); return false; } // if if (lastIp.isEmpty()) { return true; } if (!IpAccessRule::isIpAddressStringValid(lastIp.getString())) { m_lastIp.setFocus(); m_lastIp.showBalloonTip(&m_warningBalloonTip); return false; } // if AnsiStringStorage firstIpAnsi(&firstIp); AnsiStringStorage lastIpAnsi(&lastIp); unsigned long firstIpAddr = inet_addr(firstIpAnsi.getString()); unsigned long lastIpAddr = inet_addr(lastIpAnsi.getString()); if (IpAccessRule::compareIp(firstIpAddr, lastIpAddr) == 1) { m_lastIp.setFocus(); m_lastIp.showBalloonTip(&m_lastIpLessThanFirstBT); return false; } return true; }
void ControlMessage::checkRetCode() { UINT32 messageId = m_gate->readUInt32(); switch (messageId) { case ControlProto::REPLY_ERROR: { StringStorage message; m_gate->readUTF8(&message); throw RemoteException(message.getString()); } break; case ControlProto::REPLY_AUTH_NEEDED: if (m_passwordFile.getLength() != 0) { authFromFile(); } else if (m_getPassFromConfigEnabled) { authFromRegistry(); } else { ControlAuthDialog authDialog; int retCode = authDialog.showModal(); switch (retCode) { case IDCANCEL: throw ControlAuthException(StringTable::getString(IDS_USER_CANCEL_CONTROL_AUTH), true); case IDOK: ControlAuth auth(m_gate, authDialog.getPassword()); send(); break; } } break; case ControlProto::REPLY_OK: break; default: _ASSERT(FALSE); throw RemoteException(_T("Unknown ret code.")); } }
void WinFilePath::setString(const TCHAR *string) { StringStorage str(string); if (!str.isEmpty()) { if (str.findLast('/') == 0) { m_parentPathIsRoot = true; } str.replaceChar(_T('/'), _T('\\')); if (str.beginsWith(_T('\\'))) { str.remove(0, 1); } if (str.endsWith(_T('\\'))) { str.truncate(1); } } // desktop replacement //TCHAR path[MAX_PATH + 1]; StringStorage specFolder; str.getSubstring(&specFolder,0,8); if(specFolder.isEqualTo(_T("[Desktop]"))){ StringStorage tmp; str.getSubstring(&tmp,9,str.getLength()); Environment::getSpecialFolderPath(Environment::USERDESKTOP_DATA_SPECIAL_FOLDER, &specFolder); str.setString(specFolder.getString()); str.appendString(tmp.getString()); } str.getSubstring(&specFolder,0,5); if(specFolder.isEqualTo(_T("[Docs]"))){ StringStorage tmp; str.getSubstring(&tmp,6,str.getLength()); Environment::getSpecialFolderPath(Environment::USERDOCS_DATA_SPECIAL_FOLDER, &specFolder); str.setString(specFolder.getString()); str.appendString(tmp.getString()); } StringStorage::setString(str.getString()); }
void PortMappingDialog::onEditButtonClick() { int selectedIndex = m_exPortsListBox.getSelectedIndex(); if (selectedIndex == -1) { return ; } PortMapping *pPM = m_extraPorts->at(selectedIndex); EditPortMappingDialog editDialog(EditPortMappingDialog::Edit); editDialog.setParent(&m_ctrlThis); editDialog.setMapping(pPM); if (editDialog.showModal() == IDOK) { StringStorage mappingString; pPM->toString(&mappingString); m_exPortsListBox.setItemText(selectedIndex, mappingString.getString()); ((ConfigDialog *)m_parent)->updateApplyButtonState(); } }
void ControlMessage::authFromRegistry() { HKEY rootKey = m_forService ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; RegistrySettingsManager sm(rootKey, _T("Software\\TightVNC\\Server\\"), 0); unsigned char hidePassword[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char plainPassword[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; size_t passSize = sizeof(hidePassword); if (sm.getBinaryData(_T("ControlPassword"), hidePassword, &passSize)) { VncPassCrypt::getPlainPass(plainPassword, hidePassword); StringStorage password; password.fromAnsiString((char *)plainPassword); memset(plainPassword, 0, sizeof(plainPassword)); ControlAuth auth(m_gate, password.getString()); send(); } else { } }
int QueryConnectionApplication::run() { QueryConnectionCommandLine parser; try { parser.parse(m_cmdLine.getString()); } catch (Exception &) { TvnServerHelp::showUsage(); return 0; } StringStorage peerAddress; parser.getPeerAddress(&peerAddress); DWORD queryTimeout = parser.isTimeoutSpecified() ? parser.getTimeout() : 30; QueryConnectionDialog dialog(peerAddress.getString(), parser.isDefaultActionAccept(), queryTimeout); return dialog.showModal(); }
void WindowsUserInput::setKeyboardEvent(UINT32 keySym, bool down) { try { m_log->info(_T("Received the %#4.4x keysym, down = %d"), keySym, (int)down); // Generate single key event. BYTE vkCode; WCHAR ch; bool release = !down; bool extended; if (m_keyMap.keySymToVirtualCode(keySym, &vkCode, &extended)) { m_inputInjector.injectKeyEvent(vkCode, release, extended); } else if (m_keyMap.keySymToUnicodeChar(keySym, &ch)) { m_inputInjector.injectCharEvent(ch, release); } else { StringStorage message; message.format(_T("Unknown %d keysym"), keySym); throw Exception(message.getString()); } } catch (Exception &someEx) { m_log->error(_T("Exception while processing key event: %s"), someEx.getMessage()); } }
void RfbClientManager::onCheckAccessControl(RfbClient *client) { SocketAddressIPv4 peerAddr; try { client->getSocketAddr(&peerAddr); } catch (...) { throw AuthException(_T("Failed to get IP address of the RFB client")); } struct sockaddr_in addr_in = peerAddr.getSockAddr(); ServerConfig *config = Configurator::getInstance()->getServerConfig(); IpAccessRule::ActionType action; if (!client->isOutgoing()) { action = config->getActionByAddress((unsigned long)addr_in.sin_addr.S_un.S_addr); } else { action = IpAccessRule::ACTION_TYPE_ALLOW; } // Promt user to know what to do with incmoing connection. if (action == IpAccessRule::ACTION_TYPE_QUERY) { StringStorage peerHost; peerAddr.toString(&peerHost); int queryRetVal = QueryConnectionApplication::execute(peerHost.getString(), config->isDefaultActionAccept(), config->getQueryTimeout()); if (queryRetVal == 1) { throw AuthException(_T("Connection has been rejected")); } } }
void DesktopServerWatcher::doXPTrick() { m_log->info(_T("Trying to do WindowsXP trick to start process on separate session")); try { WinStaLibrary winSta; WCHAR password[1]; memset(password, 0, sizeof(password)); if (winSta.WinStationConnectW(NULL, 0, WTS::getActiveConsoleSessionId(m_log), password, 0) == FALSE) { throw SystemException(_T("Failed to call WinStationConnectW")); } // Get path to tvnserver binary. StringStorage pathToBinary; Environment::getCurrentModulePath(&pathToBinary); // Start current console process that will lock workstation (not using Xp Trick). CurrentConsoleProcess lockWorkstation(m_log, pathToBinary.getString(), _T("-lockworkstation")); lockWorkstation.start(); lockWorkstation.waitForExit(); // Check exit code (exit code is GetLastError() value in case of system error, // LockWorkstation() in child process failed, or 0 if workstation is locked). DWORD exitCode = lockWorkstation.getExitCode(); if (exitCode != 0) { throw SystemException(exitCode); } } catch (SystemException &ex) { m_log->error(ex.getMessage()); throw; } }
TvnServer::TvnServer(bool runsInServiceContext, StringStorage vncIniDirPath /*""*/, bool runAsPortable /*=false*/ ) : Singleton<TvnServer>(), ListenerContainer<TvnServerListener *>(), m_runAsService(runsInServiceContext), m_runPortable(runAsPortable), m_rfbClientManager(0), m_httpServer(0), m_controlServer(0), m_rfbServer(0) { Configurator *configurator = Configurator::getInstance(); configurator->setServiceFlag(m_runAsService); configurator->setPortableRunFlag(m_runPortable); configurator->setVncIniDirectoryPath ( vncIniDirPath.getString() ); configurator->load(); m_config = Configurator::getInstance()->getServerConfig(); resetLogFilePath(); m_log.changeLevel(m_config->getLogLevel()); Log::message(_T("TightVNC Server Build on %s"), BuildTime::DATE); Log::info(_T("Initialize WinSock")); try { WindowsSocket::startup(2, 1); } catch (Exception &ex) { Log::interror(_T("%s"), ex.getMessage()); } ZombieKiller *zombieKiller = new ZombieKiller(); m_rfbClientManager = new RfbClientManager(NULL); m_rfbClientManager->addListener(this); Configurator::getInstance()->addListener(this); { AutoLock l(&m_mutex); restartMainRfbServer(); (void)m_extraRfbServers.reload(m_runAsService, m_rfbClientManager); restartHttpServer(); restartControlServer(); } }
void AnonymousPipe::assignHandlesFor(HANDLE hTargetProc, bool neededToClose) { HANDLE hSrcProc = GetCurrentProcess(); HANDLE hWrite = 0, hRead = 0; if (DuplicateHandle(hSrcProc, m_hWrite, hTargetProc, &hWrite, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS) == 0) { StringStorage errText; Environment::getErrStr(_T("Cannot dupplicate write") _T(" handle for the anonymous pipe"), &errText); throw Exception(errText.getString()); } m_hWrite = hWrite; if (DuplicateHandle(hSrcProc, m_hRead, hTargetProc, &hRead, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS) == 0) { StringStorage errText; Environment::getErrStr(_T("Cannot dupplicate read") _T(" handle for the anonymous pipe"), &errText); throw Exception(errText.getString()); } m_hRead = hRead; m_neededToClose = neededToClose; }