HRESULT STDMETHODCALLTYPE CDriveContextMenu::InvokeCommand(/* [in] */ __in CMINVOKECOMMANDINFO *pici) { WINCDEMU_LOG_LINE(L"CDriveContextMenu::InvokeCommand()"); if (!pici) return E_NOTIMPL; extern HINSTANCE g_hModule; TCHAR tszPath[MAX_PATH]; GetModuleFileName(g_hModule, tszPath, _countof(tszPath)); BazisLib::String path = String::sFormat(L"%s\\%s", BazisLib::Path::GetDirectoryName(BazisLib::Path::GetDirectoryName(String(tszPath))).c_str(), VMNT_EXE_W); switch ((int)pici->lpVerb) { case IDM_CREATEISO: ShellExecute(pici->hwnd, _T("open"), path.c_str(), String::sFormat(L"/createiso %s", m_FileName.c_str()).c_str(), NULL, pici->nShow); break; case IDM_CHANGEIMAGE: ShellExecute(pici->hwnd, _T("open"), path.c_str(), String::sFormat(L"/remount:%c", m_FileName[0]).c_str(), NULL, pici->nShow); break; case IDM_BUILDISO: ShellExecute(pici->hwnd, _T("open"), path.c_str(), String::sFormat(L"/isofromfolder \"%s\"", m_FileName.c_str()).c_str(), NULL, pici->nShow); break; default: return E_FAIL; } return S_OK; }
bool LocalizableStringManager::ProduceHeaderFile( const BazisLib::String &fp ) { File file(fp, FileModes::CreateOrTruncateRW); if (!file.Valid()) { _tprintf(_T("ERROR: cannot open %s for writing\n"), fp.c_str()); return false; } file.WriteLine(DynamicStringA("#pragma once\r\n//Generated by BazisLib STRGEN.EXE, http://bazislib.sysprogs.org/\r\n\r\n#include<bzshlp/Win32/i18n.h>\r\n#ifndef BAZISLIB_FIRST_LOCALIZABLE_STRING_ID\r\n#define BAZISLIB_FIRST_LOCALIZABLE_STRING_ID 0x1000\r\n#endif\r\n")); unsigned id = 0; DynamicStringA definitionLine; unsigned maxIdLen = 0; for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) if (pair.first.length() > maxIdLen) maxIdLen = pair.first.length(); DynamicStringA maxSpacing; maxSpacing.insert(0, maxIdLen, ' '); for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) { const char *pSpacing = maxSpacing.c_str() + pair.first.length(); definitionLine.Format("#define %s %s(BAZISLIB_FIRST_LOCALIZABLE_STRING_ID + 0x%04X)", StringToANSIString(pair.first).c_str(), pSpacing, id++); file.WriteLine(definitionLine); } definitionLine.Format("\r\n#define BAZISLIB_LAST_LOCALIZABLE_STRING_ID \t(BAZISLIB_FIRST_LOCALIZABLE_STRING_ID + 0x%04X)", id - 1); file.WriteLine(definitionLine); return true; }
void DeleteFiles(BazisLib::String path) { TCHAR tsz[MAX_PATH] = {0,}; GetModuleFileName(GetModuleHandle(NULL), tsz, sizeof(tsz)/sizeof(tsz[0])); TCHAR *p = _tcsrchr(tsz, '\\'); if (!p) return; p[0] = 0; if (path.empty()) path = tsz; RemoveTreeRecursive((Path::Combine(path, _T("x86"))).c_str()); RemoveTreeRecursive((Path::Combine(path, _T("x64"))).c_str()); RemoveTreeRecursive((Path::Combine(path, _T("langfiles"))).c_str()); File::Delete(Path::Combine(path, _T("vmnt.exe"))); File::Delete(Path::Combine(path, _T("vmnt64.exe"))); File::Delete(Path::Combine(path, _T("batchmnt.exe"))); File::Delete(Path::Combine(path, _T("batchmnt64.exe"))); File::Delete(Path::Combine(path, _T("BazisVirtualCD.inf"))); File::Delete(Path::Combine(path, _T("VirtDiskBus.inf"))); File::Delete(Path::Combine(path, _T("BazisVirtualCDBus.inf"))); File::Delete(Path::Combine(path, _T("BazisVirtualCD.cat"))); File::Delete(Path::Combine(path, _T("VirtDiskBus.cat"))); File::Delete(Path::Combine(path, _T("BazisVirtualCDBus.cat"))); File::Delete(Path::Combine(path, _T("uninstall.exe"))); File::Delete(Path::Combine(path, _T("uninstall64.exe"))); Directory::Remove(path); p[0] = '\\'; MoveFileEx(tsz, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); }
HRESULT StartRevertingCurrentVMToLastSnapshot() { TCHAR tszDll[MAX_PATH]; GetModuleFileName(g_hThisDll, tszDll, _countof(tszDll)); BazisLib::String machineID = VBoxCmdLineToMachineID(GetCommandLineW()); BazisLib::Win32::Process process(BazisLib::String::sFormat(L"rundll32 \"%s\",VMSnapshotRevertingEntry --startvm %s", tszDll, machineID.c_str()).c_str(), (WORD)SW_SHOW); return S_OK; }
unsigned SessionNameFromVMCmdLineW(const RemoteProcessInfo &info, wchar_t *pName, size_t MaxNameLength) { int argc = 0; LPWSTR *pArgs = CommandLineToArgvW(info.CommandLine.c_str(), &argc); if (!pArgs) return 0; BazisLib::String exeName; if (argc && pArgs[0]) exeName = pArgs[0]; LocalFree(pArgs); pArgs = NULL; if (wcsstr(exeName.c_str(), L"vmware-vmx.exe") || wcsstr(exeName.c_str(), L"vmware-vmx-debug.exe") || wcsstr(exeName.c_str(), L"vmware-vmx-stats.exe")) return SessionNameFromVMWareCmdLineW(info.CommandLine.c_str(), pName, MaxNameLength); else if (wcsstr(exeName.c_str(), L"VirtualBox.exe")) return VBoxCmdLineToVMNameW(info, pName, MaxNameLength); else return 0; }
BazisLib::String LocalizableStringManager::FormatStringASCString( const BazisLib::TempString &str ) { BazisLib::String result; result.reserve(str.length()); for (size_t i = 0; i < str.length(); i++) { if (str[i] == '\\') result.append(_T("\\\\")); else if (str[i] == '\'') result.append(_T("\\\'")); else if (str[i] == '\"') result.append(_T("\\\"")); else if (str[i] == '\t') result.append(_T("\\\t")); else if (str[i] == '\r') result.append(_T("\\\r")); else if (str[i] == '\n') result.append(_T("\\\n")); else result.append(1, str[i]); } return result; }
bool LocalizableStringManager::ProduceIDTableFile( const BazisLib::String &fp, const String &HeaderFileName ) { File file(fp, FileModes::CreateOrTruncateRW); if (!file.Valid()) { _tprintf(_T("ERROR: cannot open %s for writing\n"), fp.c_str()); return false; } DynamicStringA definitionLine; file.WriteLine(DynamicStringA("#include \"stdafx.h\"\r\n#include <bzshlp/Win32/i18n.h>")); definitionLine.Format("#include \"%s\"", StringToANSIString(HeaderFileName).c_str()); file.WriteLine(definitionLine); file.WriteLine(DynamicStringA("//Generated by BazisLib STRGEN.EXE, http://bazislib.sysprogs.org/\r\n")); file.WriteLine(DynamicStringA("BazisLib::StringIDRecord g_StringIDs[] = {")); unsigned id = 0; unsigned maxIdLen = 0; for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) if (pair.first.length() > maxIdLen) maxIdLen = pair.first.length(); DynamicStringA maxSpacing; maxSpacing.insert(0, maxIdLen, ' '); for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) { const char *pSpacing = maxSpacing.c_str() + pair.first.length(); definitionLine.Format("\t{%s%s, _T(\"%s\")},", StringToANSIString(pair.first).c_str(), pSpacing, StringToANSIString(pair.first).c_str()); file.WriteLine(definitionLine); } file.WriteLine(DynamicStringA("\t{0, NULL},\r\n};")); return true; }
bool LocalizableStringManager::ProduceLanguageFile( const BazisLib::String &fp ) { File file(fp, FileModes::CreateOrTruncateRW); if (!file.Valid()) { _tprintf(_T("ERROR: cannot open %s for writing\n"), fp.c_str()); return false; } #ifdef UNICODE unsigned short unicodeHeader = 0xFEFF; file.Write(&unicodeHeader, sizeof(unicodeHeader)); #endif //1033 == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) file.WriteLine(DynamicString(_T("; Generated by BazisLib STRGEN.EXE, http://bazislib.sysprogs.org/\r\n; Syntax: <ID> <spaces or tabs> <value>\r\n; <value> should be in C/C++ format (\\r, \\n, \\t, \\\", etc.) \r\n; Strings starting with '; ' will be ignored\r\n; WARNING! This file should always be UNICODE!\r\n"))); file.WriteLine(DynamicString(_T("[settings]\r\nLanguage English\r\nLANGID 1033\r\nLanguageEng English\r\nTranslator SysProgs\r\nE-Mail [email protected]\r\n"))); file.WriteLine(DynamicString(_T("[strings]"))); unsigned maxIdLen = 0; for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) if (pair.first.length() > maxIdLen) maxIdLen = pair.first.length(); DynamicString definitionLine; DynamicString maxSpacing; maxSpacing.insert(0, maxIdLen, ' '); for each(const std::map<BazisLib::String, StringRecord>::value_type &pair in m_Strings) { const TCHAR *pSpacing = maxSpacing.c_str() + pair.first.length(); definitionLine.Format(_T("%s%s %s"), pair.first.c_str(), pSpacing, pair.second.Value.c_str()); file.WriteLine(definitionLine); } return true; }
int AppMain() { int argc; LPCWSTR lpCmdLine = GetCommandLineW(); LPWSTR *ppArgv = CommandLineToArgvW(lpCmdLine, &argc); LPCWSTR lpDiskPath = NULL; bool ShowSettingsDialog = false, ForceMountOptions = false, AdminModeOnNetworkShare = false; bool bDisableUAC = false; char DriveLetterToRemount = 0; BazisLib::String tmpString; for (int i = 1; i < argc; i++) { if (ppArgv[i][0] != '/') { if (!lpDiskPath) lpDiskPath = ppArgv[i]; } else { if (!_wcsicmp(ppArgv[i], L"/settings")) ShowSettingsDialog = true; else if (!_wcsicmp(ppArgv[i], L"/ltrselect")) ForceMountOptions = true; else if (!_wcsicmp(ppArgv[i], L"/uac_on_network_share")) AdminModeOnNetworkShare = true; else if (!_wcsicmp(ppArgv[i], L"/uacdisable")) bDisableUAC = true; else if (!_wcsicmp(ppArgv[i], L"/createiso") || !_wcsicmp(ppArgv[i], L"/isofromfolder")) { if (argc < (i + 2)) { MessageBox(HWND_DESKTOP, _TR(IDS_BADCMDLINE, "Invalid command line!"), NULL, MB_ICONERROR); return 1; } ActionStatus st; if (!_wcsicmp(ppArgv[i], L"/isofromfolder")) { wchar_t *pwszFolder = ppArgv[i + 1]; if (pwszFolder[0] && pwszFolder[wcslen(pwszFolder) - 1] == '\"') pwszFolder[wcslen(pwszFolder) - 1] = '\\'; st = BuildISOFromFolder(pwszFolder); } else st = CreateISOFile(ppArgv[i + 1]); if (!st.Successful() && st.GetErrorCode() != OperationAborted) MessageBox(HWND_DESKTOP, st.GetMostInformativeText().c_str(), NULL, MB_ICONERROR); return !st.Successful(); } else if (!_wcsnicmp(ppArgv[i], L"/remount:", 9)) DriveLetterToRemount = (char)ppArgv[i][9]; } } if (bDisableUAC) { RegistryKey driverParametersKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\BazisVirtualCDBus\\Parameters")); int prevVal = driverParametersKey[_T("GrantAccessToEveryone")]; int newVal = 1; driverParametersKey[_T("GrantAccessToEveryone")] = newVal; if (prevVal != newVal) VirtualCDClient::RestartDriver(); return 0; } if (GetKeyState(VK_SHIFT) & (1 << 31)) ForceMountOptions = true; if (!lpDiskPath && DriveLetterToRemount) { const TCHAR *pwszFilter = _TR(IDS_ISOFILTER, "ISO images (*.iso)|*.iso|All files (*.*)|*.*"); TCHAR tszFilter[128] = { 0, }; _tcsncpy(tszFilter, pwszFilter, _countof(tszFilter) - 1); for (size_t i = 0; i < _countof(tszFilter); i++) if (tszFilter[i] == '|') tszFilter[i] = '\0'; CFileDialog dlg(true, _T("iso"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, tszFilter); dlg.m_ofn.lpstrTitle = _TR(IDS_MOUNTIMAGE, "Mount a disc image"); if (dlg.DoModal() != IDOK) return 1; tmpString.assign(dlg.m_szFileName); lpDiskPath = tmpString.c_str(); } if ((argc < 2) || !ppArgv || !lpDiskPath || ShowSettingsDialog) { return ::ShowSettingsDialog(); } MMCProfile detectedProfile = mpInvalid; bool bFileOnNetworkShare = false; { TCHAR tszFullPath[MAX_PATH] = {0,}; GetFullPathName(lpDiskPath, __countof(tszFullPath), tszFullPath, NULL); TCHAR tszRoot[4] = {tszFullPath[0], ':', '\\', 0}; if (GetDriveType(tszRoot) == DRIVE_REMOTE) bFileOnNetworkShare = true; ImageFormatDatabase imageFormatDB; ManagedPointer<AIParsedCDImage> pImage = imageFormatDB.OpenCDImage(ManagedPointer<AIFile>(new ACFile(tszFullPath, FileModes::OpenReadOnly.ShareAll())), tszFullPath); if (!pImage) { if (AdminModeOnNetworkShare) MessageBox(HWND_DESKTOP, _TR(IDS_UACNETWORKWARNING, "Cannot open image file. To mount images from network drives, go to WinCDEmu settings and allow mounting drives without administrator privileges."), NULL, MB_ICONERROR); else MessageBox(HWND_DESKTOP, _TR(ISD_CORRUPTIMAGE, "Unknown or corrupt image file!"), NULL, MB_ICONERROR); return 1; } if (pImage->GetTrackCount() != 1) detectedProfile = mpCdrom; else { UDFAnalysisResult result = AnalyzeUDFImage(pImage); if (!result.isUDF) detectedProfile = mpInvalid; else if (result.foundBDMV) detectedProfile = mpBDRSequentialWritable; else if (result.foundVIDEO_TS) detectedProfile = mpDvdRecordable; } /*if ((detectedProfile == mpCdrom) || (detectedProfile == mpInvalid)) { if (pImage->GetSectorCount() >= ((10LL * 1024LL * 1024LL * 1024LL / 2048))) detectedProfile = mpBDRSequentialWritable; else if (pImage->GetSectorCount() >= ((1LL * 1024LL * 1024LL * 1024LL / 2048))) detectedProfile = mpDvdRecordable; }*/ } wchar_t wszKernelPath[512]; if (!VirtualCDClient::Win32FileNameToKernelFileName(lpDiskPath, wszKernelPath, __countof(wszKernelPath))) { MessageBox(HWND_DESKTOP, _TR(IDS_BADIMGFN, "Invalid image file name!"), NULL, MB_ICONERROR); return 1; } bool bDiskConnected = false; ActionStatus status; { VirtualCDClient clt(&status); if (!clt.Valid()) { if (status.GetErrorCode() == BazisLib::AccessDenied) { if (bFileOnNetworkShare) return (int)CUACInvokerDialog((String(GetCommandLine()) + L" /uac_on_network_share").c_str()).DoModal(); else return (int)CUACInvokerDialog(GetCommandLine()).DoModal(); } MessageBox(HWND_DESKTOP, _TR(IDS_NOBUS, "Cannot connect to BazisVirtualCD.sys!"), NULL, MB_ICONERROR); return 1; } bDiskConnected = clt.IsDiskConnected(wszKernelPath); } if (DriveLetterToRemount != 0) { if (bDiskConnected) { MessageBox(HWND_DESKTOP, String::sFormat(_TR(IDS_ALREADYMOUNTED, "%s is already mounted."), lpDiskPath).c_str(), NULL, MB_ICONERROR); status = MAKE_STATUS(OperationAborted); } else status = VirtualCDClient::MountImageOnExistingDrive(wszKernelPath, DriveLetterToRemount); } else if (!bDiskConnected) { RegistryParams params; char driveLetter = 0; bool disableAutorun = false, persistent = false; if ((params.DriveLetterPolicy == drvlAskEveryTime) || ForceMountOptions) { CLetterSelectionDialog dlg(ForceMountOptions, detectedProfile); if (dlg.DoModal() != IDOK) return 3; driveLetter = dlg.GetDriveLetter(); disableAutorun = dlg.IsAutorunDisabled(); persistent = dlg.IsPersistent(); detectedProfile = dlg.GetMMCProfile(); #ifdef WINCDEMU_DEBUG_LOGGING_SUPPORT if (dlg.IsDebugLoggingEnabled()) { FilePath fpDir = FilePath::GetSpecialDirectoryLocation(SpecialDirFromCSIDL(CSIDL_APPDATA)).PlusPath(L"WinCDEmu.debug"); bool cancel = false; if (!Directory::Exists(fpDir)) cancel = MessageBox(0, String::sFormat(L"WinCDEmu will create a directory for debugging log files (%s). If you encounter problems using WinCDEmu, please submit the most recent log file to [email protected]. Continue?", fpDir.c_str()).c_str() , L"Information", MB_OKCANCEL | MB_ICONINFORMATION) != IDOK; if (!cancel) { CreateDirectory(fpDir.c_str(), NULL); wchar_t wszKernelDirPath[512]; if (VirtualCDClient::Win32FileNameToKernelFileName(fpDir.c_str(), wszKernelDirPath, __countof(wszKernelDirPath))) VirtualCDClient().SetDebugLogDirectory(wszKernelDirPath); } } else VirtualCDClient().SetDebugLogDirectory(NULL); #endif } else { disableAutorun = params.DisableAutorun; persistent = params.PersistentDefault; if (detectedProfile == mpInvalid) detectedProfile = (MMCProfile)params.DefaultMMCProfile; if (params.DriveLetterPolicy == drvlStartingFromGiven) { DWORD dwMask = GetLogicalDrives(); unsigned char ch = 'A' + params.StartingDriveLetterIndex; for (unsigned i = (1 << (ch - 'A')); ch <= 'Z'; ch++, i <<= 1) if (!(dwMask & i)) { driveLetter = ch; break; } } } status = VirtualCDClient().ConnectDisk(wszKernelPath, driveLetter, 0, disableAutorun, persistent, AutorunErrorHandler, detectedProfile); } else status = VirtualCDClient().DisconnectDisk(wszKernelPath); if (!status.Successful()) { if (status.GetErrorCode() != OperationAborted) MessageBox(HWND_DESKTOP, status.GetMostInformativeText().c_str(), NULL, MB_ICONERROR); return 1; } return 0; }
static HRESULT DoRevertVMToSnapshot() { BazisLib::String rawMachineID = VBoxCmdLineToMachineID(GetCommandLineW()); if (rawMachineID.empty()) return E_FAIL; CComBSTR machineID = rawMachineID.c_str(); CComPtr<IVirtualBox> pVirtualBox; HRESULT hR = pVirtualBox.CoCreateInstance(CLSID_VirtualBox, NULL, CLSCTX_LOCAL_SERVER); if (!SUCCEEDED(hR)) return hR; CComPtr<IMachine> pMachine; hR = pVirtualBox->FindMachine(machineID, &pMachine); if (!SUCCEEDED(hR)) return hR; CComPtr<ISession> pSession; hR = pSession.CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER); if (!SUCCEEDED(hR)) return hR; hR = pMachine->LockMachine(pSession, LockType_Shared); if (!SUCCEEDED(hR)) { if (hR == E_FAIL) MessageBox(HWND_DESKTOP, L"Cannot connect to VirtualBox. Ensure that both VirtualBox and Visual Studio are running from the same user account, either both elevated (UAC), or both not.", L"Error", MB_ICONERROR); return hR; } CComPtr<IConsole> pConsole; hR = pSession->get_Console(&pConsole); if (!SUCCEEDED(hR)) return hR; CComPtr<ISnapshot> pSnapshot; hR = pMachine->get_CurrentSnapshot(&pSnapshot); if (!SUCCEEDED(hR)) { pSession->UnlockMachine(); return hR; } CComBSTR snapshotID; hR = pSnapshot->get_Id(&snapshotID); if (!SUCCEEDED(hR)) return hR; CComPtr<IProgress> pProgress; hR = pConsole->PowerDown(&pProgress); if (!SUCCEEDED(hR)) return hR; hR = WaitForCompletion(pProgress); if (!SUCCEEDED(hR)) return hR; pProgress = NULL; pSession->UnlockMachine(); BazisLib::DateTime dtStart = BazisLib::DateTime::Now(); for (;;) { hR = pMachine->LockMachine(pSession, LockType_Shared); if (!SUCCEEDED(hR) && (dtStart.MillisecondsElapsed() >= 10000)) return hR; if (SUCCEEDED(hR)) break; Sleep(100); } pConsole = NULL; hR = pSession->get_Console(&pConsole); if (!SUCCEEDED(hR)) return hR; hR = pConsole->RestoreSnapshot(pSnapshot, &pProgress); if (!SUCCEEDED(hR)) return hR; hR = WaitForCompletion(pProgress); if (!SUCCEEDED(hR)) return hR; pSession->UnlockMachine(); CComBSTR sessionType = L"gui"; pProgress = NULL; hR = pMachine->LaunchVMProcess(pSession, sessionType, NULL, &pProgress); if (!SUCCEEDED(hR)) return hR; hR = WaitForCompletion(pProgress); if (!SUCCEEDED(hR)) return hR; pSession->UnlockMachine(); pProgress = NULL; return S_OK; }
bool LocalizableStringManager::ParseSourceFile( const BazisLib::String &fp ) { ManagedPointer<TextANSIFileReader> pRdr = new TextANSIFileReader(new ACFile(fp, FileModes::OpenReadOnly)); if (!pRdr->Valid()) { _tprintf(_T("ERROR: cannot open %s\n"), fp.c_str()); return false; } _tprintf(_T(" %s\n"), Path::GetFileName(fp).c_str()); bool insideCCommentBlock = false; bool insideStringConstant = false; unsigned lineNum = 0; DynamicString currentDialogID; while (!pRdr->IsEOF()) { size_t LocalizationTokenStart = -1; enum { ltUnknown = 0, ltTR, ltDIALOG, ltDLGITEM, } localizationTokenType; lineNum++; DynamicStringA line = pRdr->ReadLine(); if (line[0] == '#') break; unsigned backslashCount = 0; char prevChar = 0, ch = 0; size_t lastStringStart = -1, lastStringLen = 0; for (size_t i = 0; i < line.length(); i++, prevChar = ch) { //Even amount of backslashes followed by quotation mark toggles string constant flag (outside comment block) //The "/*" and "*/" sequences outside string block change the comment flag. //The "//" sequence skips everything till the end of the string //At the end of each line inside the string block there should be a backslash ch = line[i]; bool isLastChar = (i == (line.length() - 1)); if (insideCCommentBlock) { if ((ch == '/') && (prevChar == '*')) insideCCommentBlock = false; } else //Outside comment block - detect string literals { if (ch == '\\') backslashCount++; else { if (((ch == '\"') || (ch == '\'')) && !(backslashCount % 2)) { if (!insideStringConstant) lastStringStart = i + 1, lastStringLen = 0; else lastStringLen = i - lastStringStart; insideStringConstant = !insideStringConstant; } backslashCount = 0; } if (!insideStringConstant) //Outside comment and string blocks - check for comment start { if ((ch == '*') && (prevChar == '/')) insideCCommentBlock = true; if ((ch == '/') && (prevChar == '/')) break; } else //Inside string block { if (isLastChar && (ch != '\\')) { _tprintf(_T("%s(%d) : error: Unterminated string"), GetFullPath(fp).c_str(), lineNum); return false; } } } //Here, both insideCCommentBlock and insideStringConstant reflect the real file context. So, let's find "_TR()" and LOCALIZE_DIALOG()/LOCALIZE_DLGITEM() if (!insideCCommentBlock && !insideStringConstant) { if (!IsValidCTokenChar(prevChar)) { size_t newTokenStart = -1; size_t remaining = line.length() - i; if ((remaining > 4) && (line.substr(i, 3) == "_TR") && !IsValidCTokenChar(line[i + 3])) newTokenStart = i + 3, localizationTokenType = ltTR; else if ((remaining > 16) && (line.substr(i, 15) == "LOCALIZE_DIALOG") && !IsValidCTokenChar(line[i + 15])) newTokenStart = i + 15, localizationTokenType = ltDIALOG; else if ((remaining > 17) && (line.substr(i, 16) == "LOCALIZE_DLGITEM") && !IsValidCTokenChar(line[i + 16])) newTokenStart = i + 16, localizationTokenType = ltDLGITEM; if (newTokenStart != -1) { if (LocalizationTokenStart != -1) { _tprintf(_T("%s(%d) : error: Localization token used recursively"), GetFullPath(fp).c_str(), lineNum); return false; } LocalizationTokenStart = newTokenStart; lastStringStart = -1; lastStringLen = 0; } } if (ch == '}') currentDialogID.clear(); if ((ch == ')') && (LocalizationTokenStart != -1)) { size_t tokenParamsStart = line.find_first_not_of(" \t()", LocalizationTokenStart); TempStringA tokenParams = line.substr(tokenParamsStart, i - LocalizationTokenStart); if (tokenParams.empty()) { _tprintf(_T("%s(%d) : error: Empty localization macro"), GetFullPath(fp).c_str(), lineNum); return false; } if (localizationTokenType == ltTR) { if ((lastStringStart == -1) || !lastStringLen) { _tprintf(_T("%s(%d) : error: Invalid _TR() statement - default string not found"), GetFullPath(fp).c_str(), lineNum); return false; } DynamicString lastString = ANSIStringToString(line.substr(lastStringStart, lastStringLen)); size_t idEnd = tokenParams.find_first_of(" ,"); DynamicString id = ANSIStringToString(tokenParams.substr(0, (idEnd == -1) ? 0 : idEnd)); if (id.empty()) { _tprintf(_T("%s(%d) : error: Invalid _TR() statement - cannot determine string ID"), GetFullPath(fp).c_str(), lineNum); return false; } const DynamicString &existingValue = m_Strings[id].Value; if (!existingValue.empty() && (existingValue != lastString)) _tprintf(_T("%s(%d) : warning: %s redefined with different value\n"), GetFullPath(fp).c_str(), lineNum, id.c_str()); m_Strings[id].Value = lastString; } else { _FixedSetOfCharsSplitString<2, TempStringA> params(tokenParams, ", \t"); if (params.count() < 2) { _tprintf(_T("%s(%d) : error: Invalid LOCALIZE_xxx() statement - less than 2 arguments\n"), GetFullPath(fp).c_str(), lineNum); return false; } DynamicString stringId = ANSIStringToString(params[0]); if (stringId.empty()) { _tprintf(_T("%s(%d) : error: Invalid LOCALIZE_xxx() statement - empty string ID\n"), GetFullPath(fp).c_str(), lineNum); return false; } if (localizationTokenType == ltDIALOG) { DynamicString dlgID = ANSIStringToString(params[1]); if (m_Dialogs.find(dlgID) == m_Dialogs.end()) { _tprintf(_T("%s(%d) : error: Cannot find dialog %s\n"), GetFullPath(fp).c_str(), lineNum, dlgID.c_str()); return false; } m_Dialogs[dlgID].Localized = true; m_Dialogs[dlgID].LocalizationFileAndLine.Format(_T("%s(%d)"), GetFullPath(fp).c_str(), lineNum); m_Strings[stringId].Value = m_Dialogs[dlgID].Caption; currentDialogID = dlgID; } else if (localizationTokenType == ltDLGITEM) { if (currentDialogID.empty()) { _tprintf(_T("%s(%d) : error: LOCALIZE_DLGITEM() used outside LOCALIZE_DIALOG() block\n"), GetFullPath(fp).c_str(), lineNum); return false; } DynamicString itemID = ANSIStringToString(params[1]); std::map<BazisLib::String, DialogMember>::iterator it = m_Dialogs[currentDialogID].DialogMembers.find(itemID); if ((stringId == _T("0")) || !stringId.icompare(_T("NULL"))) { it->second.Skipped = true; continue; } if (it == m_Dialogs[currentDialogID].DialogMembers.end()) { _tprintf(_T("%s(%d) : error: %s is not defined in %s\n"), GetFullPath(fp).c_str(), lineNum, itemID.c_str(), currentDialogID.c_str()); return false; } m_Strings[stringId].Value = it->second.Name; it->second.Localized = true; } } LocalizationTokenStart = -1; } } } } return true; }
bool LocalizableStringManager::ParseResourceFile( const BazisLib::String &fp ) { ManagedPointer<TextANSIFileReader> pRdr = new TextANSIFileReader(new ACFile(fp, FileModes::OpenReadOnly)); if (!pRdr->Valid()) { _tprintf(_T("ERROR: cannot open %s\n"), fp.c_str()); return false; } _tprintf(_T(" %s\n"), DynamicString(Path::GetFileName((fp))).c_str()); DynamicString dialogName; bool insideDialogDescription = false; size_t spacingBeforeDlgitem = -1; unsigned lineNum = 0; while (!pRdr->IsEOF()) { lineNum++; DynamicStringA line = pRdr->ReadLine(); _FixedCharacterSplitString<2, TempStringA> tokens(line, ' '); if (!tokens.count()) continue; if (!tokens[0].icompare("BEGIN")) insideDialogDescription = true; else if (!tokens[0].icompare("END")) dialogName.clear(), insideDialogDescription = false; else if (!tokens[1].icompare("DIALOGEX")) { dialogName = ANSIStringToString(tokens[0]), insideDialogDescription = false; m_Dialogs[dialogName].FileAndLine.Format(_T("%s(%d)"), GetFullPath(fp).c_str(), lineNum); } else if (!line.substr(0, 8).icompare("CAPTION ") && !dialogName.empty() && !insideDialogDescription) { TempStringA dlgCaption = line.substr(9); size_t lastQuote = dlgCaption.find_last_of('\"'); if (lastQuote != -1) dlgCaption = dlgCaption.substr(0, lastQuote); DynamicString translatedCaption = ANSIStringToString(dlgCaption); for (size_t idx = 0; idx < (translatedCaption.length() - 1); idx++) { if ((translatedCaption[idx] == '\"') && (translatedCaption[idx + 1] == '\"')) translatedCaption.erase(idx, 1); } m_Dialogs[dialogName].Caption = FormatStringASCString(translatedCaption); } else if (insideDialogDescription && !dialogName.empty()) { if (spacingBeforeDlgitem == -1) spacingBeforeDlgitem = line.find_first_not_of(" \t"); if (spacingBeforeDlgitem == -1) continue; if ((line.length() <= spacingBeforeDlgitem) || (line[spacingBeforeDlgitem] == ' ') || (line[spacingBeforeDlgitem] == '\t')) continue; _FixedSetOfCharsSplitString<1, TempStringA> tokens2(line.substr(spacingBeforeDlgitem), " \t"); if (tokens2.count() < 1) continue; if (!tokens2[0].length()) continue; size_t nameStart = tokens2.GetRemainderOffset(); if (nameStart == -1) continue; nameStart = line.find_first_not_of(" \t", nameStart + spacingBeforeDlgitem); if ((nameStart == -1) || (line[nameStart] != '\"')) continue; nameStart++; char prevChar = 0; size_t nameEnd; for (nameEnd = nameStart; nameEnd < line.length(); nameEnd++) { if (line[nameEnd] == '\"') { if (((nameEnd + 1) < line.length()) && (line[nameEnd + 1] == '\"')) { nameEnd++; continue; } else break; } } DynamicStringA itemText = line.substr(nameStart, nameEnd - nameStart); for (size_t idx = 0; (idx + 1) < itemText.length(); idx++) { if ((itemText[idx] == '\"') && (itemText[idx + 1] == '\"')) itemText.erase(idx, 1); } size_t IDOffset = line.find_first_not_of(" \t,", nameEnd + 1); if (IDOffset == -1) continue; size_t IDEnd = line.find_first_of(" \t,", IDOffset); TempStringA itemID = line.substr(IDOffset, (IDEnd == -1) ? -1 : IDEnd - IDOffset); m_Dialogs[dialogName].DialogMembers[ANSIStringToString(itemID)].Name = FormatStringASCString(ANSIStringToString(itemText)); } } return true; }