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.

1348 lines
46 KiB

  1. #include "stdafx.h"
  2. #include "password.h"
  3. #pragma hdrstop
  4. // class defn's used for the map net drive dialog and its helpers
  5. class CMapNetDriveMRU
  6. {
  7. public:
  8. CMapNetDriveMRU();
  9. ~CMapNetDriveMRU();
  10. BOOL IsValid() {return (NULL != m_hMRU);}
  11. BOOL FillCombo(HWND hwndCombo);
  12. BOOL AddString(LPCTSTR psz);
  13. private:
  14. static const DWORD c_nMaxMRUItems;
  15. static const TCHAR c_szMRUSubkey[];
  16. HANDLE m_hMRU;
  17. static int CompareProc(LPCTSTR lpsz1, LPCTSTR lpsz2);
  18. };
  19. class CMapNetDrivePage: public CPropertyPage
  20. {
  21. public:
  22. CMapNetDrivePage(LPCONNECTDLGSTRUCTW pConnectStruct, DWORD* pdwLastError):
  23. m_pConnectStruct(pConnectStruct), m_pdwLastError(pdwLastError)
  24. {*m_pdwLastError = WN_SUCCESS; m_szDomainUser[0] = m_szPassword[0] = TEXT('\0');}
  25. protected:
  26. // Message handlers
  27. INT_PTR DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  28. BOOL OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
  29. BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
  30. BOOL OnNotify(HWND hwnd, int idCtrl, LPNMHDR pnmh);
  31. BOOL OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem);
  32. BOOL OnDestroy(HWND hwnd);
  33. // Utility fn's
  34. void SetAdvancedLinkText(HWND hwnd);
  35. void EnableReconnect(HWND hwnd);
  36. BOOL ReadShowAdvanced();
  37. void WriteShowAdvanced(BOOL fShow);
  38. BOOL ReadReconnect();
  39. void WriteReconnect(BOOL fReconnect);
  40. void FillDriveBox(HWND hwnd);
  41. BOOL MapDrive(HWND hwnd);
  42. BOOL QueryDSForFolder(HWND hwndDlg, TCHAR* szFolderOut, DWORD cchFolderOut);
  43. private:
  44. BOOL m_fRecheckReconnect; // When (none) is selected as the drive letter, we disable reconnect; Should we reenable it when another drive letter is selected?
  45. BOOL m_fAdvancedExpanded;
  46. LPCONNECTDLGSTRUCTW m_pConnectStruct;
  47. DWORD* m_pdwLastError;
  48. // Hold results of the "connect as" dialog
  49. TCHAR m_szDomainUser[MAX_DOMAIN + MAX_USER + 2];
  50. TCHAR m_szPassword[MAX_PASSWORD + 1];
  51. // MRU list
  52. CMapNetDriveMRU m_MRU;
  53. };
  54. struct MapNetThreadData
  55. {
  56. HWND hwnd;
  57. TCHAR szDomainUser[MAX_DOMAIN + MAX_USER + 2];
  58. TCHAR szPassword[MAX_PASSWORD + 1];
  59. TCHAR szPath[MAX_PATH + 1];
  60. TCHAR szDrive[3];
  61. BOOL fReconnect;
  62. HANDLE hEventCloseNow;
  63. };
  64. class CMapNetProgress: public CDialog
  65. {
  66. public:
  67. CMapNetProgress(MapNetThreadData* pdata, DWORD* pdwDevNum, DWORD* pdwLastError):
  68. m_pdata(pdata), m_pdwDevNum(pdwDevNum), m_pdwLastError(pdwLastError)
  69. {}
  70. ~CMapNetProgress()
  71. { if (m_hEventCloseNow != NULL) CloseHandle(m_hEventCloseNow); }
  72. protected:
  73. // Message handlers
  74. INT_PTR DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  75. BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
  76. BOOL OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
  77. BOOL OnMapSuccess(HWND hwnd, DWORD dwDevNum, DWORD dwLastError);
  78. // Thread
  79. static DWORD WINAPI MapDriveThread(LPVOID pvoid);
  80. static BOOL MapDriveHelper(MapNetThreadData* pdata, DWORD* pdwDevNum, DWORD* pdwLastError);
  81. static BOOL ConfirmDisconnectDrive(HWND hWndDlg, LPCTSTR lpDrive, LPCTSTR lpShare, DWORD dwType);
  82. static BOOL ConfirmDisconnectOpenFiles(HWND hWndDlg);
  83. private:
  84. // data
  85. MapNetThreadData* m_pdata;
  86. DWORD* m_pdwDevNum;
  87. DWORD* m_pdwLastError;
  88. HANDLE m_hEventCloseNow;
  89. };
  90. class CConnectAsDlg: public CDialog
  91. {
  92. public:
  93. CConnectAsDlg(TCHAR* pszDomainUser, DWORD cchDomainUser, TCHAR* pszPassword, DWORD cchPassword):
  94. m_pszDomainUser(pszDomainUser), m_cchDomainUser(cchDomainUser), m_pszPassword(pszPassword), m_cchPassword(cchPassword)
  95. {}
  96. INT_PTR DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  97. BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
  98. BOOL OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
  99. private:
  100. TCHAR* m_pszDomainUser;
  101. DWORD m_cchDomainUser;
  102. TCHAR* m_pszPassword;
  103. DWORD m_cchPassword;
  104. };
  105. // x-position of share name in the combo box
  106. #define SHARE_NAME_PIXELS 30
  107. // Drive-related Constants
  108. #define DRIVE_NAME_STRING TEXT(" :")
  109. #define DRIVE_NAME_LENGTH ((sizeof(DRIVE_NAME_STRING) - 1) / sizeof(TCHAR))
  110. #define FIRST_DRIVE TEXT('A')
  111. #define LAST_DRIVE TEXT('Z')
  112. #define SHARE_NAME_INDEX 5 // Index of the share name in the drive string
  113. #define SELECT_DONE 0x00000001 // The highlight has been set
  114. // MPR Registry Constants
  115. #define MPR_HIVE HKEY_CURRENT_USER
  116. #define MPR_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\Persistent Connections")
  117. #define MPR_VALUE TEXT("SaveConnections")
  118. #define MPR_YES TEXT("yes")
  119. #define MPR_NO TEXT("no")
  120. const DWORD CMapNetDriveMRU::c_nMaxMRUItems = 26; // 26 is the same as the run dialog
  121. const TCHAR CMapNetDriveMRU::c_szMRUSubkey[] = TEXT("software\\microsoft\\windows\\currentversion\\explorer\\Map Network Drive MRU");
  122. CMapNetDriveMRU::CMapNetDriveMRU() : m_hMRU(NULL)
  123. {
  124. MRUINFO mruinfo;
  125. mruinfo.cbSize = sizeof (MRUINFO);
  126. mruinfo.uMax = c_nMaxMRUItems;
  127. mruinfo.fFlags = 0;
  128. mruinfo.hKey = HKEY_CURRENT_USER;
  129. mruinfo.lpszSubKey = c_szMRUSubkey;
  130. mruinfo.lpfnCompare = CompareProc;
  131. m_hMRU = CreateMRUList(&mruinfo);
  132. }
  133. BOOL CMapNetDriveMRU::FillCombo(HWND hwndCombo)
  134. {
  135. if (!m_hMRU)
  136. return FALSE;
  137. ComboBox_ResetContent(hwndCombo);
  138. int nItem = 0;
  139. TCHAR szMRUItem[MAX_PATH + 1];
  140. while (TRUE)
  141. {
  142. int nResult = EnumMRUList(m_hMRU, nItem, (LPVOID) szMRUItem, ARRAYSIZE(szMRUItem));
  143. if (-1 != nResult)
  144. {
  145. ComboBox_AddString(hwndCombo, szMRUItem); // Add the string
  146. nItem ++;
  147. }
  148. else
  149. {
  150. break; // No selection list!
  151. }
  152. }
  153. return TRUE;
  154. }
  155. BOOL CMapNetDriveMRU::AddString(LPCTSTR psz)
  156. {
  157. if (m_hMRU && (-1 != AddMRUString(m_hMRU, psz)))
  158. return TRUE;
  159. return FALSE;
  160. }
  161. CMapNetDriveMRU::~CMapNetDriveMRU()
  162. {
  163. if (m_hMRU)
  164. FreeMRUList(m_hMRU);
  165. }
  166. int CMapNetDriveMRU::CompareProc(LPCTSTR lpsz1, LPCTSTR lpsz2)
  167. {
  168. return StrCmpI(lpsz1, lpsz2);
  169. }
  170. void CMapNetDrivePage::EnableReconnect(HWND hwnd)
  171. {
  172. BOOL fEnable = !(m_pConnectStruct->dwFlags & CONNDLG_HIDE_BOX);
  173. EnableWindow(GetDlgItem(hwnd, IDC_RECONNECT), fEnable);
  174. }
  175. BOOL CMapNetDrivePage::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  176. {
  177. // Check or uncheck the "reconnect at logon" box (registry)
  178. Button_SetCheck(GetDlgItem(hwnd, IDC_RECONNECT), ReadReconnect() ? BST_CHECKED : BST_UNCHECKED);
  179. EnableReconnect(hwnd);
  180. ComboBox_LimitText(GetDlgItem(hwnd, IDC_FOLDER), MAX_PATH);
  181. // Set up the drive drop-list
  182. FillDriveBox(hwnd);
  183. // Set focus to default control
  184. return FALSE;
  185. }
  186. BOOL CMapNetDrivePage::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  187. {
  188. switch (id)
  189. {
  190. case IDC_FOLDERBROWSE:
  191. {
  192. LPITEMIDLIST pidl;
  193. // Future consideration: Need a CSIDL for computers near me to root the browse
  194. if (SHGetSpecialFolderLocation(hwnd, CSIDL_NETWORK, &pidl) == NOERROR)
  195. {
  196. TCHAR szReturnedPath[MAX_PATH];
  197. TCHAR szStartPath[MAX_PATH];
  198. TCHAR szTitle[256];
  199. // Get the path the user has typed so far; we'll try to begin
  200. // the browse at this point
  201. HWND hwndFolderEdit = GetDlgItem(hwnd, IDC_FOLDER);
  202. FetchText(hwnd, IDC_FOLDER, szStartPath, ARRAYSIZE(szStartPath));
  203. // Get the browse dialog title
  204. LoadString(g_hinst, IDS_MND_SHAREBROWSE, szTitle, ARRAYSIZE(szTitle));
  205. BROWSEINFO bi;
  206. bi.hwndOwner = hwnd;
  207. bi.pidlRoot = pidl;
  208. bi.pszDisplayName = szReturnedPath;
  209. bi.lpszTitle = szTitle;
  210. // Show old-style dialog if we're running under WOW. RAID 216120
  211. bi.ulFlags = (NULL == NtCurrentTeb()->WOW32Reserved) ? BIF_NEWDIALOGSTYLE : 0;
  212. bi.lpfn = ShareBrowseCallback;
  213. bi.lParam = (LPARAM) szStartPath;
  214. bi.iImage = 0;
  215. LPITEMIDLIST pidlReturned = SHBrowseForFolder(&bi);
  216. if (pidlReturned != NULL)
  217. {
  218. if (SUCCEEDED(SHGetTargetFolderPath(pidlReturned, szReturnedPath, ARRAYSIZE(szReturnedPath))))
  219. {
  220. SetWindowText(hwndFolderEdit, szReturnedPath);
  221. BOOL fEnableFinish = (szReturnedPath[0] != 0);
  222. PropSheet_SetWizButtons(GetParent(hwnd), fEnableFinish ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH);
  223. }
  224. ILFree(pidlReturned);
  225. }
  226. ILFree(pidl);
  227. }
  228. }
  229. return TRUE;
  230. case IDC_DRIVELETTER:
  231. if ( CBN_SELCHANGE == codeNotify )
  232. {
  233. HWND hwndCombo = GetDlgItem(hwnd, IDC_DRIVELETTER);
  234. int iItem = ComboBox_GetCurSel(hwndCombo);
  235. BOOL fNone = (BOOL)ComboBox_GetItemData(hwndCombo, iItem);
  236. HWND hwndReconnect = GetDlgItem(hwnd, IDC_RECONNECT);
  237. if (fNone)
  238. {
  239. if (IsWindowEnabled(hwndReconnect))
  240. {
  241. // going from non-none to (none) - remember if we're checked
  242. m_fRecheckReconnect = (BST_CHECKED == SendMessage(hwndReconnect, BM_GETCHECK, 0, 0));
  243. // Uncheck the box
  244. SendMessage(hwndReconnect, BM_SETCHECK, (WPARAM) BST_UNCHECKED, 0);
  245. }
  246. }
  247. else
  248. {
  249. if (!IsWindowEnabled(hwndReconnect))
  250. {
  251. SendMessage(hwndReconnect, BM_SETCHECK, (WPARAM) m_fRecheckReconnect ? BST_CHECKED : BST_UNCHECKED, 0);
  252. }
  253. }
  254. EnableWindow(GetDlgItem(hwnd, IDC_RECONNECT), !fNone);
  255. }
  256. break;
  257. case IDC_FOLDER:
  258. if ((CBN_EDITUPDATE == codeNotify) || (CBN_SELCHANGE == codeNotify))
  259. {
  260. // Enable Finish only if something is typed into the folder box
  261. TCHAR szTemp[MAX_PATH];
  262. FetchText(hwnd, IDC_FOLDER, szTemp, ARRAYSIZE(szTemp));
  263. BOOL fEnableFinish = (CBN_SELCHANGE == codeNotify) || (lstrlen(szTemp));
  264. PropSheet_SetWizButtons(GetParent(hwnd), fEnableFinish ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH);
  265. return TRUE;
  266. }
  267. break;
  268. default:
  269. break;
  270. }
  271. return FALSE;
  272. }
  273. BOOL CMapNetDrivePage::OnNotify(HWND hwnd, int idCtrl, LPNMHDR pnmh)
  274. {
  275. USES_CONVERSION;
  276. BOOL fHandled = FALSE;
  277. switch (pnmh->code)
  278. {
  279. case PSN_SETACTIVE:
  280. {
  281. m_MRU.FillCombo(GetDlgItem(hwnd, IDC_FOLDER));
  282. // A path may have been specified. If so, use it
  283. TCHAR szPath[MAX_PATH + 1];
  284. if ((m_pConnectStruct->lpConnRes != NULL) && (m_pConnectStruct->lpConnRes->lpRemoteName != NULL))
  285. {
  286. // Copy over the string into our private buffer
  287. lstrcpyn(szPath, W2T(m_pConnectStruct->lpConnRes->lpRemoteName), ARRAYSIZE(szPath));
  288. if (m_pConnectStruct->dwFlags & CONNDLG_RO_PATH)
  289. {
  290. // this is read only
  291. EnableWindow(GetDlgItem(hwnd, IDC_FOLDER), FALSE);
  292. EnableWindow(GetDlgItem(hwnd, IDC_FOLDERBROWSE), FALSE);
  293. }
  294. }
  295. else
  296. {
  297. szPath[0] = TEXT('\0');
  298. }
  299. // Set the path
  300. SetWindowText(GetDlgItem(hwnd, IDC_FOLDER), szPath);
  301. // Enable Finish only if something is typed into the folder box
  302. BOOL fEnableFinish = lstrlen(szPath);
  303. PropSheet_SetWizButtons(GetParent(hwnd), fEnableFinish ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH);
  304. }
  305. return TRUE;
  306. case PSN_QUERYINITIALFOCUS:
  307. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR) GetDlgItem(hwnd, IDC_FOLDER));
  308. return TRUE;
  309. case PSN_WIZFINISH:
  310. if (MapDrive(hwnd))
  311. {
  312. WriteReconnect(BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, IDC_RECONNECT)));
  313. // Allow wizard to exit
  314. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR) FALSE);
  315. }
  316. else
  317. {
  318. // Force wizard to stick around
  319. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR) GetDlgItem(hwnd, IDC_FOLDER));
  320. }
  321. return TRUE;
  322. case PSN_QUERYCANCEL:
  323. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); // Allow cancel
  324. *m_pdwLastError = 0xFFFFFFFF;
  325. return TRUE;
  326. case NM_CLICK:
  327. case NM_RETURN:
  328. switch (idCtrl)
  329. {
  330. case IDC_CONNECTASLINK:
  331. {
  332. CConnectAsDlg dlg(m_szDomainUser, ARRAYSIZE(m_szDomainUser), m_szPassword, ARRAYSIZE(m_szPassword));
  333. dlg.DoModal(g_hinst, MAKEINTRESOURCE(IDD_MND_CONNECTAS), hwnd);
  334. }
  335. return TRUE;
  336. case IDC_ADDPLACELINK:
  337. {
  338. // Launch the ANP wizard
  339. STARTUPINFO startupinfo = {0};
  340. startupinfo.cb = sizeof(startupinfo);
  341. TCHAR szCommandLine[] = TEXT("rundll32.exe netplwiz.dll,AddNetPlaceRunDll");
  342. PROCESS_INFORMATION process_information;
  343. if (CreateProcess(NULL, szCommandLine, NULL, NULL, 0, NULL, NULL, NULL, &startupinfo, &process_information))
  344. {
  345. CloseHandle(process_information.hProcess);
  346. CloseHandle(process_information.hThread);
  347. PropSheet_PressButton(GetParent(hwnd), PSBTN_CANCEL);
  348. }
  349. else
  350. {
  351. DisplayFormatMessage(hwnd, IDS_MAPDRIVE_CAPTION, IDS_MND_ADDPLACEERR, MB_ICONERROR | MB_OK);
  352. }
  353. }
  354. return TRUE;
  355. default:
  356. break;
  357. }
  358. break;
  359. }
  360. return FALSE;
  361. }
  362. BOOL CMapNetDrivePage::OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
  363. {
  364. // If there are no listbox items, skip this message.
  365. if (lpDrawItem->itemID == -1)
  366. return TRUE;
  367. // Draw the text for the listbox items
  368. switch (lpDrawItem->itemAction)
  369. {
  370. case ODA_SELECT:
  371. case ODA_DRAWENTIRE:
  372. {
  373. TCHAR tszDriveName[MAX_PATH + DRIVE_NAME_LENGTH + SHARE_NAME_INDEX];
  374. LPTSTR lpShare;
  375. TEXTMETRIC tm;
  376. COLORREF clrForeground;
  377. COLORREF clrBackground;
  378. DWORD dwExStyle = 0L;
  379. UINT fuETOOptions = ETO_CLIPPED;
  380. ZeroMemory(tszDriveName, sizeof(tszDriveName));
  381. // Get the text string associated with the given listbox item
  382. ComboBox_GetLBText(lpDrawItem->hwndItem, lpDrawItem->itemID, tszDriveName);
  383. // Check to see if the drive name string has a share name at
  384. // index SHARE_NAME_INDEX. If so, set lpShare to this location
  385. // and NUL-terminate the drive name.
  386. // Check for special (none) item and don't mess with the string in this case
  387. BOOL fNone = (BOOL) ComboBox_GetItemData(lpDrawItem->hwndItem, lpDrawItem->itemID);
  388. if ((*(tszDriveName + DRIVE_NAME_LENGTH) == L'\0') || fNone)
  389. {
  390. lpShare = NULL;
  391. }
  392. else
  393. {
  394. lpShare = tszDriveName + SHARE_NAME_INDEX;
  395. *(tszDriveName + DRIVE_NAME_LENGTH) = L'\0';
  396. }
  397. GetTextMetrics(lpDrawItem->hDC, &tm);
  398. clrForeground = SetTextColor(lpDrawItem->hDC,
  399. GetSysColor(lpDrawItem->itemState & ODS_SELECTED ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
  400. clrBackground = SetBkColor(lpDrawItem->hDC,
  401. GetSysColor(lpDrawItem->itemState & ODS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW));
  402. // check for RTL...
  403. dwExStyle = GetWindowLong(lpDrawItem->hwndItem, GWL_EXSTYLE);
  404. if(dwExStyle & WS_EX_RTLREADING)
  405. fuETOOptions |= ETO_RTLREADING;
  406. // Draw the text into the listbox
  407. ExtTextOut(lpDrawItem->hDC,
  408. LOWORD(GetDialogBaseUnits()) / 2,
  409. (lpDrawItem->rcItem.bottom + lpDrawItem->rcItem.top - tm.tmHeight) / 2,
  410. fuETOOptions | ETO_OPAQUE,
  411. &lpDrawItem->rcItem,
  412. tszDriveName, lstrlen(tszDriveName),
  413. NULL);
  414. // If there's a share name, draw it in a second column
  415. // at (x = SHARE_NAME_PIXELS)
  416. if (lpShare != NULL)
  417. {
  418. ExtTextOut(lpDrawItem->hDC,
  419. SHARE_NAME_PIXELS,
  420. (lpDrawItem->rcItem.bottom + lpDrawItem->rcItem.top - tm.tmHeight) / 2,
  421. fuETOOptions,
  422. &lpDrawItem->rcItem,
  423. lpShare, lstrlen(lpShare),
  424. NULL);
  425. // Restore the original string
  426. *(tszDriveName + lstrlen(DRIVE_NAME_STRING)) = TEXT(' ');
  427. }
  428. // Restore the original text and background colors
  429. SetTextColor(lpDrawItem->hDC, clrForeground);
  430. SetBkColor(lpDrawItem->hDC, clrBackground);
  431. // If the item is selected, draw the focus rectangle
  432. if (lpDrawItem->itemState & ODS_SELECTED)
  433. {
  434. DrawFocusRect(lpDrawItem->hDC, &lpDrawItem->rcItem);
  435. }
  436. break;
  437. }
  438. }
  439. return TRUE;
  440. }
  441. INT_PTR CMapNetDrivePage::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  442. {
  443. switch (uMsg)
  444. {
  445. HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog);
  446. HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
  447. HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify);
  448. HANDLE_MSG(hwnd, WM_DRAWITEM, OnDrawItem);
  449. }
  450. return FALSE;
  451. }
  452. // "Reconnect check" registry setting
  453. BOOL CMapNetDrivePage::ReadReconnect()
  454. {
  455. BOOL fReconnect = TRUE;
  456. if (m_pConnectStruct->dwFlags & CONNDLG_PERSIST)
  457. {
  458. fReconnect = TRUE;
  459. }
  460. else if (m_pConnectStruct->dwFlags & CONNDLG_NOT_PERSIST)
  461. {
  462. fReconnect = FALSE;
  463. }
  464. else
  465. {
  466. // User didn't specify -- check the registry.
  467. HKEY hkeyMPR;
  468. if (ERROR_SUCCESS == RegOpenKeyEx(MPR_HIVE, MPR_KEY, 0, KEY_READ, &hkeyMPR))
  469. {
  470. DWORD dwType;
  471. TCHAR szAnswer[ARRAYSIZE(MPR_YES) + ARRAYSIZE(MPR_NO)];
  472. DWORD cbSize = sizeof(szAnswer);
  473. if (ERROR_SUCCESS == RegQueryValueEx(hkeyMPR, MPR_VALUE, NULL,
  474. &dwType, (BYTE*) szAnswer, &cbSize))
  475. {
  476. fReconnect = (StrCmpI(szAnswer, (const TCHAR *) MPR_YES) == 0);
  477. }
  478. RegCloseKey(hkeyMPR);
  479. }
  480. }
  481. return fReconnect;
  482. }
  483. void CMapNetDrivePage::WriteReconnect(BOOL fReconnect)
  484. {
  485. // Don't write to the registry if the user didn't have a choice about reconnect
  486. if (!(m_pConnectStruct->dwFlags & CONNDLG_HIDE_BOX))
  487. {
  488. HKEY hkeyMPR;
  489. DWORD dwDisp;
  490. // User didn't specify -- check the registry.
  491. if (ERROR_SUCCESS == RegCreateKeyEx(MPR_HIVE, MPR_KEY, 0, NULL, 0, KEY_WRITE, NULL,
  492. &hkeyMPR, &dwDisp))
  493. {
  494. LPTSTR pszNewValue = (fReconnect ? MPR_YES : MPR_NO);
  495. RegSetValueEx(hkeyMPR, MPR_VALUE, NULL,
  496. REG_SZ, (BYTE*) pszNewValue, (lstrlen(pszNewValue) + 1) * sizeof (TCHAR));
  497. RegCloseKey(hkeyMPR);
  498. }
  499. }
  500. }
  501. // This routine fills the drive letter drop-down list with all
  502. // of the drive names and, if appropriate, the name of the share to which
  503. // the drive is already connected
  504. void CMapNetDrivePage::FillDriveBox(HWND hwnd)
  505. {
  506. HWND hWndCombo = GetDlgItem(hwnd, IDC_DRIVELETTER);
  507. DWORD dwFlags = 0;
  508. DWORD dwBufferLength = MAX_PATH - 1;
  509. TCHAR szDriveName[SHARE_NAME_INDEX + MAX_PATH];
  510. TCHAR szShareName[MAX_PATH - DRIVE_NAME_LENGTH];
  511. ZeroMemory(szDriveName, sizeof(szDriveName));
  512. ZeroMemory(szShareName, sizeof(szShareName));
  513. // lpDriveName looks like this: "<space>:<null>"
  514. lstrcpyn(szDriveName, DRIVE_NAME_STRING, ARRAYSIZE(szDriveName));
  515. // lpDriveName looks like this:
  516. // "<space>:<null><spaces until index SHARE_NAME_INDEX>"
  517. for (UINT i = DRIVE_NAME_LENGTH + 1; i < SHARE_NAME_INDEX; i++)
  518. {
  519. szDriveName[i] = L' ';
  520. }
  521. for (TCHAR cDriveLetter = LAST_DRIVE; cDriveLetter >= FIRST_DRIVE; cDriveLetter--)
  522. {
  523. // lpDriveName looks like this: "<drive>:<null><lots of spaces>"
  524. szDriveName[0] = cDriveLetter;
  525. UINT uDriveType = GetDriveType(szDriveName);
  526. // NoRootDir == usually available, but may be mounted to a network drive that currently isn't
  527. // available - check for this!
  528. if (DRIVE_NO_ROOT_DIR == uDriveType)
  529. {
  530. if (ERROR_CONNECTION_UNAVAIL == WNetGetConnection(szDriveName, szShareName, &dwBufferLength))
  531. {
  532. // Pretend its a remote drive
  533. uDriveType = DRIVE_REMOTE;
  534. dwBufferLength = MAX_PATH - DRIVE_NAME_LENGTH - 1;
  535. }
  536. }
  537. // Removable == floppy drives, Fixed == hard disk, CDROM == obvious :),
  538. // Remote == network drive already attached to a share
  539. switch (uDriveType)
  540. {
  541. case DRIVE_REMOVABLE:
  542. case DRIVE_FIXED:
  543. case DRIVE_CDROM:
  544. // These types of drives can't be mapped
  545. break;
  546. case DRIVE_REMOTE:
  547. {
  548. UINT i;
  549. // Reset the share buffer length (it
  550. // gets overwritten by WNetGetConnection)
  551. dwBufferLength = MAX_PATH - DRIVE_NAME_LENGTH - 1;
  552. // Retrieve "\\server\share" for current drive
  553. DWORD dwRes = WNetGetConnection(szDriveName, szShareName, &dwBufferLength);
  554. if ((dwRes == NO_ERROR) || (dwRes == ERROR_CONNECTION_UNAVAIL))
  555. {
  556. // lpDriveName looks like this:
  557. // "<drive>:<spaces until SHARE_NAME_INDEX><share name><null>"
  558. szDriveName[DRIVE_NAME_LENGTH] = L' ';
  559. lstrcpyn(szDriveName + SHARE_NAME_INDEX, szShareName, (MAX_PATH - DRIVE_NAME_LENGTH - 1));
  560. // Store a FALSE into the item data for all items except the
  561. // special (none) item
  562. int iItem = ComboBox_AddString(hWndCombo, szDriveName);
  563. ComboBox_SetItemData(hWndCombo, iItem, (LPARAM) FALSE);
  564. // Reset the drive name to "<drive>:<null><lots of spaces>"
  565. szDriveName[DRIVE_NAME_LENGTH] = L'\0';
  566. for (i = DRIVE_NAME_LENGTH + 1; i < MAX_PATH + SHARE_NAME_INDEX; i++)
  567. {
  568. *(szDriveName + i) = L' ';
  569. }
  570. break;
  571. }
  572. else
  573. {
  574. // If there's an error with this drive, ignore the drive
  575. // and skip to the next one. Note that dwBufferLength will
  576. // only be changed if lpShareName contains MAX_PATH or more
  577. // characters, which shouldn't ever happen. For release,
  578. // however, keep on limping along.
  579. dwBufferLength = MAX_PATH - DRIVE_NAME_LENGTH - 1;
  580. break;
  581. }
  582. }
  583. default:
  584. {
  585. // The drive is not already connected to a share
  586. // Suggest the first available and unconnected
  587. // drive past the C drive
  588. DWORD dwIndex = ComboBox_AddString(hWndCombo, szDriveName);
  589. if (!(dwFlags & SELECT_DONE))
  590. {
  591. ComboBox_SetCurSel(hWndCombo, dwIndex);
  592. dwFlags |= SELECT_DONE;
  593. }
  594. break;
  595. }
  596. }
  597. }
  598. // Add one more item - a special (none) item that if selected causes
  599. // a deviceless connection to be created.
  600. LoadString(g_hinst, IDS_NONE, szDriveName, ARRAYSIZE(szDriveName));
  601. int iItem = ComboBox_AddString(hWndCombo, szDriveName);
  602. ComboBox_SetItemData(hWndCombo, iItem, (LPARAM) TRUE);
  603. // If there is no selection at this point, just select (none) item
  604. // This will happen when all drive letters are mapped
  605. if (ComboBox_GetCurSel(hWndCombo) == CB_ERR)
  606. {
  607. ComboBox_SetCurSel(hWndCombo, iItem);
  608. }
  609. }
  610. BOOL CMapNetDrivePage::MapDrive(HWND hwnd)
  611. {
  612. BOOL fMapWorked = FALSE;
  613. HWND hwndCombo = GetDlgItem(hwnd, IDC_DRIVELETTER);
  614. int iItem = ComboBox_GetCurSel(hwndCombo);
  615. // Get this item's text and itemdata (to check if its the special (none) drive)
  616. BOOL fNone = (BOOL) ComboBox_GetItemData(hwndCombo, iItem);
  617. // Fill in the big structure that maps a drive
  618. MapNetThreadData* pdata = new MapNetThreadData;
  619. if (pdata != NULL)
  620. {
  621. // Set reconnect
  622. pdata->fReconnect = (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, IDC_RECONNECT)));
  623. // Set the drive
  624. if (fNone)
  625. {
  626. pdata->szDrive[0] = TEXT('\0');
  627. }
  628. else
  629. {
  630. ComboBox_GetText(hwndCombo, pdata->szDrive, 3);
  631. }
  632. // Set the net share
  633. FetchText(hwnd, IDC_FOLDER, pdata->szPath, ARRAYSIZE(pdata->szPath));
  634. PathRemoveBackslash(pdata->szPath);
  635. // Get an alternate username/password/domain if required
  636. // Domain/username
  637. lstrcpyn(pdata->szDomainUser, m_szDomainUser, ARRAYSIZE(pdata->szDomainUser));
  638. // Password
  639. lstrcpyn(pdata->szPassword, m_szPassword, ARRAYSIZE(pdata->szPassword));
  640. CMapNetProgress dlg(pdata, &m_pConnectStruct->dwDevNum, m_pdwLastError);
  641. // On IDOK == Close dialog!
  642. fMapWorked = (IDOK == dlg.DoModal(g_hinst, MAKEINTRESOURCE(IDD_MND_PROGRESS_DLG), hwnd));
  643. }
  644. if (fMapWorked)
  645. {
  646. TCHAR szPath[MAX_PATH + 1];
  647. FetchText(hwnd, IDC_FOLDER, szPath, ARRAYSIZE(szPath));
  648. m_MRU.AddString(szPath);
  649. // If a drive letter wasn't assigned, open a window on the new drive now
  650. if (fNone)
  651. {
  652. // Use shellexecuteex to open a view folder
  653. SHELLEXECUTEINFO shexinfo = {0};
  654. shexinfo.cbSize = sizeof (shexinfo);
  655. shexinfo.fMask = SEE_MASK_FLAG_NO_UI;
  656. shexinfo.nShow = SW_SHOWNORMAL;
  657. shexinfo.lpFile = szPath;
  658. shexinfo.lpVerb = TEXT("open");
  659. ShellExecuteEx(&shexinfo);
  660. }
  661. }
  662. return fMapWorked;
  663. }
  664. // Little progress dialog implementation
  665. // Private message for thread to signal dialog if successful
  666. // (DWORD) (WPARAM) dwDevNum - 0-based device number connected to (0xFFFFFFFF for none)
  667. // (DWORD) (LPARAM) dwRetVal - Return value
  668. #define WM_MAPFINISH (WM_USER + 100)
  669. INT_PTR CMapNetProgress::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  670. {
  671. switch (uMsg)
  672. {
  673. HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog);
  674. HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
  675. case WM_MAPFINISH: return OnMapSuccess(hwnd, (DWORD) wParam, (DWORD) lParam);
  676. }
  677. return FALSE;
  678. }
  679. BOOL CMapNetProgress::OnMapSuccess(HWND hwnd, DWORD dwDevNum, DWORD dwLastError)
  680. {
  681. *m_pdwDevNum = dwDevNum;
  682. *m_pdwLastError = dwLastError;
  683. EndDialog(hwnd, ((dwLastError == WN_SUCCESS) ? IDOK : IDCANCEL));
  684. return TRUE;
  685. }
  686. BOOL CMapNetProgress::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  687. {
  688. HANDLE hThread = NULL;
  689. // Set the progress dialog text
  690. TCHAR szText[256];
  691. FormatMessageString(IDS_MND_PROGRESS, szText, ARRAYSIZE(szText), m_pdata->szPath);
  692. SetWindowText(GetDlgItem(hwnd, IDC_CONNECTING), szText);
  693. // We'll signal this guy when the thread should close down
  694. static const TCHAR EVENT_NAME[] = TEXT("Thread Close Event");
  695. m_hEventCloseNow = CreateEvent(NULL, TRUE, FALSE, EVENT_NAME);
  696. m_pdata->hEventCloseNow = NULL;
  697. if (m_hEventCloseNow != NULL)
  698. {
  699. // Get a copy of this puppy for the thread
  700. m_pdata->hEventCloseNow = OpenEvent(SYNCHRONIZE, FALSE, EVENT_NAME);
  701. if (m_pdata->hEventCloseNow != NULL)
  702. {
  703. m_pdata->hwnd = hwnd;
  704. // All we have to do is start up the worker thread, who will dutifully report back to us
  705. DWORD dwId;
  706. hThread = CreateThread(NULL, 0, CMapNetProgress::MapDriveThread, (LPVOID) m_pdata, 0, &dwId);
  707. }
  708. }
  709. // Abandon the poor little guy (he'll be ok)
  710. if (hThread != NULL)
  711. {
  712. CloseHandle(hThread);
  713. /* TAKE SPECIAL CARE
  714. At this point the thread owns m_pdata! Don't access it any more except on the thread.
  715. It may be deleted at any time! */
  716. m_pdata = NULL;
  717. }
  718. else
  719. {
  720. // Usually the thread would do this
  721. if (m_pdata->hEventCloseNow != NULL)
  722. {
  723. CloseHandle(m_pdata->hEventCloseNow);
  724. }
  725. delete m_pdata;
  726. // We just failed to create a thread. The computer must be near out of
  727. // resources.
  728. EndDialog(hwnd, IDCANCEL);
  729. }
  730. return FALSE;
  731. }
  732. BOOL CMapNetProgress::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  733. {
  734. if (id == IDCANCEL)
  735. {
  736. SetEvent(m_hEventCloseNow); // Tell the thread to quit
  737. EndDialog(hwnd, id);
  738. }
  739. return FALSE;
  740. }
  741. DWORD CMapNetProgress::MapDriveThread(LPVOID pvoid)
  742. {
  743. MapNetThreadData* pdata = (MapNetThreadData*) pvoid;
  744. DWORD dwDevNum;
  745. DWORD dwLastError;
  746. BOOL fSuccess = MapDriveHelper(pdata, &dwDevNum, &dwLastError);
  747. if (WAIT_OBJECT_0 == WaitForSingleObject(pdata->hEventCloseNow, 0))
  748. {
  749. // The user clicked cancel, don't call back to the progress wnd
  750. }
  751. else
  752. {
  753. PostMessage(pdata->hwnd, WM_MAPFINISH, (WPARAM) dwDevNum,
  754. (LPARAM) dwLastError);
  755. }
  756. CloseHandle(pdata->hEventCloseNow);
  757. delete pdata;
  758. return 0;
  759. }
  760. BOOL CMapNetProgress::MapDriveHelper(MapNetThreadData* pdata, DWORD* pdwDevNum, DWORD* pdwLastError)
  761. {
  762. NETRESOURCE nrResource = {0};
  763. LPTSTR lpMessage = NULL;
  764. *pdwDevNum = 0;
  765. //
  766. // Fill in the NETRESOURCE structure -- the local name is the drive and
  767. // the remote name is \\server\share (stored in the global buffer).
  768. // The provider is NULL to let NT find the provider on its own.
  769. //
  770. nrResource.dwType = RESOURCETYPE_DISK;
  771. nrResource.lpLocalName = pdata->szDrive[0] == TEXT('\0') ? NULL : pdata->szDrive;
  772. nrResource.lpRemoteName = pdata->szPath;
  773. nrResource.lpProvider = NULL;
  774. BOOL fRetry = TRUE;
  775. while (fRetry)
  776. {
  777. *pdwLastError = WNetAddConnection3(pdata->hwnd, &nrResource,
  778. pdata->szDomainUser[0] == TEXT('\0') ? NULL : pdata->szPassword,
  779. pdata->szDomainUser[0] == TEXT('\0') ? NULL : pdata->szDomainUser,
  780. pdata->fReconnect ? CONNECT_INTERACTIVE | CONNECT_UPDATE_PROFILE : CONNECT_INTERACTIVE);
  781. // Don't display anything if we're supposed to quit
  782. if (WAIT_OBJECT_0 == WaitForSingleObject(pdata->hEventCloseNow, 0))
  783. {
  784. // We should quit (quietly exit if we just failed)!
  785. if (*pdwLastError != NO_ERROR)
  786. {
  787. *pdwLastError = RETCODE_CANCEL;
  788. fRetry = FALSE;
  789. }
  790. }
  791. else
  792. {
  793. fRetry = FALSE;
  794. switch (*pdwLastError)
  795. {
  796. case NO_ERROR:
  797. {
  798. // Put the number of the connection into dwDevNum, where
  799. // drive A is 1, B is 2, ... Note that a deviceless connection
  800. // is 0xFFFFFFFF
  801. if (pdata->szDrive[0] == TEXT('\0'))
  802. {
  803. *pdwDevNum = 0xFFFFFFFF;
  804. }
  805. else
  806. {
  807. *pdwDevNum = *pdata->szDrive - FIRST_DRIVE + 1;
  808. }
  809. *pdwLastError = WN_SUCCESS;
  810. }
  811. break;
  812. //
  813. // The user cancelled the password dialog or cancelled the
  814. // connection through a different dialog
  815. //
  816. case ERROR_CANCELLED:
  817. {
  818. *pdwLastError = RETCODE_CANCEL;
  819. }
  820. break;
  821. //
  822. // An error involving the user's password/credentials occurred, so
  823. // bring up the password prompt. - Only works for WINNT
  824. //
  825. case ERROR_ACCESS_DENIED:
  826. case ERROR_CANNOT_OPEN_PROFILE:
  827. case ERROR_INVALID_PASSWORD:
  828. case ERROR_LOGON_FAILURE:
  829. case ERROR_BAD_USERNAME:
  830. {
  831. CPasswordDialog dlg(pdata->szPath, pdata->szDomainUser, ARRAYSIZE(pdata->szDomainUser),
  832. pdata->szPassword, ARRAYSIZE(pdata->szPassword), *pdwLastError);
  833. if (IDOK == dlg.DoModal(g_hinst, MAKEINTRESOURCE(IDD_WIZ_NETPASSWORD),
  834. pdata->hwnd))
  835. {
  836. fRetry = TRUE;
  837. }
  838. }
  839. break;
  840. // There's an existing/remembered connection to this drive
  841. case ERROR_ALREADY_ASSIGNED:
  842. case ERROR_DEVICE_ALREADY_REMEMBERED:
  843. // See if the user wants us to break the connection
  844. if (ConfirmDisconnectDrive(pdata->hwnd,
  845. pdata->szDrive,
  846. pdata->szPath,
  847. *pdwLastError))
  848. {
  849. // Break the connection, but don't force it
  850. // if there are open files
  851. *pdwLastError = WNetCancelConnection2(pdata->szDrive,
  852. CONNECT_UPDATE_PROFILE,
  853. FALSE);
  854. if (*pdwLastError == ERROR_OPEN_FILES ||
  855. *pdwLastError == ERROR_DEVICE_IN_USE)
  856. {
  857. // See if the user wants to force the disconnection
  858. if (ConfirmDisconnectOpenFiles(pdata->hwnd))
  859. {
  860. // Roger 1-9er -- we have confirmation,
  861. // so force the disconnection.
  862. *pdwLastError = WNetCancelConnection2(pdata->szDrive,
  863. CONNECT_UPDATE_PROFILE,
  864. TRUE);
  865. if (*pdwLastError == NO_ERROR)
  866. {
  867. fRetry = TRUE;
  868. }
  869. else
  870. {
  871. DisplayFormatMessage(pdata->hwnd, IDS_MAPDRIVE_CAPTION, IDS_CANTCLOSEFILES_WARNING,
  872. MB_OK | MB_ICONERROR);
  873. }
  874. }
  875. }
  876. else
  877. {
  878. fRetry = TRUE;
  879. }
  880. }
  881. break;
  882. // Errors caused by an invalid remote path
  883. case ERROR_BAD_DEV_TYPE:
  884. case ERROR_BAD_NET_NAME:
  885. case ERROR_BAD_NETPATH:
  886. {
  887. DisplayFormatMessage(pdata->hwnd, IDS_ERR_CAPTION, IDS_ERR_INVALIDREMOTEPATH,
  888. MB_OK | MB_ICONERROR, pdata->szPath);
  889. }
  890. break;
  891. // Provider is busy (e.g., initializing), so user should retry
  892. case ERROR_BUSY:
  893. {
  894. DisplayFormatMessage(pdata->hwnd, IDS_ERR_CAPTION, IDS_ERR_INVALIDREMOTEPATH,
  895. MB_OK | MB_ICONERROR);
  896. }
  897. break;
  898. //
  899. // Network problems
  900. //
  901. case ERROR_NO_NET_OR_BAD_PATH:
  902. case ERROR_NO_NETWORK:
  903. {
  904. DisplayFormatMessage(pdata->hwnd, IDS_ERR_CAPTION, IDS_ERR_NONETWORK,
  905. MB_OK | MB_ICONERROR);
  906. }
  907. break;
  908. // Share already mapped with different credentials
  909. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  910. {
  911. DisplayFormatMessage(pdata->hwnd, IDS_ERR_CAPTION,
  912. IDS_MND_ALREADYMAPPED, MB_OK | MB_ICONERROR);
  913. }
  914. //
  915. // Errors that we (in theory) shouldn't get -- bad local name
  916. // (i.e., format of drive name is invalid), user profile in a bad
  917. // format, or a bad provider. Problems here most likely indicate
  918. // an NT system bug. Also note that provider-specific errors
  919. // (ERROR_EXTENDED_ERROR) and trust failures are lumped in here
  920. // as well, since the below errors will display an "Unexpected
  921. // Error" message to the user.
  922. //
  923. case ERROR_BAD_DEVICE:
  924. case ERROR_BAD_PROFILE:
  925. case ERROR_BAD_PROVIDER:
  926. default:
  927. {
  928. TCHAR szMessage[512];
  929. if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) *pdwLastError, 0, szMessage, ARRAYSIZE(szMessage), NULL))
  930. LoadString(g_hinst, IDS_ERR_UNEXPECTED, szMessage, ARRAYSIZE(szMessage));
  931. ::DisplayFormatMessage(pdata->hwnd, IDS_ERR_CAPTION, IDS_MND_GENERICERROR, MB_OK|MB_ICONERROR, szMessage);
  932. }
  933. break;
  934. }
  935. }
  936. }
  937. return (*pdwLastError == NO_ERROR);
  938. }
  939. /*++
  940. Routine Description:
  941. This routine verifies that the user wants to break a pre-existing
  942. connection to a drive.
  943. Arguments:
  944. hWndDlg -- HWND of the Completion page
  945. lpDrive -- The name of the drive to disconnect
  946. lpShare -- The share to which the "freed" drive will be connected
  947. dwType -- The connection error -- ERROR_ALREADY_ASSIGNED
  948. or ERROR_DEVICE_ALREADY_REMEMBERED
  949. Return Value:
  950. TRUE if the user wants to break the connection, FALSE otherwise
  951. --*/
  952. BOOL CMapNetProgress::ConfirmDisconnectDrive(HWND hWndDlg, LPCTSTR lpDrive, LPCTSTR lpShare, DWORD dwType)
  953. {
  954. TCHAR tszConfirmMessage[2 * MAX_PATH + MAX_STATIC] = {0};
  955. TCHAR tszCaption[MAX_CAPTION + 1] = {0};
  956. TCHAR tszConnection[MAX_PATH + 1] = {0};
  957. DWORD dwLength = MAX_PATH;
  958. LoadString(g_hinst, IDS_ERR_CAPTION, tszCaption, ARRAYSIZE(tszCaption));
  959. //
  960. // Bug #143955 -- call WNetGetConnection here since with two instances of
  961. // the wizard open and on the Completion page with the same suggested
  962. // drive, the Completion combo box doesn't contain info about the connected
  963. // share once "Finish" is selected on one of the two wizards.
  964. //
  965. DWORD dwRes = WNetGetConnection(lpDrive, tszConnection, &dwLength);
  966. if ((NO_ERROR == dwRes) || (ERROR_CONNECTION_UNAVAIL == dwRes))
  967. {
  968. //
  969. // Load the appropriate propmt string, based on the type of
  970. // error we encountered
  971. //
  972. FormatMessageString((dwType == ERROR_ALREADY_ASSIGNED ? IDS_ERR_ALREADYASSIGNED : IDS_ERR_ALREADYREMEMBERED),
  973. tszConfirmMessage, ARRAYSIZE(tszConfirmMessage), lpDrive, tszConnection, lpShare);
  974. return (MessageBox(hWndDlg, tszConfirmMessage, tszCaption, MB_YESNO | MB_ICONWARNING)
  975. == IDYES);
  976. }
  977. else
  978. {
  979. // The connection was invalid. Don't overwrite it just in case
  980. return FALSE;
  981. }
  982. }
  983. /*++
  984. Routine Description:
  985. This routine verifies that the user wants to break a pre-existing
  986. connection to a drive where the user has open files/connections
  987. Arguments:
  988. hWndDlg -- HWND of the Completion dialog
  989. Return Value:
  990. TRUE if the user wants to break the connection, FALSE otherwise
  991. --*/
  992. BOOL CMapNetProgress::ConfirmDisconnectOpenFiles(HWND hWndDlg)
  993. {
  994. TCHAR tszCaption[MAX_CAPTION + 1] = {0};
  995. TCHAR tszBuffer[MAX_STATIC + 1] = {0};
  996. LoadString(g_hinst, IDS_ERR_OPENFILES, tszBuffer, ARRAYSIZE(tszBuffer));
  997. LoadString(g_hinst, IDS_ERR_CAPTION, tszCaption, ARRAYSIZE(tszCaption));
  998. return (MessageBox(hWndDlg, tszBuffer, tszCaption, MB_YESNO | MB_ICONWARNING) == IDYES);
  999. }
  1000. // CConnectAsDlg Implementation - Windows NT only
  1001. // ----------------------------------------------
  1002. // Little "username and password" dialog for connecting as a different user - NT only
  1003. INT_PTR CConnectAsDlg::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1004. {
  1005. switch(uMsg)
  1006. {
  1007. HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog);
  1008. HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
  1009. }
  1010. return FALSE;
  1011. }
  1012. BOOL CConnectAsDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  1013. {
  1014. // Fill in the user name and password
  1015. HWND hwndCredential = GetDlgItem(hwnd, IDC_CREDENTIALS);
  1016. SendMessage(hwndCredential, CRM_SETUSERNAME, NULL, (LPARAM) m_pszDomainUser);
  1017. SendMessage(hwndCredential, CRM_SETPASSWORD, NULL, (LPARAM) m_pszPassword);
  1018. SendMessage(hwndCredential, CRM_SETUSERNAMEMAX, m_cchDomainUser - 1, NULL);
  1019. SendMessage(hwndCredential, CRM_SETPASSWORDMAX, m_cchPassword - 1, NULL);
  1020. TCHAR szUser[MAX_USER + 1];
  1021. TCHAR szDomain[MAX_DOMAIN + 1];
  1022. TCHAR szDomainUser[MAX_USER + MAX_DOMAIN + 2];
  1023. DWORD cchUser = ARRAYSIZE(szUser);
  1024. DWORD cchDomain = ARRAYSIZE(szDomain);
  1025. ::GetCurrentUserAndDomainName(szUser, &cchUser, szDomain, &cchDomain);
  1026. ::MakeDomainUserString(szDomain, szUser, szDomainUser, ARRAYSIZE(szDomainUser));
  1027. TCHAR szMessage[256];
  1028. FormatMessageString(IDS_CONNECTASUSER, szMessage, ARRAYSIZE(szMessage), szDomainUser);
  1029. SetWindowText(GetDlgItem(hwnd, IDC_MESSAGE), szMessage);
  1030. if (!IsComputerInDomain())
  1031. EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE);
  1032. return FALSE;
  1033. }
  1034. BOOL CConnectAsDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1035. {
  1036. switch (id)
  1037. {
  1038. case IDC_BROWSE:
  1039. {
  1040. // User wants to look up a username
  1041. TCHAR szUser[MAX_USER + 1];
  1042. TCHAR szDomain[MAX_DOMAIN + 1];
  1043. if (S_OK == ::BrowseForUser(hwnd, szUser, ARRAYSIZE(szUser),
  1044. szDomain, ARRAYSIZE(szDomain)))
  1045. {
  1046. TCHAR szDomainUser[MAX_USER + MAX_DOMAIN + 2];
  1047. ::MakeDomainUserString(szDomain, szUser, szDomainUser,
  1048. ARRAYSIZE(szDomainUser));
  1049. // Ok clicked and buffers valid
  1050. SendDlgItemMessage(hwnd, IDC_CREDENTIALS, CRM_SETUSERNAME, NULL, (LPARAM) szDomainUser);
  1051. }
  1052. }
  1053. return TRUE;
  1054. case IDOK:
  1055. // TODO: Figure out about the -1 thing here...
  1056. SendDlgItemMessage(hwnd, IDC_CREDENTIALS, CRM_GETUSERNAME, (WPARAM) m_cchDomainUser - 1, (LPARAM) m_pszDomainUser);
  1057. SendDlgItemMessage(hwnd, IDC_CREDENTIALS, CRM_GETPASSWORD, (WPARAM) m_cchPassword - 1, (LPARAM) m_pszPassword);
  1058. // fall through
  1059. case IDCANCEL:
  1060. EndDialog(hwnd, id);
  1061. return TRUE;
  1062. }
  1063. return FALSE;
  1064. }
  1065. // ----------------------------------------------
  1066. // This function creates the Shared Folder Wizard.
  1067. // Return Value:
  1068. // Returns WN_SUCCESS if the drive connected with no problem or
  1069. // RETCODE_CANCEL (0xFFFFFFFF) if the user cancels the Wizard or there
  1070. // is an unexplained/unrecoverable error
  1071. STDAPI_(DWORD) NetPlacesWizardDoModal(CONNECTDLGSTRUCTW *pConnDlgStruct, NETPLACESWIZARDTYPE npwt, BOOL fIsROPath)
  1072. {
  1073. DWORD dwReturn = RETCODE_CANCEL;
  1074. HRESULT hrInit = SHCoInitialize();
  1075. if (SUCCEEDED(hrInit))
  1076. {
  1077. INITCOMMONCONTROLSEX iccex = {0};
  1078. iccex.dwSize = sizeof (iccex);
  1079. iccex.dwICC = ICC_LISTVIEW_CLASSES;
  1080. InitCommonControlsEx(&iccex);
  1081. CredUIInitControls();
  1082. LinkWindow_RegisterClass();
  1083. // See if we're already running
  1084. TCHAR szCaption[256];
  1085. LoadString(g_hinst, IDS_MAPDRIVE_CAPTION, szCaption, ARRAYSIZE(szCaption));
  1086. CEnsureSingleInstance ESI(szCaption);
  1087. if (!ESI.ShouldExit())
  1088. {
  1089. CMapNetDrivePage page(pConnDlgStruct, &dwReturn);
  1090. PROPSHEETPAGE psp = {0};
  1091. psp.dwSize = sizeof(PROPSHEETPAGE);
  1092. psp.hInstance = g_hinst;
  1093. psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
  1094. psp.pszTemplate = MAKEINTRESOURCE(IDD_MND_PAGE);
  1095. page.SetPropSheetPageMembers(&psp);
  1096. HPROPSHEETPAGE hpage = CreatePropertySheetPage(&psp);
  1097. PROPSHEETHEADER psh = {0};
  1098. psh.dwSize = sizeof(PROPSHEETHEADER);
  1099. psh.dwFlags = PSH_NOCONTEXTHELP | PSH_WIZARD | PSH_WIZARD_LITE | PSH_NOAPPLYNOW;
  1100. psh.pszCaption = szCaption;
  1101. psh.hwndParent = pConnDlgStruct->hwndOwner;
  1102. psh.nPages = 1;
  1103. psh.nStartPage = 0;
  1104. psh.phpage = &hpage;
  1105. PropertySheetIcon(&psh, MAKEINTRESOURCE(IDI_PSW));
  1106. }
  1107. SHCoUninitialize(hrInit);
  1108. }
  1109. return dwReturn;
  1110. }