mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1612 lines
53 KiB
1612 lines
53 KiB
#include "mslocusr.h"
|
|
#include "msluglob.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include <regentry.h>
|
|
#include "profiles.h"
|
|
#include <npmsg.h>
|
|
|
|
extern "C" void SHFlushSFCache(void);
|
|
|
|
void ReportUserError(HWND hwndParent, HRESULT hres)
|
|
{
|
|
if (SUCCEEDED(hres))
|
|
return;
|
|
|
|
UINT idMsg;
|
|
NLS_STR nlsSub(16); /* long enough for any 32-bit number, any format */
|
|
|
|
if ((((DWORD)hres) >> 16) == (FACILITY_WIN32 | 0x8000)) {
|
|
UINT err = (hres & 0xffff);
|
|
|
|
switch (err) {
|
|
case ERROR_ACCESS_DENIED: idMsg = IDS_E_ACCESSDENIED; break;
|
|
case ERROR_NOT_AUTHENTICATED: idMsg = IDS_ERROR_NOT_AUTHENTICATED; break;
|
|
case ERROR_NO_SUCH_USER: idMsg = IDS_ERROR_NO_SUCH_USER; break;
|
|
case ERROR_USER_EXISTS: idMsg = IDS_ERROR_USER_EXISTS; break;
|
|
case ERROR_NOT_ENOUGH_MEMORY: idMsg = IDS_ERROR_OUT_OF_MEMORY; break;
|
|
case ERROR_BUSY: idMsg = IDS_ERROR_BUSY; break;
|
|
case ERROR_PATH_NOT_FOUND: idMsg = IDS_ERROR_PATH_NOT_FOUND; break;
|
|
case ERROR_BUFFER_OVERFLOW: idMsg = IDS_ERROR_BUFFER_OVERFLOW; break;
|
|
case IERR_CachingDisabled: idMsg = IDS_IERR_CachingDisabled; break;
|
|
case IERR_BadSig: idMsg = IDS_IERR_BadSig; break;
|
|
case IERR_CacheReadOnly : idMsg = IDS_IERR_CacheReadOnly; break;
|
|
case IERR_IncorrectUsername: idMsg = IDS_IERR_IncorrectUsername; break;
|
|
case IERR_CacheCorrupt: idMsg = IDS_IERR_CacheCorrupt; break;
|
|
case IERR_UsernameNotFound: idMsg = IDS_IERR_UsernameNotFound; break;
|
|
case IERR_CacheFull: idMsg = IDS_IERR_CacheFull; break;
|
|
case IERR_CacheAlreadyOpen: idMsg = IDS_IERR_CacheAlreadyOpen; break;
|
|
|
|
default:
|
|
idMsg = IDS_UNKNOWN_ERROR;
|
|
wsprintf(nlsSub.Party(), "%d", err);
|
|
nlsSub.DonePartying();
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
switch(hres) {
|
|
case E_OUTOFMEMORY: idMsg = IDS_ERROR_OUT_OF_MEMORY; break;
|
|
// case E_ACCESSDENIED: idMsg = IDS_E_ACCESSDENIED; break;
|
|
|
|
default:
|
|
idMsg = IDS_UNKNOWN_ERROR;
|
|
wsprintf(nlsSub.Party(), "0x%x", hres);
|
|
nlsSub.DonePartying();
|
|
break;
|
|
}
|
|
}
|
|
|
|
const NLS_STR *apnls[] = { &nlsSub, NULL };
|
|
|
|
MsgBox(hwndParent, idMsg, MB_OK | MB_ICONSTOP, apnls);
|
|
}
|
|
|
|
|
|
const UINT MAX_WIZ_PAGES = 8;
|
|
|
|
#if 0 /* now in mslocusr.h */
|
|
class CWizData : public IUserProfileInit
|
|
{
|
|
public:
|
|
HRESULT m_hresRatings; /* result of VerifySupervisorPassword("") */
|
|
BOOL m_fGoMultiWizard; /* TRUE if this is the big go-multiuser wizard */
|
|
NLS_STR m_nlsSupervisorPassword;
|
|
NLS_STR m_nlsUsername;
|
|
NLS_STR m_nlsUserPassword;
|
|
IUserDatabase *m_pDB;
|
|
IUser *m_pUserToClone;
|
|
int m_idPrevPage; /* ID of page before Finish */
|
|
UINT m_cRef;
|
|
DWORD m_fdwOriginalPerUserFolders;
|
|
DWORD m_fdwNewPerUserFolders;
|
|
DWORD m_fdwCloneFromDefault;
|
|
BOOL m_fCreatingProfile;
|
|
|
|
CWizData();
|
|
~CWizData();
|
|
|
|
// *** IUnknown methods ***
|
|
STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
|
|
STDMETHODIMP_(ULONG) AddRef(void);
|
|
STDMETHODIMP_(ULONG) Release(void);
|
|
|
|
STDMETHODIMP PreInitProfile(HKEY hkeyUser, LPCSTR pszProfileDir);
|
|
STDMETHODIMP PostInitProfile(HKEY hkeyUser, LPCSTR pszProfileDir);
|
|
};
|
|
#endif
|
|
|
|
|
|
CWizData::CWizData()
|
|
: m_nlsSupervisorPassword(),
|
|
m_nlsUsername(),
|
|
m_nlsUserPassword(),
|
|
m_cRef(0),
|
|
m_fdwOriginalPerUserFolders(0),
|
|
m_fdwNewPerUserFolders(0),
|
|
m_fdwCloneFromDefault(0),
|
|
m_fCreatingProfile(FALSE)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
CWizData::~CWizData()
|
|
{
|
|
if (m_pUserToClone != NULL)
|
|
m_pUserToClone->Release();
|
|
}
|
|
|
|
|
|
STDMETHODIMP CWizData::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
if (!IsEqualIID(riid, IID_IUnknown) &&
|
|
!IsEqualIID(riid, IID_IUserProfileInit)) {
|
|
*ppvObj = NULL;
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
*ppvObj = this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CWizData::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CWizData::Release(void)
|
|
{
|
|
ULONG cRef;
|
|
|
|
cRef = --m_cRef;
|
|
|
|
if (0L == m_cRef) {
|
|
delete this;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
|
|
|
|
void LimitCredentialLength(HWND hDlg, UINT idCtrl)
|
|
{
|
|
SendDlgItemMessage(hDlg, idCtrl, EM_LIMITTEXT, (WPARAM)cchMaxUsername, 0);
|
|
}
|
|
|
|
|
|
void AddPage(LPPROPSHEETHEADER ppsh, UINT id, DLGPROC pfn, LPVOID pwd)
|
|
{
|
|
if (ppsh->nPages < MAX_WIZ_PAGES)
|
|
{
|
|
PROPSHEETPAGE psp;
|
|
|
|
psp.dwSize = sizeof(psp);
|
|
psp.dwFlags = PSP_DEFAULT;
|
|
psp.hInstance = ::hInstance;
|
|
psp.pszTemplate = MAKEINTRESOURCE(id);
|
|
psp.pfnDlgProc = pfn;
|
|
psp.lParam = (LPARAM)pwd;
|
|
|
|
ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(&psp);
|
|
if (ppsh->phpage[ppsh->nPages])
|
|
ppsh->nPages++;
|
|
}
|
|
} // AddPage
|
|
|
|
|
|
INT_PTR CALLBACK IntroDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void GoToPage(HWND hDlg, int idPage)
|
|
{
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, idPage);
|
|
}
|
|
|
|
|
|
inline void FailChangePage(HWND hDlg)
|
|
{
|
|
GoToPage(hDlg, -1);
|
|
}
|
|
|
|
|
|
void InitWizDataPtr(HWND hDlg, LPARAM lParam)
|
|
{
|
|
CWizData *pwd = (CWizData *)(((LPPROPSHEETPAGE)lParam)->lParam);
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pwd);
|
|
}
|
|
|
|
|
|
void InsertControlText(HWND hDlg, UINT idCtrl, const NLS_STR *pnlsInsert)
|
|
{
|
|
int cchText = GetWindowTextLength(GetDlgItem(hDlg, IDC_MAIN_CAPTION)) + pnlsInsert->strlen() + 1;
|
|
NLS_STR nlsTemp(MAX_RES_STR_LEN);
|
|
if (nlsTemp.QueryError() == ERROR_SUCCESS) {
|
|
GetDlgItemText(hDlg, idCtrl, nlsTemp.Party(), nlsTemp.QueryAllocSize());
|
|
nlsTemp.DonePartying();
|
|
const NLS_STR *apnls[] = { pnlsInsert, NULL };
|
|
nlsTemp.InsertParams(apnls);
|
|
if (nlsTemp.QueryError() == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, idCtrl, nlsTemp.QueryPch());
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT GetControlText(HWND hDlg, UINT idCtrl, NLS_STR *pnls)
|
|
{
|
|
HWND hCtrl = GetDlgItem(hDlg, idCtrl);
|
|
if (pnls->realloc(GetWindowTextLength(hCtrl) + 1)) {
|
|
GetWindowText(hCtrl, pnls->Party(), pnls->QueryAllocSize());
|
|
pnls->DonePartying();
|
|
return NOERROR;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK EnterCAPWDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
if (SUCCEEDED(GetControlText(hDlg, IDC_PASSWORD, &pwd->m_nlsSupervisorPassword))) {
|
|
if (VerifySupervisorPassword(pwd->m_nlsSupervisorPassword.QueryPch()) == S_FALSE) {
|
|
MsgBox(hDlg, IDS_BADPASSWORD, MB_OK | MB_ICONSTOP);
|
|
SetErrorFocus(hDlg, IDC_PASSWORD);
|
|
FailChangePage(hDlg);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
InitWizDataPtr(hDlg, lParam);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK EnterUserPWDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
if (SUCCEEDED(GetControlText(hDlg, IDC_PASSWORD, &pwd->m_nlsUserPassword))) {
|
|
HANDLE hPWL = NULL;
|
|
if (FAILED(::GetUserPasswordCache(pwd->m_nlsUsername.QueryPch(),
|
|
pwd->m_nlsUserPassword.QueryPch(),
|
|
&hPWL, TRUE))) {
|
|
MsgBox(hDlg, IDS_BADPASSWORD, MB_OK | MB_ICONSTOP);
|
|
SetErrorFocus(hDlg, IDC_PASSWORD);
|
|
FailChangePage(hDlg);
|
|
}
|
|
else {
|
|
if (FAILED(pwd->m_hresRatings))
|
|
pwd->m_nlsSupervisorPassword = pwd->m_nlsUserPassword;
|
|
pwd->m_idPrevPage = IDD_EnterUserPassword;
|
|
::ClosePasswordCache(hPWL, TRUE);
|
|
int idNextPage;
|
|
if (pwd->m_fCreatingProfile)
|
|
idNextPage = IDD_ChooseFoldersWiz;
|
|
else
|
|
idNextPage = (pwd->m_fGoMultiWizard) ? IDD_FinishGoMulti : IDD_FinishAddUser;
|
|
GoToPage(hDlg, idNextPage);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
GoToPage(hDlg, IDD_EnterUsername);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
InsertControlText(hDlg, IDC_MAIN_CAPTION, &pwd->m_nlsUsername);
|
|
|
|
LimitCredentialLength(hDlg, IDC_PASSWORD);
|
|
|
|
if (FAILED(pwd->m_hresRatings)) {
|
|
NLS_STR nlsTemp(MAX_RES_STR_LEN);
|
|
if (nlsTemp.QueryError() == ERROR_SUCCESS) {
|
|
nlsTemp.LoadString(IDS_RATINGS_PW_COMMENT);
|
|
if (nlsTemp.QueryError() == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_RATINGS_PW_COMMENT, nlsTemp.QueryPch());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK EnterUsernameDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
int cchUsername = GetWindowTextLength(GetDlgItem(hDlg, IDC_USERNAME));
|
|
if (!cchUsername) {
|
|
MsgBox(hDlg, IDS_BLANK_USERNAME, MB_OK | MB_ICONSTOP);
|
|
SetErrorFocus(hDlg, IDC_USERNAME, FALSE);
|
|
FailChangePage(hDlg);
|
|
}
|
|
else {
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
if (SUCCEEDED(GetControlText(hDlg, IDC_USERNAME, &pwd->m_nlsUsername))) {
|
|
/* If we're in the add-user wizard, fail if the user
|
|
* already exists. In the go-multiuser wizard, we
|
|
* just use the info to determine whether to offer
|
|
* the folder-personalization page.
|
|
*/
|
|
IUser *pUser = NULL;
|
|
if (SUCCEEDED(pwd->m_pDB->GetUser(pwd->m_nlsUsername.QueryPch(), &pUser))) {
|
|
pUser->Release();
|
|
if (!pwd->m_fGoMultiWizard) {
|
|
const NLS_STR *apnls[] = { &pwd->m_nlsUsername, NULL };
|
|
if (MsgBox(hDlg, IDS_USER_EXISTS, MB_OKCANCEL | MB_ICONSTOP, apnls) == IDCANCEL) {
|
|
PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
|
|
break;
|
|
}
|
|
SetErrorFocus(hDlg, IDC_USERNAME, FALSE);
|
|
FailChangePage(hDlg);
|
|
break;
|
|
}
|
|
else {
|
|
pwd->m_fCreatingProfile = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
pwd->m_fCreatingProfile = TRUE;
|
|
}
|
|
|
|
/* See if the user already has a PWL. If not, next
|
|
* page is to enter and confirm a password. If there
|
|
* is a PWL and its password is non-blank, next page
|
|
* is simply to enter the password. If there's a PWL
|
|
* and its password is blank, next page is Finish.
|
|
*/
|
|
int idNextPage;
|
|
HANDLE hPWL = NULL;
|
|
HRESULT hres = ::GetUserPasswordCache(pwd->m_nlsUsername.QueryPch(),
|
|
szNULL, &hPWL, FALSE);
|
|
if (SUCCEEDED(hres)) {
|
|
::ClosePasswordCache(hPWL, TRUE);
|
|
pwd->m_idPrevPage = IDD_EnterUsername;
|
|
if (pwd->m_fCreatingProfile)
|
|
idNextPage = IDD_ChooseFoldersWiz;
|
|
else
|
|
idNextPage = (pwd->m_fGoMultiWizard) ? IDD_FinishGoMulti : IDD_FinishAddUser;
|
|
}
|
|
else if (hres == HRESULT_FROM_WIN32(IERR_IncorrectUsername)) {
|
|
idNextPage = IDD_EnterUserPassword;
|
|
}
|
|
else {
|
|
idNextPage = IDD_NewUserPassword;
|
|
}
|
|
GoToPage(hDlg, idNextPage);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
LimitCredentialLength(hDlg, IDC_USERNAME);
|
|
|
|
if (pwd->m_fGoMultiWizard) {
|
|
NLS_STR nlsText(MAX_RES_STR_LEN);
|
|
if (nlsText.QueryError() == ERROR_SUCCESS) {
|
|
nlsText.LoadString(IDS_ENTER_FIRST_USERNAME);
|
|
if (nlsText.QueryError() == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_MAIN_CAPTION, nlsText.QueryPch());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void PickUserSelected(HWND hwndLB, int iItem)
|
|
{
|
|
HWND hDlg = GetParent(hwndLB);
|
|
|
|
if (iItem == LB_ERR) {
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
}
|
|
else {
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
}
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK PickUserDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
int iItem = (int)::SendDlgItemMessage(hDlg, IDC_USERNAME, LB_GETCURSEL, 0, 0);
|
|
PickUserSelected((HWND)lParam, iItem);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
int iItem = (int)::SendDlgItemMessage(hDlg, IDC_USERNAME, LB_GETCURSEL, 0, 0);
|
|
if (iItem != LB_ERR) {
|
|
if (pwd->m_pUserToClone != NULL)
|
|
pwd->m_pUserToClone->Release();
|
|
pwd->m_pUserToClone = (IUser *)::SendDlgItemMessage(hDlg, IDC_USERNAME, LB_GETITEMDATA, iItem, 0);
|
|
if (pwd->m_pUserToClone != NULL)
|
|
pwd->m_pUserToClone->AddRef();
|
|
}
|
|
else {
|
|
MsgBox(hDlg, IDS_PICK_USERNAME, MB_OK | MB_ICONSTOP);
|
|
FailChangePage(hDlg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)(((LPPROPSHEETPAGE)lParam)->lParam);
|
|
FillUserList(GetDlgItem(hDlg, IDC_USERNAME), pwd->m_pDB, NULL,
|
|
TRUE, PickUserSelected);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
DestroyUserList(GetDlgItem(hDlg, IDC_USERNAME));
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if (LOWORD(wParam) == IDC_USERNAME && HIWORD(wParam) == LBN_SELCHANGE) {
|
|
int iItem = (int)::SendDlgItemMessage(hDlg, IDC_USERNAME, LB_GETCURSEL, 0, 0);
|
|
PickUserSelected((HWND)lParam, iItem);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK NewPasswordDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
int cchPassword = GetWindowTextLength(GetDlgItem(hDlg, IDC_PASSWORD));
|
|
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
GetControlText(hDlg, IDC_PASSWORD, &pwd->m_nlsUserPassword);
|
|
|
|
BOOL fConfirmedOK = FALSE;
|
|
int cchConfirm = GetWindowTextLength(GetDlgItem(hDlg, IDC_CONFIRM_PASSWORD));
|
|
if (cchConfirm == cchPassword) {
|
|
NLS_STR nlsConfirm(cchConfirm+1);
|
|
if (SUCCEEDED(GetControlText(hDlg, IDC_CONFIRM_PASSWORD, &nlsConfirm))) {
|
|
if (!nlsConfirm.strcmp(pwd->m_nlsUserPassword))
|
|
fConfirmedOK = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fConfirmedOK) {
|
|
MsgBox(hDlg, IDS_NO_MATCH, MB_OK | MB_ICONSTOP);
|
|
SetDlgItemText(hDlg, IDC_PASSWORD, szNULL);
|
|
SetDlgItemText(hDlg, IDC_CONFIRM_PASSWORD, szNULL);
|
|
SetErrorFocus(hDlg, IDC_PASSWORD);
|
|
FailChangePage(hDlg);
|
|
}
|
|
else {
|
|
pwd->m_idPrevPage = IDD_NewUserPassword;
|
|
UINT idNextPage;
|
|
if (pwd->m_fCreatingProfile)
|
|
idNextPage = IDD_ChooseFoldersWiz;
|
|
else
|
|
idNextPage = pwd->m_fGoMultiWizard ? IDD_FinishGoMulti : IDD_FinishAddUser;
|
|
GoToPage(hDlg, idNextPage);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
GoToPage(hDlg, IDD_EnterUsername);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
LimitCredentialLength(hDlg, IDC_PASSWORD);
|
|
LimitCredentialLength(hDlg, IDC_CONFIRM_PASSWORD);
|
|
|
|
if (pwd->m_fGoMultiWizard) {
|
|
NLS_STR nlsText(MAX_RES_STR_LEN);
|
|
if (nlsText.QueryError() == ERROR_SUCCESS) {
|
|
nlsText.LoadString(IDS_YOURNEWPASSWORD);
|
|
if (nlsText.QueryError() == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_MAIN_CAPTION, nlsText.QueryPch());
|
|
if (FAILED(pwd->m_hresRatings)) {
|
|
nlsText.LoadString(IDS_RATINGS_PW_COMMENT);
|
|
if (nlsText.QueryError() == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_RATINGS_PW_COMMENT, nlsText.QueryPch());
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
InsertControlText(hDlg, IDC_MAIN_CAPTION, &pwd->m_nlsUsername);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
const TCHAR c_szExplorerUSFKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders");
|
|
const TCHAR c_szExplorerSFKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
|
|
const struct FolderDescriptor {
|
|
UINT idsDirName; /* Resource ID for directory name */
|
|
LPCTSTR pszRegValue; /* Name of reg value to set path in */
|
|
LPCTSTR pszStaticName; /* Static name for ProfileReconciliation subkey */
|
|
LPCTSTR pszFiles; /* Spec for which files should roam */
|
|
DWORD dwAttribs; /* Desired attributes */
|
|
BOOL fSecondary : 1; /* TRUE if subsidiary to the Start Menu */
|
|
BOOL fDefaultInRoot : 1;/* TRUE if default is root of drive, not windir */
|
|
} aFolders[] = {
|
|
|
|
/* NOTE: Keep the entries in the following table in the same order as the
|
|
* corresponding FOLDER_XXXXXX bitflags in mslocusr.h.
|
|
*/
|
|
|
|
{ IDS_CSIDL_DESKTOP_L, "Desktop", "Desktop", "*.*", FILE_ATTRIBUTE_DIRECTORY, 0, 0 },
|
|
{ IDS_CSIDL_NETHOOD_L, "NetHood", "NetHood", "*.*", FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN, 0, 0 },
|
|
{ IDS_CSIDL_RECENT_L, "Recent", "Recent", "*.*", FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN, 0, 0 },
|
|
{ IDS_CSIDL_STARTMENU_L,"Start Menu","Start Menu","*.lnk,*.pif,*.url", FILE_ATTRIBUTE_DIRECTORY, 0, 0 },
|
|
{ IDS_CSIDL_PROGRAMS_L, "Programs", "Programs", "*.lnk,*.pif,*.url", FILE_ATTRIBUTE_DIRECTORY, 1, 0 },
|
|
{ IDS_CSIDL_STARTUP_L, "Startup", "Startup", "*.lnk,*.pif,*.url", FILE_ATTRIBUTE_DIRECTORY, 1, 0 },
|
|
{ IDS_CSIDL_FAVORITES_L,"Favorites", "Favorites", "*.*", FILE_ATTRIBUTE_DIRECTORY, 0, 0 },
|
|
{ IDS_CSIDL_CACHE_L, "Cache", "Cache", "", FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM, 0, 0 },
|
|
{ IDS_CSIDL_PERSONAL_L, "Personal", "Personal", "*.*", FILE_ATTRIBUTE_DIRECTORY, 0, 1 },
|
|
};
|
|
|
|
const struct FolderDescriptor fdChannels =
|
|
{ IDS_CSIDL_CHANNELS_L, NULL, "Channel Preservation Key", "*.*", FILE_ATTRIBUTE_DIRECTORY, 0, 0 };
|
|
|
|
void InitFolderCheckboxes(HWND hDlg, CWizData *pwd)
|
|
{
|
|
IUser *pUserToClone;
|
|
|
|
pwd->m_fdwOriginalPerUserFolders = 0;
|
|
|
|
if (pwd->m_pUserToClone != NULL) {
|
|
pUserToClone = pwd->m_pUserToClone;
|
|
pUserToClone->AddRef();
|
|
}
|
|
else {
|
|
pwd->m_pDB->GetSpecialUser(GSU_DEFAULT, &pUserToClone);
|
|
}
|
|
|
|
HKEY hkeyUser;
|
|
if (pUserToClone != NULL && SUCCEEDED(pUserToClone->LoadProfile(&hkeyUser))) {
|
|
HKEY hkeyProfRec, hkeyProfRec2;
|
|
if (RegOpenKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\ProfileReconciliation",
|
|
0, KEY_READ, &hkeyProfRec) != ERROR_SUCCESS)
|
|
hkeyProfRec = NULL;
|
|
if (RegOpenKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\SecondaryProfileReconciliation",
|
|
0, KEY_READ, &hkeyProfRec2) != ERROR_SUCCESS)
|
|
hkeyProfRec2 = NULL;
|
|
|
|
for (UINT iFolder = 0; iFolder < ARRAYSIZE(aFolders); iFolder++) {
|
|
HKEY hkeyTemp;
|
|
HKEY hkeyParent = aFolders[iFolder].fSecondary ? hkeyProfRec2 : hkeyProfRec;
|
|
|
|
if (hkeyParent != NULL &&
|
|
RegOpenKeyEx(hkeyParent,
|
|
aFolders[iFolder].pszStaticName,
|
|
0, KEY_READ, &hkeyTemp) == ERROR_SUCCESS) {
|
|
RegCloseKey(hkeyTemp);
|
|
pwd->m_fdwOriginalPerUserFolders |= 1 << iFolder;
|
|
}
|
|
/* else bit is already clear */
|
|
}
|
|
|
|
if (hkeyProfRec != NULL)
|
|
RegCloseKey(hkeyProfRec);
|
|
if (hkeyProfRec2 != NULL)
|
|
RegCloseKey(hkeyProfRec2);
|
|
|
|
pUserToClone->UnloadProfile(hkeyUser);
|
|
}
|
|
|
|
if (pUserToClone != NULL)
|
|
pUserToClone->Release();
|
|
|
|
CheckDlgButton(hDlg, IDC_CHECK_DESKTOP,
|
|
(pwd->m_fdwOriginalPerUserFolders &
|
|
(FOLDER_DESKTOP | FOLDER_NETHOOD | FOLDER_RECENT)) ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_CHECK_STARTMENU,
|
|
(pwd->m_fdwOriginalPerUserFolders &
|
|
(FOLDER_STARTMENU | FOLDER_PROGRAMS | FOLDER_STARTUP)) ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_CHECK_FAVORITES,
|
|
(pwd->m_fdwOriginalPerUserFolders & FOLDER_FAVORITES) ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_CHECK_CACHE,
|
|
(pwd->m_fdwOriginalPerUserFolders & FOLDER_CACHE) ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_CHECK_MYDOCS,
|
|
(pwd->m_fdwOriginalPerUserFolders & FOLDER_MYDOCS) ? 1 : 0);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK ChooseFoldersDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
InitFolderCheckboxes(hDlg, pwd);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
pwd->m_fdwCloneFromDefault = IsDlgButtonChecked(hDlg, IDC_RADIO_EMPTY) ? 0 : 0xffffffff;
|
|
pwd->m_fdwNewPerUserFolders = 0;
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_DESKTOP))
|
|
pwd->m_fdwNewPerUserFolders |= FOLDER_DESKTOP | FOLDER_NETHOOD | FOLDER_RECENT;
|
|
else
|
|
pwd->m_fdwNewPerUserFolders &= ~(FOLDER_DESKTOP | FOLDER_NETHOOD | FOLDER_RECENT);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_STARTMENU))
|
|
pwd->m_fdwNewPerUserFolders |= FOLDER_STARTMENU | FOLDER_PROGRAMS | FOLDER_STARTUP;
|
|
else
|
|
pwd->m_fdwNewPerUserFolders &= ~(FOLDER_STARTMENU | FOLDER_PROGRAMS | FOLDER_STARTUP);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_FAVORITES))
|
|
pwd->m_fdwNewPerUserFolders |= FOLDER_FAVORITES;
|
|
else
|
|
pwd->m_fdwNewPerUserFolders &= ~(FOLDER_FAVORITES);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_CACHE))
|
|
pwd->m_fdwNewPerUserFolders |= FOLDER_CACHE;
|
|
else
|
|
pwd->m_fdwNewPerUserFolders &= ~(FOLDER_CACHE);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_MYDOCS))
|
|
pwd->m_fdwNewPerUserFolders |= FOLDER_MYDOCS;
|
|
else
|
|
pwd->m_fdwNewPerUserFolders &= ~(FOLDER_MYDOCS);
|
|
|
|
pwd->m_idPrevPage = IDD_ChooseFoldersWiz;
|
|
GoToPage(hDlg, pwd->m_fGoMultiWizard ? IDD_FinishGoMulti : IDD_FinishAddUser);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
GoToPage(hDlg, pwd->m_idPrevPage);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
CheckRadioButton(hDlg, IDC_RADIO_COPY, IDC_RADIO_EMPTY, IDC_RADIO_COPY);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void GetWindowsRootPath(LPSTR pszBuffer, UINT cchBuffer)
|
|
{
|
|
GetWindowsDirectory(pszBuffer, cchBuffer);
|
|
|
|
LPSTR pszEnd = NULL;
|
|
if (*pszBuffer == '\\' && *(pszBuffer+1) == '\\') {
|
|
pszEnd = ::strchrf(pszBuffer+2, '\\');
|
|
if (pszEnd != NULL) {
|
|
pszEnd = ::strchrf(pszEnd+1, '\\');
|
|
if (pszEnd != NULL)
|
|
pszEnd++;
|
|
}
|
|
}
|
|
else {
|
|
LPSTR pszNext = CharNext(pszBuffer);
|
|
if (*pszNext == ':' && *(pszNext+1) == '\\')
|
|
pszEnd = pszNext + 2;
|
|
}
|
|
if (pszEnd != NULL)
|
|
*pszEnd = '\0';
|
|
else
|
|
AddBackslash(pszBuffer);
|
|
}
|
|
|
|
|
|
void AddProfRecKey(HKEY hkeyUser, HKEY hkeyProfRec, const FolderDescriptor *pFolder,
|
|
BOOL fCloneFromDefault, LPCSTR pszProfileDir)
|
|
{
|
|
TCHAR szDefaultPath[MAX_PATH];
|
|
|
|
if (pFolder->fDefaultInRoot)
|
|
GetWindowsRootPath(szDefaultPath, ARRAYSIZE(szDefaultPath));
|
|
else
|
|
::strcpyf(szDefaultPath, TEXT("*windir\\"));
|
|
|
|
LPTSTR pszEnd = szDefaultPath + ::strlenf(szDefaultPath);
|
|
LoadString(::hInstance, pFolder->idsDirName,
|
|
pszEnd, ARRAYSIZE(szDefaultPath) - (int)(pszEnd - szDefaultPath));
|
|
LPTSTR pszLastComponent = ::strrchrf(pszEnd, '\\');
|
|
if (pszLastComponent == NULL)
|
|
pszLastComponent = pszEnd;
|
|
else
|
|
pszLastComponent++;
|
|
|
|
HKEY hSubKey;
|
|
|
|
LONG err = RegCreateKeyEx(hkeyProfRec, pFolder->pszStaticName, 0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hSubKey, NULL);
|
|
if (err == ERROR_SUCCESS) {
|
|
err = RegSetValueEx(hSubKey, "CentralFile", 0, REG_SZ,
|
|
(LPBYTE)pszLastComponent, ::strlenf(pszLastComponent)+1);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "LocalFile", 0, REG_SZ, (LPBYTE)pszEnd,
|
|
::strlenf(pszEnd)+1);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "Name", 0, REG_SZ, (LPBYTE)pFolder->pszFiles,
|
|
::strlenf(pFolder->pszFiles) + 1);
|
|
|
|
if (fCloneFromDefault && err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "DefaultDir", 0, REG_SZ, (LPBYTE)szDefaultPath,
|
|
::strlenf(szDefaultPath) + 1);
|
|
|
|
DWORD dwOne = 1;
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "MustBeRelative", 0, REG_DWORD, (LPBYTE)&dwOne,
|
|
sizeof(dwOne));
|
|
if (fCloneFromDefault && err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "Default", 0, REG_DWORD, (LPBYTE)&dwOne,
|
|
sizeof(dwOne));
|
|
|
|
if (pFolder->pszRegValue != NULL) {
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "RegKey", 0, REG_SZ, (LPBYTE)c_szExplorerUSFKey,
|
|
::strlenf(c_szExplorerUSFKey) + 1);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hSubKey, "RegValue", 0, REG_SZ, (LPBYTE)pFolder->pszRegValue,
|
|
::strlenf(pFolder->pszRegValue) + 1);
|
|
}
|
|
|
|
if (err == ERROR_SUCCESS && pFolder->fSecondary) {
|
|
err = RegSetValueEx(hSubKey, "ParentKey", 0, REG_SZ, (LPBYTE)"Start Menu", 11);
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
/* And if we're not adding a clone-from-default profrec key, we know that
|
|
* no profile code is going to create the directory, so we'd better do it
|
|
* ourselves, and set the path in the registry.
|
|
*/
|
|
|
|
if (!fCloneFromDefault) {
|
|
NLS_STR nlsTemp(MAX_PATH);
|
|
if (nlsTemp.QueryError() == ERROR_SUCCESS) {
|
|
nlsTemp = pszProfileDir;
|
|
AddBackslash(nlsTemp);
|
|
nlsTemp.strcat(pszEnd);
|
|
|
|
HKEY hkeyExplorer;
|
|
if (RegOpenKeyEx(hkeyUser, c_szExplorerSFKey, 0,
|
|
KEY_READ | KEY_WRITE, &hkeyExplorer) == ERROR_SUCCESS) {
|
|
RegSetValueEx(hkeyExplorer, pFolder->pszRegValue,
|
|
0, REG_SZ, (LPBYTE)nlsTemp.QueryPch(),
|
|
nlsTemp.strlen()+1);
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
if (RegOpenKeyEx(hkeyUser, c_szExplorerUSFKey, 0,
|
|
KEY_READ | KEY_WRITE, &hkeyExplorer) == ERROR_SUCCESS) {
|
|
RegSetValueEx(hkeyExplorer, pFolder->pszRegValue,
|
|
0, REG_SZ, (LPBYTE)nlsTemp.QueryPch(),
|
|
nlsTemp.strlen()+1);
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
CreateDirectoryPath(nlsTemp.QueryPch());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* CWizData::PreInitProfile is called back by IUserDatabase::Install or
|
|
* ::AddUser after the new user's profile has been created but before
|
|
* directory reconciliation takes place. This is our chance to add
|
|
* roaming keys for any folders that we want to be per-user and initialized
|
|
* from the defaults, and remove roaming keys for other folders we know about.
|
|
*/
|
|
STDMETHODIMP CWizData::PreInitProfile(HKEY hkeyUser, LPCSTR pszProfileDir)
|
|
{
|
|
HKEY hkeyProfRec, hkeyProfRec2;
|
|
DWORD dwDisp;
|
|
if (RegCreateKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\ProfileReconciliation",
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hkeyProfRec, &dwDisp) != ERROR_SUCCESS)
|
|
hkeyProfRec = NULL;
|
|
if (RegCreateKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\SecondaryProfileReconciliation",
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hkeyProfRec2, &dwDisp) != ERROR_SUCCESS)
|
|
hkeyProfRec2 = NULL;
|
|
|
|
m_fChannelHack = FALSE;
|
|
|
|
DWORD fdwFlag = 1;
|
|
|
|
for (UINT iFolder = 0;
|
|
iFolder < ARRAYSIZE(aFolders);
|
|
iFolder++, fdwFlag <<= 1) {
|
|
|
|
BOOL fWasPerUser = (m_fdwOriginalPerUserFolders & fdwFlag);
|
|
BOOL fMakePerUser = (m_fdwNewPerUserFolders & fdwFlag);
|
|
BOOL fCloneFromDefault = (m_fdwCloneFromDefault & fdwFlag);
|
|
|
|
/* If the folder was shared and is staying that way, do nothing. */
|
|
if (!fWasPerUser && !fMakePerUser)
|
|
continue;
|
|
|
|
/* If the folder was per-user and is staying that way, do nothing,
|
|
* UNLESS we're creating a new profile and the user chose the start-
|
|
* out-empty option. In that case we want to make sure to kill the
|
|
* profrec keys until PostInitProfile.
|
|
*/
|
|
if (fWasPerUser && fMakePerUser && (!m_fCreatingProfile || fCloneFromDefault))
|
|
continue;
|
|
|
|
HKEY hkeyParent = aFolders[iFolder].fSecondary ? hkeyProfRec2 : hkeyProfRec;
|
|
|
|
/* If the user is making a folder per-user when it wasn't, and they
|
|
* want this folder cloned from the default, add a profrec key now.
|
|
*/
|
|
if (fMakePerUser && fCloneFromDefault) {
|
|
AddProfRecKey(hkeyUser, hkeyParent, &aFolders[iFolder], TRUE, pszProfileDir);
|
|
}
|
|
|
|
/* If the user is making a folder shared, or they want this per-user
|
|
* folder to start out empty, delete the profrec key now. In the
|
|
* latter case, we will add it for roaming purposes during
|
|
* PostInitProfile.
|
|
*/
|
|
if (!fMakePerUser || !fCloneFromDefault) {
|
|
|
|
RegDeleteKey(hkeyParent, aFolders[iFolder].pszStaticName);
|
|
|
|
/* If we're making a folder shared and we're not cloning the
|
|
* default profile, then the profile has a per-user directory
|
|
* path in it which we need to clear out.
|
|
*
|
|
* We know that we need to delete the value from User Shell Folders,
|
|
* and set the default path under Shell Folders.
|
|
*/
|
|
|
|
if (!fMakePerUser && m_pUserToClone != NULL) {
|
|
|
|
TCHAR szDefaultPath[MAX_PATH+1];
|
|
|
|
if (aFolders[iFolder].fDefaultInRoot) {
|
|
GetWindowsRootPath(szDefaultPath, ARRAYSIZE(szDefaultPath));
|
|
}
|
|
else {
|
|
GetWindowsDirectory(szDefaultPath, ARRAYSIZE(szDefaultPath));
|
|
AddBackslash(szDefaultPath);
|
|
}
|
|
LPTSTR pszEnd = szDefaultPath + ::strlenf(szDefaultPath);
|
|
|
|
LoadString(::hInstance, aFolders[iFolder].idsDirName,
|
|
pszEnd, ARRAYSIZE(szDefaultPath) - (int)(pszEnd - szDefaultPath));
|
|
|
|
HKEY hkeyExplorer;
|
|
|
|
if (RegOpenKeyEx(hkeyUser, c_szExplorerUSFKey, 0,
|
|
KEY_READ | KEY_WRITE, &hkeyExplorer) == ERROR_SUCCESS) {
|
|
if (aFolders[iFolder].fDefaultInRoot) {
|
|
RegSetValueEx(hkeyExplorer, aFolders[iFolder].pszRegValue,
|
|
0, REG_SZ, (LPBYTE)szDefaultPath,
|
|
::strlenf(szDefaultPath)+1);
|
|
}
|
|
else {
|
|
RegDeleteValue(hkeyExplorer, aFolders[iFolder].pszRegValue);
|
|
}
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyUser, c_szExplorerSFKey, 0,
|
|
KEY_READ | KEY_WRITE, &hkeyExplorer) == ERROR_SUCCESS) {
|
|
RegSetValueEx(hkeyExplorer, aFolders[iFolder].pszRegValue,
|
|
0, REG_SZ, (LPBYTE)szDefaultPath,
|
|
::strlenf(szDefaultPath)+1);
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Special code for start-out-empty folders: Some of them need to
|
|
* start out with certain crucial files, not totally empty.
|
|
*/
|
|
|
|
if (fMakePerUser &&
|
|
(!fWasPerUser || m_fCreatingProfile) &&
|
|
!fCloneFromDefault) {
|
|
|
|
/* Special hack for channels: If the user wants Favorites to be per-user,
|
|
* but chooses to start it out empty, they get no channels either, because
|
|
* Channels is a subdirectory of Favorites. So, for that case only,
|
|
* we force in a clone-from-default profrec key for Channels, which we'll
|
|
* delete in PostInit.
|
|
*/
|
|
|
|
if (fdwFlag == FOLDER_FAVORITES) {
|
|
AddProfRecKey(hkeyUser, hkeyProfRec, &fdChannels, TRUE, pszProfileDir);
|
|
m_fChannelHack = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hkeyProfRec != NULL)
|
|
RegCloseKey(hkeyProfRec);
|
|
if (hkeyProfRec2 != NULL)
|
|
RegCloseKey(hkeyProfRec2);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* CWizData::PostInitProfile is called by IUserDatabase::Install or ::AddUser
|
|
* after the user's folders have all been created and initialized. Here we
|
|
* add profrec keys for any folders which we want to be per-user but don't
|
|
* want initialized from the default.
|
|
*/
|
|
STDMETHODIMP CWizData::PostInitProfile(HKEY hkeyUser, LPCSTR pszProfileDir)
|
|
{
|
|
HKEY hkeyProfRec, hkeyProfRec2;
|
|
DWORD dwDisp;
|
|
if (RegCreateKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\ProfileReconciliation",
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hkeyProfRec, &dwDisp) != ERROR_SUCCESS)
|
|
hkeyProfRec = NULL;
|
|
if (RegCreateKeyEx(hkeyUser, "Software\\Microsoft\\Windows\\CurrentVersion\\SecondaryProfileReconciliation",
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hkeyProfRec2, &dwDisp) != ERROR_SUCCESS)
|
|
hkeyProfRec2 = NULL;
|
|
|
|
DWORD fdwFlag = 1;
|
|
for (UINT iFolder = 0;
|
|
iFolder < ARRAYSIZE(aFolders);
|
|
iFolder++, fdwFlag <<= 1) {
|
|
|
|
HKEY hkeyParent = aFolders[iFolder].fSecondary ? hkeyProfRec2 : hkeyProfRec;
|
|
|
|
if (m_fdwNewPerUserFolders & fdwFlag) {
|
|
/* If the user is making a folder per-user when it wasn't or making a
|
|
* folder per-user in a new profile, and they want this folder to start
|
|
* out empty, add a profrec key now.
|
|
*/
|
|
if ((!(m_fdwOriginalPerUserFolders & fdwFlag) || m_fCreatingProfile) &&
|
|
!(m_fdwCloneFromDefault & fdwFlag)) {
|
|
AddProfRecKey(hkeyUser, hkeyParent, &aFolders[iFolder], FALSE, pszProfileDir);
|
|
}
|
|
|
|
/* If the folder is per-user and is supposed to have special
|
|
* attributes, make sure it has them.
|
|
*/
|
|
if (aFolders[iFolder].dwAttribs != FILE_ATTRIBUTE_DIRECTORY) {
|
|
RegEntry re(aFolders[iFolder].pszStaticName, hkeyParent);
|
|
NLS_STR nlsTemp(MAX_PATH);
|
|
if (re.GetError() == ERROR_SUCCESS && nlsTemp.QueryError() == ERROR_SUCCESS) {
|
|
GetSetRegistryPath(hkeyUser, re, &nlsTemp, FALSE);
|
|
if (nlsTemp.strlen()) {
|
|
::SetFileAttributes(nlsTemp.QueryPch(), aFolders[iFolder].dwAttribs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we added a hack for channels, undo that hack now that we're done
|
|
* initializing the profile.
|
|
*/
|
|
if (m_fChannelHack)
|
|
RegDeleteKey(hkeyProfRec, fdChannels.pszStaticName);
|
|
|
|
if (hkeyProfRec != NULL)
|
|
RegCloseKey(hkeyProfRec);
|
|
if (hkeyProfRec2 != NULL)
|
|
RegCloseKey(hkeyProfRec2);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* Following is actually for the CPL version of the choose-folders dialog */
|
|
HRESULT ChooseFoldersProgressFunc(LPARAM lParam)
|
|
{
|
|
CWizData *pwd = (CWizData *)lParam;
|
|
HKEY hkeyUser;
|
|
|
|
if (pwd->m_pUserToClone != NULL &&
|
|
SUCCEEDED(pwd->m_pUserToClone->LoadProfile(&hkeyUser))) {
|
|
|
|
TCHAR szProfileDir[MAX_PATH];
|
|
DWORD cbBuffer = sizeof(szProfileDir);
|
|
pwd->m_pUserToClone->GetProfileDirectory(szProfileDir, &cbBuffer);
|
|
|
|
pwd->PreInitProfile(hkeyUser, szProfileDir);
|
|
|
|
NLS_STR nlsPath(szProfileDir);
|
|
AddBackslash(nlsPath);
|
|
|
|
DWORD fdwFlag = 1;
|
|
for (UINT iFolder = 0;
|
|
iFolder < ARRAYSIZE(aFolders);
|
|
iFolder++, fdwFlag <<= 1) {
|
|
|
|
/* Do reconciliation if we want to per-user-ize a folder that
|
|
* wasn't per-user before and we want to clone it from default.
|
|
*/
|
|
if (!(pwd->m_fdwOriginalPerUserFolders & fdwFlag) &&
|
|
(pwd->m_fdwNewPerUserFolders & fdwFlag) &&
|
|
(pwd->m_fdwCloneFromDefault & fdwFlag)) {
|
|
DefaultReconcileKey(hkeyUser, nlsPath,
|
|
aFolders[iFolder].pszStaticName,
|
|
aFolders[iFolder].fSecondary);
|
|
}
|
|
}
|
|
|
|
/* Process the initialization hack for Channels, if it exists. */
|
|
if (pwd->m_fChannelHack)
|
|
DefaultReconcileKey(hkeyUser, nlsPath, fdChannels.pszStaticName,
|
|
fdChannels.fSecondary);
|
|
|
|
pwd->PostInitProfile(hkeyUser, szProfileDir);
|
|
|
|
pwd->m_pUserToClone->UnloadProfile(hkeyUser);
|
|
|
|
SHFlushSFCache();
|
|
|
|
return S_OK;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
void FinishChooseFolders(HWND hDlg, CWizData *pwd)
|
|
{
|
|
if (SUCCEEDED(CallWithinProgressDialog(hDlg, IDD_CreateProgress,
|
|
ChooseFoldersProgressFunc, (LPARAM)pwd)))
|
|
EndDialog(hDlg, TRUE);
|
|
}
|
|
|
|
|
|
HRESULT InstallProgressFunc(LPARAM lParam)
|
|
{
|
|
CWizData *pwd = (CWizData *)lParam;
|
|
|
|
return pwd->m_pDB->Install(pwd->m_nlsUsername.QueryPch(),
|
|
pwd->m_nlsUserPassword.QueryPch(),
|
|
pwd->m_nlsSupervisorPassword.QueryPch(),
|
|
pwd);
|
|
}
|
|
|
|
|
|
BOOL FinishGoMulti(HWND hDlg, CWizData *pwd)
|
|
{
|
|
DWORD dwExitCode = 0xffffffff; /* not a valid EWX_ value */
|
|
|
|
/* If user profiles aren't enabled, enable them. Using them requires
|
|
* logging off.
|
|
*/
|
|
if (!UseUserProfiles()) {
|
|
dwExitCode = EWX_LOGOFF;
|
|
EnableProfiles();
|
|
}
|
|
|
|
/* If there is no primary logon provider, install our logon dialog as
|
|
* the primary. Using this requires rebooting the system.
|
|
*/
|
|
if (InstallLogonDialog()) {
|
|
dwExitCode = EWX_REBOOT;
|
|
}
|
|
|
|
pwd->m_nlsUserPassword.strupr();
|
|
HRESULT hres = CallWithinProgressDialog(hDlg, IDD_CreateProgress,
|
|
InstallProgressFunc, (LPARAM)pwd);
|
|
if (SUCCEEDED(hres)) {
|
|
/* Set the new username as the default one to log on as. */
|
|
HKEY hkeyLogon;
|
|
if (OpenLogonKey(&hkeyLogon) == ERROR_SUCCESS) {
|
|
pwd->m_nlsUsername.ToOEM();
|
|
RegSetValueEx(hkeyLogon, ::szUsername, 0, REG_SZ,
|
|
(LPBYTE)pwd->m_nlsUsername.QueryPch(),
|
|
pwd->m_nlsUsername.strlen() + 1);
|
|
pwd->m_nlsUsername.ToAnsi();
|
|
RegCloseKey(hkeyLogon);
|
|
}
|
|
if ((dwExitCode != 0xffffffff) &&
|
|
MsgBox(hDlg, IDS_GO_MULTI_RESTART, MB_YESNO | MB_ICONQUESTION) == IDYES) {
|
|
::ExitWindowsEx(dwExitCode, 0);
|
|
::ExitProcess(0);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
ReportUserError(hDlg, hres);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
HRESULT AddUserProgressFunc(LPARAM lParam)
|
|
{
|
|
CWizData *pwd = (CWizData *)lParam;
|
|
|
|
return pwd->m_pDB->AddUser(pwd->m_nlsUsername.QueryPch(),
|
|
pwd->m_pUserToClone, pwd, &pwd->m_pNewUser);
|
|
}
|
|
|
|
|
|
BOOL FinishAddUser(HWND hDlg, CWizData *pwd)
|
|
{
|
|
pwd->m_nlsUserPassword.strupr();
|
|
|
|
pwd->m_pNewUser = NULL;
|
|
HRESULT hres = CallWithinProgressDialog(hDlg, IDD_CreateProgress,
|
|
AddUserProgressFunc, (LPARAM)pwd);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = pwd->m_pNewUser->ChangePassword(szNULL, pwd->m_nlsUserPassword.QueryPch());
|
|
pwd->m_pNewUser->Release();
|
|
pwd->m_pNewUser = NULL;
|
|
}
|
|
else {
|
|
ReportUserError(hDlg, hres);
|
|
}
|
|
|
|
return SUCCEEDED(hres);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK FinishDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
BOOL fOK = pwd->m_fGoMultiWizard ? FinishGoMulti(hDlg, pwd) : FinishAddUser(hDlg, pwd);
|
|
if (!fOK)
|
|
FailChangePage(hDlg);
|
|
else
|
|
return FALSE; /* destroy wizard */
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
{
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
GoToPage(hDlg, pwd->m_idPrevPage);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
InitWizDataPtr(hDlg, lParam);
|
|
CWizData *pwd = (CWizData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
if (!pwd->m_fGoMultiWizard) {
|
|
InsertControlText(hDlg, IDC_MAIN_CAPTION, &pwd->m_nlsUsername);
|
|
InsertControlText(hDlg, IDC_MAIN_CAPTION2, &pwd->m_nlsUsername);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLUDatabase::InstallWizard(HWND hwndParent)
|
|
{
|
|
#if 0
|
|
if (UseUserProfiles()) {
|
|
MsgBox(hwndParent, IDS_PROFILES_ALREADY_ENABLED, MB_OK | MB_ICONINFORMATION);
|
|
return E_FAIL;
|
|
}
|
|
#endif
|
|
|
|
if (ProfileUIRestricted()) {
|
|
ReportRestrictionError(hwndParent);
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
CWizData wd;
|
|
wd.m_hresRatings = VerifySupervisorPassword(szNULL);
|
|
wd.m_fGoMultiWizard = TRUE;
|
|
wd.m_pDB = this;
|
|
AddRef(); /* just in case */
|
|
wd.m_pUserToClone = NULL;
|
|
|
|
LPPROPSHEETHEADER ppsh;
|
|
|
|
// Allocate the property sheet header
|
|
//
|
|
if ((ppsh = (LPPROPSHEETHEADER)LocalAlloc(LMEM_FIXED, sizeof(PROPSHEETHEADER)+
|
|
(MAX_WIZ_PAGES * sizeof(HPROPSHEETPAGE)))) != NULL)
|
|
{
|
|
ppsh->dwSize = sizeof(*ppsh);
|
|
ppsh->dwFlags = PSH_WIZARD;
|
|
ppsh->hwndParent = hwndParent;
|
|
ppsh->hInstance = ::hInstance;
|
|
ppsh->pszCaption = NULL;
|
|
ppsh->nPages = 0;
|
|
ppsh->nStartPage = 0;
|
|
ppsh->phpage = (HPROPSHEETPAGE *)(ppsh+1);
|
|
|
|
/* Add the pages for the wizard. Note that we have two pages to
|
|
* prompt for the user's account password -- one to enter, the other
|
|
* to enter and confirm. The code in EnterUsernameDlgProc jumps to
|
|
* the right password page depending on whether the user has a PWL.
|
|
* The code in NewPasswordDlgProc knows to jump ahead to the finish
|
|
* page.
|
|
*
|
|
* If you add more pages here, be sure to update the code as necessary
|
|
* so the sequence is correct.
|
|
*/
|
|
AddPage(ppsh, IDD_EnableProfilesIntro, IntroDlgProc, &wd);
|
|
if (wd.m_hresRatings == S_FALSE)
|
|
AddPage(ppsh, IDD_EnterCAPassword, EnterCAPWDlgProc, &wd);
|
|
AddPage(ppsh, IDD_EnterUsername, EnterUsernameDlgProc, &wd);
|
|
AddPage(ppsh, IDD_NewUserPassword, NewPasswordDlgProc, &wd);
|
|
AddPage(ppsh, IDD_EnterUserPassword, EnterUserPWDlgProc, &wd);
|
|
AddPage(ppsh, IDD_ChooseFoldersWiz, ChooseFoldersDlgProc, &wd);
|
|
AddPage(ppsh, IDD_FinishGoMulti, FinishDlgProc, &wd);
|
|
|
|
PropertySheet(ppsh);
|
|
|
|
LocalFree((HLOCAL)ppsh);
|
|
}
|
|
|
|
Release(); /* undo above AddRef() */
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT DoAddUserWizard(HWND hwndParent, IUserDatabase *pDB,
|
|
BOOL fPickUserPage, IUser *pUserToClone)
|
|
{
|
|
CWizData wd;
|
|
wd.m_hresRatings = VerifySupervisorPassword(szNULL);
|
|
wd.m_fGoMultiWizard = FALSE;
|
|
wd.m_pDB = pDB;
|
|
pDB->AddRef(); /* just in case */
|
|
wd.m_pUserToClone = pUserToClone;
|
|
if (wd.m_pUserToClone != NULL)
|
|
wd.m_pUserToClone->AddRef();
|
|
|
|
LPPROPSHEETHEADER ppsh;
|
|
|
|
// Allocate the property sheet header
|
|
//
|
|
if ((ppsh = (LPPROPSHEETHEADER)LocalAlloc(LMEM_FIXED, sizeof(PROPSHEETHEADER)+
|
|
(MAX_WIZ_PAGES * sizeof(HPROPSHEETPAGE)))) != NULL)
|
|
{
|
|
ppsh->dwSize = sizeof(*ppsh);
|
|
ppsh->dwFlags = PSH_WIZARD;
|
|
ppsh->hwndParent = hwndParent;
|
|
ppsh->hInstance = ::hInstance;
|
|
ppsh->pszCaption = NULL;
|
|
ppsh->nPages = 0;
|
|
ppsh->nStartPage = 0;
|
|
ppsh->phpage = (HPROPSHEETPAGE *)(ppsh+1);
|
|
|
|
AddPage(ppsh, IDD_AddUserIntro, IntroDlgProc, &wd);
|
|
|
|
if (IsCurrentUserSupervisor(pDB) != S_OK)
|
|
{
|
|
AddPage(ppsh, IDD_EnterCAPassword, EnterCAPWDlgProc, &wd);
|
|
}
|
|
|
|
if (fPickUserPage)
|
|
AddPage(ppsh, IDD_PickUser, PickUserDlgProc, &wd);
|
|
AddPage(ppsh, IDD_EnterUsername, EnterUsernameDlgProc, &wd);
|
|
AddPage(ppsh, IDD_NewUserPassword, NewPasswordDlgProc, &wd);
|
|
AddPage(ppsh, IDD_EnterUserPassword, EnterUserPWDlgProc, &wd);
|
|
AddPage(ppsh, IDD_ChooseFoldersWiz, ChooseFoldersDlgProc, &wd);
|
|
AddPage(ppsh, IDD_FinishAddUser, FinishDlgProc, &wd);
|
|
|
|
PropertySheet(ppsh);
|
|
|
|
LocalFree((HLOCAL)ppsh);
|
|
}
|
|
|
|
pDB->Release(); /* undo above AddRef() */
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLUDatabase::AddUserWizard(HWND hwndParent)
|
|
{
|
|
if (ProfileUIRestricted()) {
|
|
ReportRestrictionError(hwndParent);
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
return DoAddUserWizard(hwndParent, this, TRUE, NULL);
|
|
}
|
|
|
|
|
|
extern "C" void InstallWizard(HWND hwndParent, HINSTANCE hinstEXE, LPSTR pszCmdLine, int nCmdShow)
|
|
{
|
|
IUserDatabase *pDB;
|
|
if (SUCCEEDED(::CreateUserDatabase(IID_IUserDatabase, (void **)&pDB))) {
|
|
pDB->InstallWizard(hwndParent);
|
|
pDB->Release();
|
|
}
|
|
}
|
|
|
|
|
|
extern "C" void AddUserWizard(HWND hwndParent, HINSTANCE hinstEXE, LPSTR pszCmdLine, int nCmdShow)
|
|
{
|
|
IUserDatabase *pDB;
|
|
if (SUCCEEDED(::CreateUserDatabase(IID_IUserDatabase, (void **)&pDB))) {
|
|
pDB->AddUserWizard(hwndParent);
|
|
pDB->Release();
|
|
}
|
|
}
|
|
|
|
|
|
struct ProgressDlgData
|
|
{
|
|
PFNPROGRESS pfn;
|
|
LPARAM lParam;
|
|
HRESULT hres;
|
|
};
|
|
|
|
|
|
void CallProgressFunc(HWND hDlg)
|
|
{
|
|
ProgressDlgData *ppdd = (ProgressDlgData *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
ppdd->hres = ppdd->pfn(ppdd->lParam);
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
}
|
|
|
|
|
|
const UINT WM_CALL_FUNC = WM_USER + 100;
|
|
|
|
INT_PTR CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
|
|
|
|
/* Defer function call to a posted message so the dialog manager
|
|
* will show our dialog.
|
|
*
|
|
* If PostMessage fails, at least still call the function anyway.
|
|
*/
|
|
if (!PostMessage(hDlg, WM_CALL_FUNC, 0, 0)) {
|
|
CallProgressFunc(hDlg);
|
|
}
|
|
}
|
|
|
|
return TRUE; /* we didn't set the focus */
|
|
|
|
case WM_CALL_FUNC:
|
|
CallProgressFunc(hDlg);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HRESULT CallWithinProgressDialog(HWND hwndOwner, UINT idResource, PFNPROGRESS pfn,
|
|
LPARAM lParam)
|
|
{
|
|
ProgressDlgData pdd = { pfn, lParam, E_FAIL };
|
|
|
|
DialogBoxParam(::hInstance, MAKEINTRESOURCE(idResource), hwndOwner,
|
|
ProgressDlgProc, (LPARAM)&pdd);
|
|
|
|
return pdd.hres;
|
|
}
|
|
|
|
|
|
BOOL ProfileUIRestricted(void)
|
|
{
|
|
RegEntry rePolicy("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
|
|
|
|
if (rePolicy.GetError() == ERROR_SUCCESS) {
|
|
if (rePolicy.GetNumber("NoProfilePage") != 0)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void ReportRestrictionError(HWND hwndOwner)
|
|
{
|
|
MsgBox(hwndOwner, IDS_PROFILE_POLICY, MB_OK | MB_ICONSTOP);
|
|
}
|