/****************************************************************************\ 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 #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; }