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.

928 lines
27 KiB

  1. #include "stdafx.h"
  2. #include <objsel.h> // Object picker
  3. #include <dsrole.h>
  4. #include "icwcfg.h"
  5. #pragma hdrstop
  6. // Wait cursor object
  7. CWaitCursor::CWaitCursor() :
  8. _hCursor(NULL)
  9. {
  10. WaitCursor();
  11. }
  12. CWaitCursor::~CWaitCursor()
  13. {
  14. RestoreCursor();
  15. }
  16. void CWaitCursor::WaitCursor()
  17. {
  18. _hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  19. }
  20. void CWaitCursor::RestoreCursor()
  21. {
  22. if (_hCursor)
  23. {
  24. SetCursor(_hCursor);
  25. _hCursor = NULL;
  26. }
  27. }
  28. HRESULT BrowseToPidl(LPCITEMIDLIST pidl)
  29. {
  30. HRESULT hr;
  31. // Use shellexecuteex to open a view on the pidl
  32. SHELLEXECUTEINFO shexinfo = {0};
  33. shexinfo.cbSize = sizeof (shexinfo);
  34. shexinfo.fMask = SEE_MASK_IDLIST | SEE_MASK_FLAG_NO_UI;
  35. shexinfo.nShow = SW_SHOWNORMAL;
  36. shexinfo.lpIDList = (void*) pidl;
  37. shexinfo.lpVerb = TEXT("open");
  38. hr = ShellExecuteEx(&shexinfo) ? S_OK : E_FAIL;
  39. return hr;
  40. }
  41. void FetchText(HWND hWndDlg, UINT uID, LPTSTR lpBuffer, DWORD dwMaxSize)
  42. {
  43. TCHAR* pszTemp;
  44. LPTSTR pszString;
  45. *lpBuffer = L'\0';
  46. HWND hwndCtl = GetDlgItem(hWndDlg, uID);
  47. if (hwndCtl)
  48. {
  49. int iSize = GetWindowTextLength(hwndCtl);
  50. pszTemp = new TCHAR[iSize + 1];
  51. if (pszTemp)
  52. {
  53. GetWindowText(hwndCtl, pszTemp, iSize + 1);
  54. for (pszString = pszTemp ; *pszString && (*pszString == L' ') ; )
  55. pszString = CharNext(pszString);
  56. if (*pszString )
  57. {
  58. lstrcpyn(lpBuffer, pszString, dwMaxSize);
  59. pszString = lpBuffer+(lstrlen(lpBuffer)-1);
  60. while ( (pszString > lpBuffer) && (*pszString == L' ') )
  61. pszString--;
  62. pszString = CharNext(pszString);
  63. *pszString = L'\0';
  64. }
  65. delete [] pszTemp;
  66. }
  67. }
  68. }
  69. INT FetchTextLength(HWND hWndDlg, UINT uID)
  70. {
  71. TCHAR szBuffer[MAX_PATH];
  72. FetchText(hWndDlg, uID, szBuffer, ARRAYSIZE(szBuffer));
  73. return lstrlen(szBuffer);
  74. }
  75. HRESULT AttemptLookupAccountName(LPCTSTR szUsername, PSID* ppsid,
  76. LPTSTR szDomain, DWORD* pcchDomain, SID_NAME_USE* psUse)
  77. {
  78. HRESULT hr = S_OK;
  79. // First try to find required size of SID
  80. DWORD cbSid = 0;
  81. DWORD cchDomain = *pcchDomain;
  82. BOOL fSuccess = LookupAccountName(NULL, szUsername, *ppsid, &cbSid, szDomain, pcchDomain, psUse);
  83. *ppsid = LocalAlloc(0, cbSid); // Now create the SID buffer and try again
  84. if (!*ppsid )
  85. return E_OUTOFMEMORY;
  86. *pcchDomain = cchDomain;
  87. if (!LookupAccountName(NULL, szUsername, *ppsid, &cbSid, szDomain, pcchDomain, psUse))
  88. {
  89. // Free our allocated SID
  90. LocalFree(*ppsid);
  91. *ppsid = NULL;
  92. return E_FAIL;
  93. }
  94. return S_OK;
  95. }
  96. BOOL FormatMessageTemplate(LPCTSTR pszTemplate, LPTSTR pszStrOut, DWORD cchSize, ...)
  97. {
  98. va_list vaParamList;
  99. va_start(vaParamList, cchSize);
  100. BOOL fResult = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pszTemplate, 0, 0, pszStrOut, cchSize, &vaParamList);
  101. va_end(vaParamList);
  102. return fResult;
  103. }
  104. BOOL FormatMessageString(UINT idTemplate, LPTSTR pszStrOut, DWORD cchSize, ...)
  105. {
  106. BOOL fResult = FALSE;
  107. va_list vaParamList;
  108. TCHAR szFormat[MAX_STATIC + 1];
  109. if (LoadString(g_hinst, idTemplate, szFormat, ARRAYSIZE(szFormat)))
  110. {
  111. va_start(vaParamList, cchSize);
  112. fResult = FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, pszStrOut, cchSize, &vaParamList);
  113. va_end(vaParamList);
  114. }
  115. return fResult;
  116. }
  117. int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...)
  118. {
  119. int iResult = IDCANCEL;
  120. TCHAR szError[MAX_STATIC + 1]; *szError = 0;
  121. TCHAR szCaption[MAX_CAPTION + 1];
  122. TCHAR szFormat[MAX_STATIC + 1]; *szFormat = 0;
  123. // Load and format the error body
  124. if (LoadString(g_hinst, idFormatString, szFormat, ARRAYSIZE(szFormat)))
  125. {
  126. va_list arguments;
  127. va_start(arguments, uType);
  128. if (FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, szError, ARRAYSIZE(szError), &arguments))
  129. {
  130. // Load the caption
  131. if (LoadString(g_hinst, idCaption, szCaption, MAX_CAPTION))
  132. {
  133. iResult = MessageBox(hwnd, szError, szCaption, uType);
  134. }
  135. }
  136. va_end(arguments);
  137. }
  138. return iResult;
  139. }
  140. void EnableControls(HWND hwnd, const UINT* prgIDs, DWORD cIDs, BOOL fEnable)
  141. {
  142. DWORD i;
  143. for (i = 0; i < cIDs; i ++)
  144. {
  145. EnableWindow(GetDlgItem(hwnd, prgIDs[i]), fEnable);
  146. }
  147. }
  148. void MakeDomainUserString(LPCTSTR szDomain, LPCTSTR szUsername, LPTSTR szDomainUser, DWORD cchBuffer)
  149. {
  150. *szDomainUser = 0;
  151. if ((!szDomain) || szDomain[0] == TEXT('\0'))
  152. {
  153. // No domain - just use username
  154. lstrcpyn(szDomainUser, szUsername, cchBuffer);
  155. }
  156. else
  157. {
  158. // Otherwise we have to build a DOMAIN\username string
  159. wnsprintf(szDomainUser, cchBuffer, TEXT("%s\\%s"), szDomain, szUsername);
  160. }
  161. }
  162. // From the NT knowledge base
  163. #define MY_BUFSIZE 512 // highly unlikely to exceed 512 bytes
  164. BOOL GetCurrentUserAndDomainName(LPTSTR UserName, LPDWORD cchUserName, LPTSTR DomainName, LPDWORD cchDomainName)
  165. {
  166. HANDLE hToken;
  167. UCHAR InfoBuffer[ MY_BUFSIZE ];
  168. DWORD cbInfoBuffer = MY_BUFSIZE;
  169. SID_NAME_USE snu;
  170. BOOL bSuccess;
  171. if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
  172. {
  173. if(GetLastError() == ERROR_NO_TOKEN)
  174. {
  175. // attempt to open the process token, since no thread token exists
  176. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  177. return FALSE;
  178. }
  179. else
  180. {
  181. return FALSE;
  182. }
  183. }
  184. bSuccess = GetTokenInformation(hToken, TokenUser, InfoBuffer, cbInfoBuffer, &cbInfoBuffer);
  185. CloseHandle(hToken);
  186. if(!bSuccess)
  187. return FALSE;
  188. return LookupAccountSid(NULL, ((PTOKEN_USER)InfoBuffer)->User.Sid, UserName, cchUserName, DomainName, cchDomainName, &snu);
  189. }
  190. // Pass NULL as TokenHandle to see if thread token is admin
  191. HRESULT IsUserLocalAdmin(HANDLE TokenHandle, BOOL* pfIsAdmin)
  192. {
  193. // First we must check if the current user is a local administrator; if this is
  194. // the case, our dialog doesn't even display
  195. PSID psidAdminGroup = NULL;
  196. SID_IDENTIFIER_AUTHORITY security_nt_authority = SECURITY_NT_AUTHORITY;
  197. BOOL fSuccess = ::AllocateAndInitializeSid(&security_nt_authority, 2,
  198. SECURITY_BUILTIN_DOMAIN_RID,
  199. DOMAIN_ALIAS_RID_ADMINS,
  200. 0, 0, 0, 0, 0, 0,
  201. &psidAdminGroup);
  202. if (fSuccess)
  203. {
  204. // See if the user for this process is a local admin
  205. fSuccess = CheckTokenMembership(TokenHandle, psidAdminGroup, pfIsAdmin);
  206. FreeSid(psidAdminGroup);
  207. }
  208. return fSuccess ? S_OK:E_FAIL;
  209. }
  210. BOOL IsComputerInDomain()
  211. {
  212. static BOOL fInDomain = FALSE;
  213. static BOOL fValid = FALSE;
  214. if (!fValid)
  215. {
  216. fValid = TRUE;
  217. DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdspdinfb = {0};
  218. DWORD err = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic,
  219. (BYTE**) &pdspdinfb);
  220. if ((err == NO_ERROR) && (pdspdinfb != NULL))
  221. {
  222. if ((pdspdinfb->MachineRole == DsRole_RoleStandaloneWorkstation) ||
  223. (pdspdinfb->MachineRole == DsRole_RoleStandaloneServer))
  224. {
  225. fInDomain = FALSE;
  226. }
  227. else
  228. {
  229. fInDomain = TRUE;
  230. }
  231. DsRoleFreeMemory(pdspdinfb);
  232. }
  233. }
  234. return fInDomain;
  235. }
  236. void OffsetControls(HWND hwnd, const UINT* prgIDs, DWORD cIDs, int dx, int dy)
  237. {
  238. for (DWORD i = 0; i < cIDs; i ++)
  239. OffsetWindow(GetDlgItem(hwnd, prgIDs[i]), dx, dy);
  240. }
  241. void OffsetWindow(HWND hwnd, int dx, int dy)
  242. {
  243. RECT rc;
  244. GetWindowRect(hwnd, &rc);
  245. MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rc, 2);
  246. OffsetRect(&rc, dx, dy);
  247. SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
  248. }
  249. BOOL AddPropSheetPageCallback(HPROPSHEETPAGE hpsp, LPARAM lParam)
  250. {
  251. // lParam is really a ADDPROPSHEETDATA*
  252. ADDPROPSHEETDATA* ppsd = (ADDPROPSHEETDATA*)lParam;
  253. if (ppsd->nPages < ARRAYSIZE(ppsd->rgPages))
  254. {
  255. ppsd->rgPages[ppsd->nPages++] = hpsp;
  256. return TRUE;
  257. }
  258. return FALSE;
  259. }
  260. // Code to ensure only one instance of a particular window is running
  261. CEnsureSingleInstance::CEnsureSingleInstance(LPCTSTR szCaption)
  262. {
  263. // Create an event
  264. m_hEvent = CreateEvent(NULL, TRUE, FALSE, szCaption);
  265. // If any weird errors occur, default to running the instance
  266. m_fShouldExit = FALSE;
  267. if (NULL != m_hEvent)
  268. {
  269. // If our event isn't signaled, we're the first instance
  270. m_fShouldExit = (WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent, 0));
  271. if (m_fShouldExit)
  272. {
  273. // app should exit after calling ShouldExit()
  274. // Find and show the caption'd window
  275. HWND hwndActivate = FindWindow(NULL, szCaption);
  276. if (IsWindow(hwndActivate))
  277. {
  278. SetForegroundWindow(hwndActivate);
  279. }
  280. }
  281. else
  282. {
  283. // Signal that event
  284. SetEvent(m_hEvent);
  285. }
  286. }
  287. }
  288. CEnsureSingleInstance::~CEnsureSingleInstance()
  289. {
  290. if (NULL != m_hEvent)
  291. {
  292. CloseHandle(m_hEvent);
  293. }
  294. }
  295. // Browse for a user
  296. //
  297. // This routine activates the appropriate Object Picker to allow
  298. // the user to select a user
  299. // uiTextLocation -- The resource ID of the Edit control where the selected
  300. // object should be printed
  301. HRESULT BrowseForUser(HWND hwndDlg, TCHAR* pszUser, DWORD cchUser, TCHAR* pszDomain, DWORD cchDomain)
  302. {
  303. DSOP_SCOPE_INIT_INFO scopeInfo = {0};
  304. scopeInfo.cbSize = sizeof (scopeInfo);
  305. scopeInfo.flType =
  306. DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE |
  307. DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
  308. DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
  309. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN |
  310. DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN |
  311. DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  312. scopeInfo.flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  313. scopeInfo.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  314. scopeInfo.FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  315. scopeInfo.FilterFlags.Uplevel.flMixedModeOnly = 0;
  316. scopeInfo.FilterFlags.Uplevel.flNativeModeOnly = 0;
  317. scopeInfo.pwzADsPath = NULL;
  318. scopeInfo.pwzDcName = NULL;
  319. scopeInfo.hr = E_FAIL;
  320. DSOP_INIT_INFO initInfo = {0};
  321. initInfo.cbSize = sizeof (initInfo);
  322. initInfo.pwzTargetComputer = NULL;
  323. initInfo.cDsScopeInfos = 1;
  324. initInfo.aDsScopeInfos = &scopeInfo;
  325. initInfo.flOptions = 0;
  326. IDsObjectPicker* pPicker;
  327. HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (LPVOID*)&pPicker);
  328. if (SUCCEEDED(hr))
  329. {
  330. hr = pPicker->Initialize(&initInfo);
  331. if (SUCCEEDED(hr))
  332. {
  333. IDataObject* pdo;
  334. hr = pPicker->InvokeDialog(hwndDlg, &pdo); // S_FALSE indicates cancel
  335. if ((S_OK == hr) && (NULL != pdo))
  336. {
  337. // Get the DS_SELECTION_LIST out of the data obj
  338. FORMATETC fmt;
  339. fmt.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  340. fmt.ptd = NULL;
  341. fmt.dwAspect = DVASPECT_CONTENT;
  342. fmt.lindex = -1;
  343. fmt.tymed = TYMED_HGLOBAL;
  344. STGMEDIUM medium = {0};
  345. hr = pdo->GetData(&fmt, &medium);
  346. if (SUCCEEDED(hr))
  347. {
  348. DS_SELECTION_LIST* plist;
  349. plist = (DS_SELECTION_LIST*)
  350. GlobalLock(medium.hGlobal);
  351. if (NULL != plist)
  352. {
  353. if (plist->cItems >= 1)
  354. {
  355. WCHAR szWinNTProviderName[MAX_DOMAIN + MAX_USER + 10];
  356. lstrcpyn(szWinNTProviderName, plist->aDsSelection[0].pwzADsPath, ARRAYSIZE(szWinNTProviderName));
  357. // Is the name in the correct format?
  358. if (StrCmpNI(szWinNTProviderName, TEXT("WinNT://"), 8) == 0)
  359. {
  360. // Yes, copy over the user name and password
  361. LPTSTR szDomain = szWinNTProviderName + 8;
  362. LPTSTR szUser = StrChr(szDomain, TEXT('/'));
  363. if (szUser)
  364. {
  365. LPTSTR szTemp = CharNext(szUser);
  366. *szUser = 0;
  367. szUser = szTemp;
  368. // Just in case, remove the trailing slash
  369. LPTSTR szTrailingSlash = StrChr(szUser, TEXT('/'));
  370. if (szTrailingSlash)
  371. *szTrailingSlash = 0;
  372. lstrcpyn(pszUser, szUser, cchUser);
  373. lstrcpyn(pszDomain, szDomain, cchDomain);
  374. hr = S_OK;
  375. }
  376. }
  377. }
  378. }
  379. else
  380. {
  381. hr = E_UNEXPECTED; // No selection list!
  382. }
  383. GlobalUnlock(medium.hGlobal);
  384. }
  385. pdo->Release();
  386. }
  387. }
  388. pPicker->Release();
  389. }
  390. return hr;
  391. }
  392. //
  393. // create the intro/done large font for wizards
  394. //
  395. static HFONT g_hfontIntro = NULL;
  396. HFONT GetIntroFont(HWND hwnd)
  397. {
  398. if ( !g_hfontIntro )
  399. {
  400. TCHAR szBuffer[64];
  401. NONCLIENTMETRICS ncm = { 0 };
  402. LOGFONT lf;
  403. ncm.cbSize = SIZEOF(ncm);
  404. SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
  405. lf = ncm.lfMessageFont;
  406. LoadString(g_hinst, IDS_TITLEFONTNAME, lf.lfFaceName, ARRAYSIZE(lf.lfFaceName));
  407. lf.lfWeight = FW_BOLD;
  408. LoadString(g_hinst, IDS_TITLEFONTSIZE, szBuffer, ARRAYSIZE(szBuffer));
  409. lf.lfHeight = 0 - (GetDeviceCaps(NULL, LOGPIXELSY) * StrToInt(szBuffer) / 72);
  410. g_hfontIntro = CreateFontIndirect(&lf);
  411. }
  412. return g_hfontIntro;
  413. }
  414. void CleanUpIntroFont()
  415. {
  416. if (g_hfontIntro)
  417. {
  418. DeleteObject(g_hfontIntro);
  419. g_hfontIntro = NULL;
  420. }
  421. }
  422. void DomainUserString_GetParts(LPCTSTR szDomainUser, LPTSTR szUser, DWORD cchUser, LPTSTR szDomain, DWORD cchDomain)
  423. {
  424. // Check for invalid args
  425. if ((!szUser) ||
  426. (!szDomain) ||
  427. (!cchUser) ||
  428. (!cchDomain))
  429. {
  430. return;
  431. }
  432. else
  433. {
  434. *szUser = 0;
  435. *szDomain = 0;
  436. TCHAR szTemp[MAX_USER + MAX_DOMAIN + 2];
  437. lstrcpyn(szTemp, szDomainUser, ARRAYSIZE(szTemp));
  438. LPTSTR szWhack = StrChr(szTemp, TEXT('\\'));
  439. if (!szWhack)
  440. {
  441. // Also check for forward slash to be friendly
  442. szWhack = StrChr(szTemp, TEXT('/'));
  443. }
  444. if (szWhack)
  445. {
  446. LPTSTR szUserPointer = szWhack + 1;
  447. *szWhack = 0;
  448. // Temp now points to domain.
  449. lstrcpyn(szDomain, szTemp, cchDomain);
  450. lstrcpyn(szUser, szUserPointer, cchUser);
  451. }
  452. else
  453. {
  454. // Don't have a domain name - just a username
  455. lstrcpyn(szUser, szTemp, cchUser);
  456. }
  457. }
  458. }
  459. LPITEMIDLIST GetComputerParent()
  460. {
  461. USES_CONVERSION;
  462. LPITEMIDLIST pidl = NULL;
  463. IShellFolder *psfDesktop;
  464. HRESULT hres = SHGetDesktopFolder(&psfDesktop);
  465. if (SUCCEEDED(hres))
  466. {
  467. TCHAR szName[MAX_PATH];
  468. lstrcpy(szName, TEXT("\\\\"));
  469. LPTSTR pszAfterWhacks = szName + 2;
  470. DWORD cchName = MAX_PATH - 2;
  471. if (GetComputerName(pszAfterWhacks, &cchName))
  472. {
  473. hres = psfDesktop->ParseDisplayName(NULL, NULL, T2W(szName), NULL, &pidl, NULL);
  474. if (SUCCEEDED(hres))
  475. {
  476. ILRemoveLastID(pidl);
  477. }
  478. }
  479. else
  480. {
  481. hres = E_FAIL;
  482. }
  483. psfDesktop->Release();
  484. }
  485. if (FAILED(hres))
  486. {
  487. pidl = NULL;
  488. }
  489. return pidl;
  490. }
  491. int CALLBACK ShareBrowseCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  492. {
  493. switch (uMsg)
  494. {
  495. case BFFM_INITIALIZED:
  496. {
  497. // Try to set the selected item according to the path string passed in lpData
  498. LPTSTR pszPath = (LPTSTR) lpData;
  499. if (pszPath && pszPath[0])
  500. {
  501. int i = lstrlen(pszPath) - 1;
  502. if ((pszPath[i] == TEXT('\\')) ||
  503. (pszPath[i] == TEXT('/')))
  504. {
  505. pszPath[i] = 0;
  506. }
  507. SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) TRUE, (LPARAM) (LPTSTR) pszPath);
  508. }
  509. else
  510. {
  511. // Try to get the computer's container folder
  512. LPITEMIDLIST pidl = GetComputerParent();
  513. if (pidl)
  514. {
  515. SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) FALSE, (LPARAM) (LPTSTR) pidl);
  516. ILFree(pidl);
  517. }
  518. }
  519. }
  520. break;
  521. case BFFM_SELCHANGED:
  522. // Disable OK if this isn't a UNC path type thing
  523. {
  524. TCHAR szPath[MAX_PATH];
  525. LPITEMIDLIST pidl = (LPITEMIDLIST) lParam;
  526. BOOL fEnableOk = FALSE;
  527. if (SUCCEEDED(SHGetTargetFolderPath(pidl, szPath, ARRAYSIZE(szPath))))
  528. {
  529. SHFILEINFO sfi;
  530. SHGetFileInfo(szPath, 0, &sfi, sizeof(sfi), SHGFI_ATTRIBUTES);
  531. // Enable OK only if this is a file folder
  532. if (sfi.dwAttributes & SFGAO_FILESYSTEM)
  533. {
  534. fEnableOk = PathIsUNC(szPath);
  535. }
  536. }
  537. SendMessage(hwnd, BFFM_ENABLEOK, (WPARAM) 0, (LPARAM) fEnableOk);
  538. }
  539. break;
  540. }
  541. return 0;
  542. }
  543. void RemoveControl(HWND hwnd, UINT idControl, UINT idNextControl, const UINT* prgMoveControls, DWORD cControls, BOOL fShrinkParent)
  544. {
  545. HWND hwndControl = GetDlgItem(hwnd, idControl);
  546. HWND hwndNextControl = GetDlgItem(hwnd, idNextControl);
  547. RECT rcControl;
  548. RECT rcNextControl;
  549. if (hwndControl && GetWindowRect(hwndControl, &rcControl) &&
  550. hwndNextControl && GetWindowRect(hwndNextControl, &rcNextControl))
  551. {
  552. int dx = rcControl.left - rcNextControl.left;
  553. int dy = rcControl.top - rcNextControl.top;
  554. MoveControls(hwnd, prgMoveControls, cControls, dx, dy);
  555. if (fShrinkParent)
  556. {
  557. RECT rcParent;
  558. if (GetWindowRect(hwnd, &rcParent))
  559. {
  560. MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rcParent, 2);
  561. rcParent.right += dx;
  562. rcParent.bottom += dy;
  563. SetWindowPos(hwnd, NULL, 0, 0, RECTWIDTH(rcParent), RECTHEIGHT(rcParent), SWP_NOMOVE | SWP_NOZORDER);
  564. }
  565. }
  566. EnableWindow(hwndControl, FALSE);
  567. ShowWindow(hwndControl, SW_HIDE);
  568. }
  569. }
  570. void MoveControls(HWND hwnd, const UINT* prgControls, DWORD cControls, int dx, int dy)
  571. {
  572. DWORD iControl;
  573. for (iControl = 0; iControl < cControls; iControl ++)
  574. {
  575. HWND hwndControl = GetDlgItem(hwnd, prgControls[iControl]);
  576. RECT rcControl;
  577. if (hwndControl && GetWindowRect(hwndControl, &rcControl))
  578. {
  579. MapWindowPoints(NULL, hwnd, (LPPOINT)&rcControl, 2);
  580. SetWindowPos(hwndControl, NULL, rcControl.left + dx, rcControl.top + dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  581. }
  582. }
  583. }
  584. // compute the size of a control based on the you are going to set into it,
  585. // returning the delta in size.
  586. int SizeControlFromText(HWND hwnd, UINT id, LPTSTR psz)
  587. {
  588. HDC hdc = GetDC(hwnd);
  589. if (hdc)
  590. {
  591. HFONT hfDialog = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
  592. HFONT hfOld = (HFONT)SelectObject(hdc, hfDialog);
  593. RECT rc;
  594. GetClientRect(GetDlgItem(hwnd, id), &rc);
  595. int cy = RECTHEIGHT(rc);
  596. int dy = DrawTextEx(hdc, psz, -1, &rc,
  597. DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS |
  598. DT_NOPREFIX | DT_EXTERNALLEADING | DT_EDITCONTROL,
  599. NULL) - cy;
  600. SetWindowPos(GetDlgItem(hwnd, id), NULL, 0, 0, RECTWIDTH(rc), RECTHEIGHT(rc), SWP_NOMOVE|SWP_NOZORDER);
  601. if (hfOld)
  602. SelectObject(hdc, hfOld);
  603. ReleaseDC(hwnd, hdc);
  604. return dy;
  605. }
  606. return 0;
  607. }
  608. void EnableDomainForUPN(HWND hwndUsername, HWND hwndDomain)
  609. {
  610. BOOL fEnable;
  611. // Get the string the user is typing
  612. TCHAR* pszLogonName;
  613. int cchBuffer = (int)SendMessage(hwndUsername, WM_GETTEXTLENGTH, 0, 0) + 1;
  614. pszLogonName = (TCHAR*) LocalAlloc(0, cchBuffer * sizeof(TCHAR));
  615. if (pszLogonName != NULL)
  616. {
  617. SendMessage(hwndUsername, WM_GETTEXT, (WPARAM) cchBuffer, (LPARAM) pszLogonName);
  618. // Disable the domain combo if the user is using a
  619. // UPN (if there is a "@") - ie [email protected]
  620. fEnable = (NULL == StrChr(pszLogonName, TEXT('@')));
  621. EnableWindow(hwndDomain, fEnable);
  622. LocalFree(pszLogonName);
  623. }
  624. }
  625. //
  626. // Set our Alt+Tab icon for the duration of a modal property sheet.
  627. //
  628. int PropertySheetIcon(LPCPROPSHEETHEADER ppsh, LPCTSTR pszIcon)
  629. {
  630. int iResult;
  631. HWND hwnd, hwndT;
  632. BOOL fChangedIcon = FALSE;
  633. HICON hicoPrev;
  634. // This trick doesn't work for modeless property sheets
  635. _ASSERT(!(ppsh->dwFlags & PSH_MODELESS));
  636. // Don't do this if the property sheet itself already has an icon
  637. _ASSERT(ppsh->hIcon == NULL);
  638. // Walk up the parent/owner chain until we find the master owner.
  639. //
  640. // We need to walk the parent chain because sometimes we are given
  641. // a child window as our lpwd->hwnd. And we need to walk the owner
  642. // chain in order to find the owner whose icon will be used for
  643. // Alt+Tab.
  644. //
  645. // GetParent() returns either the parent or owner. Normally this is
  646. // annoying, but we luck out and it's exactly what we want.
  647. hwnd = ppsh->hwndParent;
  648. while ((hwndT = GetParent(hwnd)) != NULL)
  649. {
  650. hwnd = hwndT;
  651. }
  652. // If the master owner isn't visible we can futz his icon without
  653. // screwing up his appearance.
  654. if (!IsWindowVisible(hwnd))
  655. {
  656. HICON hicoNew = LoadIcon(g_hinst, pszIcon);
  657. hicoPrev = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoNew);
  658. fChangedIcon = TRUE;
  659. }
  660. iResult = (int)PropertySheet(ppsh);
  661. // Clean up our icon now that we're done
  662. if (fChangedIcon)
  663. {
  664. // Put the old icon back
  665. HICON hicoNew = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoPrev);
  666. if (hicoNew)
  667. DestroyIcon(hicoNew);
  668. }
  669. return iResult;
  670. }
  671. // Launch ICW shiznits
  672. BOOL IsICWCompleted()
  673. {
  674. DWORD dwICWCompleted = 0;
  675. DWORD dwICWSize = sizeof(dwICWCompleted);
  676. SHGetValue(HKEY_CURRENT_USER, TEXT(ICW_REGPATHSETTINGS), TEXT(ICW_REGKEYCOMPLETED), NULL, &dwICWCompleted, &dwICWSize);
  677. // 99/01/15 #272829 vtan: This is a horrible hack!!! If ICW has
  678. // not been run but settings have been made manually then values
  679. // in HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections
  680. // exists with the values given. Look for the presence of a key
  681. // to resolve that settings are present but that ICW hasn't been
  682. // launched.
  683. // The ideal solution is to get ICW to make this determination
  684. // for us BUT TO NOT LAUNCH ICWCONN1.EXE IN THE PROCESS.
  685. // Currently it will only launch. There is no way to get the
  686. // desired result without a launch.
  687. // 99/02/01 #280138 vtan: Well the solution put in for #272829
  688. // doesn't work. So peeking at the CheckConnectionWizard()
  689. // source in inetcfg\export.cpp shows that it uses a
  690. // wininet.dll function to determine whether manually configured
  691. // internet settings exist. It also exports this function so
  692. // look for it and bind to it dynamically.
  693. if (dwICWCompleted == 0)
  694. {
  695. #define SMART_RUNICW TRUE
  696. #define SMART_QUITICW FALSE
  697. HINSTANCE hICWInst = LoadLibrary(TEXT("inetcfg.dll"));
  698. if (hICWInst != NULL)
  699. {
  700. typedef DWORD (WINAPI *PFNISSMARTSTART) ();
  701. PFNISSMARTSTART pfnIsSmartStart = reinterpret_cast<PFNISSMARTSTART>(GetProcAddress(hICWInst, "IsSmartStart"));
  702. if (pfnIsSmartStart)
  703. {
  704. dwICWCompleted = BOOLIFY(pfnIsSmartStart() == SMART_QUITICW);
  705. }
  706. FreeLibrary(hICWInst);
  707. }
  708. }
  709. return (dwICWCompleted != 0);
  710. }
  711. void LaunchICW()
  712. {
  713. static BOOL s_fCheckedICW = FALSE;
  714. if (!s_fCheckedICW && !IsICWCompleted())
  715. {
  716. // Prevent an error in finding the ICW from causing this to execute over and over again.
  717. s_fCheckedICW = TRUE;
  718. HINSTANCE hICWInst = LoadLibrary(TEXT("inetcfg.dll"));
  719. if (hICWInst != NULL)
  720. {
  721. PFNCHECKCONNECTIONWIZARD pfnCheckConnectionWizard;
  722. pfnCheckConnectionWizard = reinterpret_cast<PFNCHECKCONNECTIONWIZARD>(GetProcAddress(hICWInst, "CheckConnectionWizard"));
  723. if (pfnCheckConnectionWizard != NULL)
  724. {
  725. // If the user cancels ICW then it needs to be launched again.
  726. s_fCheckedICW = FALSE;
  727. DWORD dwICWResult;
  728. pfnCheckConnectionWizard(ICW_LAUNCHFULL | ICW_LAUNCHMANUAL, &dwICWResult);
  729. }
  730. FreeLibrary(hICWInst);
  731. }
  732. }
  733. }
  734. HRESULT LookupLocalGroupName(DWORD dwRID, LPWSTR pszName, DWORD cchName)
  735. {
  736. HRESULT hr = E_FAIL;
  737. PSID psidGroup = NULL;
  738. SID_IDENTIFIER_AUTHORITY security_nt_authority = SECURITY_NT_AUTHORITY;
  739. BOOL fSuccess = ::AllocateAndInitializeSid(&security_nt_authority, 2,
  740. SECURITY_BUILTIN_DOMAIN_RID,
  741. dwRID,
  742. 0, 0, 0, 0, 0, 0,
  743. &psidGroup);
  744. if (fSuccess)
  745. {
  746. // Get the name
  747. WCHAR szDomain[MAX_GROUP + 1];
  748. DWORD cchDomain = ARRAYSIZE(szDomain);
  749. SID_NAME_USE type;
  750. fSuccess = LookupAccountSid(NULL, psidGroup, pszName, &cchName, szDomain, &cchDomain, &type);
  751. FreeSid(psidGroup);
  752. hr = fSuccess ? S_OK : E_FAIL;
  753. }
  754. return hr;
  755. }