windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/langinst/main.c
2020-09-26 16:20:57 +08:00

368 lines
12 KiB
C

/****************************************************************************\
MAIN.C / OPK Wizard (OPKWIZ.EXE)
Microsoft Confidential
Copyright (c) Microsoft Corporation 1999
All rights reserved
Main source file for the OPK Wizard. Contains WinMain() and global
variable declarations.
4/99 - Jason Cohen (JCOHEN)
Added this new main source file for the OPK Wizard as part of the
Millennium rewrite.
09/2000 - Stephen Lodwick (STELO)
Ported OPK Wizard to Whistler
\****************************************************************************/
//
// Include File(s):
//
#include <tchar.h>
#include "opklib.h"
#include "resource.h"
//
// Global Variable(s):
//
TCHAR g_szSource[MAX_PATH] = NULLSTR;
BOOL g_bQuiet = FALSE;
STRRES g_srLangs[] =
{
{ _T("ENG"), IDS_ENG },
{ _T("GER"), IDS_GER },
{ _T("ARA"), IDS_ARA },
{ _T("CHH"), IDS_CHH },
{ _T("CHT"), IDS_CHT },
{ _T("CHS"), IDS_CHS },
{ _T("HEB"), IDS_HEB },
{ _T("JPN"), IDS_JPN },
{ _T("KOR"), IDS_KOR },
{ _T("BRZ"), IDS_BRZ },
{ _T("CAT"), IDS_CAT },
{ _T("CZE"), IDS_CZE },
{ _T("DAN"), IDS_DAN },
{ _T("DUT"), IDS_DUT },
{ _T("FIN"), IDS_FIN },
{ _T("FRN"), IDS_FRN },
{ _T("GRK"), IDS_GRK },
{ _T("HUN"), IDS_HUN },
{ _T("ITN"), IDS_ITN },
{ _T("NOR"), IDS_NOR },
{ _T("POL"), IDS_POL },
{ _T("POR"), IDS_POR },
{ _T("RUS"), IDS_RUS },
{ _T("SPA"), IDS_SPA },
{ _T("SWE"), IDS_SWE },
{ _T("TRK"), IDS_TRK },
{ NULL, 0 },
};
//
// Internal Defined Value(s):
//
#define FILE_INF _T("langinst.inf")
#define DIR_LANG _T("lang")
#define INF_SEC_FILES _T("files")
#define INF_SEC_LANG _T("strings")
#define INF_KEY_LANG _T("lang")
#define COPYFILE_FLAG_RENAME 0x00000001
#define REG_KEY_OPK _T("SOFTWARE\\Microsoft\\OPK")
#define REG_KEY_OPK_LANGS REG_KEY_OPK _T("\\Langs")
#define REG_VAL_PATH _T("Path")
#define STR_OPT_QUIET _T("quiet")
//
// Internal Function Prototype(s):
//
static DWORD InstallLang(LPTSTR lpszInfFile, LPTSTR lpszSrcRoot, LPTSTR lpszDstRoot);
static BOOL ParseCmdLine();
//
// Main Function:
//
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int nReturn = 0;
if ( ParseCmdLine() && g_szSource[0] )
{
TCHAR szInfFile[MAX_PATH],
szDestination[MAX_PATH] = NULLSTR,
szLang[32] = NULLSTR;
LPTSTR lpLang;
HKEY hKey;
// Figure out our destination is based on the OPK tools install path.
//
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_OPK, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS )
{
DWORD dwType,
dwSize = AS(szDestination);
if ( ( RegQueryValueEx(hKey, REG_VAL_PATH, NULL, &dwType, (LPBYTE) szDestination, &dwSize) != ERROR_SUCCESS ) ||
( dwType != REG_SZ ) )
{
szDestination[0] = NULLCHR;
}
RegCloseKey(hKey);
}
// Create the path to the inf file we need on the source.
//
lstrcpyn(szInfFile, g_szSource,AS(szInfFile));
AddPathN(szInfFile, FILE_INF,AS(szInfFile));
// Make sure we have the source file and destination directory and lang.
//
if ( ( szDestination[0] ) &&
( DirectoryExists(szDestination) ) &&
( FileExists(szInfFile) ) &&
( GetPrivateProfileString(INF_SEC_LANG, INF_KEY_LANG, NULLSTR, szLang, AS(szLang), szInfFile) ) &&
( szLang[0] ) &&
( lpLang = AllocateStrRes(NULL, g_srLangs, AS(g_srLangs), szLang, NULL) ) )
{
// Now make sure the actually want to instlall it.
//
if ( g_bQuiet || ( MsgBox(NULL, IDS_ASK_INSTALL, IDS_APPNAME, MB_ICONQUESTION | MB_YESNO, lpLang) == IDYES ) )
{
// Now finish creating the root destination path.
//
AddPathN(szDestination, DIR_LANG,AS(szDestination));
AddPathN(szDestination, szLang,AS(szDestination));
// Now actually copy the files.
//
if ( nReturn = InstallLang(szInfFile, g_szSource, szDestination) )
{
// Just return 1 for success.
//
nReturn = 1;
// Set a registry key so we know that the tools for this lang are installed.
//
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_OPK_LANGS, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS )
{
DWORD dwVal = 1;
RegSetValueEx(hKey, szLang, 0, REG_DWORD, (LPBYTE) &dwVal, sizeof(DWORD));
RegCloseKey(hKey);
}
}
else
{
// Error copying files.
//
MsgBox(NULL, IDS_ERR_FILECOPY, IDS_APPNAME, MB_ERRORBOX, UPPER(szDestination[0]));
}
}
FREE(lpLang);
}
}
return nReturn;
}
//
// Internal Function(s):
//
static DWORD InstallLang(LPTSTR lpszInfFile, LPTSTR lpszSrcRoot, LPTSTR lpszDstRoot)
{
HINF hInf;
DWORD dwErr,
dwRet = 0;
BOOL bRet = TRUE;
// Open our inf that has all the data we need.
//
if ( (hInf = SetupOpenInfFile(lpszInfFile, NULL, INF_STYLE_WIN4, &dwErr)) != INVALID_HANDLE_VALUE )
{
BOOL bLoop;
INFCONTEXT InfContext;
// Loop thru each line in the section we are searching.
//
for ( bLoop = SetupFindFirstLine(hInf, INF_SEC_FILES, NULL, &InfContext);
bLoop && bRet;
bLoop = SetupFindNextLine(&InfContext, &InfContext) )
{
DWORD dwFlags = 0;
LPTSTR lpszSrcName = NULL,
lpszDstName = NULL;
TCHAR szSrcFile[MAX_PATH] = NULLSTR,
szDstFile[MAX_PATH] = NULLSTR,
szSrcFull[MAX_PATH] = NULLSTR,
szDstFull[MAX_PATH] = NULLSTR,
szSrcPath[MAX_PATH],
szDstPath[MAX_PATH];
// Get the source path and filename.
//
if ( !SetupGetStringField(&InfContext, 1, szSrcFile, AS(szSrcFile), NULL) )
szSrcFile[0] = NULLCHR;
// Get the destination path.
//
if ( !SetupGetStringField(&InfContext, 2, szDstFile, AS(szDstFile), NULL) )
szDstFile[0] = NULLCHR;
// Get any flags passed in.
//
if ( !SetupGetIntField(&InfContext, 3, &dwFlags) )
dwFlags = 0;
// Make sure we have the required data in this line.
//
if ( szSrcFile[0] && szDstFile[0] )
{
// Create the full path of the source file.
//
lstrcpyn(szSrcPath, lpszSrcRoot, AS(szSrcPath));
AddPathN(szSrcPath, szSrcFile,AS(szSrcPath));
if ( GetFullPathName(szSrcPath, AS(szSrcFull), szSrcFull, &lpszSrcName) &&
szSrcFull[0] &&
lpszSrcName &&
FileExists(szSrcFull) )
{
// If the destination is NULL or empty, we just want a file count.
//
if ( lpszDstRoot && *lpszDstRoot )
{
// Create the full path of the destination directory.
//
lstrcpyn(szDstPath, lpszDstRoot,AS(szDstPath));
AddPathN(szDstPath, szDstFile,AS(szDstPath));
if ( !(dwFlags & COPYFILE_FLAG_RENAME) )
AddPathN(szDstPath, lpszSrcName,AS(szDstPath));
if ( GetFullPathName(szDstPath, AS(szDstFull), szDstFull, &lpszDstName) &&
szDstFull[0] &&
lpszDstName )
{
// We want just the path part of the destination file name.
//
lstrcpyn(szDstPath, szDstFull, (int)(lpszDstName - szDstFull));
// Now make sure the path exists and actually copy the file.
//
if ( ( DirectoryExists(szDstPath) || CreatePath(szDstPath) ) &&
( CopyResetFile(szSrcFull, szDstFull) ) )
{
dwRet++;
}
else
bRet = FALSE;
}
}
else
dwRet++;
}
}
}
// We are done, so close the INF file.
//
SetupCloseInfFile(hInf);
}
return bRet ? dwRet : 0;
}
static BOOL ParseCmdLine()
{
DWORD dwArgs;
LPTSTR *lpArgs;
BOOL bError = FALSE;
if ( (dwArgs = GetCommandLineArgs(&lpArgs) ) && lpArgs )
{
LPTSTR lpArg;
DWORD dwArg;
// We want to skip over the first argument (it is the path
// to the command being executed.
//
if ( dwArgs > 1 )
{
dwArg = 1;
lpArg = *(lpArgs + dwArg);
}
else
lpArg = NULL;
// Loop through all the arguments.
//
while ( lpArg && !bError )
{
// Now we check to see if the first char is a dash or not.
//
if ( ( *lpArg == _T('-') ) ||
( *lpArg == _T('/') ) )
{
LPTSTR lpOption = CharNext(lpArg);
//
// This is where you add command line options that start with a dash (-).
//
// Set bError if you don't recognize the command line option (unless you
// want to just ignore it and continue).
//
if ( LSTRCMPI(lpOption, STR_OPT_QUIET) == 0 )
g_bQuiet = TRUE;
else
bError = TRUE;
}
else if ( *lpArg )
{
//
// This is where you would read any command line parameters that are just passed
// in on the command line w/o any proceeding characters (like - or /).
//
// Set bError if you don't have any of these types of parameters (unless you
// want to just ignore it and continue).
//
if ( g_szSource[0] == NULLCHR )
lstrcpy(g_szSource, lpArg);
else
bError = TRUE;
}
// Setup the pointer to the next argument in the command line.
//
if ( ++dwArg < dwArgs )
lpArg = *(lpArgs + dwArg);
else
lpArg = NULL;
}
// Make sure to free the two buffers allocated by the GetCommandLineArgs() function.
//
FREE(*lpArgs);
FREE(lpArgs);
}
return !bError;
}