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.

482 lines
13 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 2000
  4. Module Name:
  5. path.cxx
  6. Abstract:
  7. Implementation of the methods in the CRedirPath class. This class
  8. parses a path and breaks it up into different components and categorizes
  9. it into one of the well known paths:
  10. (a) a path in the local user profile location
  11. (b) a path in the user's home directory
  12. (c) a specific user specified path
  13. (d) a per-user path in a user specified location
  14. Author:
  15. Rahul Thombre (RahulTh) 3/3/2000
  16. Revision History:
  17. 3/3/2000 RahulTh Created this module.
  18. --*/
  19. #include "precomp.hxx"
  20. CRedirPath::CRedirPath(UINT cookie) : _bDataValid (FALSE), _cookie(cookie)
  21. {
  22. _szPrefix.Empty();
  23. _szSuffix.Empty();
  24. }
  25. //+--------------------------------------------------------------------------
  26. //
  27. // Member: CRedirPath::GeneratePath
  28. //
  29. // Synopsis: Generate the full path from the components
  30. //
  31. // Arguments: [out] szPath : the generated path
  32. // [in, optional] szUser : sample username
  33. //
  34. // Returns: TRUE : if the generated path is valid.
  35. // FALSE: if there is no valid path stored in this object. In
  36. // this case szPath is set to an empty string.
  37. //
  38. // History: 3/3/2000 RahulTh created
  39. //
  40. // Notes: For per user paths, this function uses a sample username
  41. // if supplied, otherwise, it uses the username variable
  42. // string %username%
  43. //
  44. //---------------------------------------------------------------------------
  45. BOOL CRedirPath::GeneratePath (OUT CString & szPath,
  46. OPTIONAL IN const CString & szUser //= USERNAME_STR
  47. ) const
  48. {
  49. BOOL bStatus;
  50. if (! _bDataValid)
  51. return FALSE;
  52. szPath = L"";
  53. bStatus = TRUE;
  54. switch (_type)
  55. {
  56. case IDS_SPECIFIC_PATH:
  57. szPath = _szPrefix;
  58. if (! IsValidPrefix (_type, (LPCTSTR) _szPrefix))
  59. bStatus = FALSE;
  60. break;
  61. case IDS_HOMEDIR_PATH:
  62. szPath = HOMEDIR_STR;
  63. if (!_szSuffix.IsEmpty())
  64. szPath += _szSuffix;
  65. bStatus = TRUE;
  66. break;
  67. case IDS_PERUSER_PATH:
  68. if (_szPrefix.IsEmpty() ||
  69. ! IsValidPrefix (_type, (LPCTSTR) _szPrefix))
  70. {
  71. bStatus = FALSE;
  72. }
  73. else
  74. {
  75. szPath = (_szPrefix + L'\\') + szUser;
  76. if (! _szSuffix.IsEmpty())
  77. szPath += _szSuffix;
  78. bStatus = TRUE;
  79. }
  80. break;
  81. case IDS_USERPROFILE_PATH:
  82. if (_szSuffix.IsEmpty())
  83. {
  84. bStatus = FALSE;
  85. }
  86. else
  87. {
  88. szPath = PROFILE_STR + _szSuffix;
  89. bStatus = TRUE;
  90. }
  91. break;
  92. default:
  93. bStatus = FALSE;
  94. break;
  95. }
  96. return bStatus;
  97. }
  98. //+--------------------------------------------------------------------------
  99. //
  100. // Member: CRedirPath::GenerateSuffix
  101. //
  102. // Synopsis: generates a new suffix based on a given path type and folder
  103. //
  104. // Arguments: [out] szSuffix
  105. // [in] cookie
  106. // [in] pathType
  107. //
  108. // Returns:
  109. //
  110. // History: 3/7/2000 RahulTh created
  111. //
  112. // Notes:
  113. //
  114. //---------------------------------------------------------------------------
  115. void CRedirPath::GenerateSuffix (OUT CString & szSuffix,
  116. IN UINT cookie,
  117. IN UINT pathType
  118. ) const
  119. {
  120. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  121. szSuffix.Empty();
  122. if (IDS_HOMEDIR_PATH == pathType)
  123. return;
  124. if (IDS_MYPICS == cookie)
  125. {
  126. //
  127. // Use the full My Documents\My Pictures path
  128. // only if we are going to the user profile.
  129. // Otherwise stick to vanilla My Pictures
  130. // This ensures that when My Pictures is redirected independently
  131. // to another location, we do not create an extra level of folders
  132. // as this might cause security problems for MyDocs if they are
  133. // also redirected to the same share.
  134. //
  135. if (IDS_USERPROFILE_PATH == pathType)
  136. szSuffix.LoadString (IDS_MYPICS_RELPATH);
  137. else
  138. szSuffix.LoadString (IDS_MYPICS);
  139. }
  140. else
  141. szSuffix.LoadString (cookie);
  142. // Precede it with a "\"
  143. szSuffix = L'\\' + szSuffix;
  144. return;
  145. }
  146. //+--------------------------------------------------------------------------
  147. //
  148. // Member: CRedirPath::Load
  149. //
  150. // Synopsis: parses a given path and breaks it into different components
  151. // so that it can be categorized into one of the well known
  152. // types
  153. //
  154. // Arguments: [in] szPath : the given full path
  155. //
  156. // Returns: TRUE: if the categorization was succesful.
  157. // FALSE otherwise
  158. //
  159. // History: 3/3/2000 RahulTh created
  160. //
  161. // Notes:
  162. //
  163. //---------------------------------------------------------------------------
  164. BOOL CRedirPath::Load (IN LPCTSTR pwszPath)
  165. {
  166. CString szPath;
  167. BOOL bStatus = FALSE;
  168. szPath = pwszPath;
  169. szPath.TrimLeft();
  170. szPath.TrimRight();
  171. szPath.TrimRight (L'\\');
  172. // First check to see if it is a homedir path.
  173. bStatus = this->LoadHomedir ((LPCTSTR)szPath);
  174. // If not, try per-user
  175. if (!bStatus)
  176. bStatus = this->LoadPerUser ((LPCTSTR) szPath);
  177. // If not, try local userprofile
  178. if (!bStatus)
  179. bStatus = this->LoadUserprofile ((LPCTSTR) szPath);
  180. //
  181. // If not try a user defined path.
  182. // Note: we cannot use the value blindly here because we need to
  183. // make sure that there are no environment variables in there.
  184. //
  185. if (!bStatus)
  186. bStatus = this->LoadSpecific ((LPCTSTR) szPath);
  187. return bStatus;
  188. }
  189. // Determines if a valid path is stored in this object.
  190. BOOL CRedirPath::IsPathValid (void) const
  191. {
  192. return _bDataValid;
  193. }
  194. //
  195. // Determines if the supplied path is different from the path stored in the
  196. // object. Note: the suffix is immaterial in these comparisons.
  197. //
  198. BOOL CRedirPath::IsPathDifferent (IN UINT type, IN LPCTSTR pwszPrefix) const
  199. {
  200. CString szPrefix;
  201. // Make sure that a path has been loaded in this object first.
  202. if (! _bDataValid)
  203. return TRUE;
  204. // If the types of the paths aren't the same, tnen the paths surely aren't
  205. if (type != _type)
  206. return TRUE;
  207. // If we are here, the types of the path are the same
  208. //
  209. // Comparing the prefix does not make sense for a homedir path or
  210. // a userprofile path
  211. //
  212. if (IDS_USERPROFILE_PATH == type ||
  213. IDS_HOMEDIR_PATH == type)
  214. {
  215. return FALSE;
  216. }
  217. szPrefix = pwszPrefix;
  218. szPrefix.TrimLeft();
  219. szPrefix.TrimRight();
  220. szPrefix.TrimRight (L'\\');
  221. if (szPrefix != _szPrefix)
  222. return TRUE;
  223. else
  224. return FALSE;
  225. }
  226. // parse the path to see if it is a homedir path
  227. BOOL CRedirPath::LoadHomedir (LPCTSTR pwszPath)
  228. {
  229. BOOL bStatus = FALSE;
  230. int len, lenHomedir;
  231. // Only the My Documents folder is allowed to have a homedir path
  232. if (IDS_MYDOCS != _cookie)
  233. return FALSE;
  234. len = lstrlen (pwszPath);
  235. lenHomedir = lstrlen (HOMEDIR_STR);
  236. if (lenHomedir <= len &&
  237. 0 == _wcsnicmp (pwszPath, HOMEDIR_STR, lenHomedir) &&
  238. (L'\0' == pwszPath[lenHomedir] || L'\\' == pwszPath[lenHomedir]) &&
  239. NULL == wcsstr (&pwszPath[lenHomedir], L"%") // Variables are not allowed anywhere else
  240. )
  241. {
  242. bStatus = TRUE;
  243. _type = IDS_HOMEDIR_PATH;
  244. _szPrefix.Empty();
  245. _szSuffix = &pwszPath[lenHomedir];
  246. }
  247. _bDataValid = bStatus;
  248. return bStatus;
  249. }
  250. // parse the path to see if it is a per-user path
  251. BOOL CRedirPath::LoadPerUser (LPCTSTR pwszPath)
  252. {
  253. BOOL bStatus = FALSE;
  254. WCHAR * pwszPos = NULL;
  255. int lenUsername, len;
  256. // Start menu is not allowed to have a per user path.
  257. if (IDS_STARTMENU == _cookie)
  258. return FALSE;
  259. pwszPos = wcsstr (pwszPath, L"%");
  260. if (pwszPos)
  261. {
  262. *pwszPos = L'\0'; // Temporarily look at only the prefix.
  263. if (!IsValidPrefix (IDS_PERUSER_PATH, pwszPath))
  264. {
  265. *pwszPos = L'%'; // Reset the character at pwszPos
  266. goto LoadPerUser_End;
  267. }
  268. else
  269. {
  270. *pwszPos = L'%'; // Reset the character at pwszPos
  271. }
  272. }
  273. //
  274. // %username% should be the first variable that appears in the path
  275. // if this is to be a per-user path, but it should not be the first
  276. // thing in the path
  277. //
  278. if (NULL != pwszPos && pwszPos != pwszPath)
  279. {
  280. len = lstrlen (pwszPos);
  281. lenUsername = lstrlen (USERNAME_STR);
  282. if (lenUsername <= len &&
  283. 0 == _wcsnicmp (pwszPos, USERNAME_STR, lenUsername) &&
  284. NULL == wcsstr (&pwszPos[lenUsername], L"%")
  285. )
  286. {
  287. bStatus = TRUE;
  288. _type = IDS_PERUSER_PATH;
  289. _szPrefix = pwszPath;
  290. _szPrefix = _szPrefix.Left (pwszPos - pwszPath);
  291. _szPrefix.TrimLeft();
  292. _szPrefix.TrimRight();
  293. _szPrefix.TrimRight(L'\\');
  294. _szSuffix = &pwszPos[lenUsername];
  295. }
  296. }
  297. LoadPerUser_End:
  298. _bDataValid = bStatus;
  299. return bStatus;
  300. }
  301. // parse the path to see if it is a userprofile path
  302. BOOL CRedirPath::LoadUserprofile (LPCTSTR pwszPath)
  303. {
  304. BOOL bStatus = FALSE;
  305. int len, lenUserprofile;
  306. len = lstrlen (pwszPath);
  307. lenUserprofile = lstrlen (PROFILE_STR);
  308. //
  309. // Note: it is considered a userprofile path only if it is of the form
  310. // %userprofile%\<name> where <name> does not contain any variables
  311. //
  312. if (lenUserprofile + 1 < len &&
  313. 0 == _wcsnicmp (pwszPath, PROFILE_STR, lenUserprofile) &&
  314. (L'\0' == pwszPath[lenUserprofile] || L'\\' == pwszPath[lenUserprofile]) &&
  315. NULL == wcsstr (&pwszPath[lenUserprofile], L"%")
  316. )
  317. {
  318. bStatus = TRUE;
  319. _type = IDS_USERPROFILE_PATH;
  320. _szPrefix.Empty();
  321. _szSuffix = &pwszPath[lenUserprofile];
  322. }
  323. _bDataValid = bStatus;
  324. return bStatus;
  325. }
  326. // parse the path to see if it is a specific path provided by the user
  327. BOOL CRedirPath::LoadSpecific (LPCTSTR pwszPath)
  328. {
  329. BOOL bStatus = FALSE;
  330. // We pretty much allow all paths other than empty paths.
  331. if (NULL != pwszPath && L'\0' != *pwszPath)
  332. {
  333. bStatus = TRUE;
  334. _type = IDS_SPECIFIC_PATH;
  335. _szPrefix = pwszPath;
  336. _szPrefix.TrimLeft();
  337. _szPrefix.TrimRight();
  338. _szPrefix.TrimRight(L'\\');
  339. // use X:\ rather than X: to make sure client does not fail
  340. if (2 == _szPrefix.GetLength() && L':' == ((LPCTSTR)_szPrefix)[1])
  341. _szPrefix += L'\\';
  342. _szSuffix.Empty();
  343. }
  344. _bDataValid = bStatus;
  345. return bStatus;
  346. }
  347. //
  348. // Validates the arguments and loads the path into the object.
  349. // The existing object is not modified if the data is invalid
  350. //
  351. BOOL CRedirPath::Load (UINT type, LPCTSTR pwszPrefix, LPCTSTR pwszSuffix)
  352. {
  353. CString szPrefix;
  354. CString szSuffix;
  355. // First process the strings.
  356. szPrefix = pwszPrefix;
  357. szPrefix.TrimLeft();
  358. szPrefix.TrimRight();
  359. szPrefix.TrimRight(L'\\');
  360. szSuffix = pwszSuffix;
  361. szSuffix.TrimLeft();
  362. szSuffix.TrimRight();
  363. szSuffix.TrimRight(L'\\');
  364. //
  365. // The suffix should never have a variable name in it, except
  366. // IDS_SPECIFIC_PATH, for which a suffix really does not make
  367. // much sense.
  368. //
  369. if (IDS_SPECIFIC_PATH != type &&
  370. -1 != szSuffix.Find (L'%'))
  371. {
  372. return FALSE;
  373. }
  374. // Now do the remaining validation on the type and the suffix.
  375. switch (type)
  376. {
  377. case IDS_PERUSER_PATH:
  378. if (szPrefix.IsEmpty() ||
  379. ! IsValidPrefix (type, (LPCTSTR) szPrefix))
  380. return FALSE;
  381. break;
  382. case IDS_SPECIFIC_PATH:
  383. if (!IsValidPrefix (type, (LPCTSTR) szPrefix))
  384. return FALSE;
  385. // use X:\ rather than X: to make sure client does not fail.
  386. if (2 == szPrefix.GetLength() && L':' == ((LPCTSTR)szPrefix)[1])
  387. szPrefix += L'\\';
  388. szSuffix.Empty(); // The entire path is in the prefix. Suffix does not make sense here.
  389. break;
  390. case IDS_USERPROFILE_PATH:
  391. case IDS_HOMEDIR_PATH:
  392. szPrefix.Empty(); // The prefix does not make sense for these paths
  393. break;
  394. default:
  395. return FALSE;
  396. break;
  397. }
  398. //
  399. // If we are here, the data is okay. So populate the members.
  400. // Note: It is okay for the suffix to be an empty string.
  401. //
  402. _bDataValid = TRUE;
  403. _type = type;
  404. _szPrefix = szPrefix;
  405. _szSuffix = szSuffix;
  406. return TRUE;
  407. }
  408. void CRedirPath::GetPrefix (OUT CString & szPrefix) const
  409. {
  410. if (_bDataValid)
  411. szPrefix = _szPrefix;
  412. else
  413. szPrefix.Empty();
  414. }
  415. UINT CRedirPath::GetType (void) const
  416. {
  417. return _type;
  418. }