Exemple #1
0
bool CRemoteCacheLink::EnsureCommandPipeOpen()
{
	AutoLocker lock(m_critSec);
	if(m_hCommandPipe != INVALID_HANDLE_VALUE)
	{
		return true;
	}

	m_hCommandPipe = CreateFile(
		GetCacheCommandPipeName(),		// pipe name
		GENERIC_READ |					// read and write access
		GENERIC_WRITE,
		0,								// no sharing
		NULL,							// default security attributes
		OPEN_EXISTING,					// opens existing pipe
		FILE_FLAG_OVERLAPPED,			// default attributes
		NULL);							// no template file

	if (m_hCommandPipe == 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(GetCacheCommandPipeName(), 50))
		{
			m_hCommandPipe = CreateFile(
				GetCacheCommandPipeName(),		// pipe name
				GENERIC_READ |					// read and write access
				GENERIC_WRITE,
				0,								// no sharing
				NULL,							// default security attributes
				OPEN_EXISTING,					// opens existing pipe
				FILE_FLAG_OVERLAPPED,			// default attributes
				NULL);							// no template file
		}
	}


	if (m_hCommandPipe != INVALID_HANDLE_VALUE)
	{
		// The pipe connected; change to message-read mode.
		DWORD dwMode;

		dwMode = PIPE_READMODE_MESSAGE;
		if(!SetNamedPipeHandleState(
			m_hCommandPipe,    // pipe handle
			&dwMode,  // new pipe mode
			NULL,     // don't set maximum bytes
			NULL))    // don't set maximum time
		{
			ATLTRACE("SetNamedPipeHandleState failed");
			CloseHandle(m_hCommandPipe);
			m_hCommandPipe = INVALID_HANDLE_VALUE;
			return false;
		}
		return true;
	}

	return false;
}
void CSettings::HandleRestart()
{
	int restart = ISettingsPropPage::Restart_None;
	restart |= m_pMainPage->GetRestart();
	restart |= m_pOverlayPage->GetRestart();
	restart |= m_pOverlaysPage->GetRestart();
	restart |= m_pOverlayHandlersPage->GetRestart();
	restart |= m_pProxyPage->GetRestart();
	restart |= m_pProgsDiffPage->GetRestart();
	restart |= m_pProgsMergePage->GetRestart();
	restart |= m_pProgsAlternativeEditor->GetRestart();
	restart |= m_pLookAndFeelPage->GetRestart();
	restart |= m_pDialogsPage->GetRestart();
	restart |= m_pColorsPage->GetRestart();
	restart |= m_pColorsPage2->GetRestart();
	restart |= m_pColorsPage3->GetRestart();
	restart |= m_pSavedPage->GetRestart();
	restart |= m_pHooksPage->GetRestart();
	restart |= m_pBugTraqPage->GetRestart();
	restart |= m_pTBlamePage->GetRestart();

	restart |= m_pGitConfig->GetRestart();
	restart |= m_pGitRemote->GetRestart();
	restart |= m_pBugTraqPage->GetRestart();
	restart |= m_pExtMenu->GetRestart();
	restart |= m_pAdvanced->GetRestart();

	if (restart & ISettingsPropPage::Restart_System)
	{
		DWORD_PTR res = 0;
		::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_ABORTIFHUNG, 20, &res);
		CMessageBox::Show(NULL, IDS_SETTINGS_RESTARTSYSTEM, IDS_APPNAME, MB_ICONINFORMATION);
	}
	if (restart & ISettingsPropPage::Restart_Cache)
	{
		DWORD_PTR res = 0;
		::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_ABORTIFHUNG, 20, &res);
		// tell the cache to refresh everything
		HANDLE hPipe = CreateFile(
			GetCacheCommandPipeName(),		// pipe name
			GENERIC_READ |					// read and write access
			GENERIC_WRITE,
			0,								// no sharing
			NULL,							// default security attributes
			OPEN_EXISTING,					// opens existing pipe
			FILE_FLAG_OVERLAPPED,			// default attributes
			NULL);							// no template file


		if (hPipe != INVALID_HANDLE_VALUE)
		{
			// The pipe connected; change to message-read mode.
			DWORD dwMode;

			dwMode = PIPE_READMODE_MESSAGE;
			if (SetNamedPipeHandleState(
				hPipe,    // pipe handle
				&dwMode,  // new pipe mode
				NULL,     // don't set maximum bytes
				NULL))    // don't set maximum time
			{
				DWORD cbWritten;
				TGITCacheCommand cmd;
				SecureZeroMemory(&cmd, sizeof(TGITCacheCommand));
				cmd.command = TGITCACHECOMMAND_REFRESHALL;
				BOOL fSuccess = WriteFile(
					hPipe,			// handle to pipe
					&cmd,			// buffer to write from
					sizeof(cmd),	// number of bytes to write
					&cbWritten,		// number of bytes written
					NULL);			// not overlapped I/O

				if (! fSuccess || sizeof(cmd) != cbWritten)
				{
					DisconnectNamedPipe(hPipe);
					CloseHandle(hPipe);
					hPipe = INVALID_HANDLE_VALUE;
				}
				if (hPipe != INVALID_HANDLE_VALUE)
				{
					// now tell the cache we don't need it's command thread anymore
					DWORD cbWritten;
					TGITCacheCommand cmd;
					SecureZeroMemory(&cmd, sizeof(TGITCacheCommand));
					cmd.command = TGITCACHECOMMAND_END;
					WriteFile(
						hPipe,			// handle to pipe
						&cmd,			// buffer to write from
						sizeof(cmd),	// number of bytes to write
						&cbWritten,		// number of bytes written
						NULL);			// not overlapped I/O
					DisconnectNamedPipe(hPipe);
					CloseHandle(hPipe);
					hPipe = INVALID_HANDLE_VALUE;
				}
			}
			else
			{
				ATLTRACE("SetNamedPipeHandleState failed");
				CloseHandle(hPipe);
			}
		}
	}
}
Exemple #3
0
void CCacheDlg::RemoveFromCache(const CString& path)
{
	// if we use the external cache, we tell the cache directly that something
	// has changed, without the detour via the shell.
	HANDLE hPipe = CreateFile( 
		GetCacheCommandPipeName(),	// 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 (hPipe != INVALID_HANDLE_VALUE) 
	{
		// The pipe connected; change to message-read mode. 
		DWORD dwMode; 

		dwMode = PIPE_READMODE_MESSAGE; 
		if(SetNamedPipeHandleState( 
			hPipe,    // pipe handle 
			&dwMode,  // new pipe mode 
			NULL,     // don't set maximum bytes 
			NULL))    // don't set maximum time 
		{
			DWORD cbWritten; 
			TGITCacheCommand cmd;
			cmd.command = TGITCACHECOMMAND_CRAWL;
			wcsncpy_s(cmd.path, path, MAX_PATH);
			BOOL fSuccess = WriteFile( 
				hPipe,			// handle to pipe 
				&cmd,			// buffer to write from 
				sizeof(cmd),	// number of bytes to write 
				&cbWritten,		// number of bytes written 
				NULL);			// not overlapped I/O 

			if (! fSuccess || sizeof(cmd) != cbWritten)
			{
				DisconnectNamedPipe(hPipe); 
				CloseHandle(hPipe); 
				hPipe = INVALID_HANDLE_VALUE;
			}
			if (hPipe != INVALID_HANDLE_VALUE)
			{
				// now tell the cache we don't need it's command thread anymore
				DWORD cbWritten2; 
				TGITCacheCommand cmd2;
				cmd2.command = TGITCACHECOMMAND_END;
				WriteFile( 
					hPipe,			// handle to pipe 
					&cmd2,			// buffer to write from 
					sizeof(cmd2),	// number of bytes to write 
					&cbWritten2,		// number of bytes written 
					NULL);			// not overlapped I/O 
				DisconnectNamedPipe(hPipe); 
				CloseHandle(hPipe); 
				hPipe = INVALID_HANDLE_VALUE;
			}
		}
		else
		{
			ATLTRACE("SetNamedPipeHandleState failed"); 
			CloseHandle(hPipe);
		}
	}
}
void CShellUpdater::UpdateShell()
{
    // Tell the shell extension to purge its cache
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Setting cache invalidation event %I64u\n", GetTickCount64());
    SetEvent(m_hInvalidationEvent);

    // We use the SVN 'notify' call-back to add items to the list
    // Because this might call-back more than once per file (for example, when committing)
    // it's possible that there may be duplicates in the list.
    // There's no point asking the shell to do more than it has to, so we remove the duplicates before
    // passing the list on
    m_pathsForUpdating.RemoveDuplicates();

    // if we use the external cache, we tell the cache directly that something
    // has changed, without the detour via the shell.
    CAutoFile hPipe = CreateFile(
        GetCacheCommandPipeName(),      // pipe name
        GENERIC_READ |                  // read and write access
        GENERIC_WRITE,
        0,                              // no sharing
        NULL,                           // default security attributes
        OPEN_EXISTING,                  // opens existing pipe
        FILE_FLAG_OVERLAPPED,           // default attributes
        NULL);                          // no template file


    if (!hPipe)
        return;

    // The pipe connected; change to message-read mode.
    DWORD dwMode = PIPE_READMODE_MESSAGE;
    if(SetNamedPipeHandleState(
         hPipe,    // pipe handle
         &dwMode,  // new pipe mode
         NULL,     // don't set maximum bytes
         NULL) == 0)    // don't set maximum time
    {
        CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
        return;
    }

    for(int nPath = 0; nPath < m_pathsForUpdating.GetCount(); nPath++)
    {
        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Cache Item Update for %s (%I64u)\n", m_pathsForUpdating[nPath].GetDirectory().GetWinPath(), GetTickCount64());
        if (!m_pathsForUpdating[nPath].IsDirectory())
        {
            // send notifications to the shell for changed files - folders are updated by the cache itself.
            SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, m_pathsForUpdating[nPath].GetWinPath(), NULL);
        }
        TSVNCacheCommand cmd;
        cmd.command = TSVNCACHECOMMAND_CRAWL;
        wcsncpy_s(cmd.path, m_pathsForUpdating[nPath].GetDirectory().GetWinPath(), _countof(cmd.path)-1);
        DWORD cbWritten;
        BOOL fSuccess = WriteFile(
            hPipe,          // handle to pipe
            &cmd,           // buffer to write from
            sizeof(cmd),    // number of bytes to write
            &cbWritten,     // number of bytes written
            NULL);          // not overlapped I/O

        if (! fSuccess || sizeof(cmd) != cbWritten)
        {
            DisconnectNamedPipe(hPipe);
            return;
        }
    }

    // now tell the cache we don't need it's command thread anymore
    TSVNCacheCommand cmd;
    cmd.command = TSVNCACHECOMMAND_END;
    DWORD cbWritten;
    WriteFile(
        hPipe,          // handle to pipe
        &cmd,           // buffer to write from
        sizeof(cmd),    // number of bytes to write
        &cbWritten,     // number of bytes written
        NULL);          // not overlapped I/O
    DisconnectNamedPipe(hPipe);
}
Exemple #5
0
bool SendCacheCommand(BYTE command, const WCHAR * path /* = NULL */)
{
    int retrycount = 2;
    CAutoFile hPipe;
    do
    {
        hPipe = CreateFile(
            GetCacheCommandPipeName(),      // pipe name
            GENERIC_READ |                  // read and write access
            GENERIC_WRITE,
            0,                              // no sharing
            NULL,                           // default security attributes
            OPEN_EXISTING,                  // opens existing pipe
            FILE_FLAG_OVERLAPPED,           // default attributes
            NULL);                          // no template file
        retrycount--;
        if (!hPipe)
            Sleep(10);
    } while ((!hPipe) && (retrycount));

    if (!hPipe)
    {
        CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not connect to pipe\n");
        return false;
    }

    // The pipe connected; change to message-read mode.
    DWORD dwMode = PIPE_READMODE_MESSAGE;
    if (SetNamedPipeHandleState(
        hPipe,    // pipe handle
        &dwMode,  // new pipe mode
        NULL,     // don't set maximum bytes
        NULL))    // don't set maximum time
    {
        DWORD cbWritten;
        TSVNCacheCommand cmd;
        SecureZeroMemory(&cmd, sizeof(TSVNCacheCommand));
        cmd.command = command;
        if (path)
            _tcsncpy_s(cmd.path, path, _TRUNCATE);

        retrycount = 2;
        BOOL fSuccess = FALSE;
        do
        {
            fSuccess = WriteFile(
                hPipe,          // handle to pipe
                &cmd,           // buffer to write from
                sizeof(cmd),    // number of bytes to write
                &cbWritten,     // number of bytes written
                NULL);          // not overlapped I/O
            retrycount--;
            if (! fSuccess || sizeof(cmd) != cbWritten)
                Sleep(10);
        } while ((retrycount) && (! fSuccess || sizeof(cmd) != cbWritten));

        if (! fSuccess || sizeof(cmd) != cbWritten)
        {
            CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not write to pipe\n");
            DisconnectNamedPipe(hPipe);
            return false;
        }
        // now tell the cache we don't need it's command thread anymore
        SecureZeroMemory(&cmd, sizeof(TSVNCacheCommand));
        cmd.command = TSVNCACHECOMMAND_END;
        WriteFile(
            hPipe,          // handle to pipe
            &cmd,           // buffer to write from
            sizeof(cmd),    // number of bytes to write
            &cbWritten,     // number of bytes written
            NULL);          // not overlapped I/O
        DisconnectNamedPipe(hPipe);
    }
    else
    {
        CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
        return false;
    }

    return true;
}
Exemple #6
0
DWORD WINAPI CommandWaitThread(LPVOID lpvParam)
{
	ATLTRACE("CommandWaitThread 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(
			GetCacheCommandPipeName(),
			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 hCommandThread = CreateThread(
				NULL,              // no security attribute
				0,                 // default stack size
				CommandThread,
				(HANDLE) hPipe,    // thread parameter
				0,                 // not suspended
				&dwThreadId);      // returns thread ID

			if (!hCommandThread)
			{
				//OutputDebugStringA("TSVNCache: Could not create Command thread\n");
				//DebugOutputLastError();
				DisconnectNamedPipe(hPipe);
				hPipe.CloseHandle();
				// 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("CommandWait thread exited\n");
	return 0;
}
bool CRemoteCacheLink::EnsureCommandPipeOpen()
{
	AutoLocker lock(m_critSec);
	return InternalEnsurePipeOpen (m_hCommandPipe, GetCacheCommandPipeName());
}
bool SendCacheCommand(BYTE command, const WCHAR* path /* = nullptr */)
{
	CAutoFile hPipe;
	CString pipeName = GetCacheCommandPipeName();
	for (int retry = 0; retry < 2; ++retry)
	{
		if (retry > 0)
			WaitNamedPipe(pipeName, 50);

		hPipe = CreateFile(
			pipeName,						// 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 (!hPipe && GetLastError() == ERROR_PIPE_BUSY)
		{
			// TGitCache 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
			continue;
		}
		break;
	}

	if (!hPipe)
	{
		CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not connect to pipe\n");
		return false;
	}

	// The pipe connected; change to message-read mode.
	DWORD dwMode = PIPE_READMODE_MESSAGE;
	if (SetNamedPipeHandleState(
		hPipe,		// pipe handle
		&dwMode,	// new pipe mode
		nullptr,	// don't set maximum bytes
		nullptr))	// don't set maximum time
	{
		DWORD cbWritten;
		TGITCacheCommand cmd = { 0 };
		cmd.command = command;
		if (path)
			wcsncpy_s(cmd.path, path, _TRUNCATE);

		int retrycount = 2;
		BOOL fSuccess = FALSE;
		do
		{
			fSuccess = WriteFile(
				hPipe,			// handle to pipe
				&cmd,			// buffer to write from
				sizeof(cmd),	// number of bytes to write
				&cbWritten,		// number of bytes written
				nullptr);		// not overlapped I/O
			retrycount--;
			if (! fSuccess || sizeof(cmd) != cbWritten)
				Sleep(10);
		} while ((retrycount) && (! fSuccess || sizeof(cmd) != cbWritten));

		if (! fSuccess || sizeof(cmd) != cbWritten)
		{
			CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not write to pipe\n");
			DisconnectNamedPipe(hPipe);
			return false;
		}
		// now tell the cache we don't need it's command thread anymore
		SecureZeroMemory(&cmd, sizeof(TGITCacheCommand));
		cmd.command = TGITCACHECOMMAND_END;
		WriteFile(
			hPipe,			// handle to pipe
			&cmd,			// buffer to write from
			sizeof(cmd),	// number of bytes to write
			&cbWritten,		// number of bytes written
			nullptr);		// not overlapped I/O
		DisconnectNamedPipe(hPipe);
	}
	else
	{
		CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
		return false;
	}

	return true;
}
Exemple #9
0
void CShellUpdater::UpdateShell()
{
    // Tell the shell extension to purge its cache
    ATLTRACE("Setting cache invalidation event %d\n", GetTickCount());
    SetEvent(m_hInvalidationEvent);

    // We use the SVN 'notify' call-back to add items to the list
    // Because this might call-back more than once per file (for example, when committing)
    // it's possible that there may be duplicates in the list.
    // There's no point asking the shell to do more than it has to, so we remove the duplicates before
    // passing the list on
    m_pathsForUpdating.RemoveDuplicates();

    // if we use the external cache, we tell the cache directly that something
    // has changed, without the detour via the shell.
    HANDLE hPipe = CreateFile(
                       GetCacheCommandPipeName(),		// pipe name
                       GENERIC_READ |					// read and write access
                       GENERIC_WRITE,
                       0,								// no sharing
                       NULL,							// default security attributes
                       OPEN_EXISTING,					// opens existing pipe
                       FILE_FLAG_OVERLAPPED,			// default attributes
                       NULL);							// no template file


    if (hPipe != INVALID_HANDLE_VALUE)
    {
        // The pipe connected; change to message-read mode.
        DWORD dwMode;

        dwMode = PIPE_READMODE_MESSAGE;
        if(SetNamedPipeHandleState(
                    hPipe,    // pipe handle
                    &dwMode,  // new pipe mode
                    NULL,     // don't set maximum bytes
                    NULL))    // don't set maximum time
        {
            CTGitPath path;
            for(int nPath = 0; nPath < m_pathsForUpdating.GetCount(); nPath++)
            {
                path.SetFromWin(g_Git.m_CurrentDir+_T("\\")+m_pathsForUpdating[nPath].GetWinPathString());
                ATLTRACE(_T("Cache Item Update for %s (%d)\n"), path.GetWinPathString(), GetTickCount());
                if (!path.IsDirectory())
                {
                    // send notifications to the shell for changed files - folders are updated by the cache itself.
                    SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, path.GetWinPath(), NULL);
                }
                DWORD cbWritten;
                TSVNCacheCommand cmd;
                cmd.command = TSVNCACHECOMMAND_CRAWL;
                wcsncpy_s(cmd.path, MAX_PATH+1, path.GetDirectory().GetWinPath(), MAX_PATH);
                BOOL fSuccess = WriteFile(
                                    hPipe,			// handle to pipe
                                    &cmd,			// buffer to write from
                                    sizeof(cmd),	// number of bytes to write
                                    &cbWritten,		// number of bytes written
                                    NULL);			// not overlapped I/O

                if (! fSuccess || sizeof(cmd) != cbWritten)
                {
                    DisconnectNamedPipe(hPipe);
                    CloseHandle(hPipe);
                    hPipe = INVALID_HANDLE_VALUE;
                    break;
                }
            }
            if (hPipe != INVALID_HANDLE_VALUE)
            {
                // now tell the cache we don't need it's command thread anymore
                DWORD cbWritten;
                TSVNCacheCommand cmd;
                cmd.command = TSVNCACHECOMMAND_END;
                WriteFile(
                    hPipe,			// handle to pipe
                    &cmd,			// buffer to write from
                    sizeof(cmd),	// number of bytes to write
                    &cbWritten,		// number of bytes written
                    NULL);			// not overlapped I/O
                DisconnectNamedPipe(hPipe);
                CloseHandle(hPipe);
                hPipe = INVALID_HANDLE_VALUE;
            }
        }
        else
        {
            ATLTRACE("SetNamedPipeHandleState failed");
            CloseHandle(hPipe);
        }
    }
}