aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Windows
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-21.07.tar.gz
7zip-21.07.tar.bz2
7zip-21.07.zip
'21.07'21.07
Diffstat (limited to 'CPP/Windows')
-rw-r--r--CPP/Windows/COM.cpp41
-rw-r--r--CPP/Windows/COM.h70
-rw-r--r--CPP/Windows/Clipboard.cpp130
-rw-r--r--CPP/Windows/Clipboard.h28
-rw-r--r--CPP/Windows/CommonDialog.cpp208
-rw-r--r--CPP/Windows/CommonDialog.h23
-rw-r--r--CPP/Windows/Console.cpp10
-rw-r--r--CPP/Windows/Console.h52
-rw-r--r--CPP/Windows/Control/ComboBox.cpp66
-rw-r--r--CPP/Windows/Control/ComboBox.h77
-rw-r--r--CPP/Windows/Control/CommandBar.h52
-rw-r--r--CPP/Windows/Control/Dialog.cpp414
-rw-r--r--CPP/Windows/Control/Dialog.h190
-rw-r--r--CPP/Windows/Control/Edit.h19
-rw-r--r--CPP/Windows/Control/ImageList.cpp10
-rw-r--r--CPP/Windows/Control/ImageList.h87
-rw-r--r--CPP/Windows/Control/ListView.cpp155
-rw-r--r--CPP/Windows/Control/ListView.h147
-rw-r--r--CPP/Windows/Control/ProgressBar.h35
-rw-r--r--CPP/Windows/Control/PropertyPage.cpp143
-rw-r--r--CPP/Windows/Control/PropertyPage.h50
-rw-r--r--CPP/Windows/Control/ReBar.h34
-rw-r--r--CPP/Windows/Control/Static.h28
-rw-r--r--CPP/Windows/Control/StatusBar.h42
-rw-r--r--CPP/Windows/Control/StdAfx.h8
-rw-r--r--CPP/Windows/Control/ToolBar.h43
-rw-r--r--CPP/Windows/Control/Trackbar.h27
-rw-r--r--CPP/Windows/Control/Window2.cpp200
-rw-r--r--CPP/Windows/Control/Window2.h51
-rw-r--r--CPP/Windows/DLL.cpp191
-rw-r--r--CPP/Windows/DLL.h84
-rw-r--r--CPP/Windows/Defs.h18
-rw-r--r--CPP/Windows/ErrorMsg.cpp133
-rw-r--r--CPP/Windows/ErrorMsg.h16
-rw-r--r--CPP/Windows/FileDir.cpp1129
-rw-r--r--CPP/Windows/FileDir.h125
-rw-r--r--CPP/Windows/FileFind.cpp1242
-rw-r--r--CPP/Windows/FileFind.h305
-rw-r--r--CPP/Windows/FileIO.cpp825
-rw-r--r--CPP/Windows/FileIO.h347
-rw-r--r--CPP/Windows/FileLink.cpp613
-rw-r--r--CPP/Windows/FileMapping.cpp12
-rw-r--r--CPP/Windows/FileMapping.h66
-rw-r--r--CPP/Windows/FileName.cpp893
-rw-r--r--CPP/Windows/FileName.h119
-rw-r--r--CPP/Windows/FileSystem.cpp135
-rw-r--r--CPP/Windows/FileSystem.h31
-rw-r--r--CPP/Windows/Handle.h39
-rw-r--r--CPP/Windows/MemoryGlobal.cpp36
-rw-r--r--CPP/Windows/MemoryGlobal.h55
-rw-r--r--CPP/Windows/MemoryLock.cpp112
-rw-r--r--CPP/Windows/MemoryLock.h40
-rw-r--r--CPP/Windows/Menu.cpp216
-rw-r--r--CPP/Windows/Menu.h158
-rw-r--r--CPP/Windows/NationalTime.cpp37
-rw-r--r--CPP/Windows/NationalTime.h20
-rw-r--r--CPP/Windows/Net.cpp370
-rw-r--r--CPP/Windows/Net.h86
-rw-r--r--CPP/Windows/NtCheck.h48
-rw-r--r--CPP/Windows/ProcessMessages.cpp22
-rw-r--r--CPP/Windows/ProcessMessages.h12
-rw-r--r--CPP/Windows/ProcessUtils.cpp102
-rw-r--r--CPP/Windows/ProcessUtils.h100
-rw-r--r--CPP/Windows/PropVariant.cpp361
-rw-r--r--CPP/Windows/PropVariant.h127
-rw-r--r--CPP/Windows/PropVariantConv.cpp138
-rw-r--r--CPP/Windows/PropVariantConv.h37
-rw-r--r--CPP/Windows/PropVariantUtils.cpp161
-rw-r--r--CPP/Windows/PropVariantUtils.h34
-rw-r--r--CPP/Windows/Registry.cpp406
-rw-r--r--CPP/Windows/Registry.h84
-rw-r--r--CPP/Windows/ResourceString.cpp103
-rw-r--r--CPP/Windows/ResourceString.h16
-rw-r--r--CPP/Windows/SecurityUtils.cpp181
-rw-r--r--CPP/Windows/SecurityUtils.h167
-rw-r--r--CPP/Windows/Shell.cpp358
-rw-r--r--CPP/Windows/Shell.h94
-rw-r--r--CPP/Windows/StdAfx.h8
-rw-r--r--CPP/Windows/Synchronization.cpp63
-rw-r--r--CPP/Windows/Synchronization.h393
-rw-r--r--CPP/Windows/System.cpp234
-rw-r--r--CPP/Windows/System.h129
-rw-r--r--CPP/Windows/SystemInfo.cpp917
-rw-r--r--CPP/Windows/SystemInfo.h18
-rw-r--r--CPP/Windows/Thread.h44
-rw-r--r--CPP/Windows/TimeUtils.cpp234
-rw-r--r--CPP/Windows/TimeUtils.h32
-rw-r--r--CPP/Windows/Window.cpp179
-rw-r--r--CPP/Windows/Window.h284
89 files changed, 14979 insertions, 0 deletions
diff --git a/CPP/Windows/COM.cpp b/CPP/Windows/COM.cpp
new file mode 100644
index 0000000..d0cb321
--- /dev/null
+++ b/CPP/Windows/COM.cpp
@@ -0,0 +1,41 @@
1// Windows/COM.cpp
2
3#include "StdAfx.h"
4
5/*
6
7#include "COM.h"
8#include "../Common/StringConvert.h"
9
10namespace NWindows {
11namespace NCOM {
12
13// CoInitialize (NULL); must be called!
14
15UString GUIDToStringW(REFGUID guid)
16{
17 UString s;
18 const unsigned kSize = 48;
19 StringFromGUID2(guid, s.GetBuf(kSize), kSize);
20 s.ReleaseBuf_CalcLen(kSize);
21 return s;
22}
23
24AString GUIDToStringA(REFGUID guid)
25{
26 return UnicodeStringToMultiByte(GUIDToStringW(guid));
27}
28
29HRESULT StringToGUIDW(const wchar_t *string, GUID &classID)
30{
31 return CLSIDFromString((wchar_t *)string, &classID);
32}
33
34HRESULT StringToGUIDA(const char *string, GUID &classID)
35{
36 return StringToGUIDW(MultiByteToUnicodeString(string), classID);
37}
38
39}}
40
41*/
diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
new file mode 100644
index 0000000..cee7f70
--- /dev/null
+++ b/CPP/Windows/COM.h
@@ -0,0 +1,70 @@
1// Windows/COM.h
2
3#ifndef __WINDOWS_COM_H
4#define __WINDOWS_COM_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NCOM {
10
11#ifdef _WIN32
12
13class CComInitializer
14{
15public:
16 CComInitializer()
17 {
18 #ifdef UNDER_CE
19 CoInitializeEx(NULL, COINIT_MULTITHREADED);
20 #else
21 // it's single thread. Do we need multithread?
22 CoInitialize(NULL);
23 #endif
24 };
25 ~CComInitializer() { CoUninitialize(); }
26};
27
28class CStgMedium
29{
30 STGMEDIUM _object;
31public:
32 bool _mustBeReleased;
33 CStgMedium(): _mustBeReleased(false) {}
34 ~CStgMedium() { Free(); }
35 void Free()
36 {
37 if (_mustBeReleased)
38 ReleaseStgMedium(&_object);
39 _mustBeReleased = false;
40 }
41 const STGMEDIUM* operator->() const { return &_object;}
42 STGMEDIUM* operator->() { return &_object;}
43 STGMEDIUM* operator&() { return &_object; }
44};
45
46#endif
47
48/*
49//////////////////////////////////
50// GUID <--> String Conversions
51UString GUIDToStringW(REFGUID guid);
52AString GUIDToStringA(REFGUID guid);
53#ifdef UNICODE
54 #define GUIDToString GUIDToStringW
55#else
56 #define GUIDToString GUIDToStringA
57#endif
58
59HRESULT StringToGUIDW(const wchar_t *string, GUID &classID);
60HRESULT StringToGUIDA(const char *string, GUID &classID);
61#ifdef UNICODE
62 #define StringToGUID StringToGUIDW
63#else
64 #define StringToGUID StringToGUIDA
65#endif
66*/
67
68}}
69
70#endif
diff --git a/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp
new file mode 100644
index 0000000..bc7e201
--- /dev/null
+++ b/CPP/Windows/Clipboard.cpp
@@ -0,0 +1,130 @@
1// Windows/Clipboard.cpp
2
3#include "StdAfx.h"
4
5#ifdef UNDER_CE
6#include <winuserm.h>
7#endif
8
9#include "../Common/StringConvert.h"
10
11#include "Clipboard.h"
12#include "Defs.h"
13#include "MemoryGlobal.h"
14#include "Shell.h"
15
16namespace NWindows {
17
18bool CClipboard::Open(HWND wndNewOwner) throw()
19{
20 m_Open = BOOLToBool(::OpenClipboard(wndNewOwner));
21 return m_Open;
22}
23
24bool CClipboard::Close() throw()
25{
26 if (!m_Open)
27 return true;
28 m_Open = !BOOLToBool(CloseClipboard());
29 return !m_Open;
30}
31
32bool ClipboardIsFormatAvailableHDROP()
33{
34 return BOOLToBool(IsClipboardFormatAvailable(CF_HDROP));
35}
36
37/*
38bool ClipboardGetTextString(AString &s)
39{
40 s.Empty();
41 if (!IsClipboardFormatAvailable(CF_TEXT))
42 return false;
43 CClipboard clipboard;
44
45 if (!clipboard.Open(NULL))
46 return false;
47
48 HGLOBAL h = ::GetClipboardData(CF_TEXT);
49 if (h != NULL)
50 {
51 NMemory::CGlobalLock globalLock(h);
52 const char *p = (const char *)globalLock.GetPointer();
53 if (p != NULL)
54 {
55 s = p;
56 return true;
57 }
58 }
59 return false;
60}
61*/
62
63/*
64bool ClipboardGetFileNames(UStringVector &names)
65{
66 names.Clear();
67 if (!IsClipboardFormatAvailable(CF_HDROP))
68 return false;
69 CClipboard clipboard;
70
71 if (!clipboard.Open(NULL))
72 return false;
73
74 HGLOBAL h = ::GetClipboardData(CF_HDROP);
75 if (h != NULL)
76 {
77 NMemory::CGlobalLock globalLock(h);
78 void *p = (void *)globalLock.GetPointer();
79 if (p != NULL)
80 {
81 NShell::CDrop drop(false);
82 drop.Attach((HDROP)p);
83 drop.QueryFileNames(names);
84 return true;
85 }
86 }
87 return false;
88}
89*/
90
91static bool ClipboardSetData(UINT uFormat, const void *data, size_t size) throw()
92{
93 NMemory::CGlobal global;
94 if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size))
95 return false;
96 {
97 NMemory::CGlobalLock globalLock(global);
98 LPVOID p = globalLock.GetPointer();
99 if (!p)
100 return false;
101 memcpy(p, data, size);
102 }
103 if (::SetClipboardData(uFormat, global) == NULL)
104 return false;
105 global.Detach();
106 return true;
107}
108
109bool ClipboardSetText(HWND owner, const UString &s)
110{
111 CClipboard clipboard;
112 if (!clipboard.Open(owner))
113 return false;
114 if (!::EmptyClipboard())
115 return false;
116
117 bool res;
118 res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Len() + 1) * sizeof(wchar_t));
119 #ifndef _UNICODE
120 AString a (UnicodeStringToMultiByte(s, CP_ACP));
121 if (ClipboardSetData(CF_TEXT, (const char *)a, (a.Len() + 1) * sizeof(char)))
122 res = true;
123 a = UnicodeStringToMultiByte(s, CP_OEMCP);
124 if (ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Len() + 1) * sizeof(char)))
125 res = true;
126 #endif
127 return res;
128}
129
130}
diff --git a/CPP/Windows/Clipboard.h b/CPP/Windows/Clipboard.h
new file mode 100644
index 0000000..60fedc1
--- /dev/null
+++ b/CPP/Windows/Clipboard.h
@@ -0,0 +1,28 @@
1// Windows/Clipboard.h
2
3#ifndef __CLIPBOARD_H
4#define __CLIPBOARD_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9
10class CClipboard
11{
12 bool m_Open;
13public:
14 CClipboard(): m_Open(false) {};
15 ~CClipboard() { Close(); }
16 bool Open(HWND wndNewOwner) throw();
17 bool Close() throw();
18};
19
20bool ClipboardIsFormatAvailableHDROP();
21
22// bool ClipboardGetFileNames(UStringVector &names);
23// bool ClipboardGetTextString(AString &s);
24bool ClipboardSetText(HWND owner, const UString &s);
25
26}
27
28#endif
diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp
new file mode 100644
index 0000000..eaaecad
--- /dev/null
+++ b/CPP/Windows/CommonDialog.cpp
@@ -0,0 +1,208 @@
1// Windows/CommonDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/MyWindows.h"
6
7#ifdef UNDER_CE
8#include <commdlg.h>
9#endif
10
11#ifndef _UNICODE
12#include "../Common/StringConvert.h"
13#endif
14
15#include "CommonDialog.h"
16#include "Defs.h"
17
18#ifndef _UNICODE
19extern bool g_IsNT;
20#endif
21
22namespace NWindows {
23
24#ifndef _UNICODE
25
26class CDoubleZeroStringListA
27{
28 LPTSTR Buf;
29 unsigned Size;
30public:
31 CDoubleZeroStringListA(LPSTR buf, unsigned size): Buf(buf), Size(size) {}
32 bool Add(LPCSTR s) throw();
33 void Finish() { *Buf = 0; }
34};
35
36bool CDoubleZeroStringListA::Add(LPCSTR s) throw()
37{
38 unsigned len = MyStringLen(s) + 1;
39 if (len >= Size)
40 return false;
41 MyStringCopy(Buf, s);
42 Buf += len;
43 Size -= len;
44 return true;
45}
46
47#endif
48
49class CDoubleZeroStringListW
50{
51 LPWSTR Buf;
52 unsigned Size;
53public:
54 CDoubleZeroStringListW(LPWSTR buf, unsigned size): Buf(buf), Size(size) {}
55 bool Add(LPCWSTR s) throw();
56 void Finish() { *Buf = 0; }
57};
58
59bool CDoubleZeroStringListW::Add(LPCWSTR s) throw()
60{
61 unsigned len = MyStringLen(s) + 1;
62 if (len >= Size)
63 return false;
64 MyStringCopy(Buf, s);
65 Buf += len;
66 Size -= len;
67 return true;
68}
69
70
71#ifdef UNDER_CE
72#define MY__OFN_PROJECT 0x00400000
73#define MY__OFN_SHOW_ALL 0x01000000
74#endif
75
76/* if (lpstrFilter == NULL && nFilterIndex == 0)
77 MSDN : "the system doesn't show any files",
78 but WinXP-64 shows all files. Why ??? */
79
80/*
81structures
82 OPENFILENAMEW
83 OPENFILENAMEA
84contain additional members:
85#if (_WIN32_WINNT >= 0x0500)
86 void *pvReserved;
87 DWORD dwReserved;
88 DWORD FlagsEx;
89#endif
90
91If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions
92will not work at NT 4.0, if we use sizeof(OPENFILENAME*).
93So we use size of old version of structure. */
94
95#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)
96// || !defined(WINVER)
97 #ifndef _UNICODE
98 #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)
99 #endif
100 #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)
101#else
102
103 // MinGW doesn't support some required macros. So we define them here:
104 #ifndef CDSIZEOF_STRUCT
105 #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
106 #endif
107 #ifndef _UNICODE
108 #ifndef OPENFILENAME_SIZE_VERSION_400A
109 #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
110 #endif
111 #endif
112 #ifndef OPENFILENAME_SIZE_VERSION_400W
113 #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
114 #endif
115
116 #ifndef _UNICODE
117 #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A
118 #endif
119 #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W
120#endif
121
122#ifndef _UNICODE
123#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }
124#endif
125
126bool MyGetOpenFileName(HWND hwnd, LPCWSTR title,
127 LPCWSTR initialDir,
128 LPCWSTR filePath,
129 LPCWSTR filterDescription,
130 LPCWSTR filter,
131 UString &resPath
132 #ifdef UNDER_CE
133 , bool openFolder
134 #endif
135 )
136{
137 const unsigned kBufSize = MAX_PATH * 2;
138 const unsigned kFilterBufSize = MAX_PATH;
139 if (!filter)
140 filter = L"*.*";
141 #ifndef _UNICODE
142 if (!g_IsNT)
143 {
144 CHAR buf[kBufSize];
145 MyStringCopy(buf, (const char *)GetSystemString(filePath));
146 // OPENFILENAME_NT4A
147 OPENFILENAMEA p;
148 memset(&p, 0, sizeof(p));
149 p.lStructSize = my_compatib_OPENFILENAMEA_size;
150 p.hwndOwner = hwnd;
151 CHAR filterBuf[kFilterBufSize];
152 {
153 CDoubleZeroStringListA dz(filterBuf, kFilterBufSize);
154 dz.Add(GetSystemString(filterDescription ? filterDescription : filter));
155 dz.Add(GetSystemString(filter));
156 dz.Finish();
157 p.lpstrFilter = filterBuf;
158 p.nFilterIndex = 1;
159 }
160
161 p.lpstrFile = buf;
162 p.nMaxFile = kBufSize;
163 CONV_U_To_A(p.lpstrInitialDir, initialDir, initialDirA);
164 CONV_U_To_A(p.lpstrTitle, title, titleA);
165 p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
166
167 bool res = BOOLToBool(::GetOpenFileNameA(&p));
168 resPath = GetUnicodeString(buf);
169 return res;
170 }
171 else
172 #endif
173 {
174 WCHAR buf[kBufSize];
175 MyStringCopy(buf, filePath);
176 // OPENFILENAME_NT4W
177 OPENFILENAMEW p;
178 memset(&p, 0, sizeof(p));
179 p.lStructSize = my_compatib_OPENFILENAMEW_size;
180 p.hwndOwner = hwnd;
181
182 WCHAR filterBuf[kFilterBufSize];
183 {
184 CDoubleZeroStringListW dz(filterBuf, kFilterBufSize);
185 dz.Add(filterDescription ? filterDescription : filter);
186 dz.Add(filter);
187 dz.Finish();
188 p.lpstrFilter = filterBuf;
189 p.nFilterIndex = 1;
190 }
191
192 p.lpstrFile = buf;
193 p.nMaxFile = kBufSize;
194 p.lpstrInitialDir = initialDir;
195 p.lpstrTitle = title;
196 p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY
197 #ifdef UNDER_CE
198 | (openFolder ? (MY__OFN_PROJECT | MY__OFN_SHOW_ALL) : 0)
199 #endif
200 ;
201
202 bool res = BOOLToBool(::GetOpenFileNameW(&p));
203 resPath = buf;
204 return res;
205 }
206}
207
208}
diff --git a/CPP/Windows/CommonDialog.h b/CPP/Windows/CommonDialog.h
new file mode 100644
index 0000000..aaf17ac
--- /dev/null
+++ b/CPP/Windows/CommonDialog.h
@@ -0,0 +1,23 @@
1// Windows/CommonDialog.h
2
3#ifndef __WINDOWS_COMMON_DIALOG_H
4#define __WINDOWS_COMMON_DIALOG_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9
10bool MyGetOpenFileName(HWND hwnd, LPCWSTR title,
11 LPCWSTR initialDir, // can be NULL, so dir prefix in filePath will be used
12 LPCWSTR filePath, // full path
13 LPCWSTR filterDescription, // like "All files (*.*)"
14 LPCWSTR filter, // like "*.exe"
15 UString &resPath
16 #ifdef UNDER_CE
17 , bool openFolder = false
18 #endif
19);
20
21}
22
23#endif
diff --git a/CPP/Windows/Console.cpp b/CPP/Windows/Console.cpp
new file mode 100644
index 0000000..28ba1c4
--- /dev/null
+++ b/CPP/Windows/Console.cpp
@@ -0,0 +1,10 @@
1// Windows/Console.cpp
2
3#include "StdAfx.h"
4
5#include "Console.h"
6
7namespace NWindows{
8namespace NConsole{
9
10}}
diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h
new file mode 100644
index 0000000..43e02fa
--- /dev/null
+++ b/CPP/Windows/Console.h
@@ -0,0 +1,52 @@
1// Windows/Console.h
2
3#ifndef __WINDOWS_CONSOLE_H
4#define __WINDOWS_CONSOLE_H
5
6#include "Defs.h"
7
8namespace NWindows {
9namespace NConsole {
10
11class CBase
12{
13protected:
14 HANDLE m_Object;
15public:
16 void Attach(HANDLE handle) { m_Object = handle; }
17 bool GetMode(DWORD &mode)
18 { return BOOLToBool(::GetConsoleMode(m_Object, &mode)); }
19 bool SetMode(DWORD mode)
20 { return BOOLToBool(::SetConsoleMode(m_Object, mode)); }
21};
22
23class CIn: public CBase
24{
25public:
26 bool PeekEvents(PINPUT_RECORD events, DWORD numEvents, DWORD &numEventsRead)
27 { return BOOLToBool(::PeekConsoleInput(m_Object, events, numEvents, &numEventsRead)); }
28 bool PeekEvent(INPUT_RECORD &event, DWORD &numEventsRead)
29 { return PeekEvents(&event, 1, numEventsRead); }
30 bool ReadEvents(PINPUT_RECORD events, DWORD numEvents, DWORD &numEventsRead)
31 { return BOOLToBool(::ReadConsoleInput(m_Object, events, numEvents, &numEventsRead)); }
32 bool ReadEvent(INPUT_RECORD &event, DWORD &numEventsRead)
33 { return ReadEvents(&event, 1, numEventsRead); }
34 bool GetNumberOfEvents(DWORD &numEvents)
35 { return BOOLToBool(::GetNumberOfConsoleInputEvents(m_Object, &numEvents)); }
36
37 bool WriteEvents(const INPUT_RECORD *events, DWORD numEvents, DWORD &numEventsWritten)
38 { return BOOLToBool(::WriteConsoleInput(m_Object, events, numEvents, &numEventsWritten)); }
39 bool WriteEvent(const INPUT_RECORD &event, DWORD &numEventsWritten)
40 { return WriteEvents(&event, 1, numEventsWritten); }
41
42 bool Read(LPVOID buffer, DWORD numChars, DWORD &numCharsRead)
43 { return BOOLToBool(::ReadConsole(m_Object, buffer, numChars, &numCharsRead, NULL)); }
44
45 bool Flush()
46 { return BOOLToBool(::FlushConsoleInputBuffer(m_Object)); }
47
48};
49
50}}
51
52#endif
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp
new file mode 100644
index 0000000..f6ed8d3
--- /dev/null
+++ b/CPP/Windows/Control/ComboBox.cpp
@@ -0,0 +1,66 @@
1// Windows/Control/ComboBox.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../../Common/StringConvert.h"
7#endif
8
9#include "ComboBox.h"
10
11#ifndef _UNICODE
12extern bool g_IsNT;
13#endif
14
15namespace NWindows {
16namespace NControl {
17
18LRESULT CComboBox::GetLBText(int index, CSysString &s)
19{
20 s.Empty();
21 LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character
22 if (len == CB_ERR)
23 return len;
24 LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len));
25 if (len2 == CB_ERR)
26 return len;
27 if (len > len2)
28 len = len2;
29 s.ReleaseBuf_CalcLen((unsigned)len);
30 return len;
31}
32
33#ifndef _UNICODE
34LRESULT CComboBox::AddString(LPCWSTR s)
35{
36 if (g_IsNT)
37 return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s);
38 return AddString(GetSystemString(s));
39}
40
41LRESULT CComboBox::GetLBText(int index, UString &s)
42{
43 s.Empty();
44 if (g_IsNT)
45 {
46 LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0);
47 if (len == CB_ERR)
48 return len;
49 LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len));
50 if (len2 == CB_ERR)
51 return len;
52 if (len > len2)
53 len = len2;
54 s.ReleaseBuf_CalcLen((unsigned)len);
55 return len;
56 }
57 AString sa;
58 LRESULT len = GetLBText(index, sa);
59 if (len == CB_ERR)
60 return len;
61 s = GetUnicodeString(sa);
62 return s.Len();
63}
64#endif
65
66}}
diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h
new file mode 100644
index 0000000..f08b1f7
--- /dev/null
+++ b/CPP/Windows/Control/ComboBox.h
@@ -0,0 +1,77 @@
1// Windows/Control/ComboBox.h
2
3#ifndef __WINDOWS_CONTROL_COMBOBOX_H
4#define __WINDOWS_CONTROL_COMBOBOX_H
5
6#include "../../Common/MyWindows.h"
7
8#include <CommCtrl.h>
9
10#include "../Window.h"
11
12namespace NWindows {
13namespace NControl {
14
15#define MY__int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i))
16
17class CComboBox: public CWindow
18{
19public:
20 void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); }
21 LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); }
22 #ifndef _UNICODE
23 LRESULT AddString(LPCWSTR s);
24 #endif
25
26 /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/
27 LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY__int_TO_WPARAM(index), 0); }
28
29 /* If no item is selected, it returns CB_ERR (-1) */
30 int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); }
31
32 /* If an error occurs, it is CB_ERR (-1) */
33 int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); }
34
35 LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); }
36 LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s); }
37 LRESULT GetLBText(int index, CSysString &s);
38 #ifndef _UNICODE
39 LRESULT GetLBText(int index, UString &s);
40 #endif
41
42 LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY__int_TO_WPARAM(index), lParam); }
43 LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY__int_TO_WPARAM(index), 0); }
44
45 LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); }
46
47 void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); }
48};
49
50#ifndef UNDER_CE
51
52class CComboBoxEx: public CComboBox
53{
54public:
55 bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }
56
57 /* Returns:
58 an INT value that represents the number of items remaining in the control.
59 If (index) is invalid, the message returns CB_ERR. */
60 LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY__int_TO_WPARAM(index), 0); }
61
62 LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); }
63 #ifndef _UNICODE
64 LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); }
65 #endif
66
67 LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); }
68 DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); }
69 HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); }
70 HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); }
71};
72
73#endif
74
75}}
76
77#endif
diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h
new file mode 100644
index 0000000..a619744
--- /dev/null
+++ b/CPP/Windows/Control/CommandBar.h
@@ -0,0 +1,52 @@
1// Windows/Control/CommandBar.h
2
3#ifndef __WINDOWS_CONTROL_COMMANDBAR_H
4#define __WINDOWS_CONTROL_COMMANDBAR_H
5
6#ifdef UNDER_CE
7
8#include "../../Common/MyWindows.h"
9
10#include <commctrl.h>
11
12#include "../Window.h"
13
14namespace NWindows {
15namespace NControl {
16
17class CCommandBar: public NWindows::CWindow
18{
19public:
20 bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar)
21 {
22 _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar);
23 return (_window != NULL);
24 }
25
26 // Macros
27 // void Destroy() { CommandBar_Destroy(_window); }
28 // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); }
29 bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); }
30 BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); }
31 void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); }
32
33 bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); }
34 int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); }
35 bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); }
36 HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); }
37 int Height() { return CommandBar_Height(_window); }
38 HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); }
39 bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); }
40 bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); }
41 bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); }
42
43
44 // CE 4.0
45 void AlignAdornments() { CommandBar_AlignAdornments(_window); }
46};
47
48}}
49
50#endif
51
52#endif
diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
new file mode 100644
index 0000000..9ddd234
--- /dev/null
+++ b/CPP/Windows/Control/Dialog.cpp
@@ -0,0 +1,414 @@
1// Windows/Control/Dialog.cpp
2
3#include "StdAfx.h"
4
5// #include "../../Windows/DLL.h"
6
7#ifndef _UNICODE
8#include "../../Common/StringConvert.h"
9#endif
10
11#include "Dialog.h"
12
13extern HINSTANCE g_hInstance;
14#ifndef _UNICODE
15extern bool g_IsNT;
16#endif
17
18namespace NWindows {
19namespace NControl {
20
21static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)
22{
23 CWindow tempDialog(dialogHWND);
24 if (message == WM_INITDIALOG)
25 tempDialog.SetUserDataLongPtr(lParam);
26 CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());
27 if (dialog == NULL)
28 return FALSE;
29 if (message == WM_INITDIALOG)
30 dialog->Attach(dialogHWND);
31
32 /* MSDN: The dialog box procedure should return
33 TRUE - if it processed the message
34 FALSE - if it did not process the message
35 If the dialog box procedure returns FALSE,
36 the dialog manager performs the default dialog operation in response to the message.
37 */
38
39 try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }
40 catch(...) { return TRUE; }
41}
42
43bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
44{
45 switch (message)
46 {
47 case WM_INITDIALOG: return OnInit();
48 case WM_COMMAND: return OnCommand(wParam, lParam);
49 case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam);
50 case WM_TIMER: return OnTimer(wParam, lParam);
51 case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
52 case WM_DESTROY: return OnDestroy();
53 case WM_HELP: OnHelp(); return true;
54 /*
55 OnHelp(
56 #ifdef UNDER_CE
57 (void *)
58 #else
59 (LPHELPINFO)
60 #endif
61 lParam);
62 return true;
63 */
64 default: return false;
65 }
66}
67
68bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam)
69{
70 return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);
71}
72
73bool CDialog::OnCommand(int code, int itemID, LPARAM lParam)
74{
75 if (code == BN_CLICKED)
76 return OnButtonClicked(itemID, (HWND)lParam);
77 return false;
78}
79
80bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)
81{
82 switch (buttonID)
83 {
84 case IDOK: OnOK(); break;
85 case IDCANCEL: OnCancel(); break;
86 case IDCLOSE: OnClose(); break;
87 case IDHELP: OnHelp(); break;
88 default: return false;
89 }
90 return true;
91}
92
93
94static bool GetWorkAreaRect(RECT *rect, HWND hwnd)
95{
96 if (hwnd)
97 {
98 #ifndef UNDER_CE
99 /* MonitorFromWindow() is supported in Win2000+
100 MonitorFromWindow() : retrieves a handle to the display monitor that has the
101 largest area of intersection with the bounding rectangle of a specified window.
102 dwFlags: Determines the function's return value if the window does not intersect any display monitor.
103 MONITOR_DEFAULTTONEAREST : Returns display that is nearest to the window.
104 MONITOR_DEFAULTTONULL : Returns NULL.
105 MONITOR_DEFAULTTOPRIMARY : Returns the primary display monitor.
106 */
107 const HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
108 if (hmon)
109 {
110 MONITORINFO mi;
111 memset(&mi, 0, sizeof(mi));
112 mi.cbSize = sizeof(mi);
113 if (GetMonitorInfoA(hmon, &mi))
114 {
115 *rect = mi.rcWork;
116 return true;
117 }
118 }
119 #endif
120 }
121
122 /* Retrieves the size of the work area on the primary display monitor.
123 The work area is the portion of the screen not obscured
124 by the system taskbar or by application desktop toolbars.
125 Any DPI virtualization mode of the caller has no effect on this output. */
126
127 return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0));
128}
129
130
131bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd)
132{
133 // it returns for system font. Real font uses another values
134 const LONG v = GetDialogBaseUnits();
135 const int x = LOWORD(v);
136 const int y = HIWORD(v);
137
138 RECT rect;
139 GetWorkAreaRect(&rect, hwnd);
140 const int wx = RECT_SIZE_X(rect);
141 const int wy = RECT_SIZE_Y(rect);
142 return
143 xSize / 4 * x <= wx &&
144 ySize / 8 * y <= wy;
145}
146
147bool CDialog::GetMargins(int margin, int &x, int &y)
148{
149 x = margin;
150 y = margin;
151 RECT rect;
152 rect.left = 0;
153 rect.top = 0;
154 rect.right = margin;
155 rect.bottom = margin;
156 if (!MapRect(&rect))
157 return false;
158 x = rect.right - rect.left;
159 y = rect.bottom - rect.top;
160 return true;
161}
162
163int CDialog::Units_To_Pixels_X(int units)
164{
165 RECT rect;
166 rect.left = 0;
167 rect.top = 0;
168 rect.right = units;
169 rect.bottom = units;
170 if (!MapRect(&rect))
171 return units * 3 / 2;
172 return rect.right - rect.left;
173}
174
175bool CDialog::GetItemSizes(int id, int &x, int &y)
176{
177 RECT rect;
178 if (!::GetWindowRect(GetItem(id), &rect))
179 return false;
180 x = RECT_SIZE_X(rect);
181 y = RECT_SIZE_Y(rect);
182 return true;
183}
184
185void CDialog::GetClientRectOfItem(int id, RECT &rect)
186{
187 ::GetWindowRect(GetItem(id), &rect);
188 ScreenToClient(&rect);
189}
190
191bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint)
192{
193 return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint)));
194}
195
196
197/*
198typedef BOOL (WINAPI * Func_DwmGetWindowAttribute)(
199 HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
200
201static bool GetWindowsRect_DWM(HWND hwnd, RECT *rect)
202{
203 // dll load and free is too slow : 300 calls in second.
204 NDLL::CLibrary dll;
205 if (!dll.Load(FTEXT("dwmapi.dll")))
206 return false;
207 Func_DwmGetWindowAttribute f = (Func_DwmGetWindowAttribute)dll.GetProc("DwmGetWindowAttribute" );
208 if (f)
209 {
210 #define MY__DWMWA_EXTENDED_FRAME_BOUNDS 9
211 // 30000 per second
212 RECT r;
213 if (f(hwnd, MY__DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK)
214 {
215 *rect = r;
216 return true;
217 }
218 }
219 return false;
220}
221*/
222
223
224static bool IsRect_Small_Inside_Big(const RECT &sm, const RECT &big)
225{
226 return sm.left >= big.left
227 && sm.right <= big.right
228 && sm.top >= big.top
229 && sm.bottom <= big.bottom;
230}
231
232
233static bool AreRectsOverlapped(const RECT &r1, const RECT &r2)
234{
235 return r1.left < r2.right
236 && r1.right > r2.left
237 && r1.top < r2.bottom
238 && r1.bottom > r2.top;
239}
240
241
242static bool AreRectsEqual(const RECT &r1, const RECT &r2)
243{
244 return r1.left == r2.left
245 && r1.right == r2.right
246 && r1.top == r2.top
247 && r1.bottom == r2.bottom;
248}
249
250
251void CDialog::NormalizeSize(bool fullNormalize)
252{
253 RECT workRect;
254 if (!GetWorkAreaRect(&workRect, *this))
255 return;
256 RECT rect;
257 if (!GetWindowRect(&rect))
258 return;
259 int xs = RECT_SIZE_X(rect);
260 int ys = RECT_SIZE_Y(rect);
261
262 // we don't want to change size using workRect, if window is outside of WorkArea
263 if (!AreRectsOverlapped(rect, workRect))
264 return;
265
266 /* here rect and workRect are overlapped, but it can be false
267 overlapping of small shadow when window in another display. */
268
269 const int xsW = RECT_SIZE_X(workRect);
270 const int ysW = RECT_SIZE_Y(workRect);
271 if (xs <= xsW && ys <= ysW)
272 return; // size of window is OK
273 if (fullNormalize)
274 {
275 Show(SW_SHOWMAXIMIZED);
276 return;
277 }
278 int x = workRect.left;
279 int y = workRect.top;
280 if (xs < xsW) x += (xsW - xs) / 2; else xs = xsW;
281 if (ys < ysW) y += (ysW - ys) / 2; else ys = ysW;
282 Move(x, y, xs, ys, true);
283}
284
285
286void CDialog::NormalizePosition()
287{
288 RECT workRect;
289 if (!GetWorkAreaRect(&workRect, *this))
290 return;
291
292 RECT rect2 = workRect;
293 bool useWorkArea = true;
294 const HWND parentHWND = GetParent();
295
296 if (parentHWND)
297 {
298 RECT workRectParent;
299 if (!GetWorkAreaRect(&workRectParent, parentHWND))
300 return;
301
302 // if windows are in different monitors, we use only workArea of current window
303
304 if (AreRectsEqual(workRectParent, workRect))
305 {
306 // RECT rect3; if (GetWindowsRect_DWM(parentHWND, &rect3)) {}
307 CWindow wnd(parentHWND);
308 if (wnd.GetWindowRect(&rect2))
309 {
310 // it's same monitor. So we try to use parentHWND rect.
311 /* we don't want to change position, if parent window is not inside work area.
312 In Win10 : parent window rect is 8 pixels larger for each corner than window size for shadow.
313 In maximize mode : window is outside of workRect.
314 if parent window is inside workRect, we will use parent window instead of workRect */
315 if (IsRect_Small_Inside_Big(rect2, workRect))
316 useWorkArea = false;
317 }
318 }
319 }
320
321 RECT rect;
322 if (!GetWindowRect(&rect))
323 return;
324
325 if (useWorkArea)
326 {
327 // we don't want to move window, if it's already inside.
328 if (IsRect_Small_Inside_Big(rect, workRect))
329 return;
330 // we don't want to move window, if it's outside of workArea
331 if (!AreRectsOverlapped(rect, workRect))
332 return;
333 rect2 = workRect;
334 }
335
336 {
337 const int xs = RECT_SIZE_X(rect);
338 const int ys = RECT_SIZE_Y(rect);
339 const int xs2 = RECT_SIZE_X(rect2);
340 const int ys2 = RECT_SIZE_Y(rect2);
341 // we don't want to change position if parent is smaller.
342 if (xs <= xs2 && ys <= ys2)
343 {
344 const int x = rect2.left + (xs2 - xs) / 2;
345 const int y = rect2.top + (ys2 - ys) / 2;
346
347 if (x != rect.left || y != rect.top)
348 Move(x, y, xs, ys, true);
349 // SetWindowPos(*this, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
350 return;
351 }
352 }
353}
354
355
356
357bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)
358{
359 HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
360 if (aHWND == 0)
361 return false;
362 Attach(aHWND);
363 return true;
364}
365
366INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow)
367{
368 return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
369}
370
371#ifndef _UNICODE
372
373bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow)
374{
375 HWND aHWND;
376 if (g_IsNT)
377 aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
378 else
379 {
380 AString name;
381 LPCSTR templateNameA;
382 if (IS_INTRESOURCE(templateName))
383 templateNameA = (LPCSTR)templateName;
384 else
385 {
386 name = GetSystemString(templateName);
387 templateNameA = name;
388 }
389 aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);
390 }
391 if (aHWND == 0)
392 return false;
393 Attach(aHWND);
394 return true;
395}
396
397INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow)
398{
399 if (g_IsNT)
400 return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
401 AString name;
402 LPCSTR templateNameA;
403 if (IS_INTRESOURCE(templateName))
404 templateNameA = (LPCSTR)templateName;
405 else
406 {
407 name = GetSystemString(templateName);
408 templateNameA = name;
409 }
410 return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);
411}
412#endif
413
414}}
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
new file mode 100644
index 0000000..8a39e99
--- /dev/null
+++ b/CPP/Windows/Control/Dialog.h
@@ -0,0 +1,190 @@
1// Windows/Control/Dialog.h
2
3#ifndef __WINDOWS_CONTROL_DIALOG_H
4#define __WINDOWS_CONTROL_DIALOG_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CDialog: public CWindow
12{
13public:
14 CDialog(HWND wnd = NULL): CWindow(wnd){};
15 virtual ~CDialog() {};
16
17 HWND GetItem(int itemID) const
18 { return GetDlgItem(_window, itemID); }
19
20 bool EnableItem(int itemID, bool enable) const
21 { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); }
22
23 bool ShowItem(int itemID, int cmdShow) const
24 { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); }
25
26 bool ShowItem_Bool(int itemID, bool show) const
27 { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); }
28
29 bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); }
30
31 bool SetItemText(int itemID, LPCTSTR s)
32 { return BOOLToBool(SetDlgItemText(_window, itemID, s)); }
33
34 bool SetItemTextA(int itemID, LPCSTR s)
35 { return BOOLToBool(SetDlgItemTextA(_window, itemID, s)); }
36
37 bool SetItemText_Empty(int itemID)
38 { return SetItemText(itemID, TEXT("")); }
39
40 #ifndef _UNICODE
41 bool SetItemText(int itemID, LPCWSTR s)
42 {
43 CWindow window(GetItem(itemID));
44 return window.SetText(s);
45 }
46 #endif
47
48 UINT GetItemText(int itemID, LPTSTR string, int maxCount)
49 { return GetDlgItemText(_window, itemID, string, maxCount); }
50 #ifndef _UNICODE
51 /*
52 bool GetItemText(int itemID, LPWSTR string, int maxCount)
53 {
54 CWindow window(GetItem(itemID));
55 return window.GetText(string, maxCount);
56 }
57 */
58 #endif
59
60 bool GetItemText(int itemID, UString &s)
61 {
62 CWindow window(GetItem(itemID));
63 return window.GetText(s);
64 }
65
66 bool SetItemInt(int itemID, UINT value, bool isSigned)
67 { return BOOLToBool(SetDlgItemInt(_window, itemID, value, BoolToBOOL(isSigned))); }
68 bool GetItemInt(int itemID, bool isSigned, UINT &value)
69 {
70 BOOL result;
71 value = GetDlgItemInt(_window, itemID, &result, BoolToBOOL(isSigned));
72 return BOOLToBool(result);
73 }
74
75 HWND GetNextGroupItem(HWND control, bool previous)
76 { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); }
77 HWND GetNextTabItem(HWND control, bool previous)
78 { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); }
79
80 LRESULT SendMsg_NextDlgCtl(WPARAM wParam, LPARAM lParam)
81 { return SendMsg(WM_NEXTDLGCTL, wParam, lParam); }
82 LRESULT SendMsg_NextDlgCtl_HWND(HWND hwnd) { return SendMsg_NextDlgCtl((WPARAM)hwnd, TRUE); }
83 LRESULT SendMsg_NextDlgCtl_CtlId(int id) { return SendMsg_NextDlgCtl_HWND(GetItem(id)); }
84 LRESULT SendMsg_NextDlgCtl_Next() { return SendMsg_NextDlgCtl(0, FALSE); }
85 LRESULT SendMsg_NextDlgCtl_Prev() { return SendMsg_NextDlgCtl(1, FALSE); }
86
87 bool MapRect(LPRECT rect)
88 { return BOOLToBool(MapDialogRect(_window, rect)); }
89
90 bool IsMessage(LPMSG message)
91 { return BOOLToBool(IsDialogMessage(_window, message)); }
92
93 LRESULT SendItemMessage(int itemID, UINT message, WPARAM wParam, LPARAM lParam)
94 { return SendDlgItemMessage(_window, itemID, message, wParam, lParam); }
95
96 bool CheckButton(int buttonID, UINT checkState)
97 { return BOOLToBool(CheckDlgButton(_window, buttonID, checkState)); }
98 bool CheckButton(int buttonID, bool checkState)
99 { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); }
100
101 UINT IsButtonChecked(int buttonID) const
102 { return IsDlgButtonChecked(_window, buttonID); }
103 bool IsButtonCheckedBool(int buttonID) const
104 { return (IsButtonChecked(buttonID) == BST_CHECKED); }
105
106 bool CheckRadioButton(int firstButtonID, int lastButtonID, int checkButtonID)
107 { return BOOLToBool(::CheckRadioButton(_window, firstButtonID, lastButtonID, checkButtonID)); }
108
109 virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
110 virtual bool OnInit() { return true; }
111 virtual bool OnCommand(WPARAM wParam, LPARAM lParam);
112 virtual bool OnCommand(int code, int itemID, LPARAM lParam);
113 virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }
114 virtual bool OnDestroy() { return false; }
115
116 /*
117 #ifdef UNDER_CE
118 virtual void OnHelp(void *) { OnHelp(); }
119 #else
120 virtual void OnHelp(LPHELPINFO) { OnHelp(); }
121 #endif
122 */
123 virtual void OnHelp() {};
124
125 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
126 virtual void OnOK() {};
127 virtual void OnCancel() {};
128 virtual void OnClose() {}
129 virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }
130 virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; }
131
132 LONG_PTR SetMsgResult(LONG_PTR newLongPtr )
133 { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }
134 LONG_PTR GetMsgResult() const
135 { return GetLongPtr(DWLP_MSGRESULT); }
136
137 bool GetMargins(int margin, int &x, int &y);
138 int Units_To_Pixels_X(int units);
139 bool GetItemSizes(int id, int &x, int &y);
140 void GetClientRectOfItem(int id, RECT &rect);
141 bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true);
142
143 void NormalizeSize(bool fullNormalize = false);
144 void NormalizePosition();
145};
146
147class CModelessDialog: public CDialog
148{
149public:
150 bool Create(LPCTSTR templateName, HWND parentWindow);
151 bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }
152 #ifndef _UNICODE
153 bool Create(LPCWSTR templateName, HWND parentWindow);
154 #endif
155 virtual void OnOK() { Destroy(); }
156 virtual void OnCancel() { Destroy(); }
157 virtual void OnClose() { Destroy(); }
158};
159
160class CModalDialog: public CDialog
161{
162public:
163 INT_PTR Create(LPCTSTR templateName, HWND parentWindow);
164 INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }
165 #ifndef _UNICODE
166 INT_PTR Create(LPCWSTR templateName, HWND parentWindow);
167 #endif
168
169 bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }
170 virtual void OnOK() { End(IDOK); }
171 virtual void OnCancel() { End(IDCANCEL); }
172 virtual void OnClose() { End(IDCLOSE); }
173};
174
175class CDialogChildControl: public NWindows::CWindow
176{
177 int m_ID;
178public:
179 void Init(const NWindows::NControl::CDialog &parentDialog, int id)
180 {
181 m_ID = id;
182 Attach(parentDialog.GetItem(id));
183 }
184};
185
186bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd = NULL);
187
188}}
189
190#endif
diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h
new file mode 100644
index 0000000..51a22c5
--- /dev/null
+++ b/CPP/Windows/Control/Edit.h
@@ -0,0 +1,19 @@
1// Windows/Control/Edit.h
2
3#ifndef __WINDOWS_CONTROL_EDIT_H
4#define __WINDOWS_CONTROL_EDIT_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CEdit: public CWindow
12{
13public:
14 void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); }
15};
16
17}}
18
19#endif
diff --git a/CPP/Windows/Control/ImageList.cpp b/CPP/Windows/Control/ImageList.cpp
new file mode 100644
index 0000000..3e22b95
--- /dev/null
+++ b/CPP/Windows/Control/ImageList.cpp
@@ -0,0 +1,10 @@
1// Windows/Control/ImageList.cpp
2
3#include "StdAfx.h"
4
5#include "ImageList.h"
6
7namespace NWindows {
8namespace NControl {
9
10}}
diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h
new file mode 100644
index 0000000..19feb11
--- /dev/null
+++ b/CPP/Windows/Control/ImageList.h
@@ -0,0 +1,87 @@
1// Windows/Control/ImageList.h
2
3#ifndef __WINDOWS_CONTROL_IMAGE_LIST_H
4#define __WINDOWS_CONTROL_IMAGE_LIST_H
5
6#include <CommCtrl.h>
7
8#include "../Defs.h"
9
10namespace NWindows {
11namespace NControl {
12
13class CImageList
14{
15 HIMAGELIST m_Object;
16public:
17 operator HIMAGELIST() const {return m_Object; }
18 CImageList(): m_Object(NULL) {}
19 bool Attach(HIMAGELIST imageList)
20 {
21 if (imageList == NULL)
22 return false;
23 m_Object = imageList;
24 return true;
25 }
26
27 HIMAGELIST Detach()
28 {
29 HIMAGELIST imageList = m_Object;
30 m_Object = NULL;
31 return imageList;
32 }
33
34 bool Create(int width, int height, UINT flags, int initialNumber, int grow)
35 {
36 HIMAGELIST a = ImageList_Create(width, height, flags,
37 initialNumber, grow);
38 if (a == NULL)
39 return false;
40 return Attach(a);
41 }
42
43 bool Destroy() // DeleteImageList() in MFC
44 {
45 if (m_Object == NULL)
46 return false;
47 return BOOLToBool(ImageList_Destroy(Detach()));
48 }
49
50 ~CImageList()
51 { Destroy(); }
52
53 int GetImageCount() const
54 { return ImageList_GetImageCount(m_Object); }
55
56 bool GetImageInfo(int index, IMAGEINFO* imageInfo) const
57 { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); }
58
59 int Add(HBITMAP hbmImage, HBITMAP hbmMask = 0)
60 { return ImageList_Add(m_Object, hbmImage, hbmMask); }
61 int AddMasked(HBITMAP hbmImage, COLORREF mask)
62 { return ImageList_AddMasked(m_Object, hbmImage, mask); }
63 int AddIcon(HICON icon)
64 { return ImageList_AddIcon(m_Object, icon); }
65 int Replace(int index, HICON icon)
66 { return ImageList_ReplaceIcon(m_Object, index, icon); }
67
68 // If index is -1, the function removes all images.
69 bool Remove(int index)
70 { return BOOLToBool(ImageList_Remove(m_Object, index)); }
71 bool RemoveAll()
72 { return BOOLToBool(ImageList_RemoveAll(m_Object)); }
73
74 HICON ExtractIcon(int index)
75 { return ImageList_ExtractIcon(NULL, m_Object, index); }
76 HICON GetIcon(int index, UINT flags)
77 { return ImageList_GetIcon(m_Object, index, flags); }
78
79 bool GetIconSize(int &width, int &height) const
80 { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); }
81 bool SetIconSize(int width, int height)
82 { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); }
83};
84
85}}
86
87#endif
diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp
new file mode 100644
index 0000000..16cfd39
--- /dev/null
+++ b/CPP/Windows/Control/ListView.cpp
@@ -0,0 +1,155 @@
1// Windows/Control/ListView.cpp
2
3#include "StdAfx.h"
4
5#include "ListView.h"
6
7#ifndef _UNICODE
8extern bool g_IsNT;
9#endif
10
11namespace NWindows {
12namespace NControl {
13
14bool CListView::CreateEx(DWORD exStyle, DWORD style,
15 int x, int y, int width, int height,
16 HWND parentWindow, HMENU idOrHMenu,
17 HINSTANCE instance, LPVOID createParam)
18{
19 return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width,
20 height, parentWindow, idOrHMenu, instance, createParam);
21}
22
23bool CListView::GetItemParam(int index, LPARAM &param) const
24{
25 LVITEM item;
26 item.iItem = index;
27 item.iSubItem = 0;
28 item.mask = LVIF_PARAM;
29 bool aResult = GetItem(&item);
30 param = item.lParam;
31 return aResult;
32}
33
34int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width)
35{
36 LVCOLUMN ci;
37 ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
38 ci.pszText = (LPTSTR)(void *)text;
39 ci.iSubItem = columnIndex;
40 ci.cx = width;
41 return InsertColumn(columnIndex, &ci);
42}
43
44int CListView::InsertItem(int index, LPCTSTR text)
45{
46 LVITEM item;
47 item.mask = LVIF_TEXT | LVIF_PARAM;
48 item.iItem = index;
49 item.lParam = index;
50 item.pszText = (LPTSTR)(void *)text;
51 item.iSubItem = 0;
52 return InsertItem(&item);
53}
54
55int CListView::SetSubItem(int index, int subIndex, LPCTSTR text)
56{
57 LVITEM item;
58 item.mask = LVIF_TEXT;
59 item.iItem = index;
60 item.pszText = (LPTSTR)(void *)text;
61 item.iSubItem = subIndex;
62 return SetItem(&item);
63}
64
65#ifndef _UNICODE
66
67int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width)
68{
69 LVCOLUMNW ci;
70 ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
71 ci.pszText = (LPWSTR)(void *)text;
72 ci.iSubItem = columnIndex;
73 ci.cx = width;
74 return InsertColumn(columnIndex, &ci);
75}
76
77int CListView::InsertItem(int index, LPCWSTR text)
78{
79 LVITEMW item;
80 item.mask = LVIF_TEXT | LVIF_PARAM;
81 item.iItem = index;
82 item.lParam = index;
83 item.pszText = (LPWSTR)(void *)text;
84 item.iSubItem = 0;
85 return InsertItem(&item);
86}
87
88int CListView::SetSubItem(int index, int subIndex, LPCWSTR text)
89{
90 LVITEMW item;
91 item.mask = LVIF_TEXT;
92 item.iItem = index;
93 item.pszText = (LPWSTR)(void *)text;
94 item.iSubItem = subIndex;
95 return SetItem(&item);
96}
97
98#endif
99
100static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
101{
102 CWindow window(hwnd);
103 CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr());
104 if (w == NULL)
105 return 0;
106 return w->OnMessage(message, wParam, lParam);
107}
108
109LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
110{
111 #ifndef _UNICODE
112 if (g_IsNT)
113 return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);
114 else
115 #endif
116 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
117}
118
119void CListView2::SetWindowProc()
120{
121 SetUserDataLongPtr((LONG_PTR)this);
122 #ifndef _UNICODE
123 if (g_IsNT)
124 _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);
125 else
126 #endif
127 _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);
128}
129
130/*
131LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
132{
133 LRESULT res = CListView2::OnMessage(message, wParam, lParam);
134 if (message == WM_GETDLGCODE)
135 {
136 // when user presses RETURN, windows sends default (first) button command to parent dialog.
137 // we disable this:
138 MSG *msg = (MSG *)lParam;
139 WPARAM key = wParam;
140 bool change = false;
141 if (msg)
142 {
143 if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN)
144 change = true;
145 }
146 else if (wParam == VK_RETURN)
147 change = true;
148 if (change)
149 res |= DLGC_WANTALLKEYS;
150 }
151 return res;
152}
153*/
154
155}}
diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h
new file mode 100644
index 0000000..a13b104
--- /dev/null
+++ b/CPP/Windows/Control/ListView.h
@@ -0,0 +1,147 @@
1// Windows/Control/ListView.h
2
3#ifndef __WINDOWS_CONTROL_LISTVIEW_H
4#define __WINDOWS_CONTROL_LISTVIEW_H
5
6#include "../../Common/MyWindows.h"
7
8#include <CommCtrl.h>
9
10#include "../Window.h"
11
12namespace NWindows {
13namespace NControl {
14
15class CListView: public NWindows::CWindow
16{
17public:
18 bool CreateEx(DWORD exStyle, DWORD style,
19 int x, int y, int width, int height,
20 HWND parentWindow, HMENU idOrHMenu,
21 HINSTANCE instance, LPVOID createParam);
22
23 void SetUnicodeFormat()
24 {
25 #ifndef UNDER_CE
26 ListView_SetUnicodeFormat(_window, TRUE);
27 #endif
28 }
29
30 bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); }
31 bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); }
32
33 int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }
34 int InsertColumn(int columnIndex, LPCTSTR text, int width);
35 bool SetColumnOrderArray(int count, const int *columns)
36 { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); }
37
38 /*
39 int GetNumColumns()
40 {
41 HWND header = ListView_GetHeader(_window);
42 if (!header)
43 return -1;
44 return Header_GetItemCount(header);
45 }
46 */
47
48 int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); }
49 int InsertItem(int index, LPCTSTR text);
50 bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); }
51 int SetSubItem(int index, int subIndex, LPCTSTR text);
52
53 #ifndef _UNICODE
54
55 int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); }
56 int InsertColumn(int columnIndex, LPCWSTR text, int width);
57 int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); }
58 int InsertItem(int index, LPCWSTR text);
59 bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); }
60 int SetSubItem(int index, int subIndex, LPCWSTR text);
61
62 #endif
63
64 bool DeleteItem(int itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); }
65
66 UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); }
67 int GetItemCount() const { return ListView_GetItemCount(_window); }
68
69 INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); }
70
71 void SetItemCount(int numItems) { ListView_SetItemCount(_window, numItems); }
72 void SetItemCountEx(int numItems, DWORD flags) { ListView_SetItemCountEx(_window, numItems, flags); }
73
74 int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); }
75 int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); }
76 int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); }
77
78 bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); }
79 bool GetItemParam(int itemIndex, LPARAM &param) const;
80 void GetItemText(int itemIndex, int subItemIndex, LPTSTR text, int textSizeMax) const
81 { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax); }
82 bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam)
83 { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); }
84
85 void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); }
86 void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); }
87 void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); }
88 void SelectAll() { SetItemState_Selected(-1); }
89 void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); }
90 UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); }
91 bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; }
92
93 bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const
94 { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); }
95
96 HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType)
97 { return ListView_SetImageList(_window, imageList, imageListType); }
98
99 // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3)
100 DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); }
101 void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); }
102 void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); }
103
104 void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)); }
105 bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); }
106
107 bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); }
108
109 bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); }
110
111 HWND GetEditControl() { return ListView_GetEditControl(_window) ; }
112 HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; }
113
114 bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); }
115 bool RedrawAllItems()
116 {
117 if (GetItemCount() > 0)
118 return RedrawItems(0, GetItemCount() - 1);
119 return true;
120 }
121 bool RedrawItem(int index) { return RedrawItems(index, index); }
122
123 int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); }
124 COLORREF GetBkColor() { return ListView_GetBkColor(_window); }
125 bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); }
126 bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); }
127};
128
129class CListView2: public CListView
130{
131 WNDPROC _origWindowProc;
132public:
133 void SetWindowProc();
134 virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
135};
136
137/*
138class CListView3: public CListView2
139{
140public:
141 virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
142};
143*/
144
145}}
146
147#endif
diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h
new file mode 100644
index 0000000..0374306
--- /dev/null
+++ b/CPP/Windows/Control/ProgressBar.h
@@ -0,0 +1,35 @@
1// Windows/Control/ProgressBar.h
2
3#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H
4#define __WINDOWS_CONTROL_PROGRESSBAR_H
5
6#include "../../Common/MyWindows.h"
7
8#include <CommCtrl.h>
9
10#include "../Window.h"
11
12namespace NWindows {
13namespace NControl {
14
15class CProgressBar: public CWindow
16{
17public:
18 LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, pos, 0); }
19 LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); }
20 UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); }
21 LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }
22 DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, minValue, maxValue); }
23 int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); }
24 LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); }
25 INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }
26
27 #ifndef UNDER_CE
28 COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, color); }
29 COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, color); }
30 #endif
31};
32
33}}
34
35#endif
diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
new file mode 100644
index 0000000..ce8696d
--- /dev/null
+++ b/CPP/Windows/Control/PropertyPage.cpp
@@ -0,0 +1,143 @@
1// Windows/Control/PropertyPage.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../../Common/StringConvert.h"
7#endif
8
9#include "PropertyPage.h"
10
11extern HINSTANCE g_hInstance;
12#ifndef _UNICODE
13extern bool g_IsNT;
14#endif
15
16namespace NWindows {
17namespace NControl {
18
19static INT_PTR APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)
20{
21 CWindow tempDialog(dialogHWND);
22 if (message == WM_INITDIALOG)
23 tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam);
24 CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());
25 if (dialog == NULL)
26 return FALSE;
27 if (message == WM_INITDIALOG)
28 dialog->Attach(dialogHWND);
29 try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }
30 catch(...) { return TRUE; }
31}
32
33bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam)
34{
35 switch (lParam->code)
36 {
37 case PSN_APPLY: SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); break;
38 case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); break;
39 case PSN_SETACTIVE: SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); break;
40 case PSN_RESET: OnReset(LPPSHNOTIFY(lParam)); break;
41 case PSN_HELP: OnNotifyHelp(LPPSHNOTIFY(lParam)); break;
42 default: return false;
43 }
44 return true;
45}
46
47INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title)
48{
49 #ifndef _UNICODE
50 AStringVector titles;
51 #endif
52 #ifndef _UNICODE
53 CRecordVector<PROPSHEETPAGEA> pagesA;
54 #endif
55 CRecordVector<PROPSHEETPAGEW> pagesW;
56
57 unsigned i;
58 #ifndef _UNICODE
59 for (i = 0; i < pagesInfo.Size(); i++)
60 titles.Add(GetSystemString(pagesInfo[i].Title));
61 #endif
62
63 for (i = 0; i < pagesInfo.Size(); i++)
64 {
65 const CPageInfo &pageInfo = pagesInfo[i];
66 #ifndef _UNICODE
67 {
68 PROPSHEETPAGE page;
69 page.dwSize = sizeof(page);
70 page.dwFlags = PSP_HASHELP;
71 page.hInstance = g_hInstance;
72 page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID);
73 page.pszIcon = NULL;
74 page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure;
75
76 if (titles[i].IsEmpty())
77 page.pszTitle = NULL;
78 else
79 {
80 page.dwFlags |= PSP_USETITLE;
81 page.pszTitle = titles[i];
82 }
83 page.lParam = (LPARAM)pageInfo.Page;
84 page.pfnCallback = NULL;
85 pagesA.Add(page);
86 }
87 #endif
88 {
89 PROPSHEETPAGEW page;
90 page.dwSize = sizeof(page);
91 page.dwFlags = PSP_HASHELP;
92 page.hInstance = g_hInstance;
93 page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID);
94 page.pszIcon = NULL;
95 page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure;
96
97 if (pageInfo.Title.IsEmpty())
98 page.pszTitle = NULL;
99 else
100 {
101 page.dwFlags |= PSP_USETITLE;
102 page.pszTitle = pageInfo.Title;
103 }
104 page.lParam = (LPARAM)pageInfo.Page;
105 page.pfnCallback = NULL;
106 pagesW.Add(page);
107 }
108 }
109
110 #ifndef _UNICODE
111 if (!g_IsNT)
112 {
113 PROPSHEETHEADER sheet;
114 sheet.dwSize = sizeof(sheet);
115 sheet.dwFlags = PSH_PROPSHEETPAGE;
116 sheet.hwndParent = hwndParent;
117 sheet.hInstance = g_hInstance;
118 AString titleA (GetSystemString(title));
119 sheet.pszCaption = titleA;
120 sheet.nPages = pagesInfo.Size();
121 sheet.nStartPage = 0;
122 sheet.ppsp = &pagesA.Front();
123 sheet.pfnCallback = NULL;
124 return ::PropertySheetA(&sheet);
125 }
126 else
127 #endif
128 {
129 PROPSHEETHEADERW sheet;
130 sheet.dwSize = sizeof(sheet);
131 sheet.dwFlags = PSH_PROPSHEETPAGE;
132 sheet.hwndParent = hwndParent;
133 sheet.hInstance = g_hInstance;
134 sheet.pszCaption = title;
135 sheet.nPages = pagesInfo.Size();
136 sheet.nStartPage = 0;
137 sheet.ppsp = &pagesW.Front();
138 sheet.pfnCallback = NULL;
139 return ::PropertySheetW(&sheet);
140 }
141}
142
143}}
diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h
new file mode 100644
index 0000000..b68fd8f
--- /dev/null
+++ b/CPP/Windows/Control/PropertyPage.h
@@ -0,0 +1,50 @@
1// Windows/Control/PropertyPage.h
2
3#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H
4#define __WINDOWS_CONTROL_PROPERTYPAGE_H
5
6#include "../../Common/MyWindows.h"
7
8#include <PrSht.h>
9
10#include "Dialog.h"
11
12namespace NWindows {
13namespace NControl {
14
15INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam);
16
17class CPropertyPage: public CDialog
18{
19public:
20 CPropertyPage(HWND window = NULL): CDialog(window){};
21
22 void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); }
23 void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); }
24
25 virtual bool OnNotify(UINT controlID, LPNMHDR lParam);
26
27 virtual bool OnKillActive() { return false; } // false = OK
28 virtual bool OnKillActive(const PSHNOTIFY *) { return OnKillActive(); }
29 virtual LONG OnSetActive() { return false; } // false = OK
30 virtual LONG OnSetActive(const PSHNOTIFY *) { return OnSetActive(); }
31 virtual LONG OnApply() { return PSNRET_NOERROR; }
32 virtual LONG OnApply(const PSHNOTIFY *) { return OnApply(); }
33 virtual void OnNotifyHelp() {}
34 virtual void OnNotifyHelp(const PSHNOTIFY *) { OnNotifyHelp(); }
35 virtual void OnReset() {}
36 virtual void OnReset(const PSHNOTIFY *) { OnReset(); }
37};
38
39struct CPageInfo
40{
41 CPropertyPage *Page;
42 UString Title;
43 UINT ID;
44};
45
46INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title);
47
48}}
49
50#endif
diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h
new file mode 100644
index 0000000..c2d58db
--- /dev/null
+++ b/CPP/Windows/Control/ReBar.h
@@ -0,0 +1,34 @@
1// Windows/Control/ReBar.h
2
3#ifndef __WINDOWS_CONTROL_REBAR_H
4#define __WINDOWS_CONTROL_REBAR_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CReBar: public NWindows::CWindow
12{
13public:
14 bool SetBarInfo(LPREBARINFO barInfo)
15 { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); }
16 bool InsertBand(int index, LPREBARBANDINFO bandInfo)
17 { return LRESULTToBool(SendMsg(RB_INSERTBAND, index, (LPARAM)bandInfo)); }
18 bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo)
19 { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); }
20 void MaximizeBand(unsigned index, bool ideal)
21 { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); }
22 bool SizeToRect(LPRECT rect)
23 { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); }
24 UINT GetHeight()
25 { return (UINT)SendMsg(RB_GETBARHEIGHT); }
26 UINT GetBandCount()
27 { return (UINT)SendMsg(RB_GETBANDCOUNT); }
28 bool DeleteBand(UINT index)
29 { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); }
30};
31
32}}
33
34#endif
diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h
new file mode 100644
index 0000000..5523b2e
--- /dev/null
+++ b/CPP/Windows/Control/Static.h
@@ -0,0 +1,28 @@
1// Windows/Control/Static.h
2
3#ifndef __WINDOWS_CONTROL_STATIC_H
4#define __WINDOWS_CONTROL_STATIC_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CStatic: public CWindow
12{
13public:
14 HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); }
15 HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); }
16
17 #ifdef UNDER_CE
18 HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); }
19 HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); }
20 #else
21 HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); }
22 HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); }
23 #endif
24};
25
26}}
27
28#endif
diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h
new file mode 100644
index 0000000..988b847
--- /dev/null
+++ b/CPP/Windows/Control/StatusBar.h
@@ -0,0 +1,42 @@
1// Windows/Control/StatusBar.h
2
3#ifndef __WINDOWS_CONTROL_STATUSBAR_H
4#define __WINDOWS_CONTROL_STATUSBAR_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CStatusBar: public NWindows::CWindow
12{
13public:
14 bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id)
15 { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != 0; }
16 bool SetText(LPCTSTR text)
17 { return CWindow::SetText(text); }
18 bool SetText(unsigned index, LPCTSTR text, UINT type)
19 { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); }
20 bool SetText(unsigned index, LPCTSTR text)
21 { return SetText(index, text, 0); }
22
23 #ifndef _UNICODE
24 bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id)
25 { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != 0; }
26 bool SetText(LPCWSTR text)
27 { return CWindow::SetText(text); }
28 bool SetText(unsigned index, LPCWSTR text, UINT type)
29 { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); }
30 bool SetText(unsigned index, LPCWSTR text)
31 { return SetText(index, text, 0); }
32 #endif
33
34 bool SetParts(unsigned numParts, const int *edgePostions)
35 { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); }
36 void Simple(bool simple)
37 { SendMsg(SB_SIMPLE, BoolToBOOL(simple), 0); }
38};
39
40}}
41
42#endif
diff --git a/CPP/Windows/Control/StdAfx.h b/CPP/Windows/Control/StdAfx.h
new file mode 100644
index 0000000..1cbd7fe
--- /dev/null
+++ b/CPP/Windows/Control/StdAfx.h
@@ -0,0 +1,8 @@
1// StdAfx.h
2
3#ifndef __STDAFX_H
4#define __STDAFX_H
5
6#include "../../Common/Common.h"
7
8#endif
diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h
new file mode 100644
index 0000000..7bc93a2
--- /dev/null
+++ b/CPP/Windows/Control/ToolBar.h
@@ -0,0 +1,43 @@
1// Windows/Control/ToolBar.h
2
3#ifndef __WINDOWS_CONTROL_TOOLBAR_H
4#define __WINDOWS_CONTROL_TOOLBAR_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CToolBar: public NWindows::CWindow
12{
13public:
14 void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); }
15 DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); }
16
17 bool GetMaxSize(LPSIZE size)
18 #ifdef UNDER_CE
19 {
20 // maybe it must be fixed for more than 1 buttons
21 DWORD val = GetButtonSize();
22 size->cx = LOWORD(val);
23 size->cy = HIWORD(val);
24 return true;
25 }
26 #else
27 {
28 return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size));
29 }
30 #endif
31
32 bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); }
33 void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); }
34 HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); }
35 bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); }
36 #ifndef _UNICODE
37 bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); }
38 #endif
39};
40
41}}
42
43#endif
diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h
new file mode 100644
index 0000000..313e0c8
--- /dev/null
+++ b/CPP/Windows/Control/Trackbar.h
@@ -0,0 +1,27 @@
1// Windows/Control/Trackbar.h
2
3#ifndef __WINDOWS_CONTROL_TRACKBAR_H
4#define __WINDOWS_CONTROL_TRACKBAR_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CTrackbar: public CWindow
12{
13public:
14 void SetRange(int minimum, int maximum, bool redraw = true)
15 { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); }
16 void SetPos(int pos, bool redraw = true)
17 { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); }
18 void SetTicFreq(int freq)
19 { SendMsg(TBM_SETTICFREQ, freq); }
20
21 int GetPos()
22 { return (int)SendMsg(TBM_GETPOS); }
23};
24
25}}
26
27#endif
diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp
new file mode 100644
index 0000000..994d96e
--- /dev/null
+++ b/CPP/Windows/Control/Window2.cpp
@@ -0,0 +1,200 @@
1// Windows/Control/Window2.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../../Common/StringConvert.h"
7#endif
8
9#include "Window2.h"
10
11#ifndef _UNICODE
12extern bool g_IsNT;
13#endif
14
15namespace NWindows {
16
17#ifndef _UNICODE
18ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);
19#endif
20
21namespace NControl {
22
23#ifdef UNDER_CE
24#define MY_START_WM_CREATE WM_CREATE
25#else
26#define MY_START_WM_CREATE WM_NCCREATE
27#endif
28
29static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, WPARAM wParam, LPARAM lParam)
30{
31 CWindow tempWindow(aHWND);
32 if (message == MY_START_WM_CREATE)
33 tempWindow.SetUserDataLongPtr((LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));
34 CWindow2 *window = (CWindow2 *)(tempWindow.GetUserDataLongPtr());
35 if (window != NULL && message == MY_START_WM_CREATE)
36 window->Attach(aHWND);
37 if (window == 0)
38 {
39 #ifndef _UNICODE
40 if (g_IsNT)
41 return DefWindowProcW(aHWND, message, wParam, lParam);
42 else
43 #endif
44 return DefWindowProc(aHWND, message, wParam, lParam);
45 }
46 return window->OnMessage(message, wParam, lParam);
47}
48
49bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName,
50 DWORD style, int x, int y, int width, int height,
51 HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance)
52{
53 WNDCLASS wc;
54 if (!::GetClassInfo(instance, className, &wc))
55 {
56 // wc.style = CS_HREDRAW | CS_VREDRAW;
57 wc.style = 0;
58 wc.lpfnWndProc = WindowProcedure;
59 wc.cbClsExtra = 0;
60 wc.cbWndExtra = 0;
61 wc.hInstance = instance;
62 wc.hIcon = NULL;
63 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
64 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
65 wc.lpszMenuName = NULL;
66 wc.lpszClassName = className;
67 if (::RegisterClass(&wc) == 0)
68 return false;
69 }
70 return CWindow::CreateEx(exStyle, className, windowName, style,
71 x, y, width, height, parentWindow, idOrHMenu, instance, this);
72}
73
74#ifndef _UNICODE
75
76bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
77 DWORD style, int x, int y, int width, int height,
78 HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance)
79{
80 bool needRegister;
81 if (g_IsNT)
82 {
83 WNDCLASSW wc;
84 needRegister = ::GetClassInfoW(instance, className, &wc) == 0;
85 }
86 else
87 {
88 WNDCLASSA windowClassA;
89 AString classNameA;
90 LPCSTR classNameP;
91 if (IS_INTRESOURCE(className))
92 classNameP = (LPCSTR)className;
93 else
94 {
95 classNameA = GetSystemString(className);
96 classNameP = classNameA;
97 }
98 needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0;
99 }
100 if (needRegister)
101 {
102 WNDCLASSW wc;
103 // wc.style = CS_HREDRAW | CS_VREDRAW;
104 wc.style = 0;
105 wc.lpfnWndProc = WindowProcedure;
106 wc.cbClsExtra = 0;
107 wc.cbWndExtra = 0;
108 wc.hInstance = instance;
109 wc.hIcon = NULL;
110 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
111 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
112 wc.lpszMenuName = NULL;
113 wc.lpszClassName = className;
114 if (MyRegisterClass(&wc) == 0)
115 return false;
116 }
117 return CWindow::CreateEx(exStyle, className, windowName, style,
118 x, y, width, height, parentWindow, idOrHMenu, instance, this);
119}
120
121#endif
122
123LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam)
124{
125 #ifndef _UNICODE
126 if (g_IsNT)
127 return DefWindowProcW(_window, message, wParam, lParam);
128 else
129 #endif
130 return DefWindowProc(_window, message, wParam, lParam);
131}
132
133LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
134{
135 LRESULT result;
136 switch (message)
137 {
138 case WM_CREATE:
139 if (!OnCreate((CREATESTRUCT *)lParam))
140 return -1;
141 break;
142 case WM_COMMAND:
143 if (OnCommand(wParam, lParam, result))
144 return result;
145 break;
146 case WM_NOTIFY:
147 if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result))
148 return result;
149 break;
150 case WM_DESTROY:
151 OnDestroy();
152 break;
153 case WM_CLOSE:
154 OnClose();
155 return 0;
156 case WM_SIZE:
157 if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam)))
158 return 0;
159 }
160 return DefProc(message, wParam, lParam);
161}
162
163bool CWindow2::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result)
164{
165 return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result);
166}
167
168bool CWindow2::OnCommand(int /* code */, int /* itemID */, LPARAM /* lParam */, LRESULT & /* result */)
169{
170 return false;
171 // return DefProc(message, wParam, lParam);
172 /*
173 if (code == BN_CLICKED)
174 return OnButtonClicked(itemID, (HWND)lParam);
175 */
176}
177
178/*
179bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
180{
181 switch (buttonID)
182 {
183 case IDOK:
184 OnOK();
185 break;
186 case IDCANCEL:
187 OnCancel();
188 break;
189 case IDHELP:
190 OnHelp();
191 break;
192 default:
193 return false;
194 }
195 return true;
196}
197
198*/
199
200}}
diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h
new file mode 100644
index 0000000..7ac580c
--- /dev/null
+++ b/CPP/Windows/Control/Window2.h
@@ -0,0 +1,51 @@
1// Windows/Control/Window2.h
2
3#ifndef __WINDOWS_CONTROL_WINDOW2_H
4#define __WINDOWS_CONTROL_WINDOW2_H
5
6#include "../Window.h"
7
8namespace NWindows {
9namespace NControl {
10
11class CWindow2: public CWindow
12{
13 LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam);
14public:
15 CWindow2(HWND newWindow = NULL): CWindow(newWindow){};
16 virtual ~CWindow2() {};
17
18 bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName,
19 DWORD style, int x, int y, int width, int height,
20 HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance);
21
22 #ifndef _UNICODE
23 bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
24 DWORD style, int x, int y, int width, int height,
25 HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance);
26 #endif
27
28 virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
29 virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; }
30 // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam);
31 virtual bool OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result);
32 virtual bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result);
33 virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }
34 virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; }
35 virtual void OnDestroy() { PostQuitMessage(0); }
36 virtual void OnClose() { Destroy(); }
37 /*
38 virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); }
39 virtual LRESULT OnHelp() {};
40 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
41 virtual void OnOK() {};
42 virtual void OnCancel() {};
43 */
44
45 LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }
46 LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); }
47};
48
49}}
50
51#endif
diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
new file mode 100644
index 0000000..cf5d01a
--- /dev/null
+++ b/CPP/Windows/DLL.cpp
@@ -0,0 +1,191 @@
1// Windows/DLL.cpp
2
3#include "StdAfx.h"
4
5#include "DLL.h"
6
7#ifdef _WIN32
8
9#ifndef _UNICODE
10extern bool g_IsNT;
11#endif
12
13extern HINSTANCE g_hInstance;
14
15namespace NWindows {
16namespace NDLL {
17
18bool CLibrary::Free() throw()
19{
20 if (_module == 0)
21 return true;
22 if (!::FreeLibrary(_module))
23 return false;
24 _module = 0;
25 return true;
26}
27
28bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw()
29{
30 if (!Free())
31 return false;
32 #ifndef _UNICODE
33 if (!g_IsNT)
34 {
35 _module = ::LoadLibraryEx(fs2fas(path), NULL, flags);
36 }
37 else
38 #endif
39 {
40 _module = ::LoadLibraryExW(fs2us(path), NULL, flags);
41 }
42 return (_module != NULL);
43}
44
45bool CLibrary::Load(CFSTR path) throw()
46{
47 if (!Free())
48 return false;
49 #ifndef _UNICODE
50 if (!g_IsNT)
51 {
52 _module = ::LoadLibrary(fs2fas(path));
53 }
54 else
55 #endif
56 {
57 _module = ::LoadLibraryW(fs2us(path));
58 }
59 return (_module != NULL);
60}
61
62bool MyGetModuleFileName(FString &path)
63{
64 HMODULE hModule = g_hInstance;
65 path.Empty();
66 #ifndef _UNICODE
67 if (!g_IsNT)
68 {
69 TCHAR s[MAX_PATH + 2];
70 s[0] = 0;
71 DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1);
72 if (size <= MAX_PATH && size != 0)
73 {
74 path = fas2fs(s);
75 return true;
76 }
77 }
78 else
79 #endif
80 {
81 WCHAR s[MAX_PATH + 2];
82 s[0] = 0;
83 DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1);
84 if (size <= MAX_PATH && size != 0)
85 {
86 path = us2fs(s);
87 return true;
88 }
89 }
90 return false;
91}
92
93#ifndef _SFX
94
95FString GetModuleDirPrefix()
96{
97 FString s;
98 if (MyGetModuleFileName(s))
99 {
100 int pos = s.ReverseFind_PathSepar();
101 if (pos >= 0)
102 s.DeleteFrom((unsigned)(pos + 1));
103 }
104 if (s.IsEmpty())
105 s = "." STRING_PATH_SEPARATOR;
106 return s;
107}
108
109#endif
110
111}}
112
113#else
114
115#include <dlfcn.h>
116#include <stdlib.h>
117
118namespace NWindows {
119namespace NDLL {
120
121bool CLibrary::Free() throw()
122{
123 if (_module == NULL)
124 return true;
125 int ret = dlclose(_module);
126 if (ret != 0)
127 return false;
128 _module = NULL;
129 return true;
130}
131
132static
133// FARPROC
134void *
135local_GetProcAddress(HMODULE module, LPCSTR procName)
136{
137 void *ptr = NULL;
138 if (module)
139 {
140 ptr = dlsym(module, procName);
141 }
142 return ptr;
143}
144
145bool CLibrary::Load(CFSTR path) throw()
146{
147 if (!Free())
148 return false;
149
150 int options = 0;
151
152 #ifdef RTLD_LOCAL
153 options |= RTLD_LOCAL;
154 #endif
155
156 #ifdef RTLD_NOW
157 options |= RTLD_NOW;
158 #endif
159
160 #ifdef RTLD_GROUP
161 #if ! (defined(hpux) || defined(__hpux))
162 options |= RTLD_GROUP; // mainly for solaris but not for HPUX
163 #endif
164 #endif
165
166 void *handler = dlopen(path, options);
167
168 if (handler)
169 {
170 // here we can transfer some settings to DLL
171 }
172 else
173 {
174 }
175
176 _module = handler;
177
178 return (_module != NULL);
179}
180
181// FARPROC
182void * CLibrary::GetProc(LPCSTR procName) const
183{
184 // return My_GetProcAddress(_module, procName);
185 return local_GetProcAddress(_module, procName);
186 // return NULL;
187}
188
189}}
190
191#endif
diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
new file mode 100644
index 0000000..0c093ee
--- /dev/null
+++ b/CPP/Windows/DLL.h
@@ -0,0 +1,84 @@
1// Windows/DLL.h
2
3#ifndef __WINDOWS_DLL_H
4#define __WINDOWS_DLL_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NDLL {
10
11#ifdef _WIN32
12
13#ifdef UNDER_CE
14#define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName)
15#else
16#define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName)
17#endif
18
19/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another
20 FreeLibrary() code: detaching code in DLL entry-point or in
21 destructors of global objects in DLL module. */
22
23class CLibrary
24{
25 HMODULE _module;
26
27 // CLASS_NO_COPY(CLibrary);
28public:
29 CLibrary(): _module(NULL) {};
30 ~CLibrary() { Free(); }
31
32 operator HMODULE() const { return _module; }
33 HMODULE* operator&() { return &_module; }
34 bool IsLoaded() const { return (_module != NULL); }
35
36 void Attach(HMODULE m)
37 {
38 Free();
39 _module = m;
40 }
41 HMODULE Detach()
42 {
43 HMODULE m = _module;
44 _module = NULL;
45 return m;
46 }
47
48 bool Free() throw();
49 bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw();
50 bool Load(CFSTR path) throw();
51 // FARPROC
52 void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }
53};
54
55#else
56
57typedef void * HMODULE;
58// typedef int (*FARPROC)();
59// typedef void *FARPROC;
60
61class CLibrary
62{
63 HMODULE _module;
64
65 // CLASS_NO_COPY(CLibrary);
66public:
67 CLibrary(): _module(NULL) {};
68 ~CLibrary() { Free(); }
69
70 bool Free() throw();
71 bool Load(CFSTR path) throw();
72 // FARPROC
73 void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); }
74};
75
76#endif
77
78bool MyGetModuleFileName(FString &path);
79
80FString GetModuleDirPrefix();
81
82}}
83
84#endif
diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h
new file mode 100644
index 0000000..1d96078
--- /dev/null
+++ b/CPP/Windows/Defs.h
@@ -0,0 +1,18 @@
1// Windows/Defs.h
2
3#ifndef __WINDOWS_DEFS_H
4#define __WINDOWS_DEFS_H
5
6#include "../Common/MyWindows.h"
7
8#ifdef _WIN32
9inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }
10inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }
11#endif
12
13inline bool BOOLToBool(BOOL v) { return (v != FALSE); }
14
15inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }
16inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }
17
18#endif
diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
new file mode 100644
index 0000000..f6343a5
--- /dev/null
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -0,0 +1,133 @@
1// Windows/ErrorMsg.h
2
3#include "StdAfx.h"
4
5#if !defined(_UNICODE) || !defined(_WIN32)
6#include "../Common/StringConvert.h"
7#endif
8
9#include "ErrorMsg.h"
10
11#ifdef _WIN32
12#if !defined(_UNICODE)
13extern bool g_IsNT;
14#endif
15#endif
16
17namespace NWindows {
18namespace NError {
19
20static bool MyFormatMessage(DWORD errorCode, UString &message)
21{
22 #ifndef _SFX
23 if ((HRESULT)errorCode == MY_HRES_ERROR__INTERNAL_ERROR)
24 {
25 message = "Internal Error: The failure in hardware (RAM or CPU), OS or program";
26 return true;
27 }
28 #endif
29
30 #ifdef _WIN32
31
32 LPVOID msgBuf;
33 #ifndef _UNICODE
34 if (!g_IsNT)
35 {
36 if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
37 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
38 NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0)
39 return false;
40 message = GetUnicodeString((LPCTSTR)msgBuf);
41 }
42 else
43 #endif
44 {
45 if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
46 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
47 NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)
48 return false;
49 message = (LPCWSTR)msgBuf;
50 }
51 ::LocalFree(msgBuf);
52 return true;
53
54 #else // _WIN32
55
56 AString m;
57
58 const char *s = NULL;
59
60 switch ((Int32)errorCode)
61 {
62 // case ERROR_NO_MORE_FILES : s = "No more files"; break;
63 // case ERROR_DIRECTORY : s = "Error Directory"; break;
64 case E_NOTIMPL : s = "E_NOTIMPL : Not implemented"; break;
65 case E_NOINTERFACE : s = "E_NOINTERFACE : No such interface supported"; break;
66 case E_ABORT : s = "E_ABORT : Operation aborted"; break;
67 case E_FAIL : s = "E_FAIL : Unspecified error"; break;
68
69 case STG_E_INVALIDFUNCTION : s = "STG_E_INVALIDFUNCTION"; break;
70 case CLASS_E_CLASSNOTAVAILABLE : s = "CLASS_E_CLASSNOTAVAILABLE"; break;
71
72 case E_OUTOFMEMORY : s = "E_OUTOFMEMORY : Can't allocate required memory"; break;
73 case E_INVALIDARG : s = "E_INVALIDARG : One or more arguments are invalid"; break;
74
75 // case MY__E_ERROR_NEGATIVE_SEEK : s = "MY__E_ERROR_NEGATIVE_SEEK"; break;
76 default:
77 break;
78 }
79
80 /* strerror() for unknown errors still shows message "Unknown error -12345678")
81 So we must transfer error codes before strerror() */
82 if (!s)
83 {
84 if ((errorCode & 0xFFFF0000) == (UInt32)((MY__FACILITY__WRes << 16) | 0x80000000))
85 errorCode &= 0xFFFF;
86 else if ((errorCode & ((UInt32)1 << 31)))
87 return false; // we will show hex error later for that case
88
89 s = strerror((int)errorCode);
90
91 // if (!s)
92 {
93 m += "errno=";
94 m.Add_UInt32(errorCode);
95 if (s)
96 m += " : ";
97 }
98 }
99
100 if (s)
101 m += s;
102
103 MultiByteToUnicodeString2(message, m);
104 return true;
105
106 #endif
107}
108
109
110UString MyFormatMessage(DWORD errorCode)
111{
112 UString m;
113 if (!MyFormatMessage(errorCode, m) || m.IsEmpty())
114 {
115 char s[16];
116 for (int i = 0; i < 8; i++)
117 {
118 unsigned t = errorCode & 0xF;
119 errorCode >>= 4;
120 s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
121 }
122 s[8] = 0;
123 m += "Error #";
124 m += s;
125 }
126 else if (m.Len() >= 2
127 && m[m.Len() - 1] == 0x0A
128 && m[m.Len() - 2] == 0x0D)
129 m.DeleteFrom(m.Len() - 2);
130 return m;
131}
132
133}}
diff --git a/CPP/Windows/ErrorMsg.h b/CPP/Windows/ErrorMsg.h
new file mode 100644
index 0000000..01204eb
--- /dev/null
+++ b/CPP/Windows/ErrorMsg.h
@@ -0,0 +1,16 @@
1// Windows/ErrorMsg.h
2
3#ifndef __WINDOWS_ERROR_MSG_H
4#define __WINDOWS_ERROR_MSG_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NError {
10
11UString MyFormatMessage(DWORD errorCode);
12inline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); }
13
14}}
15
16#endif
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
new file mode 100644
index 0000000..8a33fc8
--- /dev/null
+++ b/CPP/Windows/FileDir.cpp
@@ -0,0 +1,1129 @@
1// Windows/FileDir.cpp
2
3#include "StdAfx.h"
4
5
6#ifndef _WIN32
7#include <stdio.h>
8#include <stdlib.h>
9#include <errno.h>
10#include <limits.h>
11#include <unistd.h>
12#include <time.h>
13#include <utime.h>
14#include <fcntl.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17
18#include "../Common/StringConvert.h"
19#include "../Common/C_FileIO.h"
20#include "TimeUtils.h"
21#endif
22
23#include "FileDir.h"
24#include "FileFind.h"
25#include "FileName.h"
26
27#ifndef _UNICODE
28extern bool g_IsNT;
29#endif
30
31using namespace NWindows;
32using namespace NFile;
33using namespace NName;
34
35namespace NWindows {
36namespace NFile {
37namespace NDir {
38
39#ifdef _WIN32
40
41#ifndef UNDER_CE
42
43bool GetWindowsDir(FString &path)
44{
45 UINT needLength;
46 #ifndef _UNICODE
47 if (!g_IsNT)
48 {
49 TCHAR s[MAX_PATH + 2];
50 s[0] = 0;
51 needLength = ::GetWindowsDirectory(s, MAX_PATH + 1);
52 path = fas2fs(s);
53 }
54 else
55 #endif
56 {
57 WCHAR s[MAX_PATH + 2];
58 s[0] = 0;
59 needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1);
60 path = us2fs(s);
61 }
62 return (needLength > 0 && needLength <= MAX_PATH);
63}
64
65bool GetSystemDir(FString &path)
66{
67 UINT needLength;
68 #ifndef _UNICODE
69 if (!g_IsNT)
70 {
71 TCHAR s[MAX_PATH + 2];
72 s[0] = 0;
73 needLength = ::GetSystemDirectory(s, MAX_PATH + 1);
74 path = fas2fs(s);
75 }
76 else
77 #endif
78 {
79 WCHAR s[MAX_PATH + 2];
80 s[0] = 0;
81 needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1);
82 path = us2fs(s);
83 }
84 return (needLength > 0 && needLength <= MAX_PATH);
85}
86#endif // UNDER_CE
87
88
89bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
90{
91 #ifndef _UNICODE
92 if (!g_IsNT)
93 {
94 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
95 return false;
96 }
97 #endif
98
99 HANDLE hDir = INVALID_HANDLE_VALUE;
100 IF_USE_MAIN_PATH
101 hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
102 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
103 #ifdef WIN_LONG_PATH
104 if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
105 {
106 UString superPath;
107 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
108 hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
109 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
110 }
111 #endif
112
113 bool res = false;
114 if (hDir != INVALID_HANDLE_VALUE)
115 {
116 res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));
117 ::CloseHandle(hDir);
118 }
119 return res;
120}
121
122
123
124bool SetFileAttrib(CFSTR path, DWORD attrib)
125{
126 #ifndef _UNICODE
127 if (!g_IsNT)
128 {
129 if (::SetFileAttributes(fs2fas(path), attrib))
130 return true;
131 }
132 else
133 #endif
134 {
135 IF_USE_MAIN_PATH
136 if (::SetFileAttributesW(fs2us(path), attrib))
137 return true;
138 #ifdef WIN_LONG_PATH
139 if (USE_SUPER_PATH)
140 {
141 UString superPath;
142 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
143 return BOOLToBool(::SetFileAttributesW(superPath, attrib));
144 }
145 #endif
146 }
147 return false;
148}
149
150
151bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
152{
153 #ifdef _WIN32
154 if ((attrib & 0xF0000000) != 0)
155 attrib &= 0x3FFF;
156 #endif
157 return SetFileAttrib(path, attrib);
158}
159
160
161bool RemoveDir(CFSTR path)
162{
163 #ifndef _UNICODE
164 if (!g_IsNT)
165 {
166 if (::RemoveDirectory(fs2fas(path)))
167 return true;
168 }
169 else
170 #endif
171 {
172 IF_USE_MAIN_PATH
173 if (::RemoveDirectoryW(fs2us(path)))
174 return true;
175 #ifdef WIN_LONG_PATH
176 if (USE_SUPER_PATH)
177 {
178 UString superPath;
179 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
180 return BOOLToBool(::RemoveDirectoryW(superPath));
181 }
182 #endif
183 }
184 return false;
185}
186
187
188bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
189{
190 #ifndef _UNICODE
191 if (!g_IsNT)
192 {
193 if (::MoveFile(fs2fas(oldFile), fs2fas(newFile)))
194 return true;
195 }
196 else
197 #endif
198 {
199 IF_USE_MAIN_PATH_2(oldFile, newFile)
200 {
201 if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))
202 return true;
203 }
204 #ifdef WIN_LONG_PATH
205 if (USE_SUPER_PATH_2)
206 {
207 UString d1, d2;
208 if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
209 return BOOLToBool(::MoveFileW(d1, d2));
210 }
211 #endif
212 }
213 return false;
214}
215
216#ifndef UNDER_CE
217EXTERN_C_BEGIN
218typedef BOOL (WINAPI *Func_CreateHardLinkW)(
219 LPCWSTR lpFileName,
220 LPCWSTR lpExistingFileName,
221 LPSECURITY_ATTRIBUTES lpSecurityAttributes
222 );
223EXTERN_C_END
224#endif // UNDER_CE
225
226bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
227{
228 #ifndef _UNICODE
229 if (!g_IsNT)
230 {
231 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
232 return false;
233 /*
234 if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL))
235 return true;
236 */
237 }
238 else
239 #endif
240 {
241 Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW)
242 (void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");
243 if (!my_CreateHardLinkW)
244 return false;
245 IF_USE_MAIN_PATH_2(newFileName, existFileName)
246 {
247 if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
248 return true;
249 }
250 #ifdef WIN_LONG_PATH
251 if (USE_SUPER_PATH_2)
252 {
253 UString d1, d2;
254 if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))
255 return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL));
256 }
257 #endif
258 }
259 return false;
260}
261
262
263/*
264WinXP-64 CreateDir():
265 "" - ERROR_PATH_NOT_FOUND
266 \ - ERROR_ACCESS_DENIED
267 C:\ - ERROR_ACCESS_DENIED, if there is such drive,
268
269 D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive,
270 C:\nonExistent\folder - ERROR_PATH_NOT_FOUND
271
272 C:\existFolder - ERROR_ALREADY_EXISTS
273 C:\existFolder\ - ERROR_ALREADY_EXISTS
274
275 C:\folder - OK
276 C:\folder\ - OK
277
278 \\Server\nonExistent - ERROR_BAD_NETPATH
279 \\Server\Share_Readonly - ERROR_ACCESS_DENIED
280 \\Server\Share - ERROR_ALREADY_EXISTS
281
282 \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED
283 \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS
284*/
285
286bool CreateDir(CFSTR path)
287{
288 #ifndef _UNICODE
289 if (!g_IsNT)
290 {
291 if (::CreateDirectory(fs2fas(path), NULL))
292 return true;
293 }
294 else
295 #endif
296 {
297 IF_USE_MAIN_PATH
298 if (::CreateDirectoryW(fs2us(path), NULL))
299 return true;
300 #ifdef WIN_LONG_PATH
301 if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
302 {
303 UString superPath;
304 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
305 return BOOLToBool(::CreateDirectoryW(superPath, NULL));
306 }
307 #endif
308 }
309 return false;
310}
311
312/*
313 CreateDir2 returns true, if directory can contain files after the call (two cases):
314 1) the directory already exists
315 2) the directory was created
316 path must be WITHOUT trailing path separator.
317
318 We need CreateDir2, since fileInfo.Find() for reserved names like "com8"
319 returns FILE instead of DIRECTORY. And we need to use SuperPath */
320
321static bool CreateDir2(CFSTR path)
322{
323 #ifndef _UNICODE
324 if (!g_IsNT)
325 {
326 if (::CreateDirectory(fs2fas(path), NULL))
327 return true;
328 }
329 else
330 #endif
331 {
332 IF_USE_MAIN_PATH
333 if (::CreateDirectoryW(fs2us(path), NULL))
334 return true;
335 #ifdef WIN_LONG_PATH
336 if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
337 {
338 UString superPath;
339 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
340 {
341 if (::CreateDirectoryW(superPath, NULL))
342 return true;
343 if (::GetLastError() != ERROR_ALREADY_EXISTS)
344 return false;
345 NFind::CFileInfo fi;
346 if (!fi.Find(us2fs(superPath)))
347 return false;
348 return fi.IsDir();
349 }
350 }
351 #endif
352 }
353 if (::GetLastError() != ERROR_ALREADY_EXISTS)
354 return false;
355 NFind::CFileInfo fi;
356 if (!fi.Find(path))
357 return false;
358 return fi.IsDir();
359}
360
361#endif // _WIN32
362
363static bool CreateDir2(CFSTR path);
364
365bool CreateComplexDir(CFSTR _path)
366{
367 #ifdef _WIN32
368
369 {
370 DWORD attrib = NFind::GetFileAttrib(_path);
371 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
372 return true;
373 }
374
375 #ifndef UNDER_CE
376
377 if (IsDriveRootPath_SuperAllowed(_path))
378 return false;
379
380 const unsigned prefixSize = GetRootPrefixSize(_path);
381
382 #endif // UNDER_CE
383
384 #else // _WIN32
385
386 // Posix
387 NFind::CFileInfo fi;
388 if (fi.Find(_path))
389 {
390 if (fi.IsDir())
391 return true;
392 }
393
394 #endif // _WIN32
395
396 FString path (_path);
397
398 int pos = path.ReverseFind_PathSepar();
399 if (pos >= 0 && (unsigned)pos == path.Len() - 1)
400 {
401 if (path.Len() == 1)
402 return true;
403 path.DeleteBack();
404 }
405
406 const FString path2 (path);
407 pos = (int)path.Len();
408
409 for (;;)
410 {
411 if (CreateDir2(path))
412 break;
413 if (::GetLastError() == ERROR_ALREADY_EXISTS)
414 return false;
415 pos = path.ReverseFind_PathSepar();
416 if (pos < 0 || pos == 0)
417 return false;
418
419 #if defined(_WIN32) && !defined(UNDER_CE)
420 if (pos == 1 && IS_PATH_SEPAR(path[0]))
421 return false;
422 if (prefixSize >= (unsigned)pos + 1)
423 return false;
424 #endif
425
426 path.DeleteFrom((unsigned)pos);
427 }
428
429 while (pos < (int)path2.Len())
430 {
431 int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1));
432 if (pos2 < 0)
433 pos = (int)path2.Len();
434 else
435 pos += 1 + pos2;
436 path.SetFrom(path2, (unsigned)pos);
437 if (!CreateDir(path))
438 return false;
439 }
440
441 return true;
442}
443
444
445#ifdef _WIN32
446
447bool DeleteFileAlways(CFSTR path)
448{
449 /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.
450 SetFileAttrib("name:stream", ) changes attributes of main file. */
451 {
452 DWORD attrib = NFind::GetFileAttrib(path);
453 if (attrib != INVALID_FILE_ATTRIBUTES
454 && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0
455 && (attrib & FILE_ATTRIBUTE_READONLY) != 0)
456 {
457 if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY))
458 return false;
459 }
460 }
461
462 #ifndef _UNICODE
463 if (!g_IsNT)
464 {
465 if (::DeleteFile(fs2fas(path)))
466 return true;
467 }
468 else
469 #endif
470 {
471 /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")).
472 Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */
473 IF_USE_MAIN_PATH
474 if (::DeleteFileW(fs2us(path)))
475 return true;
476 #ifdef WIN_LONG_PATH
477 if (USE_SUPER_PATH)
478 {
479 UString superPath;
480 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
481 return BOOLToBool(::DeleteFileW(superPath));
482 }
483 #endif
484 }
485 return false;
486}
487
488
489
490bool RemoveDirWithSubItems(const FString &path)
491{
492 bool needRemoveSubItems = true;
493 {
494 NFind::CFileInfo fi;
495 if (!fi.Find(path))
496 return false;
497 if (!fi.IsDir())
498 {
499 ::SetLastError(ERROR_DIRECTORY);
500 return false;
501 }
502 if (fi.HasReparsePoint())
503 needRemoveSubItems = false;
504 }
505
506 if (needRemoveSubItems)
507 {
508 FString s (path);
509 s.Add_PathSepar();
510 const unsigned prefixSize = s.Len();
511 NFind::CEnumerator enumerator;
512 enumerator.SetDirPrefix(s);
513 NFind::CDirEntry fi;
514 bool isError = false;
515 DWORD lastError = 0;
516 while (enumerator.Next(fi))
517 {
518 s.DeleteFrom(prefixSize);
519 s += fi.Name;
520 if (fi.IsDir())
521 {
522 if (!RemoveDirWithSubItems(s))
523 {
524 lastError = GetLastError();
525 isError = true;
526 }
527 }
528 else if (!DeleteFileAlways(s))
529 {
530 lastError = GetLastError();
531 isError = false;
532 }
533 }
534 if (isError)
535 {
536 SetLastError(lastError);
537 return false;
538 }
539 }
540
541 // we clear read-only attrib to remove read-only dir
542 if (!SetFileAttrib(path, 0))
543 return false;
544 return RemoveDir(path);
545}
546
547#endif // _WIN32
548
549#ifdef UNDER_CE
550
551bool MyGetFullPathName(CFSTR path, FString &resFullPath)
552{
553 resFullPath = path;
554 return true;
555}
556
557#else
558
559bool MyGetFullPathName(CFSTR path, FString &resFullPath)
560{
561 return GetFullPath(path, resFullPath);
562}
563
564#ifdef _WIN32
565
566bool SetCurrentDir(CFSTR path)
567{
568 // SetCurrentDirectory doesn't support \\?\ prefix
569 #ifndef _UNICODE
570 if (!g_IsNT)
571 {
572 return BOOLToBool(::SetCurrentDirectory(fs2fas(path)));
573 }
574 else
575 #endif
576 {
577 return BOOLToBool(::SetCurrentDirectoryW(fs2us(path)));
578 }
579}
580
581
582bool GetCurrentDir(FString &path)
583{
584 path.Empty();
585
586 DWORD needLength;
587 #ifndef _UNICODE
588 if (!g_IsNT)
589 {
590 TCHAR s[MAX_PATH + 2];
591 s[0] = 0;
592 needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);
593 path = fas2fs(s);
594 }
595 else
596 #endif
597 {
598 WCHAR s[MAX_PATH + 2];
599 s[0] = 0;
600 needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
601 path = us2fs(s);
602 }
603 return (needLength > 0 && needLength <= MAX_PATH);
604}
605
606#endif // _WIN32
607#endif // UNDER_CE
608
609
610bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)
611{
612 bool res = MyGetFullPathName(path, resDirPrefix);
613 if (!res)
614 resDirPrefix = path;
615 int pos = resDirPrefix.ReverseFind_PathSepar();
616 pos++;
617 resFileName = resDirPrefix.Ptr((unsigned)pos);
618 resDirPrefix.DeleteFrom((unsigned)pos);
619 return res;
620}
621
622bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)
623{
624 FString resFileName;
625 return GetFullPathAndSplit(path, resDirPrefix, resFileName);
626}
627
628bool MyGetTempPath(FString &path)
629{
630 #ifdef _WIN32
631 path.Empty();
632 DWORD needLength;
633 #ifndef _UNICODE
634 if (!g_IsNT)
635 {
636 TCHAR s[MAX_PATH + 2];
637 s[0] = 0;
638 needLength = ::GetTempPath(MAX_PATH + 1, s);
639 path = fas2fs(s);
640 }
641 else
642 #endif
643 {
644 WCHAR s[MAX_PATH + 2];
645 s[0] = 0;
646 needLength = ::GetTempPathW(MAX_PATH + 1, s);;
647 path = us2fs(s);
648 }
649 return (needLength > 0 && needLength <= MAX_PATH);
650
651 #else
652
653 // FIXME: improve that code
654 path = "/tmp/";
655 if (!NFind::DoesDirExist_FollowLink(path))
656 path = "./";
657 return true;
658 #endif
659}
660
661
662static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile)
663{
664 UInt32 d =
665 #ifdef _WIN32
666 (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
667 #else
668 (UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid());
669 #endif
670
671 for (unsigned i = 0; i < 100; i++)
672 {
673 path = prefix;
674 if (addRandom)
675 {
676 char s[16];
677 UInt32 val = d;
678 unsigned k;
679 for (k = 0; k < 8; k++)
680 {
681 unsigned t = val & 0xF;
682 val >>= 4;
683 s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
684 }
685 s[k] = '\0';
686 if (outFile)
687 path += '.';
688 path += s;
689 UInt32 step = GetTickCount() + 2;
690 if (step == 0)
691 step = 1;
692 d += step;
693 }
694 addRandom = true;
695 if (outFile)
696 path += ".tmp";
697 if (NFind::DoesFileOrDirExist(path))
698 {
699 SetLastError(ERROR_ALREADY_EXISTS);
700 continue;
701 }
702 if (outFile)
703 {
704 if (outFile->Create(path, false))
705 return true;
706 }
707 else
708 {
709 if (CreateDir(path))
710 return true;
711 }
712 DWORD error = GetLastError();
713 if (error != ERROR_FILE_EXISTS &&
714 error != ERROR_ALREADY_EXISTS)
715 break;
716 }
717 path.Empty();
718 return false;
719}
720
721bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)
722{
723 if (!Remove())
724 return false;
725 if (!CreateTempFile(prefix, false, _path, outFile))
726 return false;
727 _mustBeDeleted = true;
728 return true;
729}
730
731bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile)
732{
733 if (!Remove())
734 return false;
735 FString tempPath;
736 if (!MyGetTempPath(tempPath))
737 return false;
738 if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile))
739 return false;
740 _mustBeDeleted = true;
741 return true;
742}
743
744bool CTempFile::Remove()
745{
746 if (!_mustBeDeleted)
747 return true;
748 _mustBeDeleted = !DeleteFileAlways(_path);
749 return !_mustBeDeleted;
750}
751
752bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
753{
754 // DWORD attrib = 0;
755 if (deleteDestBefore)
756 {
757 if (NFind::DoesFileExist_Raw(name))
758 {
759 // attrib = NFind::GetFileAttrib(name);
760 if (!DeleteFileAlways(name))
761 return false;
762 }
763 }
764 DisableDeleting();
765 return MyMoveFile(_path, name);
766
767 /*
768 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
769 {
770 DWORD attrib2 = NFind::GetFileAttrib(name);
771 if (attrib2 != INVALID_FILE_ATTRIBUTES)
772 SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY);
773 }
774 */
775}
776
777#ifdef _WIN32
778bool CTempDir::Create(CFSTR prefix)
779{
780 if (!Remove())
781 return false;
782 FString tempPath;
783 if (!MyGetTempPath(tempPath))
784 return false;
785 if (!CreateTempFile(tempPath + prefix, true, _path, NULL))
786 return false;
787 _mustBeDeleted = true;
788 return true;
789}
790
791bool CTempDir::Remove()
792{
793 if (!_mustBeDeleted)
794 return true;
795 _mustBeDeleted = !RemoveDirWithSubItems(_path);
796 return !_mustBeDeleted;
797}
798#endif
799
800
801
802#ifndef _WIN32
803
804bool RemoveDir(CFSTR path)
805{
806 return (rmdir(path) == 0);
807}
808
809
810static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile)
811{
812 NWindows::NFile::NIO::COutFile outFile;
813 if (!outFile.Create(newFile, false))
814 return FALSE;
815
816 NWindows::NFile::NIO::CInFile inFile;
817 if (!inFile.Open(oldFile))
818 return FALSE;
819
820 char buf[1 << 14];
821
822 for (;;)
823 {
824 const ssize_t num = inFile.read_part(buf, sizeof(buf));
825 if (num == 0)
826 return TRUE;
827 if (num < 0)
828 return FALSE;
829 size_t processed;
830 const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
831 if (num2 != num || processed != (size_t)num)
832 return FALSE;
833 }
834}
835
836
837bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
838{
839 int res = rename(oldFile, newFile);
840 if (res == 0)
841 return true;
842 if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
843 return false;
844
845 if (My__CopyFile(oldFile, newFile) == FALSE)
846 return false;
847
848 struct stat info_file;
849 res = stat(oldFile, &info_file);
850 if (res != 0)
851 return false;
852
853 /*
854 ret = chmod(dst,info_file.st_mode & g_umask.mask);
855 */
856 return (unlink(oldFile) == 0);
857}
858
859
860bool CreateDir(CFSTR path)
861{
862 return (mkdir(path, 0777) == 0); // change it
863}
864
865static bool CreateDir2(CFSTR path)
866{
867 return (mkdir(path, 0777) == 0); // change it
868}
869
870
871bool DeleteFileAlways(CFSTR path)
872{
873 return (remove(path) == 0);
874}
875
876bool SetCurrentDir(CFSTR path)
877{
878 return (chdir(path) == 0);
879}
880
881
882bool GetCurrentDir(FString &path)
883{
884 path.Empty();
885
886 #define MY__PATH_MAX PATH_MAX
887 // #define MY__PATH_MAX 1024
888
889 char s[MY__PATH_MAX + 1];
890 char *res = getcwd(s, MY__PATH_MAX);
891 if (res)
892 {
893 path = fas2fs(s);
894 return true;
895 }
896 {
897 // if (errno != ERANGE) return false;
898 #if defined(__GLIBC__) || defined(__APPLE__)
899 /* As an extension to the POSIX.1-2001 standard, glibc's getcwd()
900 allocates the buffer dynamically using malloc(3) if buf is NULL. */
901 res = getcwd(NULL, 0);
902 if (res)
903 {
904 path = fas2fs(res);
905 ::free(res);
906 return true;
907 }
908 #endif
909 return false;
910 }
911}
912
913
914
915// #undef UTIME_OMIT // to debug
916
917#ifndef UTIME_OMIT
918 /* we can define UTIME_OMIT for debian and another systems.
919 Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */
920 // #define UTIME_OMIT -2
921#endif
922
923static bool FILETME_To_timespec(const FILETIME *ft, timespec &ts)
924{
925 if (ft)
926 {
927 const Int64 sec = NTime::FileTimeToUnixTime64(*ft);
928 // time_t is long
929 const time_t sec2 = (time_t)sec;
930 if (sec2 == sec)
931 {
932 ts.tv_sec = sec2;
933 const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
934 ts.tv_nsec = (long)((winTime % 10000000) * 100);
935 return true;
936 }
937 }
938 // else
939 {
940 ts.tv_sec = 0;
941 ts.tv_nsec =
942 #ifdef UTIME_OMIT
943 UTIME_OMIT; // keep old timesptamp
944 #else
945 // UTIME_NOW; // set to the current time
946 0;
947 #endif
948 return false;
949 }
950}
951
952
953
954
955bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
956{
957 // need testing
958 /*
959 struct utimbuf buf;
960 struct stat st;
961 UNUSED_VAR(cTime)
962
963 printf("\nstat = %s\n", path);
964 int ret = stat(path, &st);
965
966 if (ret == 0)
967 {
968 buf.actime = st.st_atime;
969 buf.modtime = st.st_mtime;
970 }
971 else
972 {
973 time_t cur_time = time(0);
974 buf.actime = cur_time;
975 buf.modtime = cur_time;
976 }
977
978 if (aTime)
979 {
980 UInt32 ut;
981 if (NTime::FileTimeToUnixTime(*aTime, ut))
982 buf.actime = ut;
983 }
984
985 if (mTime)
986 {
987 UInt32 ut;
988 if (NTime::FileTimeToUnixTime(*mTime, ut))
989 buf.modtime = ut;
990 }
991
992 return utime(path, &buf) == 0;
993 */
994
995 // if (!aTime && !mTime) return true;
996
997 struct timespec times[2];
998 UNUSED_VAR(cTime)
999
1000 bool needChange;
1001 needChange = FILETME_To_timespec(aTime, times[0]);
1002 needChange |= FILETME_To_timespec(mTime, times[1]);
1003
1004 if (!needChange)
1005 return true;
1006
1007 const int flags = 0; // follow link
1008 // = AT_SYMLINK_NOFOLLOW; // don't follow link
1009 return utimensat(AT_FDCWD, path, times, flags) == 0;
1010}
1011
1012
1013
1014struct C_umask
1015{
1016 mode_t mask;
1017
1018 C_umask()
1019 {
1020 /* by security reasons we restrict attributes according
1021 with process's file mode creation mask (umask) */
1022 const mode_t um = umask(0); // octal :0022 is expected
1023 mask = 0777 & (~um); // octal: 0755 is expected
1024 umask(um); // restore the umask
1025 // printf("\n umask = 0%03o mask = 0%03o\n", um, mask);
1026
1027 // mask = 0777; // debug we can disable the restriction:
1028 }
1029};
1030
1031static C_umask g_umask;
1032
1033// #define PRF(x) x;
1034#define PRF(x)
1035
1036#define TRACE_SetFileAttrib(msg) \
1037 PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg));
1038
1039#define TRACE_chmod(s, mode) \
1040 PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode)));
1041
1042
1043bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1044{
1045 TRACE_SetFileAttrib("");
1046
1047 struct stat st;
1048
1049 bool use_lstat = true;
1050 if (use_lstat)
1051 {
1052 if (lstat(path, &st) != 0)
1053 {
1054 TRACE_SetFileAttrib("bad lstat()");
1055 return false;
1056 }
1057 // TRACE_chmod("lstat", st.st_mode);
1058 }
1059 else
1060 {
1061 if (stat(path, &st) != 0)
1062 {
1063 TRACE_SetFileAttrib("bad stat()");
1064 return false;
1065 }
1066 }
1067
1068 if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
1069 {
1070 TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION");
1071 st.st_mode = attrib >> 16;
1072 if (S_ISDIR(st.st_mode))
1073 {
1074 // user/7z must be able to create files in this directory
1075 st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
1076 }
1077 else if (!S_ISREG(st.st_mode))
1078 return true;
1079 }
1080 else if (S_ISLNK(st.st_mode))
1081 {
1082 /* for most systems: permissions for symlinks are fixed to rwxrwxrwx.
1083 so we don't need chmod() for symlinks. */
1084 return true;
1085 // SetLastError(ENOSYS);
1086 // return false;
1087 }
1088 else
1089 {
1090 TRACE_SetFileAttrib("Only Windows Attributes");
1091 // Only Windows Attributes
1092 if (S_ISDIR(st.st_mode)
1093 || (attrib & FILE_ATTRIBUTE_READONLY) == 0)
1094 return true;
1095 st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
1096 }
1097
1098 int res;
1099 /*
1100 if (S_ISLNK(st.st_mode))
1101 {
1102 printf("\nfchmodat()\n");
1103 TRACE_chmod(path, (st.st_mode) & g_umask.mask);
1104 // AT_SYMLINK_NOFOLLOW is not implemted still in Linux.
1105 res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask,
1106 S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0);
1107 }
1108 else
1109 */
1110 {
1111 TRACE_chmod(path, (st.st_mode) & g_umask.mask);
1112 res = chmod(path, (st.st_mode) & g_umask.mask);
1113 }
1114 // TRACE_SetFileAttrib("End")
1115 return (res == 0);
1116}
1117
1118
1119bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
1120{
1121 PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName));
1122 return (link(existFileName, newFileName) == 0);
1123}
1124
1125#endif // !_WIN32
1126
1127// #endif
1128
1129}}}
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
new file mode 100644
index 0000000..6d6ddea
--- /dev/null
+++ b/CPP/Windows/FileDir.h
@@ -0,0 +1,125 @@
1// Windows/FileDir.h
2
3#ifndef __WINDOWS_FILE_DIR_H
4#define __WINDOWS_FILE_DIR_H
5
6#include "../Common/MyString.h"
7
8#include "FileIO.h"
9
10namespace NWindows {
11namespace NFile {
12namespace NDir {
13
14bool GetWindowsDir(FString &path);
15bool GetSystemDir(FString &path);
16
17bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
18
19
20#ifdef _WIN32
21
22bool SetFileAttrib(CFSTR path, DWORD attrib);
23
24/*
25 Some programs store posix attributes in high 16 bits of windows attributes field.
26 Also some programs use additional flag markers: 0x8000 or 0x4000.
27 SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute
28 bits that are related to current system only.
29*/
30
31#endif
32
33bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);
34
35
36bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);
37
38#ifndef UNDER_CE
39bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName);
40#endif
41
42bool RemoveDir(CFSTR path);
43bool CreateDir(CFSTR path);
44
45/* CreateComplexDir returns true, if directory can contain files after the call (two cases):
46 1) the directory already exists (network shares and drive paths are supported)
47 2) the directory was created
48 path can be WITH or WITHOUT trailing path separator. */
49
50bool CreateComplexDir(CFSTR path);
51
52bool DeleteFileAlways(CFSTR name);
53bool RemoveDirWithSubItems(const FString &path);
54
55bool MyGetFullPathName(CFSTR path, FString &resFullPath);
56bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName);
57bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix);
58
59#ifndef UNDER_CE
60
61bool SetCurrentDir(CFSTR path);
62bool GetCurrentDir(FString &resultPath);
63
64#endif
65
66bool MyGetTempPath(FString &resultPath);
67
68class CTempFile MY_UNCOPYABLE
69{
70 bool _mustBeDeleted;
71 FString _path;
72 void DisableDeleting() { _mustBeDeleted = false; }
73public:
74 CTempFile(): _mustBeDeleted(false) {}
75 ~CTempFile() { Remove(); }
76 const FString &GetPath() const { return _path; }
77 bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix
78 bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile);
79 bool Remove();
80 bool MoveTo(CFSTR name, bool deleteDestBefore);
81};
82
83
84#ifdef _WIN32
85class CTempDir MY_UNCOPYABLE
86{
87 bool _mustBeDeleted;
88 FString _path;
89public:
90 CTempDir(): _mustBeDeleted(false) {}
91 ~CTempDir() { Remove(); }
92 const FString &GetPath() const { return _path; }
93 void DisableDeleting() { _mustBeDeleted = false; }
94 bool Create(CFSTR namePrefix) ;
95 bool Remove();
96};
97#endif
98
99
100#if !defined(UNDER_CE)
101class CCurrentDirRestorer MY_UNCOPYABLE
102{
103 FString _path;
104public:
105 bool NeedRestore;
106
107 CCurrentDirRestorer(): NeedRestore(true)
108 {
109 GetCurrentDir(_path);
110 }
111 ~CCurrentDirRestorer()
112 {
113 if (!NeedRestore)
114 return;
115 FString s;
116 if (GetCurrentDir(s))
117 if (s != _path)
118 SetCurrentDir(_path);
119 }
120};
121#endif
122
123}}}
124
125#endif
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
new file mode 100644
index 0000000..591f8df
--- /dev/null
+++ b/CPP/Windows/FileFind.cpp
@@ -0,0 +1,1242 @@
1// Windows/FileFind.cpp
2
3#include "StdAfx.h"
4
5// #include <stdio.h>
6
7#ifndef _WIN32
8#include <fcntl.h> /* Definition of AT_* constants */
9#include "TimeUtils.h"
10#endif
11
12#include "FileFind.h"
13#include "FileIO.h"
14#include "FileName.h"
15
16#ifndef _UNICODE
17extern bool g_IsNT;
18#endif
19
20using namespace NWindows;
21using namespace NFile;
22using namespace NName;
23
24#if defined(_WIN32) && !defined(UNDER_CE)
25
26EXTERN_C_BEGIN
27
28typedef enum
29{
30 My_FindStreamInfoStandard,
31 My_FindStreamInfoMaxInfoLevel
32} MY_STREAM_INFO_LEVELS;
33
34typedef struct
35{
36 LARGE_INTEGER StreamSize;
37 WCHAR cStreamName[MAX_PATH + 36];
38} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA;
39
40typedef HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,
41 LPVOID findStreamData, DWORD flags);
42
43typedef BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData);
44
45EXTERN_C_END
46
47#endif // defined(_WIN32) && !defined(UNDER_CE)
48
49
50namespace NWindows {
51namespace NFile {
52
53
54#ifdef _WIN32
55#ifdef SUPPORT_DEVICE_FILE
56namespace NSystem
57{
58bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
59}
60#endif
61#endif
62
63namespace NFind {
64
65#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
66
67void CFileInfoBase::ClearBase() throw()
68{
69 Size = 0;
70 MY_CLEAR_FILETIME(CTime);
71 MY_CLEAR_FILETIME(ATime);
72 MY_CLEAR_FILETIME(MTime);
73 Attrib = 0;
74 // ReparseTag = 0;
75 IsAltStream = false;
76 IsDevice = false;
77
78 #ifndef _WIN32
79 ino = 0;
80 nlink = 0;
81 mode = 0;
82 #endif
83}
84
85bool CFileInfo::IsDots() const throw()
86{
87 if (!IsDir() || Name.IsEmpty())
88 return false;
89 if (Name[0] != '.')
90 return false;
91 return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
92}
93
94
95#ifdef _WIN32
96
97
98#define WIN_FD_TO_MY_FI(fi, fd) \
99 fi.Attrib = fd.dwFileAttributes; \
100 fi.CTime = fd.ftCreationTime; \
101 fi.ATime = fd.ftLastAccessTime; \
102 fi.MTime = fd.ftLastWriteTime; \
103 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \
104 /* fi.ReparseTag = fd.dwReserved0; */ \
105 fi.IsAltStream = false; \
106 fi.IsDevice = false;
107
108 /*
109 #ifdef UNDER_CE
110 fi.ObjectID = fd.dwOID;
111 #else
112 fi.ReparseTag = fd.dwReserved0;
113 #endif
114 */
115
116static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi)
117{
118 WIN_FD_TO_MY_FI(fi, fd);
119 fi.Name = us2fs(fd.cFileName);
120 #if defined(_WIN32) && !defined(UNDER_CE)
121 // fi.ShortName = us2fs(fd.cAlternateFileName);
122 #endif
123}
124
125#ifndef _UNICODE
126static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)
127{
128 WIN_FD_TO_MY_FI(fi, fd);
129 fi.Name = fas2fs(fd.cFileName);
130 #if defined(_WIN32) && !defined(UNDER_CE)
131 // fi.ShortName = fas2fs(fd.cAlternateFileName);
132 #endif
133}
134#endif
135
136////////////////////////////////
137// CFindFile
138
139bool CFindFileBase::Close() throw()
140{
141 if (_handle == INVALID_HANDLE_VALUE)
142 return true;
143 if (!::FindClose(_handle))
144 return false;
145 _handle = INVALID_HANDLE_VALUE;
146 return true;
147}
148
149/*
150WinXP-64 FindFirstFile():
151 "" - ERROR_PATH_NOT_FOUND
152 folder\ - ERROR_FILE_NOT_FOUND
153 \ - ERROR_FILE_NOT_FOUND
154 c:\ - ERROR_FILE_NOT_FOUND
155 c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ )
156 c: - OK, if current dir is NOT ROOT ( c:\folder )
157 folder - OK
158
159 \\ - ERROR_INVALID_NAME
160 \\Server - ERROR_INVALID_NAME
161 \\Server\ - ERROR_INVALID_NAME
162
163 \\Server\Share - ERROR_BAD_NETPATH
164 \\Server\Share - ERROR_BAD_NET_NAME (Win7).
165 !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon),
166 when we call it for "\\Server\Share"
167
168 \\Server\Share\ - ERROR_FILE_NOT_FOUND
169
170 \\?\UNC\Server\Share - ERROR_INVALID_NAME
171 \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7)
172 \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND
173
174 \\Server\Share_RootDrive - ERROR_INVALID_NAME
175 \\Server\Share_RootDrive\ - ERROR_INVALID_NAME
176
177 e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder
178 w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w:
179*/
180
181bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
182{
183 if (!Close())
184 return false;
185 #ifndef _UNICODE
186 if (!g_IsNT)
187 {
188 WIN32_FIND_DATAA fd;
189 _handle = ::FindFirstFileA(fs2fas(path), &fd);
190 if (_handle == INVALID_HANDLE_VALUE)
191 return false;
192 Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
193 }
194 else
195 #endif
196 {
197 WIN32_FIND_DATAW fd;
198
199 IF_USE_MAIN_PATH
200 _handle = ::FindFirstFileW(fs2us(path), &fd);
201 #ifdef WIN_LONG_PATH
202 if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
203 {
204 UString superPath;
205 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
206 _handle = ::FindFirstFileW(superPath, &fd);
207 }
208 #endif
209 if (_handle == INVALID_HANDLE_VALUE)
210 return false;
211 Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
212 }
213 return true;
214}
215
216bool CFindFile::FindNext(CFileInfo &fi)
217{
218 #ifndef _UNICODE
219 if (!g_IsNT)
220 {
221 WIN32_FIND_DATAA fd;
222 if (!::FindNextFileA(_handle, &fd))
223 return false;
224 Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
225 }
226 else
227 #endif
228 {
229 WIN32_FIND_DATAW fd;
230 if (!::FindNextFileW(_handle, &fd))
231 return false;
232 Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
233 }
234 return true;
235}
236
237#if defined(_WIN32) && !defined(UNDER_CE)
238
239////////////////////////////////
240// AltStreams
241
242static FindFirstStreamW_Ptr g_FindFirstStreamW;
243static FindNextStreamW_Ptr g_FindNextStreamW;
244
245static struct CFindStreamLoader
246{
247 CFindStreamLoader()
248 {
249 HMODULE hm = ::GetModuleHandleA("kernel32.dll");
250 g_FindFirstStreamW = (FindFirstStreamW_Ptr)(void *)::GetProcAddress(hm, "FindFirstStreamW");
251 g_FindNextStreamW = (FindNextStreamW_Ptr)(void *)::GetProcAddress(hm, "FindNextStreamW");
252 }
253} g_FindStreamLoader;
254
255bool CStreamInfo::IsMainStream() const throw()
256{
257 return StringsAreEqualNoCase_Ascii(Name, "::$DATA");
258};
259
260UString CStreamInfo::GetReducedName() const
261{
262 // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"
263 UString s (Name);
264 if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))
265 s.DeleteFrom(s.Len() - 6);
266 return s;
267}
268
269/*
270UString CStreamInfo::GetReducedName2() const
271{
272 UString s = GetReducedName();
273 if (!s.IsEmpty() && s[0] == ':')
274 s.Delete(0);
275 return s;
276}
277*/
278
279static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)
280{
281 si.Size = (UInt64)sd.StreamSize.QuadPart;
282 si.Name = sd.cStreamName;
283}
284
285/*
286 WinXP-64 FindFirstStream():
287 "" - ERROR_PATH_NOT_FOUND
288 folder\ - OK
289 folder - OK
290 \ - OK
291 c:\ - OK
292 c: - OK, if current dir is ROOT ( c:\ )
293 c: - OK, if current dir is NOT ROOT ( c:\folder )
294 \\Server\Share - OK
295 \\Server\Share\ - OK
296
297 \\ - ERROR_INVALID_NAME
298 \\Server - ERROR_INVALID_NAME
299 \\Server\ - ERROR_INVALID_NAME
300*/
301
302bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
303{
304 if (!Close())
305 return false;
306 if (!g_FindFirstStreamW)
307 {
308 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
309 return false;
310 }
311 {
312 MY_WIN32_FIND_STREAM_DATA sd;
313 SetLastError(0);
314 IF_USE_MAIN_PATH
315 _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);
316 if (_handle == INVALID_HANDLE_VALUE)
317 {
318 if (::GetLastError() == ERROR_HANDLE_EOF)
319 return false;
320 // long name can be tricky for path like ".\dirName".
321 #ifdef WIN_LONG_PATH
322 if (USE_SUPER_PATH)
323 {
324 UString superPath;
325 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
326 _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);
327 }
328 #endif
329 }
330 if (_handle == INVALID_HANDLE_VALUE)
331 return false;
332 Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);
333 }
334 return true;
335}
336
337bool CFindStream::FindNext(CStreamInfo &si)
338{
339 if (!g_FindNextStreamW)
340 {
341 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
342 return false;
343 }
344 {
345 MY_WIN32_FIND_STREAM_DATA sd;
346 if (!g_FindNextStreamW(_handle, &sd))
347 return false;
348 Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);
349 }
350 return true;
351}
352
353bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)
354{
355 bool res;
356 if (_find.IsHandleAllocated())
357 res = _find.FindNext(si);
358 else
359 res = _find.FindFirst(_filePath, si);
360 if (res)
361 {
362 found = true;
363 return true;
364 }
365 found = false;
366 return (::GetLastError() == ERROR_HANDLE_EOF);
367}
368
369#endif
370
371
372/*
373WinXP-64 GetFileAttributes():
374 If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code
375
376 \ - OK
377 C:\ - OK, if there is such drive,
378 D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive,
379
380 C:\folder - OK
381 C:\folder\ - OK
382 C:\folderBad - ERROR_FILE_NOT_FOUND
383
384 \\Server\BadShare - ERROR_BAD_NETPATH
385 \\Server\Share - WORKS OK, but MSDN says:
386 GetFileAttributes for a network share, the function fails, and GetLastError
387 returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.
388*/
389
390DWORD GetFileAttrib(CFSTR path)
391{
392 #ifndef _UNICODE
393 if (!g_IsNT)
394 return ::GetFileAttributes(fs2fas(path));
395 else
396 #endif
397 {
398 IF_USE_MAIN_PATH
399 {
400 DWORD dw = ::GetFileAttributesW(fs2us(path));
401 if (dw != INVALID_FILE_ATTRIBUTES)
402 return dw;
403 }
404 #ifdef WIN_LONG_PATH
405 if (USE_SUPER_PATH)
406 {
407 UString superPath;
408 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
409 return ::GetFileAttributesW(superPath);
410 }
411 #endif
412 return INVALID_FILE_ATTRIBUTES;
413 }
414}
415
416/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk
417 so instead of absolute path we have relative path in Name. That is not good in some calls */
418
419/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */
420
421/* CFileInfo::Find()
422We alow the following paths (as FindFirstFile):
423 C:\folder
424 c: - if current dir is NOT ROOT ( c:\folder )
425
426also we support paths that are not supported by FindFirstFile:
427 \
428 \\.\c:
429 c:\ - Name will be without tail slash ( c: )
430 \\?\c:\ - Name will be without tail slash ( c: )
431 \\Server\Share
432 \\?\UNC\Server\Share
433
434 c:\folder:stream - Name = folder:stream
435 c:\:stream - Name = :stream
436 c::stream - Name = c::stream
437*/
438
439bool CFileInfo::Find(CFSTR path, bool followLink)
440{
441 #ifdef SUPPORT_DEVICE_FILE
442 if (IsDevicePath(path))
443 {
444 ClearBase();
445 Name = path + 4;
446 IsDevice = true;
447
448 if (NName::IsDrivePath2(path + 4) && path[6] == 0)
449 {
450 FChar drive[4] = { path[4], ':', '\\', 0 };
451 UInt64 clusterSize, totalSize, freeSize;
452 if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize))
453 {
454 Size = totalSize;
455 return true;
456 }
457 }
458
459 NIO::CInFile inFile;
460 // ::OutputDebugStringW(path);
461 if (!inFile.Open(path))
462 return false;
463 // ::OutputDebugStringW(L"---");
464 if (inFile.SizeDefined)
465 Size = inFile.Size;
466 return true;
467 }
468 #endif
469
470 #if defined(_WIN32) && !defined(UNDER_CE)
471
472 int colonPos = FindAltStreamColon(path);
473 if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
474 {
475 UString streamName = fs2us(path + (unsigned)colonPos);
476 FString filePath (path);
477 filePath.DeleteFrom((unsigned)colonPos);
478 /* we allow both cases:
479 name:stream
480 name:stream:$DATA
481 */
482 const unsigned kPostfixSize = 6;
483 if (streamName.Len() <= kPostfixSize
484 || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))
485 streamName += ":$DATA";
486
487 bool isOk = true;
488
489 if (IsDrivePath2(filePath) &&
490 (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\')))
491 {
492 // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)
493 ClearBase();
494 Name.Empty();
495 if (colonPos == 2)
496 Name = filePath;
497 }
498 else
499 isOk = Find(filePath, followLink); // check it (followLink)
500
501 if (isOk)
502 {
503 Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
504 Size = 0;
505 CStreamEnumerator enumerator(filePath);
506 for (;;)
507 {
508 CStreamInfo si;
509 bool found;
510 if (!enumerator.Next(si, found))
511 return false;
512 if (!found)
513 {
514 ::SetLastError(ERROR_FILE_NOT_FOUND);
515 return false;
516 }
517 if (si.Name.IsEqualTo_NoCase(streamName))
518 {
519 // we delete postfix, if alt stream name is not "::$DATA"
520 if (si.Name.Len() > kPostfixSize + 1)
521 si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);
522 Name += us2fs(si.Name);
523 Size = si.Size;
524 IsAltStream = true;
525 return true;
526 }
527 }
528 }
529 }
530
531 #endif
532
533 CFindFile finder;
534
535 #if defined(_WIN32) && !defined(UNDER_CE)
536 {
537 /*
538 DWORD lastError = GetLastError();
539 if (lastError == ERROR_FILE_NOT_FOUND
540 || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share"
541 || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share"
542 || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share"
543 || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share"
544 )
545 */
546
547 unsigned rootSize = 0;
548 if (IsSuperPath(path))
549 rootSize = kSuperPathPrefixSize;
550
551 if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)
552 {
553 DWORD attrib = GetFileAttrib(path);
554 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
555 {
556 ClearBase();
557 Attrib = attrib;
558 Name = path + rootSize;
559 Name.DeleteFrom(2);
560 if (!Fill_From_ByHandleFileInfo(path))
561 {
562 }
563 return true;
564 }
565 }
566 else if (IS_PATH_SEPAR(path[0]))
567 {
568 if (path[1] == 0)
569 {
570 DWORD attrib = GetFileAttrib(path);
571 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
572 {
573 ClearBase();
574 Name.Empty();
575 Attrib = attrib;
576 return true;
577 }
578 }
579 else
580 {
581 const unsigned prefixSize = GetNetworkServerPrefixSize(path);
582 if (prefixSize > 0 && path[prefixSize] != 0)
583 {
584 if (NName::FindSepar(path + prefixSize) < 0)
585 {
586 if (Fill_From_ByHandleFileInfo(path))
587 {
588 Name = path + prefixSize;
589 return true;
590 }
591
592 FString s (path);
593 s.Add_PathSepar();
594 s += '*'; // CHAR_ANY_MASK
595 bool isOK = false;
596 if (finder.FindFirst(s, *this))
597 {
598 if (Name == FTEXT("."))
599 {
600 Name = path + prefixSize;
601 return true;
602 }
603 isOK = true;
604 /* if "\\server\share" maps to root folder "d:\", there is no "." item.
605 But it's possible that there are another items */
606 }
607 {
608 DWORD attrib = GetFileAttrib(path);
609 if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0))
610 {
611 ClearBase();
612 if (attrib != INVALID_FILE_ATTRIBUTES)
613 Attrib = attrib;
614 else
615 SetAsDir();
616 Name = path + prefixSize;
617 return true;
618 }
619 }
620 // ::SetLastError(lastError);
621 }
622 }
623 }
624 }
625 }
626 #endif
627
628 bool res = finder.FindFirst(path, *this);
629 if (!followLink
630 || !res
631 || !HasReparsePoint())
632 return res;
633
634 // return FollowReparse(path, IsDir());
635 return Fill_From_ByHandleFileInfo(path);
636}
637
638bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path)
639{
640 BY_HANDLE_FILE_INFORMATION info;
641 if (!NIO::CFileBase::GetFileInformation(path, &info))
642 return false;
643 {
644 Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
645 CTime = info.ftCreationTime;
646 ATime = info.ftLastAccessTime;
647 MTime = info.ftLastWriteTime;
648 Attrib = info.dwFileAttributes;
649 return true;
650 }
651}
652
653/*
654bool CFileInfo::FollowReparse(CFSTR path, bool isDir)
655{
656 if (isDir)
657 {
658 FString prefix = path;
659 prefix.Add_PathSepar();
660
661 // "folder/." refers to folder itself. So we can't use that path
662 // we must use enumerator and search "." item
663 CEnumerator enumerator;
664 enumerator.SetDirPrefix(prefix);
665 for (;;)
666 {
667 CFileInfo fi;
668 if (!enumerator.NextAny(fi))
669 break;
670 if (fi.Name.IsEqualTo_Ascii_NoCase("."))
671 {
672 // we can copy preperies;
673 CTime = fi.CTime;
674 ATime = fi.ATime;
675 MTime = fi.MTime;
676 Attrib = fi.Attrib;
677 Size = fi.Size;
678 return true;
679 }
680 break;
681 }
682 // LastError(lastError);
683 return false;
684 }
685
686 {
687 NIO::CInFile inFile;
688 if (inFile.Open(path))
689 {
690 BY_HANDLE_FILE_INFORMATION info;
691 if (inFile.GetFileInformation(&info))
692 {
693 ClearBase();
694 Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
695 CTime = info.ftCreationTime;
696 ATime = info.ftLastAccessTime;
697 MTime = info.ftLastWriteTime;
698 Attrib = info.dwFileAttributes;
699 return true;
700 }
701 }
702 return false;
703 }
704}
705*/
706
707bool DoesFileExist_Raw(CFSTR name)
708{
709 CFileInfo fi;
710 return fi.Find(name) && !fi.IsDir();
711}
712
713bool DoesFileExist_FollowLink(CFSTR name)
714{
715 CFileInfo fi;
716 return fi.Find_FollowLink(name) && !fi.IsDir();
717}
718
719bool DoesDirExist(CFSTR name, bool followLink)
720{
721 CFileInfo fi;
722 return fi.Find(name, followLink) && fi.IsDir();
723}
724
725bool DoesFileOrDirExist(CFSTR name)
726{
727 CFileInfo fi;
728 return fi.Find(name);
729}
730
731
732void CEnumerator::SetDirPrefix(const FString &dirPrefix)
733{
734 _wildcard = dirPrefix;
735 _wildcard += '*';
736}
737
738bool CEnumerator::NextAny(CFileInfo &fi)
739{
740 if (_findFile.IsHandleAllocated())
741 return _findFile.FindNext(fi);
742 else
743 return _findFile.FindFirst(_wildcard, fi);
744}
745
746bool CEnumerator::Next(CFileInfo &fi)
747{
748 for (;;)
749 {
750 if (!NextAny(fi))
751 return false;
752 if (!fi.IsDots())
753 return true;
754 }
755}
756
757bool CEnumerator::Next(CFileInfo &fi, bool &found)
758{
759 /*
760 for (;;)
761 {
762 if (!NextAny(fi))
763 break;
764 if (!fi.IsDots())
765 {
766 found = true;
767 return true;
768 }
769 }
770 */
771
772 if (Next(fi))
773 {
774 found = true;
775 return true;
776 }
777
778 found = false;
779 DWORD lastError = ::GetLastError();
780 if (_findFile.IsHandleAllocated())
781 return (lastError == ERROR_NO_MORE_FILES);
782 // we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND
783 if (lastError == ERROR_FILE_NOT_FOUND)
784 return true;
785 if (lastError == ERROR_ACCESS_DENIED)
786 {
787 // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings
788 const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*";
789 const int len = (int)strlen(s);
790 const int delta = (int)_wildcard.Len() - len;
791 if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1])))
792 if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s))
793 return true;
794 }
795 return false;
796}
797
798
799////////////////////////////////
800// CFindChangeNotification
801// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
802
803bool CFindChangeNotification::Close() throw()
804{
805 if (!IsHandleAllocated())
806 return true;
807 if (!::FindCloseChangeNotification(_handle))
808 return false;
809 _handle = INVALID_HANDLE_VALUE;
810 return true;
811}
812
813HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter)
814{
815 #ifndef _UNICODE
816 if (!g_IsNT)
817 _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter);
818 else
819 #endif
820 {
821 IF_USE_MAIN_PATH
822 _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter);
823 #ifdef WIN_LONG_PATH
824 if (!IsHandleAllocated())
825 {
826 UString superPath;
827 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
828 _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);
829 }
830 #endif
831 }
832 return _handle;
833}
834
835#ifndef UNDER_CE
836
837bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
838{
839 driveStrings.Clear();
840 #ifndef _UNICODE
841 if (!g_IsNT)
842 {
843 driveStrings.Clear();
844 UINT32 size = GetLogicalDriveStrings(0, NULL);
845 if (size == 0)
846 return false;
847 CObjArray<char> buf(size);
848 UINT32 newSize = GetLogicalDriveStrings(size, buf);
849 if (newSize == 0 || newSize > size)
850 return false;
851 AString s;
852 UINT32 prev = 0;
853 for (UINT32 i = 0; i < newSize; i++)
854 {
855 if (buf[i] == 0)
856 {
857 s = buf + prev;
858 prev = i + 1;
859 driveStrings.Add(fas2fs(s));
860 }
861 }
862 return prev == newSize;
863 }
864 else
865 #endif
866 {
867 UINT32 size = GetLogicalDriveStringsW(0, NULL);
868 if (size == 0)
869 return false;
870 CObjArray<wchar_t> buf(size);
871 UINT32 newSize = GetLogicalDriveStringsW(size, buf);
872 if (newSize == 0 || newSize > size)
873 return false;
874 UString s;
875 UINT32 prev = 0;
876 for (UINT32 i = 0; i < newSize; i++)
877 {
878 if (buf[i] == 0)
879 {
880 s = buf + prev;
881 prev = i + 1;
882 driveStrings.Add(us2fs(s));
883 }
884 }
885 return prev == newSize;
886 }
887}
888
889#endif // UNDER_CE
890
891
892
893#else // _WIN32
894
895// ---------- POSIX ----------
896
897static int MY__lstat(CFSTR path, struct stat *st, bool followLink)
898{
899 memset(st, 0, sizeof(*st));
900 int res;
901 // #ifdef ENV_HAVE_LSTAT
902 if (/* global_use_lstat && */ !followLink)
903 {
904 // printf("\nlstat\n");
905 res = lstat(path, st);
906 }
907 else
908 // #endif
909 {
910 // printf("\nstat\n");
911 res = stat(path, st);
912 }
913 /*
914 printf("\nres = %d\n", res);
915 printf("\n st_dev = %lld \n", (long long)(st->st_dev));
916 printf("\n st_ino = %lld \n", (long long)(st->st_ino));
917 printf("\n st_mode = %lld \n", (long long)(st->st_mode));
918 printf("\n st_nlink = %lld \n", (long long)(st->st_nlink));
919 printf("\n st_uid = %lld \n", (long long)(st->st_uid));
920 printf("\n st_gid = %lld \n", (long long)(st->st_gid));
921 printf("\n st_size = %lld \n", (long long)(st->st_size));
922 printf("\n st_blksize = %lld \n", (long long)(st->st_blksize));
923 printf("\n st_blocks = %lld \n", (long long)(st->st_blocks));
924 */
925
926 return res;
927}
928
929
930static const char *Get_Name_from_Path(CFSTR path) throw()
931{
932 size_t len = strlen(path);
933 if (len == 0)
934 return path;
935 const char *p = path + len - 1;
936 {
937 if (p == path)
938 return path;
939 p--;
940 }
941 for (;;)
942 {
943 char c = *p;
944 if (IS_PATH_SEPAR(c))
945 return p + 1;
946 if (p == path)
947 return path;
948 p--;
949 }
950}
951
952
953void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft)
954{
955 UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
956 ft.dwLowDateTime = (DWORD)v;
957 ft.dwHighDateTime = (DWORD)(v >> 32);
958}
959
960UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode)
961{
962 UInt32 attrib = S_ISDIR(mode) ?
963 FILE_ATTRIBUTE_DIRECTORY :
964 FILE_ATTRIBUTE_ARCHIVE;
965 if ((mode & 0222) == 0) // S_IWUSR in p7zip
966 attrib |= FILE_ATTRIBUTE_READONLY;
967 return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16);
968}
969
970/*
971UInt32 Get_WinAttrib_From_stat(const struct stat &st)
972{
973 UInt32 attrib = S_ISDIR(st.st_mode) ?
974 FILE_ATTRIBUTE_DIRECTORY :
975 FILE_ATTRIBUTE_ARCHIVE;
976
977 if ((st.st_mode & 0222) == 0) // check it !!!
978 attrib |= FILE_ATTRIBUTE_READONLY;
979
980 attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16);
981 return attrib;
982}
983*/
984
985void CFileInfo::SetFrom_stat(const struct stat &st)
986{
987 IsDevice = false;
988
989 if (S_ISDIR(st.st_mode))
990 {
991 Size = 0;
992 }
993 else
994 {
995 Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename
996 }
997
998 Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode);
999
1000 // NTime::UnixTimeToFileTime(st.st_ctime, CTime);
1001 // NTime::UnixTimeToFileTime(st.st_mtime, MTime);
1002 // NTime::UnixTimeToFileTime(st.st_atime, ATime);
1003 #ifdef __APPLE__
1004 // #ifdef _DARWIN_FEATURE_64_BIT_INODE
1005 /*
1006 here we can use birthtime instead of st_ctimespec.
1007 but we use st_ctimespec for compatibility with previous versions and p7zip.
1008 st_birthtimespec in OSX
1009 st_birthtim : at FreeBSD, NetBSD
1010 */
1011 // timespec_To_FILETIME(st.st_birthtimespec, CTime);
1012 // #else
1013 timespec_To_FILETIME(st.st_ctimespec, CTime);
1014 // #endif
1015 timespec_To_FILETIME(st.st_mtimespec, MTime);
1016 timespec_To_FILETIME(st.st_atimespec, ATime);
1017 #else
1018 timespec_To_FILETIME(st.st_ctim, CTime);
1019 timespec_To_FILETIME(st.st_mtim, MTime);
1020 timespec_To_FILETIME(st.st_atim, ATime);
1021 #endif
1022
1023 dev = st.st_dev;
1024 ino = st.st_ino;
1025 nlink = st.st_nlink;
1026 mode = st.st_mode;
1027}
1028
1029bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)
1030{
1031 struct stat st;
1032 if (MY__lstat(path, &st, followLink) != 0)
1033 return false;
1034 SetFrom_stat(st);
1035 return true;
1036}
1037
1038
1039bool CFileInfo::Find(CFSTR path, bool followLink)
1040{
1041 // printf("\nCEnumerator::Find() name = %s\n", path);
1042 if (!Find_DontFill_Name(path, followLink))
1043 return false;
1044
1045 // printf("\nOK\n");
1046
1047 Name = Get_Name_from_Path(path);
1048 if (!Name.IsEmpty())
1049 {
1050 char c = Name.Back();
1051 if (IS_PATH_SEPAR(c))
1052 Name.DeleteBack();
1053 }
1054 return true;
1055}
1056
1057
1058bool DoesFileExist_Raw(CFSTR name)
1059{
1060 // FIXME for symbolic links.
1061 struct stat st;
1062 if (MY__lstat(name, &st, false) != 0)
1063 return false;
1064 return !S_ISDIR(st.st_mode);
1065}
1066
1067bool DoesFileExist_FollowLink(CFSTR name)
1068{
1069 // FIXME for symbolic links.
1070 struct stat st;
1071 if (MY__lstat(name, &st, true) != 0)
1072 return false;
1073 return !S_ISDIR(st.st_mode);
1074}
1075
1076bool DoesDirExist(CFSTR name, bool followLink)
1077{
1078 struct stat st;
1079 if (MY__lstat(name, &st, followLink) != 0)
1080 return false;
1081 return S_ISDIR(st.st_mode);
1082}
1083
1084bool DoesFileOrDirExist(CFSTR name)
1085{
1086 struct stat st;
1087 if (MY__lstat(name, &st, false) != 0)
1088 return false;
1089 return true;
1090}
1091
1092
1093CEnumerator::~CEnumerator()
1094{
1095 if (_dir)
1096 closedir(_dir);
1097}
1098
1099void CEnumerator::SetDirPrefix(const FString &dirPrefix)
1100{
1101 _wildcard = dirPrefix;
1102}
1103
1104bool CDirEntry::IsDots() const throw()
1105{
1106 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1107 we can call fstatat() for that case, but we use only (Name) check here */
1108
1109 #if !defined(_AIX)
1110 if (Type != DT_DIR && Type != DT_UNKNOWN)
1111 return false;
1112 #endif
1113
1114 return Name.Len() != 0
1115 && Name.Len() <= 2
1116 && Name[0] == '.'
1117 && (Name.Len() == 1 || Name[1] == '.');
1118}
1119
1120
1121bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
1122{
1123 found = false;
1124
1125 if (!_dir)
1126 {
1127 const char *w = "./";
1128 if (!_wildcard.IsEmpty())
1129 w = _wildcard.Ptr();
1130 _dir = ::opendir((const char *)w);
1131 if (_dir == NULL)
1132 return false;
1133 }
1134
1135 // To distinguish end of stream from an error, we must set errno to zero before readdir()
1136 errno = 0;
1137
1138 struct dirent *de = readdir(_dir);
1139 if (!de)
1140 {
1141 if (errno == 0)
1142 return true; // it's end of stream, and we report it with (found = false)
1143 // it's real error
1144 return false;
1145 }
1146
1147 fi.iNode = de->d_ino;
1148
1149 #if !defined(_AIX)
1150 fi.Type = de->d_type;
1151 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1152 we can set (Type) from fstatat() in that case.
1153 But (Type) is not too important. So we don't set it here with slow fstatat() */
1154 /*
1155 // fi.Type = DT_UNKNOWN; // for debug
1156 if (fi.Type == DT_UNKNOWN)
1157 {
1158 struct stat st;
1159 if (fstatat(dirfd(_dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)
1160 if (S_ISDIR(st.st_mode))
1161 fi.Type = DT_DIR;
1162 }
1163 */
1164 #endif
1165
1166 /*
1167 if (de->d_type == DT_DIR)
1168 fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16);
1169 else if (de->d_type < 16)
1170 fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12));
1171 */
1172 fi.Name = de->d_name;
1173
1174 /*
1175 printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr());
1176 for (unsigned i = 0; i < fi.Name.Len(); i++)
1177 printf (" %02x", (unsigned)(Byte)de->d_name[i]);
1178 printf("\n");
1179 */
1180
1181 found = true;
1182 return true;
1183}
1184
1185
1186bool CEnumerator::Next(CDirEntry &fi, bool &found)
1187{
1188 // printf("\nCEnumerator::Next()\n");
1189 // PrintName("Next", "");
1190 for (;;)
1191 {
1192 if (!NextAny(fi, found))
1193 return false;
1194 if (!found)
1195 return true;
1196 if (!fi.IsDots())
1197 {
1198 /*
1199 if (!NeedFullStat)
1200 return true;
1201 // we silently skip error file here - it can be wrong link item
1202 if (fi.Find_DontFill_Name(path))
1203 return true;
1204 */
1205 return true;
1206 }
1207 }
1208}
1209
1210/*
1211bool CEnumerator::Next(CDirEntry &fileInfo, bool &found)
1212{
1213 bool found;
1214 if (!Next(fi, found))
1215 return false;
1216 return found;
1217}
1218*/
1219
1220bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const
1221{
1222 // printf("\nCEnumerator::Fill_FileInfo()\n");
1223 struct stat st;
1224 // probably it's OK to use fstatat() even if it changes file position dirfd(_dir)
1225 int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW);
1226 // if fstatat() is not supported, we can use stat() / lstat()
1227
1228 /*
1229 const FString path = _wildcard + s;
1230 int res = MY__lstat(path, &st, followLink);
1231 */
1232
1233 if (res != 0)
1234 return false;
1235 fileInfo.SetFrom_stat(st);
1236 fileInfo.Name = de.Name;
1237 return true;
1238}
1239
1240#endif // _WIN32
1241
1242}}}
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
new file mode 100644
index 0000000..8f28ee3
--- /dev/null
+++ b/CPP/Windows/FileFind.h
@@ -0,0 +1,305 @@
1// Windows/FileFind.h
2
3#ifndef __WINDOWS_FILE_FIND_H
4#define __WINDOWS_FILE_FIND_H
5
6#ifndef _WIN32
7#include <sys/stat.h>
8#include <sys/types.h>
9#include <dirent.h>
10#endif
11
12#include "../Common/MyString.h"
13#include "../Common/MyWindows.h"
14#include "Defs.h"
15
16namespace NWindows {
17namespace NFile {
18namespace NFind {
19
20// bool DoesFileExist(CFSTR name, bool followLink);
21bool DoesFileExist_Raw(CFSTR name);
22bool DoesFileExist_FollowLink(CFSTR name);
23bool DoesDirExist(CFSTR name, bool followLink);
24
25inline bool DoesDirExist(CFSTR name)
26 { return DoesDirExist(name, false); }
27inline bool DoesDirExist_FollowLink(CFSTR name)
28 { return DoesDirExist(name, true); }
29
30// it's always _Raw
31bool DoesFileOrDirExist(CFSTR name);
32
33DWORD GetFileAttrib(CFSTR path);
34
35
36namespace NAttributes
37{
38 inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }
39 inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; }
40 inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; }
41 inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }
42 inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }
43 inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }
44 inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }
45}
46
47class CFileInfoBase
48{
49 bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }
50public:
51 UInt64 Size;
52 FILETIME CTime;
53 FILETIME ATime;
54 FILETIME MTime;
55 DWORD Attrib;
56 bool IsAltStream;
57 bool IsDevice;
58
59 #ifdef _WIN32
60 /*
61 #ifdef UNDER_CE
62 DWORD ObjectID;
63 #else
64 UINT32 ReparseTag;
65 #endif
66 */
67 #else
68 dev_t dev;
69 ino_t ino;
70 nlink_t nlink;
71 mode_t mode;
72 // bool Use_lstat;
73 #endif
74
75 CFileInfoBase() { ClearBase(); }
76 void ClearBase() throw();
77
78 void SetAsDir()
79 {
80 Attrib = FILE_ATTRIBUTE_DIRECTORY;
81 #ifndef _WIN32
82 Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
83 #endif
84 }
85
86 bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
87 bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
88 bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }
89 bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }
90 bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }
91 bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }
92 bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }
93 bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }
94 bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }
95 bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }
96 bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }
97 bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }
98
99 #ifndef _WIN32
100 bool IsPosixLink() const
101 {
102 const UInt32 mod = Attrib >> 16;
103 return S_ISLNK(mod);
104 }
105 #endif
106
107 bool IsOsSymLink() const
108 {
109 #ifdef _WIN32
110 return HasReparsePoint();
111 #else
112 return IsPosixLink();
113 #endif
114 }
115};
116
117struct CFileInfo: public CFileInfoBase
118{
119 FString Name;
120 #if defined(_WIN32) && !defined(UNDER_CE)
121 // FString ShortName;
122 #endif
123
124 bool IsDots() const throw();
125 bool Find(CFSTR path, bool followLink = false);
126 bool Find_FollowLink(CFSTR path) { return Find(path, true); }
127
128 #ifdef _WIN32
129 bool Fill_From_ByHandleFileInfo(CFSTR path);
130 // bool FollowReparse(CFSTR path, bool isDir);
131 #else
132 bool Find_DontFill_Name(CFSTR path, bool followLink = false);
133 void SetFrom_stat(const struct stat &st);
134 #endif
135};
136
137
138#ifdef _WIN32
139
140class CFindFileBase MY_UNCOPYABLE
141{
142protected:
143 HANDLE _handle;
144public:
145 bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }
146 CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {}
147 ~CFindFileBase() { Close(); }
148 bool Close() throw();
149};
150
151class CFindFile: public CFindFileBase
152{
153public:
154 bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo);
155 bool FindNext(CFileInfo &fileInfo);
156};
157
158#if defined(_WIN32) && !defined(UNDER_CE)
159
160struct CStreamInfo
161{
162 UString Name;
163 UInt64 Size;
164
165 UString GetReducedName() const; // returns ":Name"
166 // UString GetReducedName2() const; // returns "Name"
167 bool IsMainStream() const throw();
168};
169
170class CFindStream: public CFindFileBase
171{
172public:
173 bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo);
174 bool FindNext(CStreamInfo &streamInfo);
175};
176
177class CStreamEnumerator MY_UNCOPYABLE
178{
179 CFindStream _find;
180 FString _filePath;
181
182 bool NextAny(CFileInfo &fileInfo, bool &found);
183public:
184 CStreamEnumerator(const FString &filePath): _filePath(filePath) {}
185 bool Next(CStreamInfo &streamInfo, bool &found);
186};
187
188#endif // defined(_WIN32) && !defined(UNDER_CE)
189
190
191class CEnumerator MY_UNCOPYABLE
192{
193 CFindFile _findFile;
194 FString _wildcard;
195
196 bool NextAny(CFileInfo &fileInfo);
197public:
198 void SetDirPrefix(const FString &dirPrefix);
199 bool Next(CFileInfo &fileInfo);
200 bool Next(CFileInfo &fileInfo, bool &found);
201};
202
203
204class CFindChangeNotification MY_UNCOPYABLE
205{
206 HANDLE _handle;
207public:
208 operator HANDLE () { return _handle; }
209 bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }
210 CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}
211 ~CFindChangeNotification() { Close(); }
212 bool Close() throw();
213 HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);
214 bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }
215};
216
217#ifndef UNDER_CE
218bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);
219#endif
220
221typedef CFileInfo CDirEntry;
222
223
224#else // WIN32
225
226
227struct CDirEntry
228{
229 ino_t iNode;
230 #if !defined(_AIX)
231 Byte Type;
232 #endif
233 FString Name;
234
235 /*
236 #if !defined(_AIX)
237 bool IsDir() const
238 {
239 // (Type == DT_UNKNOWN) on some systems
240 return Type == DT_DIR;
241 }
242 #endif
243 */
244
245 bool IsDots() const throw();
246};
247
248class CEnumerator MY_UNCOPYABLE
249{
250 DIR *_dir;
251 FString _wildcard;
252
253 bool NextAny(CDirEntry &fileInfo, bool &found);
254public:
255 CEnumerator(): _dir(NULL) {}
256 ~CEnumerator();
257 void SetDirPrefix(const FString &dirPrefix);
258
259 bool Next(CDirEntry &fileInfo, bool &found);
260 bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
261 bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
262 {
263 #if !defined(_AIX)
264 if (de.Type == DT_DIR)
265 return true;
266 if (de.Type != DT_UNKNOWN)
267 return false;
268 #endif
269 CFileInfo fileInfo;
270 if (Fill_FileInfo(de, fileInfo, followLink))
271 {
272 return fileInfo.IsDir();
273 }
274 return false; // change it
275 }
276};
277
278/*
279inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
280{
281 UInt32 attrib = S_ISDIR(mode) ?
282 FILE_ATTRIBUTE_DIRECTORY :
283 FILE_ATTRIBUTE_ARCHIVE;
284 if ((st.st_mode & 0222) == 0) // check it !!!
285 attrib |= FILE_ATTRIBUTE_READONLY;
286 return attrib;
287}
288*/
289
290UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);
291
292// UInt32 Get_WinAttrib_From_stat(const struct stat &st);
293#if defined(_AIX)
294 #define MY_ST_TIMESPEC st_timespec
295#else
296 #define MY_ST_TIMESPEC timespec
297#endif
298
299void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft);
300
301#endif // WIN32
302
303}}}
304
305#endif
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
new file mode 100644
index 0000000..2974b1b
--- /dev/null
+++ b/CPP/Windows/FileIO.cpp
@@ -0,0 +1,825 @@
1// Windows/FileIO.cpp
2
3#include "StdAfx.h"
4
5#ifdef SUPPORT_DEVICE_FILE
6#include "../../C/Alloc.h"
7#endif
8
9// #include <stdio.h>
10
11#include "FileIO.h"
12#include "FileName.h"
13
14HRESULT GetLastError_noZero_HRESULT()
15{
16 DWORD res = ::GetLastError();
17 if (res == 0)
18 return E_FAIL;
19 return HRESULT_FROM_WIN32(res);
20}
21
22#ifdef _WIN32
23
24#ifndef _UNICODE
25extern bool g_IsNT;
26#endif
27
28using namespace NWindows;
29using namespace NFile;
30using namespace NName;
31
32namespace NWindows {
33namespace NFile {
34
35#ifdef SUPPORT_DEVICE_FILE
36
37namespace NSystem
38{
39bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
40}
41#endif
42
43namespace NIO {
44
45/*
46WinXP-64 CreateFile():
47 "" - ERROR_PATH_NOT_FOUND
48 :stream - OK
49 .:stream - ERROR_PATH_NOT_FOUND
50 .\:stream - OK
51
52 folder\:stream - ERROR_INVALID_NAME
53 folder:stream - OK
54
55 c:\:stream - OK
56
57 c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 )
58 c::stream - OK, if current dir is ROOT ( c:\ )
59*/
60
61bool CFileBase::Create(CFSTR path, DWORD desiredAccess,
62 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
63{
64 if (!Close())
65 return false;
66
67 #ifdef SUPPORT_DEVICE_FILE
68 IsDeviceFile = false;
69 #endif
70
71 #ifndef _UNICODE
72 if (!g_IsNT)
73 {
74 _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode,
75 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
76 }
77 else
78 #endif
79 {
80 IF_USE_MAIN_PATH
81 _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode,
82 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
83 #ifdef WIN_LONG_PATH
84 if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
85 {
86 UString superPath;
87 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
88 _handle = ::CreateFileW(superPath, desiredAccess, shareMode,
89 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
90 }
91 #endif
92 }
93
94 /*
95 #ifndef UNDER_CE
96 #ifndef _SFX
97 if (_handle == INVALID_HANDLE_VALUE)
98 {
99 // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10
100 DWORD lastError = GetLastError();
101 if (lastError == ERROR_CANT_ACCESS_FILE)
102 {
103 CByteBuffer buf;
104 if (NIO::GetReparseData(path, buf, NULL))
105 {
106 CReparseAttr attr;
107 if (attr.Parse(buf, buf.Size()))
108 {
109 FString dirPrefix, fileName;
110 if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName))
111 {
112 FString fullPath;
113 if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath))
114 {
115 // FIX IT: recursion levels must be restricted
116 return Create(fullPath, desiredAccess,
117 shareMode, creationDisposition, flagsAndAttributes);
118 }
119 }
120 }
121 }
122 SetLastError(lastError);
123 }
124 }
125 #endif
126 #endif
127 */
128
129 return (_handle != INVALID_HANDLE_VALUE);
130}
131
132bool CFileBase::Close() throw()
133{
134 if (_handle == INVALID_HANDLE_VALUE)
135 return true;
136 if (!::CloseHandle(_handle))
137 return false;
138 _handle = INVALID_HANDLE_VALUE;
139 return true;
140}
141
142bool CFileBase::GetLength(UInt64 &length) const throw()
143{
144 #ifdef SUPPORT_DEVICE_FILE
145 if (IsDeviceFile && SizeDefined)
146 {
147 length = Size;
148 return true;
149 }
150 #endif
151
152 DWORD high = 0;
153 const DWORD low = ::GetFileSize(_handle, &high);
154 if (low == INVALID_FILE_SIZE)
155 if (::GetLastError() != NO_ERROR)
156 return false;
157 length = (((UInt64)high) << 32) + low;
158 return true;
159
160 /*
161 LARGE_INTEGER fileSize;
162 // GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+
163 if (!GetFileSizeEx(_handle, &fileSize))
164 return false;
165 length = (UInt64)fileSize.QuadPart;
166 return true;
167 */
168}
169
170
171/* Specification for SetFilePointer():
172
173 If a new file pointer is a negative value,
174 {
175 the function fails,
176 the file pointer is not moved,
177 the code returned by GetLastError() is ERROR_NEGATIVE_SEEK.
178 }
179
180 If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set
181 {
182 an application can move the file pointer only to sector-aligned positions.
183 A sector-aligned position is a position that is a whole number multiple of
184 the volume sector size.
185 An application can obtain a volume sector size by calling the GetDiskFreeSpace.
186 }
187
188 It is not an error to set a file pointer to a position beyond the end of the file.
189 The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function.
190
191 If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL,
192 an application must call GetLastError to determine whether or not the function has succeeded or failed.
193*/
194
195bool CFileBase::GetPosition(UInt64 &position) const throw()
196{
197 LONG high = 0;
198 const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT);
199 if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
200 {
201 // for error case we can set (position) to (-1) or (0) or leave (position) unchanged.
202 // position = (UInt64)(Int64)-1; // for debug
203 position = 0;
204 return false;
205 }
206 position = (((UInt64)(UInt32)high) << 32) + low;
207 return true;
208 // we don't want recursed GetPosition()
209 // return Seek(0, FILE_CURRENT, position);
210}
211
212bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw()
213{
214 #ifdef SUPPORT_DEVICE_FILE
215 if (IsDeviceFile && SizeDefined && moveMethod == FILE_END)
216 {
217 distanceToMove += Size;
218 moveMethod = FILE_BEGIN;
219 }
220 #endif
221
222 LONG high = (LONG)(distanceToMove >> 32);
223 const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);
224 if (low == INVALID_SET_FILE_POINTER)
225 {
226 const DWORD lastError = ::GetLastError();
227 if (lastError != NO_ERROR)
228 {
229 // 21.07: we set (newPosition) to real position even after error.
230 GetPosition(newPosition);
231 SetLastError(lastError); // restore LastError
232 return false;
233 }
234 }
235 newPosition = (((UInt64)(UInt32)high) << 32) + low;
236 return true;
237}
238
239bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()
240{
241 return Seek((Int64)position, FILE_BEGIN, newPosition);
242}
243
244bool CFileBase::SeekToBegin() const throw()
245{
246 UInt64 newPosition = 0;
247 return Seek(0, newPosition) && (newPosition == 0);
248}
249
250bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw()
251{
252 return Seek(0, FILE_END, newPosition);
253}
254
255// ---------- CInFile ---------
256
257#ifdef SUPPORT_DEVICE_FILE
258
259void CInFile::CorrectDeviceSize()
260{
261 // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail
262 static const UInt32 kClusterSize = 1 << 14;
263 UInt64 pos = Size & ~(UInt64)(kClusterSize - 1);
264 UInt64 realNewPosition;
265 if (!Seek(pos, realNewPosition))
266 return;
267 Byte *buf = (Byte *)MidAlloc(kClusterSize);
268
269 bool needbackward = true;
270
271 for (;;)
272 {
273 UInt32 processed = 0;
274 // up test is slow for "PhysicalDrive".
275 // processed size for latest block for "PhysicalDrive0" is 0.
276 if (!Read1(buf, kClusterSize, processed))
277 break;
278 if (processed == 0)
279 break;
280 needbackward = false;
281 Size = pos + processed;
282 if (processed != kClusterSize)
283 break;
284 pos += kClusterSize;
285 }
286
287 if (needbackward && pos != 0)
288 {
289 pos -= kClusterSize;
290 for (;;)
291 {
292 // break;
293 if (!Seek(pos, realNewPosition))
294 break;
295 if (!buf)
296 {
297 buf = (Byte *)MidAlloc(kClusterSize);
298 if (!buf)
299 break;
300 }
301 UInt32 processed = 0;
302 // that code doesn't work for "PhysicalDrive0"
303 if (!Read1(buf, kClusterSize, processed))
304 break;
305 if (processed != 0)
306 {
307 Size = pos + processed;
308 break;
309 }
310 if (pos == 0)
311 break;
312 pos -= kClusterSize;
313 }
314 }
315 MidFree(buf);
316}
317
318
319void CInFile::CalcDeviceSize(CFSTR s)
320{
321 SizeDefined = false;
322 Size = 0;
323 if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile)
324 return;
325 #ifdef UNDER_CE
326
327 SizeDefined = true;
328 Size = 128 << 20;
329
330 #else
331
332 PARTITION_INFORMATION partInfo;
333 bool needCorrectSize = true;
334
335 /*
336 WinXP 64-bit:
337
338 HDD \\.\PhysicalDrive0 (MBR):
339 GetPartitionInfo == GeometryEx : corrrect size? (includes tail)
340 Geometry : smaller than GeometryEx (no tail, maybe correct too?)
341 MyGetDiskFreeSpace : FAIL
342 Size correction is slow and block size (kClusterSize) must be small?
343
344 HDD partition \\.\N: (NTFS):
345 MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction
346 GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS
347 Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition)
348
349 CD-ROM drive (ISO):
350 MyGetDiskFreeSpace : correct size. Same size can be calculated after correction
351 Geometry == CdRomGeometry : smaller than corrrect size
352 GetPartitionInfo == GeometryEx : larger than corrrect size
353
354 Floppy \\.\a: (FAT):
355 Geometry : correct size.
356 CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL
357 correction works OK for FAT.
358 correction works OK for non-FAT, if kClusterSize = 512.
359 */
360
361 if (GetPartitionInfo(&partInfo))
362 {
363 Size = (UInt64)partInfo.PartitionLength.QuadPart;
364 SizeDefined = true;
365 needCorrectSize = false;
366 if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0)
367 {
368 FChar path[4] = { s[4], ':', '\\', 0 };
369 UInt64 clusterSize, totalSize, freeSize;
370 if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize))
371 Size = totalSize;
372 else
373 needCorrectSize = true;
374 }
375 }
376
377 if (!SizeDefined)
378 {
379 my_DISK_GEOMETRY_EX geomEx;
380 SizeDefined = GetGeometryEx(&geomEx);
381 if (SizeDefined)
382 Size = (UInt64)geomEx.DiskSize.QuadPart;
383 else
384 {
385 DISK_GEOMETRY geom;
386 SizeDefined = GetGeometry(&geom);
387 if (!SizeDefined)
388 SizeDefined = GetCdRomGeometry(&geom);
389 if (SizeDefined)
390 Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
391 }
392 }
393
394 if (needCorrectSize && SizeDefined && Size != 0)
395 {
396 CorrectDeviceSize();
397 SeekToBegin();
398 }
399
400 // SeekToBegin();
401 #endif
402}
403
404// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&
405
406#define MY_DEVICE_EXTRA_CODE \
407 IsDeviceFile = IsDevicePath(fileName); \
408 CalcDeviceSize(fileName);
409#else
410#define MY_DEVICE_EXTRA_CODE
411#endif
412
413bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
414{
415 DWORD desiredAccess = GENERIC_READ;
416
417 #ifdef _WIN32
418 if (PreserveATime)
419 desiredAccess |= FILE_WRITE_ATTRIBUTES;
420 #endif
421
422 bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes);
423
424 #ifdef _WIN32
425 if (res && PreserveATime)
426 {
427 FILETIME ft;
428 ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF;
429 ::SetFileTime(_handle, NULL, &ft, NULL);
430 }
431 #endif
432
433 MY_DEVICE_EXTRA_CODE
434 return res;
435}
436
437bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite)
438{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
439
440bool CInFile::Open(CFSTR fileName)
441 { return OpenShared(fileName, false); }
442
443// ReadFile and WriteFile functions in Windows have BUG:
444// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
445// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
446// (Insufficient system resources exist to complete the requested service).
447
448// Probably in some version of Windows there are problems with other sizes:
449// for 32 MB (maybe also for 16 MB).
450// And message can be "Network connection was lost"
451
452static const UInt32 kChunkSizeMax = (1 << 22);
453
454bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()
455{
456 DWORD processedLoc = 0;
457 bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));
458 processedSize = (UInt32)processedLoc;
459 return res;
460}
461
462bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw()
463{
464 if (size > kChunkSizeMax)
465 size = kChunkSizeMax;
466 return Read1(data, size, processedSize);
467}
468
469bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()
470{
471 processedSize = 0;
472 do
473 {
474 UInt32 processedLoc = 0;
475 bool res = ReadPart(data, size, processedLoc);
476 processedSize += processedLoc;
477 if (!res)
478 return false;
479 if (processedLoc == 0)
480 return true;
481 data = (void *)((unsigned char *)data + processedLoc);
482 size -= processedLoc;
483 }
484 while (size > 0);
485 return true;
486}
487
488bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw()
489{
490 processedSize = 0;
491 do
492 {
493 UInt32 processedLoc = 0;
494 const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size);
495 const bool res = Read1(data, sizeLoc, processedLoc);
496 processedSize += processedLoc;
497 if (!res)
498 return false;
499 if (processedLoc == 0)
500 return true;
501 data = (void *)((unsigned char *)data + processedLoc);
502 size -= processedLoc;
503 }
504 while (size > 0);
505 return true;
506}
507
508// ---------- COutFile ---------
509
510static inline DWORD GetCreationDisposition(bool createAlways)
511 { return createAlways? CREATE_ALWAYS: CREATE_NEW; }
512
513bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
514 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
515
516bool COutFile::Open(CFSTR fileName, DWORD creationDisposition)
517 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
518
519bool COutFile::Create(CFSTR fileName, bool createAlways)
520 { return Open(fileName, GetCreationDisposition(createAlways)); }
521
522bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes)
523 { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); }
524
525bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
526 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }
527
528bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); }
529
530bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw()
531{
532 if (size > kChunkSizeMax)
533 size = kChunkSizeMax;
534 DWORD processedLoc = 0;
535 bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));
536 processedSize = (UInt32)processedLoc;
537 return res;
538}
539
540bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
541{
542 processedSize = 0;
543 do
544 {
545 UInt32 processedLoc = 0;
546 bool res = WritePart(data, size, processedLoc);
547 processedSize += processedLoc;
548 if (!res)
549 return false;
550 if (processedLoc == 0)
551 return true;
552 data = (const void *)((const unsigned char *)data + processedLoc);
553 size -= processedLoc;
554 }
555 while (size != 0);
556 return true;
557}
558
559bool COutFile::WriteFull(const void *data, size_t size) throw()
560{
561 do
562 {
563 UInt32 processedLoc = 0;
564 const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size);
565 if (!WritePart(data, sizeCur, processedLoc))
566 return false;
567 if (processedLoc == 0)
568 return (size == 0);
569 data = (const void *)((const unsigned char *)data + processedLoc);
570 size -= processedLoc;
571 }
572 while (size != 0);
573 return true;
574}
575
576bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); }
577
578bool COutFile::SetLength(UInt64 length) throw()
579{
580 UInt64 newPosition;
581 if (!Seek(length, newPosition))
582 return false;
583 if (newPosition != length)
584 return false;
585 return SetEndOfFile();
586}
587
588bool COutFile::SetLength_KeepPosition(UInt64 length) throw()
589{
590 UInt64 currentPos = 0;
591 if (!GetPosition(currentPos))
592 return false;
593 DWORD lastError = 0;
594 const bool result = SetLength(length);
595 if (!result)
596 lastError = GetLastError();
597 UInt64 currentPos2;
598 const bool result2 = Seek(currentPos, currentPos2);
599 if (lastError != 0)
600 SetLastError(lastError);
601 return (result && result2);
602}
603
604}}}
605
606#else // _WIN32
607
608
609// POSIX
610
611#include <fcntl.h>
612#include <unistd.h>
613
614namespace NWindows {
615namespace NFile {
616
617namespace NDir {
618bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
619}
620
621namespace NIO {
622
623bool CFileBase::OpenBinary(const char *name, int flags)
624{
625 #ifdef O_BINARY
626 flags |= O_BINARY;
627 #endif
628
629 Close();
630 _handle = ::open(name, flags, 0666);
631 return _handle != -1;
632}
633
634bool CFileBase::Close()
635{
636 if (_handle == -1)
637 return true;
638 if (close(_handle) != 0)
639 return false;
640 _handle = -1;
641 return true;
642}
643
644bool CFileBase::GetLength(UInt64 &length) const
645{
646 length = 0;
647 // length = (UInt64)(Int64)-1; // for debug
648 const off_t curPos = seekToCur();
649 if (curPos == -1)
650 return false;
651 const off_t lengthTemp = seek(0, SEEK_END);
652 seek(curPos, SEEK_SET);
653 length = (UInt64)lengthTemp;
654 return (lengthTemp != -1);
655}
656
657off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const
658{
659 // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove);
660 // off_t res = ::lseek(_handle, distanceToMove, moveMethod);
661 return ::lseek(_handle, distanceToMove, moveMethod);
662 // printf(" res = %lld", (long long)res);
663 // return res;
664}
665
666off_t CFileBase::seekToBegin() const throw()
667{
668 return seek(0, SEEK_SET);
669}
670
671off_t CFileBase::seekToCur() const throw()
672{
673 return seek(0, SEEK_CUR);
674}
675
676/*
677bool CFileBase::SeekToBegin() const throw()
678{
679 return (::seek(0, SEEK_SET) != -1);
680}
681*/
682
683
684/////////////////////////
685// CInFile
686
687bool CInFile::Open(const char *name)
688{
689 return CFileBase::OpenBinary(name, O_RDONLY);
690}
691
692bool CInFile::OpenShared(const char *name, bool)
693{
694 return Open(name);
695}
696
697/*
698On Linux (32-bit and 64-bit):
699read(), write() (and similar system calls) will transfer at most
7000x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred.
701*/
702
703static const size_t kChunkSizeMax = ((size_t)1 << 22);
704
705ssize_t CInFile::read_part(void *data, size_t size) throw()
706{
707 if (size > kChunkSizeMax)
708 size = kChunkSizeMax;
709 return ::read(_handle, data, size);
710}
711
712bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()
713{
714 processed = 0;
715 do
716 {
717 const ssize_t res = read_part(data, size);
718 if (res < 0)
719 return false;
720 if (res == 0)
721 break;
722 data = (void *)((unsigned char *)data + (size_t)res);
723 size -= (size_t)res;
724 processed += (size_t)res;
725 }
726 while (size > 0);
727 return true;
728}
729
730
731/////////////////////////
732// COutFile
733
734bool COutFile::Create(const char *name, bool createAlways)
735{
736 Path = name; // change it : set it only if open is success.
737 if (createAlways)
738 {
739 Close();
740 _handle = ::creat(name, 0666);
741 return _handle != -1;
742 }
743 return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);
744}
745
746bool COutFile::Open(const char *name, DWORD creationDisposition)
747{
748 UNUSED_VAR(creationDisposition) // FIXME
749 return Create(name, false);
750}
751
752ssize_t COutFile::write_part(const void *data, size_t size) throw()
753{
754 if (size > kChunkSizeMax)
755 size = kChunkSizeMax;
756 return ::write(_handle, data, size);
757}
758
759ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw()
760{
761 processed = 0;
762 do
763 {
764 const ssize_t res = write_part(data, size);
765 if (res < 0)
766 return res;
767 if (res == 0)
768 break;
769 data = (const void *)((const unsigned char *)data + (size_t)res);
770 size -= (size_t)res;
771 processed += (size_t)res;
772 }
773 while (size > 0);
774 return (ssize_t)processed;
775}
776
777bool COutFile::SetLength(UInt64 length) throw()
778{
779 const off_t len2 = (off_t)length;
780 if ((Int64)length != len2)
781 {
782 SetLastError(EFBIG);
783 return false;
784 }
785 // The value of the seek pointer shall not be modified by a call to ftruncate().
786 int iret = ftruncate(_handle, len2);
787 return (iret == 0);
788}
789
790bool COutFile::Close()
791{
792 bool res = CFileBase::Close();
793 if (!res)
794 return res;
795 if (CTime_defined || ATime_defined || MTime_defined)
796 {
797 /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path,
798 CTime_defined ? &CTime : NULL,
799 ATime_defined ? &ATime : NULL,
800 MTime_defined ? &MTime : NULL);
801 }
802 return res;
803}
804
805bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
806{
807 // On some OS (cygwin, MacOSX ...), you must close the file before updating times
808 // return true;
809
810 if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false;
811 if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false;
812 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
813 return true;
814}
815
816bool COutFile::SetMTime(const FILETIME *mTime) throw()
817{
818 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
819 return true;
820}
821
822}}}
823
824
825#endif
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
new file mode 100644
index 0000000..22998eb
--- /dev/null
+++ b/CPP/Windows/FileIO.h
@@ -0,0 +1,347 @@
1// Windows/FileIO.h
2
3#ifndef __WINDOWS_FILE_IO_H
4#define __WINDOWS_FILE_IO_H
5
6#include "../Common/MyWindows.h"
7
8#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
9#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL)
10#define _my_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL)
11
12#define _my_SYMLINK_FLAG_RELATIVE 1
13
14// what the meaning of that FLAG or field (2)?
15#define _my_LX_SYMLINK_FLAG 2
16
17#ifdef _WIN32
18
19#if defined(_WIN32) && !defined(UNDER_CE)
20#include <WinIoCtl.h>
21#endif
22
23#else
24
25#include <sys/types.h>
26#include <sys/stat.h>
27
28#endif
29
30#include "../Common/MyString.h"
31#include "../Common/MyBuffer.h"
32
33#include "Defs.h"
34
35HRESULT GetLastError_noZero_HRESULT();
36
37#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
38#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER
39#define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
40
41namespace NWindows {
42namespace NFile {
43
44#if defined(_WIN32) && !defined(UNDER_CE)
45bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL);
46#endif
47
48struct CReparseShortInfo
49{
50 unsigned Offset;
51 unsigned Size;
52
53 bool Parse(const Byte *p, size_t size);
54};
55
56struct CReparseAttr
57{
58 UInt32 Tag;
59 UInt32 Flags;
60 UString SubsName;
61 UString PrintName;
62
63 AString WslName;
64
65 bool HeaderError;
66 bool TagIsUnknown;
67 bool MinorError;
68 DWORD ErrorCode;
69
70 CReparseAttr(): Tag(0), Flags(0) {}
71
72 // Parse()
73 // returns (true) and (ErrorCode = 0), if (it'a correct known link)
74 // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag
75 bool Parse(const Byte *p, size_t size);
76
77 bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
78 bool IsSymLink_Win() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
79 bool IsSymLink_WSL() const { return Tag == _my_IO_REPARSE_TAG_LX_SYMLINK; }
80
81 bool IsRelative_Win() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }
82
83 bool IsRelative_WSL() const
84 {
85 if (WslName.IsEmpty())
86 return true;
87 char c = WslName[0];
88 return !IS_PATH_SEPAR(c);
89 }
90
91 // bool IsVolume() const;
92
93 bool IsOkNamePair() const;
94 UString GetPath() const;
95};
96
97
98#ifdef _WIN32
99
100namespace NIO {
101
102bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);
103bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
104bool DeleteReparseData(CFSTR path);
105
106class CFileBase MY_UNCOPYABLE
107{
108protected:
109 HANDLE _handle;
110
111 bool Create(CFSTR path, DWORD desiredAccess,
112 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
113
114public:
115
116 bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,
117 LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const
118 {
119 return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,
120 outBuffer, outSize, bytesReturned, overlapped));
121 }
122
123 bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const
124 {
125 return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned);
126 }
127
128 bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const
129 {
130 DWORD bytesReturned;
131 return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned);
132 }
133
134public:
135 bool PreserveATime;
136 #ifdef SUPPORT_DEVICE_FILE
137 bool IsDeviceFile;
138 bool SizeDefined;
139 UInt64 Size; // it can be larger than real available size
140 #endif
141
142 CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {};
143 ~CFileBase() { Close(); }
144
145 bool Close() throw();
146
147 bool GetPosition(UInt64 &position) const throw();
148 bool GetLength(UInt64 &length) const throw();
149
150 bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw();
151 bool Seek(UInt64 position, UInt64 &newPosition) const throw();
152 bool SeekToBegin() const throw();
153 bool SeekToEnd(UInt64 &newPosition) const throw();
154
155 bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const
156 { return BOOLToBool(GetFileInformationByHandle(_handle, info)); }
157
158 static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info)
159 {
160 // probably it can work for complex paths: unsupported by another things
161 NIO::CFileBase file;
162 if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS))
163 return false;
164 return file.GetFileInformation(info);
165 }
166};
167
168#ifndef UNDER_CE
169#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
170#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
171// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
172
173// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP
174#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)
175
176struct my_DISK_GEOMETRY_EX
177{
178 DISK_GEOMETRY Geometry;
179 LARGE_INTEGER DiskSize;
180 BYTE Data[1];
181};
182#endif
183
184class CInFile: public CFileBase
185{
186 #ifdef SUPPORT_DEVICE_FILE
187
188 #ifndef UNDER_CE
189
190 bool GetGeometry(DISK_GEOMETRY *res) const
191 { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
192
193 bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const
194 { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); }
195
196 bool GetCdRomGeometry(DISK_GEOMETRY *res) const
197 { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
198
199 bool GetPartitionInfo(PARTITION_INFORMATION *res)
200 { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }
201
202 #endif
203
204 void CorrectDeviceSize();
205 void CalcDeviceSize(CFSTR name);
206
207 #endif
208
209public:
210 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
211 bool OpenShared(CFSTR fileName, bool shareForWrite);
212 bool Open(CFSTR fileName);
213
214 #ifndef UNDER_CE
215
216 bool OpenReparse(CFSTR fileName)
217 {
218 // 17.02 fix: to support Windows XP compatibility junctions:
219 // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ
220 return
221 Create(fileName, 0,
222 // Open(fileName,
223 FILE_SHARE_READ, OPEN_EXISTING,
224 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);
225 }
226
227 #endif
228
229 bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw();
230 bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw();
231 bool Read(void *data, UInt32 size, UInt32 &processedSize) throw();
232 bool ReadFull(void *data, size_t size, size_t &processedSize) throw();
233};
234
235class COutFile: public CFileBase
236{
237public:
238 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
239 bool Open(CFSTR fileName, DWORD creationDisposition);
240 bool Create(CFSTR fileName, bool createAlways);
241 bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes);
242
243 bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
244 bool SetMTime(const FILETIME *mTime) throw();
245 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();
246 bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();
247 bool WriteFull(const void *data, size_t size) throw();
248 bool SetEndOfFile() throw();
249 bool SetLength(UInt64 length) throw();
250 bool SetLength_KeepPosition(UInt64 length) throw();
251};
252
253}
254
255
256#else // _WIN32
257
258namespace NIO {
259
260bool GetReparseData(CFSTR path, CByteBuffer &reparseData);
261// bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
262
263// parameters are in reverse order of symlink() function !!!
264bool SetSymLink(CFSTR from, CFSTR to);
265bool SetSymLink_UString(CFSTR from, const UString &to);
266
267
268class CFileBase
269{
270protected:
271 int _handle;
272
273 bool OpenBinary(const char *name, int flags);
274public:
275 bool PreserveATime;
276
277 CFileBase(): _handle(-1), PreserveATime(false) {};
278 ~CFileBase() { Close(); }
279 bool Close();
280 bool GetLength(UInt64 &length) const;
281 off_t seek(off_t distanceToMove, int moveMethod) const;
282 off_t seekToBegin() const throw();
283 off_t seekToCur() const throw();
284 // bool SeekToBegin() throw();
285 int my_fstat(struct stat *st) const { return fstat(_handle, st); }
286};
287
288class CInFile: public CFileBase
289{
290public:
291 bool Open(const char *name);
292 bool OpenShared(const char *name, bool shareForWrite);
293 ssize_t read_part(void *data, size_t size) throw();
294 // ssize_t read_full(void *data, size_t size, size_t &processed);
295 bool ReadFull(void *data, size_t size, size_t &processedSize) throw();
296};
297
298class COutFile: public CFileBase
299{
300 bool CTime_defined;
301 bool ATime_defined;
302 bool MTime_defined;
303
304 FILETIME CTime;
305 FILETIME ATime;
306 FILETIME MTime;
307
308 AString Path;
309 ssize_t write_part(const void *data, size_t size) throw();
310public:
311 COutFile():
312 CTime_defined(false),
313 ATime_defined(false),
314 MTime_defined(false)
315 {}
316
317 bool Close();
318 bool Create(const char *name, bool createAlways);
319 bool Open(const char *name, DWORD creationDisposition);
320 ssize_t write_full(const void *data, size_t size, size_t &processed) throw();
321
322 bool WriteFull(const void *data, size_t size) throw()
323 {
324 size_t processed;
325 ssize_t res = write_full(data, size, processed);
326 if (res == -1)
327 return false;
328 return processed == size;
329 }
330
331 bool SetLength(UInt64 length) throw();
332 bool SetLength_KeepPosition(UInt64 length) throw()
333 {
334 return SetLength(length);
335 }
336 bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
337 bool SetMTime(const FILETIME *mTime) throw();
338};
339
340}
341
342#endif // _WIN32
343
344}}
345
346
347#endif
diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp
new file mode 100644
index 0000000..8ce634f
--- /dev/null
+++ b/CPP/Windows/FileLink.cpp
@@ -0,0 +1,613 @@
1// Windows/FileLink.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#ifndef _WIN32
8#include <unistd.h>
9#endif
10
11#ifdef SUPPORT_DEVICE_FILE
12#include "../../C/Alloc.h"
13#endif
14
15#include "../Common/UTFConvert.h"
16#include "../Common/StringConvert.h"
17
18#include "FileDir.h"
19#include "FileFind.h"
20#include "FileIO.h"
21#include "FileName.h"
22
23#ifndef _UNICODE
24extern bool g_IsNT;
25#endif
26
27namespace NWindows {
28namespace NFile {
29
30using namespace NName;
31
32/*
33 Reparse Points (Junctions and Symbolic Links):
34 struct
35 {
36 UInt32 Tag;
37 UInt16 Size; // not including starting 8 bytes
38 UInt16 Reserved; // = 0
39
40 UInt16 SubstituteOffset; // offset in bytes from start of namesChars
41 UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL
42 UInt16 PrintOffset; // offset in bytes from start of namesChars
43 UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL
44
45 [UInt32] Flags; // for Symbolic Links only.
46
47 UInt16 namesChars[]
48 }
49
50 MOUNT_POINT (Junction point):
51 1) there is NUL wchar after path
52 2) Default Order in table:
53 Substitute Path
54 Print Path
55 3) pathnames can not contain dot directory names
56
57 SYMLINK:
58 1) there is no NUL wchar after path
59 2) Default Order in table:
60 Print Path
61 Substitute Path
62*/
63
64/*
65Win10 WSL2:
66admin rights + sudo: it creates normal windows symbolic link.
67in another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point.
68*/
69
70/*
71static const UInt32 kReparseFlags_Alias = (1 << 29);
72static const UInt32 kReparseFlags_HighLatency = (1 << 30);
73static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31);
74
75#define _my_IO_REPARSE_TAG_HSM (0xC0000004L)
76#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L)
77#define _my_IO_REPARSE_TAG_SIS (0x80000007L)
78#define _my_IO_REPARSE_TAG_WIM (0x80000008L)
79#define _my_IO_REPARSE_TAG_CSV (0x80000009L)
80#define _my_IO_REPARSE_TAG_DFS (0x8000000AL)
81#define _my_IO_REPARSE_TAG_DFSR (0x80000012L)
82*/
83
84#define Get16(p) GetUi16(p)
85#define Get32(p) GetUi32(p)
86
87static const wchar_t * const k_LinkPrefix = L"\\??\\";
88static const unsigned k_LinkPrefix_Size = 4;
89
90static bool IsLinkPrefix(const wchar_t *s)
91{
92 return IsString1PrefixedByString2(s, k_LinkPrefix);
93}
94
95/*
96static const wchar_t * const k_VolumePrefix = L"Volume{";
97static const bool IsVolumeName(const wchar_t *s)
98{
99 return IsString1PrefixedByString2(s, k_VolumePrefix);
100}
101*/
102
103#if defined(_WIN32) && !defined(UNDER_CE)
104
105#define Set16(p, v) SetUi16(p, v)
106#define Set32(p, v) SetUi32(p, v)
107
108static void WriteString(Byte *dest, const wchar_t *path)
109{
110 for (;;)
111 {
112 wchar_t c = *path++;
113 if (c == 0)
114 return;
115 Set16(dest, (UInt16)c);
116 dest += 2;
117 }
118}
119
120bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL)
121{
122 bool isAbs = IsAbsolutePath(path);
123 if (!isAbs && !isSymLink)
124 return false;
125
126 if (isWSL)
127 {
128 // unsupported characters probably use Replacement Character UTF-16 0xFFFD
129 AString utf;
130 ConvertUnicodeToUTF8(path, utf);
131 const size_t size = 4 + utf.Len();
132 if (size != (UInt16)size)
133 return false;
134 dest.Alloc(8 + size);
135 Byte *p = dest;
136 Set32(p, _my_IO_REPARSE_TAG_LX_SYMLINK);
137 Set16(p + 4, (UInt16)(size));
138 Set16(p + 6, 0);
139 Set32(p + 8, _my_LX_SYMLINK_FLAG);
140 memcpy(p + 12, utf.Ptr(), utf.Len());
141 return true;
142 }
143
144 // usual symbolic LINK (NOT WSL)
145
146 bool needPrintName = true;
147
148 if (IsSuperPath(path))
149 {
150 path += kSuperPathPrefixSize;
151 if (!IsDrivePath(path))
152 needPrintName = false;
153 }
154
155 const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0;
156
157 size_t len2 = (size_t)MyStringLen(path) * 2;
158 const size_t len1 = len2 + add_Prefix_Len * 2;
159 if (!needPrintName)
160 len2 = 0;
161
162 size_t totalNamesSize = (len1 + len2);
163
164 /* some WIM imagex software uses old scheme for symbolic links.
165 so we can old scheme for byte to byte compatibility */
166
167 bool newOrderScheme = isSymLink;
168 // newOrderScheme = false;
169
170 if (!newOrderScheme)
171 totalNamesSize += 2 * 2;
172
173 const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize;
174 if (size != (UInt16)size)
175 return false;
176 dest.Alloc(size);
177 memset(dest, 0, size);
178 const UInt32 tag = isSymLink ?
179 _my_IO_REPARSE_TAG_SYMLINK :
180 _my_IO_REPARSE_TAG_MOUNT_POINT;
181 Byte *p = dest;
182 Set32(p, tag);
183 Set16(p + 4, (UInt16)(size - 8));
184 Set16(p + 6, 0);
185 p += 8;
186
187 unsigned subOffs = 0;
188 unsigned printOffs = 0;
189 if (newOrderScheme)
190 subOffs = (unsigned)len2;
191 else
192 printOffs = (unsigned)len1 + 2;
193
194 Set16(p + 0, (UInt16)subOffs);
195 Set16(p + 2, (UInt16)len1);
196 Set16(p + 4, (UInt16)printOffs);
197 Set16(p + 6, (UInt16)len2);
198
199 p += 8;
200 if (isSymLink)
201 {
202 UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE;
203 Set32(p, flags);
204 p += 4;
205 }
206
207 if (add_Prefix_Len != 0)
208 WriteString(p + subOffs, k_LinkPrefix);
209 WriteString(p + subOffs + add_Prefix_Len * 2, path);
210 if (needPrintName)
211 WriteString(p + printOffs, path);
212 return true;
213}
214
215#endif // defined(_WIN32) && !defined(UNDER_CE)
216
217
218static void GetString(const Byte *p, unsigned len, UString &res)
219{
220 wchar_t *s = res.GetBuf(len);
221 unsigned i;
222 for (i = 0; i < len; i++)
223 {
224 wchar_t c = Get16(p + i * 2);
225 if (c == 0)
226 break;
227 s[i] = c;
228 }
229 s[i] = 0;
230 res.ReleaseBuf_SetLen(i);
231}
232
233bool CReparseAttr::Parse(const Byte *p, size_t size)
234{
235 ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA;
236 HeaderError = true;
237 TagIsUnknown = true;
238 MinorError = false;
239
240 if (size < 8)
241 return false;
242 Tag = Get32(p);
243 UInt32 len = Get16(p + 4);
244 if (len + 8 != size)
245 // if (len + 8 > size)
246 return false;
247 /*
248 if ((type & kReparseFlags_Alias) == 0 ||
249 (type & kReparseFlags_Microsoft) == 0 ||
250 (type & 0xFFFF) != 3)
251 */
252
253 if (Get16(p + 6) != 0) // padding
254 return false;
255
256 HeaderError = false;
257
258 if ( Tag != _my_IO_REPARSE_TAG_MOUNT_POINT
259 && Tag != _my_IO_REPARSE_TAG_SYMLINK
260 && Tag != _my_IO_REPARSE_TAG_LX_SYMLINK)
261 {
262 // for unsupported reparse points
263 ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH
264 // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
265 return false;
266 }
267
268 TagIsUnknown = false;
269
270 p += 8;
271 size -= 8;
272
273 if (Tag == _my_IO_REPARSE_TAG_LX_SYMLINK)
274 {
275 if (len < 4)
276 return false;
277 Flags = Get32(p); // maybe it's not Flags
278 if (Flags != _my_LX_SYMLINK_FLAG)
279 return false;
280 len -= 4;
281 p += 4;
282 char *s = WslName.GetBuf(len);
283 unsigned i;
284 for (i = 0; i < len; i++)
285 {
286 char c = (char)p[i];
287 s[i] = c;
288 if (c == 0)
289 break;
290 }
291 WslName.ReleaseBuf_SetEnd(i);
292 MinorError = (i != len);
293 ErrorCode = 0;
294 return true;
295 }
296
297 if (len < 8)
298 return false;
299 unsigned subOffs = Get16(p);
300 unsigned subLen = Get16(p + 2);
301 unsigned printOffs = Get16(p + 4);
302 unsigned printLen = Get16(p + 6);
303 len -= 8;
304 p += 8;
305
306 Flags = 0;
307 if (Tag == _my_IO_REPARSE_TAG_SYMLINK)
308 {
309 if (len < 4)
310 return false;
311 Flags = Get32(p);
312 len -= 4;
313 p += 4;
314 }
315
316 if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)
317 return false;
318 if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)
319 return false;
320 GetString(p + subOffs, subLen >> 1, SubsName);
321 GetString(p + printOffs, printLen >> 1, PrintName);
322
323 ErrorCode = 0;
324 return true;
325}
326
327
328bool CReparseShortInfo::Parse(const Byte *p, size_t size)
329{
330 const Byte *start = p;
331 Offset= 0;
332 Size = 0;
333 if (size < 8)
334 return false;
335 UInt32 Tag = Get32(p);
336 UInt32 len = Get16(p + 4);
337 if (len + 8 > size)
338 return false;
339 /*
340 if ((type & kReparseFlags_Alias) == 0 ||
341 (type & kReparseFlags_Microsoft) == 0 ||
342 (type & 0xFFFF) != 3)
343 */
344 if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&
345 Tag != _my_IO_REPARSE_TAG_SYMLINK)
346 // return true;
347 return false;
348
349 if (Get16(p + 6) != 0) // padding
350 return false;
351
352 p += 8;
353 size -= 8;
354
355 if (len != size) // do we need that check?
356 return false;
357
358 if (len < 8)
359 return false;
360 unsigned subOffs = Get16(p);
361 unsigned subLen = Get16(p + 2);
362 unsigned printOffs = Get16(p + 4);
363 unsigned printLen = Get16(p + 6);
364 len -= 8;
365 p += 8;
366
367 // UInt32 Flags = 0;
368 if (Tag == _my_IO_REPARSE_TAG_SYMLINK)
369 {
370 if (len < 4)
371 return false;
372 // Flags = Get32(p);
373 len -= 4;
374 p += 4;
375 }
376
377 if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)
378 return false;
379 if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)
380 return false;
381
382 Offset = (unsigned)(p - start) + subOffs;
383 Size = subLen;
384 return true;
385}
386
387bool CReparseAttr::IsOkNamePair() const
388{
389 if (IsLinkPrefix(SubsName))
390 {
391 if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size)))
392 return PrintName.IsEmpty();
393 if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0)
394 return true;
395 }
396 return wcscmp(SubsName, PrintName) == 0;
397}
398
399/*
400bool CReparseAttr::IsVolume() const
401{
402 if (!IsLinkPrefix(SubsName))
403 return false;
404 return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size));
405}
406*/
407
408UString CReparseAttr::GetPath() const
409{
410 if (IsSymLink_WSL())
411 {
412 UString u;
413 // if (CheckUTF8(attr.WslName)
414 if (!ConvertUTF8ToUnicode(WslName, u))
415 MultiByteToUnicodeString2(u, WslName);
416 return u;
417 }
418
419 UString s (SubsName);
420 if (IsLinkPrefix(s))
421 {
422 s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\"
423 if (IsDrivePath(s.Ptr(k_LinkPrefix_Size)))
424 s.DeleteFrontal(k_LinkPrefix_Size);
425 }
426 return s;
427}
428
429#ifdef SUPPORT_DEVICE_FILE
430
431namespace NSystem
432{
433bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
434}
435#endif // SUPPORT_DEVICE_FILE
436
437#if defined(_WIN32) && !defined(UNDER_CE)
438
439namespace NIO {
440
441bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo)
442{
443 reparseData.Free();
444 CInFile file;
445 if (!file.OpenReparse(path))
446 return false;
447
448 if (fileInfo)
449 file.GetFileInformation(fileInfo);
450
451 const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
452 CByteArr buf(kBufSize);
453 DWORD returnedSize;
454 if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))
455 return false;
456 reparseData.CopyFrom(buf, returnedSize);
457 return true;
458}
459
460static bool CreatePrefixDirOfFile(CFSTR path)
461{
462 FString path2 (path);
463 int pos = path2.ReverseFind_PathSepar();
464 if (pos < 0)
465 return true;
466 #ifdef _WIN32
467 if (pos == 2 && path2[1] == L':')
468 return true; // we don't create Disk folder;
469 #endif
470 path2.DeleteFrom((unsigned)pos);
471 return NDir::CreateComplexDir(path2);
472}
473
474
475static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size)
476{
477 COutFile file;
478 if (!file.Open(path,
479 FILE_SHARE_WRITE,
480 OPEN_EXISTING,
481 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))
482 return false;
483
484 DWORD returnedSize;
485 return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize);
486}
487
488
489// If there is Reparse data already, it still writes new Reparse data
490bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
491{
492 NFile::NFind::CFileInfo fi;
493 if (fi.Find(path))
494 {
495 if (fi.IsDir() != isDir)
496 {
497 ::SetLastError(ERROR_DIRECTORY);
498 return false;
499 }
500 }
501 else
502 {
503 if (isDir)
504 {
505 if (!NDir::CreateComplexDir(path))
506 return false;
507 }
508 else
509 {
510 CreatePrefixDirOfFile(path);
511 COutFile file;
512 if (!file.Create(path, CREATE_NEW))
513 return false;
514 }
515 }
516
517 return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size);
518}
519
520
521bool DeleteReparseData(CFSTR path)
522{
523 CByteBuffer reparseData;
524 if (!GetReparseData(path, reparseData, NULL))
525 return false;
526 /* MSDN: The tag specified in the ReparseTag member of this structure
527 must match the tag of the reparse point to be deleted,
528 and the ReparseDataLength member must be zero */
529 #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8
530 if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE)
531 {
532 SetLastError(ERROR_INVALID_REPARSE_DATA);
533 return false;
534 }
535 BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE];
536 memset(buf, 0, sizeof(buf));
537 memcpy(buf, reparseData, 4); // tag
538 return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf));
539}
540
541}
542
543#endif // defined(_WIN32) && !defined(UNDER_CE)
544
545
546#ifndef _WIN32
547
548namespace NIO {
549
550bool GetReparseData(CFSTR path, CByteBuffer &reparseData)
551{
552 reparseData.Free();
553
554 #define MAX_PATHNAME_LEN 1024
555 char buf[MAX_PATHNAME_LEN + 2];
556 const size_t request = sizeof(buf) - 1;
557
558 // printf("\nreadlink() path = %s \n", path);
559 const ssize_t size = readlink(path, buf, request);
560 // there is no tail zero
561
562 if (size < 0)
563 return false;
564 if ((size_t)size >= request)
565 {
566 SetLastError(EINVAL); // check it: ENAMETOOLONG
567 return false;
568 }
569
570 // printf("\nreadlink() res = %s size = %d \n", buf, (int)size);
571 reparseData.CopyFrom((const Byte *)buf, (size_t)size);
572 return true;
573}
574
575
576/*
577// If there is Reparse data already, it still writes new Reparse data
578bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
579{
580 // AString s;
581 // s.SetFrom_CalcLen(data, size);
582 // return (symlink(s, path) == 0);
583 UNUSED_VAR(path)
584 UNUSED_VAR(isDir)
585 UNUSED_VAR(data)
586 UNUSED_VAR(size)
587 SetLastError(ENOSYS);
588 return false;
589}
590*/
591
592bool SetSymLink(CFSTR from, CFSTR to)
593{
594 // printf("\nsymlink() %s -> %s\n", from, to);
595 int ir;
596 // ir = unlink(path);
597 // if (ir == 0)
598 ir = symlink(to, from);
599 return (ir == 0);
600}
601
602bool SetSymLink_UString(CFSTR from, const UString &to)
603{
604 AString utf;
605 ConvertUnicodeToUTF8(to, utf);
606 return SetSymLink(from, utf);
607}
608
609}
610
611#endif // !_WIN32
612
613}}
diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp
new file mode 100644
index 0000000..1933f7c
--- /dev/null
+++ b/CPP/Windows/FileMapping.cpp
@@ -0,0 +1,12 @@
1// Windows/FileMapping.cpp
2
3#include "StdAfx.h"
4
5#include "FileMapping.h"
6
7namespace NWindows {
8namespace NFile {
9namespace NMapping {
10
11
12}}}
diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h
new file mode 100644
index 0000000..f90c429
--- /dev/null
+++ b/CPP/Windows/FileMapping.h
@@ -0,0 +1,66 @@
1// Windows/FileMapping.h
2
3#ifndef __WINDOWS_FILEMAPPING_H
4#define __WINDOWS_FILEMAPPING_H
5
6#include "../Common/MyTypes.h"
7
8#include "Handle.h"
9
10namespace NWindows {
11
12class CFileMapping: public CHandle
13{
14public:
15 WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name)
16 {
17 _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name);
18 return ::GetLastError();
19 }
20
21 WRes Open(DWORD
22 #ifndef UNDER_CE
23 desiredAccess
24 #endif
25 , LPCTSTR name)
26 {
27 #ifdef UNDER_CE
28 WRes res = Create(PAGE_READONLY, 0, name);
29 if (res == ERROR_ALREADY_EXISTS)
30 return 0;
31 Close();
32 if (res == 0)
33 res = ERROR_FILE_NOT_FOUND;
34 return res;
35 #else
36 _handle = ::OpenFileMapping(desiredAccess, FALSE, name);
37 if (_handle != 0)
38 return 0;
39 return ::GetLastError();
40 #endif
41 }
42
43 LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap)
44 {
45 return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap);
46 }
47
48 #ifndef UNDER_CE
49 LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress)
50 {
51 return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress);
52 }
53 #endif
54};
55
56class CFileUnmapper
57{
58 const void *_data;
59public:
60 CFileUnmapper(const void *data) : _data(data) {}
61 ~CFileUnmapper() { ::UnmapViewOfFile(_data); }
62};
63
64}
65
66#endif
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
new file mode 100644
index 0000000..d61ff7e
--- /dev/null
+++ b/CPP/Windows/FileName.cpp
@@ -0,0 +1,893 @@
1// Windows/FileName.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6#include <limits.h>
7#include <unistd.h>
8#include "../Common/StringConvert.h"
9#include "FileDir.h"
10#endif
11
12#include "FileName.h"
13
14#ifndef _UNICODE
15extern bool g_IsNT;
16#endif
17
18namespace NWindows {
19namespace NFile {
20namespace NName {
21
22#define IS_SEPAR(c) IS_PATH_SEPAR(c)
23
24int FindSepar(const wchar_t *s) throw()
25{
26 for (const wchar_t *p = s;; p++)
27 {
28 const wchar_t c = *p;
29 if (c == 0)
30 return -1;
31 if (IS_SEPAR(c))
32 return (int)(p - s);
33 }
34}
35
36#ifndef USE_UNICODE_FSTRING
37int FindSepar(const FChar *s) throw()
38{
39 for (const FChar *p = s;; p++)
40 {
41 const FChar c = *p;
42 if (c == 0)
43 return -1;
44 if (IS_SEPAR(c))
45 return (int)(p - s);
46 }
47}
48#endif
49
50#ifndef USE_UNICODE_FSTRING
51void NormalizeDirPathPrefix(FString &dirPath)
52{
53 if (dirPath.IsEmpty())
54 return;
55 if (!IsPathSepar(dirPath.Back()))
56 dirPath.Add_PathSepar();
57}
58#endif
59
60void NormalizeDirPathPrefix(UString &dirPath)
61{
62 if (dirPath.IsEmpty())
63 return;
64 if (!IsPathSepar(dirPath.Back()))
65 dirPath.Add_PathSepar();
66}
67
68#ifdef _WIN32
69
70#ifndef USE_UNICODE_FSTRING
71#ifdef WIN_LONG_PATH
72static void NormalizeDirSeparators(UString &s)
73{
74 const unsigned len = s.Len();
75 for (unsigned i = 0; i < len; i++)
76 if (s[i] == '/')
77 s.ReplaceOneCharAtPos(i, WCHAR_PATH_SEPARATOR);
78}
79#endif
80#endif
81
82void NormalizeDirSeparators(FString &s)
83{
84 const unsigned len = s.Len();
85 for (unsigned i = 0; i < len; i++)
86 if (s[i] == '/')
87 s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR);
88}
89
90#endif
91
92
93#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
94
95bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
96
97bool IsAltPathPrefix(CFSTR s) throw()
98{
99 unsigned len = MyStringLen(s);
100 if (len == 0)
101 return false;
102 if (s[len - 1] != ':')
103 return false;
104
105 #if defined(_WIN32) && !defined(UNDER_CE)
106 if (IsDevicePath(s))
107 return false;
108 if (IsSuperPath(s))
109 {
110 s += kSuperPathPrefixSize;
111 len -= kSuperPathPrefixSize;
112 }
113 if (len == 2 && IsDrivePath2(s))
114 return false;
115 #endif
116
117 return true;
118}
119
120#if defined(_WIN32) && !defined(UNDER_CE)
121
122const char * const kSuperPathPrefix = "\\\\?\\";
123#ifdef WIN_LONG_PATH
124static const char * const kSuperUncPrefix = "\\\\?\\UNC\\";
125#endif
126
127#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
128#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
129#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
130
131#define IS_UNC_WITH_SLASH(s) ( \
132 ((s)[0] == 'U' || (s)[0] == 'u') \
133 && ((s)[1] == 'N' || (s)[1] == 'n') \
134 && ((s)[2] == 'C' || (s)[2] == 'c') \
135 && IS_SEPAR((s)[3]))
136
137bool IsDevicePath(CFSTR s) throw()
138{
139 #ifdef UNDER_CE
140
141 s = s;
142 return false;
143 /*
144 // actually we don't know the way to open device file in WinCE.
145 unsigned len = MyStringLen(s);
146 if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK"))
147 return false;
148 if (s[4] != ':')
149 return false;
150 // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));
151 */
152
153 #else
154
155 if (!IS_DEVICE_PATH(s))
156 return false;
157 unsigned len = MyStringLen(s);
158 if (len == 6 && s[5] == ':')
159 return true;
160 if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive"))
161 return false;
162 for (unsigned i = 17; i < len; i++)
163 if (s[i] < '0' || s[i] > '9')
164 return false;
165 return true;
166
167 #endif
168}
169
170bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
171bool IsNetworkPath(CFSTR s) throw()
172{
173 if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
174 return false;
175 if (IsSuperUncPath(s))
176 return true;
177 FChar c = s[2];
178 return (c != '.' && c != '?');
179}
180
181unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
182{
183 if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
184 return 0;
185 unsigned prefixSize = 2;
186 if (IsSuperUncPath(s))
187 prefixSize = kSuperUncPathPrefixSize;
188 else
189 {
190 FChar c = s[2];
191 if (c == '.' || c == '?')
192 return 0;
193 }
194 int pos = FindSepar(s + prefixSize);
195 if (pos < 0)
196 return 0;
197 return prefixSize + (unsigned)(pos + 1);
198}
199
200bool IsNetworkShareRootPath(CFSTR s) throw()
201{
202 unsigned prefixSize = GetNetworkServerPrefixSize(s);
203 if (prefixSize == 0)
204 return false;
205 s += prefixSize;
206 int pos = FindSepar(s);
207 if (pos < 0)
208 return true;
209 return s[(unsigned)pos + 1] == 0;
210}
211
212static const unsigned kDrivePrefixSize = 3; /* c:\ */
213
214bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
215// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
216bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
217bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
218// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
219
220#ifndef USE_UNICODE_FSTRING
221bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
222// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
223bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
224bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
225bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
226#endif // USE_UNICODE_FSTRING
227
228bool IsDrivePath_SuperAllowed(CFSTR s) throw()
229{
230 if (IsSuperPath(s))
231 s += kSuperPathPrefixSize;
232 return IsDrivePath(s);
233}
234
235bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
236{
237 if (IsSuperPath(s))
238 s += kSuperPathPrefixSize;
239 return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
240}
241
242bool IsAbsolutePath(const wchar_t *s) throw()
243{
244 return IS_SEPAR(s[0]) || IsDrivePath2(s);
245}
246
247int FindAltStreamColon(CFSTR path) throw()
248{
249 unsigned i = 0;
250 if (IsDrivePath2(path))
251 i = 2;
252 int colonPos = -1;
253 for (;; i++)
254 {
255 FChar c = path[i];
256 if (c == 0)
257 return colonPos;
258 if (c == ':')
259 {
260 if (colonPos < 0)
261 colonPos = (int)i;
262 continue;
263 }
264 if (IS_SEPAR(c))
265 colonPos = -1;
266 }
267}
268
269#ifndef USE_UNICODE_FSTRING
270
271static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
272{
273 // Network path: we look "server\path\" as root prefix
274 int pos = FindSepar(s);
275 if (pos < 0)
276 return 0;
277 int pos2 = FindSepar(s + (unsigned)pos + 1);
278 if (pos2 < 0)
279 return 0;
280 return pos + pos2 + 2;
281}
282
283static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
284{
285 if (IsDrivePath(s))
286 return kDrivePrefixSize;
287 if (!IS_SEPAR(s[0]))
288 return 0;
289 if (s[1] == 0 || !IS_SEPAR(s[1]))
290 return 1;
291 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
292 return (size == 0) ? 0 : 2 + size;
293}
294
295static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
296{
297 if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
298 {
299 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
300 return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
301 }
302 // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
303 int pos = FindSepar(s + kSuperPathPrefixSize);
304 if (pos < 0)
305 return 0;
306 return kSuperPathPrefixSize + pos + 1;
307}
308
309unsigned GetRootPrefixSize(CFSTR s) throw()
310{
311 if (IS_DEVICE_PATH(s))
312 return kDevicePathPrefixSize;
313 if (IsSuperPath(s))
314 return GetRootPrefixSize_Of_SuperPath(s);
315 return GetRootPrefixSize_Of_SimplePath(s);
316}
317
318#endif // USE_UNICODE_FSTRING
319
320static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
321{
322 // Network path: we look "server\path\" as root prefix
323 int pos = FindSepar(s);
324 if (pos < 0)
325 return 0;
326 int pos2 = FindSepar(s + (unsigned)pos + 1);
327 if (pos2 < 0)
328 return 0;
329 return (unsigned)(pos + pos2 + 2);
330}
331
332static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
333{
334 if (IsDrivePath(s))
335 return kDrivePrefixSize;
336 if (!IS_SEPAR(s[0]))
337 return 0;
338 if (s[1] == 0 || !IS_SEPAR(s[1]))
339 return 1;
340 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
341 return (size == 0) ? 0 : 2 + size;
342}
343
344static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
345{
346 if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
347 {
348 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
349 return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
350 }
351 // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
352 int pos = FindSepar(s + kSuperPathPrefixSize);
353 if (pos < 0)
354 return 0;
355 return kSuperPathPrefixSize + (unsigned)(pos + 1);
356}
357
358unsigned GetRootPrefixSize(const wchar_t *s) throw()
359{
360 if (IS_DEVICE_PATH(s))
361 return kDevicePathPrefixSize;
362 if (IsSuperPath(s))
363 return GetRootPrefixSize_Of_SuperPath(s);
364 return GetRootPrefixSize_Of_SimplePath(s);
365}
366
367#else // _WIN32
368
369bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); }
370
371#ifndef USE_UNICODE_FSTRING
372unsigned GetRootPrefixSize(CFSTR s) throw();
373unsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }
374#endif
375unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }
376
377#endif // _WIN32
378
379
380#ifndef UNDER_CE
381
382static bool GetCurDir(UString &path)
383{
384 path.Empty();
385
386 #ifdef _WIN32
387
388 DWORD needLength;
389 #ifndef _UNICODE
390 if (!g_IsNT)
391 {
392 TCHAR s[MAX_PATH + 2];
393 s[0] = 0;
394 needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);
395 path = fs2us(fas2fs(s));
396 }
397 else
398 #endif
399 {
400 WCHAR s[MAX_PATH + 2];
401 s[0] = 0;
402 needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
403 path = s;
404 }
405 return (needLength > 0 && needLength <= MAX_PATH);
406
407 #else
408
409 FString s;
410 if (!NDir::GetCurrentDir(s))
411 return false;
412 path = GetUnicodeString(s);
413 return true;
414
415 #endif
416}
417
418static bool ResolveDotsFolders(UString &s)
419{
420 #ifdef _WIN32
421 // s.Replace(L'/', WCHAR_PATH_SEPARATOR);
422 #endif
423
424 for (unsigned i = 0;;)
425 {
426 const wchar_t c = s[i];
427 if (c == 0)
428 return true;
429 if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
430 {
431 const wchar_t c1 = s[i + 1];
432 if (c1 == '.')
433 {
434 const wchar_t c2 = s[i + 2];
435 if (IS_SEPAR(c2) || c2 == 0)
436 {
437 if (i == 0)
438 return false;
439 int k = (int)i - 2;
440 i += 2;
441
442 for (;; k--)
443 {
444 if (k < 0)
445 return false;
446 if (!IS_SEPAR(s[(unsigned)k]))
447 break;
448 }
449
450 do
451 k--;
452 while (k >= 0 && !IS_SEPAR(s[(unsigned)k]));
453
454 unsigned num;
455
456 if (k >= 0)
457 {
458 num = i - (unsigned)k;
459 i = (unsigned)k;
460 }
461 else
462 {
463 num = (c2 == 0 ? i : (i + 1));
464 i = 0;
465 }
466
467 s.Delete(i, num);
468 continue;
469 }
470 }
471 else if (IS_SEPAR(c1) || c1 == 0)
472 {
473 unsigned num = 2;
474 if (i != 0)
475 i--;
476 else if (c1 == 0)
477 num = 1;
478 s.Delete(i, num);
479 continue;
480 }
481 }
482
483 i++;
484 }
485}
486
487#endif // UNDER_CE
488
489#define LONG_PATH_DOTS_FOLDERS_PARSING
490
491
492/*
493Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\
494To solve that problem we check such path:
495 - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper
496 - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain
497*/
498#ifdef LONG_PATH_DOTS_FOLDERS_PARSING
499#ifndef UNDER_CE
500static bool AreThereDotsFolders(CFSTR s)
501{
502 for (unsigned i = 0;; i++)
503 {
504 FChar c = s[i];
505 if (c == 0)
506 return false;
507 if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
508 {
509 FChar c1 = s[i + 1];
510 if (c1 == 0 || IS_SEPAR(c1) ||
511 (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
512 return true;
513 }
514 }
515}
516#endif
517#endif // LONG_PATH_DOTS_FOLDERS_PARSING
518
519#ifdef WIN_LONG_PATH
520
521/*
522Most of Windows versions have problems, if some file or dir name
523contains '.' or ' ' at the end of name (Bad Path).
524To solve that problem, we always use Super Path ("\\?\" prefix and full path)
525in such cases. Note that "." and ".." are not bad names.
526
527There are 3 cases:
528 1) If the path is already Super Path, we use that path
529 2) If the path is not Super Path :
530 2.1) Bad Path; we use only Super Path.
531 2.2) Good Path; we use Main Path. If it fails, we use Super Path.
532
533 NeedToUseOriginalPath returns:
534 kSuperPathType_UseOnlyMain : Super already
535 kSuperPathType_UseOnlySuper : not Super, Bad Path
536 kSuperPathType_UseMainAndSuper : not Super, Good Path
537*/
538
539int GetUseSuperPathType(CFSTR s) throw()
540{
541 if (IsSuperOrDevicePath(s))
542 {
543 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
544 if ((s)[2] != '.')
545 if (AreThereDotsFolders(s + kSuperPathPrefixSize))
546 return kSuperPathType_UseOnlySuper;
547 #endif
548 return kSuperPathType_UseOnlyMain;
549 }
550
551 for (unsigned i = 0;; i++)
552 {
553 FChar c = s[i];
554 if (c == 0)
555 return kSuperPathType_UseMainAndSuper;
556 if (c == '.' || c == ' ')
557 {
558 FChar c2 = s[i + 1];
559 if (c2 == 0 || IS_SEPAR(c2))
560 {
561 // if it's "." or "..", it's not bad name.
562 if (c == '.')
563 {
564 if (i == 0 || IS_SEPAR(s[i - 1]))
565 continue;
566 if (s[i - 1] == '.')
567 {
568 if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
569 continue;
570 }
571 }
572 return kSuperPathType_UseOnlySuper;
573 }
574 }
575 }
576}
577
578
579
580/*
581 returns false in two cases:
582 - if GetCurDir was used, and GetCurDir returned error.
583 - if we can't resolve ".." name.
584 if path is ".", "..", res is empty.
585 if it's Super Path already, res is empty.
586 for \**** , and if GetCurDir is not drive (c:\), res is empty
587 for absolute paths, returns true, res is Super path.
588*/
589
590static bool GetSuperPathBase(CFSTR s, UString &res)
591{
592 res.Empty();
593
594 FChar c = s[0];
595 if (c == 0)
596 return true;
597 if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
598 return true;
599
600 if (IsSuperOrDevicePath(s))
601 {
602 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
603
604 if ((s)[2] == '.')
605 return true;
606
607 // we will return true here, so we will try to use these problem paths.
608
609 if (!AreThereDotsFolders(s + kSuperPathPrefixSize))
610 return true;
611
612 UString temp = fs2us(s);
613 unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp);
614 if (fixedSize == 0)
615 return true;
616
617 UString rem = &temp[fixedSize];
618 if (!ResolveDotsFolders(rem))
619 return true;
620
621 temp.DeleteFrom(fixedSize);
622 res += temp;
623 res += rem;
624
625 #endif
626
627 return true;
628 }
629
630 if (IS_SEPAR(c))
631 {
632 if (IS_SEPAR(s[1]))
633 {
634 UString temp = fs2us(s + 2);
635 unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
636 // we ignore that error to allow short network paths server\share?
637 /*
638 if (fixedSize == 0)
639 return false;
640 */
641 UString rem = &temp[fixedSize];
642 if (!ResolveDotsFolders(rem))
643 return false;
644 res += kSuperUncPrefix;
645 temp.DeleteFrom(fixedSize);
646 res += temp;
647 res += rem;
648 return true;
649 }
650 }
651 else
652 {
653 if (IsDrivePath2(s))
654 {
655 UString temp = fs2us(s);
656 unsigned prefixSize = 2;
657 if (IsDrivePath(s))
658 prefixSize = kDrivePrefixSize;
659 UString rem = temp.Ptr(prefixSize);
660 if (!ResolveDotsFolders(rem))
661 return true;
662 res += kSuperPathPrefix;
663 temp.DeleteFrom(prefixSize);
664 res += temp;
665 res += rem;
666 return true;
667 }
668 }
669
670 UString curDir;
671 if (!GetCurDir(curDir))
672 return false;
673 NormalizeDirPathPrefix(curDir);
674
675 unsigned fixedSizeStart = 0;
676 unsigned fixedSize = 0;
677 const char *superMarker = NULL;
678 if (IsSuperPath(curDir))
679 {
680 fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
681 if (fixedSize == 0)
682 return false;
683 }
684 else
685 {
686 if (IsDrivePath(curDir))
687 {
688 superMarker = kSuperPathPrefix;
689 fixedSize = kDrivePrefixSize;
690 }
691 else
692 {
693 if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
694 return false;
695 fixedSizeStart = 2;
696 fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
697 if (fixedSize == 0)
698 return false;
699 superMarker = kSuperUncPrefix;
700 }
701 }
702
703 UString temp;
704 if (IS_SEPAR(c))
705 {
706 temp = fs2us(s + 1);
707 }
708 else
709 {
710 temp += &curDir[fixedSizeStart + fixedSize];
711 temp += fs2us(s);
712 }
713 if (!ResolveDotsFolders(temp))
714 return false;
715 if (superMarker)
716 res += superMarker;
717 res += curDir.Mid(fixedSizeStart, fixedSize);
718 res += temp;
719 return true;
720}
721
722
723/*
724 In that case if GetSuperPathBase doesn't return new path, we don't need
725 to use same path that was used as main path
726
727 GetSuperPathBase superPath.IsEmpty() onlyIfNew
728 false * * GetCurDir Error
729 true false * use Super path
730 true true true don't use any path, we already used mainPath
731 true true false use main path as Super Path, we don't try mainMath
732 That case is possible now if GetCurDir returns unknown
733 type of path (not drive and not network)
734
735 We can change that code if we want to try mainPath, if GetSuperPathBase returns error,
736 and we didn't try mainPath still.
737 If we want to work that way, we don't need to use GetSuperPathBase return code.
738*/
739
740bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)
741{
742 if (GetSuperPathBase(path, superPath))
743 {
744 if (superPath.IsEmpty())
745 {
746 // actually the only possible when onlyIfNew == true and superPath is empty
747 // is case when
748
749 if (onlyIfNew)
750 return false;
751 superPath = fs2us(path);
752 }
753
754 NormalizeDirSeparators(superPath);
755 return true;
756 }
757 return false;
758}
759
760bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)
761{
762 if (!GetSuperPathBase(s1, d1) ||
763 !GetSuperPathBase(s2, d2))
764 return false;
765
766 NormalizeDirSeparators(d1);
767 NormalizeDirSeparators(d2);
768
769 if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)
770 return false;
771 if (d1.IsEmpty()) d1 = fs2us(s1);
772 if (d2.IsEmpty()) d2 = fs2us(s2);
773 return true;
774}
775
776
777/*
778// returns true, if we need additional use with New Super path.
779bool GetSuperPath(CFSTR path, UString &superPath)
780{
781 if (GetSuperPathBase(path, superPath))
782 return !superPath.IsEmpty();
783 return false;
784}
785*/
786#endif // WIN_LONG_PATH
787
788bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
789{
790 res = s;
791
792 #ifdef UNDER_CE
793
794 if (!IS_SEPAR(s[0]))
795 {
796 if (!dirPrefix)
797 return false;
798 res = dirPrefix;
799 res += s;
800 }
801
802 #else
803
804 unsigned prefixSize = GetRootPrefixSize(s);
805 if (prefixSize != 0)
806 {
807 if (!AreThereDotsFolders(s + prefixSize))
808 return true;
809
810 UString rem = fs2us(s + prefixSize);
811 if (!ResolveDotsFolders(rem))
812 return true; // maybe false;
813 res.DeleteFrom(prefixSize);
814 res += us2fs(rem);
815 return true;
816 }
817
818 /*
819 FChar c = s[0];
820 if (c == 0)
821 return true;
822 if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
823 return true;
824 if (IS_SEPAR(c) && IS_SEPAR(s[1]))
825 return true;
826 if (IsDrivePath(s))
827 return true;
828 */
829
830 UString curDir;
831 if (dirPrefix)
832 curDir = fs2us(dirPrefix);
833 else
834 {
835 if (!GetCurDir(curDir))
836 return false;
837 }
838 NormalizeDirPathPrefix(curDir);
839
840 unsigned fixedSize = 0;
841
842 #ifdef _WIN32
843
844 if (IsSuperPath(curDir))
845 {
846 fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
847 if (fixedSize == 0)
848 return false;
849 }
850 else
851 {
852 if (IsDrivePath(curDir))
853 fixedSize = kDrivePrefixSize;
854 else
855 {
856 if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
857 return false;
858 fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
859 if (fixedSize == 0)
860 return false;
861 fixedSize += 2;
862 }
863 }
864
865 #endif // _WIN32
866
867 UString temp;
868 if (IS_SEPAR(s[0]))
869 {
870 temp = fs2us(s + 1);
871 }
872 else
873 {
874 temp += curDir.Ptr(fixedSize);
875 temp += fs2us(s);
876 }
877 if (!ResolveDotsFolders(temp))
878 return false;
879 curDir.DeleteFrom(fixedSize);
880 res = us2fs(curDir);
881 res += us2fs(temp);
882
883 #endif // UNDER_CE
884
885 return true;
886}
887
888bool GetFullPath(CFSTR path, FString &fullPath)
889{
890 return GetFullPath(NULL, path, fullPath);
891}
892
893}}}
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
new file mode 100644
index 0000000..de8bd13
--- /dev/null
+++ b/CPP/Windows/FileName.h
@@ -0,0 +1,119 @@
1// Windows/FileName.h
2
3#ifndef __WINDOWS_FILE_NAME_H
4#define __WINDOWS_FILE_NAME_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NFile {
10namespace NName {
11
12int FindSepar(const wchar_t *s) throw();
13#ifndef USE_UNICODE_FSTRING
14int FindSepar(const FChar *s) throw();
15#endif
16
17void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty
18void NormalizeDirPathPrefix(UString &dirPath);
19
20#ifdef _WIN32
21void NormalizeDirSeparators(FString &s);
22#endif
23
24bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\"
25
26bool IsAltPathPrefix(CFSTR s) throw(); /* name: */
27
28#if defined(_WIN32) && !defined(UNDER_CE)
29
30extern const char * const kSuperPathPrefix; /* \\?\ */
31const unsigned kDevicePathPrefixSize = 4;
32const unsigned kSuperPathPrefixSize = 4;
33const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;
34
35bool IsDevicePath(CFSTR s) throw(); /* \\.\ */
36bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */
37bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */
38
39/* GetNetworkServerPrefixSize() returns size of server prefix:
40 \\?\UNC\SERVER\
41 \\SERVER\
42 in another cases it returns 0
43*/
44
45unsigned GetNetworkServerPrefixSize(CFSTR s) throw();
46
47bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */
48
49bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\"
50bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\"
51
52bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:"
53// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:"
54bool IsSuperPath(const wchar_t *s) throw();
55bool IsSuperOrDevicePath(const wchar_t *s) throw();
56
57#ifndef USE_UNICODE_FSTRING
58bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:"
59// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:"
60bool IsDrivePath(CFSTR s) throw();
61bool IsSuperPath(CFSTR s) throw();
62bool IsSuperOrDevicePath(CFSTR s) throw();
63
64/* GetRootPrefixSize() returns size of ROOT PREFIX for cases:
65 \
66 \\.\
67 C:\
68 \\?\C:\
69 \\?\UNC\SERVER\Shared\
70 \\SERVER\Shared\
71 in another cases it returns 0
72*/
73
74unsigned GetRootPrefixSize(CFSTR s) throw();
75
76#endif
77
78int FindAltStreamColon(CFSTR path) throw();
79
80#endif // _WIN32
81
82bool IsAbsolutePath(const wchar_t *s) throw();
83unsigned GetRootPrefixSize(const wchar_t *s) throw();
84
85#ifdef WIN_LONG_PATH
86
87const int kSuperPathType_UseOnlyMain = 0;
88const int kSuperPathType_UseOnlySuper = 1;
89const int kSuperPathType_UseMainAndSuper = 2;
90
91int GetUseSuperPathType(CFSTR s) throw();
92bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew);
93bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);
94
95#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper)
96#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper)
97
98#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain)
99#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain)
100
101#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH)
102#define IF_USE_MAIN_PATH_2(x1, x2) \
103 int __useSuperPathType1 = GetUseSuperPathType(x1); \
104 int __useSuperPathType2 = GetUseSuperPathType(x2); \
105 if (USE_MAIN_PATH_2)
106
107#else
108
109#define IF_USE_MAIN_PATH
110#define IF_USE_MAIN_PATH_2(x1, x2)
111
112#endif // WIN_LONG_PATH
113
114bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath);
115bool GetFullPath(CFSTR path, FString &fullPath);
116
117}}}
118
119#endif
diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp
new file mode 100644
index 0000000..6259453
--- /dev/null
+++ b/CPP/Windows/FileSystem.cpp
@@ -0,0 +1,135 @@
1// Windows/FileSystem.cpp
2
3#include "StdAfx.h"
4
5#ifndef UNDER_CE
6
7#ifndef _UNICODE
8#include "../Common/StringConvert.h"
9#endif
10
11#include "FileSystem.h"
12#include "Defs.h"
13
14#ifndef _UNICODE
15extern bool g_IsNT;
16#endif
17
18namespace NWindows {
19namespace NFile {
20namespace NSystem {
21
22#ifdef _WIN32
23
24bool MyGetVolumeInformation(
25 CFSTR rootPath,
26 UString &volumeName,
27 LPDWORD volumeSerialNumber,
28 LPDWORD maximumComponentLength,
29 LPDWORD fileSystemFlags,
30 UString &fileSystemName)
31{
32 BOOL res;
33 #ifndef _UNICODE
34 if (!g_IsNT)
35 {
36 TCHAR v[MAX_PATH + 2]; v[0] = 0;
37 TCHAR f[MAX_PATH + 2]; f[0] = 0;
38 res = GetVolumeInformation(fs2fas(rootPath),
39 v, MAX_PATH,
40 volumeSerialNumber, maximumComponentLength, fileSystemFlags,
41 f, MAX_PATH);
42 volumeName = MultiByteToUnicodeString(v);
43 fileSystemName = MultiByteToUnicodeString(f);
44 }
45 else
46 #endif
47 {
48 WCHAR v[MAX_PATH + 2]; v[0] = 0;
49 WCHAR f[MAX_PATH + 2]; f[0] = 0;
50 res = GetVolumeInformationW(fs2us(rootPath),
51 v, MAX_PATH,
52 volumeSerialNumber, maximumComponentLength, fileSystemFlags,
53 f, MAX_PATH);
54 volumeName = v;
55 fileSystemName = f;
56 }
57 return BOOLToBool(res);
58}
59
60UINT MyGetDriveType(CFSTR pathName)
61{
62 #ifndef _UNICODE
63 if (!g_IsNT)
64 {
65 return GetDriveType(fs2fas(pathName));
66 }
67 else
68 #endif
69 {
70 return GetDriveTypeW(fs2us(pathName));
71 }
72}
73
74typedef BOOL (WINAPI * GetDiskFreeSpaceExA_Pointer)(
75 LPCSTR lpDirectoryName, // directory name
76 PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller
77 PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk
78 PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
79);
80
81typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)(
82 LPCWSTR lpDirectoryName, // directory name
83 PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller
84 PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk
85 PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
86);
87
88bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)
89{
90 DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters;
91 bool sizeIsDetected = false;
92 #ifndef _UNICODE
93 if (!g_IsNT)
94 {
95 GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)(void *)GetProcAddress(
96 GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");
97 if (pGetDiskFreeSpaceEx)
98 {
99 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;
100 sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));
101 totalSize = totalSize2.QuadPart;
102 freeSize = freeSize2.QuadPart;
103 }
104 if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters))
105 return false;
106 }
107 else
108 #endif
109 {
110 GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)(void *)GetProcAddress(
111 GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW");
112 if (pGetDiskFreeSpaceEx)
113 {
114 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;
115 sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));
116 totalSize = totalSize2.QuadPart;
117 freeSize = freeSize2.QuadPart;
118 }
119 if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters))
120 return false;
121 }
122 clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster;
123 if (!sizeIsDetected)
124 {
125 totalSize = clusterSize * (UInt64)numClusters;
126 freeSize = clusterSize * (UInt64)numFreeClusters;
127 }
128 return true;
129}
130
131#endif
132
133}}}
134
135#endif
diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h
new file mode 100644
index 0000000..9b49a02
--- /dev/null
+++ b/CPP/Windows/FileSystem.h
@@ -0,0 +1,31 @@
1// Windows/FileSystem.h
2
3#ifndef __WINDOWS_FILE_SYSTEM_H
4#define __WINDOWS_FILE_SYSTEM_H
5
6#include "../Common/MyString.h"
7#include "../Common/MyTypes.h"
8
9namespace NWindows {
10namespace NFile {
11namespace NSystem {
12
13#ifdef _WIN32
14
15bool MyGetVolumeInformation(
16 CFSTR rootPath ,
17 UString &volumeName,
18 LPDWORD volumeSerialNumber,
19 LPDWORD maximumComponentLength,
20 LPDWORD fileSystemFlags,
21 UString &fileSystemName);
22
23UINT MyGetDriveType(CFSTR pathName);
24
25bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
26
27#endif
28
29}}}
30
31#endif
diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h
new file mode 100644
index 0000000..5878c83
--- /dev/null
+++ b/CPP/Windows/Handle.h
@@ -0,0 +1,39 @@
1// Windows/Handle.h
2
3#ifndef __WINDOWS_HANDLE_H
4#define __WINDOWS_HANDLE_H
5
6#include "../Common/MyTypes.h"
7
8namespace NWindows {
9
10class CHandle MY_UNCOPYABLE
11{
12protected:
13 HANDLE _handle;
14public:
15 operator HANDLE() { return _handle; }
16 CHandle(): _handle(NULL) {}
17 ~CHandle() { Close(); }
18 bool IsCreated() const { return (_handle != NULL); }
19 bool Close()
20 {
21 if (_handle == NULL)
22 return true;
23 if (!::CloseHandle(_handle))
24 return false;
25 _handle = NULL;
26 return true;
27 }
28 void Attach(HANDLE handle) { _handle = handle; }
29 HANDLE Detach()
30 {
31 HANDLE handle = _handle;
32 _handle = NULL;
33 return handle;
34 }
35};
36
37}
38
39#endif
diff --git a/CPP/Windows/MemoryGlobal.cpp b/CPP/Windows/MemoryGlobal.cpp
new file mode 100644
index 0000000..2a22394
--- /dev/null
+++ b/CPP/Windows/MemoryGlobal.cpp
@@ -0,0 +1,36 @@
1// Windows/MemoryGlobal.cpp
2
3#include "StdAfx.h"
4
5#include "MemoryGlobal.h"
6
7namespace NWindows {
8namespace NMemory {
9
10bool CGlobal::Alloc(UINT flags, SIZE_T size) throw()
11{
12 HGLOBAL newBlock = ::GlobalAlloc(flags, size);
13 if (newBlock == NULL)
14 return false;
15 _global = newBlock;
16 return true;
17}
18
19bool CGlobal::Free() throw()
20{
21 if (_global == NULL)
22 return true;
23 _global = ::GlobalFree(_global);
24 return (_global == NULL);
25}
26
27bool CGlobal::ReAlloc(SIZE_T size) throw()
28{
29 HGLOBAL newBlock = ::GlobalReAlloc(_global, size, GMEM_MOVEABLE);
30 if (newBlock == NULL)
31 return false;
32 _global = newBlock;
33 return true;
34}
35
36}}
diff --git a/CPP/Windows/MemoryGlobal.h b/CPP/Windows/MemoryGlobal.h
new file mode 100644
index 0000000..c217510
--- /dev/null
+++ b/CPP/Windows/MemoryGlobal.h
@@ -0,0 +1,55 @@
1// Windows/MemoryGlobal.h
2
3#ifndef __WINDOWS_MEMORY_GLOBAL_H
4#define __WINDOWS_MEMORY_GLOBAL_H
5
6#include "../Common/MyWindows.h"
7
8namespace NWindows {
9namespace NMemory {
10
11class CGlobal
12{
13 HGLOBAL _global;
14public:
15 CGlobal(): _global(NULL){};
16 ~CGlobal() { Free(); }
17 operator HGLOBAL() const { return _global; }
18 void Attach(HGLOBAL hGlobal)
19 {
20 Free();
21 _global = hGlobal;
22 }
23 HGLOBAL Detach()
24 {
25 HGLOBAL h = _global;
26 _global = NULL;
27 return h;
28 }
29 bool Alloc(UINT flags, SIZE_T size) throw();
30 bool Free() throw();
31 LPVOID Lock() const { return GlobalLock(_global); }
32 void Unlock() const { GlobalUnlock(_global); }
33 bool ReAlloc(SIZE_T size) throw();
34};
35
36class CGlobalLock
37{
38 HGLOBAL _global;
39 LPVOID _ptr;
40public:
41 LPVOID GetPointer() const { return _ptr; }
42 CGlobalLock(HGLOBAL hGlobal): _global(hGlobal)
43 {
44 _ptr = GlobalLock(hGlobal);
45 };
46 ~CGlobalLock()
47 {
48 if (_ptr != NULL)
49 GlobalUnlock(_global);
50 }
51};
52
53}}
54
55#endif
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
new file mode 100644
index 0000000..fdfbeb9
--- /dev/null
+++ b/CPP/Windows/MemoryLock.cpp
@@ -0,0 +1,112 @@
1// Windows/MemoryLock.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "MemoryLock.h"
8
9namespace NWindows {
10namespace NSecurity {
11
12#ifndef UNDER_CE
13
14#ifdef _UNICODE
15#define MY_FUNC_SELECT(f) :: f
16#else
17#define MY_FUNC_SELECT(f) my_ ## f
18extern "C" {
19typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
20typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);
21typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges,
22 PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
23}
24#define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff)GetProcAddress(hModule, name)
25#endif
26
27bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
28{
29 bool res = false;
30
31 #ifndef _UNICODE
32
33 HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll"));
34 if (hModule == NULL)
35 return false;
36
37 GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken");
38 GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA");
39 GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges");
40
41 if (my_OpenProcessToken &&
42 my_AdjustTokenPrivileges &&
43 my_LookupPrivilegeValue)
44
45 #endif
46
47 {
48 HANDLE token;
49 if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
50 {
51 TOKEN_PRIVILEGES tp;
52 if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))
53 {
54 tp.PrivilegeCount = 1;
55 tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);
56 if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))
57 res = (GetLastError() == ERROR_SUCCESS);
58 }
59 ::CloseHandle(token);
60 }
61 }
62
63 #ifndef _UNICODE
64
65 ::FreeLibrary(hModule);
66
67 #endif
68
69 return res;
70}
71
72
73
74typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
75
76/*
77 We suppose that Window 10 works incorrectly with "Large Pages" at:
78 - Windows 10 1703 (15063) : incorrect allocating after VirtualFree()
79 - Windows 10 1709 (16299) : incorrect allocating after VirtualFree()
80 - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger,
81 if CPU doesn't support 1 GB pages.
82 Windows 10 1903 (18362) probably works correctly.
83*/
84
85unsigned Get_LargePages_RiskLevel()
86{
87 OSVERSIONINFOEXW vi;
88 HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
89 if (!ntdll)
90 return 0;
91 Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion");
92 if (!func)
93 return 0;
94 func(&vi);
95 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
96 return 0;
97 if (vi.dwMajorVersion + vi.dwMinorVersion != 10)
98 return 0;
99 if (vi.dwBuildNumber <= 16299)
100 return 1;
101
102 #ifdef MY_CPU_X86_OR_AMD64
103 if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB())
104 return 1;
105 #endif
106
107 return 0;
108}
109
110#endif
111
112}}
diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
new file mode 100644
index 0000000..dcaf182
--- /dev/null
+++ b/CPP/Windows/MemoryLock.h
@@ -0,0 +1,40 @@
1// Windows/MemoryLock.h
2
3#ifndef __WINDOWS_MEMORY_LOCK_H
4#define __WINDOWS_MEMORY_LOCK_H
5
6#include "../Common/MyWindows.h"
7
8namespace NWindows {
9namespace NSecurity {
10
11#ifndef UNDER_CE
12
13bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true);
14
15inline bool EnablePrivilege_LockMemory(bool enable = true)
16{
17 return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable);
18}
19
20inline void EnablePrivilege_SymLink()
21{
22 /* Probably we do not to set any Privilege for junction points.
23 But we need them for Symbolic links */
24 NSecurity::EnablePrivilege(SE_RESTORE_NAME);
25
26 /* Probably we need only SE_RESTORE_NAME, but there is also
27 SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */
28
29 NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME
30
31 // Do we need to set SE_BACKUP_NAME ?
32}
33
34unsigned Get_LargePages_RiskLevel();
35
36#endif
37
38}}
39
40#endif
diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp
new file mode 100644
index 0000000..3ad6953
--- /dev/null
+++ b/CPP/Windows/Menu.cpp
@@ -0,0 +1,216 @@
1// Windows/Menu.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../Common/StringConvert.h"
7#endif
8#include "Menu.h"
9
10#ifndef _UNICODE
11extern bool g_IsNT;
12#endif
13
14namespace NWindows {
15
16/*
17structures
18 MENUITEMINFOA
19 MENUITEMINFOW
20contain additional member:
21 #if (WINVER >= 0x0500)
22 HBITMAP hbmpItem;
23 #endif
24If we compile the source code with (WINVER >= 0x0500), some functions
25will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*).
26So we use size of old version of structure. */
27
28#if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500)
29 #ifndef _UNICODE
30 #define my_compatib_MENUITEMINFOA_size sizeof(MENUITEMINFOA)
31 #endif
32 #define my_compatib_MENUITEMINFOW_size sizeof(MENUITEMINFOW)
33#else
34 #define MY_STRUCT_SIZE_BEFORE(structname, member) ((UINT)(UINT_PTR)((LPBYTE)(&((structname*)0)->member) - (LPBYTE)(structname*)0))
35 #ifndef _UNICODE
36 #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem)
37 #endif
38 #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem)
39#endif
40
41static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si)
42{
43 ZeroMemory(&si, sizeof(si));
44 si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si);
45 si.fMask = item.fMask;
46 si.fType = item.fType;
47 si.fState = item.fState;
48 si.wID = item.wID;
49 si.hSubMenu = item.hSubMenu;
50 si.hbmpChecked = item.hbmpChecked;
51 si.hbmpUnchecked = item.hbmpUnchecked;
52 si.dwItemData = item.dwItemData;
53}
54
55#ifndef _UNICODE
56static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si)
57{
58 ZeroMemory(&si, sizeof(si));
59 si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si);
60 si.fMask = item.fMask;
61 si.fType = item.fType;
62 si.fState = item.fState;
63 si.wID = item.wID;
64 si.hSubMenu = item.hSubMenu;
65 si.hbmpChecked = item.hbmpChecked;
66 si.hbmpUnchecked = item.hbmpUnchecked;
67 si.dwItemData = item.dwItemData;
68}
69#endif
70
71static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item)
72{
73 item.fMask = si.fMask;
74 item.fType = si.fType;
75 item.fState = si.fState;
76 item.wID = si.wID;
77 item.hSubMenu = si.hSubMenu;
78 item.hbmpChecked = si.hbmpChecked;
79 item.hbmpUnchecked = si.hbmpUnchecked;
80 item.dwItemData = si.dwItemData;
81}
82
83#ifndef _UNICODE
84static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item)
85{
86 item.fMask = si.fMask;
87 item.fType = si.fType;
88 item.fState = si.fState;
89 item.wID = si.wID;
90 item.hSubMenu = si.hSubMenu;
91 item.hbmpChecked = si.hbmpChecked;
92 item.hbmpUnchecked = si.hbmpUnchecked;
93 item.dwItemData = si.dwItemData;
94}
95#endif
96
97bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item)
98{
99 const UINT kMaxSize = 512;
100 #ifndef _UNICODE
101 if (!g_IsNT)
102 {
103 CHAR s[kMaxSize + 1];
104 MENUITEMINFOA si;
105 ConvertItemToSysForm(item, si);
106 if (item.IsString())
107 {
108 si.cch = kMaxSize;
109 si.dwTypeData = s;
110 }
111 if (GetItemInfo(itemIndex, byPosition, &si))
112 {
113 ConvertItemToMyForm(si, item);
114 if (item.IsString())
115 item.StringValue = GetUnicodeString(s);
116 return true;
117 }
118 }
119 else
120 #endif
121 {
122 wchar_t s[kMaxSize + 1];
123 MENUITEMINFOW si;
124 ConvertItemToSysForm(item, si);
125 if (item.IsString())
126 {
127 si.cch = kMaxSize;
128 si.dwTypeData = s;
129 }
130 if (GetItemInfo(itemIndex, byPosition, &si))
131 {
132 ConvertItemToMyForm(si, item);
133 if (item.IsString())
134 item.StringValue = s;
135 return true;
136 }
137 }
138 return false;
139}
140
141bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
142{
143 #ifndef _UNICODE
144 if (!g_IsNT)
145 {
146 MENUITEMINFOA si;
147 ConvertItemToSysForm(item, si);
148 AString s;
149 if (item.IsString())
150 {
151 s = GetSystemString(item.StringValue);
152 si.dwTypeData = s.Ptr_non_const();
153 }
154 return SetItemInfo(itemIndex, byPosition, &si);
155 }
156 else
157 #endif
158 {
159 MENUITEMINFOW si;
160 ConvertItemToSysForm(item, si);
161 if (item.IsString())
162 si.dwTypeData = item.StringValue.Ptr_non_const();
163 return SetItemInfo(itemIndex, byPosition, &si);
164 }
165}
166
167bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
168{
169 #ifndef _UNICODE
170 if (!g_IsNT)
171 {
172 MENUITEMINFOA si;
173 ConvertItemToSysForm(item, si);
174 AString s;
175 if (item.IsString())
176 {
177 s = GetSystemString(item.StringValue);
178 si.dwTypeData = s.Ptr_non_const();
179 }
180 return InsertItem(itemIndex, byPosition, &si);
181 }
182 else
183 #endif
184 {
185 MENUITEMINFOW si;
186 ConvertItemToSysForm(item, si);
187 if (item.IsString())
188 si.dwTypeData = item.StringValue.Ptr_non_const();
189 #ifdef UNDER_CE
190 UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING;
191 UINT id = item.wID;
192 if ((item.fMask & MIIM_SUBMENU) != 0)
193 {
194 flags |= MF_POPUP;
195 id = (UINT)item.hSubMenu;
196 }
197 if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue))
198 return false;
199 return SetItemInfo(itemIndex, byPosition, &si);
200 #else
201 return InsertItem(itemIndex, byPosition, &si);
202 #endif
203 }
204}
205
206#ifndef _UNICODE
207bool CMenu::AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem)
208{
209 if (g_IsNT)
210 return BOOLToBool(::AppendMenuW(_menu, flags, newItemID, newItem));
211 else
212 return AppendItem(flags, newItemID, GetSystemString(newItem));
213}
214#endif
215
216}
diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h
new file mode 100644
index 0000000..aacdc7c
--- /dev/null
+++ b/CPP/Windows/Menu.h
@@ -0,0 +1,158 @@
1// Windows/Menu.h
2
3#ifndef __WINDOWS_MENU_H
4#define __WINDOWS_MENU_H
5
6#include "../Common/MyString.h"
7
8#include "Defs.h"
9
10namespace NWindows {
11
12struct CMenuItem
13{
14 UString StringValue;
15 UINT fMask;
16 UINT fType;
17 UINT fState;
18 UINT wID;
19 HMENU hSubMenu;
20 HBITMAP hbmpChecked;
21 HBITMAP hbmpUnchecked;
22 ULONG_PTR dwItemData;
23 // LPTSTR dwTypeData;
24 // UINT cch;
25 // HBITMAP hbmpItem;
26 bool IsString() const // change it MIIM_STRING
27 { return ((fMask & MIIM_TYPE) != 0 && (fType == MFT_STRING)); }
28 bool IsSeparator() const { return (fType == MFT_SEPARATOR); }
29 CMenuItem(): fMask(0), fType(0), fState(0), wID(0), hSubMenu(0), hbmpChecked(0),
30 hbmpUnchecked(0), dwItemData(0) {}
31};
32
33class CMenu
34{
35 HMENU _menu;
36public:
37 CMenu(): _menu(NULL) {};
38 operator HMENU() const { return _menu; }
39 void Attach(HMENU menu) { _menu = menu; }
40
41 HMENU Detach()
42 {
43 HMENU menu = _menu;
44 _menu = NULL;
45 return menu;
46 }
47
48 bool Create()
49 {
50 _menu = ::CreateMenu();
51 return (_menu != NULL);
52 }
53
54 bool CreatePopup()
55 {
56 _menu = ::CreatePopupMenu();
57 return (_menu != NULL);
58 }
59
60 bool Destroy()
61 {
62 if (_menu == NULL)
63 return false;
64 return BOOLToBool(::DestroyMenu(Detach()));
65 }
66
67 int GetItemCount()
68 {
69 #ifdef UNDER_CE
70 for (int i = 0;; i++)
71 {
72 CMenuItem item;
73 item.fMask = MIIM_STATE;
74 if (!GetItem(i, true, item))
75 return i;
76 }
77 #else
78 return GetMenuItemCount(_menu);
79 #endif
80 }
81
82 HMENU GetSubMenu(int pos) { return ::GetSubMenu(_menu, pos); }
83 #ifndef UNDER_CE
84 /*
85 bool GetItemString(UINT idItem, UINT flag, CSysString &result)
86 {
87 result.Empty();
88 int len = ::GetMenuString(_menu, idItem, 0, 0, flag);
89 int len2 = ::GetMenuString(_menu, idItem, result.GetBuf(len + 2), len + 1, flag);
90 if (len > len2)
91 len = len2;
92 result.ReleaseBuf_CalcLen(len + 2);
93 return (len != 0);
94 }
95 */
96 UINT GetItemID(int pos) { return ::GetMenuItemID(_menu, pos); }
97 UINT GetItemState(UINT id, UINT flags) { return ::GetMenuState(_menu, id, flags); }
98 #endif
99
100 bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo)
101 { return BOOLToBool(::GetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
102 bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo)
103 { return BOOLToBool(::SetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
104
105 bool AppendItem(UINT flags, UINT_PTR newItemID, LPCTSTR newItem)
106 { return BOOLToBool(::AppendMenu(_menu, flags, newItemID, newItem)); }
107
108 bool Insert(UINT position, UINT flags, UINT_PTR idNewItem, LPCTSTR newItem)
109 { return BOOLToBool(::InsertMenu(_menu, position, flags, idNewItem, newItem)); }
110
111 #ifndef UNDER_CE
112 bool InsertItem(UINT itemIndex, bool byPosition, LPCMENUITEMINFO itemInfo)
113 { return BOOLToBool(::InsertMenuItem(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
114 #endif
115
116 bool RemoveItem(UINT item, UINT flags) { return BOOLToBool(::RemoveMenu(_menu, item, flags)); }
117 void RemoveAllItemsFrom(UINT index) { while (RemoveItem(index, MF_BYPOSITION)); }
118 void RemoveAllItems() { RemoveAllItemsFrom(0); }
119
120 #ifndef _UNICODE
121 bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)
122 { return BOOLToBool(::GetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
123 bool InsertItem(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)
124 { return BOOLToBool(::InsertMenuItemW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
125 bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)
126 { return BOOLToBool(::SetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }
127 bool AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem);
128 #endif
129
130 bool GetItem(UINT itemIndex, bool byPosition, CMenuItem &item);
131 bool SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item);
132 bool InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item);
133
134 int Track(UINT flags, int x, int y, HWND hWnd) { return ::TrackPopupMenuEx(_menu, flags, x, y, hWnd, NULL); }
135
136 bool CheckRadioItem(UINT idFirst, UINT idLast, UINT idCheck, UINT flags)
137 { return BOOLToBool(::CheckMenuRadioItem(_menu, idFirst, idLast, idCheck, flags)); }
138
139 DWORD CheckItem(UINT id, UINT uCheck) { return ::CheckMenuItem(_menu, id, uCheck); }
140 DWORD CheckItemByID(UINT id, bool check) { return CheckItem(id, MF_BYCOMMAND | (check ? MF_CHECKED : MF_UNCHECKED)); }
141
142 BOOL EnableItem(UINT uIDEnableItem, UINT uEnable) { return EnableMenuItem(_menu, uIDEnableItem, uEnable); }
143};
144
145class CMenuDestroyer
146{
147 CMenu *_menu;
148public:
149 CMenuDestroyer(CMenu &menu): _menu(&menu) {}
150 CMenuDestroyer(): _menu(0) {}
151 ~CMenuDestroyer() { if (_menu) _menu->Destroy(); }
152 void Attach(CMenu &menu) { _menu = &menu; }
153 void Disable() { _menu = 0; }
154};
155
156}
157
158#endif
diff --git a/CPP/Windows/NationalTime.cpp b/CPP/Windows/NationalTime.cpp
new file mode 100644
index 0000000..0dcd31e
--- /dev/null
+++ b/CPP/Windows/NationalTime.cpp
@@ -0,0 +1,37 @@
1// Windows/NationalTime.cpp
2
3#include "StdAfx.h"
4
5#include "NationalTime.h"
6
7namespace NWindows {
8namespace NNational {
9namespace NTime {
10
11bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
12 LPCTSTR format, CSysString &resultString)
13{
14 resultString.Empty();
15 int numChars = ::GetTimeFormat(locale, flags, time, format, NULL, 0);
16 if (numChars == 0)
17 return false;
18 numChars = ::GetTimeFormat(locale, flags, time, format,
19 resultString.GetBuf(numChars), numChars + 1);
20 resultString.ReleaseBuf_CalcLen(numChars);
21 return (numChars != 0);
22}
23
24bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
25 LPCTSTR format, CSysString &resultString)
26{
27 resultString.Empty();
28 int numChars = ::GetDateFormat(locale, flags, time, format, NULL, 0);
29 if (numChars == 0)
30 return false;
31 numChars = ::GetDateFormat(locale, flags, time, format,
32 resultString.GetBuf(numChars), numChars + 1);
33 resultString.ReleaseBuf_CalcLen(numChars);
34 return (numChars != 0);
35}
36
37}}}
diff --git a/CPP/Windows/NationalTime.h b/CPP/Windows/NationalTime.h
new file mode 100644
index 0000000..49b0e5e
--- /dev/null
+++ b/CPP/Windows/NationalTime.h
@@ -0,0 +1,20 @@
1// Windows/NationalTime.h
2
3#ifndef __WINDOWS_NATIONAL_TIME_H
4#define __WINDOWS_NATIONAL_TIME_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NNational {
10namespace NTime {
11
12bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
13 LPCTSTR format, CSysString &resultString);
14
15bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
16 LPCTSTR format, CSysString &resultString);
17
18}}}
19
20#endif
diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp
new file mode 100644
index 0000000..2a3952a
--- /dev/null
+++ b/CPP/Windows/Net.cpp
@@ -0,0 +1,370 @@
1// Windows/Net.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/MyBuffer.h"
6
7#ifndef _UNICODE
8#include "../Common/StringConvert.h"
9#endif
10
11#include "Net.h"
12
13#ifndef _UNICODE
14extern bool g_IsNT;
15#endif
16
17namespace NWindows {
18namespace NNet {
19
20DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource)
21{
22 Close();
23 DWORD result = ::WNetOpenEnum(scope, type, usage, netResource, &_handle);
24 _handleAllocated = (result == NO_ERROR);
25 return result;
26}
27
28#ifndef _UNICODE
29DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource)
30{
31 Close();
32 DWORD result = ::WNetOpenEnumW(scope, type, usage, netResource, &_handle);
33 _handleAllocated = (result == NO_ERROR);
34 return result;
35}
36#endif
37
38static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srcString)
39{
40 defined = (srcString != 0);
41 if (defined)
42 destString = srcString;
43 else
44 destString.Empty();
45}
46
47static void ConvertNETRESOURCEToCResource(const NETRESOURCE &netResource, CResource &resource)
48{
49 resource.Scope = netResource.dwScope;
50 resource.Type = netResource.dwType;
51 resource.DisplayType = netResource.dwDisplayType;
52 resource.Usage = netResource.dwUsage;
53 SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName);
54 SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName);
55 SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment);
56 SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider);
57}
58
59static void SetComplexString2(LPTSTR *destString, bool defined, const CSysString &srcString)
60{
61 if (defined)
62 *destString = srcString.Ptr_non_const();
63 else
64 *destString = NULL;
65}
66
67static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE &netResource)
68{
69 netResource.dwScope = resource.Scope;
70 netResource.dwType = resource.Type;
71 netResource.dwDisplayType = resource.DisplayType;
72 netResource.dwUsage = resource.Usage;
73 SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName);
74 SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName);
75 SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment);
76 SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider);
77}
78
79#ifndef _UNICODE
80
81static void SetComplexString(bool &defined, UString &destString, LPCWSTR src)
82{
83 defined = (src != NULL);
84 if (defined)
85 destString = src;
86 else
87 destString.Empty();
88}
89
90static void ConvertNETRESOURCEToCResource(const NETRESOURCEW &netResource, CResourceW &resource)
91{
92 resource.Scope = netResource.dwScope;
93 resource.Type = netResource.dwType;
94 resource.DisplayType = netResource.dwDisplayType;
95 resource.Usage = netResource.dwUsage;
96 SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName);
97 SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName);
98 SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment);
99 SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider);
100}
101
102static void SetComplexString2(LPWSTR *destString, bool defined, const UString &srcString)
103{
104 if (defined)
105 *destString = srcString.Ptr_non_const();
106 else
107 *destString = NULL;
108}
109
110static void ConvertCResourceToNETRESOURCE(const CResourceW &resource, NETRESOURCEW &netResource)
111{
112 netResource.dwScope = resource.Scope;
113 netResource.dwType = resource.Type;
114 netResource.dwDisplayType = resource.DisplayType;
115 netResource.dwUsage = resource.Usage;
116 SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName);
117 SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName);
118 SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment);
119 SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider);
120}
121
122static void ConvertResourceWToResource(const CResourceW &resourceW, CResource &resource)
123{
124 *(CResourceBase *)&resource = *(CResourceBase *)&resourceW;
125 resource.LocalName = GetSystemString(resourceW.LocalName);
126 resource.RemoteName = GetSystemString(resourceW.RemoteName);
127 resource.Comment = GetSystemString(resourceW.Comment);
128 resource.Provider = GetSystemString(resourceW.Provider);
129}
130
131static void ConvertResourceToResourceW(const CResource &resource, CResourceW &resourceW)
132{
133 *(CResourceBase *)&resourceW = *(CResourceBase *)&resource;
134 resourceW.LocalName = GetUnicodeString(resource.LocalName);
135 resourceW.RemoteName = GetUnicodeString(resource.RemoteName);
136 resourceW.Comment = GetUnicodeString(resource.Comment);
137 resourceW.Provider = GetUnicodeString(resource.Provider);
138}
139#endif
140
141DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource)
142{
143 NETRESOURCE netResource;
144 LPNETRESOURCE pointer = NULL;
145 if (resource)
146 {
147 ConvertCResourceToNETRESOURCE(*resource, netResource);
148 pointer = &netResource;
149 }
150 return Open(scope, type, usage, pointer);
151}
152
153#ifndef _UNICODE
154DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource)
155{
156 if (g_IsNT)
157 {
158 NETRESOURCEW netResource;
159 LPNETRESOURCEW pointer = NULL;
160 if (resource)
161 {
162 ConvertCResourceToNETRESOURCE(*resource, netResource);
163 pointer = &netResource;
164 }
165 return Open(scope, type, usage, pointer);
166 }
167 CResource resourceA;
168 CResource *pointer = NULL;
169 if (resource)
170 {
171 ConvertResourceWToResource(*resource, resourceA);
172 pointer = &resourceA;
173 }
174 return Open(scope, type, usage, pointer);
175}
176#endif
177
178DWORD CEnum::Close()
179{
180 if (!_handleAllocated)
181 return NO_ERROR;
182 DWORD result = ::WNetCloseEnum(_handle);
183 _handleAllocated = (result != NO_ERROR);
184 return result;
185}
186
187DWORD CEnum::Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
188{
189 return ::WNetEnumResource(_handle, lpcCount, lpBuffer, lpBufferSize);
190}
191
192#ifndef _UNICODE
193DWORD CEnum::NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
194{
195 return ::WNetEnumResourceW(_handle, lpcCount, lpBuffer, lpBufferSize);
196}
197#endif
198
199DWORD CEnum::Next(CResource &resource)
200{
201 const DWORD kBufferSize = 16384;
202 CByteArr byteBuffer(kBufferSize);
203 LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
204 ZeroMemory(lpnrLocal, kBufferSize);
205 DWORD bufferSize = kBufferSize;
206 DWORD numEntries = 1;
207 DWORD result = Next(&numEntries, lpnrLocal, &bufferSize);
208 if (result != NO_ERROR)
209 return result;
210 if (numEntries != 1)
211 return (DWORD)E_FAIL;
212 ConvertNETRESOURCEToCResource(lpnrLocal[0], resource);
213 return result;
214}
215
216#ifndef _UNICODE
217DWORD CEnum::Next(CResourceW &resource)
218{
219 if (g_IsNT)
220 {
221 const DWORD kBufferSize = 16384;
222 CByteArr byteBuffer(kBufferSize);
223 LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
224 ZeroMemory(lpnrLocal, kBufferSize);
225 DWORD bufferSize = kBufferSize;
226 DWORD numEntries = 1;
227 DWORD result = NextW(&numEntries, lpnrLocal, &bufferSize);
228 if (result != NO_ERROR)
229 return result;
230 if (numEntries != 1)
231 return (DWORD)E_FAIL;
232 ConvertNETRESOURCEToCResource(lpnrLocal[0], resource);
233 return result;
234 }
235 CResource resourceA;
236 DWORD result = Next(resourceA);
237 ConvertResourceToResourceW(resourceA, resource);
238 return result;
239}
240#endif
241
242
243DWORD GetResourceParent(const CResource &resource, CResource &parentResource)
244{
245 const DWORD kBufferSize = 16384;
246 CByteArr byteBuffer(kBufferSize);
247 LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
248 ZeroMemory(lpnrLocal, kBufferSize);
249 DWORD bufferSize = kBufferSize;
250 NETRESOURCE netResource;
251 ConvertCResourceToNETRESOURCE(resource, netResource);
252 DWORD result = ::WNetGetResourceParent(&netResource, lpnrLocal, &bufferSize);
253 if (result != NO_ERROR)
254 return result;
255 ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource);
256 return result;
257}
258
259#ifndef _UNICODE
260DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource)
261{
262 if (g_IsNT)
263 {
264 const DWORD kBufferSize = 16384;
265 CByteArr byteBuffer(kBufferSize);
266 LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
267 ZeroMemory(lpnrLocal, kBufferSize);
268 DWORD bufferSize = kBufferSize;
269 NETRESOURCEW netResource;
270 ConvertCResourceToNETRESOURCE(resource, netResource);
271 DWORD result = ::WNetGetResourceParentW(&netResource, lpnrLocal, &bufferSize);
272 if (result != NO_ERROR)
273 return result;
274 ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource);
275 return result;
276 }
277 CResource resourceA, parentResourceA;
278 ConvertResourceWToResource(resource, resourceA);
279 DWORD result = GetResourceParent(resourceA, parentResourceA);
280 ConvertResourceToResourceW(parentResourceA, parentResource);
281 return result;
282}
283#endif
284
285DWORD GetResourceInformation(const CResource &resource,
286 CResource &destResource, CSysString &systemPathPart)
287{
288 const DWORD kBufferSize = 16384;
289 CByteArr byteBuffer(kBufferSize);
290 LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
291 ZeroMemory(lpnrLocal, kBufferSize);
292 DWORD bufferSize = kBufferSize;
293 NETRESOURCE netResource;
294 ConvertCResourceToNETRESOURCE(resource, netResource);
295 LPTSTR lplpSystem;
296 DWORD result = ::WNetGetResourceInformation(&netResource,
297 lpnrLocal, &bufferSize, &lplpSystem);
298 if (result != NO_ERROR)
299 return result;
300 if (lplpSystem != 0)
301 systemPathPart = lplpSystem;
302 ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource);
303 return result;
304}
305
306#ifndef _UNICODE
307DWORD GetResourceInformation(const CResourceW &resource,
308 CResourceW &destResource, UString &systemPathPart)
309{
310 if (g_IsNT)
311 {
312 const DWORD kBufferSize = 16384;
313 CByteArr byteBuffer(kBufferSize);
314 LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
315 ZeroMemory(lpnrLocal, kBufferSize);
316 DWORD bufferSize = kBufferSize;
317 NETRESOURCEW netResource;
318 ConvertCResourceToNETRESOURCE(resource, netResource);
319 LPWSTR lplpSystem;
320 DWORD result = ::WNetGetResourceInformationW(&netResource,
321 lpnrLocal, &bufferSize, &lplpSystem);
322 if (result != NO_ERROR)
323 return result;
324 if (lplpSystem != 0)
325 systemPathPart = lplpSystem;
326 ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource);
327 return result;
328 }
329 CResource resourceA, destResourceA;
330 ConvertResourceWToResource(resource, resourceA);
331 AString systemPathPartA;
332 DWORD result = GetResourceInformation(resourceA, destResourceA, systemPathPartA);
333 ConvertResourceToResourceW(destResourceA, destResource);
334 systemPathPart = GetUnicodeString(systemPathPartA);
335 return result;
336}
337#endif
338
339DWORD AddConnection2(const CResource &resource,
340 LPCTSTR password, LPCTSTR userName, DWORD flags)
341{
342 NETRESOURCE netResource;
343 ConvertCResourceToNETRESOURCE(resource, netResource);
344 return ::WNetAddConnection2(&netResource,
345 password, userName, flags);
346}
347
348DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags);
349
350#ifndef _UNICODE
351DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags)
352{
353 if (g_IsNT)
354 {
355 NETRESOURCEW netResource;
356 ConvertCResourceToNETRESOURCE(resource, netResource);
357 return ::WNetAddConnection2W(&netResource,password, userName, flags);
358 }
359 CResource resourceA;
360 ConvertResourceWToResource(resource, resourceA);
361 const CSysString passwordA (GetSystemString(password));
362 const CSysString userNameA (GetSystemString(userName));
363 return AddConnection2(resourceA,
364 password ? (LPCTSTR)passwordA: 0,
365 userName ? (LPCTSTR)userNameA: 0,
366 flags);
367}
368#endif
369
370}}
diff --git a/CPP/Windows/Net.h b/CPP/Windows/Net.h
new file mode 100644
index 0000000..7b60b1b
--- /dev/null
+++ b/CPP/Windows/Net.h
@@ -0,0 +1,86 @@
1// Windows/Net.h
2
3#ifndef __WINDOWS_NET_H
4#define __WINDOWS_NET_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9namespace NNet {
10
11struct CResourceBase
12{
13 DWORD Scope;
14 DWORD Type;
15 DWORD DisplayType;
16 DWORD Usage;
17 bool LocalNameIsDefined;
18 bool RemoteNameIsDefined;
19 bool CommentIsDefined;
20 bool ProviderIsDefined;
21};
22
23struct CResource: public CResourceBase
24{
25 CSysString LocalName;
26 CSysString RemoteName;
27 CSysString Comment;
28 CSysString Provider;
29};
30
31#ifdef _UNICODE
32typedef CResource CResourceW;
33#else
34struct CResourceW: public CResourceBase
35{
36 UString LocalName;
37 UString RemoteName;
38 UString Comment;
39 UString Provider;
40};
41#endif
42
43class CEnum
44{
45 HANDLE _handle;
46 bool _handleAllocated;
47 DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource);
48 DWORD Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize);
49 #ifndef _UNICODE
50 DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource);
51 DWORD NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize);
52 #endif
53protected:
54 bool IsHandleAllocated() const { return _handleAllocated; }
55public:
56 CEnum(): _handleAllocated(false) {}
57 ~CEnum() { Close(); }
58 DWORD Close();
59 DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource);
60 DWORD Next(CResource &resource);
61 #ifndef _UNICODE
62 DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource);
63 DWORD Next(CResourceW &resource);
64 #endif
65};
66
67DWORD GetResourceParent(const CResource &resource, CResource &parentResource);
68#ifndef _UNICODE
69DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource);
70#endif
71
72DWORD GetResourceInformation(const CResource &resource,
73 CResource &destResource, CSysString &systemPathPart);
74#ifndef _UNICODE
75DWORD GetResourceInformation(const CResourceW &resource,
76 CResourceW &destResource, UString &systemPathPart);
77#endif
78
79DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags);
80#ifndef _UNICODE
81DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags);
82#endif
83
84}}
85
86#endif
diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h
new file mode 100644
index 0000000..0af3291
--- /dev/null
+++ b/CPP/Windows/NtCheck.h
@@ -0,0 +1,48 @@
1// Windows/NtCheck.h
2
3#ifndef __WINDOWS_NT_CHECK_H
4#define __WINDOWS_NT_CHECK_H
5
6#ifdef _WIN32
7
8#include "../Common/MyWindows.h"
9
10#if !defined(_WIN64) && !defined(UNDER_CE)
11static inline bool IsItWindowsNT()
12{
13 OSVERSIONINFO vi;
14 vi.dwOSVersionInfoSize = sizeof(vi);
15 return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT);
16}
17#endif
18
19#ifndef _UNICODE
20 extern
21 bool g_IsNT;
22 #if defined(_WIN64) || defined(UNDER_CE)
23 bool g_IsNT = true;
24 #define SET_IS_NT
25 #else
26 bool g_IsNT = false;
27 #define SET_IS_NT g_IsNT = IsItWindowsNT();
28 #endif
29 #define NT_CHECK_ACTION
30 // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION }
31#else
32 #if !defined(_WIN64) && !defined(UNDER_CE)
33 #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION }
34 #else
35 #define NT_CHECK_ACTION
36 #endif
37 #define SET_IS_NT
38#endif
39
40#define NT_CHECK NT_CHECK_ACTION SET_IS_NT
41
42#else
43
44#define NT_CHECK
45
46#endif
47
48#endif
diff --git a/CPP/Windows/ProcessMessages.cpp b/CPP/Windows/ProcessMessages.cpp
new file mode 100644
index 0000000..0f48aee
--- /dev/null
+++ b/CPP/Windows/ProcessMessages.cpp
@@ -0,0 +1,22 @@
1// Windows/ProcessMessages.cpp
2
3#include "StdAfx.h"
4
5#include "ProcessMessages.h"
6
7namespace NWindows {
8
9void ProcessMessages(HWND window)
10{
11 MSG msg;
12 while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
13 {
14 if (window == (HWND) NULL || !IsDialogMessage(window, &msg))
15 {
16 TranslateMessage(&msg);
17 DispatchMessage(&msg);
18 }
19 }
20}
21
22}
diff --git a/CPP/Windows/ProcessMessages.h b/CPP/Windows/ProcessMessages.h
new file mode 100644
index 0000000..b2558a0
--- /dev/null
+++ b/CPP/Windows/ProcessMessages.h
@@ -0,0 +1,12 @@
1// Windows/ProcessMessages.h
2
3#ifndef __WINDOWS_PROCESSMESSAGES_H
4#define __WINDOWS_PROCESSMESSAGES_H
5
6namespace NWindows {
7
8void ProcessMessages(HWND window);
9
10}
11
12#endif
diff --git a/CPP/Windows/ProcessUtils.cpp b/CPP/Windows/ProcessUtils.cpp
new file mode 100644
index 0000000..9bf0538
--- /dev/null
+++ b/CPP/Windows/ProcessUtils.cpp
@@ -0,0 +1,102 @@
1// ProcessUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/StringConvert.h"
6
7#include "ProcessUtils.h"
8
9#ifndef _UNICODE
10extern bool g_IsNT;
11#endif
12
13namespace NWindows {
14
15#ifndef UNDER_CE
16static UString GetQuotedString(const UString &s)
17{
18 UString s2 ('\"');
19 s2 += s;
20 s2 += '\"';
21 return s2;
22}
23#endif
24
25WRes CProcess::Create(LPCWSTR imageName, const UString &params, LPCWSTR curDir)
26{
27 /*
28 OutputDebugStringW(L"CProcess::Create");
29 OutputDebugStringW(imageName);
30 if (params)
31 {
32 OutputDebugStringW(L"params:");
33 OutputDebugStringW(params);
34 }
35 if (curDir)
36 {
37 OutputDebugStringW(L"cur dir:");
38 OutputDebugStringW(curDir);
39 }
40 */
41
42 Close();
43 const UString params2 =
44 #ifndef UNDER_CE
45 GetQuotedString(imageName) + L' ' +
46 #endif
47 params;
48 #ifdef UNDER_CE
49 curDir = 0;
50 #else
51 imageName = 0;
52 #endif
53 PROCESS_INFORMATION pi;
54 BOOL result;
55 #ifndef _UNICODE
56 if (!g_IsNT)
57 {
58 STARTUPINFOA si;
59 si.cb = sizeof(si);
60 si.lpReserved = 0;
61 si.lpDesktop = 0;
62 si.lpTitle = 0;
63 si.dwFlags = 0;
64 si.cbReserved2 = 0;
65 si.lpReserved2 = 0;
66
67 CSysString curDirA;
68 if (curDir != 0)
69 curDirA = GetSystemString(curDir);
70 const AString s = GetSystemString(params2);
71 result = ::CreateProcessA(NULL, s.Ptr_non_const(),
72 NULL, NULL, FALSE, 0, NULL, ((curDir != 0) ? (LPCSTR)curDirA: 0), &si, &pi);
73 }
74 else
75 #endif
76 {
77 STARTUPINFOW si;
78 si.cb = sizeof(si);
79 si.lpReserved = 0;
80 si.lpDesktop = 0;
81 si.lpTitle = 0;
82 si.dwFlags = 0;
83 si.cbReserved2 = 0;
84 si.lpReserved2 = 0;
85
86 result = CreateProcessW(imageName, params2.Ptr_non_const(),
87 NULL, NULL, FALSE, 0, NULL, curDir, &si, &pi);
88 }
89 if (result == 0)
90 return ::GetLastError();
91 ::CloseHandle(pi.hThread);
92 _handle = pi.hProcess;
93 return 0;
94}
95
96WRes MyCreateProcess(LPCWSTR imageName, const UString &params)
97{
98 CProcess process;
99 return process.Create(imageName, params, 0);
100}
101
102}
diff --git a/CPP/Windows/ProcessUtils.h b/CPP/Windows/ProcessUtils.h
new file mode 100644
index 0000000..e46f9ab
--- /dev/null
+++ b/CPP/Windows/ProcessUtils.h
@@ -0,0 +1,100 @@
1// Windows/ProcessUtils.h
2
3#ifndef __WINDOWS_PROCESS_UTILS_H
4#define __WINDOWS_PROCESS_UTILS_H
5
6#include <Psapi.h>
7
8#include "../Common/MyString.h"
9
10#include "Defs.h"
11#include "Handle.h"
12
13namespace NWindows {
14
15class CProcess: public CHandle
16{
17public:
18 bool Open(DWORD desiredAccess, bool inheritHandle, DWORD processId)
19 {
20 _handle = ::OpenProcess(desiredAccess, inheritHandle, processId);
21 return (_handle != 0);
22 }
23
24 #ifndef UNDER_CE
25
26 bool GetExitCodeProcess(LPDWORD lpExitCode) { return BOOLToBool(::GetExitCodeProcess(_handle, lpExitCode)); }
27 bool Terminate(UINT exitCode) { return BOOLToBool(::TerminateProcess(_handle, exitCode)); }
28 #if (WINVER >= 0x0500)
29 DWORD GetGuiResources (DWORD uiFlags) { return ::GetGuiResources(_handle, uiFlags); }
30 #endif
31 bool SetPriorityClass(DWORD dwPriorityClass) { return BOOLToBool(::SetPriorityClass(_handle, dwPriorityClass)); }
32 DWORD GetPriorityClass() { return ::GetPriorityClass(_handle); }
33 // bool GetIoCounters(PIO_COUNTERS lpIoCounters ) { return BOOLToBool(::GetProcessIoCounters(_handle, lpIoCounters )); }
34
35 bool GetTimes(LPFILETIME creationTime, LPFILETIME exitTime, LPFILETIME kernelTime, LPFILETIME userTime)
36 { return BOOLToBool(::GetProcessTimes(_handle, creationTime, exitTime, kernelTime, userTime)); }
37
38 DWORD WaitForInputIdle(DWORD milliseconds) { return ::WaitForInputIdle(_handle, milliseconds); }
39
40 // Debug
41
42 bool ReadMemory(LPCVOID baseAddress, LPVOID buffer, SIZE_T size, SIZE_T* numberOfBytesRead)
43 { return BOOLToBool(::ReadProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesRead)); }
44
45 bool WriteMemory(LPVOID baseAddress, LPCVOID buffer, SIZE_T size, SIZE_T* numberOfBytesWritten)
46 { return BOOLToBool(::WriteProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesWritten)); }
47
48 bool FlushInstructionCache(LPCVOID baseAddress = 0, SIZE_T size = 0)
49 { return BOOLToBool(::FlushInstructionCache(_handle, baseAddress, size)); }
50
51 LPVOID VirtualAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect)
52 { return VirtualAllocEx(_handle, address, size, allocationType, protect); }
53
54 bool VirtualFree(LPVOID address, SIZE_T size, DWORD freeType)
55 { return BOOLToBool(::VirtualFreeEx(_handle, address, size, freeType)); }
56
57 // Process Status API (PSAPI)
58
59 bool EmptyWorkingSet()
60 { return BOOLToBool(::EmptyWorkingSet(_handle)); }
61 bool EnumModules(HMODULE *hModules, DWORD arraySizeInBytes, LPDWORD receivedBytes)
62 { return BOOLToBool(::EnumProcessModules(_handle, hModules, arraySizeInBytes, receivedBytes)); }
63
64 DWORD MyGetModuleBaseName(HMODULE hModule, LPTSTR baseName, DWORD size)
65 { return ::GetModuleBaseName(_handle, hModule, baseName, size); }
66 bool MyGetModuleBaseName(HMODULE hModule, CSysString &name)
67 {
68 const unsigned len = MAX_PATH + 100;
69 DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuf(len), len);
70 name.ReleaseBuf_CalcLen(len);
71 return (resultLen != 0);
72 }
73
74 DWORD MyGetModuleFileNameEx(HMODULE hModule, LPTSTR baseName, DWORD size)
75 { return ::GetModuleFileNameEx(_handle, hModule, baseName, size); }
76 bool MyGetModuleFileNameEx(HMODULE hModule, CSysString &name)
77 {
78 const unsigned len = MAX_PATH + 100;
79 DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuf(len), len);
80 name.ReleaseBuf_CalcLen(len);
81 return (resultLen != 0);
82 }
83
84 bool GetModuleInformation(HMODULE hModule, LPMODULEINFO moduleInfo)
85 { return BOOLToBool(::GetModuleInformation(_handle, hModule, moduleInfo, sizeof(MODULEINFO))); }
86 bool GetMemoryInfo(PPROCESS_MEMORY_COUNTERS memCounters)
87 { return BOOLToBool(::GetProcessMemoryInfo(_handle, memCounters, sizeof(PROCESS_MEMORY_COUNTERS))); }
88
89 #endif
90
91 WRes Create(LPCWSTR imageName, const UString &params, LPCWSTR curDir);
92
93 DWORD Wait() { return ::WaitForSingleObject(_handle, INFINITE); }
94};
95
96WRes MyCreateProcess(LPCWSTR imageName, const UString &params);
97
98}
99
100#endif
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
new file mode 100644
index 0000000..6e43c7b
--- /dev/null
+++ b/CPP/Windows/PropVariant.cpp
@@ -0,0 +1,361 @@
1// Windows/PropVariant.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/Defs.h"
6
7#include "PropVariant.h"
8
9namespace NWindows {
10namespace NCOM {
11
12BSTR AllocBstrFromAscii(const char *s) throw()
13{
14 if (!s)
15 return NULL;
16 UINT len = (UINT)strlen(s);
17 BSTR p = ::SysAllocStringLen(NULL, len);
18 if (p)
19 {
20 for (UINT i = 0; i <= len; i++)
21 p[i] = (Byte)s[i];
22 }
23 return p;
24}
25
26HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()
27{
28 p->bstrVal = ::SysAllocStringLen(NULL, numChars);
29 if (!p->bstrVal)
30 {
31 p->vt = VT_ERROR;
32 p->scode = E_OUTOFMEMORY;
33 return E_OUTOFMEMORY;
34 }
35 p->vt = VT_BSTR;
36 return S_OK;
37}
38
39HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
40{
41 p->bstrVal = AllocBstrFromAscii(s);
42 if (p->bstrVal)
43 {
44 p->vt = VT_BSTR;
45 return S_OK;
46 }
47 p->vt = VT_ERROR;
48 p->scode = E_OUTOFMEMORY;
49 return E_OUTOFMEMORY;
50}
51
52CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
53{
54 vt = VT_EMPTY;
55 InternalCopy(&varSrc);
56}
57
58CPropVariant::CPropVariant(const CPropVariant &varSrc)
59{
60 vt = VT_EMPTY;
61 InternalCopy(&varSrc);
62}
63
64CPropVariant::CPropVariant(BSTR bstrSrc)
65{
66 vt = VT_EMPTY;
67 *this = bstrSrc;
68}
69
70CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
71{
72 vt = VT_EMPTY;
73 *this = lpszSrc;
74}
75
76CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
77{
78 InternalCopy(&varSrc);
79 return *this;
80}
81
82CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
83{
84 InternalCopy(&varSrc);
85 return *this;
86}
87
88CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
89{
90 *this = (LPCOLESTR)bstrSrc;
91 return *this;
92}
93
94static const char * const kMemException = "out of memory";
95
96CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
97{
98 InternalClear();
99 vt = VT_BSTR;
100 wReserved1 = 0;
101 bstrVal = ::SysAllocString(lpszSrc);
102 if (!bstrVal && lpszSrc)
103 {
104 throw kMemException;
105 // vt = VT_ERROR;
106 // scode = E_OUTOFMEMORY;
107 }
108 return *this;
109}
110
111CPropVariant& CPropVariant::operator=(const UString &s)
112{
113 InternalClear();
114 vt = VT_BSTR;
115 wReserved1 = 0;
116 bstrVal = ::SysAllocStringLen(s, s.Len());
117 if (!bstrVal)
118 throw kMemException;
119 return *this;
120}
121
122CPropVariant& CPropVariant::operator=(const UString2 &s)
123{
124 /*
125 if (s.IsEmpty())
126 *this = L"";
127 else
128 */
129 {
130 InternalClear();
131 vt = VT_BSTR;
132 wReserved1 = 0;
133 bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
134 if (!bstrVal)
135 throw kMemException;
136 /* SysAllocStringLen probably appends a null-terminating character for NULL string.
137 But it doesn't specified in MSDN.
138 But we suppose that it works
139
140 if (!s.GetRawPtr())
141 {
142 *bstrVal = 0;
143 }
144 */
145
146 /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
147 pointers to this function causes an unexpected termination of the application.
148 Is it safe? Maybe we must chamnge the code for that case ? */
149 }
150 return *this;
151}
152
153CPropVariant& CPropVariant::operator=(const char *s)
154{
155 InternalClear();
156 vt = VT_BSTR;
157 wReserved1 = 0;
158 bstrVal = AllocBstrFromAscii(s);
159 if (!bstrVal)
160 {
161 throw kMemException;
162 // vt = VT_ERROR;
163 // scode = E_OUTOFMEMORY;
164 }
165 return *this;
166}
167
168CPropVariant& CPropVariant::operator=(bool bSrc) throw()
169{
170 if (vt != VT_BOOL)
171 {
172 InternalClear();
173 vt = VT_BOOL;
174 }
175 boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
176 return *this;
177}
178
179BSTR CPropVariant::AllocBstr(unsigned numChars)
180{
181 if (vt != VT_EMPTY)
182 InternalClear();
183 vt = VT_BSTR;
184 wReserved1 = 0;
185 bstrVal = ::SysAllocStringLen(NULL, numChars);
186 if (!bstrVal)
187 {
188 throw kMemException;
189 // vt = VT_ERROR;
190 // scode = E_OUTOFMEMORY;
191 }
192 return bstrVal;
193}
194
195#define SET_PROP_id_dest(id, dest) \
196 if (vt != id) { InternalClear(); vt = id; } dest = value;
197
198void CPropVariant::Set_Int32(Int32 value) throw()
199{
200 SET_PROP_id_dest(VT_I4, lVal);
201}
202
203void CPropVariant::Set_Int64(Int64 value) throw()
204{
205 SET_PROP_id_dest(VT_I8, hVal.QuadPart);
206}
207
208#define SET_PROP_FUNC(type, id, dest) \
209 CPropVariant& CPropVariant::operator=(type value) throw() \
210 { SET_PROP_id_dest(id, dest); return *this; }
211
212SET_PROP_FUNC(Byte, VT_UI1, bVal)
213// SET_PROP_FUNC(Int16, VT_I2, iVal)
214// SET_PROP_FUNC(Int32, VT_I4, lVal)
215SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
216SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
217// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
218SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
219
220HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
221{
222 switch (prop->vt)
223 {
224 case VT_EMPTY:
225 case VT_UI1:
226 case VT_I1:
227 case VT_I2:
228 case VT_UI2:
229 case VT_BOOL:
230 case VT_I4:
231 case VT_UI4:
232 case VT_R4:
233 case VT_INT:
234 case VT_UINT:
235 case VT_ERROR:
236 case VT_FILETIME:
237 case VT_UI8:
238 case VT_R8:
239 case VT_CY:
240 case VT_DATE:
241 prop->vt = VT_EMPTY;
242 prop->wReserved1 = 0;
243 prop->wReserved2 = 0;
244 prop->wReserved3 = 0;
245 prop->uhVal.QuadPart = 0;
246 return S_OK;
247 }
248 return ::VariantClear((VARIANTARG *)prop);
249 // return ::PropVariantClear(prop);
250 // PropVariantClear can clear VT_BLOB.
251}
252
253HRESULT CPropVariant::Clear() throw()
254{
255 if (vt == VT_EMPTY)
256 return S_OK;
257 return PropVariant_Clear(this);
258}
259
260HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
261{
262 ::VariantClear((tagVARIANT *)this);
263 switch (pSrc->vt)
264 {
265 case VT_UI1:
266 case VT_I1:
267 case VT_I2:
268 case VT_UI2:
269 case VT_BOOL:
270 case VT_I4:
271 case VT_UI4:
272 case VT_R4:
273 case VT_INT:
274 case VT_UINT:
275 case VT_ERROR:
276 case VT_FILETIME:
277 case VT_UI8:
278 case VT_R8:
279 case VT_CY:
280 case VT_DATE:
281 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
282 return S_OK;
283 }
284 return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
285}
286
287
288HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
289{
290 HRESULT hr = Clear();
291 if (FAILED(hr))
292 return hr;
293 // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
294 *(PROPVARIANT *)this = *pSrc;
295 pSrc->vt = VT_EMPTY;
296 return S_OK;
297}
298
299HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
300{
301 if (pDest->vt != VT_EMPTY)
302 {
303 HRESULT hr = PropVariant_Clear(pDest);
304 if (FAILED(hr))
305 return hr;
306 }
307 // memcpy(pDest, this, sizeof(PROPVARIANT));
308 *pDest = *(PROPVARIANT *)this;
309 vt = VT_EMPTY;
310 return S_OK;
311}
312
313HRESULT CPropVariant::InternalClear() throw()
314{
315 if (vt == VT_EMPTY)
316 return S_OK;
317 HRESULT hr = Clear();
318 if (FAILED(hr))
319 {
320 vt = VT_ERROR;
321 scode = hr;
322 }
323 return hr;
324}
325
326void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
327{
328 HRESULT hr = Copy(pSrc);
329 if (FAILED(hr))
330 {
331 if (hr == E_OUTOFMEMORY)
332 throw kMemException;
333 vt = VT_ERROR;
334 scode = hr;
335 }
336}
337
338int CPropVariant::Compare(const CPropVariant &a) throw()
339{
340 if (vt != a.vt)
341 return MyCompare(vt, a.vt);
342 switch (vt)
343 {
344 case VT_EMPTY: return 0;
345 // case VT_I1: return MyCompare(cVal, a.cVal);
346 case VT_UI1: return MyCompare(bVal, a.bVal);
347 case VT_I2: return MyCompare(iVal, a.iVal);
348 case VT_UI2: return MyCompare(uiVal, a.uiVal);
349 case VT_I4: return MyCompare(lVal, a.lVal);
350 case VT_UI4: return MyCompare(ulVal, a.ulVal);
351 // case VT_UINT: return MyCompare(uintVal, a.uintVal);
352 case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
353 case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
354 case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
355 case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
356 case VT_BSTR: return 0; // Not implemented
357 default: return 0;
358 }
359}
360
361}}
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
new file mode 100644
index 0000000..108bf6b
--- /dev/null
+++ b/CPP/Windows/PropVariant.h
@@ -0,0 +1,127 @@
1// Windows/PropVariant.h
2
3#ifndef __WINDOWS_PROP_VARIANT_H
4#define __WINDOWS_PROP_VARIANT_H
5
6#include "../Common/MyTypes.h"
7#include "../Common/MyWindows.h"
8#include "../Common/MyString.h"
9
10namespace NWindows {
11namespace NCOM {
12
13BSTR AllocBstrFromAscii(const char *s) throw();
14
15HRESULT PropVariant_Clear(PROPVARIANT *p) throw();
16
17HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw();
18HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw();
19
20inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw()
21{
22 p->vt = VT_UI4;
23 p->ulVal = v;
24}
25
26inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw()
27{
28 p->vt = VT_UI8;
29 p->uhVal.QuadPart = v;
30}
31
32inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw()
33{
34 p->vt = VT_FILETIME;
35 p->filetime.dwLowDateTime = (DWORD)v;
36 p->filetime.dwHighDateTime = (DWORD)(v >> 32);
37}
38
39inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw()
40{
41 p->vt = VT_BOOL;
42 p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE);
43}
44
45
46class CPropVariant : public tagPROPVARIANT
47{
48 // ---------- forbidden functions ----------
49 CPropVariant(const char *s);
50 // CPropVariant(const UString &s);
51 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
52 CPropVariant(const FString &s);
53 CPropVariant& operator=(const FString &s);
54 #endif
55
56public:
57 CPropVariant()
58 {
59 vt = VT_EMPTY;
60 wReserved1 = 0;
61 // wReserved2 = 0;
62 // wReserved3 = 0;
63 // uhVal.QuadPart = 0;
64 bstrVal = 0;
65 }
66 ~CPropVariant() throw() { Clear(); }
67 CPropVariant(const PROPVARIANT &varSrc);
68 CPropVariant(const CPropVariant &varSrc);
69 CPropVariant(BSTR bstrSrc);
70 CPropVariant(LPCOLESTR lpszSrc);
71 CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }
72 CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
73
74private:
75 CPropVariant(UInt16 value); // { vt = VT_UI2; wReserved1 = 0; uiVal = value; }
76 CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; }
77 CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; }
78 CPropVariant(Int64 value); // { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; }
79
80public:
81 CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }
82 CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }
83 CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }
84
85 CPropVariant& operator=(const CPropVariant &varSrc);
86 CPropVariant& operator=(const PROPVARIANT &varSrc);
87 CPropVariant& operator=(BSTR bstrSrc);
88 CPropVariant& operator=(LPCOLESTR lpszSrc);
89 CPropVariant& operator=(const UString &s);
90 CPropVariant& operator=(const UString2 &s);
91 CPropVariant& operator=(const char *s);
92 CPropVariant& operator=(const AString &s)
93 { return (*this)=(const char *)s; }
94
95 CPropVariant& operator=(bool bSrc) throw();
96 CPropVariant& operator=(Byte value) throw();
97
98private:
99 CPropVariant& operator=(Int16 value) throw();
100 CPropVariant& operator=(UInt16 value) throw();
101 CPropVariant& operator=(Int32 value) throw();
102 CPropVariant& operator=(Int64 value) throw();
103
104public:
105 CPropVariant& operator=(UInt32 value) throw();
106 CPropVariant& operator=(UInt64 value) throw();
107 CPropVariant& operator=(const FILETIME &value) throw();
108
109 void Set_Int32(Int32 value) throw();
110 void Set_Int64(Int64 value) throw();
111
112 BSTR AllocBstr(unsigned numChars);
113
114 HRESULT Clear() throw();
115 HRESULT Copy(const PROPVARIANT *pSrc) throw();
116 HRESULT Attach(PROPVARIANT *pSrc) throw();
117 HRESULT Detach(PROPVARIANT *pDest) throw();
118
119 HRESULT InternalClear() throw();
120 void InternalCopy(const PROPVARIANT *pSrc);
121
122 int Compare(const CPropVariant &a) throw();
123};
124
125}}
126
127#endif
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
new file mode 100644
index 0000000..b58d37e
--- /dev/null
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -0,0 +1,138 @@
1// PropVariantConv.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/IntToString.h"
6
7#include "Defs.h"
8#include "PropVariantConv.h"
9
10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
11
12bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
13{
14 *s = 0;
15 FILETIME ft;
16 if (!FileTimeToLocalFileTime(&utc, &ft))
17 return false;
18
19 SYSTEMTIME st;
20 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
21 return false;
22
23 {
24 unsigned val = st.wYear;
25 if (val >= 10000)
26 {
27 *s++ = (char)('0' + val / 10000);
28 val %= 10000;
29 }
30 s[3] = (char)('0' + val % 10); val /= 10;
31 s[2] = (char)('0' + val % 10); val /= 10;
32 s[1] = (char)('0' + val % 10);
33 s[0] = (char)('0' + val / 10);
34 s += 4;
35 }
36 UINT_TO_STR_2('-', st.wMonth);
37 UINT_TO_STR_2('-', st.wDay);
38
39 if (level > kTimestampPrintLevel_DAY)
40 {
41 UINT_TO_STR_2(' ', st.wHour);
42 UINT_TO_STR_2(':', st.wMinute);
43
44 if (level >= kTimestampPrintLevel_SEC)
45 {
46 UINT_TO_STR_2(':', st.wSecond);
47
48 if (level > kTimestampPrintLevel_SEC)
49 {
50 *s++ = '.';
51 /*
52 {
53 unsigned val = st.wMilliseconds;
54 s[2] = (char)('0' + val % 10); val /= 10;
55 s[1] = (char)('0' + val % 10);
56 s[0] = (char)('0' + val / 10);
57 s += 3;
58 }
59 *s++ = ' ';
60 */
61
62 {
63 unsigned numDigits = 7;
64 UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);
65 for (unsigned i = numDigits; i != 0;)
66 {
67 i--;
68 s[i] = (char)('0' + val % 10); val /= 10;
69 }
70 if (numDigits > (unsigned)level)
71 numDigits = (unsigned)level;
72 s += numDigits;
73 }
74 }
75 }
76 }
77
78 *s = 0;
79 return true;
80}
81
82
83bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
84{
85 char s[32];
86 bool res = ConvertUtcFileTimeToString(ft, s, level);
87 for (unsigned i = 0;; i++)
88 {
89 Byte c = (Byte)s[i];
90 dest[i] = c;
91 if (c == 0)
92 break;
93 }
94 return res;
95}
96
97
98void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()
99{
100 *dest = 0;
101 switch (prop.vt)
102 {
103 case VT_EMPTY: return;
104 case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
105 case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
106 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
107 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
108 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
109 case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return;
110 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
111 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
112 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
113 case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
114 case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
115 default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);
116 }
117}
118
119void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()
120{
121 *dest = 0;
122 switch (prop.vt)
123 {
124 case VT_EMPTY: return;
125 case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
126 case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
127 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
128 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
129 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
130 case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return;
131 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
132 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
133 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
134 case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
135 case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
136 default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
137 }
138}
diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h
new file mode 100644
index 0000000..390e0b8
--- /dev/null
+++ b/CPP/Windows/PropVariantConv.h
@@ -0,0 +1,37 @@
1// Windows/PropVariantConv.h
2
3#ifndef __PROP_VARIANT_CONV_H
4#define __PROP_VARIANT_CONV_H
5
6#include "../Common/MyTypes.h"
7
8// provide at least 32 bytes for buffer including zero-end
9
10#define kTimestampPrintLevel_DAY -3
11// #define kTimestampPrintLevel_HOUR -2
12#define kTimestampPrintLevel_MIN -1
13#define kTimestampPrintLevel_SEC 0
14#define kTimestampPrintLevel_NTFS 7
15
16bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw();
17bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
18
19// provide at least 32 bytes for buffer including zero-end
20// don't send VT_BSTR to these functions
21void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw();
22void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw();
23
24inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value)
25{
26 switch (prop.vt)
27 {
28 case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true;
29 case VT_UI4: value = prop.ulVal; return true;
30 case VT_UI2: value = prop.uiVal; return true;
31 case VT_UI1: value = prop.bVal; return true;
32 case VT_EMPTY: return false;
33 default: throw 151199;
34 }
35}
36
37#endif
diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp
new file mode 100644
index 0000000..6daee83
--- /dev/null
+++ b/CPP/Windows/PropVariantUtils.cpp
@@ -0,0 +1,161 @@
1// PropVariantUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/IntToString.h"
6
7#include "PropVariantUtils.h"
8
9using namespace NWindows;
10
11static void AddHex(AString &s, UInt32 v)
12{
13 char sz[16];
14 sz[0] = '0';
15 sz[1] = 'x';
16 ConvertUInt32ToHex(v, sz + 2);
17 s += sz;
18}
19
20
21AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)
22{
23 char sz[16];
24 const char *p = NULL;
25 for (unsigned i = 0; i < num; i++)
26 {
27 const CUInt32PCharPair &pair = pairs[i];
28 if (pair.Value == value)
29 p = pair.Name;
30 }
31 if (!p)
32 {
33 ConvertUInt32ToString(value, sz);
34 p = sz;
35 }
36 return (AString)p;
37}
38
39void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop)
40{
41 prop = TypePairToString(pairs, num, value);
42}
43
44
45AString TypeToString(const char * const table[], unsigned num, UInt32 value)
46{
47 char sz[16];
48 const char *p = NULL;
49 if (value < num)
50 p = table[value];
51 if (!p)
52 {
53 ConvertUInt32ToString(value, sz);
54 p = sz;
55 }
56 return (AString)p;
57}
58
59void TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop)
60{
61 char sz[16];
62 const char *p = NULL;
63 if (value < num)
64 p = table[value];
65 if (!p)
66 {
67 ConvertUInt32ToString(value, sz);
68 p = sz;
69 }
70 prop = p;
71}
72
73
74AString FlagsToString(const char * const *names, unsigned num, UInt32 flags)
75{
76 AString s;
77 for (unsigned i = 0; i < num; i++)
78 {
79 UInt32 flag = (UInt32)1 << i;
80 if ((flags & flag) != 0)
81 {
82 const char *name = names[i];
83 if (name && name[0] != 0)
84 {
85 s.Add_OptSpaced(name);
86 flags &= ~flag;
87 }
88 }
89 }
90 if (flags != 0)
91 {
92 s.Add_Space_if_NotEmpty();
93 AddHex(s, flags);
94 }
95 return s;
96}
97
98AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags)
99{
100 AString s;
101 for (unsigned i = 0; i < num; i++)
102 {
103 const CUInt32PCharPair &p = pairs[i];
104 UInt32 flag = (UInt32)1 << (unsigned)p.Value;
105 if ((flags & flag) != 0)
106 {
107 if (p.Name[0] != 0)
108 s.Add_OptSpaced(p.Name);
109 }
110 flags &= ~flag;
111 }
112 if (flags != 0)
113 {
114 s.Add_Space_if_NotEmpty();
115 AddHex(s, flags);
116 }
117 return s;
118}
119
120void FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NCOM::CPropVariant &prop)
121{
122 prop = FlagsToString(names, num, flags);
123}
124
125void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop)
126{
127 prop = FlagsToString(pairs, num, flags);
128}
129
130
131static AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags)
132{
133 AString s;
134 for (unsigned i = 0; i < num; i++)
135 {
136 const CUInt32PCharPair &p = pairs[i];
137 UInt64 flag = (UInt64)1 << (unsigned)p.Value;
138 if ((flags & flag) != 0)
139 {
140 if (p.Name[0] != 0)
141 s.Add_OptSpaced(p.Name);
142 }
143 flags &= ~flag;
144 }
145 if (flags != 0)
146 {
147 {
148 char sz[32];
149 sz[0] = '0';
150 sz[1] = 'x';
151 ConvertUInt64ToHex(flags, sz + 2);
152 s.Add_OptSpaced(sz);
153 }
154 }
155 return s;
156}
157
158void Flags64ToProp(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags, NCOM::CPropVariant &prop)
159{
160 prop = Flags64ToString(pairs, num, flags);
161}
diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h
new file mode 100644
index 0000000..3dd8295
--- /dev/null
+++ b/CPP/Windows/PropVariantUtils.h
@@ -0,0 +1,34 @@
1// Windows/PropVariantUtils.h
2
3#ifndef __PROP_VARIANT_UTILS_H
4#define __PROP_VARIANT_UTILS_H
5
6#include "../Common/MyString.h"
7
8#include "PropVariant.h"
9
10struct CUInt32PCharPair
11{
12 UInt32 Value;
13 const char *Name;
14};
15
16AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value);
17void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
18
19AString FlagsToString(const char * const *names, unsigned num, UInt32 flags);
20AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags);
21void FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);
22void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);
23
24AString TypeToString(const char * const table[], unsigned num, UInt32 value);
25void TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
26
27#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, ARRAY_SIZE(pairs), value, prop)
28#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, ARRAY_SIZE(pairs), value, prop)
29#define TYPE_TO_PROP(table, value, prop) TypeToProp(table, ARRAY_SIZE(table), value, prop)
30
31void Flags64ToProp(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags, NWindows::NCOM::CPropVariant &prop);
32#define FLAGS64_TO_PROP(pairs, value, prop) Flags64ToProp(pairs, ARRAY_SIZE(pairs), value, prop)
33
34#endif
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
new file mode 100644
index 0000000..b20157d
--- /dev/null
+++ b/CPP/Windows/Registry.cpp
@@ -0,0 +1,406 @@
1// Windows/Registry.cpp
2
3#include "StdAfx.h"
4
5#include <wchar.h>
6// #include <stdio.h>
7
8#ifndef _UNICODE
9#include "../Common/StringConvert.h"
10#endif
11#include "Registry.h"
12
13#ifndef _UNICODE
14extern bool g_IsNT;
15#endif
16
17namespace NWindows {
18namespace NRegistry {
19
20#define MYASSERT(expr) // _ASSERTE(expr)
21#define MY_ASSUME(expr)
22
23/*
24static void Error()
25{
26 #ifdef _CONSOLE
27 printf("\nregistry error\n");
28 #else
29 MessageBoxW(0, L"registry error", L"", 0);
30 // exit(1);
31 #endif
32}
33
34#define MY_ASSUME(expr) { if (!(expr)) Error(); }
35*/
36
37LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,
38 LPTSTR keyClass, DWORD options, REGSAM accessMask,
39 LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw()
40{
41 MY_ASSUME(parentKey != NULL);
42 DWORD dispositionReal;
43 HKEY key = NULL;
44 LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,
45 options, accessMask, securityAttributes, &key, &dispositionReal);
46 if (disposition != NULL)
47 *disposition = dispositionReal;
48 if (res == ERROR_SUCCESS)
49 {
50 res = Close();
51 _object = key;
52 }
53 return res;
54}
55
56LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw()
57{
58 MY_ASSUME(parentKey != NULL);
59 HKEY key = NULL;
60 LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);
61 if (res == ERROR_SUCCESS)
62 {
63 res = Close();
64 MYASSERT(res == ERROR_SUCCESS);
65 _object = key;
66 }
67 return res;
68}
69
70LONG CKey::Close() throw()
71{
72 LONG res = ERROR_SUCCESS;
73 if (_object != NULL)
74 {
75 res = RegCloseKey(_object);
76 _object = NULL;
77 }
78 return res;
79}
80
81// win95, win98: deletes sunkey and all its subkeys
82// winNT to be deleted must not have subkeys
83LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()
84{
85 MY_ASSUME(_object != NULL);
86 return RegDeleteKey(_object, subKeyName);
87}
88
89LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()
90{
91 CKey key;
92 LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);
93 if (res != ERROR_SUCCESS)
94 return res;
95 FILETIME fileTime;
96 const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL
97 DWORD size = kBufSize;
98 TCHAR buffer[kBufSize];
99 while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)
100 {
101 res = key.RecurseDeleteKey(buffer);
102 if (res != ERROR_SUCCESS)
103 return res;
104 size = kBufSize;
105 }
106 key.Close();
107 return DeleteSubKey(subKeyName);
108}
109
110
111/////////////////////////
112// Value Functions
113
114static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); }
115static inline bool UINT32ToBool(UInt32 value) { return (value != 0); }
116
117
118LONG CKey::DeleteValue(LPCTSTR name) throw()
119{
120 MY_ASSUME(_object != NULL);
121 return ::RegDeleteValue(_object, name);
122}
123
124#ifndef _UNICODE
125LONG CKey::DeleteValue(LPCWSTR name)
126{
127 MY_ASSUME(_object != NULL);
128 if (g_IsNT)
129 return ::RegDeleteValueW(_object, name);
130 return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name));
131}
132#endif
133
134LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw()
135{
136 MY_ASSUME(_object != NULL);
137 return RegSetValueEx(_object, name, 0, REG_DWORD,
138 (const BYTE *)&value, sizeof(UInt32));
139}
140
141LONG CKey::SetValue(LPCTSTR name, bool value) throw()
142{
143 return SetValue(name, BoolToUINT32(value));
144}
145
146LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw()
147{
148 MYASSERT(value != NULL);
149 MY_ASSUME(_object != NULL);
150 return RegSetValueEx(_object, name, 0, REG_SZ,
151 (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR));
152}
153
154/*
155LONG CKey::SetValue(LPCTSTR name, const CSysString &value)
156{
157 MYASSERT(value != NULL);
158 MY_ASSUME(_object != NULL);
159 return RegSetValueEx(_object, name, NULL, REG_SZ,
160 (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR));
161}
162*/
163
164#ifndef _UNICODE
165
166LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)
167{
168 MYASSERT(value != NULL);
169 MY_ASSUME(_object != NULL);
170 if (g_IsNT)
171 return RegSetValueExW(_object, name, 0, REG_SZ,
172 (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));
173 return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),
174 value == 0 ? 0 : (LPCSTR)GetSystemString(value));
175}
176
177#endif
178
179
180LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw()
181{
182 MYASSERT(value != NULL);
183 MY_ASSUME(_object != NULL);
184 return RegSetValueEx(_object, name, 0, REG_BINARY,
185 (const BYTE *)value, size);
186}
187
188LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)
189{
190 MYASSERT(value != NULL);
191 CKey key;
192 LONG res = key.Create(parentKey, keyName);
193 if (res == ERROR_SUCCESS)
194 res = key.SetValue(valueName, value);
195 return res;
196}
197
198LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw()
199{
200 MYASSERT(value != NULL);
201 CKey key;
202 LONG res = key.Create(_object, keyName);
203 if (res == ERROR_SUCCESS)
204 res = key.SetValue(valueName, value);
205 return res;
206}
207
208LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw()
209{
210 DWORD type = 0;
211 DWORD count = sizeof(DWORD);
212 LONG res = RegQueryValueEx(_object, name, NULL, &type,
213 (LPBYTE)&value, &count);
214 MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD));
215 MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32)));
216 return res;
217}
218
219LONG CKey::QueryValue(LPCTSTR name, bool &value) throw()
220{
221 UInt32 uintValue = BoolToUINT32(value);
222 LONG res = QueryValue(name, uintValue);
223 value = UINT32ToBool(uintValue);
224 return res;
225}
226
227LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw()
228{
229 UInt32 newVal;
230 LONG res = QueryValue(name, newVal);
231 if (res == ERROR_SUCCESS)
232 value = newVal;
233 return res;
234}
235
236LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
237{
238 bool newVal = false;
239 LONG res = QueryValue(name, newVal);
240 if (res == ERROR_SUCCESS)
241 value = newVal;
242 return res;
243}
244
245LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()
246{
247 DWORD type = 0;
248 LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
249 MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
250 return res;
251}
252
253LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
254{
255 value.Empty();
256 DWORD type = 0;
257 UInt32 curSize = 0;
258 LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
259 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
260 return res;
261 UInt32 curSize2 = curSize;
262 res = QueryValue(name, value.GetBuf(curSize), curSize2);
263 if (curSize > curSize2)
264 curSize = curSize2;
265 value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR));
266 return res;
267}
268
269
270#ifndef _UNICODE
271
272LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)
273{
274 DWORD type = 0;
275 LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
276 MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
277 return res;
278}
279
280LONG CKey::QueryValue(LPCWSTR name, UString &value)
281{
282 value.Empty();
283 DWORD type = 0;
284 UInt32 curSize = 0;
285
286 LONG res;
287
288 if (g_IsNT)
289 {
290 res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
291 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
292 return res;
293 UInt32 curSize2 = curSize;
294 res = QueryValue(name, value.GetBuf(curSize), curSize2);
295 if (curSize > curSize2)
296 curSize = curSize2;
297 value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t));
298 }
299 else
300 {
301 AString vTemp;
302 res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
303 value = GetUnicodeString(vTemp);
304 }
305
306 return res;
307}
308
309#endif
310
311
312LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()
313{
314 DWORD type = 0;
315 LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
316 MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY));
317 return res;
318}
319
320
321LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)
322{
323 DWORD type = 0;
324 dataSize = 0;
325 LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize);
326 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
327 return res;
328 value.Alloc(dataSize);
329 return QueryValue(name, (BYTE *)value, dataSize);
330}
331
332LONG CKey::EnumKeys(CSysStringVector &keyNames)
333{
334 keyNames.Clear();
335 CSysString keyName;
336 for (DWORD index = 0; ; index++)
337 {
338 const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL
339 FILETIME lastWriteTime;
340 UInt32 nameSize = kBufSize;
341 LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize),
342 (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);
343 keyName.ReleaseBuf_CalcLen(kBufSize);
344 if (result == ERROR_NO_MORE_ITEMS)
345 break;
346 if (result != ERROR_SUCCESS)
347 return result;
348 keyNames.Add(keyName);
349 }
350 return ERROR_SUCCESS;
351}
352
353LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)
354{
355 size_t numChars = 0;
356
357 unsigned i;
358
359 for (i = 0; i < strings.Size(); i++)
360 numChars += strings[i].Len() + 1;
361
362 CObjArray<wchar_t> buffer(numChars);
363 size_t pos = 0;
364
365 for (i = 0; i < strings.Size(); i++)
366 {
367 const UString &s = strings[i];
368 size_t size = s.Len() + 1;
369 wmemcpy(buffer + pos, s, size);
370 pos += size;
371 }
372 return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));
373}
374
375LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
376{
377 strings.Clear();
378 CByteBuffer buffer;
379 UInt32 dataSize = 0;
380 LONG res = QueryValue(valueName, buffer, dataSize);
381 if (res != ERROR_SUCCESS)
382 return res;
383 if (dataSize > buffer.Size())
384 return E_FAIL;
385 if (dataSize % sizeof(wchar_t) != 0)
386 return E_FAIL;
387
388 const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer;
389 size_t numChars = dataSize / sizeof(wchar_t);
390 size_t prev = 0;
391 UString s;
392
393 for (size_t i = 0; i < numChars; i++)
394 {
395 if (data[i] == 0)
396 {
397 s = data + prev;
398 strings.Add(s);
399 prev = i + 1;
400 }
401 }
402
403 return res;
404}
405
406}}
diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
new file mode 100644
index 0000000..ca79dfe
--- /dev/null
+++ b/CPP/Windows/Registry.h
@@ -0,0 +1,84 @@
1// Windows/Registry.h
2
3#ifndef __WINDOWS_REGISTRY_H
4#define __WINDOWS_REGISTRY_H
5
6#include "../Common/MyBuffer.h"
7#include "../Common/MyString.h"
8
9namespace NWindows {
10namespace NRegistry {
11
12LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);
13
14class CKey
15{
16 HKEY _object;
17public:
18 CKey(): _object(NULL) {}
19 ~CKey() { Close(); }
20
21 operator HKEY() const { return _object; }
22 void Attach(HKEY key) { _object = key; }
23 HKEY Detach()
24 {
25 HKEY key = _object;
26 _object = NULL;
27 return key;
28 }
29
30 LONG Create(HKEY parentKey, LPCTSTR keyName,
31 LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE,
32 REGSAM accessMask = KEY_ALL_ACCESS,
33 LPSECURITY_ATTRIBUTES securityAttributes = NULL,
34 LPDWORD disposition = NULL) throw();
35 LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw();
36
37 LONG Close() throw();
38
39 LONG DeleteSubKey(LPCTSTR subKeyName) throw();
40 LONG RecurseDeleteKey(LPCTSTR subKeyName) throw();
41
42 LONG DeleteValue(LPCTSTR name) throw();
43 #ifndef _UNICODE
44 LONG DeleteValue(LPCWSTR name);
45 #endif
46
47 LONG SetValue(LPCTSTR valueName, UInt32 value) throw();
48 LONG SetValue(LPCTSTR valueName, bool value) throw();
49 LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw();
50 // LONG SetValue(LPCTSTR valueName, const CSysString &value);
51 #ifndef _UNICODE
52 LONG SetValue(LPCWSTR name, LPCWSTR value);
53 // LONG SetValue(LPCWSTR name, const UString &value);
54 #endif
55
56 LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();
57
58 LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);
59 LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);
60
61 LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();
62
63 LONG QueryValue(LPCTSTR name, UInt32 &value) throw();
64 LONG QueryValue(LPCTSTR name, bool &value) throw();
65 LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw();
66 LONG QueryValue(LPCTSTR name, CSysString &value);
67
68 LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw();
69 LONG GetValue_IfOk(LPCTSTR name, bool &value) throw();
70
71 #ifndef _UNICODE
72 LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize);
73 LONG QueryValue(LPCWSTR name, UString &value);
74 #endif
75
76 LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw();
77 LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize);
78
79 LONG EnumKeys(CSysStringVector &keyNames);
80};
81
82}}
83
84#endif
diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp
new file mode 100644
index 0000000..ae8182e
--- /dev/null
+++ b/CPP/Windows/ResourceString.cpp
@@ -0,0 +1,103 @@
1// Windows/ResourceString.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../Common/StringConvert.h"
7#endif
8
9#include "ResourceString.h"
10
11extern HINSTANCE g_hInstance;
12#ifndef _UNICODE
13extern bool g_IsNT;
14#endif
15
16namespace NWindows {
17
18#ifndef _UNICODE
19
20static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)
21{
22 CSysString s;
23 int size = 128;
24 int len;
25 do
26 {
27 size <<= 1;
28 len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);
29 }
30 while (size - len <= 1);
31 s.ReleaseBuf_CalcLen((unsigned)len);
32 return s;
33}
34
35#endif
36
37static const int kStartSize = 256;
38
39static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)
40{
41 int size = kStartSize;
42 int len;
43 do
44 {
45 size <<= 1;
46 len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);
47 }
48 while (size - len <= 1);
49 s.ReleaseBuf_CalcLen((unsigned)len);
50}
51
52// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.
53
54UString MyLoadString(UINT resourceID)
55{
56 #ifndef _UNICODE
57 if (!g_IsNT)
58 return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID));
59 else
60 #endif
61 {
62 {
63 wchar_t s[kStartSize];
64 s[0] = 0;
65 int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize);
66 if (kStartSize - len > 1)
67 return s;
68 }
69 UString dest;
70 MyLoadString2(g_hInstance, resourceID, dest);
71 return dest;
72 }
73}
74
75void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest)
76{
77 dest.Empty();
78 #ifndef _UNICODE
79 if (!g_IsNT)
80 MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID));
81 else
82 #endif
83 {
84 {
85 wchar_t s[kStartSize];
86 s[0] = 0;
87 int len = ::LoadStringW(hInstance, resourceID, s, kStartSize);
88 if (kStartSize - len > 1)
89 {
90 dest = s;
91 return;
92 }
93 }
94 MyLoadString2(hInstance, resourceID, dest);
95 }
96}
97
98void MyLoadString(UINT resourceID, UString &dest)
99{
100 MyLoadString(g_hInstance, resourceID, dest);
101}
102
103}
diff --git a/CPP/Windows/ResourceString.h b/CPP/Windows/ResourceString.h
new file mode 100644
index 0000000..f0bdabf
--- /dev/null
+++ b/CPP/Windows/ResourceString.h
@@ -0,0 +1,16 @@
1// Windows/ResourceString.h
2
3#ifndef __WINDOWS_RESOURCE_STRING_H
4#define __WINDOWS_RESOURCE_STRING_H
5
6#include "../Common/MyString.h"
7
8namespace NWindows {
9
10UString MyLoadString(UINT resourceID);
11void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest);
12void MyLoadString(UINT resourceID, UString &dest);
13
14}
15
16#endif
diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp
new file mode 100644
index 0000000..640c90d
--- /dev/null
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -0,0 +1,181 @@
1// Windows/SecurityUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/MyString.h"
6
7#include "SecurityUtils.h"
8
9namespace NWindows {
10namespace NSecurity {
11
12/*
13bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,
14 CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse)
15{
16 DWORD accountNameSize = 0, domainNameSize = 0;
17
18 if (!::LookupAccountSid(systemName, sid,
19 accountName.GetBuf(0), &accountNameSize,
20 domainName.GetBuf(0), &domainNameSize, sidNameUse))
21 {
22 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
23 return false;
24 }
25 DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize;
26 bool result = BOOLToBool(::LookupAccountSid(systemName, sid,
27 accountName.GetBuf(accountNameSize), &accountNameSize2,
28 domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse));
29 accountName.ReleaseBuf_CalcLen(accountNameSize);
30 domainName.ReleaseBuf_CalcLen(domainNameSize);
31 return result;
32}
33*/
34
35static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)
36{
37 size_t len = (size_t)wcslen(src);
38 dest->Length = (USHORT)(len * sizeof(WCHAR));
39 dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));
40 dest->Buffer = src;
41}
42
43/*
44static void MyLookupSids(CPolicy &policy, PSID ps)
45{
46 LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL;
47 LSA_TRANSLATED_NAME *names = NULL;
48 NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names);
49 int res = LsaNtStatusToWinError(nts);
50 LsaFreeMemory(referencedDomains);
51 LsaFreeMemory(names);
52}
53*/
54
55#ifndef _UNICODE
56typedef BOOL (WINAPI * LookupAccountNameWP)(
57 LPCWSTR lpSystemName,
58 LPCWSTR lpAccountName,
59 PSID Sid,
60 LPDWORD cbSid,
61 LPWSTR ReferencedDomainName,
62 LPDWORD cchReferencedDomainName,
63 PSID_NAME_USE peUse
64 );
65#endif
66
67static PSID GetSid(LPWSTR accountName)
68{
69 #ifndef _UNICODE
70 HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll"));
71 if (hModule == NULL)
72 return NULL;
73 LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW");
74 if (lookupAccountNameW == NULL)
75 return NULL;
76 #endif
77
78 DWORD sidLen = 0, domainLen = 0;
79 SID_NAME_USE sidNameUse;
80 if (!
81 #ifdef _UNICODE
82 ::LookupAccountNameW
83 #else
84 lookupAccountNameW
85 #endif
86 (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse))
87 {
88 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
89 {
90 PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen);
91 LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR));
92 BOOL res =
93 #ifdef _UNICODE
94 ::LookupAccountNameW
95 #else
96 lookupAccountNameW
97 #endif
98 (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse);
99 ::HeapFree(GetProcessHeap(), 0, domainName);
100 if (res)
101 return pSid;
102 }
103 }
104 return NULL;
105}
106
107#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege"
108
109bool AddLockMemoryPrivilege()
110{
111 CPolicy policy;
112 LSA_OBJECT_ATTRIBUTES attr;
113 attr.Length = sizeof(attr);
114 attr.RootDirectory = NULL;
115 attr.ObjectName = NULL;
116 attr.Attributes = 0;
117 attr.SecurityDescriptor = NULL;
118 attr.SecurityQualityOfService = NULL;
119 if (policy.Open(NULL, &attr,
120 // GENERIC_WRITE)
121 POLICY_ALL_ACCESS)
122 // STANDARD_RIGHTS_REQUIRED,
123 // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES)
124 != 0)
125 return false;
126 LSA_UNICODE_STRING userRights;
127 wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME;
128 SetLsaString(s, &userRights);
129 WCHAR userName[256 + 2];
130 DWORD size = 256;
131 if (!GetUserNameW(userName, &size))
132 return false;
133 PSID psid = GetSid(userName);
134 if (psid == NULL)
135 return false;
136 bool res = false;
137
138 /*
139 PLSA_UNICODE_STRING userRightsArray;
140 ULONG countOfRights;
141 NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights);
142 if (status != 0)
143 return false;
144 bool finded = false;
145 for (ULONG i = 0; i < countOfRights; i++)
146 {
147 LSA_UNICODE_STRING &ur = userRightsArray[i];
148 if (ur.Length != s.Length() * sizeof(WCHAR))
149 continue;
150 if (wcsncmp(ur.Buffer, s, s.Length()) != 0)
151 continue;
152 finded = true;
153 res = true;
154 break;
155 }
156 if (!finded)
157 */
158 {
159 /*
160 LSA_ENUMERATION_INFORMATION *enums;
161 ULONG countReturned;
162 NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned);
163 if (status == 0)
164 {
165 for (ULONG i = 0; i < countReturned; i++)
166 MyLookupSids(policy, enums[i].Sid);
167 if (enums)
168 ::LsaFreeMemory(enums);
169 res = true;
170 }
171 */
172 NTSTATUS status = policy.AddAccountRights(psid, &userRights);
173 if (status == 0)
174 res = true;
175 // ULONG res = LsaNtStatusToWinError(status);
176 }
177 HeapFree(GetProcessHeap(), 0, psid);
178 return res;
179}
180
181}}
diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h
new file mode 100644
index 0000000..8966dfd
--- /dev/null
+++ b/CPP/Windows/SecurityUtils.h
@@ -0,0 +1,167 @@
1// Windows/SecurityUtils.h
2
3#ifndef __WINDOWS_SECURITY_UTILS_H
4#define __WINDOWS_SECURITY_UTILS_H
5
6#include <NTSecAPI.h>
7
8#include "Defs.h"
9
10namespace NWindows {
11namespace NSecurity {
12
13class CAccessToken
14{
15 HANDLE _handle;
16public:
17 CAccessToken(): _handle(NULL) {};
18 ~CAccessToken() { Close(); }
19 bool Close()
20 {
21 if (_handle == NULL)
22 return true;
23 bool res = BOOLToBool(::CloseHandle(_handle));
24 if (res)
25 _handle = NULL;
26 return res;
27 }
28
29 bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess)
30 {
31 Close();
32 return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle));
33 }
34
35 /*
36 bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf)
37 {
38 Close();
39 return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle));
40 }
41 */
42
43 bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState,
44 DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength)
45 { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges),
46 newState, bufferLength, previousState, returnLength)); }
47
48 bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState)
49 { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); }
50
51 bool AdjustPrivileges(PTOKEN_PRIVILEGES newState)
52 { return AdjustPrivileges(false, newState); }
53
54};
55
56#ifndef _UNICODE
57typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName,
58 PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle);
59typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle);
60typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle,
61 PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
62#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L)
63#endif
64
65struct CPolicy
66{
67protected:
68 LSA_HANDLE _handle;
69 #ifndef _UNICODE
70 HMODULE hModule;
71 #endif
72public:
73 operator LSA_HANDLE() const { return _handle; }
74 CPolicy(): _handle(NULL)
75 {
76 #ifndef _UNICODE
77 hModule = GetModuleHandle(TEXT("Advapi32.dll"));
78 #endif
79 };
80 ~CPolicy() { Close(); }
81
82 NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes,
83 ACCESS_MASK desiredAccess)
84 {
85 #ifndef _UNICODE
86 if (hModule == NULL)
87 return MY_STATUS_NOT_IMPLEMENTED;
88 LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy");
89 if (lsaOpenPolicy == NULL)
90 return MY_STATUS_NOT_IMPLEMENTED;
91 #endif
92
93 Close();
94 return
95 #ifdef _UNICODE
96 ::LsaOpenPolicy
97 #else
98 lsaOpenPolicy
99 #endif
100 (systemName, objectAttributes, desiredAccess, &_handle);
101 }
102
103 NTSTATUS Close()
104 {
105 if (_handle == NULL)
106 return 0;
107
108 #ifndef _UNICODE
109 if (hModule == NULL)
110 return MY_STATUS_NOT_IMPLEMENTED;
111 LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose");
112 if (lsaClose == NULL)
113 return MY_STATUS_NOT_IMPLEMENTED;
114 #endif
115
116 NTSTATUS res =
117 #ifdef _UNICODE
118 ::LsaClose
119 #else
120 lsaClose
121 #endif
122 (_handle);
123 _handle = NULL;
124 return res;
125 }
126
127 NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights,
128 PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned)
129 { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); }
130
131 NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights)
132 { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); }
133
134 NTSTATUS LookupSids(ULONG count, PSID* sids,
135 PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names)
136 { return LsaLookupSids(_handle, count, sids, referencedDomains, names); }
137
138 NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights)
139 {
140 #ifndef _UNICODE
141 if (hModule == NULL)
142 return MY_STATUS_NOT_IMPLEMENTED;
143 LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights");
144 if (lsaAddAccountRights == NULL)
145 return MY_STATUS_NOT_IMPLEMENTED;
146 #endif
147
148 return
149 #ifdef _UNICODE
150 ::LsaAddAccountRights
151 #else
152 lsaAddAccountRights
153 #endif
154 (_handle, accountSid, userRights, countOfRights);
155 }
156 NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights)
157 { return AddAccountRights(accountSid, userRights, 1); }
158
159 NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights)
160 { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); }
161};
162
163bool AddLockMemoryPrivilege();
164
165}}
166
167#endif
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
new file mode 100644
index 0000000..d0f9032
--- /dev/null
+++ b/CPP/Windows/Shell.cpp
@@ -0,0 +1,358 @@
1// Windows/Shell.cpp
2
3#include "StdAfx.h"
4
5/*
6#include <stdio.h>
7#include <string.h>
8*/
9
10#include "../Common/MyCom.h"
11#ifndef _UNICODE
12#include "../Common/StringConvert.h"
13#endif
14
15#include "COM.h"
16#include "Shell.h"
17
18#ifndef _UNICODE
19extern bool g_IsNT;
20#endif
21
22namespace NWindows {
23namespace NShell {
24
25#ifndef UNDER_CE
26
27// SHGetMalloc is unsupported in Windows Mobile?
28
29void CItemIDList::Free()
30{
31 if (m_Object == NULL)
32 return;
33 CMyComPtr<IMalloc> shellMalloc;
34 if (::SHGetMalloc(&shellMalloc) != NOERROR)
35 throw 41099;
36 shellMalloc->Free(m_Object);
37 m_Object = NULL;
38}
39
40/*
41CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)
42 { *this = itemIDList; }
43CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)
44 { *this = itemIDList; }
45
46CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)
47{
48 Free();
49 if (object != 0)
50 {
51 UINT32 size = GetSize(object);
52 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
53 if (m_Object != NULL)
54 MoveMemory(m_Object, object, size);
55 }
56 return *this;
57}
58
59CItemIDList& CItemIDList::operator=(const CItemIDList &object)
60{
61 Free();
62 if (object.m_Object != NULL)
63 {
64 UINT32 size = GetSize(object.m_Object);
65 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
66 if (m_Object != NULL)
67 MoveMemory(m_Object, object.m_Object, size);
68 }
69 return *this;
70}
71*/
72
73/////////////////////////////
74// CDrop
75
76void CDrop::Attach(HDROP object)
77{
78 Free();
79 m_Object = object;
80 m_Assigned = true;
81}
82
83void CDrop::Free()
84{
85 if (m_MustBeFinished && m_Assigned)
86 Finish();
87 m_Assigned = false;
88}
89
90UINT CDrop::QueryCountOfFiles()
91{
92 return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
93}
94
95UString CDrop::QueryFileName(UINT fileIndex)
96{
97 UString fileName;
98 #ifndef _UNICODE
99 if (!g_IsNT)
100 {
101 AString fileNameA;
102 UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
103 const unsigned len = bufferSize + 2;
104 QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);
105 fileNameA.ReleaseBuf_CalcLen(len);
106 fileName = GetUnicodeString(fileNameA);
107 }
108 else
109 #endif
110 {
111 UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
112 const unsigned len = bufferSize + 2;
113 QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);
114 fileName.ReleaseBuf_CalcLen(len);
115 }
116 return fileName;
117}
118
119void CDrop::QueryFileNames(UStringVector &fileNames)
120{
121 UINT numFiles = QueryCountOfFiles();
122 /*
123 char s[100];
124 sprintf(s, "QueryFileNames: %d files", numFiles);
125 OutputDebugStringA(s);
126 */
127 fileNames.ClearAndReserve(numFiles);
128 for (UINT i = 0; i < numFiles; i++)
129 {
130 const UString s2 = QueryFileName(i);
131 if (!s2.IsEmpty())
132 fileNames.AddInReserved(s2);
133 /*
134 OutputDebugStringW(L"file ---");
135 OutputDebugStringW(s2);
136 */
137 }
138}
139
140
141bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
142{
143 const unsigned len = MAX_PATH * 2;
144 bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
145 path.ReleaseBuf_CalcLen(len);
146 return result;
147}
148
149#endif
150
151#ifdef UNDER_CE
152
153bool BrowseForFolder(LPBROWSEINFO, CSysString)
154{
155 return false;
156}
157
158bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
159{
160 return false;
161}
162
163bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
164 LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
165{
166 /*
167 // SHBrowseForFolder doesn't work before CE 6.0 ?
168 if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
169 MessageBoxW(0, L"no", L"", 0);
170 else
171 MessageBoxW(0, L"yes", L"", 0);
172 */
173 /*
174 UString s = "all files";
175 s += " (*.*)";
176 return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
177 */
178 return false;
179}
180
181#else
182
183bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
184{
185 NWindows::NCOM::CComInitializer comInitializer;
186 LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
187 if (itemIDList == NULL)
188 return false;
189 CItemIDList itemIDListHolder;
190 itemIDListHolder.Attach(itemIDList);
191 return GetPathFromIDList(itemIDList, resultPath);
192}
193
194
195static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
196{
197 #ifndef UNDER_CE
198 switch (uMsg)
199 {
200 case BFFM_INITIALIZED:
201 {
202 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
203 break;
204 }
205 /*
206 case BFFM_SELCHANGED:
207 {
208 TCHAR dir[MAX_PATH];
209 if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
210 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
211 else
212 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
213 break;
214 }
215 */
216 default:
217 break;
218 }
219 #endif
220 return 0;
221}
222
223
224static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
225 LPCTSTR initialFolder, CSysString &resultPath)
226{
227 CSysString displayName;
228 BROWSEINFO browseInfo;
229 browseInfo.hwndOwner = owner;
230 browseInfo.pidlRoot = NULL;
231
232 // there are Unicode/Astring problems in some WinCE SDK ?
233 /*
234 #ifdef UNDER_CE
235 browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);
236 browseInfo.lpszTitle = (LPCSTR)title;
237 #else
238 */
239 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
240 browseInfo.lpszTitle = title;
241 // #endif
242 browseInfo.ulFlags = ulFlags;
243 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
244 browseInfo.lParam = (LPARAM)initialFolder;
245 return BrowseForFolder(&browseInfo, resultPath);
246}
247
248bool BrowseForFolder(HWND owner, LPCTSTR title,
249 LPCTSTR initialFolder, CSysString &resultPath)
250{
251 return BrowseForFolder(owner, title,
252 #ifndef UNDER_CE
253 BIF_NEWDIALOGSTYLE |
254 #endif
255 BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
256 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
257}
258
259#ifndef _UNICODE
260
261typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
262
263bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
264{
265 path.Empty();
266 SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
267 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
268 if (shGetPathFromIDListW == 0)
269 return false;
270 const unsigned len = MAX_PATH * 2;
271 bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
272 path.ReleaseBuf_CalcLen(len);
273 return result;
274}
275
276typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
277
278static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
279{
280 NWindows::NCOM::CComInitializer comInitializer;
281 SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
282 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
283 if (shBrowseForFolderW == 0)
284 return false;
285 LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
286 if (itemIDList == NULL)
287 return false;
288 CItemIDList itemIDListHolder;
289 itemIDListHolder.Attach(itemIDList);
290 return GetPathFromIDList(itemIDList, resultPath);
291}
292
293static
294int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
295{
296 switch (uMsg)
297 {
298 case BFFM_INITIALIZED:
299 {
300 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
301 break;
302 }
303 /*
304 case BFFM_SELCHANGED:
305 {
306 wchar_t dir[MAX_PATH * 2];
307
308 if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
309 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
310 else
311 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
312 break;
313 }
314 */
315 default:
316 break;
317 }
318 return 0;
319}
320
321
322static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
323 LPCWSTR initialFolder, UString &resultPath)
324{
325 UString displayName;
326 BROWSEINFOW browseInfo;
327 browseInfo.hwndOwner = owner;
328 browseInfo.pidlRoot = NULL;
329 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
330 browseInfo.lpszTitle = title;
331 browseInfo.ulFlags = ulFlags;
332 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
333 browseInfo.lParam = (LPARAM)initialFolder;
334 return BrowseForFolder(&browseInfo, resultPath);
335}
336
337bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
338{
339 if (g_IsNT)
340 return BrowseForFolder(owner, title,
341 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
342 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
343 , initialFolder, resultPath);
344 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
345 CSysString s;
346 bool res = BrowseForFolder(owner, GetSystemString(title),
347 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
348 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
349 , GetSystemString(initialFolder), s);
350 resultPath = GetUnicodeString(s);
351 return res;
352}
353
354#endif
355
356#endif
357
358}}
diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h
new file mode 100644
index 0000000..de91d3f
--- /dev/null
+++ b/CPP/Windows/Shell.h
@@ -0,0 +1,94 @@
1// Windows/Shell.h
2
3#ifndef __WINDOWS_SHELL_H
4#define __WINDOWS_SHELL_H
5
6#include "../Common/MyWindows.h"
7#include <ShlObj.h>
8
9#include "../Common/MyString.h"
10
11#include "Defs.h"
12
13namespace NWindows{
14namespace NShell{
15
16/////////////////////////
17// CItemIDList
18#ifndef UNDER_CE
19
20class CItemIDList
21{
22 LPITEMIDLIST m_Object;
23public:
24 CItemIDList(): m_Object(NULL) {}
25 // CItemIDList(LPCITEMIDLIST itemIDList);
26 // CItemIDList(const CItemIDList& itemIDList);
27 ~CItemIDList() { Free(); }
28 void Free();
29 void Attach(LPITEMIDLIST object)
30 {
31 Free();
32 m_Object = object;
33 }
34 LPITEMIDLIST Detach()
35 {
36 LPITEMIDLIST object = m_Object;
37 m_Object = NULL;
38 return object;
39 }
40 operator LPITEMIDLIST() { return m_Object;}
41 operator LPCITEMIDLIST() const { return m_Object;}
42 LPITEMIDLIST* operator&() { return &m_Object; }
43 LPITEMIDLIST operator->() { return m_Object; }
44
45 // CItemIDList& operator=(LPCITEMIDLIST object);
46 // CItemIDList& operator=(const CItemIDList &object);
47};
48
49/////////////////////////////
50// CDrop
51
52class CDrop
53{
54 HDROP m_Object;
55 bool m_MustBeFinished;
56 bool m_Assigned;
57 void Free();
58public:
59 CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {}
60 ~CDrop() { Free(); }
61
62 void Attach(HDROP object);
63 operator HDROP() { return m_Object;}
64 bool QueryPoint(LPPOINT point)
65 { return BOOLToBool(::DragQueryPoint(m_Object, point)); }
66 void Finish() { ::DragFinish(m_Object); }
67 UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT fileNameSize)
68 { return ::DragQueryFile(m_Object, fileIndex, fileName, fileNameSize); }
69 #ifndef _UNICODE
70 UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT fileNameSize)
71 { return ::DragQueryFileW(m_Object, fileIndex, fileName, fileNameSize); }
72 #endif
73 UINT QueryCountOfFiles();
74 UString QueryFileName(UINT fileIndex);
75 void QueryFileNames(UStringVector &fileNames);
76};
77
78#endif
79
80/////////////////////////////
81// Functions
82
83bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path);
84bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath);
85bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath);
86
87#ifndef _UNICODE
88bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path);
89bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath);
90bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath);
91#endif
92}}
93
94#endif
diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h
new file mode 100644
index 0000000..1766dfa
--- /dev/null
+++ b/CPP/Windows/StdAfx.h
@@ -0,0 +1,8 @@
1// StdAfx.h
2
3#ifndef __STDAFX_H
4#define __STDAFX_H
5
6#include "../Common/Common.h"
7
8#endif
diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp
new file mode 100644
index 0000000..fbf919d
--- /dev/null
+++ b/CPP/Windows/Synchronization.cpp
@@ -0,0 +1,63 @@
1// Windows/Synchronization.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6
7#include "Synchronization.h"
8
9namespace NWindows {
10namespace NSynchronization {
11
12/*
13#define INFINITE 0xFFFFFFFF
14#define MAXIMUM_WAIT_OBJECTS 64
15#define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L)
16#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
17#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
18// WINAPI
19DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout);
20*/
21
22DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)
23{
24 if (count < 1)
25 {
26 // abort();
27 SetLastError(EINVAL);
28 return WAIT_FAILED;
29 }
30
31 CSynchro *synchro = handles[0]->_sync;
32 synchro->Enter();
33
34 // #ifdef DEBUG_SYNCHRO
35 for (DWORD i = 1; i < count; i++)
36 {
37 if (synchro != handles[i]->_sync)
38 {
39 // abort();
40 synchro->Leave();
41 SetLastError(EINVAL);
42 return WAIT_FAILED;
43 }
44 }
45 // #endif
46
47 for (;;)
48 {
49 for (DWORD i = 0; i < count; i++)
50 {
51 if (handles[i]->IsSignaledAndUpdate())
52 {
53 synchro->Leave();
54 return WAIT_OBJECT_0 + i;
55 }
56 }
57 synchro->WaitCond();
58 }
59}
60
61}}
62
63#endif
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
new file mode 100644
index 0000000..7d2e8d2
--- /dev/null
+++ b/CPP/Windows/Synchronization.h
@@ -0,0 +1,393 @@
1// Windows/Synchronization.h
2
3#ifndef __WINDOWS_SYNCHRONIZATION_H
4#define __WINDOWS_SYNCHRONIZATION_H
5
6#include "../../C/Threads.h"
7
8#include "../Common/MyTypes.h"
9
10#include "Defs.h"
11
12#ifdef _WIN32
13#include "Handle.h"
14#endif
15
16namespace NWindows {
17namespace NSynchronization {
18
19class CBaseEvent MY_UNCOPYABLE
20{
21protected:
22 ::CEvent _object;
23public:
24 bool IsCreated() { return Event_IsCreated(&_object) != 0; }
25
26 CBaseEvent() { Event_Construct(&_object); }
27 ~CBaseEvent() { Close(); }
28 WRes Close() { return Event_Close(&_object); }
29
30 #ifdef _WIN32
31 operator HANDLE() { return _object; }
32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)
33 {
34 _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);
35 if (name == NULL && _object != 0)
36 return 0;
37 return ::GetLastError();
38 }
39 WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
40 {
41 _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);
42 if (_object != 0)
43 return 0;
44 return ::GetLastError();
45 }
46 #endif
47
48 WRes Set() { return Event_Set(&_object); }
49 // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }
50 WRes Reset() { return Event_Reset(&_object); }
51 WRes Lock() { return Event_Wait(&_object); }
52};
53
54class CManualResetEvent: public CBaseEvent
55{
56public:
57 WRes Create(bool initiallyOwn = false)
58 {
59 return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);
60 }
61 WRes CreateIfNotCreated_Reset()
62 {
63 if (IsCreated())
64 return Reset();
65 return ManualResetEvent_CreateNotSignaled(&_object);
66 }
67 #ifdef _WIN32
68 WRes CreateWithName(bool initiallyOwn, LPCTSTR name)
69 {
70 return CBaseEvent::Create(true, initiallyOwn, name);
71 }
72 #endif
73};
74
75class CAutoResetEvent: public CBaseEvent
76{
77public:
78 WRes Create()
79 {
80 return AutoResetEvent_CreateNotSignaled(&_object);
81 }
82 WRes CreateIfNotCreated_Reset()
83 {
84 if (IsCreated())
85 return Reset();
86 return AutoResetEvent_CreateNotSignaled(&_object);
87 }
88};
89
90
91/*
92#ifdef _WIN32
93
94class CObject: public CHandle
95{
96public:
97 WRes Lock(DWORD timeoutInterval = INFINITE)
98 { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }
99};
100
101class CMutex: public CObject
102{
103public:
104 WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)
105 {
106 _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name);
107 if (name == NULL && _handle != 0)
108 return 0;
109 return ::GetLastError();
110 }
111 #ifndef UNDER_CE
112 WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
113 {
114 _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);
115 if (_handle != 0)
116 return 0;
117 return ::GetLastError();
118 }
119 #endif
120 WRes Release()
121 {
122 return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();
123 }
124};
125
126class CMutexLock MY_UNCOPYABLE
127{
128 CMutex *_object;
129public:
130 CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }
131 ~CMutexLock() { _object->Release(); }
132};
133
134#endif // _WIN32
135*/
136
137
138class CSemaphore MY_UNCOPYABLE
139{
140 ::CSemaphore _object;
141public:
142 CSemaphore() { Semaphore_Construct(&_object); }
143 ~CSemaphore() { Close(); }
144 WRes Close() { return Semaphore_Close(&_object); }
145
146 #ifdef _WIN32
147 operator HANDLE() { return _object; }
148 #endif
149
150 // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; }
151
152 WRes Create(UInt32 initCount, UInt32 maxCount)
153 {
154 return Semaphore_Create(&_object, initCount, maxCount);
155 }
156 WRes OptCreateInit(UInt32 initCount, UInt32 maxCount)
157 {
158 return Semaphore_OptCreateInit(&_object, initCount, maxCount);
159 }
160 WRes Release() { return Semaphore_Release1(&_object); }
161 WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }
162 WRes Lock() { return Semaphore_Wait(&_object); }
163};
164
165class CCriticalSection MY_UNCOPYABLE
166{
167 ::CCriticalSection _object;
168public:
169 CCriticalSection() { CriticalSection_Init(&_object); }
170 ~CCriticalSection() { CriticalSection_Delete(&_object); }
171 void Enter() { CriticalSection_Enter(&_object); }
172 void Leave() { CriticalSection_Leave(&_object); }
173};
174
175class CCriticalSectionLock MY_UNCOPYABLE
176{
177 CCriticalSection *_object;
178 void Unlock() { _object->Leave(); }
179public:
180 CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }
181 ~CCriticalSectionLock() { Unlock(); }
182};
183
184
185#ifdef _WIN32
186
187typedef HANDLE CHandle_WFMO;
188typedef CSemaphore CSemaphore_WFMO;
189typedef CAutoResetEvent CAutoResetEvent_WFMO;
190typedef CManualResetEvent CManualResetEvent_WFMO;
191
192inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)
193{
194 return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
195}
196
197#define SYNC_OBJ_DECL(obj)
198#define SYNC_WFMO(x)
199#define SYNC_PARAM(x)
200#define SYNC_PARAM_DECL(x)
201
202#else // _WIN32
203
204// POSIX sync objects for WaitForMultipleObjects
205
206#define SYNC_WFMO(x) x
207#define SYNC_PARAM(x) x,
208#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x
209#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x;
210
211class CSynchro MY_UNCOPYABLE
212{
213 pthread_mutex_t _mutex;
214 pthread_cond_t _cond;
215 bool _isValid;
216
217public:
218 CSynchro() { _isValid = false; }
219 ~CSynchro()
220 {
221 if (_isValid)
222 {
223 ::pthread_mutex_destroy(&_mutex);
224 ::pthread_cond_destroy(&_cond);
225 }
226 _isValid = false;
227 }
228 WRes Create()
229 {
230 RINOK(::pthread_mutex_init(&_mutex, 0));
231 WRes ret = ::pthread_cond_init(&_cond, 0);
232 _isValid = 1;
233 return ret;
234 }
235 WRes Enter()
236 {
237 return ::pthread_mutex_lock(&_mutex);
238 }
239 WRes Leave()
240 {
241 return ::pthread_mutex_unlock(&_mutex);
242 }
243 WRes WaitCond()
244 {
245 return ::pthread_cond_wait(&_cond, &_mutex);
246 }
247 WRes LeaveAndSignal()
248 {
249 WRes res1 = ::pthread_cond_broadcast(&_cond);
250 WRes res2 = ::pthread_mutex_unlock(&_mutex);
251 return (res2 ? res2 : res1);
252 }
253};
254
255
256struct CBaseHandle_WFMO;
257typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO;
258
259// these constants are from Windows
260#define WAIT_OBJECT_0 0
261#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
262
263DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles);
264
265
266struct CBaseHandle_WFMO MY_UNCOPYABLE
267{
268 CSynchro *_sync;
269
270 CBaseHandle_WFMO(): _sync(NULL) {}
271
272 operator CHandle_WFMO() { return this; }
273 virtual bool IsSignaledAndUpdate() = 0;
274};
275
276
277class CBaseEvent_WFMO : public CBaseHandle_WFMO
278{
279 bool _manual_reset;
280 bool _state;
281
282public:
283
284 // bool IsCreated() { return (this->_sync != NULL); }
285 // CBaseEvent_WFMO() { ; }
286 ~CBaseEvent_WFMO() { Close(); }
287
288 WRes Close() { this->_sync = NULL; return 0; }
289
290 WRes Create(
291 CSynchro *sync,
292 bool manualReset, bool initiallyOwn)
293 {
294 this->_sync = sync;
295 this->_manual_reset = manualReset;
296 this->_state = initiallyOwn;
297 return 0;
298 }
299
300 WRes Set()
301 {
302 RINOK(this->_sync->Enter());
303 this->_state = true;
304 return this->_sync->LeaveAndSignal();
305 }
306
307 WRes Reset()
308 {
309 RINOK(this->_sync->Enter());
310 this->_state = false;
311 return this->_sync->Leave();
312 }
313
314 virtual bool IsSignaledAndUpdate()
315 {
316 if (this->_state == false)
317 return false;
318 if (this->_manual_reset == false)
319 this->_state = false;
320 return true;
321 }
322};
323
324
325class CManualResetEvent_WFMO: public CBaseEvent_WFMO
326{
327public:
328 WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); }
329};
330
331
332class CAutoResetEvent_WFMO: public CBaseEvent_WFMO
333{
334public:
335 WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); }
336 WRes CreateIfNotCreated_Reset(CSynchro *sync)
337 {
338 return Create(sync);
339 }
340};
341
342
343class CSemaphore_WFMO : public CBaseHandle_WFMO
344{
345 UInt32 _count;
346 UInt32 _maxCount;
347
348public:
349 CSemaphore_WFMO() : _count(0), _maxCount(0) {}
350
351 WRes Close() { this->_sync = NULL; return 0; }
352
353 WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount)
354 {
355 if (initCount > maxCount || maxCount < 1)
356 return EINVAL;
357 this->_sync = sync;
358 this->_count = initCount;
359 this->_maxCount = maxCount;
360 return 0;
361 }
362
363 WRes Release(UInt32 releaseCount = 1)
364 {
365 if (releaseCount < 1)
366 return EINVAL;
367
368 RINOK(this->_sync->Enter());
369 UInt32 newCount = this->_count + releaseCount;
370 if (newCount > this->_maxCount)
371 {
372 RINOK(this->_sync->Leave());
373 return ERROR_TOO_MANY_POSTS; // EINVAL
374 }
375 this->_count = newCount;
376
377 return this->_sync->LeaveAndSignal();
378 }
379
380 virtual bool IsSignaledAndUpdate()
381 {
382 if (this->_count == 0)
383 return false;
384 this->_count--;
385 return true;
386 }
387};
388
389#endif // _WIN32
390
391}}
392
393#endif
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
new file mode 100644
index 0000000..3a14b77
--- /dev/null
+++ b/CPP/Windows/System.cpp
@@ -0,0 +1,234 @@
1// Windows/System.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6#include <unistd.h>
7#ifdef __APPLE__
8#include <sys/sysctl.h>
9#else
10#include <sys/sysinfo.h>
11#endif
12#endif
13
14#include "../Common/Defs.h"
15// #include "../Common/MyWindows.h"
16
17// #include "../../C/CpuArch.h"
18
19#include "System.h"
20
21namespace NWindows {
22namespace NSystem {
23
24#ifdef _WIN32
25
26UInt32 CountAffinity(DWORD_PTR mask)
27{
28 UInt32 num = 0;
29 for (unsigned i = 0; i < sizeof(mask) * 8; i++)
30 num += (UInt32)((mask >> i) & 1);
31 return num;
32}
33
34BOOL CProcessAffinity::Get()
35{
36 #ifndef UNDER_CE
37 return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
38 #else
39 return FALSE;
40 #endif
41}
42
43
44UInt32 GetNumberOfProcessors()
45{
46 // We need to know how many threads we can use.
47 // By default the process is assigned to one group.
48 // So we get the number of logical processors (threads)
49 // assigned to current process in the current group.
50 // Group size can be smaller than total number logical processors, for exammple, 2x36
51
52 CProcessAffinity pa;
53
54 if (pa.Get() && pa.processAffinityMask != 0)
55 return pa.GetNumProcessThreads();
56
57 SYSTEM_INFO systemInfo;
58 GetSystemInfo(&systemInfo);
59 // the number of logical processors in the current group
60 return (UInt32)systemInfo.dwNumberOfProcessors;
61}
62
63#else
64
65
66BOOL CProcessAffinity::Get()
67{
68 numSysThreads = GetNumberOfProcessors();
69
70 /*
71 numSysThreads = 8;
72 for (unsigned i = 0; i < numSysThreads; i++)
73 CpuSet_Set(&cpu_set, i);
74 return TRUE;
75 */
76
77 #ifdef _7ZIP_AFFINITY_SUPPORTED
78
79 // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online
80 if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0)
81 return FALSE;
82 return TRUE;
83
84 #else
85
86 // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1;
87 return TRUE;
88 // errno = ENOSYS;
89 // return FALSE;
90
91 #endif
92}
93
94UInt32 GetNumberOfProcessors()
95{
96 #ifndef _7ZIP_ST
97 long n = sysconf(_SC_NPROCESSORS_CONF); // The number of processors configured
98 if (n < 1)
99 n = 1;
100 return (UInt32)n;
101 #else
102 return 1;
103 #endif
104}
105
106#endif
107
108
109#ifdef _WIN32
110
111#ifndef UNDER_CE
112
113#if !defined(_WIN64) && defined(__GNUC__)
114
115typedef struct _MY_MEMORYSTATUSEX {
116 DWORD dwLength;
117 DWORD dwMemoryLoad;
118 DWORDLONG ullTotalPhys;
119 DWORDLONG ullAvailPhys;
120 DWORDLONG ullTotalPageFile;
121 DWORDLONG ullAvailPageFile;
122 DWORDLONG ullTotalVirtual;
123 DWORDLONG ullAvailVirtual;
124 DWORDLONG ullAvailExtendedVirtual;
125} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;
126
127#else
128
129#define MY_MEMORYSTATUSEX MEMORYSTATUSEX
130#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX
131
132#endif
133
134typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);
135
136#endif // !UNDER_CE
137
138
139bool GetRamSize(UInt64 &size)
140{
141 size = (UInt64)(sizeof(size_t)) << 29;
142
143 #ifndef UNDER_CE
144 MY_MEMORYSTATUSEX stat;
145 stat.dwLength = sizeof(stat);
146 #endif
147
148 #ifdef _WIN64
149
150 if (!::GlobalMemoryStatusEx(&stat))
151 return false;
152 size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
153 return true;
154
155 #else
156
157 #ifndef UNDER_CE
158 GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)
159 (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx");
160 if (globalMemoryStatusEx && globalMemoryStatusEx(&stat))
161 {
162 size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
163 return true;
164 }
165 #endif
166
167 {
168 MEMORYSTATUS stat2;
169 stat2.dwLength = sizeof(stat2);
170 ::GlobalMemoryStatus(&stat2);
171 size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys);
172 return true;
173 }
174 #endif
175}
176
177#else
178
179// POSIX
180// #include <stdio.h>
181
182bool GetRamSize(UInt64 &size)
183{
184 size = (UInt64)(sizeof(size_t)) << 29;
185
186 #ifdef __APPLE__
187
188 #ifdef HW_MEMSIZE
189 uint64_t val = 0; // support 2Gb+ RAM
190 int mib[2] = { CTL_HW, HW_MEMSIZE };
191 #elif defined(HW_PHYSMEM64)
192 uint64_t val = 0; // support 2Gb+ RAM
193 int mib[2] = { CTL_HW, HW_PHYSMEM64 };
194 #else
195 unsigned int val = 0; // For old system
196 int mib[2] = { CTL_HW, HW_PHYSMEM };
197 #endif // HW_MEMSIZE
198 size_t size_sys = sizeof(val);
199
200 sysctl(mib, 2, &val, &size_sys, NULL, 0);
201 if (val)
202 size = val;
203
204 #elif defined(_AIX)
205 // fixme
206 #elif defined(__gnu_hurd__)
207 // fixme
208 #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__)
209 // GNU/kFreeBSD Debian
210 // fixme
211 #else
212
213 struct sysinfo info;
214 if (::sysinfo(&info) != 0)
215 return false;
216 size = (UInt64)info.mem_unit * info.totalram;
217 const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
218 if (size > kLimit)
219 size = kLimit;
220
221 /*
222 printf("\n mem_unit = %lld", (UInt64)info.mem_unit);
223 printf("\n totalram = %lld", (UInt64)info.totalram);
224 printf("\n freeram = %lld", (UInt64)info.freeram);
225 */
226
227 #endif
228
229 return true;
230}
231
232#endif
233
234}}
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
new file mode 100644
index 0000000..23cb0da
--- /dev/null
+++ b/CPP/Windows/System.h
@@ -0,0 +1,129 @@
1// Windows/System.h
2
3#ifndef __WINDOWS_SYSTEM_H
4#define __WINDOWS_SYSTEM_H
5
6#ifndef _WIN32
7// #include <sched.h>
8#include "../../C/Threads.h"
9#endif
10
11#include "../Common/MyTypes.h"
12
13namespace NWindows {
14namespace NSystem {
15
16
17#ifdef _WIN32
18
19UInt32 CountAffinity(DWORD_PTR mask);
20
21struct CProcessAffinity
22{
23 // UInt32 numProcessThreads;
24 // UInt32 numSysThreads;
25 DWORD_PTR processAffinityMask;
26 DWORD_PTR systemAffinityMask;
27
28 void InitST()
29 {
30 // numProcessThreads = 1;
31 // numSysThreads = 1;
32 processAffinityMask = 1;
33 systemAffinityMask = 1;
34 }
35
36 void CpuZero()
37 {
38 processAffinityMask = 0;
39 }
40
41 void CpuSet(unsigned cpuIndex)
42 {
43 processAffinityMask |= ((DWORD_PTR)1 << cpuIndex);
44 }
45
46 UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); }
47 UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); }
48
49 BOOL Get();
50
51 BOOL SetProcAffinity() const
52 {
53 return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask);
54 }
55};
56
57
58#else // WIN32
59
60struct CProcessAffinity
61{
62 UInt32 numSysThreads;
63
64 UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; }
65 BOOL Get();
66
67 #ifdef _7ZIP_AFFINITY_SUPPORTED
68
69 CCpuSet cpu_set;
70
71 void InitST()
72 {
73 numSysThreads = 1;
74 CpuSet_Zero(&cpu_set);
75 CpuSet_Set(&cpu_set, 0);
76 }
77
78 UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); }
79 void CpuZero() { CpuSet_Zero(&cpu_set); }
80 void CpuSet(unsigned cpuIndex) { CpuSet_Set(&cpu_set, cpuIndex); }
81 int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); }
82 // void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); }
83
84 BOOL SetProcAffinity() const
85 {
86 return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0;
87 }
88
89 #else
90
91 void InitST()
92 {
93 numSysThreads = 1;
94 }
95
96 UInt32 GetNumProcessThreads() const
97 {
98 return numSysThreads;
99 /*
100 UInt32 num = 0;
101 for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++)
102 num += (UInt32)((cpu_set >> i) & 1);
103 return num;
104 */
105 }
106
107 void CpuZero() { }
108 void CpuSet(unsigned cpuIndex) { UNUSED_VAR(cpuIndex); }
109 int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; }
110
111 BOOL SetProcAffinity() const
112 {
113 errno = ENOSYS;
114 return FALSE;
115 }
116
117 #endif
118};
119
120#endif
121
122
123UInt32 GetNumberOfProcessors();
124
125bool GetRamSize(UInt64 &size); // returns false, if unknown ram size
126
127}}
128
129#endif
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp
new file mode 100644
index 0000000..d882a8e
--- /dev/null
+++ b/CPP/Windows/SystemInfo.cpp
@@ -0,0 +1,917 @@
1// Windows/SystemInfo.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "../Common/IntToString.h"
8
9#ifdef _WIN32
10
11#include "Registry.h"
12
13#else
14
15#include <unistd.h>
16#include <sys/utsname.h>
17#ifdef __APPLE__
18#include <sys/sysctl.h>
19#elif !defined(_AIX)
20
21#include <sys/auxv.h>
22
23// #undef AT_HWCAP // to debug
24// #undef AT_HWCAP2 // to debug
25
26/* the following patch for some debian systems.
27 Is it OK to define AT_HWCAP and AT_HWCAP2 here with these constant numbers? */
28/*
29#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
30 #ifndef AT_HWCAP
31 #define AT_HWCAP 16
32 #endif
33 #ifndef AT_HWCAP2
34 #define AT_HWCAP2 26
35 #endif
36#endif
37*/
38
39#ifdef MY_CPU_ARM_OR_ARM64
40#include <asm/hwcap.h>
41#endif
42#endif
43
44#ifdef __linux__
45#include "../Windows/FileIO.h"
46#endif
47
48#endif // WIN32
49
50#include "SystemInfo.h"
51#include "System.h"
52
53using namespace NWindows;
54
55#ifdef __linux__
56
57static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf)
58{
59 NWindows::NFile::NIO::CInFile file;
60 if (!file.Open(fileName))
61 return false;
62 /*
63 UInt64 size;
64 if (!file.GetLength(size))
65 {
66 // GetLength() doesn't work "/proc/cpuinfo"
67 return false;
68 }
69 if (size >= ((UInt32)1 << 29))
70 return false;
71 */
72 size_t size = 0;
73 size_t addSize = ((size_t)1 << 12);
74 for (;;)
75 {
76 // printf("\nsize = %d\n", (unsigned)size);
77 buf.ChangeSize_KeepData(size + addSize, size);
78 size_t processed;
79 if (!file.ReadFull(buf + size, addSize, processed))
80 return false;
81 if (processed == 0)
82 {
83 buf.ChangeSize_KeepData(size, size);
84 return true;
85 }
86 size += processed;
87 addSize *= 2;
88 }
89}
90
91#endif
92
93
94#if defined(_WIN32) || defined(AT_HWCAP) || defined(AT_HWCAP2)
95static void PrintHex(AString &s, UInt64 v)
96{
97 char temp[32];
98 ConvertUInt64ToHex(v, temp);
99 s += temp;
100}
101#endif
102
103#ifdef MY_CPU_X86_OR_AMD64
104
105static void PrintCpuChars(AString &s, UInt32 v)
106{
107 for (int j = 0; j < 4; j++)
108 {
109 Byte b = (Byte)(v & 0xFF);
110 v >>= 8;
111 if (b == 0)
112 break;
113 s += (char)b;
114 }
115}
116
117
118static void x86cpuid_to_String(const Cx86cpuid &c, AString &s, AString &ver)
119{
120 s.Empty();
121
122 UInt32 maxFunc2 = 0;
123 UInt32 t[3];
124
125 MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]);
126
127 bool fullNameIsAvail = (maxFunc2 >= 0x80000004);
128
129 if (fullNameIsAvail)
130 {
131 for (unsigned i = 0; i < 3; i++)
132 {
133 UInt32 d[4] = { 0 };
134 MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]);
135 for (unsigned j = 0; j < 4; j++)
136 PrintCpuChars(s, d[j]);
137 }
138 }
139
140 s.Trim();
141
142 if (s.IsEmpty())
143 {
144 for (int i = 0; i < 3; i++)
145 PrintCpuChars(s, c.vendor[i]);
146 s.Trim();
147 }
148
149 {
150 char temp[32];
151 ConvertUInt32ToHex(c.ver, temp);
152 ver += temp;
153 }
154}
155
156/*
157static void x86cpuid_all_to_String(AString &s)
158{
159 Cx86cpuid p;
160 if (!x86cpuid_CheckAndRead(&p))
161 return;
162 s += "x86cpuid maxFunc = ";
163 s.Add_UInt32(p.maxFunc);
164 for (unsigned j = 0; j <= p.maxFunc; j++)
165 {
166 s.Add_LF();
167 // s.Add_UInt32(j); // align
168 {
169 char temp[32];
170 ConvertUInt32ToString(j, temp);
171 unsigned len = (unsigned)strlen(temp);
172 while (len < 8)
173 {
174 len++;
175 s.Add_Space();
176 }
177 s += temp;
178 }
179
180 s += ":";
181 UInt32 d[4] = { 0 };
182 MyCPUID(j, &d[0], &d[1], &d[2], &d[3]);
183 for (unsigned i = 0; i < 4; i++)
184 {
185 char temp[32];
186 ConvertUInt32ToHex8Digits(d[i], temp);
187 s += " ";
188 s += temp;
189 }
190 }
191}
192*/
193
194#endif
195
196
197
198#ifdef _WIN32
199
200static const char * const k_PROCESSOR_ARCHITECTURE[] =
201{
202 "x86" // "INTEL"
203 , "MIPS"
204 , "ALPHA"
205 , "PPC"
206 , "SHX"
207 , "ARM"
208 , "IA64"
209 , "ALPHA64"
210 , "MSIL"
211 , "x64" // "AMD64"
212 , "IA32_ON_WIN64"
213 , "NEUTRAL"
214 , "ARM64"
215 , "ARM32_ON_WIN64"
216};
217
218#define MY__PROCESSOR_ARCHITECTURE_INTEL 0
219#define MY__PROCESSOR_ARCHITECTURE_AMD64 9
220
221
222#define MY__PROCESSOR_INTEL_PENTIUM 586
223#define MY__PROCESSOR_AMD_X8664 8664
224
225/*
226static const CUInt32PCharPair k_PROCESSOR[] =
227{
228 { 2200, "IA64" },
229 { 8664, "x64" }
230};
231
232#define PROCESSOR_INTEL_386 386
233#define PROCESSOR_INTEL_486 486
234#define PROCESSOR_INTEL_PENTIUM 586
235#define PROCESSOR_INTEL_860 860
236#define PROCESSOR_INTEL_IA64 2200
237#define PROCESSOR_AMD_X8664 8664
238#define PROCESSOR_MIPS_R2000 2000
239#define PROCESSOR_MIPS_R3000 3000
240#define PROCESSOR_MIPS_R4000 4000
241#define PROCESSOR_ALPHA_21064 21064
242#define PROCESSOR_PPC_601 601
243#define PROCESSOR_PPC_603 603
244#define PROCESSOR_PPC_604 604
245#define PROCESSOR_PPC_620 620
246#define PROCESSOR_HITACHI_SH3 10003
247#define PROCESSOR_HITACHI_SH3E 10004
248#define PROCESSOR_HITACHI_SH4 10005
249#define PROCESSOR_MOTOROLA_821 821
250#define PROCESSOR_SHx_SH3 103
251#define PROCESSOR_SHx_SH4 104
252#define PROCESSOR_STRONGARM 2577 // 0xA11
253#define PROCESSOR_ARM720 1824 // 0x720
254#define PROCESSOR_ARM820 2080 // 0x820
255#define PROCESSOR_ARM920 2336 // 0x920
256#define PROCESSOR_ARM_7TDMI 70001
257#define PROCESSOR_OPTIL 18767 // 0x494f
258*/
259
260
261/*
262static const char * const k_PF[] =
263{
264 "FP_ERRATA"
265 , "FP_EMU"
266 , "CMPXCHG"
267 , "MMX"
268 , "PPC_MOVEMEM_64BIT"
269 , "ALPHA_BYTE"
270 , "SSE"
271 , "3DNOW"
272 , "RDTSC"
273 , "PAE"
274 , "SSE2"
275 , "SSE_DAZ"
276 , "NX"
277 , "SSE3"
278 , "CMPXCHG16B"
279 , "CMP8XCHG16"
280 , "CHANNELS"
281 , "XSAVE"
282 , "ARM_VFP_32"
283 , "ARM_NEON"
284 , "L2AT"
285 , "VIRT_FIRMWARE"
286 , "RDWRFSGSBASE"
287 , "FASTFAIL"
288 , "ARM_DIVIDE"
289 , "ARM_64BIT_LOADSTORE_ATOMIC"
290 , "ARM_EXTERNAL_CACHE"
291 , "ARM_FMAC"
292 , "RDRAND"
293 , "ARM_V8"
294 , "ARM_V8_CRYPTO"
295 , "ARM_V8_CRC32"
296 , "RDTSCP"
297 , "RDPID"
298 , "ARM_V81_ATOMIC"
299 , "MONITORX"
300};
301*/
302
303#endif
304
305
306#ifdef _WIN32
307
308static void PrintPage(AString &s, UInt32 v)
309{
310 if ((v & 0x3FF) == 0)
311 {
312 s.Add_UInt32(v >> 10);
313 s += "K";
314 }
315 else
316 s.Add_UInt32(v >> 10);
317}
318
319static AString TypeToString2(const char * const table[], unsigned num, UInt32 value)
320{
321 char sz[16];
322 const char *p = NULL;
323 if (value < num)
324 p = table[value];
325 if (!p)
326 {
327 ConvertUInt32ToString(value, sz);
328 p = sz;
329 }
330 return (AString)p;
331}
332
333// #if defined(_7ZIP_LARGE_PAGES) || defined(_WIN32)
334// #ifdef _WIN32
335void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v)
336{
337 char c = 0;
338 if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
339 if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
340 if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
341 if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
342 }}}}
343 else
344 {
345 PrintHex(s, v);
346 return;
347 }
348 char temp[32];
349 ConvertUInt64ToString(v, temp);
350 s += temp;
351 if (c)
352 s += c;
353}
354// #endif
355// #endif
356
357static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
358{
359 s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture);
360
361 if (!( (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM)
362 || (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664)))
363 {
364 s += " ";
365 // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType);
366 s.Add_UInt32(si.dwProcessorType);
367 }
368 s += " ";
369 PrintHex(s, si.wProcessorLevel);
370 s += ".";
371 PrintHex(s, si.wProcessorRevision);
372 if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors))
373 if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8)
374 {
375 s += " act:";
376 PrintHex(s, si.dwActiveProcessorMask);
377 }
378 s += " cpus:";
379 s.Add_UInt32(si.dwNumberOfProcessors);
380 if (si.dwPageSize != 1 << 12)
381 {
382 s += " page:";
383 PrintPage(s, si.dwPageSize);
384 }
385 if (si.dwAllocationGranularity != 1 << 16)
386 {
387 s += " gran:";
388 PrintPage(s, si.dwAllocationGranularity);
389 }
390 s += " ";
391
392 DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
393 UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
394 const UInt32 kReserveSize = ((UInt32)1 << 16);
395 if (minAdd != kReserveSize)
396 {
397 PrintSize_KMGT_Or_Hex(s, minAdd);
398 s += "-";
399 }
400 else
401 {
402 if ((maxSize & (kReserveSize - 1)) == 0)
403 maxSize += kReserveSize;
404 }
405 PrintSize_KMGT_Or_Hex(s, maxSize);
406}
407
408#ifndef _WIN64
409EXTERN_C_BEGIN
410typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
411EXTERN_C_END
412#endif
413
414#endif
415
416#ifdef __APPLE__
417#ifndef MY_CPU_X86_OR_AMD64
418static void Add_sysctlbyname_to_String(const char *name, AString &s)
419{
420 size_t bufSize = 256;
421 char buf[256];
422 if (My_sysctlbyname_Get(name, &buf, &bufSize) == 0)
423 s += buf;
424}
425#endif
426#endif
427
428void GetSysInfo(AString &s1, AString &s2);
429void GetSysInfo(AString &s1, AString &s2)
430{
431 s1.Empty();
432 s2.Empty();
433
434 #ifdef _WIN32
435 SYSTEM_INFO si;
436 GetSystemInfo(&si);
437 {
438 SysInfo_To_String(s1, si);
439 // s += " : ";
440 }
441
442 #if !defined(_WIN64) && !defined(UNDER_CE)
443 Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)(void *)GetProcAddress(
444 GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
445 if (fn_GetNativeSystemInfo)
446 {
447 SYSTEM_INFO si2;
448 fn_GetNativeSystemInfo(&si2);
449 // if (memcmp(&si, &si2, sizeof(si)) != 0)
450 {
451 // s += " - ";
452 SysInfo_To_String(s2, si2);
453 }
454 }
455 #endif
456 #endif
457}
458
459
460void GetCpuName(AString &s);
461
462static void AddBracedString(AString &dest, AString &src)
463{
464 if (!src.IsEmpty())
465 {
466 AString s;
467 s += '(';
468 s += src;
469 s += ')';
470 dest.Add_OptSpaced(s);
471 }
472}
473
474struct CCpuName
475{
476 AString CpuName;
477 AString Revision;
478 AString Microcode;
479 AString LargePages;
480
481 void Fill();
482
483 void Get_Revision_Microcode_LargePages(AString &s)
484 {
485 s.Empty();
486 AddBracedString(s, Revision);
487 AddBracedString(s, Microcode);
488 s.Add_OptSpaced(LargePages);
489 }
490};
491
492void CCpuName::Fill()
493{
494 CpuName.Empty();
495 Revision.Empty();
496 Microcode.Empty();
497 LargePages.Empty();
498
499 AString &s = CpuName;
500
501 #ifdef MY_CPU_X86_OR_AMD64
502 {
503 Cx86cpuid cpuid;
504 if (x86cpuid_CheckAndRead(&cpuid))
505 {
506 x86cpuid_to_String(cpuid, s, Revision);
507 }
508 else
509 {
510 #ifdef MY_CPU_AMD64
511 s += "x64";
512 #else
513 s += "x86";
514 #endif
515 }
516 }
517 #elif defined(__APPLE__)
518 {
519 Add_sysctlbyname_to_String("machdep.cpu.brand_string", s);
520 }
521 #endif
522
523
524 if (s.IsEmpty())
525 {
526 #ifdef MY_CPU_LE
527 s += "LE";
528 #elif defined(MY_CPU_BE)
529 s += "BE";
530 #endif
531 }
532
533 #ifdef __APPLE__
534 {
535 AString s2;
536 UInt32 v = 0;
537 if (My_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
538 {
539 s2.Add_UInt32(v);
540 s2 += 'C';
541 }
542 if (My_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
543 {
544 s2.Add_UInt32(v);
545 s2 += 'T';
546 }
547 if (!s2.IsEmpty())
548 {
549 s.Add_Space_if_NotEmpty();
550 s += s2;
551 }
552 }
553 #endif
554
555
556 #ifdef _WIN32
557 {
558 NRegistry::CKey key;
559 if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
560 {
561 LONG res[2];
562 CByteBuffer bufs[2];
563 {
564 for (int i = 0; i < 2; i++)
565 {
566 UInt32 size = 0;
567 res[i] = key.QueryValue(i == 0 ?
568 TEXT("Previous Update Revision") :
569 TEXT("Update Revision"), bufs[i], size);
570 if (res[i] == ERROR_SUCCESS)
571 if (size != bufs[i].Size())
572 res[i] = ERROR_SUCCESS + 1;
573 }
574 }
575 if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS)
576 {
577 for (int i = 0; i < 2; i++)
578 {
579 if (i == 1)
580 Microcode += "->";
581 if (res[i] != ERROR_SUCCESS)
582 continue;
583 const CByteBuffer &buf = bufs[i];
584 if (buf.Size() == 8)
585 {
586 UInt32 high = GetUi32(buf);
587 if (high != 0)
588 {
589 PrintHex(Microcode, high);
590 Microcode += ".";
591 }
592 PrintHex(Microcode, GetUi32(buf + 4));
593 }
594 }
595 }
596 }
597 }
598 #endif
599
600
601 #ifdef _7ZIP_LARGE_PAGES
602 Add_LargePages_String(LargePages);
603 #endif
604}
605
606void AddCpuFeatures(AString &s);
607void AddCpuFeatures(AString &s)
608{
609 #ifdef _WIN32
610 // const unsigned kNumFeatures_Extra = 32; // we check also for unknown features
611 // const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra;
612 const unsigned kNumFeatures = 64;
613 UInt64 flags = 0;
614 for (unsigned i = 0; i < kNumFeatures; i++)
615 {
616 if (IsProcessorFeaturePresent(i))
617 {
618 flags += (UInt64)1 << i;
619 // s.Add_Space_if_NotEmpty();
620 // s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i);
621 }
622 }
623 s.Add_OptSpaced("f:");
624 PrintHex(s, flags);
625
626 #elif defined(__APPLE__)
627 {
628 UInt32 v = 0;
629 if (My_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0)
630 {
631 s += "PageSize:";
632 s.Add_UInt32(v >> 10);
633 s += "KB";
634 }
635 }
636
637 #else
638
639 const long v = sysconf(_SC_PAGESIZE);
640 if (v != -1)
641 {
642 s.Add_Space_if_NotEmpty();
643 s += "PageSize:";
644 s.Add_UInt32((UInt32)(v >> 10));
645 s += "KB";
646 }
647
648 #if !defined(_AIX)
649
650 #ifdef __linux__
651
652 CByteBuffer buf;
653 if (ReadFile_to_Buffer("/sys/kernel/mm/transparent_hugepage/enabled", buf))
654 // if (ReadFile_to_Buffer("/proc/cpuinfo", buf))
655 {
656 s.Add_OptSpaced("THP:");
657 AString s2;
658 s2.SetFrom_CalcLen((const char *)(const void *)(const Byte *)buf, (unsigned)buf.Size());
659 const int pos = s2.Find('[');
660 if (pos >= 0)
661 {
662 const int pos2 = s2.Find(']', pos + 1);
663 if (pos2 >= 0)
664 {
665 s2.DeleteFrom(pos2);
666 s2.DeleteFrontal(pos + 1);
667 }
668 }
669 s += s2;
670 }
671 // else throw CSystemException(MY_SRes_HRESULT_FROM_WRes(errno));
672
673 #endif
674
675
676 #ifdef AT_HWCAP
677 s.Add_OptSpaced("hwcap:");
678 {
679 unsigned long h = getauxval(AT_HWCAP);
680 PrintHex(s, h);
681 #ifdef MY_CPU_ARM64
682 if (h & HWCAP_CRC32) s += ":CRC32";
683 if (h & HWCAP_SHA1) s += ":SHA1";
684 if (h & HWCAP_SHA2) s += ":SHA2";
685 if (h & HWCAP_AES) s += ":AES";
686 if (h & HWCAP_ASIMD) s += ":ASIMD";
687 #elif defined(MY_CPU_ARM)
688 if (h & HWCAP_NEON) s += ":NEON";
689 #endif
690 }
691 #endif // AT_HWCAP
692
693 #ifdef AT_HWCAP2
694 {
695 unsigned long h = getauxval(AT_HWCAP2);
696 #ifndef MY_CPU_ARM
697 if (h != 0)
698 #endif
699 {
700 s += " hwcap2:";
701 PrintHex(s, h);
702 #ifdef MY_CPU_ARM
703 if (h & HWCAP2_CRC32) s += ":CRC32";
704 if (h & HWCAP2_SHA1) s += ":SHA1";
705 if (h & HWCAP2_SHA2) s += ":SHA2";
706 if (h & HWCAP2_AES) s += ":AES";
707 #endif
708 }
709 }
710 #endif // AT_HWCAP2
711 #endif // _AIX
712 #endif // _WIN32
713}
714
715
716#ifdef _WIN32
717#ifndef UNDER_CE
718
719EXTERN_C_BEGIN
720typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
721EXTERN_C_END
722
723static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi)
724{
725 HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
726 if (!ntdll)
727 return FALSE;
728 Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion");
729 if (!func)
730 return FALSE;
731 func(vi);
732 return TRUE;
733}
734
735#endif
736#endif
737
738
739void GetOsInfoText(AString &sRes)
740{
741 sRes.Empty();
742 AString s;
743
744 #ifdef _WIN32
745 #ifndef UNDER_CE
746 // OSVERSIONINFO vi;
747 OSVERSIONINFOEXW vi;
748 vi.dwOSVersionInfoSize = sizeof(vi);
749 // if (::GetVersionEx(&vi))
750 if (My_RtlGetVersion(&vi))
751 {
752 s += "Windows";
753 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
754 s.Add_UInt32(vi.dwPlatformId);
755 s += " "; s.Add_UInt32(vi.dwMajorVersion);
756 s += "."; s.Add_UInt32(vi.dwMinorVersion);
757 s += " "; s.Add_UInt32(vi.dwBuildNumber);
758
759 if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0)
760 {
761 s += " SP:"; s.Add_UInt32(vi.wServicePackMajor);
762 s += "."; s.Add_UInt32(vi.wServicePackMinor);
763 }
764 // s += " Suite:"; PrintHex(s, vi.wSuiteMask);
765 // s += " Type:"; s.Add_UInt32(vi.wProductType);
766 // s += " "; s += GetOemString(vi.szCSDVersion);
767 }
768 /*
769 {
770 s += " OEMCP:"; s.Add_UInt32(GetOEMCP());
771 s += " ACP:"; s.Add_UInt32(GetACP());
772 }
773 */
774 #endif
775 #else // _WIN32
776
777 if (!s.IsEmpty())
778 s.Add_LF();
779 struct utsname un;
780 if (uname(&un) == 0)
781 {
782 s += un.sysname;
783 // s += " : "; s += un.nodename; // we don't want to show name of computer
784 s += " : "; s += un.release;
785 s += " : "; s += un.version;
786 s += " : "; s += un.machine;
787
788 #ifdef __APPLE__
789 // Add_sysctlbyname_to_String("kern.version", s);
790 // it's same as "utsname.version"
791 #endif
792 }
793 #endif // _WIN32
794
795 sRes += s;
796}
797
798
799
800void GetSystemInfoText(AString &sRes)
801{
802 GetOsInfoText(sRes);
803 sRes.Add_LF();
804
805 {
806 AString s, s1, s2;
807 GetSysInfo(s1, s2);
808 if (!s1.IsEmpty() || !s2.IsEmpty())
809 {
810 s = s1;
811 if (s1 != s2 && !s2.IsEmpty())
812 {
813 s += " - ";
814 s += s2;
815 }
816 }
817 {
818 AddCpuFeatures(s);
819 if (!s.IsEmpty())
820 {
821 sRes += s;
822 sRes.Add_LF();
823 }
824 }
825 }
826 {
827 AString s;
828 GetCpuName(s);
829 if (!s.IsEmpty())
830 {
831 sRes += s;
832 sRes.Add_LF();
833 }
834 }
835 /*
836 #ifdef MY_CPU_X86_OR_AMD64
837 {
838 AString s;
839 x86cpuid_all_to_String(s);
840 if (!s.IsEmpty())
841 {
842 printCallback->Print(s);
843 printCallback->NewLine();
844 }
845 }
846 #endif
847 */
848}
849
850
851void GetCpuName(AString &s);
852void GetCpuName(AString &s)
853{
854 CCpuName cpuName;
855 cpuName.Fill();
856 s = cpuName.CpuName;
857 AString s2;
858 cpuName.Get_Revision_Microcode_LargePages(s2);
859 s.Add_OptSpaced(s2);
860}
861
862
863void GetCpuName_MultiLine(AString &s);
864void GetCpuName_MultiLine(AString &s)
865{
866 CCpuName cpuName;
867 cpuName.Fill();
868 s = cpuName.CpuName;
869 AString s2;
870 cpuName.Get_Revision_Microcode_LargePages(s2);
871 if (!s2.IsEmpty())
872 {
873 s.Add_LF();
874 s += s2;
875 }
876}
877
878void GetCompiler(AString &s)
879{
880 #ifdef __VERSION__
881 s += __VERSION__;
882 #endif
883
884 #ifdef __GNUC__
885 s += " GCC ";
886 s.Add_UInt32(__GNUC__);
887 s += '.';
888 s.Add_UInt32(__GNUC_MINOR__);
889 s += '.';
890 s.Add_UInt32(__GNUC_PATCHLEVEL__);
891 #endif
892
893 #ifdef __clang__
894 s += " CLANG ";
895 s.Add_UInt32(__clang_major__);
896 s += '.';
897 s.Add_UInt32(__clang_minor__);
898 #endif
899
900 #ifdef __xlC__
901 s += " XLC ";
902 s.Add_UInt32(__xlC__ >> 8);
903 s += '.';
904 s.Add_UInt32(__xlC__ & 0xFF);
905 #ifdef __xlC_ver__
906 s += '.';
907 s.Add_UInt32(__xlC_ver__ >> 8);
908 s += '.';
909 s.Add_UInt32(__xlC_ver__ & 0xFF);
910 #endif
911 #endif
912
913 #ifdef _MSC_VER
914 s += " MSC ";
915 s.Add_UInt32(_MSC_VER);
916 #endif
917}
diff --git a/CPP/Windows/SystemInfo.h b/CPP/Windows/SystemInfo.h
new file mode 100644
index 0000000..e941d0a
--- /dev/null
+++ b/CPP/Windows/SystemInfo.h
@@ -0,0 +1,18 @@
1// Windows/SystemInfo.h
2
3#ifndef __WINDOWS_SYSTEM_INFO_H
4#define __WINDOWS_SYSTEM_INFO_H
5
6#include "../Common/MyString.h"
7
8
9void GetCpuName_MultiLine(AString &s);
10
11void GetOsInfoText(AString &sRes);
12void GetSystemInfoText(AString &s);
13void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v);
14void Add_LargePages_String(AString &s);
15
16void GetCompiler(AString &s);
17
18#endif
diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h
new file mode 100644
index 0000000..5fca173
--- /dev/null
+++ b/CPP/Windows/Thread.h
@@ -0,0 +1,44 @@
1// Windows/Thread.h
2
3#ifndef __WINDOWS_THREAD_H
4#define __WINDOWS_THREAD_H
5
6#include "../../C/Threads.h"
7
8#include "Defs.h"
9
10namespace NWindows {
11
12class CThread MY_UNCOPYABLE
13{
14 ::CThread thread;
15public:
16 CThread() { Thread_Construct(&thread); }
17 ~CThread() { Close(); }
18 bool IsCreated() { return Thread_WasCreated(&thread) != 0; }
19 WRes Close() { return Thread_Close(&thread); }
20 // WRes Wait() { return Thread_Wait(&thread); }
21 WRes Wait_Close() { return Thread_Wait_Close(&thread); }
22
23 WRes Create(THREAD_FUNC_TYPE startAddress, LPVOID param)
24 { return Thread_Create(&thread, startAddress, param); }
25 WRes Create_With_Affinity(THREAD_FUNC_TYPE startAddress, LPVOID param, CAffinityMask affinity)
26 { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); }
27 WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet)
28 { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); }
29
30 #ifdef _WIN32
31 operator HANDLE() { return thread; }
32 void Attach(HANDLE handle) { thread = handle; }
33 HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; }
34 DWORD Resume() { return ::ResumeThread(thread); }
35 DWORD Suspend() { return ::SuspendThread(thread); }
36 bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); }
37 int GetPriority() { return ::GetThreadPriority(thread); }
38 bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); }
39 #endif
40};
41
42}
43
44#endif
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp
new file mode 100644
index 0000000..1f1335f
--- /dev/null
+++ b/CPP/Windows/TimeUtils.cpp
@@ -0,0 +1,234 @@
1// Windows/TimeUtils.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6#include <sys/time.h>
7#endif
8
9#include "Defs.h"
10#include "TimeUtils.h"
11
12namespace NWindows {
13namespace NTime {
14
15static const UInt32 kNumTimeQuantumsInSecond = 10000000;
16static const UInt32 kFileTimeStartYear = 1601;
17#if !defined(_WIN32) || defined(UNDER_CE)
18static const UInt32 kDosTimeStartYear = 1980;
19#endif
20static const UInt32 kUnixTimeStartYear = 1970;
21static const UInt64 kUnixTimeOffset =
22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
24
25bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw()
26{
27 #if defined(_WIN32) && !defined(UNDER_CE)
28 return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));
29 #else
30 ft.dwLowDateTime = 0;
31 ft.dwHighDateTime = 0;
32 UInt64 res;
33 if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F,
34 (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res))
35 return false;
36 res *= kNumTimeQuantumsInSecond;
37 ft.dwLowDateTime = (UInt32)res;
38 ft.dwHighDateTime = (UInt32)(res >> 32);
39 return true;
40 #endif
41}
42
43static const UInt32 kHighDosTime = 0xFF9FBF7D;
44static const UInt32 kLowDosTime = 0x210000;
45
46bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
47{
48 #if defined(_WIN32) && !defined(UNDER_CE)
49
50 WORD datePart, timePart;
51 if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))
52 {
53 dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;
54 return false;
55 }
56 dosTime = (((UInt32)datePart) << 16) + timePart;
57
58 #else
59
60#define PERIOD_4 (4 * 365 + 1)
61#define PERIOD_100 (PERIOD_4 * 25 - 1)
62#define PERIOD_400 (PERIOD_100 * 4 + 1)
63
64 unsigned year, mon, day, hour, min, sec;
65 UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);
66 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
67 unsigned temp;
68 UInt32 v;
69 v64 += (kNumTimeQuantumsInSecond * 2 - 1);
70 v64 /= kNumTimeQuantumsInSecond;
71 sec = (unsigned)(v64 % 60);
72 v64 /= 60;
73 min = (unsigned)(v64 % 60);
74 v64 /= 60;
75 hour = (unsigned)(v64 % 24);
76 v64 /= 24;
77
78 v = (UInt32)v64;
79
80 year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400);
81 v %= PERIOD_400;
82
83 temp = (unsigned)(v / PERIOD_100);
84 if (temp == 4)
85 temp = 3;
86 year += temp * 100;
87 v -= temp * PERIOD_100;
88
89 temp = v / PERIOD_4;
90 if (temp == 25)
91 temp = 24;
92 year += temp * 4;
93 v -= temp * PERIOD_4;
94
95 temp = v / 365;
96 if (temp == 4)
97 temp = 3;
98 year += temp;
99 v -= temp * 365;
100
101 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
102 ms[1] = 29;
103 for (mon = 1; mon <= 12; mon++)
104 {
105 unsigned s = ms[mon - 1];
106 if (v < s)
107 break;
108 v -= s;
109 }
110 day = (unsigned)v + 1;
111
112 dosTime = kLowDosTime;
113 if (year < kDosTimeStartYear)
114 return false;
115 year -= kDosTimeStartYear;
116 dosTime = kHighDosTime;
117 if (year >= 128)
118 return false;
119 dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1);
120 #endif
121 return true;
122}
123
124UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw()
125{
126 return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
127}
128
129void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw()
130{
131 UInt64 v = UnixTimeToFileTime64(unixTime);
132 ft.dwLowDateTime = (DWORD)v;
133 ft.dwHighDateTime = (DWORD)(v >> 32);
134}
135
136UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw()
137{
138 return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
139}
140
141bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()
142{
143 if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))
144 {
145 ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1;
146 return false;
147 }
148 Int64 v = (Int64)kUnixTimeOffset + unixTime;
149 if (v < 0)
150 {
151 ft.dwLowDateTime = ft.dwHighDateTime = 0;
152 return false;
153 }
154 UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond;
155 ft.dwLowDateTime = (DWORD)v2;
156 ft.dwHighDateTime = (DWORD)(v2 >> 32);
157 return true;
158}
159
160Int64 FileTimeToUnixTime64(const FILETIME &ft) throw()
161{
162 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
163 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
164}
165
166bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
167{
168 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
169 winTime /= kNumTimeQuantumsInSecond;
170 if (winTime < kUnixTimeOffset)
171 {
172 unixTime = 0;
173 return false;
174 }
175 winTime -= kUnixTimeOffset;
176 if (winTime > 0xFFFFFFFF)
177 {
178 unixTime = 0xFFFFFFFF;
179 return false;
180 }
181 unixTime = (UInt32)winTime;
182 return true;
183}
184
185bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
186 unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw()
187{
188 resSeconds = 0;
189 if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||
190 day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)
191 return false;
192 UInt32 numYears = year - kFileTimeStartYear;
193 UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400;
194 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
195 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
196 ms[1] = 29;
197 month--;
198 for (unsigned i = 0; i < month; i++)
199 numDays += ms[i];
200 numDays += day - 1;
201 resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;
202 return true;
203}
204
205void GetCurUtcFileTime(FILETIME &ft) throw()
206{
207 // Both variants provide same low resolution on WinXP: about 15 ms.
208 // But GetSystemTimeAsFileTime is much faster.
209 #ifdef _WIN32
210
211 #ifdef UNDER_CE
212 SYSTEMTIME st;
213 GetSystemTime(&st);
214 SystemTimeToFileTime(&st, &ft);
215 #else
216 GetSystemTimeAsFileTime(&ft);
217 #endif
218
219 #else
220
221 UInt64 v = 0;
222 struct timeval now;
223 if (gettimeofday(&now, 0 ) == 0)
224 {
225 v = ((UInt64)now.tv_sec + kUnixTimeOffset) *
226 kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;
227 }
228 ft.dwLowDateTime = (DWORD)v;
229 ft.dwHighDateTime = (DWORD)(v >> 32);
230
231 #endif
232}
233
234}}
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
new file mode 100644
index 0000000..d1d8c15
--- /dev/null
+++ b/CPP/Windows/TimeUtils.h
@@ -0,0 +1,32 @@
1// Windows/TimeUtils.h
2
3#ifndef __WINDOWS_TIME_UTILS_H
4#define __WINDOWS_TIME_UTILS_H
5
6#include "../Common/MyTypes.h"
7#include "../Common/MyWindows.h"
8
9namespace NWindows {
10namespace NTime {
11
12bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw();
13bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw();
14
15// UInt32 Unix Time : for dates 1970-2106
16UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw();
17void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw();
18
19// Int64 Unix Time : negative values for dates before 1970
20UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw();
21bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw();
22
23bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw();
24Int64 FileTimeToUnixTime64(const FILETIME &ft) throw();
25
26bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
27 unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw();
28void GetCurUtcFileTime(FILETIME &ft) throw();
29
30}}
31
32#endif
diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp
new file mode 100644
index 0000000..32af4aa
--- /dev/null
+++ b/CPP/Windows/Window.cpp
@@ -0,0 +1,179 @@
1// Windows/Window.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../Common/StringConvert.h"
7#endif
8#include "Window.h"
9
10#ifndef _UNICODE
11extern bool g_IsNT;
12#endif
13
14namespace NWindows {
15
16#ifndef _UNICODE
17ATOM MyRegisterClass(CONST WNDCLASSW *wndClass)
18{
19 if (g_IsNT)
20 return RegisterClassW(wndClass);
21 WNDCLASSA wndClassA;
22 wndClassA.style = wndClass->style;
23 wndClassA.lpfnWndProc = wndClass->lpfnWndProc;
24 wndClassA.cbClsExtra = wndClass->cbClsExtra;
25 wndClassA.cbWndExtra = wndClass->cbWndExtra;
26 wndClassA.hInstance = wndClass->hInstance;
27 wndClassA.hIcon = wndClass->hIcon;
28 wndClassA.hCursor = wndClass->hCursor;
29 wndClassA.hbrBackground = wndClass->hbrBackground;
30 AString menuName;
31 AString className;
32 if (IS_INTRESOURCE(wndClass->lpszMenuName))
33 wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName;
34 else
35 {
36 menuName = GetSystemString(wndClass->lpszMenuName);
37 wndClassA.lpszMenuName = menuName;
38 }
39 if (IS_INTRESOURCE(wndClass->lpszClassName))
40 wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName;
41 else
42 {
43 className = GetSystemString(wndClass->lpszClassName);
44 wndClassA.lpszClassName = className;
45 }
46 return RegisterClassA(&wndClassA);
47}
48
49bool CWindow::Create(LPCWSTR className,
50 LPCWSTR windowName, DWORD style,
51 int x, int y, int width, int height,
52 HWND parentWindow, HMENU idOrHMenu,
53 HINSTANCE instance, LPVOID createParam)
54{
55 if (g_IsNT)
56 {
57 _window = ::CreateWindowW(className, windowName,
58 style, x, y, width, height, parentWindow,
59 idOrHMenu, instance, createParam);
60 return (_window != NULL);
61 }
62 return Create(GetSystemString(className), GetSystemString(windowName),
63 style, x, y, width, height, parentWindow,
64 idOrHMenu, instance, createParam);
65}
66
67bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className,
68 LPCWSTR windowName, DWORD style,
69 int x, int y, int width, int height,
70 HWND parentWindow, HMENU idOrHMenu,
71 HINSTANCE instance, LPVOID createParam)
72{
73 if (g_IsNT)
74 {
75 _window = ::CreateWindowExW(exStyle, className, windowName,
76 style, x, y, width, height, parentWindow,
77 idOrHMenu, instance, createParam);
78 return (_window != NULL);
79 }
80 AString classNameA;
81 LPCSTR classNameP;
82 if (IS_INTRESOURCE(className))
83 classNameP = (LPCSTR)className;
84 else
85 {
86 classNameA = GetSystemString(className);
87 classNameP = classNameA;
88 }
89 AString windowNameA;
90 LPCSTR windowNameP;
91 if (IS_INTRESOURCE(windowName))
92 windowNameP = (LPCSTR)windowName;
93 else
94 {
95 windowNameA = GetSystemString(windowName);
96 windowNameP = windowNameA;
97 }
98 return CreateEx(exStyle, classNameP, windowNameP,
99 style, x, y, width, height, parentWindow,
100 idOrHMenu, instance, createParam);
101}
102
103#endif
104
105#ifndef _UNICODE
106bool MySetWindowText(HWND wnd, LPCWSTR s)
107{
108 if (g_IsNT)
109 return BOOLToBool(::SetWindowTextW(wnd, s));
110 return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s)));
111}
112#endif
113
114bool CWindow::GetText(CSysString &s)
115{
116 s.Empty();
117 unsigned len = (unsigned)GetTextLength();
118 if (len == 0)
119 return (::GetLastError() == ERROR_SUCCESS);
120 TCHAR *p = s.GetBuf(len);
121 {
122 unsigned len2 = (unsigned)GetText(p, (int)(len + 1));
123 if (len > len2)
124 len = len2;
125 }
126 s.ReleaseBuf_CalcLen(len);
127 if (len == 0)
128 return (::GetLastError() == ERROR_SUCCESS);
129 return true;
130}
131
132#ifndef _UNICODE
133bool CWindow::GetText(UString &s)
134{
135 if (g_IsNT)
136 {
137 s.Empty();
138 unsigned len = (unsigned)GetWindowTextLengthW(_window);
139 if (len == 0)
140 return (::GetLastError() == ERROR_SUCCESS);
141 wchar_t *p = s.GetBuf(len);
142 {
143 unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1));
144 if (len > len2)
145 len = len2;
146 }
147 s.ReleaseBuf_CalcLen(len);
148 if (len == 0)
149 return (::GetLastError() == ERROR_SUCCESS);
150 return true;
151 }
152 CSysString sysString;
153 bool result = GetText(sysString);
154 MultiByteToUnicodeString2(s, sysString);
155 return result;
156}
157#endif
158
159
160/*
161bool CWindow::ModifyStyleBase(int styleOffset,
162 DWORD remove, DWORD add, UINT flags)
163{
164 DWORD style = GetWindowLong(styleOffset);
165 DWORD newStyle = (style & ~remove) | add;
166 if (style == newStyle)
167 return false; // it is not good
168
169 SetWindowLong(styleOffset, newStyle);
170 if (flags != 0)
171 {
172 ::SetWindowPos(_window, NULL, 0, 0, 0, 0,
173 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags);
174 }
175 return TRUE;
176}
177*/
178
179}
diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h
new file mode 100644
index 0000000..83726c7
--- /dev/null
+++ b/CPP/Windows/Window.h
@@ -0,0 +1,284 @@
1// Windows/Window.h
2
3#ifndef __WINDOWS_WINDOW_H
4#define __WINDOWS_WINDOW_H
5
6#include "../Common/MyWindows.h"
7#include "../Common/MyString.h"
8
9#include "Defs.h"
10
11#ifndef UNDER_CE
12
13#define MY__WM_CHANGEUISTATE 0x0127
14#define MY__WM_UPDATEUISTATE 0x0128
15#define MY__WM_QUERYUISTATE 0x0129
16
17// LOWORD(wParam) values in WM_*UISTATE
18#define MY__UIS_SET 1
19#define MY__UIS_CLEAR 2
20#define MY__UIS_INITIALIZE 3
21
22// HIWORD(wParam) values in WM_*UISTATE
23#define MY__UISF_HIDEFOCUS 0x1
24#define MY__UISF_HIDEACCEL 0x2
25#define MY__UISF_ACTIVE 0x4
26
27#endif
28
29namespace NWindows {
30
31inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass)
32 { return ::RegisterClass(wndClass); }
33
34#ifndef _UNICODE
35ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);
36#endif
37
38#ifdef _UNICODE
39inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); }
40#else
41bool MySetWindowText(HWND wnd, LPCWSTR s);
42#endif
43
44
45#ifdef UNDER_CE
46#define GWLP_USERDATA GWL_USERDATA
47#define GWLP_WNDPROC GWL_WNDPROC
48#define BTNS_BUTTON TBSTYLE_BUTTON
49#define WC_COMBOBOXW L"ComboBox"
50#define DWLP_MSGRESULT DWL_MSGRESULT
51#endif
52
53class CWindow
54{
55private:
56 // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags);
57protected:
58 HWND _window;
59public:
60 CWindow(HWND newWindow = NULL): _window(newWindow){};
61 CWindow& operator=(HWND newWindow)
62 {
63 _window = newWindow;
64 return *this;
65 }
66 operator HWND() const { return _window; }
67 void Attach(HWND newWindow) { _window = newWindow; }
68 HWND Detach()
69 {
70 HWND window = _window;
71 _window = NULL;
72 return window;
73 }
74
75 bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); }
76
77 HWND GetParent() const { return ::GetParent(_window); }
78 bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); }
79 #ifndef UNDER_CE
80 bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); }
81 #endif
82 bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); }
83 bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); }
84
85 bool CreateEx(DWORD exStyle, LPCTSTR className,
86 LPCTSTR windowName, DWORD style,
87 int x, int y, int width, int height,
88 HWND parentWindow, HMENU idOrHMenu,
89 HINSTANCE instance, LPVOID createParam)
90 {
91 _window = ::CreateWindowEx(exStyle, className, windowName,
92 style, x, y, width, height, parentWindow,
93 idOrHMenu, instance, createParam);
94 return (_window != NULL);
95 }
96
97 bool Create(LPCTSTR className,
98 LPCTSTR windowName, DWORD style,
99 int x, int y, int width, int height,
100 HWND parentWindow, HMENU idOrHMenu,
101 HINSTANCE instance, LPVOID createParam)
102 {
103 _window = ::CreateWindow(className, windowName,
104 style, x, y, width, height, parentWindow,
105 idOrHMenu, instance, createParam);
106 return (_window != NULL);
107 }
108
109 #ifndef _UNICODE
110 bool Create(LPCWSTR className,
111 LPCWSTR windowName, DWORD style,
112 int x, int y, int width, int height,
113 HWND parentWindow, HMENU idOrHMenu,
114 HINSTANCE instance, LPVOID createParam);
115 bool CreateEx(DWORD exStyle, LPCWSTR className,
116 LPCWSTR windowName, DWORD style,
117 int x, int y, int width, int height,
118 HWND parentWindow, HMENU idOrHMenu,
119 HINSTANCE instance, LPVOID createParam);
120 #endif
121
122
123 bool Destroy()
124 {
125 if (_window == NULL)
126 return true;
127 bool result = BOOLToBool(::DestroyWindow(_window));
128 if (result)
129 _window = NULL;
130 return result;
131 }
132 bool IsWindow() { return BOOLToBool(::IsWindow(_window)); }
133 bool Move(int x, int y, int width, int height, bool repaint = true)
134 { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); }
135
136 bool ChangeSubWindowSizeX(HWND hwnd, int xSize)
137 {
138 RECT rect;
139 ::GetWindowRect(hwnd, &rect);
140 POINT p1;
141 p1.x = rect.left;
142 p1.y = rect.top;
143 ScreenToClient(&p1);
144 return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE));
145 }
146
147 void ScreenToClient(RECT *rect)
148 {
149 POINT p1, p2;
150 p1.x = rect->left;
151 p1.y = rect->top;
152 p2.x = rect->right;
153 p2.y = rect->bottom;
154 ScreenToClient(&p1);
155 ScreenToClient(&p2);
156
157 rect->left = p1.x;
158 rect->top = p1.y;
159 rect->right = p2.x;
160 rect->bottom = p2.y;
161 }
162
163 bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); }
164 bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); }
165 bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); }
166
167 #ifndef UNDER_CE
168 bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); }
169 bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); }
170 #endif
171 bool Update() { return BOOLToBool(::UpdateWindow(_window)); }
172 bool InvalidateRect(LPCRECT rect, bool backgroundErase = true)
173 { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); }
174 void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); }
175
176 LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }
177 LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }
178 // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); }
179
180 LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); }
181 LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); }
182 LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); }
183 LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); }
184
185
186 #ifdef UNDER_CE
187
188 LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); }
189 LONG_PTR GetLongPtr(int index) const { return GetLong(index); }
190
191 LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); }
192 LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); }
193
194 #else
195
196 LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr)
197 { return ::SetWindowLongPtr(_window, index,
198 #ifndef _WIN64
199 (LONG)
200 #endif
201 newLongPtr); }
202 #ifndef _UNICODE
203 LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr)
204 { return ::SetWindowLongPtrW(_window, index,
205 #ifndef _WIN64
206 (LONG)
207 #endif
208 newLongPtr); }
209 #endif
210
211 LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); }
212 LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); }
213 LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); }
214
215 #endif
216
217 /*
218 bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)
219 { return ModifyStyleBase(GWL_STYLE, remove, add, flags); }
220 bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)
221 { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); }
222 */
223
224 HWND SetFocus() { return ::SetFocus(_window); }
225
226 LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
227 { return ::SendMessage(_window, message, wParam, lParam); }
228 #ifndef _UNICODE
229 LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
230 { return ::SendMessageW(_window, message, wParam, lParam); }
231 #endif
232
233 bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
234 { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); }
235 #ifndef _UNICODE
236 bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
237 { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); }
238 #endif
239
240 bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); }
241 #ifndef _UNICODE
242 bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); }
243 #endif
244
245 int GetTextLength() const
246 { return GetWindowTextLength(_window); }
247 int GetText(LPTSTR string, int maxCount) const
248 { return GetWindowText(_window, string, maxCount); }
249 bool GetText(CSysString &s);
250 #ifndef _UNICODE
251 /*
252 UINT GetText(LPWSTR string, int maxCount) const
253 { return GetWindowTextW(_window, string, maxCount); }
254 */
255 bool GetText(UString &s);
256 #endif
257
258 bool Enable(bool enable)
259 { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); }
260
261 bool IsEnabled()
262 { return BOOLToBool(::IsWindowEnabled(_window)); }
263
264 #ifndef UNDER_CE
265 HMENU GetSystemMenu(bool revert)
266 { return ::GetSystemMenu(_window, BoolToBOOL(revert)); }
267 #endif
268
269 UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = 0)
270 { return ::SetTimer(_window, idEvent, elapse, timerFunc); }
271 bool KillTimer(UINT_PTR idEvent)
272 {return BOOLToBool(::KillTimer(_window, idEvent)); }
273
274 HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); }
275};
276
277#define RECT_SIZE_X(r) ((r).right - (r).left)
278#define RECT_SIZE_Y(r) ((r).bottom - (r).top)
279
280inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; }
281
282}
283
284#endif