2565 lines
79 KiB
C++
2565 lines
79 KiB
C++
|
//--------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1999 - 2000.
|
||
|
//
|
||
|
//
|
||
|
// File: loadsys
|
||
|
//
|
||
|
// Contents: Load system settings.
|
||
|
//
|
||
|
//---------------------------------------------------------------
|
||
|
|
||
|
#include "loadhead.cxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <common.hxx>
|
||
|
#include <stdlib.h>
|
||
|
#include <objerror.h>
|
||
|
#include <loadstate.hxx>
|
||
|
#include <bothchar.hxx>
|
||
|
#include <winnetwk.h>
|
||
|
#include <lmshare.h>
|
||
|
#include <lmaccess.h>
|
||
|
#include <winspool.h>
|
||
|
#include <winuserp.h> // in \nt\private\inc
|
||
|
#include <wingdip.h> // in \nt\private\inc
|
||
|
#include <ntlsa.h> // for domain/workgroup membership
|
||
|
#include <ntexapi.h> // for NtSetDefaultLocale
|
||
|
#include <devguid.h> // for modem device class
|
||
|
#include <ras.h>
|
||
|
#include <raserror.h>
|
||
|
|
||
|
#include <loadras.hxx> // State Migration private RAS Phonebook APIs
|
||
|
|
||
|
|
||
|
const TCHAR NETSHARES_SECTION[] = TEXT("NetShares");
|
||
|
const TCHAR PRINTERS_SECTION[] = TEXT("Printers");
|
||
|
const TCHAR PRINTER_DRIVER_MAP[] = TEXT("Printer Driver Mapping");
|
||
|
const TCHAR RAS_SECTION[] = TEXT("RAS");
|
||
|
const TCHAR ACCESS_SECTION[] = TEXT("Accessibility");
|
||
|
const TCHAR DESKTOP_SECTION[] = TEXT("Desktop");
|
||
|
const TCHAR KEYBOARDLAYOUT_MAP[] = TEXT("Keyboard.Layout.Mappings");
|
||
|
const TCHAR REGKEY_PRELOAD[] = TEXT("Keyboard Layout\\Preload");
|
||
|
const TCHAR REGKEY_SUBSTITUTES[] = TEXT("Keyboard Layout\\Substitutes");
|
||
|
const TCHAR REGKEY_INTL[] = TEXT("Control Panel\\International");
|
||
|
const TCHAR SCHED_PARAMS[] = TEXT(" /s /p");
|
||
|
|
||
|
|
||
|
const DWORD INTL_NT4 = 0x200; // platform ID from intl.inf
|
||
|
const DWORD INTL_95 = 0x001; // platform ID from intl.inf
|
||
|
const DWORD INTL_98 = 0x002; // platform ID from intl.inf
|
||
|
const int SIZE_128 = 128; // for user locale strings
|
||
|
|
||
|
// Types and defines
|
||
|
#define IS_IME_KBDLAYOUT(hkl) ((HIWORD((ULONG_PTR)(hkl)) & 0xf000) == 0xe000)
|
||
|
#define ChkErr(s) if ((dwErr = (s)) != ERROR_SUCCESS) goto Err;
|
||
|
#define ChkBoolErr(s) if ((success = (s)) == FALSE) { \
|
||
|
dwErr = GetLastError(); \
|
||
|
goto Err;\
|
||
|
}
|
||
|
|
||
|
|
||
|
#define PRIVATE_RAS // Define this to use our private
|
||
|
// RasSetEntryProperties implementation.
|
||
|
|
||
|
//
|
||
|
// private structure needed by ConvertRecentDocsMRU
|
||
|
//
|
||
|
typedef struct {
|
||
|
// Link structure
|
||
|
WORD wSize;
|
||
|
//ITEMIDLIST idl; // variable-length struct
|
||
|
// String, plus three bytes appended to struct
|
||
|
} LINKSTRUCT, *PLINKSTRUCT;
|
||
|
|
||
|
//
|
||
|
// Win95 uses a mix of LOGFONTA and a weird 16-bit LOGFONT
|
||
|
// structure that uses SHORTs instead of LONGs.
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT lfHeight;
|
||
|
SHORT lfWidth;
|
||
|
SHORT lfEscapement;
|
||
|
SHORT lfOrientation;
|
||
|
SHORT lfWeight;
|
||
|
BYTE lfItalic;
|
||
|
BYTE lfUnderline;
|
||
|
BYTE lfStrikeOut;
|
||
|
BYTE lfCharSet;
|
||
|
BYTE lfOutPrecision;
|
||
|
BYTE lfClipPrecision;
|
||
|
BYTE lfQuality;
|
||
|
BYTE lfPitchAndFamily;
|
||
|
char lfFaceName[LF_FACESIZE];
|
||
|
} SHORT_LOGFONT, *PSHORT_LOGFONT;
|
||
|
|
||
|
#define COLOR_MAX_V1 25
|
||
|
#define COLOR_MAX_V3 25
|
||
|
#define COLOR_MAX_V4 29
|
||
|
#define COLOR_MAX_NT 29 // this is a modified version 2 format, similar to 4
|
||
|
|
||
|
//
|
||
|
// NT uses only UNICODE structures, and pads the members
|
||
|
// to 32-bit boundaries.
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT version; // 2 for NT UNICODE
|
||
|
WORD wDummy; // for alignment
|
||
|
NONCLIENTMETRICSW ncm;
|
||
|
LOGFONTW lfIconTitle;
|
||
|
COLORREF rgb[COLOR_MAX_NT];
|
||
|
} SCHEMEDATA_NT, *PSCHEMEDATA_NT;
|
||
|
|
||
|
//
|
||
|
// Win95 uses NONCLIENTMETRICSA which has LOGFONTA members,
|
||
|
// but it uses a 16-bit LOGFONT as well.
|
||
|
//
|
||
|
|
||
|
#pragma pack(push)
|
||
|
#pragma pack(1)
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT version; // 1 for Win95 ANSI
|
||
|
NONCLIENTMETRICSA ncm;
|
||
|
SHORT_LOGFONT lfIconTitle;
|
||
|
COLORREF rgb[COLOR_MAX_V1];
|
||
|
} SCHEMEDATA_V1, *PSCHEMEDATA_V1;
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT version; // 1 for Win95 ANSI
|
||
|
|
||
|
NONCLIENTMETRICSA ncm;
|
||
|
SHORT_LOGFONT lfIconTitle;
|
||
|
COLORREF rgb[COLOR_MAX_V4];
|
||
|
} SCHEMEDATA_V1A, *PSCHEMEDATA_V1A;
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT version; // 3 for Win98 ANSI, 4 for portable format
|
||
|
WORD Dummy;
|
||
|
NONCLIENTMETRICSA ncm;
|
||
|
LOGFONTA lfIconTitle;
|
||
|
COLORREF rgb[COLOR_MAX_V3];
|
||
|
} SCHEMEDATA_V3, *PSCHEMEDATA_V3;
|
||
|
|
||
|
typedef struct {
|
||
|
SHORT version; // 4 for Win32 format (whatever that means)
|
||
|
WORD Dummy;
|
||
|
NONCLIENTMETRICSA ncm;
|
||
|
LOGFONTA lfIconTitle;
|
||
|
COLORREF rgb[COLOR_MAX_V4];
|
||
|
} SCHEMEDATA_V4, *PSCHEMEDATA_V4;
|
||
|
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
typedef struct _APPLET_TIME_ZONE_INFORMATION
|
||
|
{
|
||
|
LONG Bias;
|
||
|
LONG StandardBias;
|
||
|
LONG DaylightBias;
|
||
|
SYSTEMTIME StandardDate;
|
||
|
SYSTEMTIME DaylightDate;
|
||
|
} APPLET_TIME_ZONE_INFORMATION;
|
||
|
|
||
|
// RAS api functions
|
||
|
typedef DWORD
|
||
|
(*MRasSetEntryDialParams)(
|
||
|
IN LPCTSTR lpszPhonebook,
|
||
|
IN LPRASDIALPARAMS lprasdialparams,
|
||
|
IN BOOL fRemovePassword);
|
||
|
|
||
|
typedef DWORD
|
||
|
(*MRasGetEntryProperties)(
|
||
|
IN LPCTSTR lpszPhonebook,
|
||
|
IN LPCTSTR lpszEntry,
|
||
|
OUT LPRASENTRYW lpRasEntry,
|
||
|
OUT LPDWORD lpdwEntryInfoSize,
|
||
|
OUT LPBYTE lpbDeviceInfo,
|
||
|
OUT LPDWORD lpdwDeviceInfoSize);
|
||
|
|
||
|
#ifdef PRIVATE_RAS
|
||
|
typedef DWORD
|
||
|
(*MWinState_RasSetEntryProperties)(
|
||
|
IN LPCWSTR lpszPhonebook,
|
||
|
IN LPCWSTR lpszEntry,
|
||
|
IN LPRASENTRYW lpRasEntry,
|
||
|
IN DWORD dwcbRasEntry,
|
||
|
IN LPBYTE lpbDeviceConfig,
|
||
|
IN DWORD dwcbDeviceConfig);
|
||
|
#else
|
||
|
typedef DWORD
|
||
|
(*MRasSetEntryProperties)(
|
||
|
IN LPCTSTR lpszPhonebook,
|
||
|
IN LPCTSTR lpszEntry,
|
||
|
IN LPRASENTRY lpRasEntry,
|
||
|
IN DWORD dwEntryInfoSize,
|
||
|
IN LPBYTE lpbDeviceInfo,
|
||
|
IN DWORD dwDeviceInfoSize);
|
||
|
#endif
|
||
|
|
||
|
// Statics
|
||
|
#ifdef PRIVATE_RAS
|
||
|
static MWinState_RasSetEntryProperties GWinState_RasSetEntryProperties = NULL;
|
||
|
#else
|
||
|
static MRasSetEntryProperties GRasSetEntryProperties = NULL;
|
||
|
#endif
|
||
|
static MRasSetEntryDialParams GRasSetEntryDialParams = NULL;
|
||
|
static MRasGetEntryProperties GRasGetEntryProperties = NULL;
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: InitializeRasApi
|
||
|
//
|
||
|
// Synopsis: Loads rasapi32.dll, if it exists
|
||
|
//
|
||
|
// Arguments: none
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 24-Feb-00 Jay Thaler Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD InitializeRasApi()
|
||
|
{
|
||
|
DWORD result = ERROR_SUCCESS;
|
||
|
HINSTANCE rasdll;
|
||
|
HINSTANCE loadrasdll; // State Mig. RAS Wrapper
|
||
|
|
||
|
//
|
||
|
// Load rasapi32.dll
|
||
|
// If this fails, RAS isn't installed and we won't migrate RAS conectoids
|
||
|
//
|
||
|
rasdll = LoadLibraryA( "rasapi32.dll" );
|
||
|
if (rasdll == NULL)
|
||
|
{
|
||
|
result = GetLastError();
|
||
|
if (Verbose && DebugOutput)
|
||
|
{
|
||
|
Win32Printf(STDERR, "Warning: rasapi32.dll not loaded: %d\r\n", result);
|
||
|
}
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
GRasSetEntryDialParams = (MRasSetEntryDialParams)GetProcAddress(rasdll, "RasSetEntryDialParamsW");
|
||
|
if (GRasSetEntryDialParams == NULL)
|
||
|
{
|
||
|
result = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
#ifndef PRIVATE_RAS
|
||
|
GRasSetEntryProperties = (MRasSetEntryProperties)GetProcAddress(rasdll, "RasSetEntryPropertiesW");
|
||
|
if (GRasSetEntryProperties == NULL)
|
||
|
{
|
||
|
result = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
#else
|
||
|
//
|
||
|
// Load the private wrapper for RAS APIs
|
||
|
//
|
||
|
loadrasdll = LoadLibraryA( "loadras.dll" );
|
||
|
if (loadrasdll == NULL)
|
||
|
{
|
||
|
result = GetLastError();
|
||
|
if (Verbose && DebugOutput)
|
||
|
{
|
||
|
Win32Printf(STDERR, "Warning: loadras.dll not loaded: %d\r\n", result);
|
||
|
}
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
GWinState_RasSetEntryProperties =
|
||
|
(MWinState_RasSetEntryProperties)GetProcAddress(loadrasdll, "WinState_RasSetEntryPropertiesW");
|
||
|
if (GWinState_RasSetEntryProperties == NULL)
|
||
|
{
|
||
|
result = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
cleanup:
|
||
|
if (result != ERROR_SUCCESS)
|
||
|
{
|
||
|
#ifdef PRIVATE_RAS
|
||
|
GWinState_RasSetEntryProperties = NULL;
|
||
|
#else
|
||
|
GRasSetEntryProperties = NULL;
|
||
|
#endif
|
||
|
GRasSetEntryDialParams = NULL;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetInfField
|
||
|
//
|
||
|
// Synopsis: returns an allocated string for current line field #N
|
||
|
//
|
||
|
// Arguments: [ppBuffer] -- output buffer
|
||
|
// [pContext] -- INF file context
|
||
|
// [nArg] -- argument field number
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD GetInfField (TCHAR **ppBuffer, INFCONTEXT *pContext, DWORD nArg)
|
||
|
{
|
||
|
ULONG len = 0;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
TCHAR *buffer;
|
||
|
|
||
|
*ppBuffer = NULL;
|
||
|
if (!SetupGetStringField ( pContext, nArg, NULL, 0, &len ))
|
||
|
return ERROR_BAD_FORMAT;
|
||
|
|
||
|
|
||
|
// Allocate a buffer. Some callers need an extra char for processing
|
||
|
buffer = (TCHAR *) malloc( (len+1)*sizeof(TCHAR) );
|
||
|
if (buffer == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!SetupGetStringField( pContext, nArg, buffer, len, &len ))
|
||
|
{
|
||
|
free( buffer );
|
||
|
dwErr = ERROR_BAD_FORMAT;
|
||
|
}
|
||
|
else *ppBuffer = buffer;
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LogFormatError
|
||
|
//
|
||
|
// Synopsis: logs error message in current locale
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LogFormatError (DWORD dwErr)
|
||
|
{
|
||
|
DWORD dwRet = ERROR_SUCCESS;
|
||
|
TCHAR *pcs = NULL;
|
||
|
|
||
|
if (0 != FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,
|
||
|
dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(TCHAR*) &pcs, 0, NULL))
|
||
|
{
|
||
|
dwRet = Win32Printf (LogFile, "%ws\r\n", pcs);
|
||
|
LocalFree (pcs);
|
||
|
}
|
||
|
else dwRet = GetLastError();
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsDefaultShare
|
||
|
//
|
||
|
// Synopsis: check if share name is a known system default share
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL IsDefaultShare (TCHAR *buffer)
|
||
|
{
|
||
|
ULONG ul = lstrlen(buffer);
|
||
|
if (buffer[ul - 1] == '$')
|
||
|
{
|
||
|
if (lstrcmp (buffer, TEXT("IPC$")) == 0) return TRUE;
|
||
|
if (lstrcmp (buffer, TEXT("ADMIN$")) == 0) return TRUE;
|
||
|
if (ul == 2 && IsCharAlpha (buffer[0])) return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadNetShares
|
||
|
//
|
||
|
// Synopsis: loads network share settings
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
// NOTES: This code could be updated to do the following:
|
||
|
// 1. Get the correct disk type from the field instead of
|
||
|
// using STYPE_DISKTREE.
|
||
|
// 2. Store (and retrieve) the correct max user count
|
||
|
// 3. Handle custom access permissions
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadNetShares ()
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
INFCONTEXT context;
|
||
|
NETRESOURCE nr;
|
||
|
BOOL success;
|
||
|
TCHAR * buffer = NULL;
|
||
|
TCHAR * buffer2 = NULL;
|
||
|
|
||
|
success = SetupFindFirstLine(InputInf, NETSHARES_SECTION, NULL, &context);
|
||
|
if (!success)
|
||
|
return ERROR_SUCCESS; // line not found
|
||
|
|
||
|
do
|
||
|
{
|
||
|
BOOL fPersist = FALSE;
|
||
|
BOOL bIgnore = FALSE;
|
||
|
|
||
|
ZeroMemory (&nr, sizeof(nr));
|
||
|
// loop through all the network shares and connect to them
|
||
|
|
||
|
dwErr = GetInfField (&buffer, &context, 1);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
Win32Printf (LogFile, "Missing share name in [%ws]\r\n",
|
||
|
NETSHARES_SECTION);
|
||
|
break;
|
||
|
}
|
||
|
nr.dwType = RESOURCETYPE_DISK;
|
||
|
nr.lpLocalName = buffer;
|
||
|
|
||
|
dwErr = GetInfField (&buffer2, &context, 2);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
Win32Printf (LogFile, "Missing remote name in [%ws]\r\n",
|
||
|
NETSHARES_SECTION);
|
||
|
free (buffer);
|
||
|
break;
|
||
|
}
|
||
|
nr.lpRemoteName = buffer2;
|
||
|
|
||
|
if (buffer2[0] != L'\0' && buffer2[0] == L'\\' && buffer2[1] == L'\\')
|
||
|
{
|
||
|
TCHAR *buffer3 = NULL;
|
||
|
if (ERROR_SUCCESS == GetInfField (&buffer3, &context, 3))
|
||
|
{
|
||
|
if (lstrcmp (buffer3, TEXT("persist")) == 0)
|
||
|
fPersist = TRUE;
|
||
|
free (buffer3);
|
||
|
}
|
||
|
dwErr = WNetAddConnection2 (&nr, NULL, NULL,
|
||
|
fPersist ? CONNECT_UPDATE_PROFILE : 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TCHAR *buffer3 = NULL;
|
||
|
TCHAR *buffer4 = NULL;
|
||
|
SHARE_INFO_2 si2;
|
||
|
DWORD dwPerm = ACCESS_READ; // default access
|
||
|
|
||
|
if (!IsDefaultShare(buffer)) // ignore system shares
|
||
|
{
|
||
|
|
||
|
dwErr = GetInfField (&buffer3, &context, 3);
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
dwPerm = _wtoi (buffer3); // share permission bits
|
||
|
}
|
||
|
|
||
|
dwErr = GetInfField (&buffer4, &context, 4);
|
||
|
ZeroMemory (&si2, sizeof(si2));
|
||
|
si2.shi2_netname = buffer;
|
||
|
si2.shi2_type = STYPE_DISKTREE; // should get type from field
|
||
|
si2.shi2_remark = buffer4;
|
||
|
si2.shi2_permissions = dwPerm;
|
||
|
|
||
|
if (lstrlen(buffer2) == 2 && buffer2[1] == ':')
|
||
|
lstrcat ((TCHAR*)buffer2, TEXT("\\"));
|
||
|
|
||
|
si2.shi2_path = buffer2;
|
||
|
si2.shi2_max_uses = SHI_USES_UNLIMITED; // should get number
|
||
|
|
||
|
// should handle custom access permissions here
|
||
|
|
||
|
dwErr = NetShareAdd (NULL, 2, (BYTE *) &si2, NULL);
|
||
|
|
||
|
if (buffer3 != NULL)
|
||
|
free (buffer3);
|
||
|
if (buffer4 != NULL)
|
||
|
free (buffer4);
|
||
|
}
|
||
|
else bIgnore = TRUE;
|
||
|
}
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
LogFormatError (dwErr); // log error and keep on going
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
}
|
||
|
else // log that the share was successfully added
|
||
|
{
|
||
|
Win32Printf (LogFile, "NetShare %ws %ws %ws\r\n", buffer, buffer2,
|
||
|
bIgnore ? TEXT("not processed") : TEXT("added"));
|
||
|
}
|
||
|
|
||
|
free (buffer);
|
||
|
free (buffer2);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
break;
|
||
|
|
||
|
// Advance to the next line.
|
||
|
success = SetupFindNextLine( &context, &context );
|
||
|
} while (success);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: TranslatePrinterDriver
|
||
|
//
|
||
|
// Synopsis: converts Win9x printer driver names to NT driver names
|
||
|
//
|
||
|
// Arguments: [pcs9x] -- Win9x printer driver name
|
||
|
// [pcsNT] -- NT printer driver name
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD TranslatePrinterDriver (WCHAR *pcs9x, WCHAR **ppcsNT)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
HINF hInf;
|
||
|
INFCONTEXT InfContext;
|
||
|
|
||
|
*ppcsNT = NULL;
|
||
|
|
||
|
//
|
||
|
// See in prtupg9x.inf to see if the driver has a different name on NT
|
||
|
//
|
||
|
if ( SetupFindFirstLine(InputInf,
|
||
|
PRINTER_DRIVER_MAP,
|
||
|
pcs9x,
|
||
|
&InfContext) )
|
||
|
{
|
||
|
dwErr = GetInfField (ppcsNT, &InfContext, 1);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadPrinters
|
||
|
//
|
||
|
// Synopsis: loads printers settings
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadPrinters ()
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
INFCONTEXT context;
|
||
|
BOOL success;
|
||
|
TCHAR * buffer = NULL;
|
||
|
DWORD dwReturnUp = ERROR_SUCCESS;
|
||
|
|
||
|
success = SetupFindFirstLine(InputInf, PRINTERS_SECTION, NULL, &context);
|
||
|
if (!success)
|
||
|
return ERROR_SUCCESS; // line not found
|
||
|
|
||
|
do
|
||
|
{
|
||
|
dwErr = GetInfField (&buffer, &context, 1);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
Win32PrintfResource (LogFile, IDS_PRINTER_MISSINGNAME,
|
||
|
PRINTERS_SECTION);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!AddPrinterConnection (buffer))
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
LogFormatError (dwErr); // log error and keep on going
|
||
|
dwReturnUp = dwErr;
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Win32PrintfResource (LogFile, IDS_PRINTER_MIGRATED,
|
||
|
buffer, buffer);
|
||
|
}
|
||
|
|
||
|
free (buffer); buffer = NULL;
|
||
|
|
||
|
// Advance to the next line.
|
||
|
success = SetupFindNextLine( &context, &context );
|
||
|
}
|
||
|
while (success);
|
||
|
|
||
|
if (buffer) free (buffer);
|
||
|
|
||
|
return dwReturnUp;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetOSMajorID
|
||
|
//
|
||
|
// Synopsis: translate GetVersion IDs to INTL IDs
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD GetOSMajorID ()
|
||
|
{
|
||
|
if (SourceVersion & 0x80000000)
|
||
|
{
|
||
|
if ((SourceVersion & 0xFFFF) == 0x004)
|
||
|
return INTL_NT4;
|
||
|
}
|
||
|
else if ((SourceVersion & 0xFFFF) == 0xA04)
|
||
|
return INTL_98;
|
||
|
else if ((SourceVersion & 0xFFFF) == 0x004)
|
||
|
return INTL_95;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsInExcludeList
|
||
|
//
|
||
|
// Synopsis: check if langid is in the exclude list to block migration
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL IsInExcludeList( HINF Inf, LANGID LangID)
|
||
|
{
|
||
|
TCHAR LangIDStr[9];
|
||
|
TCHAR *Field;
|
||
|
INFCONTEXT InfContext;
|
||
|
int iOSID;
|
||
|
int iLangID;
|
||
|
|
||
|
wsprintf(LangIDStr,TEXT("0000%04X"),LangID);
|
||
|
if (SetupFindFirstLine( Inf,
|
||
|
TEXT("ExcludeSourceLocale"),
|
||
|
LangIDStr,
|
||
|
&InfContext ))
|
||
|
{
|
||
|
do {
|
||
|
//
|
||
|
// if in excluded field, this is not what we want
|
||
|
//
|
||
|
if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 0, &iLangID) &&
|
||
|
(iLangID == LangID))
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// if it is in major version list, we also got what we want
|
||
|
//
|
||
|
if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 1, &iOSID))
|
||
|
{
|
||
|
if (iOSID & GetOSMajorID())
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} while ( SetupFindNextLine(&InfContext, &InfContext));
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CheckLanguageVersion
|
||
|
//
|
||
|
// Synopsis: verifies that source and target languages allow migration
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CheckLanguageVersion (HINF Inf, LANGID SourceLangID, LANGID TargetLangID)
|
||
|
{
|
||
|
TCHAR SourceLangIDStr[9];
|
||
|
LANGID SrcLANGID;
|
||
|
TCHAR * Field;
|
||
|
INFCONTEXT InfContext;
|
||
|
int iOSID;
|
||
|
int iLangID;
|
||
|
|
||
|
if (SourceLangID == 0 || TargetLangID == 0)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
if (SourceLangID == TargetLangID)
|
||
|
{
|
||
|
//
|
||
|
// special case, for Middle East version,
|
||
|
// NT5 is localized build but NT4 is not
|
||
|
//
|
||
|
// they don't allow NT5 localized build to upgrade NT4,
|
||
|
// although they are same language
|
||
|
//
|
||
|
// so we need to exclude these
|
||
|
//
|
||
|
return ((IsInExcludeList(Inf, SourceLangID) == FALSE));
|
||
|
}
|
||
|
//
|
||
|
// if Src != Dst, then we need to look up inf file to see
|
||
|
//
|
||
|
// if we can open a backdoor for Target language
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// find alternative SourceLangID
|
||
|
//
|
||
|
|
||
|
wsprintf(SourceLangIDStr,TEXT("0000%04X"),SourceLangID);
|
||
|
|
||
|
if (SetupFindFirstLine( Inf,
|
||
|
TEXT("AlternativeSourceLocale"),
|
||
|
SourceLangIDStr,
|
||
|
&InfContext ))
|
||
|
{
|
||
|
do {
|
||
|
//
|
||
|
// Check if we found alternative locale
|
||
|
//
|
||
|
//
|
||
|
if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 0, &iLangID) &&
|
||
|
(iLangID == SourceLangID))
|
||
|
{
|
||
|
if (ERROR_SUCCESS == GetInfField (&Field, &InfContext, 1))
|
||
|
{
|
||
|
LANGID AltTargetLangID = LANGIDFROMLCID(
|
||
|
_tcstoul(Field,NULL,16));
|
||
|
free (Field);
|
||
|
if (TargetLangID != AltTargetLangID)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// We are here if we found alternative target lang,
|
||
|
//
|
||
|
// now check the version criteria
|
||
|
//
|
||
|
//
|
||
|
// if it is in major version list, we also got what we want
|
||
|
//
|
||
|
if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 2, &iOSID))
|
||
|
{
|
||
|
if (iOSID & GetOSMajorID())
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} while ( SetupFindNextLine(&InfContext,&InfContext));
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadVerifyOSLang
|
||
|
//
|
||
|
// Synopsis: verifies that source and target languages allow migration
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadVerifyOSLang ()
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
INFCONTEXT InfContext;
|
||
|
LANGID langidLoad = 0;
|
||
|
LANGID langidScan = 0;
|
||
|
UINT errorline;
|
||
|
TCHAR tcsInf [MAX_PATH+1];
|
||
|
|
||
|
if (0 == GetWindowsDirectory ((TCHAR*)tcsInf, MAX_PATH))
|
||
|
return GetLastError();
|
||
|
|
||
|
// This inf file must exist for all Windows 2000 localized versions
|
||
|
_tcsncat (tcsInf, TEXT("\\inf\\intl.inf"), MAX_PATH-_tcslen(tcsInf));
|
||
|
|
||
|
HINF Inf = SetupOpenInfFile(tcsInf, NULL, INF_STYLE_WIN4, &errorline );
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == Inf)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
Win32Printf (LogFile, "%systemroot%\\system\\inf\\intl.inf"
|
||
|
"could not be opened Error=%d\r\n", dwErr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (SetupFindFirstLine( Inf,
|
||
|
TEXT("DefaultValues"),
|
||
|
TEXT("Locale"),
|
||
|
&InfContext ))
|
||
|
{
|
||
|
TCHAR *pLoadLang = NULL;
|
||
|
dwErr = GetInfField (&pLoadLang, &InfContext, 1);
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
langidLoad = (LANGID)_tcstoul(pLoadLang,NULL,16);
|
||
|
free (pLoadLang);
|
||
|
|
||
|
if ( SetupFindFirstLine(InputInf,
|
||
|
SOURCE_SECTION,
|
||
|
LOCALE,
|
||
|
&InfContext) )
|
||
|
{
|
||
|
TCHAR *pScanLang = NULL;
|
||
|
dwErr = GetInfField (&pScanLang, &InfContext, 1);
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
langidScan = (LANGID)_tcstoul(pScanLang,NULL,16);
|
||
|
free (pScanLang);
|
||
|
|
||
|
if (FALSE == CheckLanguageVersion(Inf,
|
||
|
langidScan,langidLoad))
|
||
|
{
|
||
|
dwErr = ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
|
||
|
LogFormatError (dwErr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Win32Printf (LogFile, "locale missing in [%ws]\r\n",
|
||
|
SOURCE_SECTION);
|
||
|
LogFormatError (dwErr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
Win32Printf (LogFile, "intl.inf: default locale missing\r\n");
|
||
|
LogFormatError (dwErr);
|
||
|
}
|
||
|
SetupCloseInfFile (Inf);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MigrateKeyboardSubstitutes
|
||
|
//
|
||
|
// Synopsis: changes the user keyboard layouts
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD MigrateKeyboardSubstitutes (TCHAR *tcsName)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
ULONG ulOrig = _tcstoul(tcsName, NULL, 16);
|
||
|
ULONG ulLang = LOWORD(ulOrig);
|
||
|
HKEY hKey = NULL;
|
||
|
BOOL fFound = FALSE;
|
||
|
|
||
|
if (IS_IME_KBDLAYOUT(ulOrig) || ulLang == ulOrig)
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
if (ERROR_SUCCESS == RegOpenKeyEx (
|
||
|
CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
|
||
|
REGKEY_SUBSTITUTES,
|
||
|
NULL,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey))
|
||
|
{
|
||
|
DWORD dwIndex = 0;
|
||
|
ULONG ulIndex;
|
||
|
ULONG ulValue;
|
||
|
TCHAR tcsIndex[KL_NAMELENGTH];
|
||
|
TCHAR tcsValue[KL_NAMELENGTH];
|
||
|
|
||
|
while (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
DWORD cbIndex = sizeof (tcsIndex);
|
||
|
DWORD cbValue = sizeof(tcsValue);
|
||
|
dwErr = RegEnumValue (hKey, dwIndex, tcsIndex, &cbIndex,
|
||
|
NULL, NULL, (BYTE*) tcsValue, &cbValue);
|
||
|
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
ulIndex = _tcstoul(tcsIndex, NULL, 16);
|
||
|
ulValue = _tcstoul(tcsValue, NULL, 16);
|
||
|
if (ulIndex == ulLang && ulValue == ulOrig)
|
||
|
{
|
||
|
fFound = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
dwIndex++;
|
||
|
}
|
||
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (!fFound) // add a new value
|
||
|
{
|
||
|
wsprintf (tcsIndex, TEXT("%08x"), ulLang);
|
||
|
dwErr = RegSetValueEx (hKey, tcsIndex, 0, REG_SZ, (BYTE*)tcsName,
|
||
|
(_tcslen(tcsName)+1)*sizeof(TCHAR));
|
||
|
}
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
}
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MigrateKeyboardPreloads
|
||
|
//
|
||
|
// Synopsis: changes the user keyboard layouts
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD MigrateKeyboardPreloads (TCHAR *tcsName)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
ULONG ul = _tcstoul(tcsName, NULL, 16);
|
||
|
HKEY hKey = NULL;
|
||
|
BOOL fFound = FALSE;
|
||
|
|
||
|
// look for a preload with this locale
|
||
|
if (!IS_IME_KBDLAYOUT(ul))
|
||
|
ul = LOWORD(ul);
|
||
|
|
||
|
if (ERROR_SUCCESS == RegOpenKeyEx (
|
||
|
CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
|
||
|
REGKEY_PRELOAD,
|
||
|
NULL,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey))
|
||
|
{
|
||
|
DWORD dwIndex = 0;
|
||
|
ULONG ulIndexMax = 0;
|
||
|
ULONG ulIndex;
|
||
|
ULONG ulValue;
|
||
|
TCHAR tcsIndex[KL_NAMELENGTH];
|
||
|
TCHAR tcsValue[KL_NAMELENGTH];
|
||
|
|
||
|
while (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
DWORD cbIndex = sizeof (tcsIndex);
|
||
|
DWORD cbValue = sizeof(tcsValue);
|
||
|
dwErr = RegEnumValue (hKey, dwIndex, tcsIndex, &cbIndex,
|
||
|
NULL, NULL, (BYTE*)tcsValue, &cbValue);
|
||
|
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
ulIndex = _tcstoul(tcsIndex, NULL, 10);
|
||
|
if (ulIndex > ulIndexMax)
|
||
|
ulIndexMax = ulIndex;
|
||
|
ulValue = _tcstoul(tcsValue, NULL, 16);
|
||
|
if (ulValue == ul)
|
||
|
{
|
||
|
fFound = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
dwIndex++;
|
||
|
}
|
||
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (!fFound) // add a new value
|
||
|
{
|
||
|
wsprintf (tcsIndex, TEXT("%d"), ulIndexMax+1);
|
||
|
wsprintf (tcsValue, TEXT("%08x"), ul);
|
||
|
dwErr = RegSetValueEx (hKey, tcsIndex, 0, REG_SZ, (BYTE*)tcsValue,
|
||
|
(_tcslen(tcsValue)+1)*sizeof(TCHAR));
|
||
|
}
|
||
|
RegCloseKey (hKey);
|
||
|
}
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadKeyboardLayouts
|
||
|
//
|
||
|
// Synopsis: changes the user keyboard layouts
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadKeyboardLayouts ()
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
INFCONTEXT InfContext;
|
||
|
BOOL fFound;
|
||
|
|
||
|
// translate input locales if source is Win9x
|
||
|
if (!(SourceVersion & 0x80000000))
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
if (SetupFindFirstLine(InputInf, SOURCE_SECTION, INPUTLOCALE, &InfContext))
|
||
|
{
|
||
|
TCHAR *pLayout = NULL;
|
||
|
UINT iLayouts = SetupGetFieldCount(&InfContext);
|
||
|
for (UINT i = 1; i <= iLayouts; i++)
|
||
|
{
|
||
|
dwErr = GetInfField (&pLayout, &InfContext, i);
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
INFCONTEXT InfContext2;
|
||
|
//
|
||
|
// See in usermig.inf to see if different ID exists
|
||
|
//
|
||
|
if ( SetupFindFirstLine(InputInf,
|
||
|
KEYBOARDLAYOUT_MAP,
|
||
|
pLayout,
|
||
|
&InfContext2) )
|
||
|
{
|
||
|
TCHAR *pMap = NULL;
|
||
|
if (ERROR_SUCCESS == GetInfField (&pMap, &InfContext2, 1))
|
||
|
{
|
||
|
free (pLayout);
|
||
|
pLayout = pMap;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwErr = MigrateKeyboardPreloads (pLayout);
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
dwErr = MigrateKeyboardSubstitutes (pLayout);
|
||
|
|
||
|
if (CurrentUser == HKEY_CURRENT_USER)
|
||
|
{
|
||
|
TCHAR kbname[KL_NAMELENGTH];
|
||
|
GetKeyboardLayoutName (kbname);
|
||
|
if (i == 1 && lstrcmp(kbname, pLayout) != 0) // load default
|
||
|
{
|
||
|
ULONG ulLayout = _tcstoul(pLayout, NULL, 16);
|
||
|
HKL hklCurrent = GetKeyboardLayout(0);
|
||
|
if (Verbose)
|
||
|
printf ("Loading keyboard layout %ws \n", pLayout);
|
||
|
|
||
|
HKL hkl = LoadKeyboardLayoutEx (hklCurrent, pLayout,
|
||
|
KLF_REORDER | KLF_ACTIVATE | KLF_SETFORPROCESS |
|
||
|
KLF_SUBSTITUTE_OK);
|
||
|
if (hkl != NULL)
|
||
|
{
|
||
|
SystemParametersInfo (SPI_SETDEFAULTINPUTLANG, 0,
|
||
|
(VOID *) &hkl, 0);
|
||
|
if (Verbose)
|
||
|
{
|
||
|
#ifdef _WIN64
|
||
|
printf ("Activated keyboard layout %08I64x\n",hkl);
|
||
|
#else
|
||
|
printf ("Activated keyboard layout %08x\n",hkl);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (i > 1) // load the alternates
|
||
|
{
|
||
|
LoadKeyboardLayout (pLayout, KLF_SUBSTITUTE_OK);
|
||
|
}
|
||
|
}
|
||
|
free (pLayout);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Win32Printf (LogFile,"Could not read keyboard layout %d\r\n",i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
Win32Printf (LogFile, "Could not load all keyboard layouts\r\n");
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: EnumerateModems
|
||
|
//
|
||
|
// Synopsis: enumerates the modem devices on the system
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD EnumerateModems (TCHAR *ptsPort, ULONG ulLen)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
UINT i = 0;
|
||
|
BOOL fDetected = FALSE;
|
||
|
SP_DEVINFO_DATA sdd;
|
||
|
|
||
|
HDEVINFO hdi = SetupDiGetClassDevs (&GUID_DEVCLASS_MODEM,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
DIGCF_PRESENT );
|
||
|
|
||
|
if (hdi != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
ZeroMemory (&sdd, sizeof(sdd));
|
||
|
sdd.cbSize = sizeof(sdd);
|
||
|
sdd.ClassGuid = GUID_DEVCLASS_MODEM;
|
||
|
|
||
|
while (SetupDiEnumDeviceInfo (hdi, i++, &sdd))
|
||
|
{
|
||
|
HKEY hKey = SetupDiOpenDevRegKey (hdi,
|
||
|
&sdd,
|
||
|
DICS_FLAG_GLOBAL,
|
||
|
0,
|
||
|
DIREG_DRV,
|
||
|
KEY_READ);
|
||
|
if (hKey != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
ULONG ulLenQuery = ulLen;
|
||
|
dwErr = RegQueryValueEx(hKey,
|
||
|
TEXT("AttachedTo"),
|
||
|
NULL,
|
||
|
NULL,
|
||
|
(BYTE *)ptsPort,
|
||
|
&ulLenQuery);
|
||
|
RegCloseKey (hKey);
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS) // found a modem
|
||
|
{
|
||
|
fDetected = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else dwErr = GetLastError();
|
||
|
}
|
||
|
if (!fDetected)
|
||
|
dwErr = ERROR_NO_MORE_DEVICES; // no modem detected
|
||
|
}
|
||
|
else dwErr = GetLastError();
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: RasGetPhoneBookFile
|
||
|
//
|
||
|
// Synopsis: determines location of RAS settings in phonebook file
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD RasGetPhoneBookFile(TCHAR *strPhoneBook)
|
||
|
{
|
||
|
const TCHAR RASPHONE_SUBPATH[] = TEXT("\\ras\\rasphone.pbk");
|
||
|
|
||
|
if (0 == GetSystemDirectory ((TCHAR*)strPhoneBook, MAX_PATH))
|
||
|
return GetLastError();
|
||
|
|
||
|
_tcsncat(strPhoneBook, (TCHAR *) RASPHONE_SUBPATH,
|
||
|
MAX_PATH-_tcslen(strPhoneBook));
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadRas
|
||
|
//
|
||
|
// Synopsis: create the phonebook file for RAS settings
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadRas()
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
BOOL success;
|
||
|
INFCONTEXT context;
|
||
|
RASENTRY RasEntry;
|
||
|
RASDIALPARAMS RasDialParams;
|
||
|
|
||
|
success = SetupFindFirstLine(InputInf, RAS_SECTION, NULL, &context);
|
||
|
if (!success)
|
||
|
return ERROR_SUCCESS; // line not found
|
||
|
|
||
|
do {
|
||
|
ZeroMemory( &RasEntry, sizeof(RASENTRY) );
|
||
|
ZeroMemory( &RasDialParams, sizeof(RASDIALPARAMS) );
|
||
|
|
||
|
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
|
||
|
RasEntry.dwSize = sizeof(RASENTRY);
|
||
|
|
||
|
ChkBoolErr( SetupGetStringField( &context, 1, RasDialParams.szEntryName,
|
||
|
RAS_MaxEntryName + 1, NULL) );
|
||
|
// load RasEntry structure
|
||
|
ChkBoolErr( SetupGetIntField( &context, 2, (int*)&RasEntry.dwfOptions) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 3, (int*)&RasEntry.dwCountryID) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 4, (int*)&RasEntry.dwCountryCode) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 5, RasEntry.szAreaCode,
|
||
|
RAS_MaxAreaCode + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 6, RasEntry.szLocalPhoneNumber,
|
||
|
RAS_MaxPhoneNumber + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 7, (int*)&RasEntry.dwAlternateOffset) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 8, (int*)&RasEntry.ipaddr) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 9, (int*)&RasEntry.ipaddrDns) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 10, (int*)&RasEntry.ipaddrDnsAlt) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 11, (int*)&RasEntry.ipaddrWins) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 12, (int*)&RasEntry.ipaddrWinsAlt) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 13, (int*)&RasEntry.dwFrameSize) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 14, (int*)&RasEntry.dwfNetProtocols) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 15, (int*)&RasEntry.dwFramingProtocol) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 16, RasEntry.szScript, MAX_PATH, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 17, RasEntry.szAutodialDll, MAX_PATH, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 18, RasEntry.szAutodialFunc, MAX_PATH, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 19, RasEntry.szDeviceType,
|
||
|
RAS_MaxDeviceType + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 20, RasEntry.szDeviceName,
|
||
|
RAS_MaxDeviceName + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 21, RasEntry.szX25PadType,
|
||
|
RAS_MaxPadType + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 22, RasEntry.szX25Address,
|
||
|
RAS_MaxX25Address + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 23, RasEntry.szX25Facilities,
|
||
|
RAS_MaxFacilities + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 24, RasEntry.szX25UserData,
|
||
|
RAS_MaxUserData + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetIntField( &context, 25, (int*)&RasEntry.dwChannels) );
|
||
|
|
||
|
// load RasDialParams structure
|
||
|
ChkBoolErr( SetupGetStringField( &context, 26, RasDialParams.szPhoneNumber,
|
||
|
RAS_MaxPhoneNumber + 1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 27, RasDialParams.szCallbackNumber,
|
||
|
RAS_MaxCallbackNumber+1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 28, RasDialParams.szUserName, UNLEN+1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 29, RasDialParams.szPassword, PWLEN+1, NULL) );
|
||
|
ChkBoolErr( SetupGetStringField( &context, 30, RasDialParams.szDomain, DNLEN+1, NULL) );
|
||
|
|
||
|
// Set default options that do not exist on pre-Win2000 OS, but are
|
||
|
// set by default when you create a connection via the Win2000 GUI.
|
||
|
RasEntry.dwfOptions |= RASEO_PreviewUserPw;
|
||
|
RasEntry.dwfOptions |= RASEO_ShowDialingProgress;
|
||
|
RasEntry.dwfOptions |= RASEO_ModemLights;
|
||
|
|
||
|
// New Win2k encryption field
|
||
|
if( RasEntry.dwfOptions & RASEO_RequireDataEncryption )
|
||
|
{
|
||
|
RasEntry.dwEncryptionType = ET_Require;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RasEntry.dwEncryptionType = ET_Optional;
|
||
|
}
|
||
|
|
||
|
#ifdef PRIVATE_RAS
|
||
|
dwErr = GWinState_RasSetEntryProperties(NULL, // Current user default phonebook
|
||
|
RasDialParams.szEntryName,
|
||
|
&RasEntry,
|
||
|
sizeof(RASENTRY),
|
||
|
NULL,
|
||
|
NULL);
|
||
|
#else
|
||
|
dwErr = GRasSetEntryProperties(NULL, // Current user default phonebook
|
||
|
RasDialParams.szEntryName,
|
||
|
&RasEntry,
|
||
|
sizeof(RASENTRY),
|
||
|
NULL,
|
||
|
NULL);
|
||
|
#endif
|
||
|
if ( dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, RasDialParams.szEntryName);
|
||
|
if (DebugOutput)
|
||
|
Win32Printf(LogFile, "RasSetEntryProperties failed: Error %d\r\n", dwErr);
|
||
|
}
|
||
|
|
||
|
dwErr = GRasSetEntryDialParams(NULL,
|
||
|
&RasDialParams,
|
||
|
TRUE); // Never put password in
|
||
|
if ( dwErr != ERROR_SUCCESS)
|
||
|
{
|
||
|
Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, RasDialParams.szEntryName);
|
||
|
if (DebugOutput)
|
||
|
Win32Printf(LogFile, "RasSetEntryDialParams failed: Error %d\r\n", dwErr);
|
||
|
}
|
||
|
|
||
|
// Advance to the next line.
|
||
|
success = SetupFindNextLine( &context, &context );
|
||
|
} while (success);
|
||
|
|
||
|
Err:
|
||
|
return dwErr;
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertLFShort
|
||
|
//
|
||
|
// Synopsis: convert Win9x 16-bit LOGFONTs to NT formats
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertLFShort (LOGFONTW *plfDest, const SHORT_LOGFONT *plfSrc)
|
||
|
{
|
||
|
plfDest->lfHeight = plfSrc->lfHeight;
|
||
|
plfDest->lfWidth = plfSrc->lfWidth;
|
||
|
plfDest->lfEscapement = plfSrc->lfEscapement;
|
||
|
plfDest->lfOrientation = plfSrc->lfOrientation;
|
||
|
plfDest->lfWeight = plfSrc->lfWeight;
|
||
|
plfDest->lfItalic = plfSrc->lfItalic;
|
||
|
plfDest->lfUnderline = plfSrc->lfUnderline;
|
||
|
plfDest->lfStrikeOut = plfSrc->lfStrikeOut;
|
||
|
plfDest->lfCharSet = plfSrc->lfCharSet;
|
||
|
plfDest->lfOutPrecision = plfSrc->lfOutPrecision;
|
||
|
plfDest->lfClipPrecision = plfSrc->lfClipPrecision;
|
||
|
plfDest->lfQuality = plfSrc->lfQuality;
|
||
|
plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily;
|
||
|
ZeroMemory (plfDest->lfFaceName, sizeof(plfDest->lfFaceName));
|
||
|
|
||
|
if (0 == MultiByteToWideChar (GetACP(),
|
||
|
0,
|
||
|
plfSrc->lfFaceName,
|
||
|
-1,
|
||
|
plfDest->lfFaceName,
|
||
|
sizeof (plfDest->lfFaceName) / sizeof (WCHAR)))
|
||
|
return GetLastError();
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertLF
|
||
|
//
|
||
|
// Synopsis: convert Win9x LOGFONTs to NT formats
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertLF (LOGFONTW *plfDest, const LOGFONTA *plfSrc)
|
||
|
{
|
||
|
plfDest->lfHeight = plfSrc->lfHeight;
|
||
|
plfDest->lfWidth = plfSrc->lfWidth;
|
||
|
plfDest->lfEscapement = plfSrc->lfEscapement;
|
||
|
plfDest->lfOrientation = plfSrc->lfOrientation;
|
||
|
plfDest->lfWeight = plfSrc->lfWeight;
|
||
|
plfDest->lfItalic = plfSrc->lfItalic;
|
||
|
plfDest->lfUnderline = plfSrc->lfUnderline;
|
||
|
plfDest->lfStrikeOut = plfSrc->lfStrikeOut;
|
||
|
plfDest->lfCharSet = plfSrc->lfCharSet;
|
||
|
plfDest->lfOutPrecision = plfSrc->lfOutPrecision;
|
||
|
plfDest->lfClipPrecision = plfSrc->lfClipPrecision;
|
||
|
plfDest->lfQuality = plfSrc->lfQuality;
|
||
|
plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily;
|
||
|
ZeroMemory (plfDest->lfFaceName, sizeof(plfDest->lfFaceName));
|
||
|
|
||
|
if (0 == MultiByteToWideChar (GetACP(),
|
||
|
0,
|
||
|
plfSrc->lfFaceName,
|
||
|
-1,
|
||
|
plfDest->lfFaceName,
|
||
|
sizeof (plfDest->lfFaceName) / sizeof (WCHAR)))
|
||
|
return GetLastError();
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertNonClientMetrics
|
||
|
//
|
||
|
// Synopsis: convert Win9x client metrics to NT formats
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void ConvertNonClientMetrics (NONCLIENTMETRICSW *Dest, NONCLIENTMETRICSA *Src)
|
||
|
{
|
||
|
Dest->cbSize = sizeof (NONCLIENTMETRICSW);
|
||
|
Dest->iBorderWidth = Src->iBorderWidth;
|
||
|
Dest->iScrollWidth = Src->iScrollWidth;
|
||
|
Dest->iScrollHeight = Src->iScrollHeight;
|
||
|
Dest->iCaptionWidth = Src->iCaptionWidth;
|
||
|
Dest->iCaptionHeight = Src->iCaptionHeight;
|
||
|
Dest->iSmCaptionWidth = Src->iSmCaptionWidth;
|
||
|
Dest->iSmCaptionHeight = Src->iSmCaptionHeight;
|
||
|
Dest->iMenuWidth = Src->iMenuWidth;
|
||
|
Dest->iMenuHeight = Src->iMenuHeight;
|
||
|
|
||
|
ConvertLF (&Dest->lfCaptionFont, &Src->lfCaptionFont);
|
||
|
ConvertLF (&Dest->lfSmCaptionFont, &Src->lfSmCaptionFont);
|
||
|
ConvertLF (&Dest->lfMenuFont, &Src->lfMenuFont);
|
||
|
ConvertLF (&Dest->lfStatusFont, &Src->lfStatusFont);
|
||
|
ConvertLF (&Dest->lfMessageFont, &Src->lfMessageFont);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertAppearanceScheme
|
||
|
//
|
||
|
// Synopsis: convert Win9x schemes to NT formats
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertAppearanceScheme (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD dwSize = *pdata_len;
|
||
|
|
||
|
if (*ptype == REG_BINARY &&
|
||
|
(dwSize == sizeof(SCHEMEDATA_V1) ||
|
||
|
dwSize == sizeof(SCHEMEDATA_V3) ||
|
||
|
dwSize == sizeof(SCHEMEDATA_V4) ||
|
||
|
dwSize == sizeof(SCHEMEDATA_V1A)))
|
||
|
{
|
||
|
SCHEMEDATA_NT sd_nt;
|
||
|
SCHEMEDATA_V1 * psd_v1;
|
||
|
SCHEMEDATA_V3 * psd_v3;
|
||
|
SCHEMEDATA_V4 * psd_v4;
|
||
|
SCHEMEDATA_V1A * psd_v1a;
|
||
|
BOOL Copy3dValues = FALSE;
|
||
|
BOOL shouldChange = TRUE;
|
||
|
|
||
|
psd_v1 = (SCHEMEDATA_V1 *) *pdata;
|
||
|
if (psd_v1->version == 1)
|
||
|
{
|
||
|
sd_nt.version = 2;
|
||
|
ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1->ncm);
|
||
|
ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1->lfIconTitle);
|
||
|
|
||
|
ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
|
||
|
CopyMemory ( &sd_nt.rgb, &psd_v1->rgb,
|
||
|
min (sizeof (psd_v1->rgb), sizeof (sd_nt.rgb)));
|
||
|
|
||
|
Copy3dValues = TRUE;
|
||
|
}
|
||
|
else if (psd_v1->version == 3 && dwSize==sizeof(SCHEMEDATA_V1A))
|
||
|
{
|
||
|
psd_v1a = (PSCHEMEDATA_V1A) psd_v1;
|
||
|
sd_nt.version = 2;
|
||
|
ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1a->ncm);
|
||
|
ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1a->lfIconTitle);
|
||
|
|
||
|
ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
|
||
|
CopyMemory ( &sd_nt.rgb, &psd_v1a->rgb,
|
||
|
min (sizeof (psd_v1a->rgb), sizeof (sd_nt.rgb)) );
|
||
|
|
||
|
Copy3dValues = TRUE;
|
||
|
}
|
||
|
else if (psd_v1->version == 3 && dwSize==sizeof(SCHEMEDATA_V3))
|
||
|
{
|
||
|
psd_v3 = (PSCHEMEDATA_V3) psd_v1;
|
||
|
|
||
|
sd_nt.version = 2;
|
||
|
ConvertNonClientMetrics (&sd_nt.ncm, &psd_v3->ncm);
|
||
|
ConvertLF (&sd_nt.lfIconTitle, &psd_v3->lfIconTitle);
|
||
|
|
||
|
ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
|
||
|
CopyMemory ( &sd_nt.rgb, &psd_v3->rgb,
|
||
|
min (sizeof (psd_v3->rgb), sizeof (sd_nt.rgb)) );
|
||
|
|
||
|
Copy3dValues = TRUE;
|
||
|
|
||
|
}
|
||
|
else if (psd_v1->version == 4)
|
||
|
{
|
||
|
psd_v4 = (PSCHEMEDATA_V4) psd_v1;
|
||
|
|
||
|
sd_nt.version = 2;
|
||
|
ConvertNonClientMetrics (&sd_nt.ncm, &psd_v4->ncm);
|
||
|
ConvertLF (&sd_nt.lfIconTitle, &psd_v4->lfIconTitle);
|
||
|
|
||
|
ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
|
||
|
CopyMemory ( &sd_nt.rgb, &psd_v4->rgb,
|
||
|
min (sizeof (psd_v4->rgb), sizeof (sd_nt.rgb)) );
|
||
|
}
|
||
|
else shouldChange = FALSE;
|
||
|
|
||
|
if (Copy3dValues)
|
||
|
{
|
||
|
//
|
||
|
// Make sure the NT structure has values for 3D colors
|
||
|
//
|
||
|
|
||
|
sd_nt.rgb[COLOR_HOTLIGHT] = sd_nt.rgb[COLOR_ACTIVECAPTION];
|
||
|
sd_nt.rgb[COLOR_GRADIENTACTIVECAPTION] =
|
||
|
sd_nt.rgb[COLOR_ACTIVECAPTION];
|
||
|
sd_nt.rgb[COLOR_GRADIENTINACTIVECAPTION] =
|
||
|
sd_nt.rgb[COLOR_INACTIVECAPTION];
|
||
|
}
|
||
|
if (shouldChange)
|
||
|
{
|
||
|
BYTE *pnew_data;
|
||
|
if (NULL == (pnew_data = (BYTE *)malloc (sizeof(sd_nt))))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
CopyMemory (pnew_data, &sd_nt, sizeof(sd_nt));
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = pnew_data;
|
||
|
*pdata_len = sizeof(sd_nt);
|
||
|
}
|
||
|
}
|
||
|
else if (Verbose)
|
||
|
printf ("ConvertAppearanceScheme type=%d, size=%d\n",*ptype,*pdata_len);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertRecentDocsMRU
|
||
|
//
|
||
|
// Synopsis: convert Win9x "Start Menu" "Documents" settings
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertRecentDocsMRU (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (*ptype == REG_BINARY)
|
||
|
{
|
||
|
LINKSTRUCT *pls95, *plsNT;
|
||
|
CHAR *str, *strEnd;
|
||
|
WCHAR *wstr, *wstrEnd;
|
||
|
DWORD dwLinkSize, dwNewSize;
|
||
|
DWORD dwRenewSize;
|
||
|
|
||
|
str = (CHAR *) *pdata;
|
||
|
dwNewSize = strlen(str);
|
||
|
strEnd = str + dwNewSize;
|
||
|
|
||
|
pls95 = (LINKSTRUCT *) strEnd;
|
||
|
dwLinkSize = dwNewSize + 1 + pls95->wSize + sizeof (WORD);
|
||
|
|
||
|
if (dwLinkSize != *pdata_len)
|
||
|
{
|
||
|
return ERROR_SUCCESS; // length mismatch, do not transform
|
||
|
}
|
||
|
|
||
|
dwNewSize = MultiByteToWideChar (GetACP(),0,str,-1, NULL, 0);
|
||
|
if (dwNewSize == 0)
|
||
|
return GetLastError();
|
||
|
|
||
|
if (NULL == (wstr = (WCHAR *) malloc (
|
||
|
(dwNewSize + 1)*sizeof(WCHAR) + dwLinkSize)))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
if (0 == MultiByteToWideChar (GetACP(),0,str,-1,wstr,dwNewSize))
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
wstrEnd = wstr + wcslen(wstr);
|
||
|
|
||
|
plsNT = (PLINKSTRUCT) ((LPBYTE) wstr + ((DWORD)(wstrEnd-wstr)));
|
||
|
CopyMemory (plsNT, pls95, dwLinkSize);
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = (BYTE *) wstr;
|
||
|
*pdata_len = dwNewSize;
|
||
|
}
|
||
|
else free (wstr);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertLogFont
|
||
|
//
|
||
|
// Synopsis: convert Win9x font binary data
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertLogFont (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
if (*ptype == REG_BINARY && *pdata_len == sizeof(SHORT_LOGFONT))
|
||
|
{
|
||
|
BYTE *pnew_data;
|
||
|
LOGFONTW lfNT;
|
||
|
ConvertLFShort (&lfNT, (SHORT_LOGFONT *) *pdata);
|
||
|
|
||
|
if (NULL == (pnew_data = (BYTE *)malloc (sizeof(lfNT))))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
CopyMemory (pnew_data, &lfNT, sizeof(lfNT));
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = pnew_data;
|
||
|
*pdata_len = sizeof(lfNT);
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertToDword
|
||
|
//
|
||
|
// Synopsis: convert string data to DWORD
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertToDword (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
if (*ptype == REG_SZ || *ptype == REG_EXPAND_SZ)
|
||
|
{
|
||
|
BYTE *pnew_data;
|
||
|
DWORD dwValue = _tcstoul ((PCTSTR) *pdata, NULL, 10);
|
||
|
if (NULL == (pnew_data = (BYTE *)malloc (sizeof(dwValue))))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
CopyMemory (pnew_data, &dwValue, sizeof(dwValue));
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = pnew_data;
|
||
|
*pdata_len = sizeof(dwValue);
|
||
|
*ptype = REG_DWORD;
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConvertToString
|
||
|
//
|
||
|
// Synopsis: convert DWORD to a string
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ConvertToString (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
if (*ptype == REG_DWORD)
|
||
|
{
|
||
|
BYTE *pnew_data;
|
||
|
DWORD dwSize;
|
||
|
TCHAR tcsValue[16];
|
||
|
wsprintf (tcsValue, TEXT("%lu"), * ((DWORD *) *pdata));
|
||
|
|
||
|
dwSize = (_tcslen (tcsValue) + 1) * sizeof(TCHAR);
|
||
|
|
||
|
if (NULL == (pnew_data = (BYTE *)malloc (dwSize)))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
CopyMemory (pnew_data, tcsValue, dwSize);
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = pnew_data;
|
||
|
*pdata_len = dwSize;
|
||
|
*ptype = REG_SZ;
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: AntiAlias
|
||
|
//
|
||
|
// Synopsis: convert FontSmoothing from "1" to "2"
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD AntiAlias (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
if (*ptype == REG_SZ)
|
||
|
{
|
||
|
DWORD dwValue = _tcstoul ((TCHAR *) *pdata, NULL, 10);
|
||
|
if (dwValue > 0)
|
||
|
wsprintf ((TCHAR *) *pdata, TEXT("%d"), FE_AA_ON);
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: FixActiveDesktop
|
||
|
//
|
||
|
// Synopsis: convert active desktop blob
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD FixActiveDesktop (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
|
||
|
{
|
||
|
const USHORT BadBufferSize = 16;
|
||
|
const USHORT GoodBufferSize = 28;
|
||
|
|
||
|
BYTE BadBuffer[BadBufferSize] =
|
||
|
{0x10, 0x00, 0x00, 0x00,
|
||
|
0x01, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00};
|
||
|
|
||
|
BYTE GoodBuffer[GoodBufferSize] =
|
||
|
{0x1C, 0x00, 0x00, 0x00,
|
||
|
0x20, 0x08, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00,
|
||
|
0x0A, 0x00, 0x00, 0x00};
|
||
|
|
||
|
if (*ptype == REG_BINARY && *pdata_len == BadBufferSize)
|
||
|
{
|
||
|
BOOL shouldChange = TRUE;
|
||
|
for (USHORT i = 0; i < BadBufferSize; i++)
|
||
|
{
|
||
|
if ((*pdata)[i] != BadBuffer[i])
|
||
|
{
|
||
|
shouldChange = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (shouldChange)
|
||
|
{
|
||
|
BYTE *pnew_data;
|
||
|
if (NULL == (pnew_data = (BYTE *)malloc (sizeof(GoodBuffer))))
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
CopyMemory (pnew_data, GoodBuffer, sizeof(GoodBuffer));
|
||
|
|
||
|
free (*pdata);
|
||
|
*pdata = pnew_data;
|
||
|
*pdata_len = sizeof(GoodBuffer);
|
||
|
}
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadTimeZone
|
||
|
//
|
||
|
// Synopsis: set the current timezone
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadTimeZone ()
|
||
|
{
|
||
|
const int TZNAME_SIZE = 32;
|
||
|
const TCHAR REGKEY_TIMEZONES[] =
|
||
|
_T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
|
||
|
|
||
|
const TCHAR REGVAL_TZI[] = _T("TZI");
|
||
|
const TCHAR REGVAL_DLT[] = _T("Dlt");
|
||
|
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
const int LINEBUFSIZE = 1024;
|
||
|
HKEY hKey = NULL;
|
||
|
INFCONTEXT InfContext;
|
||
|
TCHAR tcsTimeZone[LINEBUFSIZE];
|
||
|
TIME_ZONE_INFORMATION tzi;
|
||
|
APPLET_TIME_ZONE_INFORMATION atzi;
|
||
|
|
||
|
if (TIME_ZONE_ID_INVALID == GetTimeZoneInformation (&tzi))
|
||
|
{
|
||
|
Win32Printf (LogFile, "Could not get time zone information\r\n");
|
||
|
ChkErr (GetLastError());
|
||
|
}
|
||
|
|
||
|
if (SetupFindFirstLine(InputInf, SOURCE_SECTION, TIMEZONE, &InfContext))
|
||
|
{
|
||
|
TCHAR *buffer = NULL;
|
||
|
TCHAR *buffer2 = NULL;
|
||
|
|
||
|
ChkErr (GetInfField (&buffer, &InfContext, 1));
|
||
|
|
||
|
if (lstrcmp (tzi.StandardName, buffer) != 0)
|
||
|
{
|
||
|
|
||
|
_tcsncpy (tcsTimeZone, (TCHAR*) REGKEY_TIMEZONES, LINEBUFSIZE);
|
||
|
_tcsncat (tcsTimeZone, TEXT("\\"),
|
||
|
LINEBUFSIZE - _tcslen(tcsTimeZone) - 1);
|
||
|
_tcsncat (tcsTimeZone, buffer,
|
||
|
LINEBUFSIZE - _tcslen(tcsTimeZone) - 1);
|
||
|
|
||
|
if (RegOpenKey (HKEY_LOCAL_MACHINE, tcsTimeZone, &hKey) ==
|
||
|
ERROR_SUCCESS)
|
||
|
{
|
||
|
ULONG ulLen = sizeof(atzi);
|
||
|
if (ERROR_SUCCESS == RegQueryValueEx(hKey,
|
||
|
REGVAL_TZI, 0, NULL, (LPBYTE)&atzi, &ulLen))
|
||
|
{
|
||
|
tzi.Bias = atzi.Bias;
|
||
|
tzi.StandardBias = atzi.StandardBias;
|
||
|
tzi.DaylightBias = atzi.DaylightBias;
|
||
|
tzi.StandardDate = atzi.StandardDate;
|
||
|
tzi.DaylightDate = atzi.DaylightDate;
|
||
|
_tcsncpy (tzi.StandardName, buffer, TZNAME_SIZE);
|
||
|
|
||
|
ULONG ulLen = TZNAME_SIZE;
|
||
|
if (ERROR_SUCCESS != RegQueryValueEx(hKey, REGVAL_DLT,
|
||
|
0, NULL, (LPBYTE) &tzi.DaylightName, &ulLen))
|
||
|
_tcscpy (tzi.DaylightName, TEXT(""));
|
||
|
|
||
|
// SetTimeZoneInformation will update local time
|
||
|
// since the UTC time has not changed
|
||
|
if (FALSE == SetTimeZoneInformation (&tzi))
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
if (Verbose)
|
||
|
printf ("TimeZone = %ws\n", tzi.StandardName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
free (buffer);
|
||
|
}
|
||
|
|
||
|
Err:
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey (hKey);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SaveLocaleInfo
|
||
|
//
|
||
|
// Synopsis: formats a locale setting for registry update
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD SaveLocaleInfo(HKEY hKey, LCID lcid, LCTYPE LCType, TCHAR *pIniString)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
TCHAR ptcsBuffer[SIZE_128];
|
||
|
|
||
|
if (GetLocaleInfo( lcid,
|
||
|
LCType | LOCALE_NOUSEROVERRIDE,
|
||
|
ptcsBuffer,
|
||
|
SIZE_128 ))
|
||
|
{
|
||
|
dwErr = RegSetValueEx( hKey,
|
||
|
pIniString,
|
||
|
0L,
|
||
|
REG_SZ,
|
||
|
(BYTE *)ptcsBuffer,
|
||
|
(lstrlen(ptcsBuffer)+1) * sizeof(TCHAR));
|
||
|
}
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadInstallUserLocale
|
||
|
//
|
||
|
// Synopsis: sets the current user locale
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadInstallUserLocale ()
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
LCID lcid = 0;
|
||
|
TCHAR *ptcsUserLocale = NULL;
|
||
|
TCHAR ptcsOldLocale[25];
|
||
|
INFCONTEXT infcontext;
|
||
|
ULONG ulLen = 0;
|
||
|
|
||
|
if (SetupFindFirstLine(InputInf, SOURCE_SECTION, USERLOCALE, &infcontext))
|
||
|
{
|
||
|
dwErr = GetInfField (&ptcsUserLocale, &infcontext, 1);
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
{
|
||
|
lcid = (LCID)_tcstoul(ptcsUserLocale,NULL,16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Revert to current user locale if missing from INF
|
||
|
//
|
||
|
if (lcid == 0)
|
||
|
{
|
||
|
free (ptcsUserLocale);
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure the locale is valid.
|
||
|
//
|
||
|
if (!IsValidLocale(lcid, LCID_INSTALLED))
|
||
|
{
|
||
|
ChkErr (ERROR_INSTALL_LANGUAGE_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the locale value in the user's control panel international
|
||
|
// section of the registry.
|
||
|
//
|
||
|
ChkErr(RegOpenKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
|
||
|
REGKEY_INTL,
|
||
|
0L,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey ));
|
||
|
|
||
|
//
|
||
|
// Update user locale only if it's different
|
||
|
//
|
||
|
ulLen = sizeof (ptcsOldLocale);
|
||
|
if (ERROR_SUCCESS == RegQueryValueEx(hKey,
|
||
|
TEXT("Locale"),
|
||
|
NULL,NULL,
|
||
|
(BYTE*)ptcsOldLocale, &ulLen) &&
|
||
|
lstrcmp (ptcsUserLocale, ptcsOldLocale) == 0)
|
||
|
{
|
||
|
free (ptcsUserLocale);
|
||
|
RegCloseKey (hKey);
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
ChkErr (RegSetValueEx( hKey,
|
||
|
TEXT("Locale"),
|
||
|
0L,
|
||
|
REG_SZ,
|
||
|
(LPBYTE)ptcsUserLocale,
|
||
|
(lstrlen(ptcsUserLocale)+1) * sizeof(TCHAR)));
|
||
|
|
||
|
//
|
||
|
// When the locale changes, update ALL registry information.
|
||
|
//
|
||
|
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICALENDARTYPE, TEXT("iCalendarType")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICOUNTRY, TEXT("iCountry")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICURRDIGITS, TEXT("iCurrDigits")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICURRENCY, TEXT("iCurrency")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDATE, TEXT("iDate")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDIGITS, TEXT("iDigits")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IFIRSTDAYOFWEEK, TEXT("iFirstDayOfWeek" )));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IFIRSTWEEKOFYEAR, TEXT("iFirstWeekOfYear")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ILZERO, TEXT("iLzero")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IMEASURE, TEXT("iMeasure")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_INEGCURR, TEXT("iNegCurr")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_INEGNUMBER, TEXT("iNegNumber")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITIME, TEXT("iTime")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITIMEMARKPOSN, TEXT("iTimePrefix")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITLZERO, TEXT("iTLZero")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDIGITSUBSTITUTION,TEXT("NumShape")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_S1159, TEXT("s1159")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_S2359, TEXT("s2359")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SCOUNTRY, TEXT("sCountry")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SCURRENCY, TEXT("sCurrency")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SDATE, TEXT("sDate")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SDECIMAL, TEXT("sDecimal")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SGROUPING, TEXT("sGrouping")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SABBREVLANGNAME, TEXT("sLanguage")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SLIST, TEXT("sList")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SLONGDATE, TEXT("sLongDate")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONDECIMALSEP, TEXT("sMonDecimalSep")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONGROUPING, TEXT("sMonGrouping")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONTHOUSANDSEP, TEXT("sMonThousandSep")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SNATIVEDIGITS, TEXT("sNativeDigits")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SNEGATIVESIGN, TEXT("sNegativeSign")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SPOSITIVESIGN, TEXT("sPositiveSign")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SSHORTDATE, TEXT("sShortDate")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STHOUSAND, TEXT("sThousand")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STIME, TEXT("sTime")));
|
||
|
ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STIMEFORMAT, TEXT("sTimeFormat")));
|
||
|
|
||
|
//
|
||
|
// Set the user's default locale in the system so that any new
|
||
|
// process will use the new locale.
|
||
|
//
|
||
|
if (CurrentUser == HKEY_CURRENT_USER)
|
||
|
NtSetDefaultLocale(TRUE, lcid);
|
||
|
|
||
|
Err:
|
||
|
//
|
||
|
// Flush the International key.
|
||
|
//
|
||
|
if (hKey != NULL)
|
||
|
{
|
||
|
RegFlushKey(hKey);
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
if (ptcsUserLocale != NULL)
|
||
|
free (ptcsUserLocale);
|
||
|
|
||
|
//
|
||
|
// Return success.
|
||
|
//
|
||
|
return (dwErr);
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ReadVersionKey
|
||
|
//
|
||
|
// Synopsis: helper function that reads a value in CurrentVersion key
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD ReadVersionKey (TCHAR *pValueName, TCHAR *pValue, ULONG ulLen)
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
static const TCHAR REGKEY_VERSION[] =
|
||
|
TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
|
||
|
|
||
|
ChkErr (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_VERSION,
|
||
|
NULL, KEY_READ, &hKey));
|
||
|
ChkErr (RegQueryValueEx(hKey,pValueName,NULL,NULL,(BYTE*)pValue, &ulLen));
|
||
|
Err:
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey (hKey);
|
||
|
return dwErr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if 0
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetDomainMembershipInfo
|
||
|
//
|
||
|
// Synopsis: return domain or workgroup name
|
||
|
//
|
||
|
// Arguments: [szname] -- output string for sysprep
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS GetDomainMembershipInfo (TCHAR *szName)
|
||
|
{
|
||
|
NTSTATUS ntstatus;
|
||
|
POLICY_PRIMARY_DOMAIN_INFO* ppdi;
|
||
|
LSA_OBJECT_ATTRIBUTES loa;
|
||
|
LSA_HANDLE hLsa = 0;
|
||
|
|
||
|
loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
|
||
|
loa.RootDirectory = NULL;
|
||
|
loa.ObjectName = NULL;
|
||
|
loa.Attributes = 0;
|
||
|
loa.SecurityDescriptor = NULL;
|
||
|
loa.SecurityQualityOfService = NULL;
|
||
|
|
||
|
ntstatus = LsaOpenPolicy(NULL, &loa, POLICY_VIEW_LOCAL_INFORMATION, &hLsa);
|
||
|
if (LSA_SUCCESS(ntstatus))
|
||
|
{
|
||
|
ntstatus = LsaQueryInformationPolicy( hLsa,
|
||
|
PolicyPrimaryDomainInformation,
|
||
|
(VOID **) &ppdi );
|
||
|
if( LSA_SUCCESS( ntstatus ) )
|
||
|
{
|
||
|
lstrcpy (szName, (ppdi->Sid > 0 ) ? TEXT("JoinDomain=") :
|
||
|
TEXT("JoinWorkgroup="));
|
||
|
lstrcat( szName, ppdi->Name.Buffer );
|
||
|
}
|
||
|
LsaClose (hLsa);
|
||
|
}
|
||
|
return (ntstatus);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if 0
|
||
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SysprepFile
|
||
|
//
|
||
|
// Synopsis: generates the sysprep unattended file
|
||
|
//
|
||
|
// Arguments: [dwLangGroup] -- language group to install
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
DWORD SysprepFile (DWORD dwLangGroup)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD dwTimeZone = 0;
|
||
|
INFCONTEXT InfContext;
|
||
|
TCHAR * pFullName = NULL;
|
||
|
TCHAR * pOrgName = NULL;
|
||
|
const int MAX_WORKGROUP_LENGTH = 15;
|
||
|
const int NAME_LENGTH = 128;
|
||
|
const TCHAR REGVAL_FULLNAME[] = TEXT("RegisteredOwner");
|
||
|
const TCHAR REGVAL_ORGNAME[] = TEXT("RegisteredOrganization");
|
||
|
const TCHAR REGVAL_INSTALLPATH[] = TEXT("SourcePath");
|
||
|
TCHAR szFullName[NAME_LENGTH] = TEXT("");
|
||
|
TCHAR szOrgName[NAME_LENGTH] = TEXT("");
|
||
|
TCHAR szInstall[MAX_PATH];
|
||
|
TCHAR szTargetPath[MAX_PATH];
|
||
|
TCHAR szComputerName[NAME_LENGTH];
|
||
|
TCHAR *pTargetPath;
|
||
|
CHAR *pFile = NULL;
|
||
|
ULONG ulLen;
|
||
|
TCHAR szJoin [MAX_WORKGROUP_LENGTH + 1 + NAME_LENGTH];
|
||
|
|
||
|
CHAR szSysprep[] = "[Unattended]\r\n"
|
||
|
"OemSkipEula=Yes\r\n"
|
||
|
"InstallFilesPath=%ws\r\n"
|
||
|
"TargetPath=%ws\r\n"
|
||
|
"\r\n"
|
||
|
"[GuiUnattended]\r\n"
|
||
|
"AdminPassword=*\r\n"
|
||
|
"OEMSkipRegional=1\r\n"
|
||
|
"TimeZone=%x\r\n"
|
||
|
"OemSkipWelcome=1\r\n"
|
||
|
"\r\n"
|
||
|
"[UserData]\r\n"
|
||
|
"FullName=\"%ws\"\r\n"
|
||
|
"OrgName=\"%ws\"\r\n"
|
||
|
"ComputerName=%ws\r\n"
|
||
|
"\r\n"
|
||
|
"[Identification]\r\n"
|
||
|
"%ws\r\n"
|
||
|
"\r\n"
|
||
|
"[RegionalSettings]\r\n"
|
||
|
"LanguageGroup=%d\r\n"
|
||
|
"\r\n"
|
||
|
"[Networking]\r\n"
|
||
|
"InstallDefaultComponents=Yes\r\n";
|
||
|
|
||
|
|
||
|
if (FALSE == GetWindowsDirectory ((TCHAR*) szTargetPath, MAX_PATH))
|
||
|
ChkErr (GetLastError());
|
||
|
|
||
|
if (szTargetPath[1] == ':' && szTargetPath[2] == '\\')
|
||
|
pTargetPath = &szTargetPath[2];
|
||
|
else
|
||
|
pTargetPath = &szTargetPath[0];
|
||
|
|
||
|
ulLen = NAME_LENGTH;
|
||
|
if (FALSE == GetComputerName ((TCHAR*) szComputerName, &ulLen))
|
||
|
ChkErr (GetLastError());
|
||
|
|
||
|
if (SetupFindFirstLine(InputInf, SOURCE_SECTION, FULLNAME, &InfContext))
|
||
|
{
|
||
|
ChkErr (GetInfField (&pFullName, &InfContext, 1));
|
||
|
}
|
||
|
else // use the current fullname
|
||
|
{
|
||
|
ChkErr(ReadVersionKey((TCHAR*)REGVAL_FULLNAME,
|
||
|
szFullName, sizeof(szFullName)));
|
||
|
pFullName = szFullName;
|
||
|
}
|
||
|
|
||
|
if (SetupFindFirstLine(InputInf, SOURCE_SECTION, ORGNAME, &InfContext))
|
||
|
{
|
||
|
ChkErr (GetInfField (&pOrgName, &InfContext, 1));
|
||
|
}
|
||
|
else // use the current org name
|
||
|
{
|
||
|
ChkErr(ReadVersionKey((TCHAR*)REGVAL_ORGNAME,
|
||
|
szFullName, sizeof(szFullName)));
|
||
|
pFullName = szOrgName;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS != ReadVersionKey((TCHAR*)REGVAL_INSTALLPATH,
|
||
|
szInstall, sizeof(szInstall)))
|
||
|
{
|
||
|
lstrcpy ((TCHAR *)szInstall, TEXT("")); // prompt for media?
|
||
|
}
|
||
|
|
||
|
if(!LSA_SUCCESS(GetDomainMembershipInfo(szJoin)))
|
||
|
lstrcpy (szJoin, TEXT(""));
|
||
|
|
||
|
if ((pFile = (CHAR *) malloc (4096)) == NULL)
|
||
|
ChkErr (ERROR_NOT_ENOUGH_MEMORY);
|
||
|
|
||
|
wsprintfA (pFile, szSysprep, szInstall, pTargetPath, dwTimeZone,
|
||
|
pFullName, pOrgName, szComputerName, szJoin, dwLangGroup);
|
||
|
|
||
|
hFile = CreateFile (
|
||
|
TEXT("sysprep.inf"),
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
0, // No sharing.
|
||
|
NULL, // No inheritance
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL // No template file.
|
||
|
);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hFile)
|
||
|
ChkErr (GetLastError());
|
||
|
|
||
|
if (FALSE == WriteFile (hFile, pFile, lstrlenA(pFile), &ulLen, NULL))
|
||
|
ChkErr (GetLastError());
|
||
|
|
||
|
Err:
|
||
|
if (pFullName != NULL)
|
||
|
free (pFullName);
|
||
|
if (pOrgName != NULL)
|
||
|
free (pOrgName);
|
||
|
if (pFile != NULL)
|
||
|
free (pFile);
|
||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||
|
CloseHandle (hFile);
|
||
|
return dwErr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadSystem
|
||
|
//
|
||
|
// Synopsis: load system settings
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: Appropriate status code
|
||
|
//
|
||
|
// History: 20-Sep-99 HenryLee Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD LoadSystem(int argc, char *argv[])
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD ccLen;
|
||
|
WCHAR *pBuf = NULL;
|
||
|
HKEY hKey;
|
||
|
WCHAR *pwMigrationPath = NULL;
|
||
|
int i;
|
||
|
DWORD dwInfCount = 0;
|
||
|
|
||
|
if ((dwErr = LoadVerifyOSLang()) != ERROR_SUCCESS)
|
||
|
return dwErr;
|
||
|
|
||
|
// If the schedule flag is set, write a run once to schedule
|
||
|
// applying the system settings.
|
||
|
if (SchedSystem)
|
||
|
{
|
||
|
WCHAR wcsModule[MAX_PATH];
|
||
|
DWORD ccModule = MAX_PATH;
|
||
|
|
||
|
if (0 == GetModuleFileName (NULL, wcsModule, ccModule))
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Convert the migration path to unicode.
|
||
|
dwErr = MakeUnicode( MigrationPath, &pwMigrationPath );
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
|
||
|
// Build a command line containing:
|
||
|
// /p parameter, to indicate running the user portion
|
||
|
// /s parameter, to indicate migrating system settings
|
||
|
// path to migration.inf
|
||
|
ccLen = wcslen(wcsModule) + wcslen(SCHED_PARAMS) + 1;
|
||
|
pBuf = (WCHAR *) malloc( ccLen * sizeof(WCHAR) );
|
||
|
if (pBuf == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
wcscpy( pBuf, wcsModule );
|
||
|
wcscat( pBuf, SCHED_PARAMS);
|
||
|
|
||
|
// Open the run once key.
|
||
|
dwErr = RegOpenKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
|
||
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
||
|
0, KEY_WRITE, &hKey );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
|
||
|
// Write the command to the registry.
|
||
|
dwErr = RegSetValueEx( hKey, TEXT("loadstate"), 0, REG_SZ,
|
||
|
(UCHAR *) pBuf, ccLen*sizeof(WCHAR) );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
RegCloseKey( hKey );
|
||
|
|
||
|
dwErr = RegCreateKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
|
||
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Loadstate",
|
||
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
|
||
|
// Write LogFile path to registry
|
||
|
dwErr = RegSetValueEx( hKey, TEXT("Logfile"), 0, REG_SZ,
|
||
|
(UCHAR *)szLogFile, (_tcslen(szLogFile) * sizeof(TCHAR)) );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
|
||
|
// Write Migration path to registry
|
||
|
dwErr = RegSetValueEx( hKey, TEXT("Store"), 0, REG_SZ,
|
||
|
(UCHAR *)pwMigrationPath, (_tcslen(pwMigrationPath) * sizeof(TCHAR)) );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
|
||
|
TCHAR szInfFile[MAX_PATH + 1];
|
||
|
TCHAR szFullInfFile[MAX_PATH + 1];
|
||
|
TCHAR szKeyName[6];
|
||
|
TCHAR *ptsFileNamePart;
|
||
|
|
||
|
// Prevent KeyName buffer overflow
|
||
|
if ( argc > 99)
|
||
|
{
|
||
|
if (Verbose)
|
||
|
{
|
||
|
Win32Printf(LogFile, "ERROR: Too many command line arguments [%d]\r\n", argc);
|
||
|
}
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
// Write InfFile paths to registry
|
||
|
for (i = 1; i < argc; i++)
|
||
|
{
|
||
|
if ((argv[i][0] == '/' || argv[i][0] == '-') &&
|
||
|
(tolower(argv[i][1]) == 'i'))
|
||
|
{
|
||
|
i++;
|
||
|
_stprintf(szKeyName, TEXT("Inf%d"), ++dwInfCount);
|
||
|
|
||
|
if (0 == MultiByteToWideChar (GetACP(), 0, argv[i], -1, szInfFile, MAX_PATH))
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
dwErr = GetFullPathName( szInfFile,
|
||
|
MAX_PATH,
|
||
|
szFullInfFile,
|
||
|
&ptsFileNamePart);
|
||
|
if (0 == dwErr)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
goto cleanup;
|
||
|
}
|
||
|
dwErr = RegSetValueEx( hKey, szKeyName, 0, REG_SZ,
|
||
|
(UCHAR *)szFullInfFile, (_tcslen(szFullInfFile) * sizeof(TCHAR)) );
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto cleanup;
|
||
|
}
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
|
||
|
cleanup:
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
LogFormatError (dwErr);
|
||
|
|
||
|
free( pBuf );
|
||
|
free( pwMigrationPath );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!CopySystem)
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
ChkErr (LoadNetShares());
|
||
|
ChkErr (LoadPrinters());
|
||
|
|
||
|
dwErr = InitializeRasApi();
|
||
|
if ( dwErr == ERROR_SUCCESS )
|
||
|
{
|
||
|
ChkErr (LoadRas());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No problem, just skip Ras processing
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
if (CopyUser == FALSE)
|
||
|
{
|
||
|
if (CurrentUser == NULL)
|
||
|
CurrentUser = HKEY_CURRENT_USER;
|
||
|
|
||
|
ChkErr(InitializeHash());
|
||
|
}
|
||
|
|
||
|
ChkErr(CopyInf (ACCESS_SECTION));
|
||
|
ChkErr(CopyInf (DESKTOP_SECTION));
|
||
|
ChkErr(LoadKeyboardLayouts());
|
||
|
ChkErr (LoadTimeZone());
|
||
|
ChkErr (LoadInstallUserLocale());
|
||
|
}
|
||
|
|
||
|
Err:
|
||
|
return dwErr;
|
||
|
}
|