Source code of Windows XP (NT5)
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.

720 lines
17 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1993 **
  4. //*********************************************************************
  5. #include "admincfg.h"
  6. INT_PTR CALLBACK ConnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
  7. LPARAM lParam);
  8. BOOL InitConnectDlg(HWND hDlg);
  9. BOOL ProcessConnectDlg(HWND hDlg);
  10. TCHAR szRemoteName[COMPUTERNAMELEN+1];
  11. #define MAX_KEY_NAME 200
  12. typedef struct _KEYNODE {
  13. LPTSTR lpUserName;
  14. struct _KEYNODE *pNext;
  15. } KEYNODE, * LPKEYNODE;
  16. BOOL AddKeyNode (LPKEYNODE *lpList, LPTSTR lpUserName);
  17. BOOL FreeKeyList (LPKEYNODE lpList);
  18. typedef struct _USERINFO {
  19. LPTSTR lpComputerName;
  20. LPKEYNODE lpList;
  21. LPKEYNODE lpSelectedItem;
  22. HKEY hkeyRemoteHLM;
  23. } USERINFO, * LPUSERINFO;
  24. // HKEYs to remote registry
  25. HKEY hkeyRemoteHLM = NULL; // remote HKEY_LOCAL_MACHINE
  26. HKEY hkeyRemoteHCU = NULL; // remote HKEY_CURRENT_USER
  27. HKEY hkeyVirtHLM = HKEY_LOCAL_MACHINE; // virtual HKEY_LOCAL_MACHINE
  28. HKEY hkeyVirtHCU = HKEY_CURRENT_USER; // virtual HKEY_CURRENT_USER
  29. BOOL OnConnect(HWND hwndApp,HWND hwndList)
  30. {
  31. if (dwAppState & AS_FILEDIRTY) {
  32. if (!QueryForSave(hwndApp,hwndList)) return TRUE; // user cancelled
  33. }
  34. if (DialogBox(ghInst,MAKEINTRESOURCE(DLG_CONNECT),hwndApp,
  35. ConnectDlgProc)) {
  36. if (dwAppState & AS_FILELOADED) {
  37. // Free dirty file and free users
  38. RemoveAllUsers(hwndList);
  39. }
  40. if (!LoadFromRegistry(hwndApp,hwndList,TRUE)) {
  41. OnDisconnect(hwndApp);
  42. return FALSE;
  43. }
  44. lstrcpy(szDatFilename,szNull);
  45. dwAppState |= AS_FILELOADED | AS_FILEHASNAME | AS_REMOTEREGISTRY;
  46. dwAppState &= (~AS_CANOPENTEMPLATE & ~AS_LOCALREGISTRY & ~AS_POLICYFILE);
  47. EnableMenuItems(hwndApp,dwAppState);
  48. SetTitleBar(hwndApp,szRemoteName);
  49. EnableWindow(hwndList,TRUE);
  50. }
  51. return TRUE;
  52. }
  53. INT_PTR CALLBACK ConnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  54. {
  55. switch (uMsg) {
  56. case WM_INITDIALOG:
  57. if (!InitConnectDlg(hDlg)) {
  58. EndDialog(hDlg,0);
  59. return FALSE;
  60. }
  61. return TRUE;
  62. case WM_COMMAND:
  63. switch (LOWORD(wParam)) {
  64. case IDOK:
  65. if (ProcessConnectDlg(hDlg))
  66. EndDialog(hDlg,TRUE);
  67. return TRUE;
  68. break;
  69. case IDCANCEL:
  70. EndDialog(hDlg,FALSE);
  71. return TRUE;
  72. break;
  73. }
  74. break;
  75. }
  76. return FALSE;
  77. }
  78. BOOL ProcessConnectDlg(HWND hDlg)
  79. {
  80. TCHAR szComputerName[COMPUTERNAMELEN+1];
  81. hkeyRemoteHLM=NULL;
  82. // get computer name from dialog
  83. if (!GetDlgItemText(hDlg,IDD_COMPUTERNAME,szComputerName,
  84. ARRAYSIZE(szComputerName))) {
  85. SetFocus(GetDlgItem(hDlg,IDD_COMPUTERNAME));
  86. MsgBox(hDlg,IDS_NEEDCOMPUTERNAME,MB_OK,MB_ICONINFORMATION);
  87. return FALSE;
  88. }
  89. // make the connection
  90. if (RemoteConnect(hDlg,szComputerName,TRUE)) {
  91. HKEY hkeyState;
  92. // save this name to fill in UI as default in future connect dlgs
  93. if (RegCreateKey(HKEY_CURRENT_USER,szAPPREGKEY,&hkeyState) ==
  94. ERROR_SUCCESS) {
  95. RegSetValueEx(hkeyState,szLASTCONNECTION,0,REG_SZ,szComputerName,(lstrlen(szComputerName)+1) * sizeof(TCHAR));
  96. RegCloseKey(hkeyState);
  97. }
  98. return TRUE;
  99. } else return FALSE;
  100. }
  101. void GetRealUserName (HKEY hRemoteHLM, LPTSTR lpRemoteMachine,
  102. LPTSTR lpInput, LPTSTR lpOutput)
  103. {
  104. TCHAR szName [MAX_PATH];
  105. TCHAR szDomainName [MAX_PATH];
  106. LONG lResult;
  107. HKEY hKey;
  108. DWORD dwSize, dwType, dwDomainSize;
  109. PSID pSid;
  110. SID_NAME_USE SidNameUse;
  111. //
  112. // Initialize the output with the default name
  113. //
  114. lstrcpy (lpOutput, lpInput);
  115. //
  116. // If the remote machine is NT, then this registry call will
  117. // succeed and we can get the real sid to look up with.
  118. // If the remote machine is Windows, then this call will fail
  119. // and we'll go with the default input name (which is ok because
  120. // Windows uses the user name in HKEY_USERS rather than a SID.
  121. //
  122. wsprintf (szName, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s"),
  123. lpInput);
  124. lResult = RegOpenKeyEx (hRemoteHLM,
  125. szName,
  126. 0,
  127. KEY_READ,
  128. &hKey);
  129. if (lResult != ERROR_SUCCESS) {
  130. return;
  131. }
  132. //
  133. // Query the size of the SID (binary)
  134. //
  135. lResult = RegQueryValueEx (hKey,
  136. TEXT("Sid"),
  137. NULL,
  138. &dwType,
  139. NULL,
  140. &dwSize);
  141. if (lResult != ERROR_SUCCESS) {
  142. RegCloseKey (hKey);
  143. return;
  144. }
  145. //
  146. // Allocate space for the SID
  147. //
  148. pSid = GlobalAlloc (GPTR, dwSize);
  149. if (!pSid) {
  150. RegCloseKey (hKey);
  151. return;
  152. }
  153. lResult = RegQueryValueEx (hKey,
  154. TEXT("Sid"),
  155. NULL,
  156. &dwType,
  157. pSid,
  158. &dwSize);
  159. if (lResult != ERROR_SUCCESS) {
  160. GlobalFree (pSid);
  161. RegCloseKey (hKey);
  162. return;
  163. }
  164. //
  165. // Lookup the account name
  166. //
  167. dwSize = MAX_PATH;
  168. dwDomainSize = MAX_PATH;
  169. if (LookupAccountSid (lpRemoteMachine,
  170. pSid,
  171. szName,
  172. &dwSize,
  173. szDomainName,
  174. &dwDomainSize,
  175. &SidNameUse) ) {
  176. lstrcpy (lpOutput, szDomainName);
  177. lstrcat (lpOutput, TEXT("\\"));
  178. lstrcat (lpOutput, szName);
  179. } else {
  180. LoadSz(IDS_ACCOUNTUNKNOWN, lpOutput, MAX_KEY_NAME);
  181. }
  182. //
  183. // Clean up
  184. //
  185. GlobalFree (pSid);
  186. RegCloseKey (hKey);
  187. }
  188. LRESULT CALLBACK ChooseUserDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  189. {
  190. switch (message) {
  191. case WM_INITDIALOG:
  192. {
  193. LPUSERINFO lpInfo = (LPUSERINFO) lParam;
  194. LPKEYNODE lpItem;
  195. TCHAR szMsg[60+COMPUTERNAMELEN],szFmt[60];
  196. TCHAR szUserName[MAX_KEY_NAME];
  197. INT iResult;
  198. //
  199. // Store the LPUSERINFO pointer in the extra words
  200. //
  201. SetWindowLongPtr (hDlg, GWLP_USERDATA, (LONG_PTR) lpInfo);
  202. //
  203. // Fill in the title
  204. //
  205. LoadSz(IDS_CHOOSEUSER_TITLE, szFmt, ARRAYSIZE(szFmt));
  206. wsprintf(szMsg,szFmt,lpInfo->lpComputerName);
  207. SendDlgItemMessage (hDlg, IDD_USER, WM_SETTEXT, 0, (LPARAM) szMsg);
  208. lpItem = lpInfo->lpList;
  209. while (lpItem) {
  210. //
  211. // If the user name is not .Default, add it to
  212. // the list.
  213. //
  214. if (lstrcmpi(lpItem->lpUserName, TEXT(".Default")) != 0) {
  215. //
  216. // Get the user name to display
  217. //
  218. GetRealUserName (lpInfo->hkeyRemoteHLM, lpInfo->lpComputerName,
  219. lpItem->lpUserName, szUserName);
  220. iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_INSERTSTRING,
  221. (WPARAM) -1, (LPARAM) szUserName);
  222. if (iResult != LB_ERR) {
  223. SendDlgItemMessage (hDlg, IDD_LIST, LB_SETITEMDATA,
  224. iResult, (LPARAM) lpItem);
  225. }
  226. }
  227. lpItem = lpItem->pNext;
  228. }
  229. //
  230. // Select the first item, or disable the Ok button if no
  231. // one is logged on.
  232. //
  233. iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETCOUNT, 0, 0);
  234. if (iResult == 0) {
  235. EnableWindow (GetDlgItem (hDlg, IDOK), FALSE);
  236. } else {
  237. SendDlgItemMessage (hDlg, IDD_LIST, LB_SETCURSEL, 0, 0);
  238. }
  239. }
  240. break;
  241. case WM_COMMAND:
  242. if ((LOWORD(wParam) == IDOK) ||
  243. ((LOWORD(wParam) == IDD_LIST) && (HIWORD(wParam) == LBN_DBLCLK))){
  244. LPUSERINFO lpInfo = (LPUSERINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  245. INT iResult;
  246. if (!lpInfo) {
  247. return TRUE;
  248. }
  249. //
  250. // Find the selected item
  251. //
  252. iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETCURSEL, 0, 0);
  253. if (iResult != LB_ERR) {
  254. //
  255. // Save the item pointer
  256. //
  257. iResult = (INT)SendDlgItemMessage (hDlg, IDD_LIST, LB_GETITEMDATA,
  258. (WPARAM) iResult, 0);
  259. if (iResult != LB_ERR) {
  260. lpInfo->lpSelectedItem = (LPKEYNODE) IntToPtr(iResult);
  261. } else {
  262. lpInfo->lpSelectedItem = NULL;
  263. }
  264. EndDialog(hDlg, TRUE);
  265. }
  266. return TRUE;
  267. }
  268. if (LOWORD(wParam) == IDCANCEL) {
  269. EndDialog(hDlg, FALSE);
  270. return TRUE;
  271. }
  272. break;
  273. }
  274. return FALSE;
  275. }
  276. BOOL RemoteConnectHCU (HWND hwndOwner, TCHAR * pszComputerName,
  277. HKEY hkeyRemoteHLM, HKEY * hkeyRemoteHCU,
  278. BOOL fDisplayError)
  279. {
  280. USERINFO UserInfo;
  281. HKEY hkeyRemoteHU;
  282. LONG lResult;
  283. DWORD dwSubKeys;
  284. TCHAR szUserName[MAX_KEY_NAME];
  285. LPKEYNODE lpList = NULL, lpItem;
  286. DWORD dwSize;
  287. UINT Index = 0;
  288. FILETIME ftWrite;
  289. BOOL bRetVal = FALSE;
  290. //
  291. // Connect to HKEY_USERS on the remote machine to see
  292. // how many people are logged on.
  293. //
  294. lResult = RegConnectRegistry(pszComputerName,HKEY_USERS,
  295. &hkeyRemoteHU);
  296. if (lResult != ERROR_SUCCESS) {
  297. return FALSE;
  298. }
  299. //
  300. // Enumerate the subkeys
  301. //
  302. dwSize = MAX_KEY_NAME;
  303. lResult = RegEnumKeyEx(hkeyRemoteHU, Index, szUserName, &dwSize, NULL,
  304. NULL, NULL, &ftWrite);
  305. if (lResult == ERROR_SUCCESS) {
  306. do {
  307. //
  308. // Add the node
  309. //
  310. if (!AddKeyNode (&lpList, szUserName)) {
  311. break;
  312. }
  313. Index++;
  314. dwSize = MAX_KEY_NAME;
  315. lResult = RegEnumKeyEx(hkeyRemoteHU, Index, szUserName, &dwSize, NULL,
  316. NULL, NULL, &ftWrite);
  317. } while (lResult == ERROR_SUCCESS);
  318. } else {
  319. RegCloseKey(hkeyRemoteHU);
  320. return FALSE;
  321. }
  322. UserInfo.lpComputerName = pszComputerName;
  323. UserInfo.lpList = lpList;
  324. UserInfo.hkeyRemoteHLM = hkeyRemoteHLM;
  325. if (DialogBoxParam (ghInst, MAKEINTRESOURCE(DLG_CHOOSEUSER), hwndOwner,
  326. ChooseUserDlgProc, (LPARAM)&UserInfo)) {
  327. if (UserInfo.lpSelectedItem) {
  328. lResult = RegOpenKeyEx (hkeyRemoteHU,
  329. UserInfo.lpSelectedItem->lpUserName,
  330. 0,
  331. KEY_ALL_ACCESS,
  332. hkeyRemoteHCU);
  333. if (lResult == ERROR_SUCCESS) {
  334. bRetVal = TRUE;
  335. } else {
  336. SetFocus(GetDlgItem(hwndOwner,IDD_COMPUTERNAME));
  337. SendDlgItemMessage(hwndOwner,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
  338. if (fDisplayError) {
  339. TCHAR szMsg[MEDIUMBUF+COMPUTERNAMELEN+COMPUTERNAMELEN];
  340. TCHAR szFmt[MEDIUMBUF];
  341. LoadSz(IDS_CANTCONNECT,szFmt,ARRAYSIZE(szFmt));
  342. wsprintf(szMsg,szFmt,pszComputerName,pszComputerName);
  343. MsgBoxSz(hwndOwner,szMsg,MB_OK,MB_ICONINFORMATION);
  344. }
  345. }
  346. }
  347. }
  348. //
  349. // Free the link list
  350. //
  351. FreeKeyList (lpList);
  352. //
  353. // Close HKEY_USERS on the remote machine
  354. //
  355. RegCloseKey (hkeyRemoteHU);
  356. return bRetVal;
  357. }
  358. BOOL RemoteConnect(HWND hwndOwner,TCHAR * pszComputerName,BOOL fDisplayError)
  359. {
  360. UINT uRet;
  361. HCURSOR hOldCursor;
  362. #ifdef DEBUG
  363. wsprintf(szDebugOut,TEXT("ADMINCFG: connecting to %s\r\n"),pszComputerName);
  364. OutputDebugString(szDebugOut);
  365. #endif
  366. hkeyRemoteHLM = hkeyRemoteHCU = NULL;
  367. hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
  368. //
  369. // try to connect to remote registry HKEY_LOCAL_MACHINE
  370. //
  371. uRet = RegConnectRegistry(pszComputerName,HKEY_LOCAL_MACHINE,
  372. &hkeyRemoteHLM);
  373. SetCursor(hOldCursor);
  374. if (uRet != ERROR_SUCCESS) {
  375. SetFocus(GetDlgItem(hwndOwner,IDD_COMPUTERNAME));
  376. SendDlgItemMessage(hwndOwner,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
  377. if (fDisplayError) {
  378. TCHAR szMsg[MEDIUMBUF+COMPUTERNAMELEN+COMPUTERNAMELEN];
  379. TCHAR szFmt[MEDIUMBUF];
  380. LoadSz(IDS_CANTCONNECT,szFmt,ARRAYSIZE(szFmt));
  381. wsprintf(szMsg,szFmt,pszComputerName,pszComputerName);
  382. MsgBoxSz(hwndOwner,szMsg,MB_OK,MB_ICONINFORMATION);
  383. }
  384. return FALSE;
  385. }
  386. //
  387. // try to connect to remote registry HKEY_CURRENT_USER
  388. //
  389. uRet = RemoteConnectHCU (hwndOwner, pszComputerName, hkeyRemoteHLM,
  390. &hkeyRemoteHCU, fDisplayError);
  391. if (!uRet) {
  392. RegCloseKey(hkeyRemoteHLM);
  393. hkeyRemoteHLM = NULL;
  394. return FALSE;
  395. }
  396. hkeyVirtHLM = hkeyRemoteHLM;
  397. hkeyVirtHCU = hkeyRemoteHCU;
  398. // change "connect..." menu item to "disconnect"
  399. ReplaceMenuItem(hwndMain,IDM_CONNECT,IDM_DISCONNECT,IDS_DISCONNECT);
  400. lstrcpy(szRemoteName,pszComputerName);
  401. return TRUE;
  402. }
  403. BOOL OnDisconnect(HWND hwndOwner)
  404. {
  405. #ifdef DEBUG
  406. OutputDebugString(TEXT("ADMINCFG: Disconnecting.\r\n"));
  407. #endif
  408. if (hkeyRemoteHLM) {
  409. RegCloseKey(hkeyRemoteHLM);
  410. hkeyRemoteHLM = NULL;
  411. }
  412. if (hkeyRemoteHCU) {
  413. RegCloseKey(hkeyRemoteHCU);
  414. hkeyRemoteHCU = NULL;
  415. }
  416. // point virtual HLM, HCU keys at local machine
  417. hkeyVirtHLM = HKEY_LOCAL_MACHINE;
  418. hkeyVirtHCU = HKEY_CURRENT_USER;
  419. // change "disconnect" menu item to "connect..."
  420. ReplaceMenuItem(hwndMain,IDM_DISCONNECT,IDM_CONNECT,IDS_CONNECT);
  421. SetTitleBar(hwndMain,NULL);
  422. return TRUE;
  423. }
  424. BOOL InitConnectDlg(HWND hDlg)
  425. {
  426. HKEY hkeyState;
  427. TCHAR szComputerName[COMPUTERNAMELEN+1];
  428. DWORD dwSize = ARRAYSIZE(szComputerName);
  429. SetFocus(GetDlgItem(hDlg,IDD_COMPUTERNAME));
  430. SendDlgItemMessage(hDlg,IDD_COMPUTERNAME,EM_SETLIMITTEXT,
  431. COMPUTERNAMELEN,0L);
  432. if (RegOpenKey(HKEY_CURRENT_USER,szAPPREGKEY,&hkeyState) ==
  433. ERROR_SUCCESS) {
  434. if (RegQueryValueEx(hkeyState,szLASTCONNECTION,NULL,NULL,szComputerName,&dwSize)
  435. ==ERROR_SUCCESS) {
  436. SetDlgItemText(hDlg,IDD_COMPUTERNAME,szComputerName);
  437. SendDlgItemMessage(hDlg,IDD_COMPUTERNAME,EM_SETSEL,0,-1);
  438. }
  439. RegCloseKey(hkeyState);
  440. }
  441. return TRUE;
  442. }
  443. //*************************************************************
  444. //
  445. // AddKEYNODE()
  446. //
  447. // Purpose: Adds a key node to the link listed
  448. //
  449. // Parameters: lpList - Link list of nodes
  450. // lpUserName - User Name
  451. //
  452. //
  453. // Return: TRUE if successful
  454. // FALSE if an error occurs
  455. //
  456. // Comments:
  457. //
  458. // History: Date Author Comment
  459. // 1/16/96 ericflo Created
  460. //
  461. //*************************************************************
  462. BOOL AddKeyNode (LPKEYNODE *lpList, LPTSTR lpUserName)
  463. {
  464. LPKEYNODE lpNewItem;
  465. if (!lpUserName || !*lpUserName) {
  466. return TRUE;
  467. }
  468. //
  469. // Setup the new node
  470. //
  471. lpNewItem = (LPKEYNODE) LocalAlloc(LPTR, sizeof(KEYNODE) +
  472. ((lstrlen(lpUserName) + 1) * sizeof(TCHAR)));
  473. if (!lpNewItem) {
  474. return FALSE;
  475. }
  476. lpNewItem->lpUserName = (LPTSTR)((LPBYTE)lpNewItem + sizeof(KEYNODE));
  477. lstrcpy (lpNewItem->lpUserName, lpUserName);
  478. lpNewItem->pNext = *lpList;
  479. *lpList = lpNewItem;
  480. return TRUE;
  481. }
  482. //*************************************************************
  483. //
  484. // FreeKeyList()
  485. //
  486. // Purpose: Free's a KEYNODE link list
  487. //
  488. // Parameters: lpList - List to be freed
  489. //
  490. // Return: TRUE if successful
  491. // FALSE if an error occurs
  492. //
  493. // Comments:
  494. //
  495. // History: Date Author Comment
  496. // 1/16/96 ericflo Created
  497. //
  498. //*************************************************************
  499. BOOL FreeKeyList (LPKEYNODE lpList)
  500. {
  501. LPKEYNODE lpNext;
  502. if (!lpList) {
  503. return TRUE;
  504. }
  505. lpNext = lpList->pNext;
  506. while (lpList) {
  507. LocalFree (lpList);
  508. lpList = lpNext;
  509. if (lpList) {
  510. lpNext = lpList->pNext;
  511. }
  512. }
  513. return TRUE;
  514. }