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.

1083 lines
29 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: util.cpp
  8. //
  9. // This file contains misc functions.
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "rshx32.h"
  13. #include <shlobjp.h> // SHFree
  14. #include <shlwapip.h> // IsOS
  15. #include <safeboot.h> // SAFEBOOT_* flags
  16. #undef IDC_STATIC
  17. #include <xpsp1res.h>
  18. STDMETHODIMP
  19. IDA_BindToFolder(LPIDA pIDA, LPSHELLFOLDER *ppsf)
  20. {
  21. HRESULT hr;
  22. LPSHELLFOLDER psfDesktop;
  23. TraceEnter(TRACE_UTIL, "IDA_BindToFolder");
  24. TraceAssert(pIDA != NULL);
  25. TraceAssert(ppsf != NULL);
  26. *ppsf = NULL;
  27. hr = SHGetDesktopFolder(&psfDesktop);
  28. if (SUCCEEDED(hr))
  29. {
  30. LPCITEMIDLIST pidlFolder = (LPCITEMIDLIST)ByteOffset(pIDA, pIDA->aoffset[0]);
  31. if (ILIsEmpty(pidlFolder))
  32. {
  33. // We're binding to the desktop
  34. *ppsf = psfDesktop;
  35. }
  36. else
  37. {
  38. hr = psfDesktop->BindToObject(pidlFolder,
  39. NULL,
  40. IID_IShellFolder,
  41. (PVOID*)ppsf);
  42. psfDesktop->Release();
  43. }
  44. }
  45. TraceLeaveResult(hr);
  46. }
  47. STDMETHODIMP
  48. IDA_GetItemName(LPSHELLFOLDER psf,
  49. LPCITEMIDLIST pidl,
  50. LPTSTR pszName,
  51. UINT cchName,
  52. SHGNO uFlags)
  53. {
  54. STRRET str;
  55. HRESULT hr;
  56. hr = psf->GetDisplayNameOf(pidl, uFlags, &str);
  57. if (SUCCEEDED(hr))
  58. {
  59. DWORD dwErr;
  60. LPSTR psz;
  61. switch (str.uType)
  62. {
  63. case STRRET_WSTR:
  64. #ifdef UNICODE
  65. lstrcpyn(pszName, str.pOleStr, cchName);
  66. #else // !UNICODE
  67. if (!WideCharToMultiByte(CP_ACP,
  68. 0,
  69. str.pOleStr,
  70. -1,
  71. pszName,
  72. cchName,
  73. NULL,
  74. NULL))
  75. {
  76. dwErr = GetLastError();
  77. hr = HRESULT_FROM_WIN32(dwErr);
  78. }
  79. #endif // !UNICODE
  80. //
  81. // Since this string was alocated from the shell's IMalloc heap,
  82. // we must free it to the same place.
  83. //
  84. SHFree(str.pOleStr);
  85. break;
  86. case STRRET_OFFSET:
  87. psz = (LPSTR)ByteOffset(pidl, str.uOffset);
  88. goto GetItemName_ANSI;
  89. case STRRET_CSTR:
  90. psz = str.cStr;
  91. GetItemName_ANSI:
  92. #ifdef UNICODE
  93. if (!MultiByteToWideChar(CP_ACP,
  94. 0,
  95. psz,
  96. -1,
  97. pszName,
  98. cchName))
  99. {
  100. dwErr = GetLastError();
  101. hr = HRESULT_FROM_WIN32(dwErr);
  102. }
  103. #else // !UNICODE
  104. lstrcpyn(pszName, psz, cchName);
  105. #endif // !UNICODE
  106. break;
  107. default:
  108. hr = E_UNEXPECTED;
  109. break;
  110. }
  111. }
  112. return hr;
  113. }
  114. STDMETHODIMP
  115. IDA_GetItemName(LPSHELLFOLDER psf,
  116. LPCITEMIDLIST pidl,
  117. LPTSTR *ppszName,
  118. SHGNO uFlags)
  119. {
  120. TCHAR szName[MAX_PATH];
  121. HRESULT hr = IDA_GetItemName(psf, pidl, szName, ARRAYSIZE(szName));
  122. if (SUCCEEDED(hr))
  123. hr = LocalAllocString(ppszName, szName);
  124. else
  125. *ppszName = NULL;
  126. return hr;
  127. }
  128. //
  129. // Helper functions used by DPA_CompareSecurityIntersection
  130. //
  131. BOOL
  132. IsEqualSID(PSID pSid1, PSID pSid2)
  133. {
  134. //
  135. // Are they both NULL?
  136. //
  137. if (pSid1 || pSid2)
  138. {
  139. //
  140. // At least one is non-NULL, so if one is NULL then they can't
  141. // be equal.
  142. //
  143. if (pSid1 == NULL || pSid2 == NULL)
  144. return FALSE;
  145. //
  146. // Both are non-NULL. Check the SIDs.
  147. //
  148. if (!EqualSid(pSid1, pSid2))
  149. return FALSE;
  150. }
  151. return TRUE;
  152. }
  153. BOOL
  154. IsEqualACL(PACL pA1, PACL pA2)
  155. {
  156. //
  157. // Are they both NULL?
  158. //
  159. if (pA1 || pA2)
  160. {
  161. //
  162. // At least one is non-NULL, so if one is NULL then they can't
  163. // be equal.
  164. //
  165. if (pA1 == NULL || pA2 == NULL)
  166. return FALSE;
  167. //
  168. // At this point we know that both are non-NULL. Check the
  169. // sizes and contents.
  170. //
  171. // could do a lot more here
  172. if (pA1->AclSize != pA2->AclSize || memcmp(pA1, pA2, pA1->AclSize))
  173. return FALSE;
  174. }
  175. return TRUE;
  176. }
  177. //+---------------------------------------------------------------------------
  178. //
  179. // Function: CompareSecurityDescriptors
  180. //
  181. // Synopsis: Determines if 2 security descriptors are identical. It does
  182. // this by comparing control fields, owner/group, and acls.
  183. //
  184. // Arguments: [IN] pSD1 - 1st SD to compare
  185. // [IN] pSD2 - 2nd SD to compare
  186. // [OUT] pfOwnerConflict - (optional) Set to TRUE if the Owner SIDs are not equal
  187. // [OUT] pfGroupConflict - (optional) Set to TRUE if the Group SIDs are not equal
  188. // [OUT] pfDACLConflict - (optional) Set to TRUE if the DACLs are not equal
  189. // [OUT] pfSACLConflict - (optional) Set to TRUE if the SACLs are not equal
  190. //
  191. // Returns: nothing
  192. //
  193. //
  194. //----------------------------------------------------------------------------
  195. #define DACL_CONTROL_MASK (SE_DACL_PRESENT | SE_DACL_DEFAULTED | SE_DACL_AUTO_INHERITED | SE_DACL_PROTECTED)
  196. #define SACL_CONTROL_MASK (SE_SACL_PRESENT | SE_SACL_DEFAULTED | SE_SACL_AUTO_INHERITED | SE_SACL_PROTECTED)
  197. void
  198. CompareSecurityDescriptors(PSECURITY_DESCRIPTOR pSD1,
  199. PSECURITY_DESCRIPTOR pSD2,
  200. BOOL *pfOwnerConflict,
  201. BOOL *pfGroupConflict,
  202. BOOL *pfSACLConflict,
  203. BOOL *pfDACLConflict)
  204. {
  205. PISECURITY_DESCRIPTOR pS1 = (PISECURITY_DESCRIPTOR)pSD1;
  206. PISECURITY_DESCRIPTOR pS2 = (PISECURITY_DESCRIPTOR)pSD2;
  207. //
  208. // Are the pointers identical?
  209. // This includes the case where both are NULL.
  210. //
  211. if (pS1 == pS2)
  212. {
  213. if (pfOwnerConflict)
  214. *pfOwnerConflict = FALSE;
  215. if (pfGroupConflict)
  216. *pfGroupConflict = FALSE;
  217. if (pfSACLConflict)
  218. *pfSACLConflict = FALSE;
  219. if (pfDACLConflict)
  220. *pfDACLConflict = FALSE;
  221. return;
  222. }
  223. //
  224. // Is (only) one of them NULL? If so, then we can't compare so
  225. // assume that nothing matches.
  226. //
  227. if (!pS1 || !pS2)
  228. {
  229. if (pfOwnerConflict)
  230. *pfOwnerConflict = TRUE;
  231. if (pfGroupConflict)
  232. *pfGroupConflict = TRUE;
  233. if (pfSACLConflict)
  234. *pfSACLConflict = TRUE;
  235. if (pfDACLConflict)
  236. *pfDACLConflict = TRUE;
  237. return;
  238. }
  239. //
  240. // Owner
  241. //
  242. if (pfOwnerConflict)
  243. {
  244. if ((pS1->Control & SE_OWNER_DEFAULTED) != (pS2->Control & SE_OWNER_DEFAULTED))
  245. {
  246. *pfOwnerConflict = TRUE;
  247. }
  248. else
  249. {
  250. *pfOwnerConflict = !IsEqualSID(RtlpOwnerAddrSecurityDescriptor(pS1),
  251. RtlpOwnerAddrSecurityDescriptor(pS2));
  252. }
  253. }
  254. //
  255. // Group
  256. //
  257. if (pfGroupConflict)
  258. {
  259. if ((pS1->Control & SE_GROUP_DEFAULTED) != (pS2->Control & SE_GROUP_DEFAULTED))
  260. {
  261. *pfGroupConflict = TRUE;
  262. }
  263. else
  264. {
  265. *pfGroupConflict = !IsEqualSID(RtlpGroupAddrSecurityDescriptor(pS1),
  266. RtlpGroupAddrSecurityDescriptor(pS2));
  267. }
  268. }
  269. //
  270. // Sacl
  271. //
  272. if (pfSACLConflict)
  273. {
  274. if ((pS1->Control & SACL_CONTROL_MASK) != (pS2->Control & SACL_CONTROL_MASK))
  275. {
  276. *pfSACLConflict = TRUE;
  277. }
  278. else
  279. {
  280. *pfSACLConflict = !IsEqualACL(RtlpSaclAddrSecurityDescriptor(pS1),
  281. RtlpSaclAddrSecurityDescriptor(pS2));
  282. }
  283. }
  284. //
  285. // Dacl
  286. //
  287. if (pfDACLConflict)
  288. {
  289. if ((pS1->Control & DACL_CONTROL_MASK) != (pS2->Control & DACL_CONTROL_MASK))
  290. {
  291. *pfDACLConflict = TRUE;
  292. }
  293. else
  294. {
  295. *pfDACLConflict = !IsEqualACL(RtlpDaclAddrSecurityDescriptor(pS1),
  296. RtlpDaclAddrSecurityDescriptor(pS2));
  297. }
  298. }
  299. }
  300. /*******************************************************************
  301. NAME: DPA_CompareSecurityIntersection
  302. SYNOPSIS: Determines if the selected objects have
  303. equivalent security descriptors
  304. ENTRY: hItemList - DPA containing item names
  305. pfnReadSD - callback function to read the Security Descriptor
  306. for a single item.
  307. pfOwnerConflict - (optional) Set to TRUE if not all Owner SIDs are equal
  308. pfGroupConflict - (optional) Set to TRUE if not all Group SIDs are equal
  309. pfDACLConflict - (optional) Set to TRUE if not all DACLs are equal
  310. pfSACLConflict - (optional) Set to TRUE if not all SACLs are equal
  311. ppszOwnerConflict - (optional) The name of the first item
  312. with a different Owner is returned here.
  313. Free with LocalFreeString.
  314. ppszGroupConflict - (optional) similar to ppszOwnerConflict
  315. ppszDaclConflict - (optional) similar to ppszOwnerConflict
  316. ppszSaclConflict - (optional) similar to ppszOwnerConflict
  317. RETURNS: S_OK if successful, HRESULT error code otherwise
  318. NOTES: The function may exit without checking all objects if all of
  319. the requested flags become FALSE. All out parameters are
  320. valid if the function succeeds, and undetermined otherwise.
  321. HISTORY:
  322. JeffreyS 18-Feb-1997 Created
  323. ********************************************************************/
  324. STDMETHODIMP
  325. DPA_CompareSecurityIntersection(HDPA hItemList,
  326. PFN_READ_SD pfnReadSD,
  327. BOOL *pfOwnerConflict,
  328. BOOL *pfGroupConflict,
  329. BOOL *pfSACLConflict,
  330. BOOL *pfDACLConflict,
  331. LPTSTR *ppszOwnerConflict,
  332. LPTSTR *ppszGroupConflict,
  333. LPTSTR *ppszSaclConflict,
  334. LPTSTR *ppszDaclConflict,
  335. LPBOOL pbCancel)
  336. {
  337. HRESULT hr = S_OK;
  338. DWORD dwErr;
  339. SECURITY_INFORMATION si = 0;
  340. DWORD dwPriv = SE_SECURITY_PRIVILEGE;
  341. HANDLE hToken = INVALID_HANDLE_VALUE;
  342. LPTSTR pszItem;
  343. LPTSTR pszFile;
  344. PSECURITY_DESCRIPTOR pSD1 = NULL;
  345. PSECURITY_DESCRIPTOR pSD2 = NULL;
  346. int i;
  347. #if DBG
  348. DWORD dwTimeStart = GetTickCount();
  349. #endif
  350. TraceEnter(TRACE_UTIL, "DPA_CompareSecurityIntersection");
  351. TraceAssert(hItemList != NULL);
  352. TraceAssert(pfnReadSD != NULL);
  353. if (pfOwnerConflict)
  354. {
  355. *pfOwnerConflict = FALSE;
  356. si |= OWNER_SECURITY_INFORMATION;
  357. }
  358. if (pfGroupConflict)
  359. {
  360. *pfGroupConflict = FALSE;
  361. si |= GROUP_SECURITY_INFORMATION;
  362. }
  363. if (pfSACLConflict)
  364. {
  365. *pfSACLConflict = FALSE;
  366. // SeAuditPrivilege must be enabled to read the SACL.
  367. hToken = EnablePrivileges(&dwPriv, 1);
  368. if (INVALID_HANDLE_VALUE != hToken)
  369. {
  370. si |= SACL_SECURITY_INFORMATION;
  371. }
  372. else
  373. {
  374. // Leave *pfSACLConflict set to FALSE
  375. pfSACLConflict = NULL;
  376. TraceMsg("Security privilege not enabled -- not checking SACL");
  377. }
  378. }
  379. if (pfDACLConflict)
  380. {
  381. *pfDACLConflict = FALSE;
  382. si |= DACL_SECURITY_INFORMATION;
  383. }
  384. if (ppszOwnerConflict != NULL)
  385. *ppszOwnerConflict = NULL;
  386. if (ppszGroupConflict != NULL)
  387. *ppszGroupConflict = NULL;
  388. if (ppszSaclConflict != NULL)
  389. *ppszSaclConflict = NULL;
  390. if (ppszDaclConflict != NULL)
  391. *ppszDaclConflict = NULL;
  392. if (si == 0 || DPA_GetPtrCount(hItemList) < 2)
  393. ExitGracefully(hr, S_OK, "Nothing requested or list contains only one item");
  394. if (pbCancel && *pbCancel)
  395. ExitGracefully(hr, S_OK, "DPA_CompareSecurityIntersection cancelled");
  396. //
  397. // Get the first item name and load its security descriptor.
  398. //
  399. pszItem = (LPTSTR)DPA_FastGetPtr(hItemList, 0);
  400. if (NULL == pszItem)
  401. ExitGracefully(hr, E_UNEXPECTED, "Item list is empty");
  402. dwErr = (*pfnReadSD)(pszItem, si, &pSD1);
  403. if (dwErr)
  404. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "Unable to read Security Descriptor");
  405. //
  406. // Go through the rest of the list and compare their security
  407. // descriptors to the first one.
  408. //
  409. for (i = 1; i < DPA_GetPtrCount(hItemList) && si != 0; i++)
  410. {
  411. if (pbCancel && *pbCancel)
  412. ExitGracefully(hr, S_OK, "DPA_CompareSecurityIntersection cancelled");
  413. pszItem = (LPTSTR)DPA_FastGetPtr(hItemList, i);
  414. if (NULL == pszItem)
  415. ExitGracefully(hr, E_UNEXPECTED, "Unable to retrieve item name from list");
  416. dwErr = (*pfnReadSD)(pszItem, si, &pSD2);
  417. if (dwErr)
  418. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "Unable to read Security Descriptor");
  419. CompareSecurityDescriptors(pSD1,
  420. pSD2,
  421. pfOwnerConflict,
  422. pfGroupConflict,
  423. pfSACLConflict,
  424. pfDACLConflict);
  425. if (pSD2 != NULL)
  426. {
  427. LocalFree(pSD2);
  428. pSD2 = NULL;
  429. }
  430. //
  431. // Get the leaf name of the item to return as the conflict name
  432. //
  433. pszFile = PathFindFileName(pszItem);
  434. if (!pszFile)
  435. pszFile = pszItem;
  436. // If we find an owner that doesn't match, we can stop checking owners
  437. if (pfOwnerConflict && *pfOwnerConflict)
  438. {
  439. pfOwnerConflict = NULL;
  440. si &= ~OWNER_SECURITY_INFORMATION;
  441. if (ppszOwnerConflict)
  442. LocalAllocString(ppszOwnerConflict, pszFile);
  443. }
  444. // Ditto for the group
  445. if (pfGroupConflict && *pfGroupConflict)
  446. {
  447. pfGroupConflict = NULL;
  448. si &= ~GROUP_SECURITY_INFORMATION;
  449. if (ppszGroupConflict)
  450. LocalAllocString(ppszGroupConflict, pszFile);
  451. }
  452. // Same for SACLs
  453. if (pfSACLConflict && *pfSACLConflict)
  454. {
  455. pfSACLConflict = NULL;
  456. si &= ~SACL_SECURITY_INFORMATION;
  457. if (ppszSaclConflict)
  458. LocalAllocString(ppszSaclConflict, pszFile);
  459. }
  460. // Same for DACLs
  461. if (pfDACLConflict && *pfDACLConflict)
  462. {
  463. pfDACLConflict = NULL;
  464. si &= ~DACL_SECURITY_INFORMATION;
  465. if (ppszDaclConflict)
  466. LocalAllocString(ppszDaclConflict, pszFile);
  467. }
  468. }
  469. exit_gracefully:
  470. // Release any privileges we enabled
  471. ReleasePrivileges(hToken);
  472. if (FAILED(hr))
  473. {
  474. LocalFreeString(ppszOwnerConflict);
  475. LocalFreeString(ppszGroupConflict);
  476. LocalFreeString(ppszSaclConflict);
  477. LocalFreeString(ppszDaclConflict);
  478. }
  479. if (pSD1 != NULL)
  480. LocalFree(pSD1);
  481. #if DBG
  482. Trace((TEXT("DPA_CompareSecurityIntersection done: %d"), GetTickCount() - dwTimeStart));
  483. #endif
  484. TraceLeaveResult(hr);
  485. }
  486. //*************************************************************
  487. //
  488. // GetRemotePath
  489. //
  490. // Purpose: Return UNC version of a path
  491. //
  492. // Parameters: pszInName - initial path
  493. // ppszOutName - UNC path returned here
  494. //
  495. //
  496. // Return: HRESULT
  497. // S_OK - UNC path returned
  498. // S_FALSE - drive not connected (UNC not returned)
  499. // or failure code
  500. //
  501. // Notes: The function fails is the path is not a valid
  502. // network path. If the path is already UNC,
  503. // a copy is made without validating the path.
  504. // *ppszOutName must be LocalFree'd by the caller.
  505. //
  506. //*************************************************************
  507. DWORD _WNetGetConnection(LPCTSTR pszLocal, LPTSTR pszRemote, LPDWORD pdwLen)
  508. {
  509. DWORD dwErr = ERROR_PROC_NOT_FOUND;
  510. // This is the only function we call in mpr.dll, and it's delay-loaded
  511. // so wrap it with SEH.
  512. __try
  513. {
  514. dwErr = WNetGetConnection(pszLocal, pszRemote, pdwLen);
  515. }
  516. __finally
  517. {
  518. }
  519. return dwErr;
  520. }
  521. STDMETHODIMP
  522. GetRemotePath(LPCTSTR pszInName, LPTSTR *ppszOutName)
  523. {
  524. HRESULT hr = HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME);
  525. TraceEnter(TRACE_UTIL, "GetRemotePath");
  526. TraceAssert(pszInName);
  527. TraceAssert(ppszOutName);
  528. *ppszOutName = NULL;
  529. if (pszInName[1] == TEXT(':'))
  530. {
  531. DWORD dwErr;
  532. TCHAR szLocalName[3];
  533. TCHAR szRemoteName[MAX_PATH];
  534. DWORD dwLen = ARRAYSIZE(szRemoteName);
  535. szLocalName[0] = pszInName[0];
  536. szLocalName[1] = pszInName[1];
  537. szLocalName[2] = TEXT('\0');
  538. dwErr = _WNetGetConnection(szLocalName, szRemoteName, &dwLen);
  539. if (NO_ERROR == dwErr)
  540. {
  541. hr = S_OK;
  542. dwLen = lstrlen(szRemoteName);
  543. }
  544. else if (ERROR_NOT_CONNECTED == dwErr)
  545. {
  546. ExitGracefully(hr, S_FALSE, "Drive not connected");
  547. }
  548. else if (ERROR_MORE_DATA != dwErr)
  549. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "WNetGetConnection failed");
  550. // if dwErr == ERROR_MORE_DATA, dwLen already has the correct value
  551. // Skip the drive letter and add the length of the rest of the path
  552. // (including NULL)
  553. pszInName += 2;
  554. dwLen += lstrlen(pszInName) + 1;
  555. // We should never get incomplete paths, so we should always
  556. // see a backslash after the "X:". If this isn't true, then
  557. // we should call GetFullPathName above.
  558. TraceAssert(TEXT('\\') == *pszInName);
  559. // Allocate the return buffer
  560. *ppszOutName = (LPTSTR)LocalAlloc(LPTR, dwLen * SIZEOF(TCHAR));
  561. if (!*ppszOutName)
  562. ExitGracefully(hr, E_OUTOFMEMORY, "LocalAlloc failed");
  563. if (ERROR_MORE_DATA == dwErr)
  564. {
  565. // Try again with the bigger buffer
  566. dwErr = _WNetGetConnection(szLocalName, *ppszOutName, &dwLen);
  567. hr = HRESULT_FROM_WIN32(dwErr);
  568. FailGracefully(hr, "WNetGetConnection failed");
  569. }
  570. else
  571. {
  572. // WNetGetConnection succeeded. Copy the result
  573. lstrcpy(*ppszOutName, szRemoteName);
  574. }
  575. // Copy the rest of the path
  576. lstrcat(*ppszOutName, pszInName);
  577. }
  578. else if (PathIsUNC(pszInName))
  579. {
  580. // Just copy the path without validating it
  581. hr = LocalAllocString(ppszOutName, pszInName);
  582. }
  583. exit_gracefully:
  584. if (FAILED(hr))
  585. LocalFreeString(ppszOutName);
  586. TraceLeaveResult(hr);
  587. }
  588. /*******************************************************************
  589. NAME: LocalFreeDPA
  590. SYNOPSIS: LocalFree's all pointers in a Dynamic Pointer
  591. Array and then frees the DPA.
  592. ENTRY: hList - handle of list to destroy
  593. RETURNS: nothing
  594. ********************************************************************/
  595. int CALLBACK
  596. _LocalFreeCB(LPVOID pVoid, LPVOID /*pData*/)
  597. {
  598. if (pVoid)
  599. LocalFree(pVoid);
  600. return 1;
  601. }
  602. void
  603. LocalFreeDPA(HDPA hList)
  604. {
  605. if (hList != NULL)
  606. DPA_DestroyCallback(hList, _LocalFreeCB, 0);
  607. }
  608. //+---------------------------------------------------------------------------
  609. //
  610. // Function: IsSafeMode
  611. //
  612. // Synopsis: Checks the registry to see if the system is in safe mode.
  613. //
  614. // History: 06-Oct-00 JeffreyS Created
  615. //
  616. //----------------------------------------------------------------------------
  617. BOOL
  618. IsSafeMode(void)
  619. {
  620. BOOL fIsSafeMode = FALSE;
  621. LONG ec;
  622. HKEY hkey;
  623. ec = RegOpenKeyEx(
  624. HKEY_LOCAL_MACHINE,
  625. TEXT("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option"),
  626. 0,
  627. KEY_QUERY_VALUE,
  628. &hkey
  629. );
  630. if (ec == NO_ERROR)
  631. {
  632. DWORD dwValue;
  633. DWORD dwValueSize = sizeof(dwValue);
  634. ec = RegQueryValueEx(hkey,
  635. TEXT("OptionValue"),
  636. NULL,
  637. NULL,
  638. (LPBYTE)&dwValue,
  639. &dwValueSize);
  640. if (ec == NO_ERROR)
  641. {
  642. fIsSafeMode = (dwValue == SAFEBOOT_MINIMAL || dwValue == SAFEBOOT_NETWORK);
  643. }
  644. RegCloseKey(hkey);
  645. }
  646. return fIsSafeMode;
  647. }
  648. //+---------------------------------------------------------------------------
  649. //
  650. // Function: IsGuestAccessMode
  651. //
  652. // Synopsis: Checks the registry to see if the system is using the
  653. // Guest-only network access mode.
  654. //
  655. // History: 06-Oct-00 JeffreyS Created
  656. // 19-Apr-00 GPease Modified and changed name
  657. //
  658. //----------------------------------------------------------------------------
  659. BOOL
  660. IsForcedGuestModeOn(void)
  661. {
  662. BOOL fIsForcedGuestModeOn = FALSE;
  663. if (IsOS(OS_PERSONAL))
  664. {
  665. // Guest mode is always on for Personal
  666. fIsForcedGuestModeOn = TRUE;
  667. }
  668. else if (IsOS(OS_PROFESSIONAL) && !IsOS(OS_DOMAINMEMBER))
  669. {
  670. LONG ec;
  671. HKEY hkey;
  672. // Professional, not in a domain. Check the ForceGuest value.
  673. ec = RegOpenKeyEx(
  674. HKEY_LOCAL_MACHINE,
  675. TEXT("SYSTEM\\CurrentControlSet\\Control\\LSA"),
  676. 0,
  677. KEY_QUERY_VALUE,
  678. &hkey
  679. );
  680. if (ec == NO_ERROR)
  681. {
  682. DWORD dwValue;
  683. DWORD dwValueSize = sizeof(dwValue);
  684. ec = RegQueryValueEx(hkey,
  685. TEXT("ForceGuest"),
  686. NULL,
  687. NULL,
  688. (LPBYTE)&dwValue,
  689. &dwValueSize);
  690. if (ec == NO_ERROR && 1 == dwValue)
  691. {
  692. fIsForcedGuestModeOn = TRUE;
  693. }
  694. RegCloseKey(hkey);
  695. }
  696. }
  697. return fIsForcedGuestModeOn;
  698. }
  699. //+---------------------------------------------------------------------------
  700. //
  701. // Function: IsSimpleUI
  702. //
  703. // Synopsis: Checks whether to show the simple version of the UI.
  704. //
  705. // History: 06-Oct-00 JeffreyS Created
  706. // 19-Apr-00 GPease Removed CTRL key check
  707. //
  708. //----------------------------------------------------------------------------
  709. BOOL
  710. IsSimpleUI(void)
  711. {
  712. // Show old UI in safe mode and anytime network access involves
  713. // true user identity (server, pro with GuestMode off).
  714. // Show simple UI anytime network access is done using the Guest
  715. // account (personal, pro with GuestMode on) except in safe mode.
  716. return (!IsSafeMode() && IsForcedGuestModeOn());
  717. }
  718. HRESULT BindToObjectEx(IShellFolder *psf, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
  719. {
  720. HRESULT hr;
  721. IShellFolder *psfRelease = NULL;
  722. if (!psf)
  723. {
  724. SHGetDesktopFolder(&psf);
  725. psfRelease = psf;
  726. }
  727. if (psf)
  728. {
  729. if (!pidl || ILIsEmpty(pidl))
  730. {
  731. hr = psf->QueryInterface(riid, ppv);
  732. }
  733. else
  734. {
  735. hr = psf->BindToObject(pidl, pbc, riid, ppv);
  736. }
  737. }
  738. else
  739. {
  740. *ppv = NULL;
  741. hr = E_FAIL;
  742. }
  743. if (psfRelease)
  744. {
  745. psfRelease->Release();
  746. }
  747. if (SUCCEEDED(hr) && (*ppv == NULL))
  748. {
  749. // Some shell extensions (eg WS_FTP) will return success and a null out pointer
  750. hr = E_FAIL;
  751. }
  752. return hr;
  753. }
  754. LPITEMIDLIST ILCloneParent(LPCITEMIDLIST pidl)
  755. {
  756. LPITEMIDLIST pidlParent = ILClone(pidl);
  757. if (pidlParent)
  758. ILRemoveLastID(pidlParent);
  759. return pidlParent;
  760. }
  761. // psfRoot is the base of the bind. If NULL, then we use the shell desktop.
  762. // If you want to bind relative to the explorer root (e.g., CabView, MSN),
  763. // then use SHBindToIDListParent.
  764. HRESULT BindToFolderIDListParent(IShellFolder *psfRoot, LPCITEMIDLIST pidl, REFIID riid, void **ppv, LPCITEMIDLIST *ppidlLast)
  765. {
  766. HRESULT hr;
  767. // Old shell32 code in some cases simply whacked the pidl,
  768. // but this is unsafe. Do what shdocvw does and clone/remove:
  769. //
  770. LPITEMIDLIST pidlParent = ILCloneParent(pidl);
  771. if (pidlParent)
  772. {
  773. hr = BindToObjectEx(psfRoot, pidlParent, NULL, riid, ppv);
  774. ILFree(pidlParent);
  775. }
  776. else
  777. hr = E_OUTOFMEMORY;
  778. if (ppidlLast)
  779. *ppidlLast = ILFindLastID(pidl);
  780. return hr;
  781. }
  782. //+---------------------------------------------------------------------------
  783. //
  784. // Function: IsUIHiddenByPrivacyPolicy
  785. //
  786. // Synopsis: Checks if Security Tab is hidden by privacy policy
  787. // NTRAID#NTBUG9-223899-2001/03/06-hiteshr
  788. // History: 06-March-01 hiteshr Created
  789. //
  790. //----------------------------------------------------------------------------
  791. BOOL
  792. IsUIHiddenByPrivacyPolicy(void)
  793. {
  794. BOOL fIsUIHiddenByPrivacyPolicy = FALSE;
  795. LONG ec;
  796. HKEY hkey = NULL;
  797. ec = RegOpenKeyEx(HKEY_CURRENT_USER,
  798. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"),
  799. 0,
  800. KEY_QUERY_VALUE,
  801. &hkey
  802. );
  803. if (ec == NO_ERROR)
  804. {
  805. DWORD dwValue = 0;
  806. DWORD dwValueSize = sizeof(dwValue);
  807. ec = RegQueryValueEx(hkey,
  808. TEXT("NoSecurityTab"),
  809. NULL,
  810. NULL,
  811. (LPBYTE)&dwValue,
  812. &dwValueSize);
  813. if (ec == NO_ERROR && 1 == dwValue)
  814. {
  815. fIsUIHiddenByPrivacyPolicy = TRUE;
  816. }
  817. RegCloseKey(hkey);
  818. }
  819. return fIsUIHiddenByPrivacyPolicy;
  820. }
  821. //+----------------------------------------------------------------------------
  822. // Function:SetAclOnRemoteNetworkDrive
  823. // Synopsis: If Z: is a mapped drive( mapped to \\machineA\share), when
  824. // we set DACL/SACL on Z:, Security API's cannot determine
  825. // the parent of "share" on machineA and so we lose all the
  826. // inherited aces. All UI can do is to detect such cases and
  827. // show a warning. Thats what this function does.
  828. // Arguments:hItemList List of items on which security is going to be set
  829. // si: SECURITY_INFORMATION
  830. // pSD: Security Descriptor to be set
  831. // hWndPopupOwner: Owner window for message box
  832. // Returns:
  833. // NTRAID#NTBUG9-581195-2002/03/26-hiteshr
  834. // NOTES:Since this fix is XPSP1, resources are going to be loaded from
  835. // xpsp1res.dll
  836. //-----------------------------------------------------------------------------
  837. BOOL SetAclOnRemoteNetworkDrive(HDPA hItemList,
  838. SECURITY_INFORMATION si,
  839. PSECURITY_DESCRIPTOR pSD,
  840. HWND hWndPopupOwner)
  841. {
  842. if(!hItemList || !pSD)
  843. {
  844. ASSERT(hItemList);
  845. ASSERT(pSD);
  846. return FALSE;
  847. }
  848. //We care only about DACL and SACL
  849. if(!(si & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)))
  850. {
  851. return TRUE;
  852. }
  853. SECURITY_DESCRIPTOR_CONTROL Control = 0;
  854. DWORD dwRevision = 0;
  855. //Check if DACL or SACL is protected
  856. if(!GetSecurityDescriptorControl(pSD,&Control,&dwRevision))
  857. {
  858. return FALSE;
  859. }
  860. //If inheritance is prevented for this object,there is no loss of inheritance
  861. //so we are fine
  862. if( ((si & DACL_SECURITY_INFORMATION) && (Control & SE_DACL_PROTECTED)) ||
  863. ((si & SACL_SECURITY_INFORMATION) && (Control & SE_SACL_PROTECTED)))
  864. {
  865. return TRUE;
  866. }
  867. LPWSTR pszMessage = NULL;
  868. LPWSTR pszTitle = NULL;
  869. BOOL bRet = TRUE;
  870. HINSTANCE hResModule = NULL;
  871. //Now Check if any of the items in hItemList is a mapped network drive
  872. for (int i = 0; i < DPA_GetPtrCount(hItemList); i++)
  873. {
  874. LPTSTR pszPath = (LPTSTR)DPA_FastGetPtr(hItemList, i);
  875. //Path in not a root
  876. if(!PathIsRoot(pszPath))
  877. {
  878. continue;
  879. }
  880. //Path is root but not remote
  881. if(GetDriveType(pszPath) != DRIVE_REMOTE)
  882. {
  883. continue;
  884. }
  885. int nMsgId = (si & DACL_SECURITY_INFORMATION) ? IDS_RSHX32_SET_PERMS_ON_NETWORK_DRIVE : IDS_RSHX32_SET_SACLS_ON_NETWORK_DRIVE;
  886. //LOAD Resource from
  887. WCHAR szResourceDLL[] = L"xpsp1res.dll";
  888. hResModule = LoadLibrary(szResourceDLL);
  889. if(hResModule)
  890. {
  891. if(!LoadStringAlloc(&pszTitle, hResModule, IDS_RSHX32_PROP_PAGE_TITLE))
  892. break;
  893. if(!LoadStringAlloc(&pszMessage, hResModule, nMsgId))
  894. break;
  895. //Ok, this is a remote network drive, display Warning.
  896. //We display only one warning per list
  897. if (IDNO == MsgPopup(hWndPopupOwner,
  898. pszMessage,
  899. pszTitle,
  900. MB_YESNO|MB_DEFBUTTON2| MB_ICONWARNING | MB_SETFOREGROUND,
  901. g_hInstance,
  902. pszPath))
  903. {
  904. bRet = FALSE;
  905. }
  906. }
  907. break;
  908. }
  909. LocalFreeString(&pszTitle);
  910. LocalFreeString(&pszMessage);
  911. if(hResModule)
  912. FreeLibrary(hResModule);
  913. return bRet;
  914. }