text: #include "headers.hxx"
  #include "..\CSVDSReader.hpp"
  #include "..\constants.hpp"
  #include "..\global.hpp"
  #include <winnls.h>
  
  
  
  String escape(const wchar_t *str)
  {
     LOG_FUNCTION(escape);
     String dest;
     wchar_t strNum[5];
  
     while(*str!=0)
     {
        wsprintf(strNum,L"\\x%x",*str);
        dest+=String(strNum);
        str++;
     }
     return dest;
  }
  
  
  
  String issues;
  
  bool
  isPropertyInChangeList
  (
     String, //property,
     const objectChanges &//changes
  )
  {
     /*objectChanges::const_iterator begin,end;
     begin=changes.begin();
     end=changes.end();
     while(begin!=end)
     {
        changeList::const_iterator beginChanges,endChanges;
        beginChanges=begin->second.begin();
        endChanges=begin->second.end();
        while(beginChanges!=endChanges)
        {
           if (property.icompare(beginChanges->property)==0) return true;
           beginChanges++;
        }
        begin++;
     }*/
     return false;
  }
  
  bool
  isObjectPropertyInChangeList
  (
     String object,
     String property,
     const objectChanges &changes
  )
  {
     objectChanges::const_iterator begin,end;
     begin=changes.begin();
     end=changes.end();
     while(begin!=end)
     {
        changeList::const_iterator beginChanges,endChanges;
        beginChanges=begin->second.begin();
        endChanges=begin->second.end();
        while(beginChanges!=endChanges)
        {
           if (
                 property.icompare(beginChanges->property)==0 &&
                 object.icompare(beginChanges->object)==0
              ) 
           {
              return true;
           }
           beginChanges++;
        }
        begin++;
     }
     return false;
  }
  
  
  
  HRESULT
  getCommonProperties
  (
     const mapOfPositions& pp1,
     const mapOfPositions& pp2,
     StringList &commonProperties
  )
  {
     LOG_FUNCTION(getCommonProperties);
  
     HRESULT hr=S_OK;
     do
     {
  
        if(pp1.size()!=0)
        {
           mapOfPositions::const_iterator begin=pp1.begin(),end=pp1.end();
           while(begin!=end)
           {
              if(pp2.find(begin->first)==pp2.end())
              {
                 error=L"The property:" + begin->first +
                       L" was found only in Old. \r\n" +
                       L"This program does not take into account" +
                       L" the removal of properties from Old to New.\r\n"
                       L"You should pass the Old csv file as the"
                       L" first command line argument.";
  
                 hr=E_FAIL;
                 break;
              }
              begin++;
           }
           BREAK_ON_FAILED_HRESULT(hr);
        }
        if(pp2.size()!=0)
        {
           mapOfPositions::const_iterator begin=pp2.begin(),end=pp2.end();
           while(begin!=end)
           {
              if(pp1.find(begin->first)==pp1.end())
              {
  			   //bugbug - No Longer possible
                 /*if (!isPropertyInChangeList(begin->first,changes))
                 {
                    issues +=
                       L"The property:" + begin->first +
                       L" was found only in New but is not a global" 
                       L" change. \r\nThis program does not generate entries" 
                       L" for properties only in New.\r\n\r\n\r\n";
                 }*/
              }
              else
              {
                 commonProperties.push_back(begin->first);
              }
              begin++;
           }
           BREAK_ON_FAILED_HRESULT(hr);
        }
     } while (0);
  
     return hr;
  }
  
  
  
  HRESULT
  addReplace
  (
     const enum TYPE_OF_CHANGE  type,
     const long                 locale,
     const String               &object,
     const String               &property,
     const String               &valueOld,
     const String               &valueNew,
     const HANDLE               fileOut
  )
  {
     LOG_FUNCTION(addReplace);
     ASSERT(
              type==REPLACE_W2K_MULTIPLE_VALUE || 
              type==REPLACE_W2K_SINGLE_VALUE
           );
  
     
     HRESULT hr=S_OK;
  
     do
     {
        String entry;
        entry=String::format
              (
                   L"\r\n"
                   L"\r\n"
                   L"   addChange\r\n"
                   L"   (\r\n"
                   L"      0x%1!x!,\r\n"
                   L"      L\"%2\",\r\n"
                   L"      L\"%3\",\r\n"
                   L"      //%4 \r\n"
                   L"      L\"%5\",\r\n"
                   L"      //%6 \r\n"
                   L"      L\"%7\",\r\n"
                   L"      %8\r\n"
                   L"   );",
                   locale,                              //1
                   object.c_str(),                      //2
                   property.c_str(),                    //3
                   valueOld.c_str(),                    //4
                   escape(valueOld.c_str()).c_str(),    //5
                   valueNew.c_str(),                     //6
                   escape(valueNew.c_str()).c_str(),     //7
                   (type==REPLACE_W2K_SINGLE_VALUE) ?   //8
                    L"REPLACE_Old_SINGLE_VALUE":
                    L"REPLACE_Old_MULTIPLE_VALUE"
              );
  
        
  
        AnsiString ansiEntry;
        String::ConvertResult res=entry.convert(ansiEntry);
        if(res!=String::CONVERT_SUCCESSFUL)
        {
              error=L"Ansi conversion failure";
              hr=E_FAIL;
              break;
        }
  
        hr = FS::Write(fileOut,ansiEntry);
     } while(0);
     return hr;
  }
  
  
  bool
  findI
  (
     const StringList &list,
     const String &value
  )
  {
     LOG_FUNCTION(findI);
     for
     (
        StringList::const_iterator current=list.begin(),end=list.end();
        current!=end;
        current++
     )
     {
        //if(current->icompare(value)==0)
        if(*current==value)
        {
           return true;
        }
     }
     return false;
  }
  
  bool
  findIPartial
  (
     const StringList &list,
     const String &value,
     String &valueFound
  )
  {
     LOG_FUNCTION(findIPartial);
     for
     (
        StringList::const_iterator current=list.begin(),end=list.end();
        current!=end;
        current++
     )
     {
        if(value.size()<=current->size())
        {
           //if(value.icompare( current->substr(0,value.size()) )==0)
           if( value == current->substr(0,value.size()) )
           {
              valueFound=*current;
              return true;
           }
        }
     }
     return false;
  }
  
  
  
  HRESULT
  dealWithMultipleValues
  (
     const long locale,
     const String& object,
     const String& property,
     const StringList &valuesNew,
     const StringList &valuesOld,
     const HANDLE fileOut
  )
  {
     LOG_FUNCTION(dealWithMultipleValues);
  
     StringList::const_iterator bgOld=valuesOld.begin();
     StringList::const_iterator endOld=valuesOld.end();
     HRESULT hr=S_OK;
     do
     {
        while(bgOld!=endOld)
        {
           if (!findI(valuesNew,*bgOld))
           {
              // The value was not found in New
              // The beginning of the value should be found
  
              String beforeComma,valueFound;
              size_t pos=bgOld->find(L',');
              if(pos==String::npos || pos==0)
              {
                 error=String::format
                       (
                          L"(%1!x!,%2,%3) should have comma after 1st position",
                          locale,
                          object.c_str(),
                          property.c_str()
                       );
                 hr=E_FAIL;
                 break;
              }
              // pos+1 will include the comma
              beforeComma=bgOld->substr(0,pos+1);
  
              if(
                    beforeComma.icompare(L"cn,")==0 && 
                    object.icompare(L"domainDNS-Display")==0 && 
                    property.icompare(L"attributeDisplayNames")==0
                )
              {
              // We are opening this exception since
              // this is the only value that had its beforeComma
              // part changed.
                 beforeComma=L"dc,";
              }
  
              if(!findIPartial(valuesNew,beforeComma,valueFound))
              {
                 error=String::format
                       (
                          L"(%1!x!,%2,%3) Value %4 is not in New",
                          locale,
                          object.c_str(),
                          property.c_str(),
                          beforeComma.c_str()
                       );
                 hr=E_FAIL;
                 break;
              }
              hr=addReplace
              (
                 REPLACE_W2K_MULTIPLE_VALUE,
                 locale,
                 object.c_str(),
                 property.c_str(),
                 *bgOld,
                 valueFound,
                 fileOut
              );
              BREAK_ON_FAILED_HRESULT(hr);
           }
           bgOld++;
        }
        BREAK_ON_FAILED_HRESULT(hr);
     } while(0);
  
     return hr;
  
  }
  
  
  // the function bellow is auxiliary in testing
  // how well csvreader performs its tasks of 
  // reading properties. It dumps csvName to fileOut
  HRESULT
  dumpCsv
  (
      const String &csvName,
      const long *locales,
      const HANDLE fileOut
  )
  {
     LOG_FUNCTION(dumpCsv);
     HRESULT hr=S_OK;
  
     do
     {
        CSVDSReader csv;
        hr=csv.read(csvName.c_str(),locales);
        BREAK_ON_FAILED_HRESULT(hr);
  
        const mapOfPositions& pp1=csv.getProperties();
  
        // First we dump all the properties
        mapOfPositions::iterator begin=pp1.begin();
        mapOfPositions::iterator end=pp1.end();
        mapOfProperties prop;
        StringList emptyList;
        while(begin!=end)
        {
           hr=FS::Write(fileOut,begin->first);
           BREAK_ON_FAILED_HRESULT(hr);
           hr=FS::Write(fileOut,L",");
           BREAK_ON_FAILED_HRESULT(hr);
           prop[begin->first]=emptyList;
           begin++;
        }
        BREAK_ON_FAILED_HRESULT(hr);
     
        hr=FS::Write(fileOut,L"\r\n");
        BREAK_ON_FAILED_HRESULT(hr);
  
        bool flagEOF=false;
  
        // Now we will enumerate all csv lines
        hr=csv.initializeGetNext();
        BREAK_ON_FAILED_HRESULT(hr);
  
        do
        {
  
           long loc;
           String obj;
     
           hr=csv.getNextObject(loc,obj,prop);
           BREAK_ON_FAILED_HRESULT(hr);
  
           if(hr==S_FALSE) flagEOF=true;
           if(loc==0) continue;
  
           // now we enumerate each Value set from a property
           mapOfProperties::iterator begin=prop.begin();
           mapOfProperties::iterator end=prop.end();
           mapOfProperties::iterator last=prop.end();
           last--;
           
           while(begin!=end)
           {
  
              if(begin->second.size()!=0)
              {
                 StringList::iterator curValue=begin->second.begin();
                 StringList::iterator endValue=begin->second.end();
                 StringList::iterator lastValue=endValue;
                 lastValue--;
  
                 if( 
                       begin->second.size()>1 || 
                       begin->second.begin()->find(L',')!=String::npos
                   )
                 {
                    hr=FS::Write(fileOut,L"\"");
                    BREAK_ON_FAILED_HRESULT(hr);   
                 }
  
                 while(curValue!=endValue)
                 {
  
                    hr=FS::Write(fileOut,*curValue);
                    BREAK_ON_FAILED_HRESULT(hr);
  
  
                    if(curValue!=lastValue)
                    {
                       hr=FS::Write(fileOut,L";");
                       BREAK_ON_FAILED_HRESULT(hr);   
                    }
                    
                 
                    curValue++;
                 }
                 BREAK_ON_FAILED_HRESULT(hr);
  
                 if( 
                       begin->second.size()>1 || 
                       begin->second.begin()->find(L',')!=String::npos
                   )
                 {
                    hr=FS::Write(fileOut,L"\"");
                    BREAK_ON_FAILED_HRESULT(hr);
                 }
  
              }
  
              if(begin!=last)
              {
                 hr=FS::Write(fileOut,L",");
                 BREAK_ON_FAILED_HRESULT(hr);
              }
  
              begin++;
           }
           BREAK_ON_FAILED_HRESULT(hr);
  
           hr=FS::Write(fileOut,L"\r\n");
           BREAK_ON_FAILED_HRESULT(hr);
     
        } while(!flagEOF);
  
     } while(0);
  
     return hr;
  
  }
  
  
  // Compare the Old and New csv files to check for
  // differences in their common properties that will generate
  // REPLACE_Old entries in fileOut. locales has the set of locales
  // expected to be present in both the csv files.
  HRESULT
  generateChanges
  (
     const String &csvOldName,
     const String &csvNewName,
     const long *locales,
     const HANDLE fileOut
  )
  {
     LOG_FUNCTION(generateChanges);
     HRESULT hr=S_OK;
  
     // bugbug No Longer Necessary
     // Let's add the new objects in a StringList
     // to later use findI to skip csv lines with
     // new objects
     StringList newNewObjects;
     for(long t=0;*NEW_WHISTLER_OBJECTS[t]!=0;t++)
     {
        newNewObjects.push_back(NEW_WHISTLER_OBJECTS[t]);
     }
  
  
     do
     {
        CSVDSReader csvOld;
        hr=csvOld.read(csvOldName.c_str(),locales);
        BREAK_ON_FAILED_HRESULT(hr);
  
        CSVDSReader csvNew;
        hr=csvNew.read(csvNewName.c_str(),locales);
        BREAK_ON_FAILED_HRESULT(hr);
  
        // Now we get the common properties as a StringList
  
        const mapOfPositions& pp1=csvOld.getProperties();
        const mapOfPositions& pp2=csvNew.getProperties();
        
        StringList commonProperties;
  
  	  // bugbug. Get uncommon too and write them as 
  	  // global ADD_ALL_CSV_VALUES changes
        hr=getCommonProperties
           (
              pp1,
              pp2,
              commonProperties
           );
        BREAK_ON_FAILED_HRESULT(hr);
  
        
        // Here we start readding both csv files
        hr=csvOld.initializeGetNext();
        BREAK_ON_FAILED_HRESULT(hr);
        hr=csvNew.initializeGetNext();
        BREAK_ON_FAILED_HRESULT(hr);
  
        // The loop bellow will sequentially read objects 
        // in both csv's making sure the same objects are read.
        bool flagEOF=false;
        do
        {
           mapOfProperties propOld,propNew;
           long locOld,locNew;
           String objOld,objNew;
           
           hr=csvOld.getNextObject(locOld,objOld,propOld);
           if(objOld==L"remoteStorageServicePoint-Display")
           {
              flagEOF=flagEOF;
           }
           LOG(locOld);
           LOG(objOld);
           BREAK_ON_FAILED_HRESULT(hr);
           if(hr==S_FALSE) flagEOF=true;
           
           // The loop bellow skips csv lines with new objects.
           do
           {
  			//bugbug instead of skipping add locale dependent NEW_OBJECT
  			//changes. It will require no parameters since it will use
  			//the latest csv. The loop goes untill the objects are the same
  			//or the new has ended. If the old has ended, clear its object 
  			// to go on with the new
              hr=csvNew.getNextObject(locNew,objNew,propNew);
              BREAK_ON_FAILED_HRESULT(hr);
           } while(hr!=S_FALSE && findI(newNewObjects,objNew));
  		 
  		 //bugbug if the new has ended
  
           BREAK_ON_FAILED_HRESULT(hr);
           if(hr==S_FALSE) flagEOF=true;
  
           if(locNew==0 && locOld==0) continue; 
           // This means blank lines on both csvs. 
           // Blank lines would be common only in the end of
           // the file, but I don't care for them in the middle as long as they are
           // in the same number in both the New and Old csvs.
           // If we have blank lines in only one of the files, the if 
           // bellow will flag it as any other assynchronous result
  
  
           if( (objOld != objNew) || (locOld != locNew) )
           {
              error=String::format
                    (
                       "(%1,%2!x!) should be the same as (%3,%4!x!).",
                       objOld.c_str(),
                       locOld,
                       objNew.c_str(),
                       locNew
                    );
              hr=E_FAIL;
              break;
           }
  
  
           // now let's check the differences in the common properties
           StringList::iterator curCommon=commonProperties.begin();
           StringList::iterator endCommon=commonProperties.end();
           for(;curCommon!=endCommon;curCommon++)
           {
              //bugbug no longer possible
  			/*
              if (isObjectPropertyInChangeList(objOld,*curCommon,changes) )
              {  // It is already taken care of by a global change
                 continue;
              }*/
  
              const StringList &valuesOld=propOld[*curCommon];
              const StringList &valuesNew=propNew[*curCommon];
  
              long Oldlen=valuesOld.size();
              long Newlen=valuesNew.size();
  
              if (Oldlen!=Newlen)
              {
                 error=String::format
                       (
                          L"(%1!x!,%2,%3) should have the same Old(%4!d!) "
                          L"and New(%5!d!) number of values",
                          locOld,
                          objOld.c_str(),
                          curCommon->c_str(),
                          Oldlen,
                          Newlen
                       );
                 hr=E_FAIL;
                 break;
              }
  
              if(Oldlen==1) // and, therefore, Newlen==1
              {
                 if( valuesNew.begin()->icompare(*valuesOld.begin()) != 0 )
                 {
                    hr=addReplace
                    (
                       REPLACE_W2K_SINGLE_VALUE,
                       locOld,
                       objOld.c_str(),
                       curCommon->c_str(),
                       *valuesOld.begin(),
                       *valuesNew.begin(),
                       fileOut
                    );
                    BREAK_ON_FAILED_HRESULT(hr);
                 }
              }
              else if(Oldlen > 1)
              {
                 hr=dealWithMultipleValues
                    (
                       locOld,
                       objOld.c_str(),
                       curCommon->c_str(),
                       valuesNew,
                       valuesOld,
                       fileOut
                    );
                 BREAK_ON_FAILED_HRESULT(hr);
              } // else both are 0 and replacements are not needed
           }
           BREAK_ON_FAILED_HRESULT(hr);
        } while(!flagEOF);
        BREAK_ON_FAILED_HRESULT(hr);
     }
     while(0);
     return hr;
  }
  
  void chk()
  {
  
  	HRESULT hr=S_OK;
  	HANDLE file=NULL;
  	String errors;
  
  	do
  	{
  
  		hr=FS::CreateFile("c:\\public\\dcpromoOld.csv",
  				   file,
  				   GENERIC_READ);
  		if(FAILED(hr)) break;
  
  		int countLine=0;
  
  		bool flagEof=false;
  		while(!flagEof)
  		{
  			String line;
  			hr=ReadLine(file,line);
  			if(hr==EOF_HRESULT)
  			{
  				hr=S_OK;
  				flagEof=true;
  			}
  
  			if(line.empty()) continue;
  
  			if(IsNLSDefinedString(COMPARE_STRING,0,NULL,line.c_str(),line.length())==FALSE)
  			{
  				errors+=String::format(L"line:%1!d! ", countLine+1);
  				wchar_t str[2];
  				str[1]=0;
  				
  				for(int countColumn=0;countColumn<line.length();countColumn++)
  				{
  					str[0]=line[countColumn];
  					if(IsNLSDefinedString(COMPARE_STRING,0,NULL,str,wcslen(str))==FALSE)
  					{
  						errors+=String::format(L"(0x%1!x! at %2!d!)",str[0],countColumn+1);
  					}
  				}
  				errors+=L".\n";
  			}
  			countLine++;
  
  		}
  	}
  	while(0);
  
      if(file!=NULL) CloseHandle(file);
  	MessageBox(NULL,errors.c_str(),L"errors",MB_OK);
  
  }
  
  #include <rpcdce.h>
  
  
  void printGUID(const GUID& g)
  {
  	printf("{%x,%x,%x,{%x,%x,%x,%x,%x,%x,%x,%x}}\n",g.Data1,g.Data2,g.Data3,
  		g.Data4[0],g.Data4[1],g.Data4[2],g.Data4[3],g.Data4[4],g.Data4[5],
  		g.Data4[6],g.Data4[7]);
  	wchar_t *str;
  	if(UuidToString((UUID*)&g,&str)==RPC_S_OK)
  	{
  		wprintf(L" %s\n\n",str);
  		RpcStringFree(&str);
  	}
  }
  
  void __cdecl main( void )
  {
     GUID g1={0,0,1,0,1,2,3,4,5,6,7};
     printGUID(g1);
     if(UuidFromString(L"baddb31b-b428-4103-ae78-3bba5541a20d",&g1)==RPC_S_OK)
     {
  		printGUID(g1);
     }
     else
     {
  	   printf("UUID string is not valid");
     }
  }
  
  /*
  void __cdecl main(int argc,char *argv[])
  {
  	if(argc!=7)
  	{
  		printf("\nThis program generates a new set of changes to be "
  			   "used in dcpromo.lib by comparing the new and previous"
  			   " csv files. Usage:\n\n\"preBuild.exe GUID oldDcpromo "
  			   "newDcpromo old409 new409 targetFolder\"\n\n"
  			   "GUID is the identifier for this set of changes, for example:\n"
  			   "{0x4444C516,0xF43A,0x4c12,0x9C,0x4B,0xB5,0xC0,0x64,0x94,"
  			   "0x1D,0x61}\n\n"
  			   "oldDcpromo is the previous dcpromo.csv\n"
  			   "newDcpromo is the new dcpromo.csv\n"
  			   "old409 is the previous 409.csv\n"
  			   "new409 is the new 409.csv\n\n"
  			   "targetFolder is the sources file for dcpromo.lib,"
  			   " where guids.cpp, and " 
  			   "changes.NNN.cpp will be generated and where the sources "
  			   "file for the display specifier upgrade library is. "
  			   "An entry like: \"changes.NNN.cpp	\\\" will be added "
  			   "at the end targetFolder\\sources.\n\n");
  
  	}
  	else printf(argv[1]);
  }
  */
  
  /*
  
  int WINAPI
  WinMain(
     HINSTANCE   hInstance,
     HINSTANCE,  //hPrevInstance
     LPSTR,      //lpszCmdLine
     int         //nCmdShow
  )
  {
     LOG_FUNCTION(WinMain);
     chk();
     return 0;
  
     hResourceModuleHandle=hInstance;
     
     int argv;
     LPWSTR *argc=CommandLineToArgvW(GetCommandLine(),&argv);
  
     String usage;
     usage =  L"Usage: OldRepl folder outputFile\r\n"
              L"Example: obj\\i386\\OldRepl .\\ ..\\setReplacements.cpp\r\n"
              L"folder must have four files: \r\n"
              L"    win2k.dcpromo.csv\r\n"
              L"    whistler.dcpromo.csv\r\n"
              L"    win2k.409.csv\r\n"
              L"    whistler.409.csv\r\n"
              L" Don't forget to checkout the output file if\r\n"
              L" it is under source control.\r\n";
  
  
     if(argv!=3)
     {
        MessageBox(NULL,usage.c_str(),L"Two arguments required.",MB_OK);
        return 0;
     }
  
     
     String path = FS::NormalizePath(argc[1]);
     String outFileName = FS::NormalizePath(argc[2]);
     String dcpromoNew = path+L"whistler.dcpromo.csv";
     String dcpromoOld = path+L"win2k.dcpromo.csv";
     String csv409New = path+L"whistler.409.csv";
     String csv409Old = path+L"win2k.409.csv";
  
     if( 
           !FS::FileExists(dcpromoNew)    ||
           !FS::FileExists(dcpromoOld)   ||
           !FS::FileExists(csv409New)     ||
           !FS::FileExists(csv409Old)
       )
     {
        MessageBox(NULL,usage.c_str(),L"Some file doesn't exist",MB_OK);
        return 0;
     }
     
     
  
     HANDLE outFile=INVALID_HANDLE_VALUE;
     HRESULT hr=S_OK;
     hr=FS::CreateFile(   outFileName,
                          outFile,
                          GENERIC_WRITE,
                          FILE_SHARE_READ,
                          CREATE_ALWAYS);
  
     if FAILED(hr)
     {
        MessageBox(NULL,L"Problems to create output file",L"Error",MB_OK);
        LOG_HRESULT(hr);
        return hr;
     }
  
     do
     {
  
        AnsiString header;
        header = "// This file is generated by OldRepl.exe\r\n"
                 "// Copyright (c) 2001 Microsoft Corporation\r\n"
                 "// Jun 2001 lucios\r\n"
                 "\r\n"
                 "#include \"headers.hxx\"\r\n"
                 "#include \"constants.hpp\"\r\n"
                 "\r\n"
                 "void setReplacementChanges()\r\n"
                 "{";
  
        hr =  FS::Write(outFile,header);
        BREAK_ON_FAILED_HRESULT(hr);
  
  
        hr=generateChanges
           (
              dcpromoOld,
              dcpromoNew,
              LOCALEIDS,
              outFile
           );
        BREAK_ON_FAILED_HRESULT(hr);
        hr=generateChanges
           (
              csv409Old,
              csv409New,
              LOCALE409,
              outFile
           );
        BREAK_ON_FAILED_HRESULT(hr);
  
        AnsiString tail="\r\n}\r\n";
  
        hr =  FS::Write(outFile,tail);
        BREAK_ON_FAILED_HRESULT(hr);
        //hr=dumpCsv(dcpromoOld,LOCALEIDS,outFile);
        //hr=dumpCsv(csv409Old,LOCALE409,outFile);
        //BREAK_ON_FAILED_HRESULT(hr);
  
     } while(0);
  
  
     CloseHandle(outFile);
  
     if(FAILED(hr))
     {
        MessageBox(NULL,error.c_str(),L"Error",MB_OK);
     }
     else
     {
        MessageBox(NULL,L"Generation Successful",L"Success",MB_OK);
     }
     return 1;
  
  }
  */