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.

1292 lines
42 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/system/system_traits.hpp
  3. *
  4. * Purpose: Contains the system_traits template class, and ANSI and
  5. * Unicode specialisations thereof.
  6. *
  7. * Created: 15th November 2002
  8. * Updated: 10th September 2011
  9. *
  10. * Thanks to: Austin Ziegler for spotting the defective pre-condition
  11. * enforcement of expand_environment_strings().
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 2002-2011, Matthew Wilson and Synesis Software
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are
  20. * met:
  21. *
  22. * - Redistributions of source code must retain the above copyright notice,
  23. * this list of conditions and the following disclaimer.
  24. * - Redistributions in binary form must reproduce the above copyright
  25. * notice, this list of conditions and the following disclaimer in the
  26. * documentation and/or other materials provided with the distribution.
  27. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the
  28. * names of any contributors may be used to endorse or promote products
  29. * derived from this software without specific prior written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  32. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  33. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  35. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  36. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  37. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  38. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  39. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  40. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  41. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. *
  43. * ////////////////////////////////////////////////////////////////////// */
  44. /** \file winstl/system/system_traits.hpp
  45. *
  46. * \brief [C++ only] Definition of the winstl::system_traits traits
  47. * class
  48. * (\ref group__library__system "System" Library).
  49. */
  50. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS
  51. #define WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS
  52. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  53. # define WINSTL_VER_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS_MAJOR 5
  54. # define WINSTL_VER_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS_MINOR 6
  55. # define WINSTL_VER_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS_REVISION 1
  56. # define WINSTL_VER_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS_EDIT 131
  57. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  58. /* /////////////////////////////////////////////////////////////////////////
  59. * Includes
  60. */
  61. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  62. # include <winstl/winstl.h>
  63. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  64. #ifndef STLSOFT_INCL_STLSOFT_INTERNAL_H_SAFESTR
  65. # include <stlsoft/internal/safestr.h>
  66. #endif /* !STLSOFT_INCL_STLSOFT_INTERNAL_H_SAFESTR */
  67. #if defined(WINSTL_OS_IS_WIN64) || \
  68. defined(_Wp64)
  69. # define _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  70. #endif /* _WIN64 || _M_IA64 */
  71. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  72. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  73. # ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_TRUNCATION_CAST
  74. # include <stlsoft/conversion/truncation_cast.hpp>
  75. # endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_TRUNCATION_CAST */
  76. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  77. # ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_TRUNCATION_TEST
  78. # include <stlsoft/conversion/truncation_test.hpp>
  79. # endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_TRUNCATION_TEST */
  80. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  81. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  82. #ifndef STLSOFT_INCL_H_STRING
  83. # define STLSOFT_INCL_H_STRING
  84. # include <string.h>
  85. #endif /* !STLSOFT_INCL_H_STRING */
  86. #ifndef STLSOFT_INCL_H_WCHAR
  87. # define STLSOFT_INCL_H_WCHAR
  88. # include <wchar.h>
  89. #endif /* !STLSOFT_INCL_H_WCHAR */
  90. /* /////////////////////////////////////////////////////////////////////////
  91. * Namespace
  92. */
  93. #ifndef _WINSTL_NO_NAMESPACE
  94. # if defined(_STLSOFT_NO_NAMESPACE) || \
  95. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  96. /* There is no stlsoft namespace, so must define ::winstl */
  97. namespace winstl
  98. {
  99. # else
  100. /* Define stlsoft::winstl_project */
  101. namespace stlsoft
  102. {
  103. namespace winstl_project
  104. {
  105. # endif /* _STLSOFT_NO_NAMESPACE */
  106. #endif /* !_WINSTL_NO_NAMESPACE */
  107. /* /////////////////////////////////////////////////////////////////////////
  108. * Classes
  109. */
  110. #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
  111. /** Traits for accessing the correct system functions for a given
  112. * character type.
  113. *
  114. * \ingroup group__library__system
  115. *
  116. * system_traits is a traits class for determining the correct system
  117. * structures and functions for a given character type.
  118. *
  119. * \param C The character type (e.g. \c char, \c wchar_t)
  120. */
  121. template <ss_typename_param_k C>
  122. struct system_traits
  123. {
  124. /// \name Types
  125. /// @{
  126. public:
  127. /// The character type
  128. typedef C char_type;
  129. /// The size type
  130. typedef ws_size_t size_type;
  131. /// The difference type
  132. typedef ws_ptrdiff_t difference_type;
  133. /// The current instantion of the type
  134. typedef system_traits<C> class_type;
  135. /// The (signed) integer type
  136. typedef ws_int_t int_type;
  137. /// The Boolean type
  138. typedef ws_bool_t bool_type;
  139. /// The type of a handle to a dynamically loaded module
  140. typedef HMODULE module_type;
  141. /// The type of a handle to a kernel object
  142. typedef HANDLE handle_type;
  143. /// The type of system result codes
  144. typedef DWORD result_code_type;
  145. /// The type of system error codes
  146. typedef DWORD error_type;
  147. /// @}
  148. /// \name General string handling
  149. /// @{
  150. public:
  151. /// Copies a specific number of characters from the source to the destination
  152. static char_type* char_copy(char_type* dest, char_type const* src, size_type n);
  153. #if !defined(STLSOFT_USING_SAFE_STR_FUNCTIONS) || \
  154. defined(_CRT_SECURE_NO_DEPRECATE)
  155. /// Copies the contents of \c src to \c dest
  156. static char_type* str_copy(char_type* dest, char_type const* src);
  157. /// Copies the contents of \c src to \c dest, up to cch \c characters
  158. static char_type* str_n_copy(char_type* dest, char_type const* src, size_type cch);
  159. /// Appends the contents of \c src to \c dest
  160. static char_type* str_cat(char_type* dest, char_type const* src);
  161. /// Appends the contents of \c src to \c dest, up to cch \c characters
  162. static char_type* str_n_cat(char_type* dest, char_type const* src, size_type cch);
  163. #endif /* !STLSOFT_USING_SAFE_STR_FUNCTIONS || _CRT_SECURE_NO_DEPRECATE */
  164. /// Compares the contents of \c src and \c dest
  165. static int_type str_compare(char_type const* s1, char_type const* s2);
  166. /// Compares the contents of \c src and \c dest in a case-insensitive fashion
  167. static int_type str_compare_no_case(char_type const* s1, char_type const* s2);
  168. /// Compares the contents of \c src and \c dest up to \c cch characters
  169. static int_type str_n_compare(char_type const* s1, char_type const* s2, size_type cch);
  170. /// Compares the contents of \c src and \c dest up to \c cch characters
  171. static int_type str_n_compare_no_case(char_type const* s1, char_type const* s2, size_type cch);
  172. /// Evaluates the length of \c src
  173. static size_type str_len(char_type const* src);
  174. /// Finds the given character \c ch in \c s
  175. static char_type* str_chr(char_type const* s, char_type ch);
  176. /// Finds the rightmost instance \c ch in \c s
  177. static char_type* str_rchr(char_type const* s, char_type ch);
  178. /// Finds the given substring \c sub in \c s
  179. static char_type* str_str(char_type const* s, char_type const* sub);
  180. /// Finds one of a set of characters in \c s
  181. static char_type* str_pbrk(char_type const* s, char_type const* charSet);
  182. /// Returns a pointer to the end of the string
  183. static char_type* str_end(char_type const* s);
  184. /// Sets each character in \c s to the character \c c
  185. ///
  186. /// \return s + n
  187. static char_type* str_set(char_type* s, size_type n, char_type c);
  188. /// @}
  189. /// \name Locale management
  190. /// @{
  191. public:
  192. /// Returns the locale information
  193. #ifndef NONLS
  194. static int_type get_locale_info(LCID locale, LCTYPE type, char_type* data, int_type cchData);
  195. #endif /* !NONLS */
  196. /// @}
  197. /// \name Module Paths
  198. /// @{
  199. public:
  200. /// Gets the full path name of the given module
  201. static size_type get_module_filename(HMODULE hModule, char_type* buffer, size_type cchBuffer);
  202. /// Gets the full path name of the directory of the given module
  203. static size_type get_module_directory(HMODULE hModule, char_type* buffer, size_type cchBuffer);
  204. /// Gets the full path name of the system directory
  205. static size_type get_system_directory(char_type* buffer, size_type cchBuffer);
  206. /// Gets the full path name of the windows directory
  207. static size_type get_windows_directory(char_type* buffer, size_type cchBuffer);
  208. /// @}
  209. /// \name Dynamic Loading
  210. /// @{
  211. public:
  212. /// Loads the given executable module
  213. static module_type load_library(char_type const* name);
  214. /// Closes the given executable module
  215. static bool_type free_library(module_type hModule);
  216. /// Retrieves the given symbol from the library
  217. static FARPROC find_symbol(module_type hModule, char const* symbolName);
  218. /// @}
  219. /// \name Kernel object control
  220. /// @{
  221. public:
  222. /// Closes the given operating system handle
  223. static bool_type close_handle(handle_type h);
  224. /// @}
  225. /// \name Error
  226. /// @{
  227. public:
  228. /// Gives the last error
  229. static error_type get_last_error();
  230. /// Sets the last error
  231. static void set_last_error(error_type er);
  232. /// @}
  233. /// \name Environment
  234. /// @{
  235. public:
  236. /// Gets an environment variable into the given buffer
  237. ///
  238. /// \param name The name of the variable to find
  239. /// \param buffer The buffer in which to write the variable. If this is NULL, then the required length is returned
  240. /// \param cchBuffer The size of the buffer, in characters
  241. ///
  242. /// \pre NULL != name
  243. static size_type get_environment_variable(char_type const* name, char_type* buffer, size_type cchBuffer);
  244. /// Expands environment strings in \c src into \c buffer, up to a maximum \c cchDest characters
  245. static size_type expand_environment_strings(char_type const* src, char_type* buffer, size_type cchBuffer);
  246. /// @}
  247. };
  248. #else /* ? STLSOFT_DOCUMENTATION_SKIP_SECTION */
  249. template <ss_typename_param_k C>
  250. struct system_traits;
  251. struct system_traits_
  252. {
  253. public:
  254. typedef ws_size_t size_type;
  255. typedef ws_ptrdiff_t difference_type;
  256. typedef system_traits_ class_type;
  257. typedef ws_int_t int_type;
  258. typedef ws_bool_t bool_type;
  259. typedef HMODULE module_type;
  260. typedef HANDLE handle_type;
  261. typedef DWORD result_code_type;
  262. typedef DWORD error_type;
  263. class scoped_mem_block
  264. {
  265. public:
  266. ss_explicit_k scoped_mem_block(void* block)
  267. : m_block(block)
  268. {}
  269. ~scoped_mem_block() stlsoft_throw_0()
  270. {
  271. ::HeapFree(::GetProcessHeap(), 0, m_block);
  272. }
  273. private:
  274. scoped_mem_block(scoped_mem_block const&);
  275. scoped_mem_block& operator =(scoped_mem_block const&);
  276. public:
  277. static ws_char_a_t* allocate_string_buffer_a(size_type n)
  278. {
  279. return static_cast<ws_char_a_t*>(::HeapAlloc(::GetProcessHeap(), 0, sizeof(ws_char_a_t) * (1 + n)));
  280. }
  281. static ws_char_w_t* allocate_string_buffer_w(size_type n)
  282. {
  283. return static_cast<ws_char_w_t*>(::HeapAlloc(::GetProcessHeap(), 0, sizeof(ws_char_w_t) * (1 + n)));
  284. }
  285. public:
  286. void* get() const
  287. {
  288. return m_block;
  289. }
  290. private:
  291. void* m_block;
  292. };
  293. public:
  294. static bool_type close_handle(handle_type h)
  295. {
  296. return FALSE != ::CloseHandle(h);
  297. }
  298. public:
  299. static bool_type free_library(module_type hModule)
  300. {
  301. return FALSE != ::FreeLibrary(hModule);
  302. }
  303. static FARPROC find_symbol(module_type hModule, char const* symbolName)
  304. {
  305. return ::GetProcAddress(hModule, symbolName);
  306. }
  307. public:
  308. static error_type get_last_error()
  309. {
  310. return ::GetLastError();
  311. }
  312. static void set_last_error(error_type er)
  313. {
  314. ::SetLastError(er);
  315. }
  316. };
  317. STLSOFT_TEMPLATE_SPECIALISATION
  318. struct system_traits<ws_char_a_t>
  319. {
  320. public:
  321. typedef ws_char_a_t char_type;
  322. typedef ws_size_t size_type;
  323. typedef ws_ptrdiff_t difference_type;
  324. typedef system_traits<char_type> class_type;
  325. typedef ws_int_t int_type;
  326. typedef ws_bool_t bool_type;
  327. typedef HMODULE module_type;
  328. typedef HANDLE handle_type;
  329. typedef DWORD result_code_type;
  330. typedef DWORD error_type;
  331. public:
  332. static char_type* char_copy(char_type* dest, char_type const* src, size_type n)
  333. {
  334. WINSTL_ASSERT(NULL != dest);
  335. WINSTL_ASSERT(0 == n || NULL != src);
  336. return static_cast<char_type*>(::memcpy(dest, src, sizeof(char_type) * n));
  337. }
  338. #if !defined(STLSOFT_USING_SAFE_STR_FUNCTIONS) || \
  339. defined(_CRT_SECURE_NO_DEPRECATE)
  340. static char_type* str_copy(char_type* dest, char_type const* src)
  341. {
  342. WINSTL_ASSERT(NULL != dest);
  343. WINSTL_ASSERT(NULL != src);
  344. # ifdef STLSOFT_MIN_CRT
  345. return ::lstrcpyA(dest, src);
  346. # else /*? STLSOFT_MIN_CRT */
  347. return ::strcpy(dest, src);
  348. # endif /* STLSOFT_MIN_CRT */
  349. }
  350. static char_type* str_n_copy(char_type* dest, char_type const* src, size_type cch)
  351. {
  352. WINSTL_ASSERT(NULL != dest);
  353. WINSTL_ASSERT(0 == cch || NULL != src);
  354. return ::strncpy(dest, src, cch);
  355. }
  356. static char_type* str_cat(char_type* dest, char_type const* src)
  357. {
  358. WINSTL_ASSERT(NULL != dest);
  359. WINSTL_ASSERT(NULL != src);
  360. # ifdef STLSOFT_MIN_CRT
  361. return ::lstrcatA(dest, src);
  362. # else /*? STLSOFT_MIN_CRT */
  363. return ::strcat(dest, src);
  364. # endif /* STLSOFT_MIN_CRT */
  365. }
  366. static char_type* str_n_cat(char_type* dest, char_type const* src, size_type cch)
  367. {
  368. WINSTL_ASSERT(NULL != dest);
  369. WINSTL_ASSERT(NULL != src);
  370. return ::strncat(dest, src, cch);
  371. }
  372. #endif /* !STLSOFT_USING_SAFE_STR_FUNCTIONS || _CRT_SECURE_NO_DEPRECATE */
  373. static int_type str_compare(char_type const* s1, char_type const* s2)
  374. {
  375. WINSTL_ASSERT(NULL != s1);
  376. WINSTL_ASSERT(NULL != s2);
  377. #ifdef STLSOFT_MIN_CRT
  378. return ::lstrcmpA(s1, s2);
  379. #else /*? STLSOFT_MIN_CRT */
  380. return ::strcmp(s1, s2);
  381. #endif /* STLSOFT_MIN_CRT */
  382. }
  383. static int_type str_compare_no_case(char_type const* s1, char_type const* s2)
  384. {
  385. WINSTL_ASSERT(NULL != s1);
  386. WINSTL_ASSERT(NULL != s2);
  387. return ::lstrcmpiA(s1, s2);
  388. }
  389. static int_type str_n_compare(char_type const* s1, char_type const* s2, size_type cch)
  390. {
  391. WINSTL_ASSERT(NULL != s1);
  392. WINSTL_ASSERT(NULL != s2);
  393. return ::strncmp(s1, s2, cch);
  394. }
  395. // TODO: move all these into internal, C-compatible, service files
  396. //
  397. // #include <stlsoft/system/apis/string/strnicmp.h
  398. #ifdef WINSTL_SYSTEM_TRAITS_HAS_strnicmp_
  399. # undef WINSTL_SYSTEM_TRAITS_HAS_strnicmp_
  400. #endif /* WINSTL_SYSTEM_TRAITS_HAS_strnicmp_ */
  401. #ifdef WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  402. # undef WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  403. #endif /* WINSTL_SYSTEM_TRAITS_HAS__strnicmp_ */
  404. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  405. # if !defined(__STDC__)
  406. # define WINSTL_SYSTEM_TRAITS_HAS_strnicmp_
  407. # endif
  408. # if !defined(__MFC_COMPAT__)
  409. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  410. # endif
  411. #elif defined(STLSOFT_COMPILER_IS_DMC)
  412. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  413. #elif defined(STLSOFT_COMPILER_IS_GCC)
  414. # if !defined(__STRICT_ANSI__)
  415. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  416. # endif
  417. #elif defined(STLSOFT_COMPILER_IS_INTEL) || \
  418. defined(STLSOFT_COMPILER_IS_MSVC)
  419. # if !defined(__STDC__) && \
  420. !defined(STLSOFT_USING_SAFE_STR_FUNCTIONS)
  421. # define WINSTL_SYSTEM_TRAITS_HAS_strnicmp_
  422. # endif
  423. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  424. #elif defined(STLSOFT_COMPILER_IS_MWERKS)
  425. # define WINSTL_SYSTEM_TRAITS_HAS_strnicmp_
  426. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  427. #elif defined(STLSOFT_COMPILER_IS_WATCOM)
  428. # define WINSTL_SYSTEM_TRAITS_HAS__strnicmp_
  429. #endif /* compiler */
  430. #if defined(WINSTL_SYSTEM_TRAITS_HAS_strnicmp_) || \
  431. defined(WINSTL_SYSTEM_TRAITS_HAS__strnicmp_)
  432. static int_type str_n_compare_no_case(char_type const* s1, char_type const* s2, size_type cch)
  433. {
  434. WINSTL_ASSERT(NULL != s1);
  435. WINSTL_ASSERT(NULL != s2);
  436. # if defined(WINSTL_SYSTEM_TRAITS_HAS_strnicmp_)
  437. return ::strnicmp(s1, s2, cch);
  438. # elif defined(WINSTL_SYSTEM_TRAITS_HAS__strnicmp_)
  439. return ::_strnicmp(s1, s2, cch);
  440. # else
  441. # error
  442. # endif
  443. }
  444. #else /* ? compiler */
  445. static int_type str_n_compare_no_case(char_type const* s1, char_type const* s2, size_type cch);
  446. #endif /* compiler */
  447. static size_type str_len(char_type const* src)
  448. {
  449. WINSTL_ASSERT(NULL != src);
  450. #ifdef STLSOFT_MIN_CRT
  451. return static_cast<size_type>(::lstrlenA(src));
  452. #else /*? STLSOFT_MIN_CRT */
  453. return ::strlen(src);
  454. #endif /* STLSOFT_MIN_CRT */
  455. }
  456. static char_type* str_chr(char_type const* s, char_type ch)
  457. {
  458. WINSTL_ASSERT(NULL != s);
  459. return const_cast<char_type*>(::strchr(s, ch));
  460. }
  461. static char_type* str_rchr(char_type const* s, char_type ch)
  462. {
  463. WINSTL_ASSERT(NULL != s);
  464. return const_cast<char_type*>(::strrchr(s, ch));
  465. }
  466. static char_type* str_str(char_type const* s, char_type const* sub)
  467. {
  468. WINSTL_ASSERT(NULL != s);
  469. WINSTL_ASSERT(NULL != sub);
  470. return const_cast<char_type*>(::strstr(s, sub));
  471. }
  472. static char_type* str_pbrk(char_type const* s, char_type const* charSet)
  473. {
  474. WINSTL_ASSERT(NULL != s);
  475. WINSTL_ASSERT(NULL != charSet);
  476. return const_cast<char_type*>(::strpbrk(s, charSet));
  477. }
  478. static char_type* str_end(char_type const* s)
  479. {
  480. WINSTL_ASSERT(NULL != s);
  481. for(; *s != '\0'; ++s)
  482. {}
  483. return const_cast<char_type*>(s);
  484. }
  485. static char_type* str_set(char_type* s, size_type n, char_type c)
  486. {
  487. WINSTL_ASSERT(NULL != s || 0u == n);
  488. for(; 0u != n; --n, ++s)
  489. {
  490. *s = c;
  491. }
  492. return s;
  493. }
  494. public:
  495. #ifndef NONLS
  496. static int_type get_locale_info(LCID locale, LCTYPE type, char_type* data, int cchData)
  497. {
  498. return ::GetLocaleInfoA(locale, type, data, cchData);
  499. }
  500. #endif /* !NONLS */
  501. public:
  502. static size_type get_module_filename(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  503. {
  504. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  505. if(0 == cchBuffer)
  506. {
  507. char_type buff[1 + WINSTL_CONST_MAX_PATH];
  508. return get_module_filename(hModule, &buff[0], STLSOFT_NUM_ELEMENTS(buff));
  509. }
  510. return class_type::GetModuleFileNameA(hModule, buffer, cchBuffer);
  511. }
  512. static size_type get_module_directory(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  513. {
  514. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  515. size_type cch = get_module_filename(hModule, buffer, cchBuffer);
  516. if( 0 != cch &&
  517. cch < cchBuffer)
  518. {
  519. buffer[cch] = '\0';
  520. char_type *s = str_rchr(buffer, '\\');
  521. if(NULL != s)
  522. {
  523. *s = '\0';
  524. cch = static_cast<size_type>(s - buffer);
  525. }
  526. }
  527. return cch;
  528. }
  529. static size_type get_system_directory(char_type* buffer, size_type cchBuffer)
  530. {
  531. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  532. return class_type::GetSystemDirectoryA(buffer, cchBuffer);
  533. }
  534. static size_type get_windows_directory(char_type* buffer, size_type cchBuffer)
  535. {
  536. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  537. return class_type::GetWindowsDirectoryA(buffer, cchBuffer);
  538. }
  539. public:
  540. static module_type load_library(char_type const* name)
  541. {
  542. WINSTL_ASSERT(NULL != name);
  543. return ::LoadLibraryA(name);
  544. }
  545. static bool_type free_library(module_type hModule)
  546. {
  547. return system_traits_::free_library(hModule);
  548. }
  549. static FARPROC find_symbol(module_type hModule, char const* symbolName)
  550. {
  551. WINSTL_ASSERT(NULL != symbolName);
  552. return system_traits_::find_symbol(hModule, symbolName);
  553. }
  554. static bool_type close_handle(handle_type h)
  555. {
  556. return system_traits_::close_handle(h);
  557. }
  558. public:
  559. static error_type get_last_error()
  560. {
  561. return system_traits_::get_last_error();
  562. }
  563. static void set_last_error(error_type er = error_type())
  564. {
  565. system_traits_::set_last_error(er);
  566. }
  567. public:
  568. static size_type get_environment_variable(char_type const* name, char_type* buffer, size_type cchBuffer)
  569. {
  570. WINSTL_ASSERT(NULL != name);
  571. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  572. char_type dummy[1];
  573. // If the buffer is NULL, we set it to a local buffer and cchBuffer
  574. // to 0, which will cause the API function to return the required
  575. // number of variables
  576. if(NULL == buffer)
  577. {
  578. buffer = &dummy[0];
  579. cchBuffer = 0u;
  580. }
  581. size_type n = class_type::GetEnvironmentVariableA(name, buffer, cchBuffer);
  582. if(n > cchBuffer)
  583. {
  584. --n; // GetEnvironmentVariable always gives size of string + nul terminator
  585. }
  586. if( 0u != cchBuffer &&
  587. n >= cchBuffer)
  588. {
  589. typedef system_traits_::scoped_mem_block scoped_mem_block;
  590. char_type* buffer2 = scoped_mem_block::allocate_string_buffer_a(n);
  591. if(NULL == buffer2)
  592. {
  593. return 0;
  594. }
  595. else
  596. {
  597. scoped_mem_block block(buffer2);
  598. size_type n2 = class_type::GetEnvironmentVariableA(name, buffer2, 1 + n);
  599. if(n2 > cchBuffer)
  600. {
  601. n2 = cchBuffer;
  602. }
  603. char_copy(buffer, buffer2, n2);
  604. return n2;
  605. }
  606. }
  607. return n;
  608. }
  609. static size_type expand_environment_strings(char_type const* src, char_type* dest, size_type cch_dest)
  610. {
  611. WINSTL_ASSERT(NULL != src);
  612. WINSTL_ASSERT(NULL != dest || 0 == cch_dest);
  613. return class_type::ExpandEnvironmentStringsA(src, dest, cch_dest);
  614. }
  615. private:
  616. static size_type GetModuleFileNameA(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  617. {
  618. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  619. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  620. return ::GetModuleFileNameA(hModule, buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  621. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  622. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  623. return ::GetModuleFileNameA(hModule, buffer, static_cast<DWORD>(cchBuffer));
  624. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  625. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  626. return ::GetModuleFileNameA(hModule, buffer, cchBuffer);
  627. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  628. }
  629. static size_type GetSystemDirectoryA(char_type* buffer, size_type cchBuffer)
  630. {
  631. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  632. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  633. return ::GetSystemDirectoryA(buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  634. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  635. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  636. return ::GetSystemDirectoryA(buffer, static_cast<DWORD>(cchBuffer));
  637. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  638. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  639. return ::GetSystemDirectoryA(buffer, cchBuffer);
  640. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  641. }
  642. static size_type GetWindowsDirectoryA(char_type* buffer, size_type cchBuffer)
  643. {
  644. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  645. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  646. return ::GetWindowsDirectoryA(buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  647. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  648. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  649. return ::GetWindowsDirectoryA(buffer, static_cast<DWORD>(cchBuffer));
  650. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  651. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  652. return ::GetWindowsDirectoryA(buffer, cchBuffer);
  653. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  654. }
  655. static size_type GetEnvironmentVariableA(char_type const* name, char_type* buffer, size_type cchBuffer)
  656. {
  657. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  658. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  659. return ::GetEnvironmentVariableA(name, buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  660. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  661. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  662. return ::GetEnvironmentVariableA(name, buffer, static_cast<DWORD>(cchBuffer));
  663. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  664. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  665. return ::GetEnvironmentVariableA(name, buffer, cchBuffer);
  666. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  667. }
  668. static size_type ExpandEnvironmentStringsA(char_type const* src, char_type* dest, size_type cch_dest)
  669. {
  670. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  671. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  672. return ::ExpandEnvironmentStringsA(src, dest, stlsoft_ns_qual(truncation_cast)<DWORD>(cch_dest));
  673. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  674. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cch_dest));
  675. return ::ExpandEnvironmentStringsA(src, dest, static_cast<DWORD>(cch_dest));
  676. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  677. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  678. return ::ExpandEnvironmentStringsA(src, dest, cch_dest);
  679. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  680. }
  681. };
  682. STLSOFT_TEMPLATE_SPECIALISATION
  683. struct system_traits<ws_char_w_t>
  684. {
  685. public:
  686. typedef ws_char_w_t char_type;
  687. typedef ws_size_t size_type;
  688. typedef ws_ptrdiff_t difference_type;
  689. typedef system_traits<char_type> class_type;
  690. typedef ws_int_t int_type;
  691. typedef ws_bool_t bool_type;
  692. typedef HMODULE module_type;
  693. typedef HANDLE handle_type;
  694. typedef DWORD result_code_type;
  695. typedef DWORD error_type;
  696. public:
  697. static char_type* char_copy(char_type* dest, char_type const* src, size_type n)
  698. {
  699. WINSTL_ASSERT(NULL != dest);
  700. WINSTL_ASSERT(0 == n || NULL != src);
  701. return static_cast<char_type*>(::memcpy(dest, src, sizeof(char_type) * n));
  702. }
  703. #if !defined(STLSOFT_USING_SAFE_STR_FUNCTIONS) || \
  704. defined(_CRT_SECURE_NO_DEPRECATE)
  705. static char_type* str_copy(char_type* dest, char_type const* src)
  706. {
  707. WINSTL_ASSERT(NULL != dest);
  708. WINSTL_ASSERT(NULL != src);
  709. # ifdef STLSOFT_MIN_CRT
  710. return ::lstrcpyW(dest, src);
  711. # else /*? STLSOFT_MIN_CRT */
  712. return ::wcscpy(dest, src);
  713. # endif /* STLSOFT_MIN_CRT */
  714. }
  715. static char_type* str_n_copy(char_type* dest, char_type const* src, size_type cch)
  716. {
  717. WINSTL_ASSERT(NULL != dest);
  718. WINSTL_ASSERT(0 == cch || NULL != src);
  719. return ::wcsncpy(dest, src, cch);
  720. }
  721. static char_type* str_cat(char_type* dest, char_type const* src)
  722. {
  723. WINSTL_ASSERT(NULL != dest);
  724. WINSTL_ASSERT(NULL != src);
  725. # ifdef STLSOFT_MIN_CRT
  726. return ::lstrcatW(dest, src);
  727. # else /*? STLSOFT_MIN_CRT */
  728. return ::wcscat(dest, src);
  729. # endif /* STLSOFT_MIN_CRT */
  730. }
  731. static char_type* str_n_cat(char_type* dest, char_type const* src, size_type cch)
  732. {
  733. WINSTL_ASSERT(NULL != dest);
  734. WINSTL_ASSERT(NULL != src);
  735. return ::wcsncat(dest, src, cch);
  736. }
  737. #endif /* !STLSOFT_USING_SAFE_STR_FUNCTIONS || _CRT_SECURE_NO_DEPRECATE */
  738. static int_type str_compare(char_type const* s1, char_type const* s2)
  739. {
  740. WINSTL_ASSERT(NULL != s1);
  741. WINSTL_ASSERT(NULL != s2);
  742. #ifdef STLSOFT_MIN_CRT
  743. return ::lstrcmpW(s1, s2);
  744. #else /*? STLSOFT_MIN_CRT */
  745. return ::wcscmp(s1, s2);
  746. #endif /* STLSOFT_MIN_CRT */
  747. }
  748. static int_type str_compare_no_case(char_type const* s1, char_type const* s2)
  749. {
  750. WINSTL_ASSERT(NULL != s1);
  751. WINSTL_ASSERT(NULL != s2);
  752. return ::lstrcmpiW(s1, s2);
  753. }
  754. static int_type str_n_compare(char_type const* s1, char_type const* s2, size_type cch)
  755. {
  756. WINSTL_ASSERT(NULL != s1);
  757. WINSTL_ASSERT(NULL != s2);
  758. return ::wcsncmp(s1, s2, cch);
  759. }
  760. // TODO: move all these into internal, C-compatible, service files
  761. //
  762. // #include <stlsoft/system/apis/string/wcsnicmp.h
  763. #ifdef WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_
  764. # undef WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_
  765. #endif /* WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_ */
  766. #ifdef WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  767. # undef WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  768. #endif /* WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_ */
  769. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  770. # if !defined(__STDC__)
  771. # define WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_
  772. # endif
  773. # if !defined(__MFC_COMPAT__)
  774. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  775. # endif
  776. #elif defined(STLSOFT_COMPILER_IS_DMC)
  777. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  778. #elif defined(STLSOFT_COMPILER_IS_GCC)
  779. # if !defined(__STRICT_ANSI__)
  780. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  781. # endif
  782. #elif defined(STLSOFT_COMPILER_IS_INTEL) || \
  783. defined(STLSOFT_COMPILER_IS_MSVC)
  784. # if !defined(__STDC__)
  785. # define WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_
  786. # endif
  787. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  788. #elif defined(STLSOFT_COMPILER_IS_MWERKS)
  789. # define WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_
  790. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  791. #elif defined(STLSOFT_COMPILER_IS_WATCOM)
  792. # define WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_
  793. #endif /* compiler */
  794. #if defined(WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_) || \
  795. defined(WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_)
  796. static int_type str_n_compare_no_case(char_type const* s1, char_type const* s2, size_type cch)
  797. {
  798. WINSTL_ASSERT(NULL != s1);
  799. WINSTL_ASSERT(NULL != s2);
  800. # if defined(WINSTL_SYSTEM_TRAITS_HAS__wcsnicmp_)
  801. return ::_wcsnicmp(s1, s2, cch);
  802. # elif defined(WINSTL_SYSTEM_TRAITS_HAS_wcsnicmp_)
  803. return ::wcsnicmp(s1, s2, cch);
  804. # else
  805. # error
  806. # endif
  807. }
  808. #else /* ? compiler */
  809. static int_type str_n_compare_no_case(char_type const* s1, char_type const* s2, size_type cch);
  810. #endif /* compiler */
  811. static size_type str_len(char_type const* src)
  812. {
  813. WINSTL_ASSERT(NULL != src);
  814. #ifdef STLSOFT_MIN_CRT
  815. return static_cast<size_type>(::lstrlenW(src));
  816. #else /*? STLSOFT_MIN_CRT */
  817. return ::wcslen(src);
  818. #endif /* STLSOFT_MIN_CRT */
  819. }
  820. static char_type* str_chr(char_type const* s, char_type ch)
  821. {
  822. WINSTL_ASSERT(NULL != s);
  823. return const_cast<char_type*>(::wcschr(s, ch));
  824. }
  825. static char_type* str_rchr(char_type const* s, char_type ch)
  826. {
  827. WINSTL_ASSERT(NULL != s);
  828. return const_cast<char_type*>(::wcsrchr(s, ch));
  829. }
  830. static char_type* str_str(char_type const* s, char_type const* sub)
  831. {
  832. WINSTL_ASSERT(NULL != s);
  833. WINSTL_ASSERT(NULL != sub);
  834. return const_cast<char_type*>(::wcsstr(s, sub));
  835. }
  836. static char_type* str_pbrk(char_type const* s, char_type const* charSet)
  837. {
  838. WINSTL_ASSERT(NULL != s);
  839. WINSTL_ASSERT(NULL != charSet);
  840. return const_cast<char_type*>(::wcspbrk(s, charSet));
  841. }
  842. static char_type* str_end(char_type const* s)
  843. {
  844. WINSTL_ASSERT(NULL != s);
  845. for(; *s != L'\0'; ++s)
  846. {}
  847. return const_cast<char_type*>(s);
  848. }
  849. static char_type* str_set(char_type* s, size_type n, char_type c)
  850. {
  851. WINSTL_ASSERT(NULL != s || 0u == n);
  852. for(; 0u != n; --n, ++s)
  853. {
  854. *s = c;
  855. }
  856. return s;
  857. }
  858. public:
  859. #ifndef NONLS
  860. static int_type get_locale_info(LCID locale, LCTYPE type, char_type* data, int cchData)
  861. {
  862. return ::GetLocaleInfoW(locale, type, data, cchData);
  863. }
  864. #endif /* !NONLS */
  865. public:
  866. static size_type get_module_filename(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  867. {
  868. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  869. if(0 == cchBuffer)
  870. {
  871. char_type buff[1 + WINSTL_CONST_MAX_PATH];
  872. size_type cch = get_module_filename(hModule, &buff[0], STLSOFT_NUM_ELEMENTS(buff));
  873. if(0 == str_compare(L"\\\\?\\", buff))
  874. {
  875. return CONST_NT_MAX_PATH;
  876. }
  877. else
  878. {
  879. return cch;
  880. }
  881. }
  882. return class_type::GetModuleFileNameW(hModule, buffer, cchBuffer);
  883. }
  884. static size_type get_module_directory(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  885. {
  886. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  887. size_type cch = get_module_filename(hModule, buffer, cchBuffer);
  888. if( 0 != cch &&
  889. cch < cchBuffer)
  890. {
  891. buffer[cch] = '\0';
  892. char_type *s = str_rchr(buffer, '\\');
  893. if(NULL != s)
  894. {
  895. *s = '\0';
  896. cch = static_cast<size_type>(s - buffer);
  897. }
  898. }
  899. return cch;
  900. }
  901. static size_type get_system_directory(char_type* buffer, size_type cchBuffer)
  902. {
  903. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  904. return class_type::GetSystemDirectoryW(buffer, cchBuffer);
  905. }
  906. static size_type get_windows_directory(char_type* buffer, size_type cchBuffer)
  907. {
  908. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  909. return class_type::GetWindowsDirectoryW(buffer, cchBuffer);
  910. }
  911. public:
  912. static module_type load_library(char_type const* name)
  913. {
  914. WINSTL_ASSERT(NULL != name);
  915. return ::LoadLibraryW(name);
  916. }
  917. static bool_type free_library(module_type hModule)
  918. {
  919. return system_traits_::free_library(hModule);
  920. }
  921. static FARPROC find_symbol(module_type hModule, char const* symbolName)
  922. {
  923. WINSTL_ASSERT(NULL != symbolName);
  924. return system_traits_::find_symbol(hModule, symbolName);
  925. }
  926. public:
  927. static bool_type close_handle(handle_type h)
  928. {
  929. return system_traits_::close_handle(h);
  930. }
  931. public:
  932. static error_type get_last_error()
  933. {
  934. return system_traits_::get_last_error();
  935. }
  936. static void set_last_error(error_type er = error_type())
  937. {
  938. system_traits_::set_last_error(er);
  939. }
  940. public:
  941. static size_type get_environment_variable(char_type const* name, char_type* buffer, size_type cchBuffer)
  942. {
  943. WINSTL_ASSERT(NULL != name);
  944. WINSTL_ASSERT(NULL != buffer || 0 == cchBuffer);
  945. char_type dummy[1];
  946. // If the buffer is NULL, we set it to a local buffer and cchBuffer
  947. // to 0, which will cause the API function to return the required
  948. // number of variables
  949. if(NULL == buffer)
  950. {
  951. buffer = &dummy[0];
  952. cchBuffer = 0u;
  953. }
  954. size_type n = class_type::GetEnvironmentVariableW(name, buffer, cchBuffer);
  955. if(n > cchBuffer)
  956. {
  957. --n; // GetEnvironmentVariable always gives size of string + nul terminator
  958. }
  959. if( 0u != cchBuffer &&
  960. n >= cchBuffer)
  961. {
  962. typedef system_traits_::scoped_mem_block scoped_mem_block;
  963. char_type* buffer2 = scoped_mem_block::allocate_string_buffer_w(n);
  964. if(NULL == buffer2)
  965. {
  966. return 0;
  967. }
  968. else
  969. {
  970. scoped_mem_block block(buffer2);
  971. size_type n2 = class_type::GetEnvironmentVariableW(name, buffer2, 1 + n);
  972. if(n2 > cchBuffer)
  973. {
  974. n2 = cchBuffer;
  975. }
  976. char_copy(buffer, buffer2, n2);
  977. return n2;
  978. }
  979. }
  980. return n;
  981. }
  982. static size_type expand_environment_strings(char_type const* src, char_type* dest, size_type cch_dest)
  983. {
  984. WINSTL_ASSERT(NULL != src);
  985. WINSTL_ASSERT(NULL != dest || 0 == cch_dest);
  986. return class_type::ExpandEnvironmentStringsW(src, dest, cch_dest);
  987. }
  988. private:
  989. static size_type GetModuleFileNameW(HMODULE hModule, char_type* buffer, size_type cchBuffer)
  990. {
  991. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  992. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  993. return ::GetModuleFileNameW(hModule, buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  994. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  995. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  996. return ::GetModuleFileNameW(hModule, buffer, static_cast<DWORD>(cchBuffer));
  997. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  998. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  999. return ::GetModuleFileNameW(hModule, buffer, cchBuffer);
  1000. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1001. }
  1002. static size_type GetSystemDirectoryW(char_type* buffer, size_type cchBuffer)
  1003. {
  1004. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  1005. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1006. return ::GetSystemDirectoryW(buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  1007. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  1008. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  1009. return ::GetSystemDirectoryW(buffer, static_cast<DWORD>(cchBuffer));
  1010. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1011. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1012. return ::GetSystemDirectoryW(buffer, cchBuffer);
  1013. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1014. }
  1015. static size_type GetWindowsDirectoryW(char_type* buffer, size_type cchBuffer)
  1016. {
  1017. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  1018. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1019. return ::GetWindowsDirectoryW(buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  1020. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  1021. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  1022. return ::GetWindowsDirectoryW(buffer, static_cast<DWORD>(cchBuffer));
  1023. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1024. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1025. return ::GetWindowsDirectoryW(buffer, cchBuffer);
  1026. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1027. }
  1028. static size_type GetEnvironmentVariableW(char_type const* name, char_type* buffer, size_type cchBuffer)
  1029. {
  1030. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  1031. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1032. return ::GetEnvironmentVariableW(name, buffer, stlsoft_ns_qual(truncation_cast)<DWORD>(cchBuffer));
  1033. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  1034. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cchBuffer));
  1035. return ::GetEnvironmentVariableW(name, buffer, static_cast<DWORD>(cchBuffer));
  1036. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1037. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1038. return ::GetEnvironmentVariableW(name, buffer, cchBuffer);
  1039. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1040. }
  1041. static size_type ExpandEnvironmentStringsW(char_type const* src, char_type* dest, size_type cch_dest)
  1042. {
  1043. #ifdef _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING
  1044. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1045. return ::ExpandEnvironmentStringsW(src, dest, stlsoft_ns_qual(truncation_cast)<DWORD>(cch_dest));
  1046. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  1047. WINSTL_MESSAGE_ASSERT("buffer size out of range", stlsoft_ns_qual(truncation_test)<DWORD>(cch_dest));
  1048. return ::ExpandEnvironmentStringsW(src, dest, static_cast<DWORD>(cch_dest));
  1049. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1050. #else /* ? _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1051. return ::ExpandEnvironmentStringsW(src, dest, cch_dest);
  1052. #endif /* _WINSTL_SYSTEM_TRAITS_USE_TRUNCATION_TESTING */
  1053. }
  1054. };
  1055. #endif /* STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1056. /* /////////////////////////////////////////////////////////////////////////
  1057. * Unit-testing
  1058. */
  1059. #ifdef STLSOFT_UNITTEST
  1060. # include "./unittest/system_traits_unittest_.h"
  1061. #endif /* STLSOFT_UNITTEST */
  1062. /* ////////////////////////////////////////////////////////////////////// */
  1063. #ifndef _WINSTL_NO_NAMESPACE
  1064. # if defined(_STLSOFT_NO_NAMESPACE) || \
  1065. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1066. } // namespace winstl
  1067. # else
  1068. } // namespace winstl_project
  1069. } // namespace stlsoft
  1070. # endif /* _STLSOFT_NO_NAMESPACE */
  1071. #endif /* !_WINSTL_NO_NAMESPACE */
  1072. /* ////////////////////////////////////////////////////////////////////// */
  1073. #endif /* WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_TRAITS */
  1074. /* ///////////////////////////// end of file //////////////////////////// */