/*++ Copyright (c) 1995 Microsoft Corporation Module Name: intl.c Abstract: Module with code for NLS-related stuff. This module is designed to be used with intl.inf and font.inf by control panel applets. Author: Ted Miller (tedm) 15-Aug-1995 Revision History: --*/ #include "setupp.h" #pragma hdrstop // // This structure and the callback function below are used to set the // hidden attribute bit on certain font files. That bit causes the font folder // app to not autoinstall these files. // typedef struct _FONTQCONTEXT { PVOID SetupQueueContext; HINF FontInf; } FONTQCONTEXT, *PFONTQCONTEXT; PCWSTR szHiddenFontFiles = L"HiddenFontFiles"; UINT pSetupFontQueueCallback( IN PFONTQCONTEXT Context, IN UINT Notification, IN UINT Param1, IN UINT Param2 ) { PFILEPATHS FilePaths; PWCHAR p; INFCONTEXT InfContext; // // If a file is finished being copied, set its attributes // to include the hidden attribute if necessary. // if((Notification == SPFILENOTIFY_ENDCOPY) && (FilePaths = (PFILEPATHS)Param1) && (FilePaths->Win32Error == NO_ERROR) && (p = wcsrchr(FilePaths->Target,L'\\')) && SetupFindFirstLine(Context->FontInf,szHiddenFontFiles,p+1,&InfContext)) { SetFileAttributes(FilePaths->Target,FILE_ATTRIBUTE_HIDDEN); } return(SetupDefaultQueueCallback(Context->SetupQueueContext,Notification,Param1,Param2)); } VOID pSetupMarkHiddenFonts( VOID ) { HINF hInf; INFCONTEXT InfContext; BOOL b; WCHAR Path[MAX_PATH]; PWCHAR p; PCWSTR q; int Space; hInf = SetupOpenInfFile(L"FONT.INF",NULL,INF_STYLE_WIN4,NULL); if(hInf != INVALID_HANDLE_VALUE) { GetWindowsDirectory(Path,MAX_PATH); lstrcat(Path,L"\\FONTS\\"); p = Path + lstrlen(Path); Space = MAX_PATH - (p - Path); if(SetupFindFirstLine(hInf,szHiddenFontFiles,NULL,&InfContext)) { do { if(q = pSetupGetField(&InfContext,0)) { lstrcpyn(p,q,Space); if(FileExists(Path,NULL)) { SetFileAttributes(Path,FILE_ATTRIBUTE_HIDDEN); } } } while(SetupFindNextLine(&InfContext,&InfContext)); } SetupCloseInfFile(hInf); } } DWORD pSetupNLSInstallFonts( IN HWND Window, IN HINF InfHandle, IN PCWSTR OemCodepage, IN PCWSTR FontSize, IN HSPFILEQ FileQueue ) { BOOL b; WCHAR SectionName[64]; // // Form section name. // wsprintf(SectionName,L"Font.CP%s.%s",OemCodepage,FontSize); if(FileQueue) { // // First pass: just enqueue files for copy. // b = SetupInstallFilesFromInfSection( InfHandle, NULL, FileQueue, SectionName, NULL, SP_COPY_NEWER ); } else { // // Second pass: do registry munging, etc. // b = SetupInstallFromInfSection( Window, InfHandle, SectionName, SPINST_ALL & ~SPINST_FILES, NULL, NULL, 0, NULL, NULL, NULL, NULL ); } return(b ? NO_ERROR : GetLastError()); } DWORD pSetupNLSLoadInfs( OUT HINF *FontInfHandle, OUT HINF *IntlInfHandle OPTIONAL ) { HINF fontInfHandle; HINF intlInfHandle; DWORD d; fontInfHandle = SetupOpenInfFile(L"font.inf",NULL,INF_STYLE_WIN4,NULL); if(fontInfHandle == INVALID_HANDLE_VALUE) { d = GetLastError(); goto c0; } if(!SetupOpenAppendInfFile(NULL,fontInfHandle,NULL)) { d = GetLastError(); goto c1; } if(IntlInfHandle) { intlInfHandle = SetupOpenInfFile(L"intl.inf",NULL,INF_STYLE_WIN4,NULL); if(intlInfHandle == INVALID_HANDLE_VALUE) { d = GetLastError(); goto c1; } if(!SetupOpenAppendInfFile(NULL,intlInfHandle,NULL)) { d = GetLastError(); goto c2; } *IntlInfHandle = intlInfHandle; } *FontInfHandle = fontInfHandle; return(NO_ERROR); c2: SetupCloseInfFile(intlInfHandle); c1: SetupCloseInfFile(fontInfHandle); c0: return(d); } DWORD SetupChangeLocale( IN HWND Window, IN LCID NewLocale ) { DWORD d; BOOL b; HINF IntlInfHandle; INFCONTEXT InfContext; WCHAR Codepage[24]; WCHAR NewLocaleString[24]; FONTQCONTEXT QueueContext; HSPFILEQ FileQueue; PCWSTR SizeSpec; HDC hdc; PCWSTR p; SizeSpec = L"96"; if(hdc = CreateDC(L"DISPLAY",NULL,NULL,NULL)) { if(GetDeviceCaps(hdc,LOGPIXELSY) > 108) { SizeSpec = L"120"; } DeleteDC(hdc); } // // Load inf files. // d = pSetupNLSLoadInfs(&QueueContext.FontInf,&IntlInfHandle); if(d != NO_ERROR) { goto c0; } // // Get oem codepage for the locale. This is also a sanity check // to see that the locale is supported. // wsprintf(NewLocaleString,L"%.8x",NewLocale); if(!SetupFindFirstLine(IntlInfHandle,L"Locales",NewLocaleString,&InfContext)) { d = ERROR_INVALID_PARAMETER; goto c1; } p = pSetupGetField(&InfContext,2); if(!p) { d = ERROR_INVALID_PARAMETER; goto c1; } // // Copy into local storage since p points into internal structures // that could move as we call INF APIs // lstrcpyn(Codepage,p,sizeof(Codepage)/sizeof(Codepage[0])); // // Create a setup file queue and initialize default Setup copy queue // callback context. // FileQueue = SetupOpenFileQueue(); if(!FileQueue || (FileQueue == INVALID_HANDLE_VALUE)) { d = ERROR_OUTOFMEMORY; goto c1; } QueueContext.SetupQueueContext = SetupInitDefaultQueueCallback(Window); if(!QueueContext.SetupQueueContext) { d = ERROR_OUTOFMEMORY; goto c2; } // // Enqueue locale-related files for copy. // b = SetupInstallFilesFromInfSection( IntlInfHandle, NULL, FileQueue, NewLocaleString, NULL, SP_COPY_NEWER ); if(!b) { d = GetLastError(); goto c3; } // // Enqueue font-related files for copy. // d = pSetupNLSInstallFonts(Window,QueueContext.FontInf,Codepage,SizeSpec,FileQueue); if(d != NO_ERROR) { goto c3; } // // Determine whether the queue actually needs to be committed. // b = SetupScanFileQueue( FileQueue, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER, Window, NULL, NULL, &d ); if(!b) { d = GetLastError(); goto c3; } // // d = 0: User wants new files or some files were missing; // Must commit queue. // // d = 1: User wants to use existing files and queue is empty; // Can skip committing queue. // // d = 2: User wants to use existing files but del/ren queues not empty. // Must commit queue. The copy queue will have been emptied, // so only del/ren functions will be performed. // if(d == 1) { b = TRUE; } else { // // Copy enqueued files. // b = SetupCommitFileQueue( Window, FileQueue, pSetupFontQueueCallback, &QueueContext ); } if(!b) { d = GetLastError(); goto c3; } // // Complete installation of locale stuff. // b = SetupInstallFromInfSection( Window, IntlInfHandle, NewLocaleString, SPINST_ALL & ~SPINST_FILES, NULL, NULL, 0, NULL, NULL, NULL, NULL ); if(!b) { d = GetLastError(); goto c3; } // // Perform font magic associated with the new locale's codepage(s). // d = pSetupNLSInstallFonts(Window,QueueContext.FontInf,Codepage,SizeSpec,NULL); c3: SetupTermDefaultQueueCallback(QueueContext.SetupQueueContext); c2: SetupCloseFileQueue(FileQueue); c1: SetupCloseInfFile(QueueContext.FontInf); SetupCloseInfFile(IntlInfHandle); c0: return(d); } DWORD SetupChangeFontSize( IN HWND Window, IN PCWSTR SizeSpec ) { DWORD d; WCHAR cp[24]; FONTQCONTEXT QueueContext; HSPFILEQ FileQueue; BOOL b; // // BUGBUG do we really want the current OEM CP? // wsprintf(cp,L"%u",GetOEMCP()); // // Load NLS inf. // d = pSetupNLSLoadInfs(&QueueContext.FontInf,NULL); if(d != NO_ERROR) { goto c0; } // // Create queue and initialize default callback routine. // FileQueue = SetupOpenFileQueue(); if(!FileQueue || (FileQueue == INVALID_HANDLE_VALUE)) { d = ERROR_OUTOFMEMORY; goto c1; } QueueContext.SetupQueueContext = SetupInitDefaultQueueCallback(Window); if(!QueueContext.SetupQueueContext) { d = ERROR_OUTOFMEMORY; goto c2; } // // First pass: copy files. // d = pSetupNLSInstallFonts(Window,QueueContext.FontInf,cp,SizeSpec,FileQueue); if(d != NO_ERROR) { goto c3; } // // Determine whether the queue actually needs to be committed. // b = SetupScanFileQueue( FileQueue, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER, Window, NULL, NULL, &d ); if(!b) { d = GetLastError(); goto c3; } // // d = 0: User wants new files or some files were missing; // Must commit queue. // // d = 1: User wants to use existing files and queue is empty; // Can skip committing queue. // // d = 2: User wants to use existing files but del/ren queues not empty. // Must commit queue. The copy queue will have been emptied, // so only del/ren functions will be performed. // if(d == 1) { b = TRUE; } else { b = SetupCommitFileQueue( Window, FileQueue, pSetupFontQueueCallback, &QueueContext ); } if(!b) { d = GetLastError(); goto c3; } // // Second pass: perform registry munging, etc. // d = pSetupNLSInstallFonts(Window,QueueContext.FontInf,cp,SizeSpec,NULL); c3: SetupTermDefaultQueueCallback(QueueContext.SetupQueueContext); c2: SetupCloseFileQueue(FileQueue); c1: SetupCloseInfFile(QueueContext.FontInf); c0: return(d); }