/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: WMILFILE.CPP Abstract: Implementation of CWmiLocFile, the MOF parser for Localization Studio History: --*/ #include "precomp.h" #include "stdafx.h" #include #include #include "WMIparse.h" #include "resource.h" #include "WMIlprs.h" #include "WMIlfile.h" #include //***************************************************************************** // // CWMILocFile::CWMILocFile // //***************************************************************************** CWMILocFile::CWMILocFile( ILocParser *pParentClass) { // // C.O.M. initialization // m_pParentClass = pParentClass; m_sCurrentNamespace = ""; m_ulRefCount = 0; // // WMI file initialization // m_uiLineNumber = 0; m_pOpenSourceFile = NULL; m_pOpenTargetFile = NULL; AddRef(); IncrementClassCount(); } //***************************************************************************** // // CWMILocFile::GetFileDescriptions // //***************************************************************************** void CWMILocFile::GetFileDescriptions( CEnumCallback &cb) { EnumInfo eiFileInfo; CLString strDesc; eiFileInfo.szAbbreviation = NULL; LTVERIFY(strDesc.LoadString(g_hDll, IDS_WMI_DESC)); eiFileInfo.szDescription = (const TCHAR *)strDesc; eiFileInfo.ulValue = ftWMIFileType; cb.ProcessEnum(eiFileInfo); } //***************************************************************************** // // CWMILocFile::AddRef // //***************************************************************************** ULONG CWMILocFile::AddRef(void) { if (m_pParentClass != NULL) { m_pParentClass->AddRef(); } return m_ulRefCount++; } //***************************************************************************** // // CWMILocFile::Release // //***************************************************************************** ULONG CWMILocFile::Release(void) { LTASSERT(m_ulRefCount != 0); if (m_pParentClass != NULL) { m_pParentClass->Release(); } m_ulRefCount--; if (m_ulRefCount == 0) { delete this; return 0; } return m_ulRefCount; } //***************************************************************************** // // CWMILocFile::QueryInterface // //***************************************************************************** HRESULT CWMILocFile::QueryInterface( REFIID iid, LPVOID *ppvObj) { if (m_pParentClass != NULL) { return m_pParentClass->QueryInterface(iid, ppvObj); } else { SCODE scRetVal = E_NOINTERFACE; *ppvObj = NULL; if (iid == IID_IUnknown) { *ppvObj = (IUnknown *)this; scRetVal = S_OK; } else if (iid == IID_ILocFile) { *ppvObj = (ILocFile *)this; scRetVal = S_OK; } if (scRetVal == S_OK) { AddRef(); } return ResultFromScode(scRetVal); } } //***************************************************************************** // // CWMILocFile::AssertValidInterface // //***************************************************************************** void CWMILocFile::AssertValidInterface(void) const { AssertValid(); } //***************************************************************************** // // CWMILocFile::OpenFile // //***************************************************************************** BOOL CWMILocFile::OpenFile( const CFileSpec &fsFile, CReporter &Reporter) { LTTRACEPOINT("OpenFile()"); BOOL fRetCode; LTASSERT(m_pOpenTargetFile == NULL); fRetCode = FALSE; m_didFileId = fsFile.GetFileId(); m_pstrFileName = fsFile.GetFileName(); if (m_pOpenSourceFile != NULL) { fclose(m_pOpenSourceFile); m_pOpenSourceFile = NULL; } // We are just going to open the file. // and save the handle. // =================================== try { m_pOpenSourceFile = fopen(_T(m_pstrFileName), "rb"); if (!m_pOpenSourceFile) { fclose(m_pOpenSourceFile); m_pOpenSourceFile = NULL; } else { fRetCode = TRUE; } } catch (CMemoryException *pMemoryException) { CLString strContext; strContext.LoadString(g_hDll, IDS_WMI_GENERIC_LOCATION); Reporter.IssueMessage(esError, strContext, g_hDll, IDS_WMI_NO_MEMORY, g_locNull); pMemoryException->Delete(); } return fRetCode; } //***************************************************************************** // // CWMILocFile::GetFileType // //***************************************************************************** FileType CWMILocFile::GetFileType(void) const { // // Just return some number that isn't ftUnknown... // return ftWMIFileType; } //***************************************************************************** // // CWMILocFile::GetFileTypeDescription // //***************************************************************************** void CWMILocFile::GetFileTypeDescription( CLString &strDesc) const { LTVERIFY(strDesc.LoadString(g_hDll, IDS_WMI_DESC)); return; } //***************************************************************************** // // CWMILocFile::GetAssociatedFiles // //***************************************************************************** BOOL CWMILocFile::GetAssociatedFiles( CStringList &lstFiles) const { LTASSERT(lstFiles.GetCount() == 0); lstFiles.RemoveAll(); return FALSE; } //***************************************************************************** // // CWMILocFile::EnumerateFile // //***************************************************************************** BOOL CWMILocFile::EnumerateFile( CLocItemHandler &ihItemHandler, const CLocLangId &lid, const DBID &dbidFileId) { BOOL bRet = TRUE; DBID dbidThisId = dbidFileId; LTTRACEPOINT("EnumerateFile()"); if (m_pOpenSourceFile == NULL) { return FALSE; } // Enumerate file will need to: // * Parse the MOF. // * Walk through all qualifiers. For each "Amended" qualifier, // send back a CLocItem whose key is namespace, class, property and qualifier name. // * Fail if the language ID does not match that of LocaleID. // * Parent objects are namespaces, classes // ============================================================= m_cpSource = lid.GetCodePage(cpAnsi); m_wSourceId = lid.GetLanguageId(); ihItemHandler.SetProgressIndicator(0); bRet = ReadLines(ihItemHandler, dbidFileId, FALSE); return bRet; } //***************************************************************************** // // CWMILocFile::GenerateFile // //***************************************************************************** BOOL CWMILocFile::GenerateFile( const CPascalString &pstrTargetFile, CLocItemHandler &ihItemHandler, const CLocLangId &lidSource, const CLocLangId &lidTarget, const DBID &dbidParent) { LTASSERT(m_pOpenTargetFile == NULL); BOOL fRetVal = TRUE; if (m_pOpenSourceFile== NULL) { return FALSE; } // Generate File needs to: // * Parse the MOF. // * Walk through all qualifiers. For each "Amended" qualifier, // send back a CLocItem whose key is namespace, class, property and qualifier name. // * Replace all Amended qualifiers with localized text // * Replace all occurrences of the locale ID in namespaces and qualifiers // with the new one. // ================================================================================= m_cpSource = lidSource.GetCodePage(cpAnsi); m_cpTarget = lidTarget.GetCodePage(cpAnsi); m_wSourceId = lidSource.GetLanguageId(); m_wTargetId = lidTarget.GetLanguageId(); try { CFileException excFile; fRetVal = FALSE; if (m_pOpenTargetFile != NULL) { fclose(m_pOpenTargetFile); m_pOpenTargetFile = NULL; } char FileName[255]; strcpy(FileName, _bstr_t(_T(pstrTargetFile))); // This file must be in Unicode. HANDLE hFile = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if(hFile != INVALID_HANDLE_VALUE) { unsigned char cUnicodeHeader[2] = {0xff, 0xfe}; DWORD dwWrite; WriteFile(hFile, cUnicodeHeader, 2, &dwWrite, NULL); CloseHandle(hFile); } m_pOpenTargetFile = fopen(FileName, "ab"); if (!m_pOpenTargetFile) { fclose(m_pOpenTargetFile); m_pOpenTargetFile = NULL; } else { fRetVal = TRUE; } } catch (CMemoryException *pMemoryException) { CLString strContext; GetFullContext(strContext); ihItemHandler.IssueMessage(esError, strContext, g_hDll, IDS_WMI_NO_MEMORY, g_locNull); pMemoryException->Delete(); } catch (CFileException *pFileException) { fclose(m_pOpenTargetFile); fRetVal = FALSE; ReportFileError((const WCHAR *)pstrTargetFile, m_didFileId, pFileException, ihItemHandler); pFileException->Delete(); } if (!fRetVal) { return fRetVal; } fRetVal = ReadLines(ihItemHandler, dbidParent, TRUE); fclose(m_pOpenTargetFile); if (!fRetVal) { DeleteFileW (pstrTargetFile); } return fRetVal; } //***************************************************************************** // // CWMILocFile::GenerateItem // //***************************************************************************** BOOL CWMILocFile::GenerateItem( CLocItemHandler &ihItemHandler, CLocItemSet &isItemSet, wchar_t **pOutBuffer, UINT &uiStartingPos) { BOOL fRetVal = TRUE; UINT uiLength; wchar_t *pTemp = *pOutBuffer; _bstr_t sQualifierValue; // If nothing has changed, we can just // ignore this line. fRetVal = GetQualifierValue(pTemp, uiStartingPos, sQualifierValue, uiLength); if (fRetVal) { fRetVal = ihItemHandler.HandleItemSet(isItemSet); if (fRetVal) { sQualifierValue = ""; for (int i = 0; i < isItemSet.GetSize(); i++) { CVC::ValidationCode vcRetVal; CLocItem *pLocItem = isItemSet[i]; CLString strContext; CLocation loc; GetFullContext(strContext); loc.SetGlobalId( CGlobalId(pLocItem->GetMyDatabaseId(), otResource)); loc.SetView(vTransTab); CPascalString pstrId, pstrText; pLocItem->GetUniqueId().GetResId().GetId(pstrId); pstrText = pLocItem->GetLocString().GetString(); if (i > 0) sQualifierValue += L"\",\""; sQualifierValue += (const wchar_t *)pstrText; } // Set it live in the buffer. We are not going to // write it to the file until the very end. fRetVal = SetQualifierValue(pTemp, pOutBuffer, uiStartingPos, sQualifierValue, uiLength); pTemp = *pOutBuffer; } } return fRetVal; } //***************************************************************************** // // CWMILocFile::EnumerateItem // //***************************************************************************** BOOL CWMILocFile::EnumerateItem( CLocItemHandler &ihItemHandler, CLocItemSet &isItemSet) { BOOL fRetVal; if (isItemSet.GetSize() != 0) { fRetVal = ihItemHandler.HandleItemSet(isItemSet); } else { fRetVal = TRUE; } return fRetVal; } #ifdef _DEBUG //***************************************************************************** // // CWMILocFile::AssertValid // //***************************************************************************** void CWMILocFile::AssertValid(void) const { CLObject::AssertValid(); } //***************************************************************************** // // CWMILocFile::Dump // //***************************************************************************** void CWMILocFile::Dump( CDumpContext &dc) const { CLObject::Dump(dc); } #endif //***************************************************************************** // // CWMILocFile::~CWMILocFile // //***************************************************************************** CWMILocFile::~CWMILocFile() { DEBUGONLY(AssertValid()); if (m_pOpenSourceFile != NULL) { fclose(m_pOpenSourceFile); m_pOpenSourceFile = NULL; } DecrementClassCount(); } //***************************************************************************** // // CWMILocFile::SetFlags // //***************************************************************************** void CWMILocFile::SetFlags( CLocItem *pItem, CLocString &lsString) const { ULONG ulItemType; pItem->SetFDevLock(FALSE); pItem->SetFUsrLock(FALSE); pItem->SetFExpandable(FALSE); LTVERIFY(pItem->GetUniqueId().GetTypeId().GetId(ulItemType)); switch (ulItemType) { case wltNamespaceName: pItem->SetFDisplayable(TRUE); pItem->SetFNoResTable(TRUE); break; case wltClassName: case wltPropertyName: pItem->SetFDisplayable(FALSE); pItem->SetFNoResTable(FALSE); lsString.SetCodePageType(cpAnsi); lsString.SetStringType(CST::Text); break; default: LTASSERT(FALSE && "Unexpected item type!"); } } //***************************************************************************** // // CWMILocFile::ReadLines // //***************************************************************************** BOOL CWMILocFile::ReadLines( CLocItemHandler &ihItemHandler, const DBID &dbidFileId, BOOL fGenerating) { DBID dbidSectionId; BOOL fRetVal = TRUE; wchar_t *pstrNamespaceName; _bstr_t pstrClassName; UINT uiStartPos = 0; UINT uiCommentNum; UINT uiReadingOrder; dbidSectionId = dbidFileId; m_uiLineNumber = 0; BOOL bPendingObj = FALSE; try { UINT uiOldPercentage = 0, uiNewPercentage = 0; UINT uiBytesRead, uiCurrPos = 1; ihItemHandler.SetProgressIndicator(uiOldPercentage); fseek(m_pOpenSourceFile, 0, SEEK_END); long lSize = ftell(m_pOpenSourceFile) + 6; fseek(m_pOpenSourceFile, 0, SEEK_SET); // Check for UNICODE source file. // ============================== BYTE UnicodeSignature[2]; BOOL bUnicode = FALSE; if (fread(UnicodeSignature, sizeof(BYTE), 2, m_pOpenSourceFile) != 2) { fRetVal = FALSE; return fRetVal; } if ((UnicodeSignature[0] == 0xFF && UnicodeSignature[1] == 0xFE) || (UnicodeSignature[0] == 0xFE && UnicodeSignature[1] == 0xFF)) { bUnicode = TRUE; lSize *= 2; } if (!bUnicode) fseek(m_pOpenSourceFile, 0, SEEK_SET); wchar_t *pBuff = (wchar_t *)new wchar_t[lSize+1]; if (!pBuff) { fRetVal = FALSE; return fRetVal; } memset(pBuff,0,lSize*sizeof(wchar_t)); // If this is not a Unicode file, // we need to perform a conversion. // ===================================== if (bUnicode) uiBytesRead = fread(pBuff, sizeof(wchar_t), lSize, m_pOpenSourceFile); else { char *pCharBuff = new char[lSize+1]; if (pCharBuff) { uiBytesRead = fread(pCharBuff, sizeof(char), lSize, m_pOpenSourceFile); pCharBuff[lSize] = '\0'; swprintf(pBuff, L"%S", pCharBuff); delete pCharBuff; } } pBuff[lSize] = '\0'; if (uiBytesRead != 0) { wchar_t *pOutBuffer = NULL; uiCurrPos += uiBytesRead; fRetVal = TRUE; pstrNamespaceName = NULL; m_sCurrentNamespace = L""; pstrClassName = L""; uiCommentNum = 0; uiReadingOrder = 1; WMIFileError wmiRet; CLocItemSet isItemSet; UINT uiTemp = 0; DWORD dwCount = 0; // If we are generating a file, make a copy // of the outbound buffer. if (fGenerating) pOutBuffer = pBuff; while (GetNextQualifierPos(L"amended", pBuff, uiTemp, uiTemp) && !bPendingObj) { // If we have found the "amended" keyword, // we want to find the namespace, // class, and property if applicable, and // generate the object as appropriate. // ====================================== pstrNamespaceName = GetCurrentNamespace(pBuff, uiTemp); if (!pstrNamespaceName || !wcslen(pstrNamespaceName)) { delete pBuff; return FALSE; } if (wcscmp(pstrNamespaceName, m_sCurrentNamespace)) { // We need to generate this object, // and set it up as the current parent. // ==================================== CLocItem *pNewItem = new CLocItem; CPascalString sId; if (pNewItem) { CLocUniqueId uid; sId = (const WCHAR *)pstrNamespaceName; uid.GetResId().SetId(sId); uid.GetTypeId().SetId(wltNamespaceName); uid.SetParentId(dbidFileId); pNewItem->SetUniqueId(uid); CLocString lsString; pNewItem->SetIconType(CIT::String); CPascalString pstrComment, pstrText; pNewItem->SetInstructions(pstrComment); lsString.SetString(pstrText); SetFlags(pNewItem, lsString); pNewItem->SetLocString(lsString); isItemSet.Add(pNewItem); uiReadingOrder = (uiReadingOrder + 999)/1000*1000; isItemSet[0]->SetDisplayOrder(uiReadingOrder); uiReadingOrder++; fRetVal = EnumerateItem(ihItemHandler, isItemSet); dbidSectionId.Clear(); dbidSectionId = isItemSet[0]->GetMyDatabaseId(); isItemSet.ClearItemSet(); uiTemp += 1; } m_sCurrentNamespace = pstrNamespaceName; delete pstrNamespaceName; } // For the class name, this is trickier. // If there are one or more qualifiers // on the class itself, we need to read ahead // to find the class name, and then // generate all the qualifier objects at once. // ========================================== wmiRet = GetNextItemSet(dwCount, pBuff, isItemSet, dbidSectionId, uiStartPos); while (wmiRet == WMINoError) { // For each item, we want to set its key, // and push it or write it as appropriate. // ======================================== dwCount++; ULONG ulItemType; CLocUniqueId &rUid = isItemSet[0]->GetUniqueId(); rUid.GetTypeId().GetId(ulItemType); //if (ulItemType == wltClassName) //{ // uiCommentNum = 0; // uiReadingOrder = (uiReadingOrder + 999)/1000*1000; //} for (int i = 0; i < isItemSet.GetSize(); i++) { isItemSet[i]->SetDisplayOrder(uiReadingOrder); uiReadingOrder++; } if (fGenerating) { fRetVal = GenerateItem(ihItemHandler, isItemSet, &pOutBuffer, uiStartPos); if (pBuff != pOutBuffer) { delete pBuff; pBuff = NULL; pBuff = pOutBuffer; // The old memory has already been deleted. } else { fRetVal = FALSE; } } else { fRetVal = EnumerateItem(ihItemHandler, isItemSet); } isItemSet.ClearItemSet(); uiTemp += 1; if (!fRetVal) { fRetVal = TRUE; break; } wmiRet = GetNextItemSet(dwCount, pBuff, isItemSet, dbidSectionId, uiStartPos); if (uiStartPos > uiTemp) uiTemp = uiStartPos; if (dwCount%20 == 0) { if (uiNewPercentage < 100) uiNewPercentage++; ihItemHandler.SetProgressIndicator(uiNewPercentage); } } // If we were generating the file, // we're done. // ============================== if (fGenerating) break; if (uiNewPercentage < 100) uiNewPercentage++; ihItemHandler.SetProgressIndicator(uiNewPercentage); } uiTemp = 0; // Now, we get to search and replace the locale IDs, // and actually write out the file. // ================================================= if (fRetVal && fGenerating) { fRetVal = WriteNewFile(pOutBuffer); } } if (pBuff) delete pBuff; ihItemHandler.SetProgressIndicator(100); } catch (CFileException *pFileException) { fRetVal = FALSE; ReportFileError(m_pstrFileName, m_didFileId, pFileException, ihItemHandler); pFileException->Delete(); } catch (CUnicodeException *pUnicodeException) { CLocation loc; loc.SetGlobalId(CGlobalId(m_didFileId, otFile)); loc.SetView(vProjWindow); ReportUnicodeError(pUnicodeException, ihItemHandler, loc); pUnicodeException->Delete(); fRetVal = FALSE; } catch (CMemoryException *pMemoryException) { CLString strContext; ihItemHandler.IssueMessage(esError, strContext, g_hDll, IDS_WMI_NO_MEMORY, g_locNull); fRetVal = FALSE; pMemoryException->Delete(); } catch (CException *pException) { CLocation loc; loc.SetGlobalId(CGlobalId(m_didFileId, otFile)); loc.SetView(vProjWindow); ReportException(pException, ihItemHandler, loc); pException->Delete(); fRetVal = FALSE; } return fRetVal; } //***************************************************************************** // // CWMILocFile::WriteWaterMark // //***************************************************************************** void CWMILocFile::WriteWaterMark() { LTASSERT(NULL != m_pOpenTargetFile); LTASSERT(NULL != m_pOpenSourceFile); // Do we need to support this? } //***************************************************************************** // // CWMILocFile::GetNextQualifierPos // //***************************************************************************** BOOL CWMILocFile::GetNextQualifierPos(const wchar_t *wTmp, const wchar_t *pBuff, UINT &uiNewPos, UINT uiStartingPos) { BOOL bRet = FALSE; UINT uiPos = uiStartingPos; BOOL bComment = FALSE; if (pBuff && wcslen(pBuff) < uiStartingPos) return FALSE; wchar_t *pTemp = (wchar_t *)pBuff; pTemp += uiStartingPos; while (TRUE) { wchar_t *pszTest2 = NULL; pszTest2 = wcsstr(pTemp, L":"); if (pszTest2) { uiPos = pszTest2 - pBuff + 1; // Look for the "amended" keyword. // ============================== WCHAR temp = pszTest2[0]; while(temp == L' ' || temp == L'\0' || temp == L':') { pszTest2++; temp = pszTest2[0]; } if (temp != L'\0') { wchar_t wTmp2[8]; wcsncpy(wTmp2, pszTest2, 7); wTmp2[7] = '\0'; if (!_wcsicmp(wTmp2, wTmp)) { bRet = TRUE; } } // If here, we found a non-match, so try again. // ============================================ if (!bRet) pTemp = pszTest2 + 1; else break; } else { break; } } if (bRet) uiNewPos = uiPos; return bRet; } //***************************************************************************** // // CWMILocFile::GetCurrentNamespace // //***************************************************************************** wchar_t *CWMILocFile::GetCurrentNamespace(wchar_t *pstr, UINT uPos) { wchar_t *pTemp = pstr; _bstr_t pstrNamespace = m_sCurrentNamespace; UINT uiCurrPos = 0; BOOL bComment = FALSE; wchar_t wTmp[] = L"#pragma namespace"; int iHCLen = wcslen(wTmp); // Find the first occurrence of the namespace // before the current position. if (pstrNamespace.length() > 0) pTemp = wcsstr(pTemp, pstrNamespace); // Jump directly to the existing one. while (uiCurrPos < uPos) { wchar_t *pszTest2 = NULL; pszTest2 = wcsstr(pTemp, L"#"); if (pszTest2) { // First, go back and make sure this isn't a comment line. // ======================================================= bComment = FALSE; wchar_t *pComment = pszTest2; while (pComment > pstr) { if (pComment[0] == L'\n' || pComment[0] == L'\r') { if (pComment[1] == L'/' && pComment[2] == L'/') { bComment = TRUE; } else { bComment = FALSE; } break; } pComment--; } if (!bComment) { wchar_t wTmp2[100]; wcsncpy(wTmp2, pszTest2, 17); wTmp2[17] = '\0'; if (!_wcsicmp(wTmp2, wTmp)) { uiCurrPos += (pszTest2 - pTemp); wchar_t *pszTest3 = wcschr(pszTest2, L')'); int iLen = (pszTest3 - pszTest2); wchar_t *pszTmpNS = new wchar_t[iLen*2+1]; if (pszTmpNS) { pszTest2 += iHCLen + 2; // skip quote and open parent. wcsncpy(pszTmpNS, pszTest2, iLen - 2); // strip quotes. pszTmpNS[iLen-iHCLen-3] = '\0'; pstrNamespace = pszTmpNS; pTemp = pszTest2 + 1; delete pszTmpNS; } } else { pTemp = pszTest2 + 1; } } else { pTemp = pszTest2 + 1; } } else { break; } } int iLen = wcslen(pstrNamespace) ; wchar_t *pNew = new wchar_t[iLen*2+1]; if (pNew) { wcsncpy(pNew, (const wchar_t *)pstrNamespace, iLen); pNew[iLen] = '\0'; } return pNew; } //***************************************************************************** // // CWMILocFile::GetNextItemSet // //***************************************************************************** CWMILocFile::WMIFileError CWMILocFile::GetNextItemSet( DWORD dwCurrPos, const _bstr_t &pstrCurrentLine, CLocItemSet &aNewItem, const DBID &dbidSection, UINT &uiStartPos) { // In this function, we know there is an // "amended" keyword in here somewhere. // We want to know to which class and/or // property does it belong? If we don't // have enough data to figure it out, // we need to send back a WMIIncompleteObj // code. // ====================================== UINT uiCurrPos = 0; WMIFileError feRetCode = WMINoError; _bstr_t sQualifierName, sRawValue, sPropName, sClassName; BOOL bClass = FALSE; int iLen = pstrCurrentLine.length() + 1; iLen *= 2; // Get the position of the keyword // "amended" in this chunk of text. wchar_t *wTemp = new wchar_t[iLen+1]; if (!wTemp) { feRetCode = WMIOOM; return feRetCode; } if (GetNextQualifierPos(L"amended", pstrCurrentLine, uiCurrPos, uiStartPos)) { BOOL bArray = FALSE; uiStartPos = uiCurrPos; // Find the qualifier name and value. // wTemp = Top of File // wTmp2 = "Amended" keyword // wQfrVal = Opening bracket // wBkwd = floating pointer. wchar_t *wTmp2 = NULL, *wBkwd = NULL, *wQfrVal = NULL; wcscpy(wTemp, pstrCurrentLine); wTemp[iLen] = '\0'; wTmp2 = wTemp; wTmp2 += (uiCurrPos - 1); // the "Amended" keyword. wQfrVal = FindTop(wTmp2, wTemp, bArray); if (!wQfrVal) // Make sure we had an open parenth { feRetCode = WMISyntaxError; delete wTemp; return feRetCode; } // Find the beginning of the qualifier name. wBkwd = wQfrVal; while (wBkwd[0] != L',' && wBkwd[0] != L'[' && wBkwd >= wTemp) { wBkwd--; } if (wBkwd[0] != L',' && wBkwd[0] != L'[') // Make sure we had a valid qualifier name. { feRetCode = WMISyntaxError; delete wTemp; return feRetCode; } WCHAR *token; UINT uiLen; wBkwd += 1; wchar_t wTmpBuff[256]; wcsncpy(wTmpBuff, wBkwd, wQfrVal - wBkwd); wTmpBuff[wQfrVal - wBkwd] = '\0'; sQualifierName = wTmpBuff; GetQualifierValue(wTemp, uiStartPos, sRawValue, uiLen); // Finally, populate the CLocItem. // =============================== LTASSERT(aNewItem.GetSize() == 0); if (feRetCode == WMINoError) { CLocItem *pNewItem; try { // Now we have a value, but it may be an // array. If so, we need to add one CLocItem // for each value in the array. VectorString arrValues; if (bArray) ParseArray(sRawValue, arrValues); else arrValues.push_back(sRawValue); for (int i = 0; i < arrValues.size(); i++) { wchar_t szTmp[20]; swprintf(szTmp, L"%ld", dwCurrPos); _bstr_t sValue = arrValues.at(i); pNewItem = new CLocItem; CLocUniqueId uid; CPascalString sTempString; sTempString = sQualifierName; sTempString += szTmp; uid.GetResId().SetId(sTempString) ; if (bClass) uid.GetTypeId().SetId(wltClassName); else uid.GetTypeId().SetId(wltPropertyName); uid.SetParentId(dbidSection); pNewItem->SetUniqueId(uid); CLocString lsString; CPascalString pstrComment, pstrText; pstrText = sValue; pNewItem->SetIconType(CIT::String); pNewItem->SetInstructions(pstrComment); lsString.SetString(pstrText); SetFlags(pNewItem, lsString); pNewItem->SetLocString(lsString); aNewItem.Add(pNewItem); } } catch (CMemoryException *pMemoryException) { feRetCode = WMIOOM; pMemoryException->Delete(); } } else { LTTRACE("Unable to process line '%ls'", (const WCHAR *)pstrCurrentLine); } } else { feRetCode = WMINoMore; } uiStartPos = uiCurrPos; delete wTemp; return feRetCode; } const UINT WMI_MAX_CONTEXT = 256; //***************************************************************************** // // CWMILocFile::GetFullContext // //***************************************************************************** void CWMILocFile::GetFullContext( CLString &strContext) const { CLString strFormat; strFormat.LoadString(g_hDll, IDS_WMI_FULL_CONTEXT); strContext.Empty(); _sntprintf(strContext.GetBuffer(WMI_MAX_CONTEXT), WMI_MAX_CONTEXT, (const TCHAR *)strFormat, (const WCHAR *)m_pstrFileName, (UINT)m_uiLineNumber); strContext.ReleaseBuffer(); } //***************************************************************************** // // CWMILocFile::ReportFileError // //***************************************************************************** void CWMILocFile::ReportFileError( const _bstr_t &pstrFileName, const DBID &didFileId, CFileException *pFileException, CReporter &Reporter) const { CLString strContext; CLString strMessage; const UINT MAX_MESSAGE = 256; TCHAR szFileErrorMessage[MAX_MESSAGE]; CLocation loc; pFileException->GetErrorMessage(szFileErrorMessage, MAX_MESSAGE); strMessage.Format(g_hDll, IDS_WMI_BAD_FILE, (const WCHAR *)pstrFileName, szFileErrorMessage); GetFullContext(strContext); loc.SetGlobalId(CGlobalId(didFileId, otFile)); loc.SetView(vProjWindow); Reporter.IssueMessage(esError, strContext, strMessage, loc); } //***************************************************************************** // // CWMILocFile::ReportUnicodeError // //***************************************************************************** void CWMILocFile::ReportUnicodeError( CUnicodeException *pUnicodeException, CReporter &Reporter, const CLocation &Location) const { CLString strContext; CLString strMessage; const UINT MAX_MESSAGE = 256; TCHAR szUnicodeErrorMessage[MAX_MESSAGE]; CLocation loc; pUnicodeException->GetErrorMessage(szUnicodeErrorMessage, MAX_MESSAGE); strMessage.Format(g_hDll, IDS_WMI_UNICODE_ERROR, szUnicodeErrorMessage); GetFullContext(strContext); Reporter.IssueMessage(esError, strContext, strMessage, Location, IDH_UNICODE_CONV); } //***************************************************************************** // // CWMILocFile::ReportException // //***************************************************************************** void CWMILocFile::ReportException( CException *pException, CReporter &Reporter, const CLocation &Location) const { CLString strContext; CLString strMessage; const UINT MAX_MESSAGE = 256; TCHAR szErrorMessage[MAX_MESSAGE]; pException->GetErrorMessage(szErrorMessage, MAX_MESSAGE); strMessage.Format(g_hDll, IDS_WMI_EXCEPTION, szErrorMessage); GetFullContext(strContext); Reporter.IssueMessage(esError, strContext, strMessage, Location); } // // This function estimates the size of a buffer // required to hold a string up to something like __"}__ or __")__ // invalid combinations are \"} and \") (there is the escape) // but double \\"} or \\") are valid // // // // we will consider \\ and \" as special // white spaces are \r \n \t \x20 // array of strings { "" , "" } // ("") // states of the FSA modelling the parser #define BEFORE_PAREN 0 #define AFTER_PAREN 1 #define OPEN_QUOTE 2 #define CLOSE_QUOTE 3 #define COMMA 4 #define CLOSE_PAREN 5 #define BAD 6 #define LAST_STATE 7 // classes of characters #define QUOTE 0 #define PAREN_OPEN 1 #define SPACES 2 #define PAREN_CLOSE 3 #define COMMA_CHAR 4 #define OTHER 5 #define LAST_CLASS 6 DWORD g_pTable[LAST_STATE][LAST_CLASS] = { /* BEFORE_PAREN */ {BAD , AFTER_PAREN, BEFORE_PAREN, BAD, BAD, BAD }, /* AFTER_PAREN */ {OPEN_QUOTE , BAD, AFTER_PAREN, BAD, BAD, BAD }, /* OPEN_QUOTE */ {CLOSE_QUOTE, OPEN_QUOTE, OPEN_QUOTE, OPEN_QUOTE, OPEN_QUOTE, OPEN_QUOTE }, /* CLOSE_QUOTE */ {BAD, BAD, CLOSE_QUOTE, CLOSE_PAREN, COMMA, BAD }, /* COMMA */ {OPEN_QUOTE , BAD, COMMA, BAD, BAD, BAD}, /* CLOSE_PAREN */ {BAD, BAD,BAD,BAD,BAD,BAD }, /* BAD */ {BAD, BAD,BAD,BAD,BAD,BAD }, }; ULONG_PTR Estimate(WCHAR * pBuff,BOOL * pbOK, DWORD InitState) { DWORD State = InitState; ULONG_PTR i=0; while (pBuff[i]) { switch(pBuff[i]) { case L'{': case L'(': State = g_pTable[State][PAREN_OPEN]; break; case L'}': case L')': State = g_pTable[State][PAREN_CLOSE]; break; case L'\t': case L'\r': case L'\n': case L' ': State = g_pTable[State][SPACES]; break; case L'\"': State = g_pTable[State][QUOTE]; break; case L',': State = g_pTable[State][COMMA_CHAR]; break; case L'\\': if ((pBuff[i+1] == L'\"' || pBuff[i+1] == L'\\' || pBuff[i+1] == L'r' || pBuff[i+1] == L'n' || pBuff[i+1] == L't' ) && (State == OPEN_QUOTE)){ i++; }; State = g_pTable[State][OTHER]; break; default: State = g_pTable[State][OTHER]; }; i++; if (State == CLOSE_PAREN){ *pbOK = TRUE; break; } if (State == BAD) { *pbOK = FALSE; // // get the next ) or }, and take the most far // ULONG_PTR NextClose1 = (ULONG_PTR)wcschr(&pBuff[i],L'}'); ULONG_PTR NextClose2 = (ULONG_PTR)wcschr(&pBuff[i],L')'); ULONG_PTR Res = (NextClose1 uiLen) // The length of the new buffer iLen += (iNewLen - uiLen); // If the new value is longer, add it. pStart++; // jump past the '(' character. uiLen starts now. int iPos = pStart-pIn; // The current position. iLen *= 2; wchar_t *pNew = new wchar_t[iLen+3]; if (pNew) { int iTempPos = 0; wcsncpy(pNew, pIn, iPos); // Copy the initial part of the file. if (bQuotes) pNew[iPos] = '\"'; pNew[iPos+1] = '\0'; // Null terminate wcscat(pNew, sValue); // Add the new value. iPos += 1 + wcslen(sValue); // Jump past the value if (bQuotes) pNew[iPos] = '\"'; pNew[iPos+1] = '\0'; // Null terminate the value. pStart += uiLen; // Jump past the current value. iTempPos = iPos; iPos = wcslen(pIn) - (pStart-pIn); // Calculate the length of the rest of the file. wcsncat(pNew, pStart, iPos); // Append the rest of the file to the new buffer. pStart = pNew + iLen; pStart = FindPrevious(pStart, L";", pNew); pStart[1] = L'\r'; pStart[2] = L'\n'; pStart[3] = L'\0'; *pOut = pNew; fRetVal = TRUE; } } // Adjust the position. int iNewLen = wcslen(sValue); if (iNewLen < uiLen) uiPos -= (uiLen - iNewLen); else uiPos += (iNewLen - uiLen); uiPos += 3; return fRetVal; } //***************************************************************************** // // CWMILocFile::WriteNewFile // //***************************************************************************** BOOL CWMILocFile::WriteNewFile(wchar_t *pBuffer) { // This needs to seek and replace all instances of the // original Locale with the new one. // =================================================== BOOL fRetVal = FALSE, fSuccess = TRUE; UINT uiPos = 0, uiStartingPos = 0; int uiLen = wcslen(pBuffer); _bstr_t sThisLocale, sTargetLocale; wchar_t wOldCodePage[30], wNewCodePage[30]; swprintf(wOldCodePage, L"_%X", m_wSourceId ); swprintf(wNewCodePage, L"_%X", m_wTargetId ); if (m_wSourceId != m_wTargetId) { wchar_t *pLocale = wcsstr(pBuffer, wOldCodePage); while (pLocale != NULL) { for (int i = 0; i < wcslen(wOldCodePage); i++) { pLocale[i] = wNewCodePage[i]; } pLocale = wcsstr(pLocale, wOldCodePage); } // Now look for the locale if // it was converted to a decimal. // ============================== swprintf(wOldCodePage, L"(0x%X)", m_wSourceId ); swprintf(wNewCodePage, L"(0x%X)", m_wTargetId ); pLocale = wcsstr(pBuffer, wOldCodePage); while (pLocale != NULL) { for (int i = 0; i < wcslen(wOldCodePage); i++) { pLocale[i] = wNewCodePage[i]; } pLocale = wcsstr(pLocale, wOldCodePage); } // Now look for the locale if // it was converted to a decimal. // ============================== swprintf(wOldCodePage, L"(%ld)", m_wSourceId ); swprintf(wNewCodePage, L"(%ld)", m_wTargetId ); pLocale = wcsstr(pBuffer, wOldCodePage); while (pLocale != NULL) { for (int i = 0; i < wcslen(wOldCodePage); i++) { pLocale[i] = wNewCodePage[i]; } pLocale = wcsstr(pLocale, wOldCodePage); } } if (fSuccess) { fRetVal = TRUE; // Finally, write out the buffer to a brand new file // ================================================= while (uiLen >= 0) { if (fwrite(pBuffer, sizeof(wchar_t), (uiLen > 4096) ? 4096: uiLen, m_pOpenTargetFile) < 0) { fRetVal = FALSE; break; } else { fRetVal = TRUE; pBuffer += 4096; uiLen -= 4096; } fflush(m_pOpenTargetFile); } } return fRetVal; } //***************************************************************************** // // CWMILocFile::FindPrevious // //***************************************************************************** wchar_t *CWMILocFile::FindPrevious(wchar_t *pBuffer, const wchar_t *pFind, const wchar_t *pTop) { wchar_t *pRet = NULL; WCHAR t1, t2; int iLen = wcslen(pFind); BOOL bFound = FALSE; pRet = pBuffer; while (pRet >= pTop) { t2 = pRet[0]; for (int i = 0; i < iLen; i++) { t1 = pFind[i]; if (t1 == t2) { bFound = TRUE; break; } } if (bFound) break; pRet--; } if (pRet <= pTop) pRet = NULL; return pRet; } //***************************************************************************** // // CWMILocFile::FindTop // //***************************************************************************** wchar_t *CWMILocFile::FindTop(wchar_t *wTmp2, wchar_t *wTop, BOOL &bArray) { wchar_t *wQfrVal = FindPrevious(wTmp2, L"({", wTop); while (wQfrVal) { WCHAR *pQT = wQfrVal + 1; BOOL bFound = FALSE; while (TRUE) { if (*pQT != L' ' && *pQT != L'\t' && *pQT != L'\r' && *pQT != L'\n') { if (*pQT == L'\"') { bFound = TRUE; } break; } pQT++; } if (!bFound) { wQfrVal --; wQfrVal = FindPrevious(wQfrVal, L"({", wTop); } else break; } if (wQfrVal) { if (wQfrVal[0] == L'{') bArray = TRUE; } return wQfrVal; } //***************************************************************************** // // CWMILocFile::ParseArray // //***************************************************************************** void CWMILocFile::ParseArray(wchar_t *pIn, VectorString &arrOut) { wchar_t *pLast = pIn; if (*pLast == L'\"') pLast++; BOOL bOK = FALSE; BOOL bAlloc = FALSE; ULONG_PTR qwSize = Estimate(pLast,&bOK,OPEN_QUOTE); wchar_t * Buff = new WCHAR[(DWORD)qwSize]; if(Buff == NULL){ Buff = (WCHAR *)_alloca((DWORD)qwSize); } else { bAlloc = TRUE; } wchar_t *pFind = wcsstr(pIn, L"\","); arrOut.clear(); while (pFind) { wchar_t temp = pFind[-1]; if (temp == '\\') { pFind++; pFind = wcsstr(pFind, L"\","); continue; } wcsncpy(Buff, pLast, pFind-pLast); Buff[pFind-pLast] = '\0'; arrOut.push_back(_bstr_t(Buff)); // Now move pFind to the next valid char. while (pFind[0] == L'\n' || pFind[0] == L'\r' || pFind[0] == L' ' || pFind[0] == L',' || pFind[0] == L'\"' ) pFind++; pLast = pFind ; pFind = wcsstr(pFind, L"\","); } wcscpy(Buff, pLast); if (Buff[wcslen(Buff)-1] == L'\"') Buff[wcslen(Buff)-1] = L'\0'; // strip off that trailing quote. else Buff[wcslen(Buff)] = L'\0'; // strip off that trailing quote. arrOut.push_back(_bstr_t(Buff)); if (bAlloc) { delete [] Buff; } return; } //***************************************************************************** // // CVC::ValidateString // //***************************************************************************** CVC::ValidationCode ValidateString( const CLocTypeId &, const CLocString &clsOutputLine, CReporter &repReporter, const CLocation &loc, const CLString &strContext) { CVC::ValidationCode vcRetVal = CVC::NoError; CLString strMyContext = strContext; if (strMyContext.GetLength() == 0) { strMyContext.LoadString(g_hDll, IDS_WMI_GENERIC_LOCATION); } loc; repReporter; clsOutputLine; /* if (clsOutputLine.HasHotKey()) { vcRetVal = CVC::UpgradeValue(vcRetVal, CVC::Warning); repReporter.IssueMessage(esWarning, strMyContext, g_hDll, IDS_WMI_VAL_HOTKEY, loc); } _bstr_t pstrBadChars; UINT uiBadPos; pstrBadChars.SetString(L"\n\ra", (UINT)3); if (pstrOutput.FindOneOf(pstrBadChars, 0, uiBadPos)) { vcRetVal = CVC::UpgradeValue(vcRetVal, CVC::Error); repReporter.IssueMessage(esError, strMyContext, g_hDll, IDS_WMI_VAL_BAD_CHARS, loc); } */ return vcRetVal; }