Leaked source code of windows server 2003
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.

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