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.

740 lines
26 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/system/searchpath_sequence.hpp
  3. *
  4. * Purpose: Contains the basic_searchpath_sequence template class, and ANSI
  5. * and Unicode specialisations thereof.
  6. *
  7. * Created: 12th July 2002
  8. * Updated: 12th August 2010
  9. *
  10. * Home: http://stlsoft.org/
  11. *
  12. * Copyright (c) 2002-2010, Matthew Wilson and Synesis Software
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice, this
  19. * list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  24. * any contributors may be used to endorse or promote products derived from
  25. * this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * ////////////////////////////////////////////////////////////////////// */
  40. /** \file winstl/system/searchpath_sequence.hpp
  41. *
  42. * \brief [C++ only] Definition of the winstl::basic_searchpath_sequence
  43. * class template
  44. * (\ref group__library__system "System" Library).
  45. */
  46. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_SEARCHPATH_SEQUENCE
  47. #define WINSTL_INCL_WINSTL_SYSTEM_HPP_SEARCHPATH_SEQUENCE
  48. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  49. # define WINSTL_VER_SYSTEM_HPP_SEARCHPATH_SEQUENCE_MAJOR 4
  50. # define WINSTL_VER_SYSTEM_HPP_SEARCHPATH_SEQUENCE_MINOR 2
  51. # define WINSTL_VER_SYSTEM_HPP_SEARCHPATH_SEQUENCE_REVISION 4
  52. # define WINSTL_VER_SYSTEM_HPP_SEARCHPATH_SEQUENCE_EDIT 97
  53. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  54. /* /////////////////////////////////////////////////////////////////////////
  55. * Includes
  56. */
  57. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  58. # include <winstl/winstl.h>
  59. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  60. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  61. # include <winstl/filesystem/filesystem_traits.hpp>
  62. #endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  63. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  64. # include <winstl/memory/processheap_allocator.hpp>
  65. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  66. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_VERSION
  67. # include <winstl/system/system_version.hpp>
  68. #endif /* !WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_VERSION */
  69. #ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX
  70. # include <winstl/synch/spin_mutex.hpp>
  71. #endif /* !WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX */
  72. #ifndef WINSTL_INCL_WINSTL_HPP_REGISTRY_FUNCTIONS
  73. //# include <winstl/registry_functions.hpp>
  74. #endif /* !WINSTL_INCL_WINSTL_HPP_REGISTRY_FUNCTIONS */
  75. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  76. # include <stlsoft/memory/auto_buffer.hpp>
  77. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  78. #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE
  79. # include <stlsoft/synch/lock_scope.hpp>
  80. #endif /* !STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE */
  81. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  82. # include <stlsoft/util/std/iterator_helper.hpp>
  83. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  84. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  85. # include <stlsoft/collections/util/collections.hpp>
  86. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  87. /* /////////////////////////////////////////////////////////////////////////
  88. * Namespace
  89. */
  90. #ifndef _WINSTL_NO_NAMESPACE
  91. # if defined(_STLSOFT_NO_NAMESPACE) || \
  92. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  93. /* There is no stlsoft namespace, so must define ::winstl */
  94. namespace winstl
  95. {
  96. # else
  97. /* Define stlsoft::winstl_project */
  98. namespace stlsoft
  99. {
  100. namespace winstl_project
  101. {
  102. # endif /* _STLSOFT_NO_NAMESPACE */
  103. #endif /* !_WINSTL_NO_NAMESPACE */
  104. /* /////////////////////////////////////////////////////////////////////////
  105. * Classes
  106. */
  107. // class basic_searchpath_sequence
  108. /** \brief Presents an STL-like sequence interface to the search path sequence for the current process
  109. *
  110. * \ingroup group__library__system
  111. *
  112. * \param C The character type
  113. * \param T The traits type. On translators that support default template arguments this defaults to filesystem_traits<C>
  114. */
  115. template< ss_typename_param_k C
  116. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  117. , ss_typename_param_k T = filesystem_traits<C>
  118. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  119. , ss_typename_param_k T /* = filesystem_traits<C> */
  120. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  121. >
  122. class basic_searchpath_sequence
  123. : public stlsoft_ns_qual(stl_collection_tag)
  124. {
  125. public:
  126. /// The character type
  127. typedef C char_type;
  128. /// The traits type
  129. typedef T traits_type;
  130. /// The current parameterisation of the type
  131. typedef basic_searchpath_sequence<C, T> class_type;
  132. /// The value type
  133. typedef char_type const* value_type;
  134. /// The pointer type
  135. typedef value_type* pointer;
  136. /// The non-mutable (const) pointer type
  137. typedef value_type const* const_pointer;
  138. /// The reference type
  139. typedef value_type& reference;
  140. /// The non-mutable (const) reference type
  141. typedef value_type const& const_reference;
  142. /// The size type
  143. typedef ws_size_t size_type;
  144. /// The difference type
  145. typedef ws_ptrdiff_t difference_type;
  146. /// The non-mutating (const) iterator type
  147. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  148. typedef stlsoft_ns_qual(pointer_iterator)<
  149. #else /* ? compiler */
  150. typedef ss_typename_type_k stlsoft_ns_qual(pointer_iterator)<
  151. #endif /* compiler */
  152. value_type
  153. , const_pointer
  154. , const_reference
  155. >::type const_iterator;
  156. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  157. /// The non-mutating (const) reverse iterator type
  158. typedef stlsoft_ns_qual(const_reverse_iterator_base)<
  159. const_iterator
  160. , value_type
  161. , const_reference
  162. , const_pointer
  163. , difference_type
  164. > const_reverse_iterator;
  165. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  166. // Construction
  167. public:
  168. /// Determines the search path sequence for the calling process
  169. ///
  170. /// \note The process directory appears before the current directory
  171. basic_searchpath_sequence();
  172. /// Determines the search path sequence for the calling process
  173. ///
  174. /// \param bIncludeApplicationDirectory If this is \c true the application directory is included in the search path sequence
  175. /// \param bIncludeCurrentDirectory If this is \c true the current directory is included in the search path sequence
  176. /// \param bApplicationDirectoryFirst If this is \c true the process directory is placed before the current directory in the search (the normal loading sequence). If not, then the current directory comes first.
  177. basic_searchpath_sequence(
  178. ws_bool_t bIncludeApplicationDirectory
  179. , ws_bool_t bIncludeCurrentDirectory
  180. , ws_bool_t bApplicationDirectoryFirst = true
  181. );
  182. /// Releases any resources
  183. ~basic_searchpath_sequence() stlsoft_throw_0();
  184. // Iteration
  185. public:
  186. /// Begins the iteration
  187. ///
  188. /// \return An iterator representing the start of the sequence
  189. const_iterator begin() const;
  190. /// Ends the iteration
  191. ///
  192. /// \return An iterator representing the end of the sequence
  193. const_iterator end() const;
  194. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  195. /// Begins the reverse iteration
  196. ///
  197. /// \return An iterator representing the start of the reverse sequence
  198. const_reverse_iterator rbegin() const;
  199. /// Ends the reverse iteration
  200. ///
  201. /// \return An iterator representing the end of the reverse sequence
  202. const_reverse_iterator rend() const;
  203. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  204. // State
  205. public:
  206. /// Returns the number of items in the sequence
  207. size_type size() const;
  208. /// Indicates whether the sequence is empty
  209. ws_bool_t empty() const;
  210. /// Returns the maximum number of items in the sequence
  211. static size_type max_size();
  212. // Accessors
  213. public:
  214. /// Returns the item at the given index
  215. value_type operator [](size_type index) const;
  216. // Members
  217. private:
  218. // 1. Application directory - GetModuleFileName(NULL, ...);
  219. // 2. Current directory - GetCurrentDirectory
  220. // 3. System directory
  221. // 4. NT-only: 16-bit system directory
  222. // 5. Windows directory
  223. // 6 - n. Path directories
  224. typedef processheap_allocator<char_type> main_allocator_type_;
  225. typedef processheap_allocator<value_type> value_allocator_type_;
  226. typedef stlsoft_ns_qual(auto_buffer_old)<
  227. char_type
  228. , main_allocator_type_
  229. , 1024
  230. > main_buffer_type_;
  231. typedef stlsoft_ns_qual(auto_buffer_old)<
  232. value_type
  233. , value_allocator_type_
  234. , 24
  235. > value_buffer_type_;
  236. main_buffer_type_ m_buffer;
  237. value_buffer_type_ m_values;
  238. const_iterator m_end;
  239. // Implementation
  240. private:
  241. void construct_(
  242. ws_bool_t bIncludeApplicationDirectory
  243. , ws_bool_t bIncludeCurrentDirectory
  244. , ws_bool_t bApplicationDirectoryFirst
  245. );
  246. /* WSCB: Borland has an internal compiler error if use ws_bool_t */
  247. #ifdef STLSOFT_COMPILER_IS_BORLAND
  248. typedef ws_int_t init_type;
  249. #else /* ? compiler */
  250. typedef ws_bool_t init_type;
  251. #endif /* compiler */
  252. static char_type const* get_application_directory()
  253. {
  254. static char_type s_application_directory[WINSTL_CONST_MAX_PATH + 1];
  255. static atomic_int_t s_mx;
  256. spin_mutex mx(&s_mx);
  257. stlsoft_ns_qual(lock_scope)<spin_mutex> lock(mx);
  258. static init_type s_init = ws_false_v;
  259. if(!s_init)
  260. {
  261. char_type dummy[WINSTL_CONST_MAX_PATH + 1];
  262. char_type* file_part;
  263. traits_type::get_module_filename(NULL, s_application_directory, STLSOFT_NUM_ELEMENTS(s_application_directory));
  264. traits_type::get_full_path_name(s_application_directory, STLSOFT_NUM_ELEMENTS(dummy), dummy, &file_part);
  265. s_application_directory[file_part - &dummy[0] - 1] = '\0';
  266. s_init = ws_true_v;
  267. }
  268. return s_application_directory;
  269. }
  270. static char_type const* get_system_directory()
  271. {
  272. static char_type s_system_directory[WINSTL_CONST_MAX_PATH + 1];
  273. static atomic_int_t s_mx;
  274. spin_mutex mx(&s_mx);
  275. stlsoft_ns_qual(lock_scope)<spin_mutex> lock(mx);
  276. static init_type s_init = (traits_type::get_system_directory(s_system_directory, STLSOFT_NUM_ELEMENTS(s_system_directory)), ws_true_v);
  277. return s_system_directory;
  278. }
  279. static char_type const* get_windows_directory()
  280. {
  281. static char_type s_windows_directory[WINSTL_CONST_MAX_PATH + 1];
  282. static atomic_int_t s_mx;
  283. spin_mutex mx(&s_mx);
  284. stlsoft_ns_qual(lock_scope)<spin_mutex> lock(mx);
  285. static init_type s_init = (traits_type::get_windows_directory(s_windows_directory, STLSOFT_NUM_ELEMENTS(s_windows_directory)), ws_true_v);
  286. return s_windows_directory;
  287. }
  288. static char_type const* get_system16_directory()
  289. {
  290. static char_type s_system16_directory[WINSTL_CONST_MAX_PATH + 1];
  291. static atomic_int_t s_mx;
  292. spin_mutex mx(&s_mx);
  293. stlsoft_ns_qual(lock_scope)<spin_mutex> lock(mx);
  294. static init_type s_init = ws_false_v;
  295. if(!s_init)
  296. {
  297. if(system_version::winnt())
  298. {
  299. char_type* file_part;
  300. traits_type::get_full_path_name(get_system_directory(), STLSOFT_NUM_ELEMENTS(s_system16_directory), s_system16_directory, &file_part);
  301. traits_type::char_copy(file_part, disgusting_hack_("SYSTEM", L"SYSTEM"), 7);
  302. }
  303. else
  304. {
  305. s_system16_directory[0] = '\0';
  306. }
  307. s_init = ws_true_v;
  308. }
  309. return s_system16_directory;
  310. }
  311. static ws_size_t directories_total()
  312. {
  313. ws_size_t cch = 0;
  314. cch += 1 + traits_type::str_len(get_application_directory()); // Application directory
  315. cch += 1 + traits_type::get_current_directory(static_cast<char*>(NULL), 0); // Current directory
  316. cch += 1 + traits_type::str_len(get_system_directory()); // System directory
  317. cch += 1 + traits_type::str_len(get_system16_directory()); // 16-bit System directory
  318. cch += 1 + traits_type::str_len(get_windows_directory()); // Windows directory
  319. cch += 1 + traits_type::get_environment_variable(disgusting_hack_("PATH", L"PATH"), NULL, 0); // PATH
  320. return cch;
  321. }
  322. static ws_size_t num_paths()
  323. {
  324. ws_size_t cPaths = 0;
  325. ws_size_t cch = traits_type::get_environment_variable(disgusting_hack_("PATH", L"PATH"), NULL, 0);
  326. main_buffer_type_ buffer(1 + cch);
  327. char_type const* begin = &buffer[0];
  328. char_type const* end = begin + cch;
  329. char_type const* last;
  330. traits_type::get_environment_variable(disgusting_hack_("PATH", L"PATH"), &buffer[0], buffer.size());
  331. for(; begin != end; ++begin)
  332. {
  333. if(*begin != ';')
  334. {
  335. break;
  336. }
  337. }
  338. for(last = begin; begin != end; ++begin)
  339. {
  340. if(*begin == ';')
  341. {
  342. if(1 < begin - last)
  343. {
  344. ++cPaths;
  345. }
  346. last = begin + 1;
  347. }
  348. }
  349. if(1 < begin - last)
  350. {
  351. ++cPaths;
  352. }
  353. return cPaths;
  354. }
  355. static ws_bool_t is_curr_dir_last_()
  356. {
  357. if( system_version::winnt() &&
  358. system_version::major() >= 5 &&
  359. system_version::minor() == 1)
  360. {
  361. ws_bool_t res = false;
  362. HKEY hkey;
  363. LRESULT lRes = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE
  364. , L"SYSTEM\\CurrentControlSet\\Control\\Session Manager"
  365. , 0
  366. , KEY_QUERY_VALUE
  367. , &hkey);
  368. if(ERROR_SUCCESS == lRes)
  369. {
  370. DWORD type;
  371. DWORD data;
  372. DWORD cbData = sizeof(data);
  373. lRes = ::RegQueryValueExW(hkey, L"SafeDllSearchMode", NULL, &type, reinterpret_cast<LPBYTE>(&data), &cbData);
  374. if(ERROR_SUCCESS == lRes)
  375. {
  376. if(1 == data)
  377. {
  378. res = true;
  379. }
  380. }
  381. ::RegCloseKey(hkey);
  382. }
  383. return res;
  384. }
  385. else
  386. {
  387. return false;
  388. }
  389. }
  390. // One to be ashamed of. This will be replaced in the next version of the libraries
  391. static char_type const* disgusting_hack_(ws_char_a_t* literal_a, ws_char_w_t* literal_w)
  392. {
  393. #if defined(STLSOFT_COMPILER_IS_DMC)
  394. if(sizeof(char_type) == sizeof(ws_char_w_t))
  395. {
  396. return static_cast<char_type*>(static_cast<void*>(literal_w));
  397. }
  398. else
  399. {
  400. return static_cast<char_type*>(static_cast<void*>(literal_a));
  401. }
  402. #else /* ? compiler */
  403. return static_cast<char_type*>((sizeof(char_type) == sizeof(ws_char_w_t)) ? static_cast<void*>(literal_w) : static_cast<void*>(literal_a));
  404. #endif /* compiler */
  405. }
  406. // Not to be implemented
  407. private:
  408. basic_searchpath_sequence(class_type const&);
  409. basic_searchpath_sequence const& operator =(class_type const&);
  410. };
  411. /* /////////////////////////////////////////////////////////////////////////
  412. * Typedefs for commonly encountered types
  413. */
  414. /** \brief Specialisation of the basic_searchpath_sequence template for the ANSI character type \c char
  415. *
  416. * \ingroup group__library__system
  417. */
  418. typedef basic_searchpath_sequence<ws_char_a_t, filesystem_traits<ws_char_a_t> > searchpath_sequence_a;
  419. /** \brief Specialisation of the basic_searchpath_sequence template for the Unicode character type \c wchar_t
  420. *
  421. * \ingroup group__library__system
  422. */
  423. typedef basic_searchpath_sequence<ws_char_w_t, filesystem_traits<ws_char_w_t> > searchpath_sequence_w;
  424. /** \brief Specialisation of the basic_searchpath_sequence template for the Win32 character type \c TCHAR
  425. *
  426. * \ingroup group__library__system
  427. */
  428. typedef basic_searchpath_sequence<TCHAR, filesystem_traits<TCHAR> > searchpath_sequence;
  429. ////////////////////////////////////////////////////////////////////////////
  430. // Unit-testing
  431. #ifdef STLSOFT_UNITTEST
  432. #include "./unittest/searchpath_sequence_unittest_.h"
  433. #endif /* STLSOFT_UNITTEST */
  434. ////////////////////////////////////////////////////////////////////////////
  435. // Implementation
  436. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  437. // basic_searchpath_sequence
  438. template< ss_typename_param_k C
  439. , ss_typename_param_k T
  440. >
  441. inline basic_searchpath_sequence<C, T>::basic_searchpath_sequence()
  442. : m_buffer(directories_total())
  443. , m_values(num_paths() + (system_version::winnt() ? 5 : 4))
  444. {
  445. construct_(true, true, true);
  446. }
  447. template< ss_typename_param_k C
  448. , ss_typename_param_k T
  449. >
  450. inline basic_searchpath_sequence<C, T>::basic_searchpath_sequence(
  451. ws_bool_t bIncludeApplicationDirectory
  452. , ws_bool_t bIncludeCurrentDirectory
  453. , ws_bool_t bApplicationDirectoryFirst /* = true */
  454. )
  455. : m_buffer(directories_total())
  456. , m_values(num_paths() + (system_version::winnt() ? 5 : 4) - (!bIncludeApplicationDirectory + !bIncludeCurrentDirectory))
  457. {
  458. construct_(bIncludeApplicationDirectory, bIncludeCurrentDirectory, bApplicationDirectoryFirst);
  459. }
  460. template< ss_typename_param_k C
  461. , ss_typename_param_k T
  462. >
  463. inline void basic_searchpath_sequence<C, T>::construct_(
  464. ws_bool_t bIncludeApplicationDirectory
  465. , ws_bool_t bIncludeCurrentDirectory
  466. , ws_bool_t bApplicationDirectoryFirst
  467. )
  468. {
  469. // Determine whether the current directory must be relegated
  470. ws_bool_t bIncludeCurrentDirectoryLast = bIncludeCurrentDirectory && is_curr_dir_last_();
  471. // 6 - n. Path directories
  472. char_type* psz = &m_buffer[0];
  473. char_type const** it = &m_values[0];
  474. char_type const* cwd = NULL;
  475. psz[0] = '\0';
  476. { for(int i = 0; i < 2; ++i) {
  477. if((i & 1) != static_cast<int>(bApplicationDirectoryFirst))
  478. {
  479. if(bIncludeApplicationDirectory)
  480. {
  481. *it++ = psz;
  482. // 1. Application directory - GetModuleFileName(NULL, ...);
  483. size_t n = traits_type::str_len(get_application_directory());
  484. traits_type::char_copy(psz, get_application_directory(), n + 1);
  485. psz += n;
  486. }
  487. }
  488. else
  489. {
  490. if(bIncludeCurrentDirectory)
  491. {
  492. cwd = psz;
  493. // 2. Current directory - GetCurrentDirectory
  494. psz += traits_type::get_current_directory(WINSTL_CONST_MAX_PATH + 1, psz);
  495. if(!bIncludeCurrentDirectoryLast)
  496. {
  497. *it++ = cwd;
  498. }
  499. }
  500. }
  501. ++psz;
  502. }}
  503. size_t n;
  504. // 3. System directory
  505. *it++ = psz;
  506. n = traits_type::str_len(get_system_directory());
  507. traits_type::char_copy(psz, get_system_directory(), n + 1);
  508. psz += n;
  509. ++psz;
  510. // 4. NT-only: 16-bit system directory
  511. if(system_version::winnt())
  512. {
  513. *it++ = psz;
  514. n = traits_type::str_len(get_system16_directory());
  515. traits_type::char_copy(psz, get_system16_directory(), n + 1);
  516. psz += n;
  517. ++psz;
  518. }
  519. // 5. Windows directory
  520. *it++ = psz;
  521. n = traits_type::str_len(get_windows_directory());
  522. traits_type::char_copy(psz, get_windows_directory(), n + 1);
  523. psz += n;
  524. ++psz;
  525. // 2.b. Current directory last?
  526. if( bIncludeCurrentDirectory &&
  527. bIncludeCurrentDirectoryLast)
  528. {
  529. *it++ = cwd;
  530. }
  531. // 6. Paths
  532. char_type const* begin = psz;
  533. char_type const* const end = begin + traits_type::get_environment_variable(disgusting_hack_("PATH", L"PATH"), psz, static_cast<DWORD>(m_buffer.end() - psz));
  534. char_type const* last;
  535. // Move along to the first valid item
  536. for(; begin != end; ++begin)
  537. {
  538. if(*begin != ';')
  539. {
  540. break;
  541. }
  542. }
  543. for(last = begin; begin != end; ++begin)
  544. {
  545. if(*begin == ';')
  546. {
  547. if(1 < begin - last)
  548. {
  549. *it++ = last;
  550. }
  551. *const_cast<char_type*>(begin) = '\0';
  552. last = begin + 1;
  553. }
  554. }
  555. if(1 < begin - last)
  556. {
  557. *it++ = last;
  558. }
  559. m_end = it;
  560. }
  561. template< ss_typename_param_k C
  562. , ss_typename_param_k T
  563. >
  564. inline basic_searchpath_sequence<C, T>::~basic_searchpath_sequence() stlsoft_throw_0()
  565. {}
  566. template< ss_typename_param_k C
  567. , ss_typename_param_k T
  568. >
  569. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::const_iterator basic_searchpath_sequence<C, T>::begin() const
  570. {
  571. return &m_values[0];
  572. }
  573. template< ss_typename_param_k C
  574. , ss_typename_param_k T
  575. >
  576. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::const_iterator basic_searchpath_sequence<C, T>::end() const
  577. {
  578. return m_end;
  579. }
  580. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  581. template< ss_typename_param_k C
  582. , ss_typename_param_k T
  583. >
  584. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::const_reverse_iterator basic_searchpath_sequence<C, T>::rbegin() const
  585. {
  586. return const_reverse_iterator(end());
  587. }
  588. template< ss_typename_param_k C
  589. , ss_typename_param_k T
  590. >
  591. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::const_reverse_iterator basic_searchpath_sequence<C, T>::rend() const
  592. {
  593. return const_reverse_iterator(begin());
  594. }
  595. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  596. template< ss_typename_param_k C
  597. , ss_typename_param_k T
  598. >
  599. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::size_type basic_searchpath_sequence<C, T>::size() const
  600. {
  601. return static_cast<size_type>(end() - begin());
  602. }
  603. template< ss_typename_param_k C
  604. , ss_typename_param_k T
  605. >
  606. inline ws_bool_t basic_searchpath_sequence<C, T>::empty() const
  607. {
  608. return begin() == end();
  609. }
  610. template< ss_typename_param_k C
  611. , ss_typename_param_k T
  612. >
  613. inline /* static */ ss_typename_type_ret_k basic_searchpath_sequence<C, T>::size_type basic_searchpath_sequence<C, T>::max_size()
  614. {
  615. // Kind of kludgy, sigh.
  616. return static_cast<size_type>(-1) / WINSTL_CONST_MAX_PATH;
  617. }
  618. template< ss_typename_param_k C
  619. , ss_typename_param_k T
  620. >
  621. inline ss_typename_type_ret_k basic_searchpath_sequence<C, T>::value_type basic_searchpath_sequence<C, T>::operator [](ss_typename_type_k basic_searchpath_sequence<C, T>::size_type index) const
  622. {
  623. WINSTL_MESSAGE_ASSERT("Invalid index in search path sequence", !(size() < index));
  624. return begin()[index];
  625. }
  626. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  627. /* ////////////////////////////////////////////////////////////////////// */
  628. #ifndef _WINSTL_NO_NAMESPACE
  629. # if defined(_STLSOFT_NO_NAMESPACE) || \
  630. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  631. } // namespace winstl
  632. # else
  633. } // namespace winstl_project
  634. } // namespace stlsoft
  635. # endif /* _STLSOFT_NO_NAMESPACE */
  636. #endif /* !_WINSTL_NO_NAMESPACE */
  637. /* ////////////////////////////////////////////////////////////////////// */
  638. #endif /* WINSTL_INCL_WINSTL_SYSTEM_HPP_SEARCHPATH_SEQUENCE */
  639. /* ///////////////////////////// end of file //////////////////////////// */