1 /*
2  * Copyright 2017 Doug Lyons
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 /* Documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/bb759975(v=vs.85).aspx */
20 
21 #include <apitest.h>
22 #include <shlwapi.h>
23 #include <strsafe.h>
24 
25 #define DO_TEST(exp, str) \
26 do { \
27      StrFormatByteSizeW(exp, lpszDest, cchMax);\
28      if (lpszDest[1] == L',') lpszDest[1] = L'.';\
29      ok(_wcsicmp(lpszDest, (str)) == 0, "Expected %s got %s\n",\
30            wine_dbgstr_w((str)), wine_dbgstr_w((lpszDest)));\
31 } while (0)
32 
33 WCHAR lpszDest[260];
34 UINT cchMax=260;
35 
36 /* Returns true if the user interface is in English. Note that this does not
37  * presume of the formatting of dates, numbers, etc.
38  * Taken from WINE.
39  */
40 static BOOL is_lang_english(void)
41 {
42     static HMODULE hkernel32 = NULL;
43     static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
44     static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
45 
46     if (!hkernel32)
47     {
48         hkernel32 = GetModuleHandleA("kernel32.dll");
49         pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
50         pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
51     }
52 
53     if (pGetThreadUILanguage)
54         return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
55     if (pGetUserDefaultUILanguage)
56         return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
57 
58     return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
59 }
60 
61 /* Returns true if the dates, numbers, etc. are formatted using English
62  * conventions.
63  * Taken from WINE.
64  */
65 static BOOL is_locale_english(void)
66 {
67     /* Surprisingly GetThreadLocale() is irrelevant here */
68     LANGID langid = PRIMARYLANGID(GetUserDefaultLangID());
69     /* With the checks in DO_TEST, DUTCH can be used here as well.
70     TODO: Add other combinations that should work. */
71     return langid == LANG_ENGLISH || langid == LANG_DUTCH;
72 }
73 
74 START_TEST(StrFormatByteSizeW)
75 {
76     /* language-dependent test */
77     if (!is_lang_english() || !is_locale_english())
78     {
79         skip("An English UI and locale is required for the StrFormat*Size tests\n");
80         return;
81     }
82     DO_TEST(0, L"0 bytes");                            // 0x0
83     DO_TEST(1, L"1 bytes");                            // 0x1
84     DO_TEST(1024, L"1.00 KB");                         // 0x400
85     DO_TEST(1048576, L"1.00 MB");                      // 0x100000
86     DO_TEST(1073741824, L"1.00 GB");                   // 0x40000000
87     DO_TEST(0x70000000, L"1.75 GB");                   // 0x70000000
88     DO_TEST(0x80000000, L"2.00 GB");                   // 0x80000000
89     DO_TEST(0x100000000, L"4.00 GB");                  // 0x100000000
90     DO_TEST(1099511627776, L"1.00 TB");                // 0x10000000000
91     DO_TEST(1125899906842624, L"1.00 PB");             // 0x4000000000000
92     DO_TEST(1152921504606846976, L"1.00 EB");          // 0x1000000000000000
93     DO_TEST(2305843009213693952, L"2.00 EB");          // 0x2000000000000000
94     DO_TEST(4611686018427387904, L"4.00 EB");          // 0x4000000000000000
95     DO_TEST(0x7fffffffffffffff, L"7.99 EB");           // 0x7fffffffffffffff
96     DO_TEST(0x8000000000000000, L"0 bytes");           // 0x8000000000000000  High Bit Set Here
97     DO_TEST(0xffffffff00000000, L"0 bytes");           // 0xffffffff00000000
98     DO_TEST(0xffffffff00000001, L"1 bytes");           // 0xffffffff00000001
99     DO_TEST(0xffffffff70000000, L"1879048192 bytes");  // 0xffffffff70000000
100     DO_TEST(0xffffffff7fffffff, L"2147483647 bytes");  // 0xffffffff7fffffff
101     DO_TEST(0xffffffff80000000, L"-2147483648 bytes"); // 0xffffffff80000000 // Maximum Negative Number -2.00 GB
102     DO_TEST(0xffffffff80000001, L"-2147483647 bytes"); // 0xffffffff80000001
103     DO_TEST(0xffffffff90000000, L"-1879048192 bytes"); // 0xffffffff90000000
104     DO_TEST(-1073741824, L"-1073741824 bytes");        // 0xffffffffc0000000  -1.00 GB
105     DO_TEST(-1048576, L"-1048576 bytes");              // 0xfffffffffff00000  -1.00 MB
106     DO_TEST(-1024, L"-1024 bytes");                    // 0xfffffffffffffc00  -1.00 KB
107     DO_TEST(0xffffffffffffffff, L"-1 bytes");          // 0xffffffffffffffff
108 
109     // Here are some large negative tests and they all return zero bytes
110 
111     DO_TEST(-4294967296, L"0 bytes");           // 0xffffffff00000000
112     DO_TEST(-8589934592, L"0 bytes");           // 0xfffffffe00000000
113     DO_TEST(-17179869184, L"0 bytes");          // 0xfffffffc00000000
114     DO_TEST(-34359738368, L"0 bytes");          // 0xfffffff800000000
115     DO_TEST(-68719476736, L"0 bytes");          // 0xfffffff000000000
116     DO_TEST(-137438953472, L"0 bytes");         // 0xffffffe000000000
117     DO_TEST(-274877906944, L"0 bytes");         // 0xffffffc000000000
118     DO_TEST(-549755813888, L"0 bytes");         // 0xffffff8000000000
119     DO_TEST(-1099511627776, L"0 bytes");        // 0xffffff0000000000
120     DO_TEST(-1152921504606846976, L"0 bytes");  // 0xf000000000000000
121 
122     // These statements create compile errors and seem to be compiler conversion related
123     //DO_TEST(2147483648, L"2.00 GB");         //  2.00 GB & This gives a compile error
124     //DO_TEST(-2147483648, L"0 bytes");        // -2.00 GB & This gives a compile error
125 }
126