Ejemplo n.º 1
0
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
    BOOL lbRc = FALSE;
    BOOL fSuccess = FALSE;
    MSectionThread SCT(csTabs);

    if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER)
    {
        gpPlugServer->BreakConnection(pInst);
        return FALSE;
    }

    UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);

    // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат
    switch (pIn->hdr.nCmd)
    {
    case CMD_LANGCHANGE:
    {
        _ASSERTE(nDataSize>=4); //-V112
        // LayoutName: "00000409", "00010409", ...
        // А HKL от него отличается, так что передаем DWORD
        // HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409"
        DWORD hkl = pIn->dwData[0];
        DWORD dwLastError = 0;
        HKL hkl1 = NULL, hkl2 = NULL;

        if (hkl)
        {
            WCHAR szLoc[10];
            _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl);
            hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS);
            hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER);

            if (!hkl2)
                dwLastError = GetLastError();
            else
                fSuccess = TRUE;
        }

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = fSuccess;
            ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError;
        }

        break;
    } // CMD_LANGCHANGE

#if 0
    case CMD_DEFFONT:
    {
        // исключение - асинхронный, результат не требуется
        SetConsoleFontSizeTo(FarHwnd, 4, 6);
        MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки...
        break;
    }
    CMD_DEFFONT
#endif

    case CMD_REQTABS:
    case CMD_SETWINDOW:
    {
        MSectionLock SC;
        SC.Lock(csTabs, FALSE, 1000);
        DWORD nSetWindowWait = (DWORD)-1;

        if (pIn->hdr.nCmd == CMD_SETWINDOW)
        {
            ResetEvent(ghSetWndSendTabsEvent);

            // Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно
            if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1])
            {
                // А вот для FAR1 - нужно шаманить
                Plugin()->ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/);
            }

            // Пересылается 2 DWORD
            BOOL bCmdRc = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData);

            DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n");

            WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?");
            if ((gFarVersion.dwVerMajor >= 2) && bCmdRc)
            {
                DWORD nTimeout = 2000;
#ifdef _DEBUG
                if (IsDebuggerPresent()) nTimeout = 120000;
#endif

                nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout);
            }

            if (nSetWindowWait == WAIT_TIMEOUT)
            {
                gbForceSendTabs = TRUE;
                DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW timeout !!!\n");
            }
            else
            {
                DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n");
            }
        }

        if (gpTabs && (nSetWindowWait != WAIT_TIMEOUT))
        {
            //fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = gpTabs->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr));
                lbRc = TRUE;
            }
        }

        SC.Unlock();
        break;
    } // CMD_REQTABS, CMD_SETWINDOW

    case CMD_FARSETCHANGED:
    {
        // Установить переменные окружения
        // Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина
        _ASSERTE(nDataSize>=8);
        FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data;

        cmd_FarSetChanged(pFarSet);

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = TRUE;
        }

        //_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar));
        //gbMonitorEnvVar = false;
        //// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса)
        //bool lbOk = false;

        //if (nDataSize<sizeof(gsMonitorEnvVar))
        //{
        //	memcpy(gsMonitorEnvVar, pszName, nDataSize);
        //	lbOk = true;
        //}

        //UpdateEnvVar(pszName);
        ////while (*pszName && *pszValue) {
        ////	const wchar_t* pszChanged = pszValue;
        ////	// Для ConEmuOutput == AUTO выбирается по версии ФАРа
        ////	if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) {
        ////		if (gFarVersion.dwVerMajor==1)
        ////			pszChanged = L"ANSI";
        ////		else
        ////			pszChanged = L"UNICODE";
        ////	}
        ////	// Если в pszValue пустая строка - удаление переменной
        ////	SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL);
        ////	//
        ////	pszName = pszValue + lstrlenW(pszValue) + 1;
        ////	if (*pszName == 0) break;
        ////	pszValue = pszName + lstrlenW(pszName) + 1;
        ////}
        //gbMonitorEnvVar = lbOk;

        break;
    } // CMD_FARSETCHANGED

    case CMD_DRAGFROM:
    {
#ifdef _DEBUG
        BOOL  *pbClickNeed = (BOOL*)pIn->Data;
        COORD *crMouse = (COORD *)(pbClickNeed+1);
#endif

        Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data);
        CESERVER_REQ* pCmdRet = NULL;
        Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

        if (pCmdRet)
        {
            //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = pCmdRet->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                lbRc = TRUE;
                memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
            }
            Free(pCmdRet);
        }

        break;
    } // CMD_DRAGFROM

    case CMD_EMENU:
    {
        COORD *crMouse = (COORD *)pIn->Data;
#ifdef _DEBUG
        const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1);
