windows-nt/Source/XPSP1/NT/ds/security/gina/policy/poledit/connect.c
2020-09-26 16:20:57 +08:00

721 lines
17 KiB
C

//*********************************************************************
//* Microsoft Windows **
//* Copyright(c) Microsoft Corp., 1993 **
//*********************************************************************
#include "admincfg.h"
INT_PTR CALLBACK ConnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam);
BOOL InitConnectDlg(HWND hDlg);
BOOL ProcessConnectDlg(HWND hDlg);
TCHAR szRemoteName[COMPUTERNAMELEN+1];
#define MAX_KEY_NAME 200
typedef struct _KEYNODE {
LPTSTR lpUserName;
struct _KEYNODE *pNext;
} KEYNODE, * LPKEYNODE;
BOOL AddKeyNode (LPKEYNODE *lpList, LPTSTR lpUserName);
BOOL FreeKeyList (LPKEYNODE lpList);
typedef struct _USERINFO {
LPTSTR lpComputerName;
LPKEYNODE lpList;
LPKEYNODE lpSelectedItem;
HKEY hkeyRemoteHLM;
} USERINFO, * LPUSERINFO;
// HKEYs to remote registry
HKEY hkeyRemoteHLM = NULL; // remote HKEY_LOCAL_MACHINE
HKEY hkeyRemoteHCU = NULL; // remote HKEY_CURRENT_USER
HKEY hkeyVirtHLM = HKEY_LOCAL_MACHINE; // virtual HKEY_LOCAL_MACHINE
HKEY hkeyVirtHCU = HKEY_CURRENT_USER; // virtual HKEY_CURRENT_USER
BOOL OnConnect(HWND hwndApp,HWND hwndList)
{
if (dwAppState & AS_FILEDIRTY) {
if (!QueryForSave(hwndApp,hwndList)) return TRUE; // user cancelled
}
if (DialogBox(ghInst,MAKEINTRESOURCE(DLG_CONNECT),hwndApp,
ConnectDlgProc)) {
if (dwAppState & AS_FILELOADED) {
// Free dirty file and free users
RemoveAllUsers(hwndList);
}
if (!LoadFromRegistry(hwndApp,hwndList,TRUE)) {
OnDisconnect(hwndApp);
return FALSE;
}
lstrcpy(szDatFilename,szNull);
dwAppState |= AS_FILELOADED | AS_FILEHASNAME | AS_REMOTEREGISTRY;
dwAppState &= (~AS_CANOPENTEMPLATE & ~AS_LOCALREGISTRY & ~AS_POLICYFILE);
EnableMenuItems(hwndApp,dwAppState);
SetTitleBar(hwndApp,szRemoteName);
EnableWindow(hwndList,TRUE);
}
return TRUE;
}
INT_PTR CALLBACK ConnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
if (!InitConnectDlg(hDlg)) {
EndDialog(hDlg,0);
return FALSE;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (ProcessConnectDlg(hDlg))
EndDialog(hDlg,TRUE);
return TRUE;
break;
case IDCANCEL:
EndDialog(hDlg,FALSE);
return TRUE;
break;
}
break;
}
return FALSE;
}
BOOL ProcessConnectDlg(HWND hDlg)
{
TCHAR szComputerName[COMPUTERNAMELEN+1];
hkeyRemoteHLM=NULL;
// get computer name from dialog
if (!GetDlgItemText(hDlg,IDD_COMPUTERNAME,szComputerName,
ARRAYSIZE(szComputerName))) {
SetFocus(GetDlgItem(hDlg,IDD_COMPUTERNAME));
MsgBox(hDlg,IDS_NEEDCOMPUTERNAME,MB_OK,MB_ICONINFORMATION);
return FALSE;
}
// make the connection
if (RemoteConnect(hDlg,szComputerName,TRUE)) {
HKEY hkeyState;
// save this name to fill in UI as default in future connect dlgs
if (RegCreateKey(HKEY_CURRENT_USER,szAPPREGKEY,&hkeyState) ==
ERROR_SUCCESS) {
RegSetValueEx(hkeyState,szLASTCONNECTION,0,REG_SZ,szComputerName,(lstrlen(szComputerName)+1) * sizeof(TCHAR));
RegCloseKey(hkeyState);
}
return TRUE;
} else return FALSE;
}
void GetRealUserName (HKEY hRemoteHLM, LPTSTR lpRemoteMachine,
LPTSTR lpInput, LPTSTR lpOutput)
{
TCHAR szName [MAX_PATH];
TCHAR szDomainName [MAX_PATH];
LONG lResult;
HKEY hKey;
DWORD dwSize, dwType, dwDomainSize;
PSID pSid;
SID_NAME_USE SidNameUse;
//
// Initialize the output with the default name
//
lstrcpy (lpOutput, lpInput);
//
// If the remote machine is NT, then this registry call will
// succeed and we can get the real sid to look up with.
// If the remote machine is Windows, then this call will fail
// and we'll go with the default input name (which is ok because
// Windows uses the user name in HKEY_USERS rather than a SID.
//
wsprintf (szName, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s"),
lpInput);
lResult = RegOpenKeyEx (hRemoteHLM,
szName,
0,
KEY_READ,
&hKey);
if (lResult != ERROR_SUCCESS) {
return;
}
//
// Query the size of the SID (binary)
//
lResult = RegQueryValueEx (hKey,
TEXT("Sid"),
NULL,
&dwType,
NULL,
&dwSize);
if (lResult != ERROR_SUCCESS) {
RegCloseKey (hKey);
return;
}
//
// Allocate space for the SID
//
pSid = GlobalAlloc (GPTR, dwSize);
if (!pSid) {
RegCloseKey (hKey);
return;
}
lResult = RegQueryValueEx (hKey,
TEXT("Sid"),
NULL,
&dwType,
pSid,
&dwSize);
if (lResult != ERROR_SUCCESS) {
GlobalFree (pSid);
RegCloseKey (hKey);
return;
}
//
// Lookup the account name
//
dwSize = MAX_PATH;
dwDomainSize = MAX_PATH;
if (LookupAccountSid (lpRemoteMachine,
pSid,
szName,
&dwSize,
szDomainName,
&dwDomainSize,
&SidNameUse) ) {
lstrcpy (lpOutput, szDomainName);
lstrcat (lpOutput, TEXT("\\"));
lstrcat (lpOutput, szName);
} else {
LoadSz(IDS_ACCOUNTUNKNOWN, lpOutput, MAX_KEY_NAME);
}
//
// Clean up
//
GlobalFree (pSid);
RegCloseKey (hKey);
}
LRESULT CALLBACK ChooseUserDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
{
LPUSERINFO lpInfo = (LPUSERINFO) lParam;
LPKEYNODE lpItem;
TCHAR szMsg[60+COMPUTERNAMELEN],szFmt[60];
TCHAR szUserName[MAX_KEY_NAME];
INT iResult;
//
// Store the LPUSERINFO pointer in the extra words
//
SetWindowLongPtr (hDlg, GWLP_USERDATA, (LONG_PTR) lpInfo);
//
// Fill in the title
//
LoadSz(IDS_CHOOSEUSER_TITLE, szFmt, ARRAYSIZE(szFmt));
wsprintf(szMsg,szFmt,lpInfo->lpComputerName);
SendDlgItemMessage (hDlg, IDD_USER, WM_SETTEXT, 0, (LPARAM) szMsg);
lpItem = lpInfo->lpList;
while (lpItem) {
//
// If the user name is not .Default, add it to
// the list.
//
if (lstrcmpi(lpItem->lpUserName, TEXT(".Default")) != 0) {
//
// Get the user name to display
//
GetRealUserName (lpInfo->hkeyRemoteHLM, lpInfo->lpComputerName,
lpItem->lpUserName, szUserName);
iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_INSERTSTRING,
(WPARAM) -1, (LPARAM) szUserName);
if (iResult != LB_ERR) {
SendDlgItemMessage (hDlg, IDD_LIST, LB_SETITEMDATA,
iResult, (LPARAM) lpItem);
}
}
lpItem = lpItem->pNext;
}
//
// Select the first item, or disable the Ok button if no
// one is logged on.
//
iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETCOUNT, 0, 0);
if (iResult == 0) {
EnableWindow (GetDlgItem (hDlg, IDOK), FALSE);
} else {
SendDlgItemMessage (hDlg, IDD_LIST, LB_SETCURSEL, 0, 0);
}
}
break;
case WM_COMMAND:
if ((LOWORD(wParam) == IDOK) ||
((LOWORD(wParam) == IDD_LIST) && (HIWORD(wParam) == LBN_DBLCLK))){
LPUSERINFO lpInfo = (LPUSERINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
INT iResult;
if (!lpInfo) {
return TRUE;
}
//
// Find the selected item
//
iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETCURSEL, 0, 0);
if (iResult != LB_ERR) {
//
// Save the item pointer
//
iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETITEMDATA,
(WPARAM) iResult, 0);
if (iResult != LB_ERR) {
lpInfo->lpSelectedItem = (LPKEYNODE) IntToPtr(iResult);
} else {
lpInfo->lpSelectedItem = NULL;
}
EndDialog(hDlg, TRUE);
}
return TRUE;
}
if (LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
BOOL RemoteConnectHCU (HWND hwndOwner, TCHAR * pszComputerName,
HKEY hkeyRemoteHLM, HKEY * hkeyRemoteHCU,
BOOL fDisplayError)
{
USERINFO UserInfo;
HKEY hkeyRemoteHU;
LONG lResult;
DWORD dwSubKeys;
TCHAR szUserName[MAX_KEY_NAME];
LPKEYNODE lpList = NULL, lpItem;
DWORD dwSize;
UINT Index = 0;
FILETIME ftWrite;
BOOL bRetVal = FALSE;
//
// Connect to HKEY_USERS on the remote machine to see
// how many people are logged on.
//
lResult = RegConnectRegistry(pszComputerName,HKEY_USERS,
&hkeyRemoteHU);
if (lResult != ERROR_SUCCESS) {
return FALSE;
}
//
// Enumerate the subkeys
//
dwSize = MAX_KEY_NAME;
lResult = RegEnumKeyEx(hkeyRemoteHU, Index, szUserName, &dwSize, NULL,
NULL, NULL, &ftWrite);
if (lResult == ERROR_SUCCESS) {
do {
//
// Add the node
//
if (!AddKeyNode (&lpList, szUserName)) {
break;
}
Index++;
dwSize = MAX_KEY_NAME;
lResult = RegEnumKeyEx(hkeyRemoteHU, Index, szUserName, &dwSize, NULL,
NULL, NULL, &ftWrite);
} while (lResult == ERROR_SUCCESS);
} else {
RegCloseKey(hkeyRemoteHU);
return FALSE;
}
UserInfo.lpComputerName = pszComputerName;
UserInfo.lpList = lpList;
UserInfo.hkeyRemoteHLM = hkeyRemoteHLM;
if (DialogBoxParam (ghInst, MAKEINTRESOURCE(DLG_CHOOSEUSER), hwndOwner,
ChooseUserDlgProc, (LPARAM)&UserInfo)) {
if (UserInfo.lpSelectedItem) {
lResult = RegOpenKeyEx (hkeyRemoteHU,
UserInfo.lpSelectedItem->lpUserName,
0,
KEY_ALL_ACCESS,
hkeyRemoteHCU);
if (lResult == ERROR_SUCCESS) {
bRetVal = TRUE;
} else {
SetFocus(GetDlgItem(hwndOwner,IDD_COMPUTERNAME));
SendDlgItemMessage(hwndOwner,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
if (fDisplayError) {
TCHAR szMsg[MEDIUMBUF+COMPUTERNAMELEN+COMPUTERNAMELEN];
TCHAR szFmt[MEDIUMBUF];
LoadSz(IDS_CANTCONNECT,szFmt,ARRAYSIZE(szFmt));
wsprintf(szMsg,szFmt,pszComputerName,pszComputerName);
MsgBoxSz(hwndOwner,szMsg,MB_OK,MB_ICONINFORMATION);
}
}
}
}
//
// Free the link list
//
FreeKeyList (lpList);
//
// Close HKEY_USERS on the remote machine
//
RegCloseKey (hkeyRemoteHU);
return bRetVal;
}
BOOL RemoteConnect(HWND hwndOwner,TCHAR * pszComputerName,BOOL fDisplayError)
{
UINT uRet;
HCURSOR hOldCursor;
#ifdef DEBUG
wsprintf(szDebugOut,TEXT("ADMINCFG: connecting to %s\r\n"),pszComputerName);
OutputDebugString(szDebugOut);
#endif
hkeyRemoteHLM = hkeyRemoteHCU = NULL;
hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
//
// try to connect to remote registry HKEY_LOCAL_MACHINE
//
uRet = RegConnectRegistry(pszComputerName,HKEY_LOCAL_MACHINE,
&hkeyRemoteHLM);
SetCursor(hOldCursor);
if (uRet != ERROR_SUCCESS) {
SetFocus(GetDlgItem(hwndOwner,IDD_COMPUTERNAME));
SendDlgItemMessage(hwndOwner,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
if (fDisplayError) {
TCHAR szMsg[MEDIUMBUF+COMPUTERNAMELEN+COMPUTERNAMELEN];
TCHAR szFmt[MEDIUMBUF];
LoadSz(IDS_CANTCONNECT,szFmt,ARRAYSIZE(szFmt));
wsprintf(szMsg,szFmt,pszComputerName,pszComputerName);
MsgBoxSz(hwndOwner,szMsg,MB_OK,MB_ICONINFORMATION);
}
return FALSE;
}
//
// try to connect to remote registry HKEY_CURRENT_USER
//
uRet = RemoteConnectHCU (hwndOwner, pszComputerName, hkeyRemoteHLM,
&hkeyRemoteHCU, fDisplayError);
if (!uRet) {
RegCloseKey(hkeyRemoteHLM);
hkeyRemoteHLM = NULL;
return FALSE;
}
hkeyVirtHLM = hkeyRemoteHLM;
hkeyVirtHCU = hkeyRemoteHCU;
// change "connect..." menu item to "disconnect"
ReplaceMenuItem(hwndMain,IDM_CONNECT,IDM_DISCONNECT,IDS_DISCONNECT);
lstrcpy(szRemoteName,pszComputerName);
return TRUE;
}
BOOL OnDisconnect(HWND hwndOwner)
{
#ifdef DEBUG
OutputDebugString(TEXT("ADMINCFG: Disconnecting.\r\n"));
#endif
if (hkeyRemoteHLM) {
RegCloseKey(hkeyRemoteHLM);
hkeyRemoteHLM = NULL;
}
if (hkeyRemoteHCU) {
RegCloseKey(hkeyRemoteHCU);
hkeyRemoteHCU = NULL;
}
// point virtual HLM, HCU keys at local machine
hkeyVirtHLM = HKEY_LOCAL_MACHINE;
hkeyVirtHCU = HKEY_CURRENT_USER;
// change "disconnect" menu item to "connect..."
ReplaceMenuItem(hwndMain,IDM_DISCONNECT,IDM_CONNECT,IDS_CONNECT);
SetTitleBar(hwndMain,NULL);
return TRUE;
}
BOOL InitConnectDlg(HWND hDlg)
{
HKEY hkeyState;
TCHAR szComputerName[COMPUTERNAMELEN+1];
DWORD dwSize = ARRAYSIZE(szComputerName);
SetFocus(GetDlgItem(hDlg,IDD_COMPUTERNAME));
SendDlgItemMessage(hDlg,IDD_COMPUTERNAME,EM_SETLIMITTEXT,
COMPUTERNAMELEN,0L);
if (RegOpenKey(HKEY_CURRENT_USER,szAPPREGKEY,&hkeyState) ==
ERROR_SUCCESS) {
if (RegQueryValueEx(hkeyState,szLASTCONNECTION,NULL,NULL,szComputerName,&dwSize)
==ERROR_SUCCESS) {
SetDlgItemText(hDlg,IDD_COMPUTERNAME,szComputerName);
SendDlgItemMessage(hDlg,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
}
RegCloseKey(hkeyState);
}
return TRUE;
}
//*************************************************************
//
// AddKEYNODE()
//
// Purpose: Adds a key node to the link listed
//
// Parameters: lpList - Link list of nodes
// lpUserName - User Name
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 1/16/96 ericflo Created
//
//*************************************************************
BOOL AddKeyNode (LPKEYNODE *lpList, LPTSTR lpUserName)
{
LPKEYNODE lpNewItem;
if (!lpUserName || !*lpUserName) {
return TRUE;
}
//
// Setup the new node
//
lpNewItem = (LPKEYNODE) LocalAlloc(LPTR, sizeof(KEYNODE) +
((lstrlen(lpUserName) + 1) * sizeof(TCHAR)));
if (!lpNewItem) {
return FALSE;
}
lpNewItem->lpUserName = (LPTSTR)((LPBYTE)lpNewItem + sizeof(KEYNODE));
lstrcpy (lpNewItem->lpUserName, lpUserName);
lpNewItem->pNext = *lpList;
*lpList = lpNewItem;
return TRUE;
}
//*************************************************************
//
// FreeKeyList()
//
// Purpose: Free's a KEYNODE link list
//
// Parameters: lpList - List to be freed
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 1/16/96 ericflo Created
//
//*************************************************************
BOOL FreeKeyList (LPKEYNODE lpList)
{
LPKEYNODE lpNext;
if (!lpList) {
return TRUE;
}
lpNext = lpList->pNext;
while (lpList) {
LocalFree (lpList);
lpList = lpNext;
if (lpList) {
lpNext = lpList->pNext;
}
}
return TRUE;
}