bool CRemoteCacheLink::EnsurePipeOpen() { AutoLocker lock(m_critSec); if (InternalEnsurePipeOpen (m_hPipe, GetCachePipeName())) { // create an unnamed (=local) manual reset event for use in the overlapped structure if (m_hEvent) return true; m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hEvent) return true; CTraceToOutputDebugString::Instance()(__FUNCTION__ ": CreateEvent failed"); ClosePipe(); } return false; }
bool CCacheDlg::EnsurePipeOpen() { if(m_hPipe != INVALID_HANDLE_VALUE) { return true; } m_hPipe = CreateFile( GetCachePipeName(), // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing nullptr, // default security attributes OPEN_EXISTING, // opens existing pipe FILE_FLAG_OVERLAPPED, // default attributes nullptr); // no template file if (m_hPipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) { // TSVNCache is running but is busy connecting a different client. // Do not give up immediately but wait for a few milliseconds until // the server has created the next pipe instance if (WaitNamedPipe(GetCachePipeName(), 50)) { m_hPipe = CreateFile( GetCachePipeName(), // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing nullptr, // default security attributes OPEN_EXISTING, // opens existing pipe FILE_FLAG_OVERLAPPED, // default attributes nullptr); // no template file } } if (m_hPipe != INVALID_HANDLE_VALUE) { // The pipe connected; change to message-read mode. DWORD dwMode; dwMode = PIPE_READMODE_MESSAGE; if(!SetNamedPipeHandleState( m_hPipe, // pipe handle &dwMode, // new pipe mode nullptr, // don't set maximum bytes nullptr)) // don't set maximum time { ATLTRACE("SetNamedPipeHandleState failed"); CloseHandle(m_hPipe); m_hPipe = INVALID_HANDLE_VALUE; return false; } // create an unnamed (=local) manual reset event for use in the overlapped structure m_hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); if (m_hEvent) return true; ATLTRACE("CreateEvent failed"); ClosePipe(); return false; } return false; }
DWORD WINAPI PipeThread(LPVOID lpvParam) { ATLTRACE("PipeThread started\n"); bool * bRun = (bool *)lpvParam; // The main loop creates an instance of the named pipe and // then waits for a client to connect to it. When the client // connects, a thread is created to handle communications // with that client, and the loop is repeated. DWORD dwThreadId; BOOL fConnected; CAutoFile hPipe; while (*bRun) { hPipe = CreateNamedPipe( GetCachePipeName(), PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size BUFSIZE, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out NULL); // NULL DACL if (!hPipe) { //OutputDebugStringA("TSVNCache: CreatePipe failed\n"); //DebugOutputLastError(); if (*bRun) Sleep(200); continue; // never leave the thread! } // Wait for the client to connect; if it succeeds, // the function returns a nonzero value. If the function returns // zero, GetLastError returns ERROR_PIPE_CONNECTED. fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if (fConnected) { // Create a thread for this client. CAutoGeneralHandle hInstanceThread = CreateThread( NULL, // no security attribute 0, // default stack size InstanceThread, (HANDLE) hPipe, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if (!hInstanceThread) { //OutputDebugStringA("TSVNCache: Could not create Instance thread\n"); //DebugOutputLastError(); DisconnectNamedPipe(hPipe); // since we're now closing this thread, we also have to close the whole application! // otherwise the thread is dead, but the app is still running, refusing new instances // but no pipe will be available anymore. PostMessage(hWnd, WM_CLOSE, 0, 0); return 1; } // detach the handle, since we passed it to the thread hPipe.Detach(); } else { // The client could not connect, so close the pipe. //OutputDebugStringA("TSVNCache: ConnectNamedPipe failed\n"); //DebugOutputLastError(); hPipe.CloseHandle(); if (*bRun) Sleep(200); continue; // don't end the thread! } } ATLTRACE("Pipe thread exited\n"); return 0; }