text: /*++
  
  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 <buildnum.h>
  #include <helpids.h>
  
  #include "WMIparse.h"
  #include "resource.h"
  #include "WMIlprs.h"
  
  
  #include "WMIlfile.h"
  
  #include <malloc.h>
  
  //*****************************************************************************
  //
  //  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<NextClose2)?NextClose2:NextClose1;
  			if (Res){
                  i = 1+(Res-(ULONG_PTR)pBuff);
  				i /= sizeof(WCHAR);
  			}
  			break;
  		}
  	}
  
      /*
      {
        char pBuffDbg[64];
        wsprintfA(pBuffDbg,"pBuff %p Size %d\n",pBuff,(DWORD)i);
        OutputDebugStringA(pBuffDbg);
      }
      */
  
  	return i+4;
  }
  
  
  //*****************************************************************************
  //
  //  CWMILocFile::GetQualifierValue
  //
  //*****************************************************************************
  
  BOOL CWMILocFile::GetQualifierValue(wchar_t *pBuffer, UINT &uiPos, _bstr_t &sValue, UINT &uiPhysLen)
  {
  
      // This needs to read up the text of the qualifier,
      // strip out the quotes and carriage returns, and
      // return it and its *physical* length-in-file.
  
      BOOL fRetVal = FALSE;
      BOOL bArray = FALSE;
  
      wchar_t *pTemp = pBuffer;
  
      pTemp += uiPos;
  
      pTemp = FindTop(pTemp, pBuffer, bArray);
      if (pTemp)
      {
  
          BOOL bOK = FALSE;
          ULONG_PTR dwSize = Estimate(pTemp,&bOK,BEFORE_PAREN);
          wchar_t * tempBuff = new WCHAR[dwSize+1];
  
          if (tempBuff == NULL){
              return FALSE;
          }
          
          int iCount = 0;
  
          pTemp++;    // Step past this character.
          uiPhysLen = 0;
  
          WCHAR *token = pTemp;
          BOOL bEnd = FALSE;
          while (!bEnd)
          {
              uiPhysLen++;    // Count every character.
              WCHAR *Test;
  
              switch(*token)
              {
              case L'\0':
                  bEnd = TRUE;
                  break;
              case L'\n':
              case L'\r':
              case L'\t':
                  break;
              case L'\"':
                  if (!iCount)
                      break;
              case L')':
              case L'}': 
                  Test = token - 1;
                  while (TRUE)                    
                  {
                      if (*Test == L' ' || *Test == L'\r' || *Test == L'\n' || *Test == L'\t')
                      {
                          Test--;
                          continue;
                      }
                      if (*Test == L'\"')
                      {
                          Test--;
                          if (*Test != L'\\')
                          {
                              bEnd = TRUE;
                              break;
                          }
                          else
                          {
                              Test--;
                              if (*Test == L'\\')
                              {
                                  bEnd = TRUE;
                                  break;
                              }
                          }
                      }
                      tempBuff[iCount] = *token;
                      iCount++;
                      break;
                  }
                  break;
              default:
                  tempBuff[iCount] = *token;
                  iCount++;
                  break;
  
              }
              token++;
          }
          if (tempBuff[iCount-1] == L'\"')
              tempBuff[iCount-1] = '\0';
          else
              tempBuff[iCount] = '\0';
          sValue = tempBuff;
  
          delete [] tempBuff;
          
          fRetVal = TRUE;
      }
      uiPhysLen -= 1; // We want to keep the closing parenth.
  
      return fRetVal;
  
  }
  
  //*****************************************************************************
  //
  //  CWMILocFile::SetQualifierValue
  //
  //*****************************************************************************
  
  BOOL CWMILocFile::SetQualifierValue(wchar_t *pIn, wchar_t **pOut, UINT &uiPos, _bstr_t &sValue, UINT &uiLen, BOOL bQuotes)
  {
      // This needs to write the localized qualifier value
      // and erase *uiLen* characters.
      // uiPos will need to be updated with the *new*
      // position of this qualifier.
      
      BOOL fRetVal = FALSE;
      wchar_t *pStart = pIn + uiPos;
      BOOL bArray = FALSE;
  
      pStart = FindTop(pStart, pIn, bArray);
      if (pStart)
      {
          int iNewLen = wcslen(sValue);
          int iLen = wcslen(pIn) + 3;
          if (iNewLen > 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;
  }
  