#endif
        DWORD ClickArg[2] = {(DWORD)TRUE, (DWORD)MAKELONG(crMouse->X, crMouse->Y)};

        // Выделить файл под курсором
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n");
        BOOL lb1 = Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/);
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n");

        // А теперь, собственно вызовем меню
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n");
        BOOL lb2 = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data);
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n");

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = lb1;
            ppReply->dwData[1] = lb1;
        }

        break;
    } // CMD_EMENU

    case CMD_ACTIVEWNDTYPE:
    {
        int nWindowType = -1;
        //CESERVER_REQ Out;
        //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD));

        if (gFarVersion.dwVerMajor>=2)
            nWindowType = Plugin()->GetActiveWindowType();

        //fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL);

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = nDataSize;
        }

        break;
    } // CMD_ACTIVEWNDTYPE

    case CECMD_ATTACH2GUI:
    {
        BOOL bAttached = Plugin()->Attach2Gui();
        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = bAttached;
        }
        break;
    } // CECMD_ATTACH2GUI

    default:
    {
        CESERVER_REQ* pCmdRet = NULL;
        BOOL lbCmd = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

        if (pCmdRet)
        {
            //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = pCmdRet->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                lbRc = TRUE;
                memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
            }
            Free(pCmdRet);
        }

    } // default
    } // switch (pIn->hdr.nCmd)

    return lbRc;
}
Ejemplo n.º 2
0
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	BOOL lbRc = FALSE;
	//HANDLE hPipe = (HANDLE)ahPipe;
	//CESERVER_REQ *pIn=NULL;
	//BYTE cbBuffer[64]; // Для большей части команд нам хватит
	//DWORD cbRead = 0, cbWritten = 0, dwErr = 0;
	BOOL fSuccess = FALSE;
	MSectionThread SCT(csTabs);
	// Send a message to the pipe server and read the response.
	//fSuccess = ReadFile(hPipe, cbBuffer, sizeof(cbBuffer), &cbRead, NULL);
	//dwErr = GetLastError();

	//if (!fSuccess && (dwErr != ERROR_MORE_DATA))
	//{
	//	_ASSERTE("ReadFile(pipe) failed"==NULL);
	//	CloseHandle(hPipe);
	//	return 0;
	//}

	//pIn = (CESERVER_REQ*)cbBuffer; // Пока cast, если нужно больше - выделим память
	//_ASSERTE(pIn->hdr.cbSize>=sizeof(CESERVER_REQ_HDR) && cbRead>=sizeof(CESERVER_REQ_HDR));
	//_ASSERTE(pIn->hdr.nVersion == CESERVER_REQ_VER);

	if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER)
	{
		//CloseHandle(hPipe);
		gpPlugServer->BreakConnection(pInst);
		return FALSE;
	}

	//int nAllSize = pIn->hdr.cbSize;
	//pIn = (CESERVER_REQ*)Alloc(nAllSize,1);
	//_ASSERTE(pIn!=NULL);

	//if (!pIn)
	//{
	//	CloseHandle(hPipe);
	//	return 0;
	//}

	//memmove(pIn, cbBuffer, cbRead);
	//_ASSERTE(pIn->hdr.nVersion==CESERVER_REQ_VER);
	//LPBYTE ptrData = ((LPBYTE)pIn)+cbRead;
	//nAllSize -= cbRead;

	//while(nAllSize>0)
	//{
	//	//_tprintf(TEXT("%s\n"), chReadBuf);

	//	// Break if TransactNamedPipe or ReadFile is successful
	//	if (fSuccess)
	//		break;

	//	// Read from the pipe if there is more data in the message.
	//	fSuccess = ReadFile(
	//	               hPipe,      // pipe handle
	//	               ptrData,    // buffer to receive reply
	//	               nAllSize,   // size of buffer
	//	               &cbRead,    // number of bytes read
	//	               NULL);      // not overlapped

	//	// Exit if an error other than ERROR_MORE_DATA occurs.
	//	if (!fSuccess && ((dwErr = GetLastError()) != ERROR_MORE_DATA))
	//		break;

	//	ptrData += cbRead;
	//	nAllSize -= cbRead;
	//}

	//TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения");
	//_ASSERTE(nAllSize==0);

	//if (nAllSize>0)
	//{
	//	if (((LPVOID)cbBuffer) != ((LPVOID)pIn))
	//		Free(pIn);

	//	CloseHandle(hPipe);
	//	return 0; // удалось считать не все данные
	//}

	UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);

	// Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат
	//fSuccess = WriteFile( hPipe, pOut, pOut->nSize, &cbWritten, NULL);

	if (pIn->hdr.nCmd == CMD_LANGCHANGE)
	{
		_ASSERTE(nDataSize>=4); //-V112
		// LayoutName: "00000409", "00010409", ...
		// А HKL от него отличается, так что передаем DWORD
		// HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409"
		DWORD hkl = pIn->dwData[0];
		DWORD dwLastError = 0;
		HKL hkl1 = NULL, hkl2 = NULL;

		if (hkl)
		{
			WCHAR szLoc[10]; _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl);
			hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS);
			hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER);

			if (!hkl2)
				dwLastError = GetLastError();
			else
				fSuccess = TRUE;
		}

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = fSuccess;
			ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError;
		}

	}
	//} else if (pIn->hdr.nCmd == CMD_DEFFONT) {
	//	// исключение - асинхронный, результат не требуется
	//	SetConsoleFontSizeTo(FarHwnd, 4, 6);
	//	MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки...
	else if (pIn->hdr.nCmd == CMD_REQTABS || pIn->hdr.nCmd == CMD_SETWINDOW)
	{
		MSectionLock SC; SC.Lock(csTabs, FALSE, 1000);
		DWORD nSetWindowWait = (DWORD)-1;

		if (pIn->hdr.nCmd == CMD_SETWINDOW)
		{
			ResetEvent(ghSetWndSendTabsEvent);

			// Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно
			if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1])
			{
				// А вот для FAR1 - нужно шаманить
				ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/);
			}

			// Пересылается 2 DWORD
			BOOL bCmdRc = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData);

			DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n");

			WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?");
			if ((gFarVersion.dwVerMajor >= 2) && bCmdRc)
			{
				DWORD nTimeout = 2000;
				#ifdef _DEBUG
				if (IsDebuggerPresent()) nTimeout = 120000;
				#endif
				
				nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout);
			}

			DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n");
		}

		if (gpTabs)
		{
			//fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = gpTabs->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr));
				lbRc = TRUE;
			}
		}

		SC.Unlock();
	}
	else if (pIn->hdr.nCmd == CMD_FARSETCHANGED)
	{
		// Установить переменные окружения
		// Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина
		_ASSERTE(nDataSize>=8);
		FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data;

		cmd_FarSetChanged(pFarSet);

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = TRUE;
		}

		//_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar));
		//gbMonitorEnvVar = false;
		//// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса)
		//bool lbOk = false;

		//if (nDataSize<sizeof(gsMonitorEnvVar))
		//{
		//	memcpy(gsMonitorEnvVar, pszName, nDataSize);
		//	lbOk = true;
		//}

		//UpdateEnvVar(pszName);
		////while (*pszName && *pszValue) {
		////	const wchar_t* pszChanged = pszValue;
		////	// Для ConEmuOutput == AUTO выбирается по версии ФАРа
		////	if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) {
		////		if (gFarVersion.dwVerMajor==1)
		////			pszChanged = L"ANSI";
		////		else
		////			pszChanged = L"UNICODE";
		////	}
		////	// Если в pszValue пустая строка - удаление переменной
		////	SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL);
		////	//
		////	pszName = pszValue + lstrlenW(pszValue) + 1;
		////	if (*pszName == 0) break;
		////	pszValue = pszName + lstrlenW(pszName) + 1;
		////}
		//gbMonitorEnvVar = lbOk;
	}
	else if (pIn->hdr.nCmd == CMD_DRAGFROM)
	{
		#ifdef _DEBUG
		BOOL  *pbClickNeed = (BOOL*)pIn->Data;
		COORD *crMouse = (COORD *)(pbClickNeed+1);
		#endif

		ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data);
		CESERVER_REQ* pCmdRet = NULL;
		ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

		if (pCmdRet)
		{
			//fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = pCmdRet->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
			}
			Free(pCmdRet);
		}

		//if (gpCmdRet && gpCmdRet == pCmdRet)
		//{
		//	Free(gpCmdRet);
		//	gpCmdRet = NULL; gpData = NULL; gpCursor = NULL;
		//}
	}
	else if (pIn->hdr.nCmd == CMD_EMENU)
	{
		COORD *crMouse = (COORD *)pIn->Data;
#ifdef _DEBUG
		const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1);
