619 lines
17 KiB
C++
619 lines
17 KiB
C++
|
#include "mslocusr.h"
|
||
|
#include "msluglob.h"
|
||
|
|
||
|
#include "resource.h"
|
||
|
#include <winnetwk.h>
|
||
|
#include <netspi.h>
|
||
|
|
||
|
#pragma data_seg(".shared")
|
||
|
char szDefaultLogonUsername[MAX_PATH] = "";
|
||
|
char szDefaultLogonPassword[MAX_PATH] = "";
|
||
|
BOOL fDoDefaultLogon = FALSE;
|
||
|
#pragma data_seg()
|
||
|
|
||
|
|
||
|
struct LogonData
|
||
|
{
|
||
|
LPLOGONINFO lpAuthentInfo;
|
||
|
DWORD dwFlags;
|
||
|
IUser **ppOut;
|
||
|
HBITMAP hbmTransparent;
|
||
|
};
|
||
|
|
||
|
|
||
|
void ObfuscateString(LPSTR pszBuffer)
|
||
|
{
|
||
|
DWORD dwMask = 0xa95e633b; /* nice random collection of bits */
|
||
|
|
||
|
unsigned char ch;
|
||
|
do {
|
||
|
ch = *pszBuffer;
|
||
|
|
||
|
*(pszBuffer++) = ch ^ (unsigned char)(dwMask & 0xff);
|
||
|
dwMask = (dwMask >> 8) | (dwMask << 24);
|
||
|
} while (ch);
|
||
|
}
|
||
|
|
||
|
|
||
|
void DeObfuscateString(LPSTR pszBuffer)
|
||
|
{
|
||
|
DWORD dwMask = 0xa95e633b; /* nice random collection of bits */
|
||
|
|
||
|
unsigned char ch;
|
||
|
do {
|
||
|
ch = *pszBuffer ^ (unsigned char)(dwMask & 0xff);
|
||
|
|
||
|
*(pszBuffer++) = ch;
|
||
|
dwMask = (dwMask >> 8) | (dwMask << 24);
|
||
|
} while (ch);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CacheLogonCredentials(LPCSTR pszUsername, LPCSTR pszPassword)
|
||
|
{
|
||
|
lstrcpy(szDefaultLogonUsername, pszUsername);
|
||
|
lstrcpy(szDefaultLogonPassword, pszPassword);
|
||
|
fDoDefaultLogon = TRUE;
|
||
|
|
||
|
ObfuscateString(szDefaultLogonUsername);
|
||
|
ObfuscateString(szDefaultLogonPassword);
|
||
|
}
|
||
|
|
||
|
|
||
|
SPIENTRY NPGetCaps(
|
||
|
DWORD nIndex
|
||
|
)
|
||
|
{
|
||
|
switch (nIndex) {
|
||
|
case WNNC_SPEC_VERSION:
|
||
|
return 0x00040001; /* spec version 4.1 */
|
||
|
|
||
|
case WNNC_NET_TYPE:
|
||
|
return WNNC_NET_MSNET;
|
||
|
|
||
|
case WNNC_DRIVER_VERSION:
|
||
|
return 0x00010000; /* driver version 1.0 */
|
||
|
|
||
|
case WNNC_USER:
|
||
|
return
|
||
|
// WNNC_USR_GETUSER |
|
||
|
0;
|
||
|
|
||
|
case WNNC_CONNECTION:
|
||
|
return
|
||
|
0;
|
||
|
|
||
|
case WNNC_DIALOG:
|
||
|
return
|
||
|
0;
|
||
|
|
||
|
case WNNC_ENUMERATION:
|
||
|
return
|
||
|
0;
|
||
|
|
||
|
case WNNC_START:
|
||
|
return 0x1; /* started */
|
||
|
|
||
|
case WNNC_RESOURCE:
|
||
|
return
|
||
|
0;
|
||
|
|
||
|
case WNNC_AUTHENTICATION:
|
||
|
return
|
||
|
WNNC_AUTH_LOGON |
|
||
|
WNNC_AUTH_LOGOFF |
|
||
|
// WNNC_AUTH_GETHOMEDIRECTORY |
|
||
|
// WNNC_AUTH_GETPOLICYPATH |
|
||
|
0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// FEATURE not multimonitor friendly
|
||
|
|
||
|
VOID PlaceDialog(HWND hDlg, BOOL fTopThird)
|
||
|
{
|
||
|
RECT rc;
|
||
|
int dyScreen = GetSystemMetrics(SM_CYSCREEN);
|
||
|
int yDialog;
|
||
|
|
||
|
GetWindowRect(hDlg,&rc);
|
||
|
|
||
|
if (fTopThird)
|
||
|
yDialog = (dyScreen / 3) - ((rc.bottom-rc.top) / 2);
|
||
|
else
|
||
|
yDialog = (dyScreen - (rc.bottom - rc.top)) / 2;
|
||
|
|
||
|
SetWindowPos(hDlg,NULL,
|
||
|
(GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2,
|
||
|
yDialog, 0, 0, SWP_NOSIZE);
|
||
|
}
|
||
|
|
||
|
|
||
|
void UserSelected(HWND hwndLB, int iItem)
|
||
|
{
|
||
|
BOOL fNeedPassword;
|
||
|
BOOL fEnableOK;
|
||
|
|
||
|
if (iItem == LB_ERR) {
|
||
|
fNeedPassword = FALSE;
|
||
|
fEnableOK = FALSE;
|
||
|
}
|
||
|
else {
|
||
|
IUser *pUser = (IUser *)::SendMessage(hwndLB, LB_GETITEMDATA, iItem, 0);
|
||
|
fNeedPassword = FAILED(pUser->Authenticate(""));
|
||
|
fEnableOK = TRUE;
|
||
|
}
|
||
|
HWND hDlg = GetParent(hwndLB);
|
||
|
EnableWindow(GetDlgItem(hDlg, IDC_PASSWORD_LABEL), fNeedPassword);
|
||
|
EnableWindow(GetDlgItem(hDlg, IDC_PASSWORD), fNeedPassword);
|
||
|
EnableWindow(GetDlgItem(hDlg, IDOK), fEnableOK);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT FillUserList(HWND hwndLB, IUserDatabase *pDB, LPCSTR pszDefaultSelection,
|
||
|
BOOL fIncludeGuest, PFNSELNOTIFY pfnSelNotify)
|
||
|
{
|
||
|
IEnumUnknown *pEnum;
|
||
|
BOOL fSelectionSet = FALSE;
|
||
|
|
||
|
if (fIncludeGuest) {
|
||
|
NLS_STR nlsTemp(MAX_RES_STR_LEN);
|
||
|
if (nlsTemp.LoadString(IDS_GUEST_USERNAME) == ERROR_SUCCESS) {
|
||
|
UINT iItem = (UINT)::SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)nlsTemp.QueryPch());
|
||
|
if (iItem != LB_ERR && iItem != LB_ERRSPACE) {
|
||
|
::SendMessage(hwndLB, LB_SETITEMDATA, iItem, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT hres = pDB->EnumUsers(&pEnum);
|
||
|
if (SUCCEEDED(hres)) {
|
||
|
IUnknown *pUnk;
|
||
|
while (pEnum->Next(1, &pUnk, NULL) == S_OK) {
|
||
|
IUser *pUser;
|
||
|
if (SUCCEEDED(pUnk->QueryInterface(IID_IUser, (void **)&pUser))) {
|
||
|
char szBuf[cchMaxUsername+1];
|
||
|
DWORD cbBuffer = sizeof(szBuf);
|
||
|
|
||
|
if (SUCCEEDED(pUser->GetName(szBuf, &cbBuffer))) {
|
||
|
UINT iItem = (UINT)::SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)szBuf);
|
||
|
if (iItem != LB_ERR && iItem != LB_ERRSPACE) {
|
||
|
if (::SendMessage(hwndLB, LB_SETITEMDATA, iItem, (LPARAM)pUser) == LB_ERR)
|
||
|
::SendMessage(hwndLB, LB_SETITEMDATA, iItem, 0);
|
||
|
if (!fSelectionSet) {
|
||
|
if (pszDefaultSelection != NULL && !::stricmpf(szBuf, pszDefaultSelection)) {
|
||
|
fSelectionSet = TRUE;
|
||
|
::SendMessage(hwndLB, LB_SETCURSEL, iItem, 0);
|
||
|
if (pfnSelNotify != NULL)
|
||
|
(*pfnSelNotify)(hwndLB, iItem);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/* Note that pUser is not Release()d here, since the
|
||
|
* listbox has a pointer to it.
|
||
|
*/
|
||
|
}
|
||
|
pUnk->Release();
|
||
|
}
|
||
|
|
||
|
if (!fSelectionSet) {
|
||
|
if (pfnSelNotify)
|
||
|
(*pfnSelNotify)(hwndLB, LB_ERR);
|
||
|
}
|
||
|
else {
|
||
|
/* If we select the default item above, then insert more names
|
||
|
* above it, the focus rect and the selection will be different,
|
||
|
* which is confusing if the user tabs to the listbox. Work
|
||
|
* around this by setting the caret index manually.
|
||
|
*/
|
||
|
LRESULT iItem = ::SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
|
||
|
if (iItem != LB_ERR)
|
||
|
::SendMessage(hwndLB, LB_SETCURSEL, iItem, 0);
|
||
|
}
|
||
|
|
||
|
pEnum->Release();
|
||
|
}
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
return hres;
|
||
|
|
||
|
return fSelectionSet ? NOERROR : S_FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL IsMemphis(void)
|
||
|
{
|
||
|
OSVERSIONINFOA osvi;
|
||
|
|
||
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||
|
GetVersionExA(&osvi);
|
||
|
|
||
|
return (VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId &&
|
||
|
(osvi.dwMajorVersion > 4 ||
|
||
|
(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion >= 10)));
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD InitLogonDialog(HWND hwndDialog, LogonData *pld)
|
||
|
{
|
||
|
DWORD err = WN_NO_NETWORK;
|
||
|
BOOL fSelectionSet = FALSE;
|
||
|
|
||
|
::SetWindowLongPtr(hwndDialog, DWLP_USER, (LONG_PTR)pld);
|
||
|
|
||
|
PlaceDialog(hwndDialog, FALSE);
|
||
|
|
||
|
int idBitmap;
|
||
|
DWORD dwFlags;
|
||
|
|
||
|
if (IsMemphis())
|
||
|
idBitmap = IDB_IMAGE_WIN98_LOGON;
|
||
|
else
|
||
|
idBitmap = IDB_IMAGE_LOGON;
|
||
|
|
||
|
/* The bitmap we show at the top of the logon dialog has black text on a
|
||
|
* transparent background. If the dialog background is very dark, the
|
||
|
* text will be unreadable. In that case we use a static bitmap with
|
||
|
* a white background. For more common background colors, though, we use
|
||
|
* LoadImage to load a transparent image and replace the bitmap in the
|
||
|
* dialog.
|
||
|
*
|
||
|
* CODEWORK: Could try a variant of COLORISLIGHT macro from shell32,
|
||
|
* defview.cpp; it seems pretty aggressive about declaring blues in
|
||
|
* particular as "dark". Maybe we could have the alternate bitmap be
|
||
|
* 3D-mapped as well, but have white text and maybe a white box around
|
||
|
* the Windows flag, then we could always be transparent and just choose
|
||
|
* one or the other at an arbitrary cutoff point.
|
||
|
*/
|
||
|
DWORD clrBtnFace = GetSysColor(COLOR_3DFACE);
|
||
|
if ((LOBYTE(clrBtnFace) >= 128) ||
|
||
|
(LOBYTE(clrBtnFace >> 8) >= 128) ||
|
||
|
(LOBYTE(clrBtnFace >> 16) >= 128)) {
|
||
|
|
||
|
dwFlags = LR_LOADMAP3DCOLORS; /* we'll use a transparent bitmap */
|
||
|
}
|
||
|
else {
|
||
|
idBitmap++; /* advance to static bitmap ID */
|
||
|
dwFlags = LR_DEFAULTCOLOR;
|
||
|
}
|
||
|
|
||
|
pld->hbmTransparent = (HBITMAP)LoadImage(::hInstance,
|
||
|
MAKEINTRESOURCE(idBitmap),
|
||
|
IMAGE_BITMAP, 0, 0,
|
||
|
dwFlags);
|
||
|
if (pld->hbmTransparent != NULL) {
|
||
|
HBITMAP hbmOld = (HBITMAP)SendDlgItemMessage(hwndDialog,
|
||
|
IDC_MAIN_CAPTION,
|
||
|
STM_SETIMAGE,
|
||
|
(WPARAM)IMAGE_BITMAP,
|
||
|
(LPARAM)pld->hbmTransparent);
|
||
|
/* If we set the new bitmap into the control, we got the old one
|
||
|
* back. Delete the old one. We will also have to delete the
|
||
|
* new one when the dialog is dismissed.
|
||
|
*/
|
||
|
if (hbmOld != NULL)
|
||
|
DeleteObject(hbmOld);
|
||
|
}
|
||
|
|
||
|
IUserDatabase *pDB;
|
||
|
|
||
|
if (SUCCEEDED(::CreateUserDatabase(IID_IUserDatabase, (void **)&pDB))) {
|
||
|
HRESULT hres = FillUserList(GetDlgItem(hwndDialog, IDC_USERNAME),
|
||
|
pDB, pld->lpAuthentInfo ? pld->lpAuthentInfo->lpUsername : NULL,
|
||
|
FALSE, UserSelected);
|
||
|
|
||
|
if (SUCCEEDED(hres)) {
|
||
|
err = ERROR_SUCCESS;
|
||
|
|
||
|
::SetFocus(::GetDlgItem(hwndDialog, hres == NOERROR ? IDC_PASSWORD : IDC_USERNAME));
|
||
|
}
|
||
|
pDB->Release();
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL ValidateLogonDialog(HWND hwndDialog)
|
||
|
{
|
||
|
LRESULT iItem = ::SendDlgItemMessage(hwndDialog, IDC_USERNAME, LB_GETCURSEL, 0, 0);
|
||
|
if (iItem == LB_ERR)
|
||
|
return FALSE;
|
||
|
|
||
|
IUser *pUser = (IUser *)::SendDlgItemMessage(hwndDialog, IDC_USERNAME, LB_GETITEMDATA, iItem, 0);
|
||
|
|
||
|
if (pUser != NULL) {
|
||
|
NLS_STR nlsUsername(cchMaxUsername+1);
|
||
|
if (nlsUsername.QueryError())
|
||
|
return FALSE;
|
||
|
|
||
|
DWORD cbBuffer = nlsUsername.QueryAllocSize();
|
||
|
pUser->GetName(nlsUsername.Party(), &cbBuffer);
|
||
|
nlsUsername.DonePartying();
|
||
|
|
||
|
HWND hwndPassword = ::GetDlgItem(hwndDialog, IDC_PASSWORD);
|
||
|
NLS_STR nlsPassword(::GetWindowTextLength(hwndPassword)+2);
|
||
|
if (nlsPassword.QueryError())
|
||
|
return FALSE;
|
||
|
|
||
|
::GetWindowText(hwndPassword, nlsPassword.Party(), nlsPassword.QueryAllocSize()-1);
|
||
|
nlsPassword.DonePartying();
|
||
|
|
||
|
if (SUCCEEDED(pUser->Authenticate(nlsPassword.QueryPch()))) {
|
||
|
LogonData *pld = (LogonData *)::GetWindowLongPtr(hwndDialog, DWLP_USER);
|
||
|
if (pld->lpAuthentInfo) {
|
||
|
DWORD cbUsername = pld->lpAuthentInfo->cbUsername;
|
||
|
DWORD cbPassword = pld->lpAuthentInfo->cbPassword;
|
||
|
NPSCopyNLS(&nlsUsername, pld->lpAuthentInfo->lpUsername, &cbUsername);
|
||
|
NPSCopyNLS(&nlsPassword, pld->lpAuthentInfo->lpPassword, &cbPassword);
|
||
|
}
|
||
|
|
||
|
if (pld->ppOut) {
|
||
|
*pld->ppOut = pUser;
|
||
|
pUser->AddRef();
|
||
|
}
|
||
|
|
||
|
if (pld->dwFlags & LUA_FORNEXTLOGON) {
|
||
|
CacheLogonCredentials(nlsUsername.QueryPch(), nlsPassword.QueryPch());
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
NLS_STR nlsTitle(MAX_RES_STR_LEN);
|
||
|
NLS_STR nlsMessage(MAX_RES_STR_LEN);
|
||
|
if (!nlsTitle.QueryError() && !nlsMessage.QueryError()) {
|
||
|
nlsTitle.LoadString(IDS_LOGONTITLE);
|
||
|
nlsMessage.LoadString(IDS_BADPASSWORD);
|
||
|
::MessageBox(hwndDialog, nlsMessage.QueryPch(), nlsTitle.QueryPch(), MB_ICONSTOP | MB_OK);
|
||
|
}
|
||
|
::SetFocus(hwndPassword);
|
||
|
::SendMessage(hwndPassword, EM_SETSEL, (WPARAM)(INT)0, (WPARAM)(INT)-1);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void DestroyUserList(HWND hwndLB)
|
||
|
{
|
||
|
LRESULT cItems = ::SendMessage(hwndLB, LB_GETCOUNT, 0, 0);
|
||
|
|
||
|
for (LRESULT iItem = 0; iItem < cItems; iItem++) {
|
||
|
IUser *pUser = (IUser *)::SendMessage(hwndLB, LB_GETITEMDATA, iItem, 0);
|
||
|
if (pUser != NULL) {
|
||
|
pUser->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void ExitLogonDialog(HWND hwndDialog, DWORD err)
|
||
|
{
|
||
|
DestroyUserList(GetDlgItem(hwndDialog, IDC_USERNAME));
|
||
|
|
||
|
LogonData *pld = (LogonData *)::GetWindowLongPtr(hwndDialog, DWLP_USER);
|
||
|
if (pld->hbmTransparent != NULL)
|
||
|
DeleteObject(pld->hbmTransparent);
|
||
|
|
||
|
::EndDialog(hwndDialog, err);
|
||
|
}
|
||
|
|
||
|
|
||
|
extern "C" {
|
||
|
|
||
|
INT_PTR LogonDlgProc(
|
||
|
HWND hwndDlg,
|
||
|
UINT msg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
#if 0 /*** no help for now ***/
|
||
|
// Help text array
|
||
|
static DWORD aIds[] = {
|
||
|
IDC_DUMMY1, IDH_NET_LOG_USERNAME,
|
||
|
IDD_LOG_USERNAME, IDH_NET_LOG_USERNAME,
|
||
|
IDC_DUMMY2, IDH_NET_LOG_PASSWORD,
|
||
|
IDD_LOG_PASSWORD, IDH_NET_LOG_PASSWORD,
|
||
|
IDC_LOGOFRAME, NO_HELP,
|
||
|
IDC_DUMMY3, NO_HELP,
|
||
|
0,0
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
switch (msg) {
|
||
|
case WM_INITDIALOG:
|
||
|
{
|
||
|
DWORD err = ::InitLogonDialog(hwndDlg, (LogonData *)lParam);
|
||
|
if (err != ERROR_SUCCESS) {
|
||
|
::ExitLogonDialog(hwndDlg, err);
|
||
|
}
|
||
|
}
|
||
|
return FALSE; /* we set the focus */
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
switch (LOWORD(wParam)) {
|
||
|
case IDCANCEL:
|
||
|
::ExitLogonDialog(hwndDlg, WN_CANCEL);
|
||
|
return TRUE; /* we processed a message */
|
||
|
|
||
|
case IDOK:
|
||
|
if (::ValidateLogonDialog(hwndDlg))
|
||
|
::ExitLogonDialog(hwndDlg, WN_SUCCESS);
|
||
|
return TRUE; /* we processed a message */
|
||
|
|
||
|
case IDC_USERNAME:
|
||
|
if (HIWORD(wParam) == LBN_SELCHANGE) {
|
||
|
int iItem = (int)::SendDlgItemMessage(hwndDlg, IDC_USERNAME, LB_GETCURSEL, 0, 0);
|
||
|
UserSelected((HWND)lParam, iItem);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#if 0 /*** no help for now ***/
|
||
|
case WM_HELP:
|
||
|
WinHelp( ((LPHELPINFO)lParam)->hItemHandle, szHelpFile,
|
||
|
HELP_WM_HELP, (DWORD)(LPVOID)aIds );
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
WinHelp( (HWND)wParam, szHelpFile, HELP_CONTEXTMENU,
|
||
|
(DWORD)(LPVOID)aIds );
|
||
|
return TRUE;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return FALSE; /* we didn't process the message */
|
||
|
}
|
||
|
|
||
|
}; /* extern "C" */
|
||
|
|
||
|
|
||
|
DWORD DoLogonDialog(HWND hwndOwner, LPLOGONINFO lpAuthentInfo)
|
||
|
{
|
||
|
LogonData ld;
|
||
|
|
||
|
ld.lpAuthentInfo = lpAuthentInfo;
|
||
|
ld.dwFlags = 0;
|
||
|
ld.ppOut = NULL;
|
||
|
ld.hbmTransparent = NULL;
|
||
|
|
||
|
INT_PTR nRet = ::DialogBoxParam(::hInstance, MAKEINTRESOURCE(IDD_LOGON),
|
||
|
hwndOwner, LogonDlgProc, (LPARAM)&ld);
|
||
|
|
||
|
if (nRet == -1)
|
||
|
return WN_OUT_OF_MEMORY;
|
||
|
else
|
||
|
return (DWORD)nRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT DoUserDialog(HWND hwndOwner, DWORD dwFlags, IUser **ppOut)
|
||
|
{
|
||
|
LogonData ld;
|
||
|
|
||
|
ld.lpAuthentInfo = NULL;
|
||
|
ld.dwFlags = dwFlags;
|
||
|
ld.ppOut = ppOut;
|
||
|
if (ppOut != NULL)
|
||
|
*ppOut = NULL;
|
||
|
|
||
|
INT_PTR nRet = ::DialogBoxParam(::hInstance, MAKEINTRESOURCE(IDD_LOGON),
|
||
|
hwndOwner, LogonDlgProc, (LPARAM)&ld);
|
||
|
|
||
|
if (nRet == -1)
|
||
|
return E_OUTOFMEMORY;
|
||
|
else
|
||
|
return (nRet == WN_SUCCESS) ? S_OK : E_ABORT;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD TryDefaultLogon(LPCSTR pszUsername, LPCSTR pszPassword, LPLOGONINFO lpAuthentInfo)
|
||
|
{
|
||
|
IUserDatabase *pDB = NULL;
|
||
|
if (FAILED(::CreateUserDatabase(IID_IUserDatabase, (void **)&pDB))) {
|
||
|
return WN_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
DWORD err;
|
||
|
IUser *pUser;
|
||
|
if (SUCCEEDED(pDB->GetUser(pszUsername, &pUser))) {
|
||
|
if (SUCCEEDED(pUser->Authenticate(pszPassword)))
|
||
|
err = WN_SUCCESS;
|
||
|
else
|
||
|
err = WN_BAD_PASSWORD;
|
||
|
|
||
|
pUser->Release();
|
||
|
}
|
||
|
else {
|
||
|
err = WN_BAD_USER;
|
||
|
}
|
||
|
|
||
|
pDB->Release();
|
||
|
|
||
|
if (err == WN_SUCCESS) {
|
||
|
DWORD cbUsername = lpAuthentInfo->cbUsername;
|
||
|
DWORD cbPassword = lpAuthentInfo->cbPassword;
|
||
|
NPSCopyString(pszUsername, lpAuthentInfo->lpUsername, &cbUsername);
|
||
|
NPSCopyString(pszPassword, lpAuthentInfo->lpPassword, &cbPassword);
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
|
||
|
SPIENTRY NPLogon(
|
||
|
HWND hwndOwner,
|
||
|
LPLOGONINFO lpAuthentInfo,
|
||
|
LPLOGONINFO lpPreviousAuthentInfo,
|
||
|
LPTSTR lpLogonScript,
|
||
|
DWORD dwBufferSize,
|
||
|
DWORD dwFlags
|
||
|
)
|
||
|
{
|
||
|
/* ignore logon done notification, we only act on logon starting */
|
||
|
if (dwFlags & LOGON_DONE) {
|
||
|
return WN_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/* we have nothing to do if we're not the primary logon provider */
|
||
|
if (!(dwFlags & LOGON_PRIMARY)) {
|
||
|
return WN_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/* make sure profiles are enabled, fall back to windows logon if not */
|
||
|
HKEY hkeyLogon;
|
||
|
DWORD err;
|
||
|
DWORD fProfilesEnabled = FALSE;
|
||
|
DWORD cbData = sizeof(fProfilesEnabled);
|
||
|
err = ::RegOpenKey(HKEY_LOCAL_MACHINE, ::szLogonKey, &hkeyLogon);
|
||
|
if (err != ERROR_SUCCESS)
|
||
|
return WN_NO_NETWORK;
|
||
|
err = ::RegQueryValueEx(hkeyLogon, ::szUserProfiles, NULL, NULL,
|
||
|
(LPBYTE)&fProfilesEnabled, &cbData);
|
||
|
::RegCloseKey(hkeyLogon);
|
||
|
if (err != ERROR_SUCCESS || !fProfilesEnabled)
|
||
|
return WN_NO_NETWORK;
|
||
|
|
||
|
/* If we have cached logon credentials, attempt to use them. */
|
||
|
|
||
|
if (fDoDefaultLogon) {
|
||
|
DeObfuscateString(szDefaultLogonUsername);
|
||
|
DeObfuscateString(szDefaultLogonPassword);
|
||
|
|
||
|
DWORD err = TryDefaultLogon(szDefaultLogonUsername, szDefaultLogonPassword, lpAuthentInfo);
|
||
|
|
||
|
::memsetf(szDefaultLogonUsername, '\0', sizeof(szDefaultLogonUsername));
|
||
|
::memsetf(szDefaultLogonPassword, '\0', sizeof(szDefaultLogonPassword));
|
||
|
fDoDefaultLogon = FALSE;
|
||
|
|
||
|
if (err == WN_SUCCESS)
|
||
|
return WN_SUCCESS;
|
||
|
}
|
||
|
|
||
|
return DoLogonDialog(hwndOwner, lpAuthentInfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
SPIENTRY NPLogoff(
|
||
|
HWND hwndOwner,
|
||
|
LPLOGONINFO lpAuthentInfo,
|
||
|
DWORD dwReason
|
||
|
)
|
||
|
{
|
||
|
return WN_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
SPIENTRY NPGetPolicyPath(
|
||
|
LPTSTR lpPath,
|
||
|
LPDWORD lpBufferSize,
|
||
|
DWORD dwFlags
|
||
|
)
|
||
|
{
|
||
|
return WN_NOT_SUPPORTED;
|
||
|
}
|