www.pudn.com > Uconvert.zip > INSTALL.C


/**************************************************************************\ 
* install.c -- install c_*.nls conversion tables. 
* 
*         Steve Firebaugh 
*         Microsoft Developer Support 
*         Copyright (c) 1992-1997 Microsoft Corporation 
* 
* 
* 
* Note, this module must have UNICODE defined because the registry 
*  code will not work without it. 
* 
\**************************************************************************/ 
#define UNICODE 
 
#include  
#include  
#include  
#include  
#include "uconvert.h" 
#include "install.h" 
 
/**************************************************************************\ 
*  Global variables. 
\**************************************************************************/ 
 
/* This is the registry key that we store conversion table information under. */ 
TCHAR NlsRegEntryStr[]=TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage"); 
 
 
/***************************************************************************\ 
*    FUNCTION: InstallTableProc 
* 
* Dialog window procedure for the Install *.nls tables dialog. 
* 
\***************************************************************************/ 
LRESULT CALLBACK InstallTableProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
 
 
  switch (message) { 
 
    /**********************************************************************\ 
    *  WM_INITDIALOG 
    * 
    * Fill dialog with a list of the currently existing tables. 
    \**********************************************************************/ 
    case WM_INITDIALOG: 
      if (!ListInstalledTables (GetDlgItem (hwnd, DID_LISTBOX), LB_ADDSTRING, FALSE)) 
        EndDialog (hwnd, FALSE); 
        return TRUE; 
    break; 
 
    case WM_COMMAND: 
      switch (wParam) { 
        case IDCANCEL: 
        case IDOK: 
          EndDialog (hwnd, TRUE); 
        break; 
 
 
        /**********************************************************************\ 
        *  WM_COMMAND, BID_ADD 
        * 
        * Use common dialog, get new *.nls name, and try to install it. 
        \**********************************************************************/ 
        case BID_ADD: 
          if (GetTableFileNames(hwnd)) 
            ListInstalledTables (GetDlgItem (hwnd, DID_LISTBOX), LB_ADDSTRING, FALSE); 
        break; 
      } 
    break; /* end WM_COMMAND */ 
 
 
    case WM_SYSCOMMAND: 
      if (wParam == SC_CLOSE) 
        EndDialog (hwnd, TRUE); 
    break; /* end WM_SYSCOMMAND */ 
 
 
  } /* end switch */ 
  return FALSE; 
} 
 
 
 
