DWORD CDragDrop::DragStart(IDropSource *pDropSource, const DWORD dwAllowedEffects, DWORD& dwEffect) { DWORD dwResult = E_UNEXPECTED; wchar_t szStep[255]; _wsprintf(szStep, SKIPLEN(countof(szStep)) L"DoDragDrop(Eff=0x%X, DataObject=0x%08X, DropSource=0x%08X)", dwAllowedEffects, (DWORD)mp_DataObject, (DWORD)pDropSource); //-V205 DebugLog(szStep); SAFETRY { dwResult = DoDragDrop(mp_DataObject, pDropSource, dwAllowedEffects, &dwEffect); } SAFECATCH { dwResult = DRAGDROP_S_CANCEL; MBoxA(L"Exception in DoDragDrop\nConEmu restart is recommended"); } _wsprintf(szStep, SKIPLEN(countof(szStep)) L"DoDragDrop finished, Code=0x%08X", dwResult); switch(dwResult) { case S_OK: wcscat_c(szStep, L" (S_OK)"); break; case DRAGDROP_S_DROP: wcscat_c(szStep, L" (DRAGDROP_S_DROP)"); break; case DRAGDROP_S_CANCEL: wcscat_c(szStep, L" (DRAGDROP_S_CANCEL)"); break; //case E_UNSPEC: lstrcat(szStep, L" (E_UNSPEC)"); break; } DebugLog(szStep, (dwResult!=S_OK && dwResult!=DRAGDROP_S_CANCEL && dwResult!=DRAGDROP_S_DROP)); return dwResult; }
bool CBackgroundInfo::LoadBackgroundFile(bool abShowErrors) { // Пустой путь - значит БЕЗ обоев if (!*ms_BgImage) { return true; } //_ASSERTE(gpConEmu->isMainThread()); _ASSERTE(gpConEmu->isMainThread()); bool lRes = false; BY_HANDLE_FILE_INFORMATION inf = {0}; BITMAPFILEHEADER* pBkImgData = NULL; if (wcspbrk(ms_BgImage, L"%\\.") == NULL) { // May be "Solid color" COLORREF clr = (COLORREF)-1; if (GetColorRef(ms_BgImage, &clr)) { pBkImgData = CreateSolidImage(clr, 128, 128); } } if (!pBkImgData) { wchar_t* exPath = ExpandEnvStr(ms_BgImage); if (!exPath || !*exPath) { if (abShowErrors) { wchar_t szError[MAX_PATH*2]; DWORD dwErr = GetLastError(); _wsprintf(szError, SKIPLEN(countof(szError)) L"Can't expand environment strings:\r\n%s\r\nError code=0x%08X\r\nImage loading failed", ms_BgImage, dwErr); MBoxA(szError); } return false; } pBkImgData = LoadImageEx(exPath, inf); } if (pBkImgData) { ftBgModified = inf.ftLastWriteTime; nBgModifiedTick = GetTickCount(); //NeedBackgroundUpdate(); //MSectionLock SBG; SBG.Lock(&mcs_BgImgData); SafeFree(mp_BgImgData); mb_IsBackgroundImageValid = true; mp_BgImgData = pBkImgData; lRes = true; } return lRes; }
bool CConEmuStart::GetCfgParm(LPCWSTR& cmdLineRest, CESwitch& Val, int nMaxLen, bool bExpandAndDup /*= false*/) { if (Val.Type == sw_Str || Val.Type == sw_EnvStr || Val.Type == sw_PathStr) { SafeFree(Val.Str); } else { Val.Type = bExpandAndDup ? sw_EnvStr : sw_Str; } Val.Exists = false; if (!cmdLineRest || !*cmdLineRest) { _ASSERTE(cmdLineRest && *cmdLineRest); return false; } // Сохраним, может для сообщения об ошибке понадобится LPCWSTR pszName = cmdLineRest; CmdArg szGetCfgParmTemp; if (!(cmdLineRest = NextArg(cmdLineRest, szGetCfgParmTemp))) { return false; } LPCWSTR curCommand = szGetCfgParmTemp.ms_Val; int nLen = _tcslen(curCommand); if (nLen >= nMaxLen) { int nCchSize = nLen+100+_tcslen(pszName); wchar_t* psz = (wchar_t*)calloc(nCchSize,sizeof(wchar_t)); if (psz) { swprintf_c(psz, nCchSize/*#SECURELEN*/, L"Too long %s value (%i chars).\r\n", pszName, nLen); _wcscat_c(psz, nCchSize, curCommand); MBoxA(psz); free(psz); } return false; } // We need independent absolute file paths, Working dir changes during ConEmu session if (bExpandAndDup) Val.Str = GetFullPathNameEx(curCommand); // it allocates memory else Val.SetStr(curCommand, Val.Type); // Ok Val.Exists = (Val.Str && *Val.Str); return true; }
void SettingsXML::CloseStorage() { HRESULT hr = S_OK; HANDLE hFile = NULL; bool bCanSave = false; CloseKey(); if (mb_Modified && mp_File) { // Путь к файлу проинициализирован в OpenKey _ASSERTE(m_Storage.pszFile && *m_Storage.pszFile); LPCWSTR pszXmlFile = m_Storage.pszFile; if (pszXmlFile) { hFile = CreateFile(pszXmlFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); // XML-файл отсутсвует, или ошибка доступа if (hFile == INVALID_HANDLE_VALUE) { DWORD dwErrCode = GetLastError(); wchar_t szErr[MAX_PATH*2]; _wsprintf(szErr, SKIPLEN(countof(szErr)) L"Can't open file for writing!\n%s\nErrCode=0x%08X", pszXmlFile, dwErrCode); MBoxA(szErr); } else { CloseHandle(hFile); hFile = NULL; bCanSave = true; } if (bCanSave) { VARIANT vt; vt.vt = VT_BSTR; vt.bstrVal = ::SysAllocString(pszXmlFile); hr = mp_File->save(vt); VariantClear(&vt); } } } SafeRelease(mp_File); mb_Modified = false; mb_DataChanged = false; mb_Empty = false; mn_access = 0; }
CBackgroundInfo* CBackgroundInfo::CreateBackgroundObject(LPCWSTR inPath, bool abShowErrors) { if (inPath && _tcslen(inPath)>=MAX_PATH) { if (abShowErrors) MBoxA(L"Invalid 'BgImagePath' in CBackgroundInfo::CreateBackgroundObject"); return NULL; } // Допускается и пустой путь! inPath = SkipNonPrintable(inPath); if (!inPath) inPath = L""; CBackgroundInfo* p = NULL; for (INT_PTR i = 0; i < g_Backgrounds.size(); i++) { if (!g_Backgrounds[i]) { _ASSERTE(g_Backgrounds[i]!=NULL); continue; } if (lstrcmpi(g_Backgrounds[i]->BgImage(), inPath) == 0) { p = g_Backgrounds[i]; break; } } if (p) { p->AddRef(); } else { p = new CBackgroundInfo(inPath); if (inPath && *inPath && !p->LoadBackgroundFile(abShowErrors)) { SafeRelease(p); } } return p; }
BOOL CConEmuPipe::Init(LPCTSTR asOp, BOOL abSilent) { wchar_t szErr[MAX_PATH*2]; mh_Pipe = ExecuteOpenPipe(ms_PipeName, szErr, gpConEmu->GetDefaultTitle()); if (!mh_Pipe || mh_Pipe == INVALID_HANDLE_VALUE) { MBoxA(szErr); return FALSE; } return TRUE; //DWORD dwErr = 0; // //// Try to open a named pipe; wait for it, if necessary. //while (1) //{ // mh_Pipe = CreateFile( // ms_PipeName, // pipe name // GENERIC_READ | // read and write access // GENERIC_WRITE, // 0, // no sharing // NULL, // default security attributes // OPEN_EXISTING, // opens existing pipe // 0, // default attributes // NULL); // no template file // // // Break if the pipe handle is valid. // if (mh_Pipe != INVALID_HANDLE_VALUE) // break; // // // Exit if an error other than ERROR_PIPE_BUSY occurs. // dwErr = GetLastError(); // if (dwErr != ERROR_PIPE_BUSY) // { // if (!abSilent) { // WCHAR szMsg[128]; // swprintf(szMsg, _T("Can't open plugin pipe! Plugin is not installed?\r\nFAR PID: %i, ErrCode: 0x%08X"), mn_FarPID, dwErr); // MBoxA(szMsg); // } // return FALSE; // } // // // All pipe instances are busy, so wait for 1 second. // if (!WaitNamedPipe(ms_PipeName, 1000) ) // { // if (!abSilent) { // WCHAR szMsg[128]; // swprintf(szMsg, _T("Plugin pipe timeout!\r\nFAR PID: %i"), mn_FarPID); // MBoxA(szMsg); // } // return FALSE; // } //} // //// The pipe connected; change to message-read mode. //DWORD dwMode = CE_PIPE_READMODE; //BOOL fSuccess = SetNamedPipeHandleState( // mh_Pipe, // pipe handle // &dwMode, // new pipe mode // NULL, // don't set maximum bytes // NULL); // don't set maximum time //if (!fSuccess) //{ // SafeCloseHandle(mh_Pipe); // return FALSE; //} // //return TRUE; }
// Не интересуется результатом команды! BOOL CConEmuPipe::Execute(int nCmd, LPCVOID apData, UINT anDataSize) { WARNING("Если указан mdw_Timeout - создать нить и выполнять команду в ней. Ожидать нить не более и прибить ее, если пришел Timeout"); MCHKHEAP if (!((nCmd >= (int)CMD_FIRST_FAR_CMD && nCmd <= (int)CMD_LAST_FAR_CMD))) { TCHAR szError[128]; _wsprintf(szError, SKIPLEN(countof(szError)) _T("Invalid command id (%i)!\nPID=%u, TID=%u"), nCmd, GetCurrentProcessId(), GetCurrentThreadId()); MBoxA(szError); return FALSE; } #ifdef _DEBUG WCHAR szMsg[64]; _wsprintf(szMsg, SKIPLEN(countof(szMsg)) _T("Pipe:Execute(%i)\n"), nCmd); DEBUGSTR(szMsg); #endif int nAllSize = sizeof(CESERVER_REQ_HDR)+anDataSize; CESERVER_REQ* pIn = ExecuteNewCmd(nCmd, nAllSize); if (!pIn) { _ASSERTE(pIn!=NULL); TCHAR szError[128]; _wsprintf(szError, SKIPLEN(countof(szError)) _T("Pipe: Can't allocate memory (%i) bytes, Cmd = %i!"), nAllSize, nCmd); MBoxA(szError); Close(); return FALSE; } if (apData && anDataSize) { memmove(pIn->Data, apData, anDataSize); } DWORD dwTickStart = timeGetTime(); BYTE cbReadBuf[512]; BOOL fSuccess; DWORD cbRead, dwErr; // Send a message to the pipe server and read the response. fSuccess = TransactNamedPipe( mh_Pipe, // pipe handle pIn, // message to server pIn->hdr.cbSize, // message length cbReadBuf, // buffer to receive reply sizeof(cbReadBuf), // size of read buffer &cbRead, // bytes read NULL); // not overlapped dwErr = GetLastError(); gpSetCls->debugLogCommand(pIn, FALSE, dwTickStart, timeGetTime()-dwTickStart, ms_PipeName); if (!fSuccess && dwErr == ERROR_BROKEN_PIPE) { // Плагин не вернул данных, но обработал команду Close(); SafeFree(pIn); return TRUE; } else if (!fSuccess && (dwErr != ERROR_MORE_DATA)) { DEBUGSTR(L" - FAILED!\n"); TCHAR szError[128]; _wsprintf(szError, SKIPLEN(countof(szError)) _T("Pipe: TransactNamedPipe failed, Cmd = %i, ErrCode = 0x%08X!"), nCmd, dwErr); MBoxA(szError); Close(); SafeFree(pIn); return FALSE; } if (cbRead < sizeof(DWORD)) { pOut = NULL; Close(); SafeFree(pIn); return FALSE; } pOut = (CESERVER_REQ*)cbReadBuf; // Проверка размера if (pOut->hdr.cbSize <= sizeof(pOut->hdr)) { _ASSERTE(pOut->hdr.cbSize == 0); pOut = NULL; Close(); SafeFree(pIn); return FALSE; } if (pOut->hdr.nVersion != CESERVER_REQ_VER) { gpConEmu->ReportOldCmdVersion(pOut->hdr.nCmd, pOut->hdr.nVersion, -1, pOut->hdr.nSrcPID, pOut->hdr.hModule, pOut->hdr.nBits); pOut = NULL; Close(); SafeFree(pIn); return FALSE; } nAllSize = pOut->hdr.cbSize; pOut = NULL; if (nAllSize==0) { DEBUGSTR(L" - FAILED!\n"); DisplayLastError(L"Empty data recieved from server", 0); Close(); SafeFree(pIn); return FALSE; } pOut = (CESERVER_REQ*)calloc(nAllSize,1); _ASSERTE(pOut!=NULL); memmove(pOut, cbReadBuf, cbRead); _ASSERTE(pOut->hdr.nVersion==CESERVER_REQ_VER); LPBYTE ptrData = ((LPBYTE)pOut)+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( mh_Pipe, // 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 && (GetLastError() != ERROR_MORE_DATA)) break; ptrData += cbRead; nAllSize -= cbRead; } TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения"); _ASSERTE(nAllSize==0); SafeCloseHandle(mh_Pipe); SafeFree(pIn); lpCursor = pOut->Data; dwMaxDataSize = pOut->hdr.cbSize - sizeof(CESERVER_REQ_HDR); return TRUE; }
bool SettingsXML::OpenKey(const wchar_t *regPath, uint access, BOOL abSilent /*= FALSE*/) { // That may occures if Basic settings and "Export" button was pressed _ASSERTE(!gpConEmu->IsResetBasicSettings() || ((access & KEY_WRITE)!=KEY_WRITE)); bool lbRc = false; HRESULT hr = S_OK; wchar_t szErr[512]; szErr[0] = 0; wchar_t szName[MAX_PATH]; const wchar_t* psz = NULL; IXMLDOMNode* pKey = NULL; IXMLDOMNode* pChild = NULL; bool bAllowCreate = (access & KEY_WRITE) == KEY_WRITE; CloseKey(); // на всякий if (!regPath || !*regPath) { return false; } if (!OpenStorage(access, szErr)) { goto wrap; } SAFETRY { _ASSERTE(mp_File != NULL); hr = mp_File->QueryInterface(IID_IXMLDOMNode, (void **)&pKey); if (FAILED(hr)) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Root node not found!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } mi_Level = 0; while (*regPath) { // Получить следующий токен psz = wcschr(regPath, L'\\'); if (!psz) psz = regPath + _tcslen(regPath); lstrcpyn(szName, regPath, psz-regPath+1); // Найти в структуре XML pChild = FindItem(pKey, L"key", szName, bAllowCreate); pKey->Release(); pKey = pChild; pChild = NULL; mi_Level++; if (!pKey) { if (bAllowCreate) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Can't create key <%s>!", szName); } else { //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: key <%s> not found!", szName); szErr[0] = 0; // ошибку не показывать - настройки по умолчанию } goto wrap; } if (*psz == L'\\') { regPath = psz + 1; } else { break; } } // Нашли, запомнили mp_Key = pKey; pKey = NULL; #if 0 if (mp_Key) { SYSTEMTIME st; wchar_t szTime[32]; GetLocalTime(&st); _wsprintf(szTime, SKIPLEN(countof(szTime)) L"%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); SetAttr(mp_Key, L"modified", szTime); SetAttr(mp_Key, L"build", gpConEmu->ms_ConEmuBuild); } #endif lbRc = true; } SAFECATCH { lstrcpy(szErr, L"Exception in SettingsXML::OpenKey"); lbRc = false; } wrap: SafeRelease(pChild); SafeRelease(pKey); if (!lbRc && szErr[0] && !abSilent) { MBoxA(szErr); } return lbRc; }
//------------------------------------------------------------------------ ///| Parsing the command line |/////////////////////////////////////////// //------------------------------------------------------------------------ // Returns: // true - continue normal startup // false - exit process with iResult code bool CConEmuStart::ParseCommandLine(LPCWSTR pszCmdLine, int& iResult) { bool bRc = false; iResult = 100; _ASSERTE(pszCmdLine!=NULL); opt.cmdLine.Set(pszCmdLine ? pszCmdLine : L""); // pszCmdLine *may* or *may not* start with our executable or full path to our executable LPCWSTR pszTemp = opt.cmdLine; LPCWSTR cmdLineRest = SkipNonPrintable(opt.cmdLine); LPCWSTR pszName, pszArgStart; LPCWSTR psUnknown = NULL; CEStr szArg, szNext; CEStr szExeName, szExeNameOnly; // Set %ConEmuArgs% env var // It may be usefull if we need to restart ConEmu // from batch/script with the same arguments (selfupdate etc.) LPCWSTR pszCopyToEnvStart = NULL; // Have to get our exectuable name and name without extension szExeName.Set(PointToName(gpConEmu->ms_ConEmuExe)); szExeNameOnly.Set(szExeName); wchar_t* pszDot = (wchar_t*)PointToExt(szExeNameOnly.ms_Val); _ASSERTE(pszDot); if (pszDot) *pszDot = 0; // Check the first argument in the command line (most probably it will be our executable path/name) if (NextArg(&pszTemp, szArg) != 0) { _ASSERTE(FALSE && "GetCommandLine() is empty"); // Treat as empty command line, allow to start bRc = true; iResult = 0; goto wrap; } pszName = PointToName(szArg); if ((lstrcmpi(pszName, szExeName) == 0) || (lstrcmpi(pszName, szExeNameOnly) == 0)) { // OK, our executable was specified properly in the command line _ASSERTE(*pszTemp != L' '); cmdLineRest = SkipNonPrintable(pszTemp); } // Must be empty at the moment _ASSERTE(opt.runCommand.IsEmpty()); // Does the command line contain our switches? // Or we need to append all switches to starting shell? if (cmdLineRest && *cmdLineRest) { pszTemp = cmdLineRest; if (NextArg(&pszTemp, szArg) == 0) { if ((*szArg.ms_Val != L'/') && (*szArg.ms_Val != L'-') /*&& !wcschr(szArg.ms_Val, L'/')*/ ) { // Save it for further use opt.runCommand.Set(cmdLineRest); // And do not process it (no switches at all) cmdLineRest = NULL; opt.params = -1; } } } // Let parse the reset szArg.Empty(); szNext.Empty(); // Processing loop begin if (cmdLineRest && *cmdLineRest) { pszCopyToEnvStart = cmdLineRest; opt.cfgSwitches.Set(pszCopyToEnvStart); while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0) { bool lbNotFound = false; // ':' removed from checks because otherwise it will not warn // on invalid usage of "-new_console:a" for example if (szArg.ms_Val[0] == L'-' && szArg.ms_Val[1] && !wcspbrk(szArg.ms_Val+1, L"\\//|.&<>^")) { // Seems this is to be the "switch" too // Use both notations ('-' and '/') *szArg.ms_Val = L'/'; } LPCWSTR curCommand = szArg.ms_Val; #define NeedNextArg() \ if (NextArg(&cmdLineRest, szNext) != 0) { iResult = 101; goto wrap; } \ curCommand = szNext.ms_Val; if (*curCommand != L'/') { continue; // Try next switch? } else { opt.params++; if (!klstricmp(curCommand, _T("/autosetup"))) { BOOL lbTurnOn = TRUE; NeedNextArg(); if (*curCommand == _T('0')) { lbTurnOn = FALSE; } else { NeedNextArg(); DWORD dwAttr = GetFileAttributes(curCommand); if (dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { iResult = 102; goto wrap; } } HKEY hk = NULL; DWORD dw; int nSetupRc = 100; if (0 != RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Command Processor"), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dw)) { iResult = 103; goto wrap; } if (lbTurnOn) { size_t cchMax = _tcslen(curCommand); LPCWSTR pszArg1 = NULL; if (*cmdLineRest) { // May be ‘/GHWND=NEW’ or smth else pszArg1 = cmdLineRest; cchMax += _tcslen(pszArg1); } cchMax += 16; // + quotations, spaces and so on wchar_t* pszCmd = (wchar_t*)calloc(cchMax, sizeof(*pszCmd)); _wsprintf(pszCmd, SKIPLEN(cchMax) L"\"%s\"%s%s%s", curCommand, pszArg1 ? L" \"" : L"", pszArg1 ? pszArg1 : L"", pszArg1 ? L"\"" : L""); if (0 == RegSetValueEx(hk, _T("AutoRun"), 0, REG_SZ, (LPBYTE)pszCmd, (DWORD)sizeof(*pszCmd)*(_tcslen(pszCmd)+1))) nSetupRc = 1; free(pszCmd); } else { if (0==RegDeleteValue(hk, _T("AutoRun"))) nSetupRc = 1; } RegCloseKey(hk); // сбросить CreateInNewEnvironment для ConMan ResetConman(); iResult = nSetupRc; goto wrap; } else if (!klstricmp(curCommand, _T("/bypass")) || !klstricmp(curCommand, _T("/apparent")) || !klstricmp(curCommand, _T("/system")) || !klstricmp(curCommand, _T("/interactive")) || !klstricmp(curCommand, _T("/demote"))) { // -bypass // Этот ключик был придуман для прозрачного запуска консоли // в режиме администратора // (т.е. чтобы окно UAC нормально всплывало, но не мелькало консольное окно) // Но не получилось, пока требуются хэндлы процесса, а их не получается // передать в НЕ приподнятый процесс (исходный ConEmu GUI). // -apparent // Same as -bypass, but run the process as SW_SHOWNORMAL // -demote // Запуск процесса (ком.строка после "/demote") в режиме простого юзера, // когда текущий процесс уже запущен "под админом". "Понизить" текущие // привилегии просто так нельзя, поэтому запуск идет через TaskSheduler. // -system // Non-interactive process, started as System account // It's used when starting consoles, our server works fine as non-interactive // -interactive // Used when ConEmu.exe is started under System account, // but we need to give starting process interactive capabilities. _ASSERTE(opt.runCommand.IsEmpty()); pszTemp = cmdLineRest; if ((NextArg(&pszTemp, szNext) == 0) && (szNext.ms_Val[0] == L'-' || szNext.ms_Val[0] == L'/') && (lstrcmpi(szNext.ms_Val+1, L"cmd") == 0)) { opt.runCommand.Set(pszTemp); } else { opt.runCommand.Set(cmdLineRest); } if (opt.runCommand.IsEmpty()) { CEStr lsMsg(L"Invalid cmd line. '", curCommand, L"' exists, command line is empty"); DisplayLastError(lsMsg, -1); goto wrap; } // Information #ifdef _DEBUG STARTUPINFO siOur = {sizeof(siOur)}; GetStartupInfo(&siOur); #endif STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; si.dwFlags = STARTF_USESHOWWINDOW; // Only `-demote` and `-apparent` switches were implemented to start application visible // All others are intended to run our server process, without blinking of course if ((0 == klstricmp(curCommand, _T("/demote"))) || (0 == klstricmp(curCommand, _T("/apparent")))) si.wShowWindow = SW_SHOWNORMAL; else si.wShowWindow = SW_HIDE; wchar_t szCurDir[MAX_PATH+1] = L""; GetCurrentDirectory(countof(szCurDir), szCurDir); BOOL b; DWORD nErr = 0; // if we were started from TaskScheduler, it would be nice to wait a little // to let parent (creator of the scheduler task) know we were started successfully bool bFromScheduler = false; // Log the command to be started { CEStr lsLog( L"Starting process", L": ", curCommand, L" `", opt.runCommand.ms_Val, L"`"); LogString(lsLog); } if (!klstricmp(curCommand, _T("/demote"))) { b = CreateProcessDemoted(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi, &nErr); } else if (!klstricmp(curCommand, _T("/system"))) { b = CreateProcessSystem(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi); } else if (!klstricmp(curCommand, _T("/interactive"))) { b = CreateProcessInteractive((DWORD)-1, NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi, &nErr); bFromScheduler = true; } else // -bypass, -apparent { b = CreateProcess(NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); nErr = b ? 0 : GetLastError(); bFromScheduler = true; } // Log the result { CEStr lsLog; wchar_t szExtra[32] = L""; if (b) { if (pi.dwProcessId) _wsprintf(szExtra, SKIPCOUNT(szExtra) L", PID=%u", pi.dwProcessId); lsLog = lstrmerge( L"Process was created successfully", szExtra); } else { _wsprintf(szExtra, SKIPCOUNT(szExtra) L", ErrorCode=%u", nErr); lsLog = lstrmerge( L"Failed to start process", szExtra); } LogString(lsLog); } // If the error was not shown yet if (nErr) DisplayLastError(opt.runCommand, nErr); // if we were started from TaskScheduler, it would be nice to wait a little // to let parent (creator of the scheduler task) know we were started successfully if (bFromScheduler) { LogString(L"Sleeping for 5 seconds"); Sleep(5*1000); } // Success? if (b) { iResult = 0; } // Done, close handles, if they were opened SafeCloseHandle(pi.hProcess); SafeCloseHandle(pi.hThread); goto wrap; } else if (!klstricmp(curCommand, _T("/multi"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.MultiConValue = true; } else if (!klstricmp(curCommand, _T("/nomulti"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.MultiConValue = false; } else if (!klstricmp(curCommand, _T("/visible"))) { gpConEmu->opt.VisValue = true; } else if (!klstricmp(curCommand, _T("/ct")) || !klstricmp(curCommand, _T("/cleartype")) || !klstricmp(curCommand, _T("/ct0")) || !klstricmp(curCommand, _T("/ct1")) || !klstricmp(curCommand, _T("/ct2"))) { switch (curCommand[3]) { case L'0': gpConEmu->opt.ClearTypeVal = NONANTIALIASED_QUALITY; break; case L'1': gpConEmu->opt.ClearTypeVal = ANTIALIASED_QUALITY; break; default: gpConEmu->opt.ClearTypeVal = CLEARTYPE_NATURAL_QUALITY; } } // Interface language else if (!klstricmp(curCommand, _T("/lng"))) { NeedNextArg(); if (!gpConEmu->opt.Language.Exists) { gpConEmu->opt.Language = curCommand; gpConEmu->AppendExtraArgs(L"/lng", curCommand); } } // Optional specific "ConEmu.l10n" else if (!klstricmp(curCommand, _T("/lngfile"))) { NeedNextArg(); if (!gpConEmu->opt.LanguageFile.Exists) { gpConEmu->opt.LanguageFile = curCommand; gpConEmu->AppendExtraArgs(L"/lngfile", curCommand); } } // имя шрифта else if (!klstricmp(curCommand, _T("/font"))) { NeedNextArg(); if (!gpConEmu->opt.FontVal.Exists) { gpConEmu->opt.FontVal = curCommand; gpConEmu->AppendExtraArgs(L"/font", curCommand); } } // Высота шрифта else if (!klstricmp(curCommand, _T("/size"))) { NeedNextArg(); if (!gpConEmu->opt.SizeVal.Exists) { gpConEmu->opt.SizeVal.SetInt(curCommand); } } // ADD fontname; by Mors else if (!klstricmp(curCommand, _T("/fontfile"))) { CESwitch szFile(sw_Str); if (!GetCfgParm(cmdLineRest, szFile, MAX_PATH)) { goto wrap; } gpConEmu->AppendExtraArgs(L"/fontfile", szFile.GetStr()); gpFontMgr->RegisterFont(szFile.GetStr(), TRUE); } // Register all fonts from specified directory else if (!klstricmp(curCommand, _T("/fontdir"))) { CESwitch szDir(sw_Str); if (!GetCfgParm(cmdLineRest, szDir, MAX_PATH)) { goto wrap; } gpConEmu->AppendExtraArgs(L"/fontdir", szDir.GetStr()); gpFontMgr->RegisterFontsDir(szDir.GetStr()); } else if (!klstricmp(curCommand, _T("/fs"))) { gpConEmu->opt.WindowModeVal = wmFullScreen; } else if (!klstricmp(curCommand, _T("/max"))) { gpConEmu->opt.WindowModeVal = wmMaximized; } else if (!klstricmp(curCommand, _T("/min")) || !klstricmp(curCommand, _T("/mintsa")) || !klstricmp(curCommand, _T("/starttsa"))) { gpConEmu->WindowStartMinimized = true; if (klstricmp(curCommand, _T("/min")) != 0) { gpConEmu->WindowStartTsa = true; gpConEmu->WindowStartNoClose = (klstricmp(curCommand, _T("/mintsa")) == 0); } } else if (!klstricmp(curCommand, _T("/tsa")) || !klstricmp(curCommand, _T("/tray"))) { gpConEmu->ForceMinimizeToTray = true; } else if (!klstricmp(curCommand, _T("/detached"))) { gpConEmu->m_StartDetached = crb_On; } else if (!klstricmp(curCommand, _T("/here"))) { gpConEmu->mb_ConEmuHere = true; gpConEmu->StoreWorkDir(); } else if (!klstricmp(curCommand, _T("/update"))) { gpConEmu->opt.AutoUpdateOnStart = true; } else if (!klstricmp(curCommand, _T("/noupdate"))) { // This one has more weight than AutoUpdateOnStart gpConEmu->opt.DisableAutoUpdate = true; } else if (!klstricmp(curCommand, _T("/nokeyhook")) || !klstricmp(curCommand, _T("/nokeyhooks")) || !klstricmp(curCommand, _T("/nokeybhook")) || !klstricmp(curCommand, _T("/nokeybhooks"))) { gpConEmu->DisableKeybHooks = true; } else if (!klstricmp(curCommand, _T("/nocloseconfirm"))) { gpConEmu->DisableCloseConfirm = true; } else if (!klstricmp(curCommand, _T("/nomacro"))) { gpConEmu->DisableAllMacro = true; } else if (!klstricmp(curCommand, _T("/nohotkey")) || !klstricmp(curCommand, _T("/nohotkeys"))) { gpConEmu->DisableAllHotkeys = true; } else if (!klstricmp(curCommand, _T("/nodeftrm")) || !klstricmp(curCommand, _T("/nodefterm"))) { gpConEmu->DisableSetDefTerm = true; } else if (!klstricmp(curCommand, _T("/noregfont")) || !klstricmp(curCommand, _T("/noregfonts"))) { gpConEmu->DisableRegisterFonts = true; } else if (!klstricmp(curCommand, _T("/inside")) || !lstrcmpni(curCommand, _T("/inside="), 8)) { bool bRunAsAdmin = isPressed(VK_SHIFT); bool bSyncDir = false; LPCWSTR pszSyncFmt = NULL; gpConEmu->mb_ConEmuHere = true; gpConEmu->StoreWorkDir(); if (curCommand[7] == _T('=')) { bSyncDir = true; pszSyncFmt = curCommand+8; // \eCD /d %1 - \e - ESC, \b - BS, \n - ENTER, %1 - "dir", %2 - "bash dir" } CConEmuInside::InitInside(bRunAsAdmin, bSyncDir, pszSyncFmt, 0, NULL); } else if (!klstricmp(curCommand, _T("/insidepid"))) { NeedNextArg(); bool bRunAsAdmin = isPressed(VK_SHIFT); wchar_t* pszEnd; // Здесь указывается PID, в который нужно внедриться. DWORD nInsideParentPID = wcstol(curCommand, &pszEnd, 10); if (nInsideParentPID) { CConEmuInside::InitInside(bRunAsAdmin, false, NULL, nInsideParentPID, NULL); } } else if (!klstricmp(curCommand, _T("/insidewnd"))) { NeedNextArg(); if (curCommand[0] == L'0' && (curCommand[1] == L'x' || curCommand[1] == L'X')) curCommand += 2; else if (curCommand[0] == L'x' || curCommand[0] == L'X') curCommand ++; bool bRunAsAdmin = isPressed(VK_SHIFT); wchar_t* pszEnd; // Здесь указывается HWND, в котором нужно создаваться. HWND hParent = (HWND)(DWORD_PTR)wcstoul(curCommand, &pszEnd, 16); if (hParent && IsWindow(hParent)) { CConEmuInside::InitInside(bRunAsAdmin, false, NULL, 0, hParent); } } else if (!klstricmp(curCommand, _T("/icon"))) { NeedNextArg(); if (!gpConEmu->opt.IconPrm.Exists && *curCommand) { gpConEmu->opt.IconPrm = true; gpConEmu->mps_IconPath = ExpandEnvStr(curCommand); } } else if (!klstricmp(curCommand, _T("/dir"))) { NeedNextArg(); if (*curCommand) { // Например, "%USERPROFILE%" wchar_t* pszExpand = NULL; if (wcschr(curCommand, L'%') && ((pszExpand = ExpandEnvStr(curCommand)) != NULL)) { gpConEmu->StoreWorkDir(pszExpand); SafeFree(pszExpand); } else { gpConEmu->StoreWorkDir(curCommand); } } } else if (!klstricmp(curCommand, _T("/updatejumplist"))) { // Copy current Task list to Win7 Jump list (Taskbar icon) gpConEmu->mb_UpdateJumpListOnStartup = true; } else if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0") || !klstricmp(curCommand, L"/log1") || !klstricmp(curCommand, L"/log2") || !klstricmp(curCommand, L"/log3") || !klstricmp(curCommand, L"/log4")) { if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0")) gpConEmu->opt.AdvLogging.SetInt(1); else gpConEmu->opt.AdvLogging.SetInt((BYTE)(curCommand[4] - L'0')); // 1..4 // Do create logging service DEBUGSTRSTARTUP(L"Creating log file"); gpConEmu->CreateLog(); } else if (!klstricmp(curCommand, _T("/single")) || !klstricmp(curCommand, _T("/reuse"))) { // "/reuse" switch to be remastered gpConEmu->AppendExtraArgs(curCommand); gpSetCls->SingleInstanceArg = sgl_Enabled; } else if (!klstricmp(curCommand, _T("/nosingle"))) { gpConEmu->AppendExtraArgs(curCommand); gpSetCls->SingleInstanceArg = sgl_Disabled; } else if (!klstricmp(curCommand, _T("/DesktopMode"))) { gpConEmu->opt.DesktopMode = true; } else if (!klstricmp(curCommand, _T("/quake")) || !klstricmp(curCommand, _T("/quakeauto")) || !klstricmp(curCommand, _T("/noquake"))) { if (!klstricmp(curCommand, _T("/quake"))) gpConEmu->opt.QuakeMode = 1; else if (!klstricmp(curCommand, _T("/quakeauto"))) gpConEmu->opt.QuakeMode = 2; else { gpConEmu->opt.QuakeMode = 0; if (gpSetCls->SingleInstanceArg == sgl_Default) gpSetCls->SingleInstanceArg = sgl_Disabled; } } else if (!klstricmp(curCommand, _T("/showhide")) || !klstricmp(curCommand, _T("/showhideTSA"))) { gpSetCls->SingleInstanceArg = sgl_Enabled; gpSetCls->SingleInstanceShowHide = !klstricmp(curCommand, _T("/showhide")) ? sih_ShowMinimize : sih_ShowHideTSA; } else if (!klstricmp(curCommand, _T("/reset")) || !klstricmp(curCommand, _T("/resetdefault")) || !klstricmp(curCommand, _T("/basic"))) { gpConEmu->opt.ResetSettings = true; if (!klstricmp(curCommand, _T("/resetdefault"))) { gpSetCls->isFastSetupDisabled = true; } else if (!klstricmp(curCommand, _T("/basic"))) { gpSetCls->isFastSetupDisabled = true; gpSetCls->isResetBasicSettings = true; } } else if (!klstricmp(curCommand, _T("/nocascade")) || !klstricmp(curCommand, _T("/dontcascade"))) { gpConEmu->AppendExtraArgs(curCommand); gpSetCls->isDontCascade = true; } else if (!klstricmp(curCommand, _T("/WndX")) || !klstricmp(curCommand, _T("/WndY")) || !klstricmp(curCommand, _T("/WndW")) || !klstricmp(curCommand, _T("/WndWidth")) || !klstricmp(curCommand, _T("/WndH")) || !klstricmp(curCommand, _T("/WndHeight"))) { TCHAR ch = curCommand[4]; CharUpperBuff(&ch, 1); CESwitch psz(sw_Str); bool bParm = false; if (!GetCfgParm(cmdLineRest, bParm, psz, 32)) { goto wrap; } gpConEmu->opt.SizePosPrm = true; // Direct X/Y implies /nocascade if (ch == _T('X') || ch == _T('Y')) { // TODO: isDontCascade must be in our opt struct !!! gpSetCls->isDontCascade = true; } switch (ch) { case _T('X'): gpConEmu->opt.sWndX.SetStr(psz.Str, sw_Str); break; case _T('Y'): gpConEmu->opt.sWndY.SetStr(psz.Str, sw_Str); break; case _T('W'): gpConEmu->opt.sWndW.SetStr(psz.Str, sw_Str); break; case _T('H'): gpConEmu->opt.sWndH.SetStr(psz.Str, sw_Str); break; } } else if (!klstricmp(curCommand, _T("/Monitor"))) { CESwitch psz(sw_Str); bool bParm = false; if (!GetCfgParm(cmdLineRest, bParm, psz, 64)) { goto wrap; } if ((gpConEmu->opt.Monitor.Mon = MonitorFromParam(psz.Str)) != NULL) { gpConEmu->opt.Monitor.Exists = true; gpConEmu->opt.Monitor.Type = sw_Int; gpStartEnv->hStartMon = gpConEmu->opt.Monitor.Mon; } } else if (!klstricmp(curCommand, _T("/Buffer")) || !klstricmp(curCommand, _T("/BufferHeight"))) { NeedNextArg(); if (!gpConEmu->opt.BufferHeightVal.Exists) { gpConEmu->opt.BufferHeightVal.SetInt(curCommand); if (gpConEmu->opt.BufferHeightVal.GetInt() < 0) { //setParent = true; -- Maximus5 - нефиг, все ручками gpConEmu->opt.BufferHeightVal = -gpConEmu->opt.BufferHeightVal.GetInt(); } if (gpConEmu->opt.BufferHeightVal.GetInt() < LONGOUTPUTHEIGHT_MIN) gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MIN; else if (gpConEmu->opt.BufferHeightVal.GetInt() > LONGOUTPUTHEIGHT_MAX) gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MAX; } } else if (!klstricmp(curCommand, _T("/Config"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ConfigVal, 127)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/Palette"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.PaletteVal, MAX_PATH)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/LoadRegistry"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.ForceUseRegistryPrm = true; } else if (!klstricmp(curCommand, _T("/LoadCfgFile")) || !klstricmp(curCommand, _T("/LoadXmlFile"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.LoadCfgFile, MAX_PATH, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/SaveCfgFile")) || !klstricmp(curCommand, _T("/SaveXmlFile"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.SaveCfgFile, MAX_PATH, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/GuiMacro"))) { // -- выполняется только последний if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ExecGuiMacro, 0x8000, false)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/UpdateSrcSet"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.UpdateSrcSet, MAX_PATH*4, false)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/AnsiLog"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.AnsiLogPath, MAX_PATH-40, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/SetDefTerm"))) { gpConEmu->opt.SetUpDefaultTerminal = true; } else if (!klstricmp(curCommand, _T("/ZoneId"))) { gpConEmu->opt.FixZoneId = true; } else if (!klstricmp(curCommand, _T("/Exit"))) { gpConEmu->opt.ExitAfterActionPrm = true; } else if (!klstricmp(curCommand, _T("/QuitOnClose"))) { gpConEmu->mb_ForceQuitOnClose = true; } else if (!klstricmp(curCommand, _T("/Title"))) { bool bOk = false; CESwitch pszTitle(sw_Str); if (!GetCfgParm(cmdLineRest, bOk, pszTitle, 127)) { goto wrap; } gpConEmu->SetTitleTemplate(pszTitle.GetStr()); } else if (!klstricmp(curCommand, _T("/FindBugMode"))) { gpConEmu->mb_FindBugMode = true; } else if (!klstricmp(curCommand, _T("/debug")) || !klstricmp(curCommand, _T("/debugw")) || !klstricmp(curCommand, _T("/debugi"))) { // These switches were already processed } else if (!klstricmp(curCommand, _T("/?")) || !klstricmp(curCommand, _T("/h")) || !klstricmp(curCommand, _T("/help"))) { if (gpLng) gpLng->Reload(); ConEmuAbout::OnInfo_About(); iResult = -1; goto wrap; } // Final `-cmd ...` or `-cmdlist ...` else if ( !klstricmp(curCommand, _T("/cmd")) || !klstricmp(curCommand, _T("/cmdlist")) ) { if (opt.cfgSwitches.ms_Val) { _ASSERTE(pszArgStart>pszCopyToEnvStart); _ASSERTE((INT_PTR)(pszArgStart - pszCopyToEnvStart) <= opt.cfgSwitches.GetLen()); opt.cfgSwitches.ms_Val[pszArgStart - pszCopyToEnvStart] = 0; } opt.runCommand.Set(SkipNonPrintable(cmdLineRest)); opt.isScript = (klstricmp(curCommand, L"/cmdlist") == 0); break; } else { // Show error on unknown switch psUnknown = pszArgStart; break; } } // (*curCommand == L'/') // Avoid assertions in NextArg szArg.Empty(); szNext.Empty(); } // while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0) } // Processing loop end if (psUnknown) { DEBUGSTRSTARTUP(L"Unknown switch, exiting!"); if (gpSet->isLogging()) { // For direct logging we do not use lng resources CEStr lsLog(L"\r\n", L"Unknown switch specified: ", psUnknown, L"\r\n\r\n"); gpConEmu->LogString(lsLog, false, false); } CEStr szNewConWarn; LPCWSTR pszTestSwitch = (psUnknown[0] == L'-' || psUnknown[0] == L'/') ? ((psUnknown[1] == L'-' || psUnknown[1] == L'/') ? (psUnknown+2) : (psUnknown+1)) : psUnknown; if ((lstrcmpni(pszTestSwitch, L"new_console", 11) == 0) || (lstrcmpni(pszTestSwitch, L"cur_console", 11) == 0)) { szNewConWarn = lstrmerge(L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch4/*"Switch -new_console must be specified *after* /cmd or /cmdlist"*/) ); } CEStr lsMsg( CLngRc::getRsrc(lng_UnknownSwitch1/*"Unknown switch specified:"*/), L"\r\n\r\n", psUnknown, szNewConWarn, L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch2/*"Visit website to get thorough switches description:"*/), L"\r\n" CEGUIARGSPAGE L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch3/*"Or run ‘ConEmu.exe -?’ to get the brief."*/) ); MBoxA(lsMsg); goto wrap; } // Set "ConEmuArgs" and "ConEmuArgs2" ProcessConEmuArgsVar(); // Continue normal startup bRc = true; wrap: return bRc; }
bool SettingsXML::OpenKey(const wchar_t *regPath, uint access, BOOL abSilent /*= FALSE*/) { _ASSERTE(!gpConEmu->IsResetBasicSettings() || ((access & KEY_WRITE)!=KEY_WRITE)); bool lbRc = false; HRESULT hr = S_OK; wchar_t szErr[512]; szErr[0] = 0; wchar_t szName[MAX_PATH]; const wchar_t* psz = NULL; VARIANT_BOOL bSuccess; IXMLDOMParseError* pErr = NULL; //IXMLDOMNodeList* pList = NULL; IXMLDOMNode* pKey = NULL; IXMLDOMNode* pChild = NULL; VARIANT vt; VariantInit(&vt); bool bAllowCreate = (access & KEY_WRITE) == KEY_WRITE; CloseKey(); // на всякий if (!regPath || !*regPath) { return false; } HANDLE hFile = NULL; DWORD dwAccess = GENERIC_READ; if ((access & KEY_WRITE) == KEY_WRITE) dwAccess |= GENERIC_WRITE; LPCWSTR pszXmlFile; if (m_Storage.pszFile && *m_Storage.pszFile) { pszXmlFile = m_Storage.pszFile; } else { _ASSERTE(m_Storage.pszFile && *m_Storage.pszFile); m_Storage.pszFile = pszXmlFile = gpConEmu->ConEmuXml(); } if (!pszXmlFile || !*pszXmlFile) { return false; } hFile = CreateFile(pszXmlFile, dwAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); // XML-файл отсутсвует if (hFile == INVALID_HANDLE_VALUE) { return false; } else { BY_HANDLE_FILE_INFORMATION bfi = {0}; if (GetFileInformationByHandle(hFile, &bfi)) mb_Empty = (bfi.nFileSizeHigh == 0 && bfi.nFileSizeLow == 0); CloseHandle(hFile); hFile = NULL; if (mb_Empty && bAllowCreate) { hFile = CreateFile(pszXmlFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { LPCSTR pszDefault = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<key name=\"Software\">\r\n\t<key name=\"ConEmu\">\r\n\t</key>\r\n</key>\r\n"; DWORD nLen = lstrlenA(pszDefault); WriteFile(hFile, pszDefault, nLen, &nLen, NULL); CloseHandle(hFile); } hFile = NULL; } } if (mb_Empty && !bAllowCreate) return false; SAFETRY { _ASSERTE(mp_File == NULL); mp_File = CreateDomDocument(szErr, countof(szErr)); if (FAILED(hr) || !mp_File) { //Ошибка уже в szErr //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"Can't create IID_IXMLDOMDocument!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } hr = mp_File->put_preserveWhiteSpace(VARIANT_TRUE); hr = mp_File->put_async(VARIANT_FALSE); // Загрузить xml-ку bSuccess = VARIANT_FALSE; vt.vt = VT_BSTR; vt.bstrVal = ::SysAllocString(pszXmlFile); hr = mp_File->load(vt, &bSuccess); VariantClear(&vt); if (hr == S_FALSE) { mb_Empty = true; // Файл пуст (может только заголовок?) } else if (FAILED(hr) || !bSuccess) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"Failed to load ConEmu.xml!\nHR=0x%08X\n", (DWORD)hr); hr = mp_File->get_parseError(&pErr); if (pErr) { long errorCode = 0; // Contains the error code of the last parse error. Read-only. long line = 0; // Specifies the line number that contains the error. Read-only. long linepos = 0; // Contains the character position within the line where the error occurred. Read-only. hr = pErr->get_errorCode(&errorCode); hr = pErr->get_line(&line); hr = pErr->get_linepos(&linepos); wsprintf(szErr+_tcslen(szErr), L"XmlErrCode=%i, Line=%i, Pos=%i", errorCode, line, linepos); } goto wrap; } hr = mp_File->QueryInterface(IID_IXMLDOMNode, (void **)&pKey); if (FAILED(hr)) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Root node not found!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } mi_Level = 0; while(*regPath) { // Получить следующий токен psz = wcschr(regPath, L'\\'); if (!psz) psz = regPath + _tcslen(regPath); lstrcpyn(szName, regPath, psz-regPath+1); // Найти в структуре XML pChild = FindItem(pKey, L"key", szName, bAllowCreate); pKey->Release(); pKey = pChild; pChild = NULL; mi_Level++; if (!pKey) { if (bAllowCreate) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Can't create key <%s>!", szName); } else { //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: key <%s> not found!", szName); szErr[0] = 0; // ошибку не показывать - настройки по умолчанию } goto wrap; } if (*psz == L'\\') { regPath = psz + 1; } else { break; } } // Нашли, запомнили mp_Key = pKey; pKey = NULL; if (mp_Key) { SYSTEMTIME st; wchar_t szTime[32]; GetLocalTime(&st); _wsprintf(szTime, SKIPLEN(countof(szTime)) L"%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); SetAttr(mp_Key, L"modified", szTime); SetAttr(mp_Key, L"build", gpConEmu->ms_ConEmuBuild); } lbRc = true; } SAFECATCH { lstrcpy(szErr, L"Exception in SettingsXML::OpenKey"); lbRc = false; } wrap: if (pErr) { pErr->Release(); pErr = NULL; } if (pChild) { pChild->Release(); pChild = NULL; } if (pKey) { pKey->Release(); pKey = NULL; } if (!lbRc && szErr[0] && !abSilent) { MBoxA(szErr); } return lbRc; }