windows-nt/Source/XPSP1/NT/base/ntsetup/oobe/msobcomm/misc.cpp
2020-09-26 16:20:57 +08:00

1409 lines
36 KiB
C++

/*-----------------------------------------------------------------------------
misc.cpp
service functions
History:
1/7/98 DONALDM Moved to new ICW project and string
and nuked 16 bit stuff
-----------------------------------------------------------------------------*/
//#include <stdio.h>
#include "obcomglb.h"
#include <shlobj.h>
#include <winsock2.h>
#include <assert.h>
#include <ras.h>
#include <util.h>
#include <inetreg.h>
#include <userenv.h>
#include <userenvp.h>
#include <shlwapi.h>
#include <sddl.h>
extern "C"
{
#include <sputils.h>
}
#define DIR_SIGNUP L"signup"
#define DIR_WINDOWS L"windows"
#define DIR_SYSTEM L"system"
#define DIR_TEMP L"temp"
#define INF_DEFAULT L"SPAM SPAM SPAM SPAM SPAM SPAM EGGS AND SPAM"
const WCHAR cszFALSE[] = L"FALSE";
const WCHAR cszTRUE[] = L"TRUE";
BOOL g_bGotProxy=FALSE;
//+----------------------------------------------------------------------------
// NAME: GetSz
//
// Load strings from resources
//
// Created 1/28/96, Chris Kauffman
//+----------------------------------------------------------------------------
LPWSTR GetSz(DWORD dwszID)
{
/*
LPWSTR psz = szStrTable[iSzTable];
iSzTable++;
if (iSzTable >= MAX_STRINGS)
iSzTable = 0;
if (!LoadString(_Module.GetModuleInstance(), dwszID, psz, 512))
{
*psz = 0;
}
return (psz);
*/
return (NULL);
}
//+---------------------------------------------------------------------------
//
// Function: ProcessDBCS
//
// Synopsis: Converts control to use DBCS compatible font
// Use this at the beginning of the dialog procedure
//
// Note that this is required due to a bug in Win95-J that prevents
// it from properly mapping MS Shell Dlg. This hack is not needed
// under winNT.
//
// Arguments: hwnd - Window handle of the dialog
// cltID - ID of the control you want changed.
//
// Returns: ERROR_SUCCESS
//
// History: 4/31/97 a-frankh Created
// 5/13/97 jmazner Stole from CM to use here
//----------------------------------------------------------------------------
void ProcessDBCS(HWND hDlg, int ctlID)
{
HFONT hFont = NULL;
/*if( IsNT() )
{
return;
}*/
hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
if (hFont == NULL)
hFont = (HFONT) GetStockObject(SYSTEM_FONT);
if (hFont != NULL)
SendMessage(GetDlgItem(hDlg, ctlID), WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0));
}
// ############################################################################
// StoreInSignUpReg
//
// Created 3/18/96, Chris Kauffman
// ############################################################################
HRESULT StoreInSignUpReg(LPBYTE lpbData, DWORD dwSize, DWORD dwType, LPCWSTR pszKey)
{
HRESULT hr = ERROR_ACCESS_DENIED;
HKEY hKey;
hr = RegCreateKey(HKEY_LOCAL_MACHINE, SIGNUPKEY, &hKey);
if (hr != ERROR_SUCCESS) goto StoreInSignUpRegExit;
hr = RegSetValueEx(hKey, pszKey, 0,dwType,lpbData,dwSize);
RegCloseKey(hKey);
StoreInSignUpRegExit:
return hr;
}
HRESULT ReadSignUpReg(LPBYTE lpbData, DWORD *pdwSize, DWORD dwType, LPCWSTR pszKey)
{
HRESULT hr = ERROR_ACCESS_DENIED;
HKEY hKey = 0;
hr = RegOpenKey(HKEY_LOCAL_MACHINE, SIGNUPKEY, &hKey);
if (hr != ERROR_SUCCESS) goto ReadSignUpRegExit;
hr = RegQueryValueEx(hKey, pszKey, 0,&dwType,lpbData,pdwSize);
ReadSignUpRegExit:
if (hKey) RegCloseKey (hKey);
return hr;
}
HRESULT DeleteSignUpReg(LPCWSTR pszKey)
{
HRESULT hr = ERROR_ACCESS_DENIED;
HKEY hKey = 0;
hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SIGNUPKEY, 0, KEY_ALL_ACCESS, &hKey);
if (hr != ERROR_SUCCESS) goto ReadSignUpRegExit;
hr = RegDeleteValue(hKey, pszKey);
ReadSignUpRegExit:
if (hKey) RegCloseKey (hKey);
return hr;
}
// ############################################################################
// GetDataFromISPFile
//
// This function will read a specific piece of information from an ISP file.
//
// Created 3/16/96, Chris Kauffman
// ############################################################################
HRESULT GetDataFromISPFile
(
LPWSTR pszISPCode,
LPWSTR pszSection,
LPWSTR pszDataName,
LPWSTR pszOutput,
DWORD cchOutput)
{
LPWSTR pszTemp;
HRESULT hr = ERROR_SUCCESS;
WCHAR szTempPath[MAX_PATH];
//WCHAR szBuff256[256];
*pszOutput = L'\0'; // since lstrlen(pszOutput) is used later when
// pszOutput may be otherwise still uninitialized
// Locate ISP file
if (!SearchPath(NULL, pszISPCode, INF_SUFFIX,MAX_PATH,szTempPath,&pszTemp))
{
//wsprintf(szBuff256, L"Can not find:%s%s (%d) (connect.exe)", pszISPCode,INF_SUFFIX,GetLastError());
////AssertMsg(0, szBuff256);
//lstrcpyn(szTempPath, pszISPCode, MAX_PATH);
//lstrcpyn(&szTempPath[lstrlen(szTempPath)], INF_SUFFIX, MAX_PATH-lstrlen(szTempPath));
//wsprintf(szBuff256, GetSz(IDS_CANTLOADINETCFG), szTempPath);
////MessageBox(NULL, szBuff256, GetSz(IDS_TITLE),MB_MYERROR);
hr = ERROR_FILE_NOT_FOUND;
} else if (!GetPrivateProfileString(pszSection, pszDataName, INF_DEFAULT,
pszOutput, (int)cchOutput, szTempPath))
{
//TraceMsg(TF_GENERAL, L"ICWHELP: %s not specified in ISP file.\n", pszDataName);
hr = ERROR_FILE_NOT_FOUND;
}
// 10/23/96 jmazner Normandy #9921
// CompareString does _not_ have same return values as lsrtcmp!
// Return value of 2 indicates strings are equal.
//if (!CompareString(LOCALE_SYSTEM_DEFAULT, 0, INF_DEFAULT,lstrlen(INF_DEFAULT),pszOutput,lstrlen(pszOutput)))
if (2 == CompareString(LOCALE_SYSTEM_DEFAULT, 0, INF_DEFAULT,lstrlen(INF_DEFAULT),pszOutput,lstrlen(pszOutput)))
{
hr = ERROR_FILE_NOT_FOUND;
}
if (hr != ERROR_SUCCESS && cchOutput)
*pszOutput = L'\0'; // I suppose if CompareString fails, this is not
// redundant with the first *pszOutput = L'\0';.
return hr;
}
// ############################################################################
// GetINTFromISPFile
//
// This function will read a specific integer from an ISP file.
//
//
// ############################################################################
HRESULT GetINTFromISPFile
(
LPWSTR pszISPCode,
LPWSTR pszSection,
LPWSTR pszDataName,
int far *lpData,
int iDefaultValue
)
{
LPWSTR pszTemp;
HRESULT hr = ERROR_SUCCESS;
WCHAR szTempPath[MAX_PATH];
//WCHAR szBuff256[256];
// Locate ISP file
if (!SearchPath(NULL, pszISPCode, INF_SUFFIX,MAX_PATH,szTempPath,&pszTemp))
{
//wsprintf(szBuff256, L"Can not find:%s%s (%d) (connect.exe)", pszISPCode,INF_SUFFIX,GetLastError());
////AssertMsg(0, szBuff256);
//lstrcpyn(szTempPath, pszISPCode, MAX_PATH);
//lstrcpyn(&szTempPath[lstrlen(szTempPath)], INF_SUFFIX, MAX_PATH-lstrlen(szTempPath));
//wsprintf(szBuff256, GetSz(IDS_CANTLOADINETCFG), szTempPath);
//MessageBox(NULL, szBuff256, GetSz(IDS_TITLE),MB_MYERROR);
hr = ERROR_FILE_NOT_FOUND;
}
*lpData = GetPrivateProfileInt(pszSection,
pszDataName,
iDefaultValue,
szTempPath);
return hr;
}
//+-------------------------------------------------------------------
//
// Function: IsNT
//
// Synopsis: findout If we are running on NT
//
// Arguements: none
//
// Return: TRUE - Yes
// FALSE - No
//
//--------------------------------------------------------------------
BOOL IsNT ()
{
OSVERSIONINFO OsVersionInfo;
ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo);
return (VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId);
} //end of IsNT function call
//+-------------------------------------------------------------------
//
// Function: IsNT4SP3Lower
//
// Synopsis: findout If we are running on NTSP3 or lower
//
// Arguements: none
//
// Return: TRUE - Yes
// FALSE - No
//
//--------------------------------------------------------------------
BOOL IsNT4SP3Lower()
{
return FALSE;
}
// ############################################################################
HRESULT ClearProxySettings()
{
/*
HINSTANCE hinst = NULL;
FARPROC fp;
HRESULT hr = ERROR_SUCCESS;
hinst = LoadLibrary(L"INETCFG.DLL");
if (hinst)
{
fp = GetProcAddress(hinst, "InetGetProxy");
if (!fp)
{
hr = GetLastError();
goto ClearProxySettingsExit;
}
//hr = ((PFNINETGETPROXY)fp)(&g_bProxy, NULL, 0,NULL,0);
if (hr == ERROR_SUCCESS)
g_bGotProxy = TRUE;
else
goto ClearProxySettingsExit;
if (g_bProxy)
{
fp = GetProcAddress(hinst, "InetSetProxy");
if (!fp)
{
hr = GetLastError();
goto ClearProxySettingsExit;
}
((PFNINETSETPROXY)fp)(FALSE, (LPCSTR)NULL, (LPCSTR)NULL);
}
} else {
hr = GetLastError();
}
ClearProxySettingsExit:
if (hinst)
FreeLibrary(hinst);
return hr;
*/
return ERROR_SUCCESS;
}
// ############################################################################
HRESULT RestoreProxySettings()
{
/*
HINSTANCE hinst = NULL;
FARPROC fp;
HRESULT hr = ERROR_SUCCESS;
hinst = LoadLibrary(L"INETCFG.DLL");
if (hinst && g_bGotProxy)
{
fp = GetProcAddress(hinst, "InetSetProxy");
if (!fp)
{
hr = GetLastError();
goto RestoreProxySettingsExit;
}
((PFNINETSETPROXY)fp)(g_bProxy, (LPCSTR)NULL, (LPCSTR)NULL);
} else {
hr = GetLastError();
}
RestoreProxySettingsExit:
if (hinst)
FreeLibrary(hinst);
return hr;
*/
return ERROR_SUCCESS;
}
// ############################################################################
BOOL FSz2Dw(LPCWSTR pSz, LPDWORD dw)
{
DWORD val = 0;
while (*pSz && *pSz != L'.')
{
if (*pSz >= L'0' && *pSz <= L'9')
{
val *= 10;
val += *pSz++ - L'0';
}
else
{
return FALSE; //bad number
}
}
*dw = val;
return (TRUE);
}
// ############################################################################
LPWSTR GetNextNumericChunk(LPWSTR psz, LPWSTR pszLim, LPWSTR* ppszNext)
{
LPWSTR pszEnd;
// init for error case
*ppszNext = NULL;
// skip non numerics if any to start of next numeric chunk
while(*psz<L'0' || *psz>L'9')
{
if(psz >= pszLim) return NULL;
psz++;
}
// skip all numerics to end of country code
for(pszEnd=psz; *pszEnd>=L'0' && *pszEnd<=L'9' && pszEnd<pszLim; pszEnd++)
;
// zap whatever delimiter there was to terminate this chunk
*pszEnd++ = L'\0';
// return ptr to next chunk (pszEnd now points to it)
if(pszEnd<pszLim)
*ppszNext = pszEnd;
return psz; // return ptr to start of chunk
}
// ############################################################################
// BOOL FSz2DwEx(PCSTR pSz, DWORD *dw)
// Accepts -1 as a valid number. currently this is used for LCID, since all langs has a LDID == -1
BOOL FSz2DwEx(LPCWSTR pSz, DWORD far *dw)
{
DWORD val = 0;
BOOL bNeg = FALSE;
while (*pSz)
{
if( *pSz == L'-' )
{
bNeg = TRUE;
pSz++;
}
else if ((*pSz >= L'0' && *pSz <= L'9'))
{
val *= 10;
val += *pSz++ - L'0';
}
else
{
return FALSE; //bad number
}
}
if(bNeg)
val = 0 - val;
*dw = val;
return (TRUE);
}
// ############################################################################
// BOOL FSz2WEx(PCSTR pSz, WORD *w)
//Accepts -1 as a valid number. currently this is used for LCID, since all langs has a LDID == -1
BOOL FSz2WEx(LPCWSTR pSz, WORD far *w)
{
DWORD dw;
if (FSz2DwEx(pSz, &dw))
{
*w = (WORD)dw;
return TRUE;
}
return FALSE;
}
// ############################################################################
// BOOL FSz2W(PCSTR pSz, WORD *w)
BOOL FSz2W(LPCWSTR pSz, WORD far *w)
{
DWORD dw;
if (FSz2Dw(pSz, &dw))
{
*w = (WORD)dw;
return TRUE;
}
return FALSE;
}
// ############################################################################
WORD Sz2W (LPCWSTR szBuf)
{
DWORD dw;
if (FSz2Dw(szBuf, &dw))
{
return (WORD)dw;
}
return 0;
}
// ############################################################################
// BOOL FSz2B(PCSTR pSz, BYTE *pb)
BOOL FSz2BOOL(LPCWSTR pSz, BOOL far *pbool)
{
if (lstrcmpi(cszFALSE, pSz) == 0)
{
*pbool = (BOOL)FALSE;
}
else
{
*pbool = (BOOL)TRUE;
}
return TRUE;
}
// ############################################################################
// BOOL FSz2B(PCSTR pSz, BYTE *pb)
BOOL FSz2B(LPCWSTR pSz, BYTE far *pb)
{
DWORD dw;
if (FSz2Dw(pSz, &dw))
{
*pb = (BYTE)dw;
return TRUE;
}
return FALSE;
}
BOOL FSz2SPECIAL(LPCWSTR pSz, BOOL far *pbool, BOOL far *pbIsSpecial, int far *pInt)
{
// See if the value is a BOOL (TRUE or FALSE)
if (lstrcmpi(cszFALSE, pSz) == 0)
{
*pbool = FALSE;
*pbIsSpecial = FALSE;
}
else if (lstrcmpi(cszTRUE, pSz) == 0)
{
*pbool = (BOOL)TRUE;
*pbIsSpecial = FALSE;
}
else
{
// Not a BOOL, so it must be special
*pbool = (BOOL)FALSE;
*pbIsSpecial = TRUE;
*pInt = _wtoi(pSz);
}
return TRUE;
}
// ############################################################################
int FIsDigit( int c )
{
WCHAR szIn[2];
WORD rwOut[2];
szIn[0] = (WCHAR)c;
szIn[1] = L'\0';
GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, szIn,-1,rwOut);
return rwOut[0] & C1_DIGIT;
}
// ############################################################################
LPBYTE MyMemSet(LPBYTE dest, int c, size_t count)
{
LPVOID pv = dest;
LPVOID pvEnd = (LPVOID)(dest + (WORD)count);
while (pv < pvEnd)
{
*(LPINT)pv = c;
//((WORD)pv)++;
pv=((LPINT)pv)+1;
}
return dest;
}
// ############################################################################
LPBYTE MyMemCpy(LPBYTE dest, const LPBYTE src, size_t count)
{
LPBYTE pbDest = (LPBYTE)dest;
LPBYTE pbSrc = (LPBYTE)src;
LPBYTE pbEnd = (LPBYTE)((DWORD_PTR)src + (DWORD_PTR)count);
while (pbSrc < pbEnd)
{
*pbDest = *pbSrc;
pbSrc++;
pbDest++;
}
return dest;
}
// ############################################################################
BOOL ShowControl(HWND hDlg, int idControl, BOOL fShow)
{
HWND hWnd;
if (NULL == hDlg)
{
////AssertMsg(0, L"Null Param");
return FALSE;
}
hWnd = GetDlgItem(hDlg, idControl);
if (hWnd)
{
ShowWindow(hWnd, fShow ? SW_SHOW : SW_HIDE);
}
return TRUE;
}
BOOL isAlnum(WCHAR c)
{
if ((c >= L'0' && c <= L'9') ||
(c >= L'a' && c <= L'z') ||
(c >= L'A' && c <= L'Z') )
return TRUE;
return FALSE;
}
// ############################################################################
BOOL FShouldRetry2(HRESULT hrErr)
{
BOOL bRC;
if (hrErr == ERROR_LINE_BUSY ||
hrErr == ERROR_VOICE_ANSWER ||
hrErr == ERROR_NO_ANSWER ||
hrErr == ERROR_NO_CARRIER ||
hrErr == ERROR_AUTHENTICATION_FAILURE ||
hrErr == ERROR_PPP_TIMEOUT ||
hrErr == ERROR_REMOTE_DISCONNECTION ||
hrErr == ERROR_AUTH_INTERNAL ||
hrErr == ERROR_PROTOCOL_NOT_CONFIGURED ||
hrErr == ERROR_PPP_NO_PROTOCOLS_CONFIGURED)
{
bRC = TRUE;
} else {
bRC = FALSE;
}
return bRC;
}
//+----------------------------------------------------------------------------
//
// Function: FCampusNetOverride
//
// Synopsis: Detect if the dial should be skipped for the campus network
//
// Arguments: None
//
// Returns: TRUE - overide enabled
//
// History: 8/15/96 ChrisK Created
//
//-----------------------------------------------------------------------------
#if defined(PRERELEASE)
BOOL FCampusNetOverride()
{
HKEY hkey = NULL;
BOOL bRC = FALSE;
DWORD dwType = 0;
DWORD dwSize = 0;
DWORD dwData = 0;
if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\ISignup\\Debug", &hkey))
goto FCampusNetOverrideExit;
dwSize = sizeof(dwData);
if (ERROR_SUCCESS != RegQueryValueEx(hkey, L"CampusNet", 0,&dwType,
(LPBYTE)&dwData, &dwSize))
goto FCampusNetOverrideExit;
////AssertMsg(REG_DWORD == dwType, L"Wrong value type for CampusNet. Must be DWORD.\r\n");
bRC = (0 != dwData);
if (bRC)
{
if (IDOK != MessageBox(NULL, L"DEBUG ONLY: CampusNet will be used.", L"Testing Override",MB_OKCANCEL))
bRC = FALSE;
}
FCampusNetOverrideExit:
if (hkey)
RegCloseKey(hkey);
return bRC;
}
#endif //PRERELEASE
//+----------------------------------------------------------------------------
// Function CopyUntil
//
// Synopsis Copy from source until destination until running out of source
// or until the next character of the source is the chend character
//
// Arguments dest - buffer to recieve characters
// src - source buffer
// lpdwLen - length of dest buffer
// chend - the terminating character
//
// Returns FALSE - ran out of room in dest buffer
//
// Histroy 10/25/96 ChrisK Created
//-----------------------------------------------------------------------------
static BOOL CopyUntil(LPWSTR *dest, LPWSTR *src, LPDWORD lpdwLen, WCHAR chend)
{
while ((L'\0' != **src) && (chend != **src) && (0 != *lpdwLen))
{
**dest = **src;
(*lpdwLen)--;
(*dest)++;
(*src)++;
}
return (0 != *lpdwLen);
}
//+---------------------------------------------------------------------------
//
// Function: GenericMsg
//
//----------------------------------------------------------------------------
void GenericMsg
(
HWND hwnd,
UINT uId,
LPCWSTR lpszArg,
UINT uType
)
{
WCHAR szTemp[MAX_STRING + 1];
WCHAR szMsg[MAX_STRING + MAX_PATH + 1];
LPWSTR psz;
//Assert( lstrlen( GetSz(uId) ) <= MAX_STRING );
psz = GetSz( (DWORD)uId );
if (psz) {
lstrcpy( szTemp, psz );
}
else {
szTemp[0] = '\0';
}
if (lpszArg)
{
//Assert( lstrlen( lpszArg ) <= MAX_PATH );
wsprintf(szMsg, szTemp, lpszArg);
}
else
{
lstrcpy(szMsg, szTemp);
}
//MessageBox(hwnd,
// szMsg,
// GetSz(IDS_TITLE),
// uType);
}
//=--------------------------------------------------------------------------=
// MakeWideFromAnsi
//=--------------------------------------------------------------------------=
// given a string, make a BSTR out of it.
//
// Parameters:
// LPWSTR - [in]
// BYTE - [in]
//
// Output:
// LPWSTR - needs to be cast to final desired result
//
// Notes:
//
LPWSTR MakeWideStrFromAnsi
(
LPSTR psz,
BYTE bType
)
{
LPWSTR pwsz = NULL;
int i;
// arg checking.
//
if (!psz)
return NULL;
// compute the length of the required BSTR
//
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
if (i <= 0) return NULL;
// allocate the widestr
//
switch (bType) {
case STR_BSTR:
// -1 since it'll add it's own space for a NULL terminator
//
pwsz = (LPWSTR) SysAllocStringLen(NULL, i - 1);
break;
case STR_OLESTR:
pwsz = (LPWSTR) CoTaskMemAlloc(BYTES_REQUIRED_BY_CCH(i));
break;
//default:
////AssertMsg(0, L"Bogus String Type.");
}
if (!pwsz) return NULL;
MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
pwsz[i - 1] = 0;
return pwsz;
}
//=--------------------------------------------------------------------------=
// MakeWideStrFromResId
//=--------------------------------------------------------------------------=
// given a resource ID, load it, and allocate a wide string for it.
//
// Parameters:
// WORD - [in] resource id.
// BYTE - [in] type of string desired.
//
// Output:
// LPWSTR - needs to be cast to desired string type.
//
// Notes:
//
LPWSTR MakeWideStrFromResourceId
(
WORD wId,
BYTE bType
)
{
//int i;
CHAR szTmp[512] = "0";
// load the string from the resources.
//
//i = LoadString(_Module.GetModuleInstance(), wId, szTmp, 512);
//if (!i) return NULL;
return MakeWideStrFromAnsi(szTmp, bType);
}
//=--------------------------------------------------------------------------=
// MakeWideStrFromWide
//=--------------------------------------------------------------------------=
// given a wide string, make a new wide string with it of the given type.
//
// Parameters:
// LPWSTR - [in] current wide str.
// BYTE - [in] desired type of string.
//
// Output:
// LPWSTR
//
// Notes:
//
LPWSTR MakeWideStrFromWide
(
LPWSTR pwsz,
BYTE bType
)
{
LPWSTR pwszTmp = NULL;
int i;
if (!pwsz) return NULL;
// just copy the string, depending on what type they want.
//
switch (bType) {
case STR_OLESTR:
i = lstrlenW(pwsz);
pwszTmp = (LPWSTR)CoTaskMemAlloc(BYTES_REQUIRED_BY_CCH(i+1));
if (!pwszTmp) return NULL;
memcpy(pwszTmp, pwsz, (BYTES_REQUIRED_BY_CCH(i+1)));
break;
case STR_BSTR:
pwszTmp = (LPWSTR)SysAllocString(pwsz);
break;
}
return pwszTmp;
}
HRESULT
GetCommonAppDataDirectory(
LPWSTR szDirectory,
DWORD cchDirectory
)
{
assert(MAX_PATH <= cchDirectory);
if (MAX_PATH > cchDirectory)
{
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
return SHGetFolderPath(NULL, // hwndOwner
CSIDL_COMMON_APPDATA,
NULL, // hAccessToken
SHGFP_TYPE_CURRENT,
szDirectory
);
}
const LPWSTR cszPhoneBookPath =
L"Microsoft\\Network\\Connections\\Pbk";
const LPWSTR cszDefPhoneBook = L"rasphone.pbk";
HRESULT
GetDefaultPhoneBook(
LPWSTR szPhoneBook,
DWORD cchPhoneBook
)
{
WCHAR rgchDirectory[MAX_PATH];
int cch;
HRESULT hr = GetCommonAppDataDirectory(rgchDirectory, MAX_PATH);
if (FAILED(hr))
{
return hr;
}
if (cchPhoneBook < (DWORD)(lstrlen(rgchDirectory) + lstrlen(cszPhoneBookPath) + lstrlen(cszDefPhoneBook) + 3)
)
{
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
cch = wsprintf(szPhoneBook, L"%s\\%s\\%s",
rgchDirectory, cszPhoneBookPath, cszDefPhoneBook
);
assert(cch == lstrlen(rgchDirectory) + lstrlen(cszPhoneBookPath) +
lstrlen(cszDefPhoneBook) + 2
);
return hr;
}
BOOL
INetNToW(
struct in_addr inaddr,
LPWSTR szAddr
)
{
USES_CONVERSION;
LPSTR sz = inet_ntoa(inaddr);
if (NULL != sz)
{
lstrcpy(szAddr, A2W(sz));
}
return (NULL != sz);
} // INetNToW
#ifndef REGSTR_VAL_NONETAUTODIAL
#define REGSTR_VAL_NONETAUTODIAL L"NoNetAutodial"
#endif
LONG
SetAutodial(
IN HKEY hUserRoot, // HKEY_CURRENT_USER or other user hive root
IN AUTODIAL_TYPE eType, // Type of autodial for the connectoid
IN LPCWSTR szConnectoidName, // NULL terminated string of connectoid name
IN BOOL bSetICWCompleted // set ICW completed flag or not
)
/*++
Routine Description:
Set a particular per-user registry settings to default an autodial
connectoid to the name specified and always dial the autodial connection, and/or
set the ICW completed flag
Return Value:
WIN32 Error code, i.e. ERROR_SUCCESS on success, -1 or other non-zero value
on failure.
Note:
Despite the name, this function sets ICW Completed flag if bSetICWCompleted
is true and do not set autodial if szConnectoidName is NULL.
--*/
{
LONG ret = -1;
HKEY hKey = NULL;
DWORD dwRet = -1;
if (bSetICWCompleted)
{
if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
ICWSETTINGSPATH,
&hKey) )
{
DWORD dwCompleted = 1;
ret = RegSetValueEx( hKey,
ICWCOMPLETEDKEY,
0,
REG_DWORD,
(CONST BYTE*)&dwCompleted,
sizeof(dwCompleted) );
TRACE1(L"Setting ICW Completed key 0x%08lx", ret);
RegCloseKey(hKey);
}
}
// Set the name if given, else do not change the entry.
if (szConnectoidName)
{
// Set the name of the connectoid for autodial.
// HKCU\RemoteAccess\InternetProfile
if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
REGSTR_PATH_REMOTEACCESS,
&hKey) )
{
ret = RegSetValueEx( hKey,
REGSTR_VAL_INTERNETPROFILE,
0,
REG_SZ,
(BYTE*)szConnectoidName,
BYTES_REQUIRED_BY_SZ(szConnectoidName) );
TRACE2(L"Setting IE autodial connectoid to %s 0x%08lx", szConnectoidName, ret);
RegCloseKey(hKey);
}
hKey = NULL;
if (ERROR_SUCCESS == ret)
{
// Set setting in the registry that indicates whether autodialing is enabled.
// HKCU\Software\Microsoft\Windows\CurrentVersion\InternetSettings\EnableAutodial
if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
REGSTR_PATH_INTERNET_SETTINGS,
&hKey) )
{
DWORD dwValue;
dwValue = (eType == AutodialTypeAlways || eType == AutodialTypeNoNet) ? 1 : 0;
ret = RegSetValueEx( hKey,
REGSTR_VAL_ENABLEAUTODIAL,
0,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(DWORD) );
TRACE1(L"Enable/Disable IE Autodial 0x%08lx", ret);
dwValue = (eType == AutodialTypeNoNet) ? 1 : 0;
ret = RegSetValueEx( hKey,
REGSTR_VAL_NONETAUTODIAL,
0,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(DWORD) );
TRACE1(L"Setting Autodial mode 0x%08lx", ret);
RegCloseKey(hKey);
}
}
}
return ret;
}
LONG
SetUserAutodial(
IN LPWSTR szProfileDir, // Directory containing a user's ntuser.dat file
IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
IN LPCWSTR szConnectoidName,// NULL terminated string of connectoid name
IN BOOL bSetICWCompleted // set the ICW completed key or not
)
/*++
Routine Description:
Modified a user profile, specified by the profile directory, to enable
autodial. SE_BACKUP_NAME and SE_RESTORE_NAME privileges are required to
load and unload a user hive.
Return Value:
WIN32 Error code, i.e. ERROR_SUCCESS on success, -1 or other non-zero value
on failure.
--*/
{
const WCHAR OOBE_USER_HIVE[] = L"OOBEUSERHIVE";
HKEY hUserHive = NULL;
WCHAR szProfilePath[MAX_PATH+1] = L"";
LONG ret = -1;
lstrcpyn(szProfilePath, szProfileDir, MAX_CHARS_IN_BUFFER(szProfilePath));
pSetupConcatenatePaths(szProfilePath,
L"\\NTUSER.DAT",
MAX_CHARS_IN_BUFFER(szProfilePath),
NULL);
ret = RegLoadKey(HKEY_USERS, OOBE_USER_HIVE, szProfilePath);
if (ret == ERROR_SUCCESS)
{
ret = RegOpenKeyEx( HKEY_USERS,
OOBE_USER_HIVE,
0,
KEY_WRITE,
&hUserHive );
if (ERROR_SUCCESS == ret)
{
ret = SetAutodial(hUserHive, eType, szConnectoidName, bSetICWCompleted);
RegCloseKey(hUserHive);
TRACE1(L"Autodial set %s", szProfilePath);
}
else
{
TRACE2(L"RegOpenKey %s failed %d", szProfilePath, ret);
}
RegUnLoadKey(HKEY_USERS, OOBE_USER_HIVE);
}
else
{
TRACE2(L"RegLoadKey %s failed %d", szProfilePath, ret);
}
return ret;
}
BOOL
MyGetUserProfileDirectory(
IN LPWSTR szUser, // a user account name
OUT LPWSTR szUserProfileDir, // buffer to receive null terminate string
IN OUT LPDWORD pcchSize // input the buffer size in TCHAR, including terminating NULL
)
/*++
Routine Description:
This function does what the SDK function GetUserProfileDirectory does,
except that it accepts a user account name instead of handle to a user
token.
Return Value:
TRUE - Success
FALSE - Failure
--*/
{
PSID pSid = NULL;
DWORD cbSid = 0;
LPWSTR szDomainName = NULL;
DWORD cbDomainName = 0;
SID_NAME_USE eUse = SidTypeUser;
BOOL bRet;
bRet = LookupAccountName(NULL,
szUser,
NULL,
&cbSid,
NULL,
&cbDomainName,
&eUse);
if (!bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pSid = (PSID) LocalAlloc(LPTR, cbSid);
szDomainName = (LPWSTR) LocalAlloc(LPTR, cbDomainName * sizeof(TCHAR));
if (pSid && szDomainName)
{
bRet = LookupAccountName(NULL,
szUser,
pSid,
&cbSid,
szDomainName,
&cbDomainName,
&eUse);
}
}
if (bRet && SidTypeUser == eUse)
{
bRet = GetUserProfileDirFromSid(pSid, szUserProfileDir, pcchSize);
if (!bRet)
{
TRACE1(L"GetUserProfileDirFromSid (%d)", GetLastError());
}
}
else
{
if (SidTypeUser == eUse)
{
TRACE2(L"LookupAccountName %s (%d)", szUser, GetLastError());
}
}
if (pSid)
{
LocalFree(pSid);
pSid = NULL;
}
if (szDomainName)
{
LocalFree(szDomainName);
szDomainName = NULL;
}
return bRet;
}
BOOL EnumBuildInAdministrators(
OUT LPWSTR* pszAlias // list of name delimited by null, double null-terminated
)
/*++
Routine Description:
List all the build-in administrator accounts created by Windows Setup.
Return Value:
TRUE - Success
FALSE - Failure
--*/
{
WCHAR szReservedAdmins[MAX_PATH * 2] = L"";
PWCHAR p = NULL;
DWORD len;
BOOL ret = FALSE;
HINSTANCE hInstance = NULL;
if (pszAlias != NULL)
{
*pszAlias = NULL;
hInstance = LoadLibraryEx(OOBE_MAIN_DLL, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (hInstance != NULL)
{
len = LoadString(hInstance,
566, // IDS_ACCTLIST_RESERVEDADMINS in OOBE_MAIN_DLL
szReservedAdmins,
MAX_CHARS_IN_BUFFER(szReservedAdmins));
if (len)
{
DWORD cbSize;
p = StrChr(szReservedAdmins, L'|');
while ( p )
{
PWCHAR t = CharNext(p);
*p = L'\0';
p = StrChr(t, L'|');
}
cbSize = sizeof(WCHAR) * (len + 1);
// Make sure we have enough space for
// double NULL terminate the return value
*pszAlias = (LPWSTR) GlobalAlloc(GPTR, cbSize + sizeof(WCHAR));
if (*pszAlias)
{
CopyMemory(*pszAlias, szReservedAdmins, cbSize);
// double NULL terminate the string
(*pszAlias)[cbSize / sizeof(WCHAR)] = L'\0';
ret = TRUE;
}
}
FreeLibrary(hInstance);
}
}
return ret;
}
BOOL
SetMultiUserAutodial(
IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
IN LPCWSTR szConnectoidName,// NULL terminated string of connectoid name
IN BOOL bSetICWCompleted // set the ICW completed key or not
)
{
BOOL bSucceed = TRUE;
LONG lRet = ERROR_SUCCESS;
WCHAR szProfileDir[MAX_PATH+1] = L"";
DWORD dwSize;
LPWSTR szAdmins = NULL;
// SYSTEM
lRet = SetAutodial(HKEY_CURRENT_USER, eType, szConnectoidName, bSetICWCompleted);
if (lRet != ERROR_SUCCESS)
{
bSucceed = FALSE;
}
pSetupEnablePrivilege(SE_BACKUP_NAME, TRUE);
pSetupEnablePrivilege(SE_RESTORE_NAME, TRUE);
// Default User, which will apply to any new user profiles created
// afterward.
dwSize = MAX_CHARS_IN_BUFFER(szProfileDir);
if (GetDefaultUserProfileDirectory(szProfileDir, &dwSize))
{
lRet = SetUserAutodial(szProfileDir, eType, szConnectoidName, bSetICWCompleted);
if (lRet != ERROR_SUCCESS)
{
bSucceed = FALSE;
}
}
// Built-in Administrators, e.g. Administrator.
if (EnumBuildInAdministrators(&szAdmins))
{
LPWSTR szAdmin = szAdmins;
while (*szAdmin)
{
// MAX_CHARS_IN_BUFFER excludes the terminating NULL
dwSize = MAX_CHARS_IN_BUFFER(szProfileDir) + 1;
if (MyGetUserProfileDirectory(szAdmin, szProfileDir, &dwSize))
{
lRet = SetUserAutodial(szProfileDir, eType, szConnectoidName, bSetICWCompleted);
if (lRet != ERROR_SUCCESS)
{
bSucceed = FALSE;
}
}
szAdmin += (lstrlen(szAdmin) + 1);
}
GlobalFree(szAdmins);
}
return bSucceed;
}
BOOL
SetDefaultConnectoid(
IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
IN LPCWSTR szConnectoidName // null terminated autodial connectoid name
)
/*++
Routine Description:
Set the default autodial connectoid for SYSTEM, Default User and
build-in administrators. Assume that this function is run in System
context, i.e. it is SYSTEM who runs OOBE.
Return Value:
TRUE - Success to set all user accounts
FALSE - Failure to set any one of the user accounts
--*/
{
BOOL bSucceed = TRUE;
LONG lRet = ERROR_SUCCESS;
RASAUTODIALENTRY adEntry;
//
// IE on WinXP use Ras autodial address, instead of its own registry
// key for autodial connection name, but it keeps using its own registry
// key for autodial mode.
//
ZeroMemory(&adEntry, sizeof(RASAUTODIALENTRY));
adEntry.dwSize = sizeof(RASAUTODIALENTRY);
lstrcpyn(adEntry.szEntry, szConnectoidName,
sizeof(adEntry.szEntry)/sizeof(WCHAR)
);
lRet = RasSetAutodialAddress(NULL,
NULL,
&adEntry,
sizeof(RASAUTODIALENTRY),
1
);
TRACE2(L"Setting default autodial connectoid to %s %d\n",
szConnectoidName, lRet);
if (lRet != ERROR_SUCCESS)
{
bSucceed = FALSE;
return bSucceed;
}
bSucceed = SetMultiUserAutodial(eType, szConnectoidName, FALSE);
return bSucceed;
}