/***************************************************************************\ 
*    FUNCTION: GetTableFileNames 
* 
* Throw up a common dialog to the user, and let them search for the *.nls 
*  file to install. 
* 
* LIMITATION:  Currently only works for one file at a time. 
*  Should rewrite to accept multiple files. 
* 
\***************************************************************************/ 
int GetTableFileNames (HWND hwnd) 
{ 
    OPENFILENAME OpenFileName; 
 
 
    /* buffers for the file names. */ 
    TCHAR szFile[MAX_PATH],szFileTitle[MAX_PATH]; 
    TCHAR szFilter[MAX_PATH], buffer[50]; 
    TCHAR *p; 
 
    /* Build up the correct filter strings for OPENFILENAME structure */ 
 
    p = szFilter; 
    lstrcpy (buffer,LoadResourceString(IDS_FILE_FILTER_SPEC4)); 
    lstrcpy (p,buffer); 
    p += lstrlen (buffer) +1; 
    lstrcpy (buffer,TEXT("*.nls")); 
    lstrcpy (p,buffer); 
    p += lstrlen (buffer) +1; 
 
    lstrcpy (p,TEXT("\0")); 
 
 
    wsprintf (szFile, TEXT("")); 
    wsprintf (szFileTitle, TEXT("")); 
 
    OpenFileName.lStructSize       = sizeof(OPENFILENAME); 
    OpenFileName.hwndOwner         = hwnd; 
    OpenFileName.hInstance         = NULL; 
    OpenFileName.lpstrFilter       = szFilter; 
    OpenFileName.lpstrCustomFilter = NULL; 
    OpenFileName.nMaxCustFilter    = 0L; 
    OpenFileName.nFilterIndex      = 1L; 
    OpenFileName.lpstrFile         = szFile; 
    OpenFileName.nMaxFile          = MAX_PATH; 
    OpenFileName.lpstrFileTitle    = szFileTitle; 
    OpenFileName.nMaxFileTitle     = MAX_PATH; 
    OpenFileName.lpstrInitialDir   = NULL; 
    OpenFileName.lpstrTitle        = LoadResourceString(IDS_TABLE_FILE_TITLE); 
 
    OpenFileName.nFileOffset       = 0; 
    OpenFileName.nFileExtension    = 0; 
    OpenFileName.lpstrDefExt       = NULL; 
 
    OpenFileName.lCustData         = 0; 
    OpenFileName.lpfnHook          = NULL; 
    OpenFileName.lpTemplateName    = NULL; 
 
//    OpenFileName.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT; 
    OpenFileName.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST ; 
 
    if (!GetOpenFileName(&OpenFileName)) return 0; 
 
 
    return (InstallFile (szFile,szFileTitle)); 
} 
 
 
 
 
/***************************************************************************\ 
*    FUNCTION: InstallFile 
* 
* Given full path name, and just file name, copy that file into the 
*  system directory, and change the registry to indicate that the file 
*  has now been "installed." 
* 
\***************************************************************************/ 
int InstallFile (TCHAR* szPathAndName, TCHAR* szName) 
{ 
TCHAR szTargetFile[MAX_PATH], buffer[MAX_PATH]; 
TCHAR keyname[MAX_PATH]; 
HKEY hKey; 
int cp, nChar; 
LONG rValue; 
 
    /* First verify that they have selected a valid file name. */ 
    CharLowerBuff (szName,lstrlen (szName)); 
    if (myScanf (szName, &cp) != 1) { 
      MessageBox (NULL, LoadResourceString(IDS_INCORRECT_FILE_TYPE), 
                        NULL, MB_ICONSTOP | MB_OK); 
      return FALSE; 
    } 
 
 
 
 
    /* Build up a complete path name for the target file. 
     *  Get the system directory, and prepend it before szName. 
     */ 
    GetSystemDirectory (buffer, MAX_PATH); 
    nChar = wsprintf (szTargetFile, TEXT("%s\\%s"), buffer, szName); 
 
    if (nChar >= MAX_PATH) { 
      MessageBox (NULL, LoadResourceString(IDS_FILENAME_OVERFLOW),NULL, MB_ICONSTOP | MB_OK); 
      return FALSE; 
    } 
 
 
 
    /* Now, try to open the registry for writing... This may fail if 
     *  the current user has insufficient privilege, or it may fail 
     *  for other, unforeseen, reasons. 
     */ 
    rValue = RegOpenKeyEx (HKEY_LOCAL_MACHINE, NlsRegEntryStr, 0, KEY_SET_VALUE, &hKey); 
    if (rValue == ERROR_ACCESS_DENIED) { 
      MessageBox (NULL, LoadResourceString(IDS_LOGON_AS_ADMIN), 
               LoadResourceString(IDS_ACCESS_DENIED), MB_ICONSTOP | MB_OK); 
      return FALSE; 
    } 
    if (rValue != ERROR_SUCCESS) { 
      MessageBox (NULL, LoadResourceString(IDS_REGOPENKEYEX_FAILED),NULL, MB_ICONSTOP | MB_OK); 
      return FALSE; 
    } 
 
 
    /* Try to copy file... one reason for failure is file already 
     *  exists.  If so, query the user to try again. 
     *  If fails again, just report problem and exit. 
     */ 
    if (!CopyFile (szPathAndName, szTargetFile, TRUE)) { 
 
      /* if failure was from existing file, query user preference 
       *  regarding replacing it. 
       */ 
      if (GetLastError() == ERROR_FILE_EXISTS) { 
        if (MessageBox (NULL, LoadResourceString(IDS_FILE_ALREADY_EXISTS), 
                        LoadResourceString(IDS_APP_WARNING), 
                        MB_ICONEXCLAMATION | MB_YESNO) == IDNO) { 
          goto close_and_exit; 
        } else { 
          if (!CopyFile (szPathAndName, szTargetFile, FALSE)) { 
            MessageBox (NULL, LoadResourceString(IDS_FILE_CP_FAILED_AGAIN), 
                          NULL, MB_ICONSTOP | MB_OK); 
            goto close_and_exit; 
          } 
        } 
 
      /* no duplicate file, CopyFile() failed for other reasons 
       *  report failure and return. 
       */ 
      } else { 
        MessageBox (NULL, LoadResourceString(IDS_FILE_CP_FAILED), 
                      NULL, MB_ICONSTOP | MB_OK); 
        goto close_and_exit; 
 
      } 
    } 
 
 
    /* Finally, write the new key value to the registry. */ 
    if (myScanf (szName, &cp) == 1) { 
      wsprintf (keyname, TEXT("%d"), cp); 
      RegSetValueEx (hKey, keyname, 0, REG_SZ, (LPBYTE)szName, 
                     (DWORD)((lstrlen(szName) +1)*sizeof(TCHAR))); 
 
    } else 
      MessageBox (NULL, szName, LoadResourceString(IDS_FILE_PARSE_FAILED), 
              MB_ICONSTOP | MB_OK); 
 
 
close_and_exit: 
 
    RegCloseKey (hKey); 
 
    return TRUE; 
} 
 
 
/***************************************************************************\ 
*    FUNCTION: ListInstalledTables 
* 
* Display the *.nls conversion tables currently installed, according to the 
*  registry.  Display either the file name, or just the codepage number. 
* 
* hwndFill - listbox or combobox to fill with names. 
* message - LB_ADDSTRING or CB_ADDSTRING 
* NumberOnly - FALSE then use full file name, TRUE then just use number. 
* 
* CRITERION for table being installed: 
*  value in registry is c_* where * is number. 
* 
\***************************************************************************/ 
int ListInstalledTables (HWND hwndFill, UINT message, int NumberOnly) 
{ 
 
  TCHAR szKeyname[MAX_PATH], szValue[MAX_PATH]; 
  DWORD cBytesName, cBytesValue, iSubKey; 
  int  cp; 
  HKEY hKey; 
 
  /* open the registry key for reading.  If failure, report and exit. */ 
  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, NlsRegEntryStr, 0, KEY_QUERY_VALUE, &hKey)) { 
    MessageBox (NULL, LoadResourceString(IDS_REGOPENKEYEX_FAILED), 
            NULL, MB_ICONSTOP | MB_OK); 
    return FALSE; 
  } 
 
 
  /* empty the current contents. */ 
  if (message == LB_ADDSTRING) 
    SendMessage (hwndFill, LB_RESETCONTENT, 0, 0); 
  else if (message == CB_ADDSTRING) 
    SendMessage (hwndFill, CB_RESETCONTENT, 0, 0); 
 
 
  iSubKey = 0; 
  cBytesName = cBytesValue = MAX_PATH; 
  while (!RegEnumValue (hKey, iSubKey, szKeyname, &cBytesName, NULL, NULL, (LPBYTE)szValue, &cBytesValue)) { 
 
    if (myScanf (szValue, &cp) == 1) { 
 
      /* if we are to display only the number, then reformat szValue string */ 
      if (NumberOnly) 
        wsprintf (szValue, TEXT("%d"), cp); 
 
 
      SendMessage (hwndFill, message, 0 ,(LPARAM) szValue); 
    } 
 
    iSubKey++; 
    cBytesName = cBytesValue = MAX_PATH;  // undoc.ed feature, must be set each time. 
  } 
 
  RegCloseKey (hKey); 
 
  return TRUE; 
} 
 
 
 
 
 
 
 
 
/***************************************************************************\ 
*    FUNCTION: myScanf 
* 
* Convert a string into a number (like sscanf). 
*  However, this function works independent of UNICODE turned on. 
* 
* NOT a general function... looking for "c_%d.nls" 
* 
\***************************************************************************/ 
int myScanf (TCHAR* pSource, int* pValue) 
{ 
char ansibuffer[MAX_PATH]; 
int iStrLen; 
 
  iStrLen = lstrlen (pSource); 
  if (iStrLen == 0) return 0; 
 
#ifdef UNICODE 
  WideCharToMultiByte (CP_ACP, 0, pSource, -1, 
           ansibuffer, MAX_PATH, NULL, NULL); 
#else 
  lstrcpy (ansibuffer, pSource); 
#endif 
 
  CharLowerBuffA (ansibuffer,lstrlenA (ansibuffer)); 
 
  return (sscanf (ansibuffer, "c_%d.nls", pValue)); // leave off TEXT() 
}