#endif
		DWORD ClickArg[2] = {TRUE, MAKELONG(crMouse->X, crMouse->Y)};
		
		// Выделить файл под курсором
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n");
		BOOL lb1 = ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/);
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n");

		// А теперь, собственно вызовем меню
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n");
		BOOL lb2 = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data);
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n");

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = lb1;
			ppReply->dwData[1] = lb1;
		}
	}
	else if (pIn->hdr.nCmd == CMD_ACTIVEWNDTYPE)
	{
		int nWindowType = -1;
		//CESERVER_REQ Out;
		//ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD));

		if (gFarVersion.dwVerMajor>=2)
			nWindowType = GetActiveWindowType();

		//fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL);

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = nDataSize;
		}		
	}
	else
	{
		CESERVER_REQ* pCmdRet = NULL;
		BOOL lbCmd = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

		if (pCmdRet)
		{
			//fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = pCmdRet->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
			}
			Free(pCmdRet);
		}

		//if (gpCmdRet && gpCmdRet == pCmdRet) {
		//	Free(gpCmdRet);
		//	gpCmdRet = NULL; gpData = NULL; gpCursor = NULL;
		//}
	}

	//// Освободить память
	//if (((LPVOID)cbBuffer) != ((LPVOID)pIn))
	//	Free(pIn);

	//CloseHandle(hPipe);
	return lbRc;
}