#include <windows.h>
#include "common.h"

#define BLOCKLEN 100

#ifndef DBCS
#define AnsiNext(x) ((x)+1)
#endif

LPSTR lpMerge;
char szDotClasses[] = "\\.classes\\";
char szHkeyClassesRoot[] = "HKEY_CLASSES_ROOT\\";

extern HWND hWndHelp;

extern unsigned long NEAR PASCAL MySetValue(HKEY hKey, PSTR pSubKey, PSTR pVal);

NEAR PASCAL
ImportWin40RegFile(
    VOID
    );

static PSTR NEAR PASCAL GetFileLine(void)
{
   static HANDLE hFile = NULL;
   static PSTR pFile;
   static WORD wLen;

   LPSTR lpStart;
   HANDLE hTemp;
   WORD wLineLen;
   char cFile;

/* We need a place to put the file line */
   if(!hFile) {
      if(!(hFile=LocalAlloc(LMEM_MOVEABLE, wLen=BLOCKLEN)))
         goto Error1;
      if(!(pFile=LocalLock(hFile)))
         goto Error2;
   }

/* If we have read the whole file, then clean up and return */
   if(!*lpMerge)
      goto Error3;

   for(lpStart=lpMerge; ; ) {
      cFile = *lpMerge;
      lpMerge = AnsiNext(lpMerge);

      switch(cFile) {
      case('\n'):
      case('\r'):
      case('\0'):
/* EOL so return */
         goto CopyLine;
      }
   }

CopyLine:
   wLineLen = lpMerge - lpStart - 1;
/* Make the buffer larger if necessary */
   if(wLineLen >= wLen) {
      LocalUnlock(hFile);
      wLen = wLineLen + BLOCKLEN;
      if(!(hTemp=LocalReAlloc(hFile, wLen, LMEM_MOVEABLE)))
         goto Error2;
      if(!(pFile=LocalLock(hFile=hTemp)))
         goto Error2;
   }
   RepeatMove(pFile, lpStart, wLineLen);
   pFile[wLineLen] = '\0';
   return(pFile);


Error3:
   LocalUnlock(hFile);
Error2:
   LocalFree(hFile);
   hFile = NULL;
Error1:
   return(NULL);
}

static VOID NEAR PASCAL MergeFileData(void)
{
  static struct tagKEYANDROOT
    {
      PSTR szKey;
      HKEY hKeyRoot;
    } krClasses[] =
    {
      szHkeyClassesRoot, HKEY_CLASSES_ROOT,
      szDotClasses, HKEY_CLASSES_ROOT
    } ;
#define NUM_KEYWORDS (sizeof(krClasses)/sizeof(krClasses[0]))

  PSTR pLine;
  PSTR pLast;
  HKEY hKeyRoot, hSubKey;
  int i;

  /* Get the initial line if this is the first time through */
  if(!(pLine=GetFileLine()))
      return;
  /* Otherwise, open a key so that we only do one write to the disk */
  if(RegCreateKey(HKEY_CLASSES_ROOT, NULL, &hSubKey) != ERROR_SUCCESS)
      return;

  do
    {
      for (i=0; i<NUM_KEYWORDS; ++i)
	{
	  char cTemp;
	  int nCmp, nLen;

	  cTemp = pLine[nLen=lstrlen(krClasses[i].szKey)];
	  pLine[nLen] = '\0';
	  nCmp = lstrcmp(krClasses[i].szKey, pLine);
	  pLine[nLen] = cTemp;
	  if (!nCmp)
	    {
	      pLine += nLen;
	      hKeyRoot = krClasses[i].hKeyRoot;
	      goto MergeTheData;
	    }
	}
      continue;

MergeTheData:
      /* This is a line that needs to get merged.
       * Find a space (and then skip spaces) or "= " */
      for(pLast=pLine; *pLast; pLast=AnsiNext(pLast))
	{
	  if(*pLast == ' ')
	    {
	      *pLast = '\0';
	      while(*(++pLast) == ' ')
		  /* find the first non-space */ ;
	      break;
	    }
	}

      /* There is an error if we don't have "= " */
      if(*pLast=='=' && *(++pLast)==' ')
	 ++pLast;

      /* Set the value */
      MySetValue(hKeyRoot, pLine, pLast);
    } while(pLine=GetFileLine()) ;

  RegCloseKey(hSubKey);
}


VOID NEAR PASCAL ProcessFiles(HWND hDlg, HANDLE hCmdLine, WORD wFlags)
{
   HANDLE hMerge, hHeader;
   PSTR pHeader;
   int hFile;
   LONG lSize;
   LPSTR lpFileName, lpTemp;
   OFSTRUCT of;
   WORD wErrMsg;

   lpFileName = GlobalLock(hCmdLine);
/* We need to process all file names on the command line */
   while(lpTemp=MyStrTok(lpFileName, ' ')) {
/* Open the file */
      wErrMsg = IDS_CANTOPENFILE;
      if((hFile=OpenFile(lpFileName, &of, OF_READ)) == -1)
         goto Error2;

/* Determine the file size; limit it to just less than 64K */
      wErrMsg = IDS_CANTREADFILE;
      if((lSize=_llseek(hFile, 0L, 2))==-1 || lSize>0xfff0)
         goto Error3;
      _llseek(hFile, 0L, 0);

/* Allocate a block of memory for the file */
      wErrMsg = IDS_OUTOFMEMORY;
      if(!(hMerge=GlobalAlloc(GHND, lSize+2)))
         goto Error3;
      if(!(lpMerge=GlobalLock(hMerge)))
         goto Error4;

/* Read in the file */
      wErrMsg = IDS_CANTREADFILE;
      if(_lread(hFile, lpMerge, LOWORD(lSize)) != LOWORD(lSize))
         goto Error5;

/* Look for the header */
      wErrMsg = IDS_OUTOFMEMORY;
      if(!(hHeader=MyLoadString(IDS_REGHEADER, NULL, LMEM_MOVEABLE)))
         goto Error5;
      pHeader = LocalLock(hHeader);

      wErrMsg = IDS_BADFORMAT;
      while(*lpMerge == ' ')
         ++lpMerge;
      while(*pHeader)
         if(*lpMerge++ != *pHeader++)
            goto Error6;
      if(*lpMerge=='4')
       {
        ImportWin40RegFile();
        wErrMsg = IDS_SUCCESSREAD;
        goto Error6;
       }
      while(*lpMerge == ' ')
         ++lpMerge;
      if(*lpMerge!='\r' && *lpMerge!='\n')
         goto Error6;

/* Merge the data */
      MergeFileData(); /* This makes the changes */

      wErrMsg = IDS_SUCCESSREAD;
Error6:
      LocalUnlock(hHeader);
      LocalFree(hHeader);
Error5:
      GlobalUnlock(hMerge);
Error4:
      GlobalFree(hMerge);
Error3:
      _lclose(hFile);
Error2:
/* Display the status message */
      if(!(wFlags&FLAG_SILENT) || wErrMsg!=IDS_SUCCESSREAD)
         MyMessageBox(hDlg, wErrMsg, MB_OK | MB_ICONEXCLAMATION,
	       lstrlen(lpFileName), lpFileName);

      lpFileName = lpTemp;
      while(*lpFileName == ' ')
         ++lpFileName;
   }

   GlobalUnlock(hCmdLine);

   GlobalFree(hCmdLine);
}